0853c1f5beae45c6c88f7218e51210489b7ce98a
[openafs.git] / src / vol / test / updateDirInode.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11 **      Lists all files in a /vicepX partition. This started as an
12 **      exercise to know the layout of AFS data in a fileserver
13 **      partition. Later on, it proved useful in debugging problems 
14 **      at customer sites too. 
15 **
16 */
17 #include <afsconfig.h>
18 #include <afs/param.h>
19
20
21 #include <rx/xdr.h>
22 #include <afs/afsint.h>
23 #include <ctype.h>
24 #include <sys/param.h>
25 #if !defined(AFS_SGI_ENV)
26 #ifdef  AFS_OSF_ENV
27 #include <ufs/fs.h>
28 #else /* AFS_OSF_ENV */
29 #ifdef AFS_VFSINCL_ENV
30 #define VFS
31 #ifdef  AFS_SUN5_ENV
32 #include <sys/fs/ufs_fs.h>
33 #else
34 #include <ufs/fs.h>
35 #endif
36 #else /* AFS_VFSINCL_ENV */
37 #ifndef AFS_AIX_ENV
38 #include <sys/fs.h>
39 #endif
40 #endif /* AFS_VFSINCL_ENV */
41 #endif /* AFS_OSF_ENV */
42 #endif /* AFS_SGI_ENV */
43 #include <sys/errno.h>
44 #include <sys/stat.h>
45 #include <stdio.h>
46 #include <sys/file.h>
47 #if defined(AFS_SGI_ENV) || (defined(AFS_SUN_ENV) && !defined(AFS_BSD_ENV))
48 #include <dirent.h>
49 #else
50 #include <sys/dir.h>
51 #endif
52 #ifdef  AFS_AIX_ENV
53 #include <sys/vfs.h>
54 #include <fcntl.h>
55 #else
56 #ifdef  AFS_HPUX_ENV
57 #include <fcntl.h>
58 #include <mntent.h>
59 #else
60 #if     defined(AFS_SUN_ENV) || defined(AFS_SUN5_ENV)
61 #ifdef  AFS_SUN5_ENV
62 #include <sys/mnttab.h>
63 #include <sys/mntent.h>
64 #else
65 #include <mntent.h>
66 #endif
67 #else
68 #if defined(AFS_SGI_ENV)
69 #include <fcntl.h>
70 #include <mntent.h>
71
72 /*
73 #include <sys/fs/efs.h>
74 */
75 #include "efs.h"                /* until 5.1 release */
76
77 #define ROOTINO EFS_ROOTINO
78 #else
79 #include <fstab.h>
80 #endif
81 #endif /* AFS_SGI_ENV */
82 #endif /* AFS_HPUX_ENV */
83 #endif
84 #include <netdb.h>
85 #include <netinet/in.h>
86 #include <sys/wait.h>
87 #include <setjmp.h>
88 #ifndef ITIMER_REAL
89 #include <sys/time.h>
90 #endif /* ITIMER_REAL */
91
92 #include "nfs.h"
93 #include <afs/errors.h>
94 #include "lock.h"
95 #include "lwp.h"
96 #include "vnode.h"
97 #include "volume.h"
98 #include "vldb.h"
99 #include "partition.h"
100 #include "afs/opr_assert.h"
101 #include "filesignal.h"
102 #include "vutils.h"
103 #include "daemon_com.h"
104 #include "fssync.h"
105 #include <afs/auxinode.h>
106 #include <afs/dir.h>
107 #include <unistd.h>
108
109 #ifdef  AFS_OSF_ENV
110 extern void *calloc(), *realloc();
111 #endif
112 #include "salvage.h"
113 int volumeId;
114 int VolumeChanged;              /* to satisfy library libdir use */
115
116 #include "listVicepx.h"
117 char *orphan_NoVnode = "ORPHANED_NoVnode";
118 char *orphan_NoUnique = "ORPHANED_NoUnique";
119 #define READBUFSIZE     5*1024
120
121
122 #define allNull         0x00
123 #define verbose         0x01
124 #define update          0x02    /* update specified dir inode */
125
126 int
127 Usage(name)
128      char *name;
129 {
130     assert(name);
131     printf
132         ("Usage is %s -p <partition name> -v <volume name> -dirInode <directory inode> -f <directoryFileName> -verbose\n",
133          name);
134     exit(1);
135 }
136
137
138 main(argc, argv)
139      int argc;
140      char *argv[];
141 {
142     char fullName[32 + VNAMESIZE + sizeof(VHDREXT) + 4];
143     char partition[32], volume[VNAMESIZE];
144     struct stat statBuf;
145     struct VolumeHeader volumeHeader;
146     int fd, i, sawPart = 0, sawVolume = 0, sawDirContents = 0, sawDirFile = 0;
147     char option = allNull;      /* no default options */
148     Inode dirInode;             /* destination dir Inode */
149     char *fileName;             /* source directory file */
150
151     for (i = 1; i < argc; i++) {
152         if (!strcmp(argv[i], "-p")) {
153             if ((i + 1) >= argc)
154                 Usage(argv[0]);
155             assert(strlen(argv[i + 1]) < 32);
156             strcpy(partition, argv[++i]);
157             sawPart = 1;
158         } else if (!strcmp(argv[i], "-v")) {
159             if ((i + 1) >= argc)
160                 Usage(argv[0]);
161             assert(strlen(argv[i + 1]) < VNAMESIZE);
162             strcpy(volume, argv[++i]);
163             sawVolume = 1;
164         } else if (!strcmp(argv[i], "-dirInode")) {
165             if ((i + 1) >= argc)
166                 Usage(argv[0]);
167             dirInode = atoi(argv[++i]);
168             sawDirContents = 1;
169             option |= update;
170         } else if (!strcmp(argv[i], "-f")) {
171             if ((i + 1) >= argc)
172                 Usage(argv[0]);
173             fileName = argv[++i];
174             sawDirFile = 1;
175         } else if (!strcmp(argv[i], "-verbose"))
176             option |= verbose;
177         else
178             Usage(argv[0]);
179     }
180
181     /* option to verify whether input file is syntactically good */
182     if (sawDirFile && !sawPart && !sawVolume && !sawDirContents) {
183         scanDirFile(0, 0, fileName, option);
184         exit(2);
185     }
186
187     /* check input parameters */
188     if (!sawPart || !sawVolume || !sawDirFile || !sawDirContents)
189         Usage(argv[0]);
190
191     /* extract volume id */
192     volumeId = atoi(volume);
193
194     /* construct  unix file name */
195     strcpy(fullName, partition);
196     strcat(fullName, "/V");
197     strcat(fullName, volume);
198     strcat(fullName, VHDREXT);
199
200     /* check to see that volume exists */
201     if (stat(fullName, &statBuf) < 0) {
202         printf("Error in stat(%s) : %d\n", fullName, errno);
203         exit(2);
204     }
205
206     /* read volume header */
207     if ((fd = open(fullName, O_RDONLY)) < 0) {
208         printf("Error in open(%s) : %d\n", fullName, errno);
209         exit(3);
210     }
211     if (read(fd, &volumeHeader, sizeof(struct VolumeHeader)) <
212         sizeof(struct VolumeHeader)) {
213         printf("Error in reading Volume Header : %d\n", errno);
214         exit(4);
215     }
216
217     scanDirFile(statBuf.st_dev, dirInode, fileName, option);
218     close(fd);
219 }
220
221 int
222 scanDirFile(dev, node, fileName, option)
223      dev_t dev;
224      Inode node;                /* destination directory inode number */
225      char *fileName;            /* source file to update from */
226      char option;               /* user options */
227 {
228     int fd, i, j, temp;
229     FILE *fp;
230     char dirPage[2048];
231     char buf[READBUFSIZE];      /* read buffer */
232     struct DirHeader *dhp = (struct DirHeader *)&dirPage[0];
233     struct stat statBuf;
234     int pgCount = 0;            /* current page */
235
236     /* open this directory source file */
237     if ((fp = fopen(fileName, "r")) == 0) {
238         printf("fopen of %s failed : %d\n", fileName, errno);
239         exit(6);
240     }
241
242     fgets(buf, READBUFSIZE, fp);        /* ignore "Alloc map:" */
243     for (i = 0; i < MAXPAGES; i++) {    /* read alloMap */
244         fscanf(fp, "%x", &temp);
245         dhp->alloMap[i] = (unsigned char)temp;
246     }
247     fgets(buf, READBUFSIZE, fp);        /* ignore trailing spaces */
248
249     fgets(buf, READBUFSIZE, fp);        /* ignore "Hash map:" */
250     for (i = 0; i < NHASHENT; i++) {
251         fscanf(fp, "%d", &temp);
252         dhp->hashTable[i] = (unsigned short)temp;
253     }
254     fgets(buf, READBUFSIZE, fp);        /* ignore trailing spaces */
255
256     while (ReadPage(fp, dhp, pgCount)) {        /* read from source file */
257         if (option & verbose)
258             PrintDir(dhp, pgCount);
259         if (option & update) {  /* update destnation dir inode */
260             if (pgCount == 0)   /* first page */
261                 if ((fd = iopen(dev, node, O_WRONLY)) < 0) {
262                     printf("Error in opening destination inode %d(err %d)\n",
263                            node, errno);
264                     exit(1);
265                 }
266             if (write(fd, dirPage, sizeof(dirPage)) != sizeof(dirPage)) {
267                 printf("Error in writing %d th page into inode %d(err %d)\n",
268                        pgCount, node, errno);
269                 exit(1);
270             }
271         }
272         pgCount++;
273     }
274     fclose(fp);
275     close(fd);
276 }
277
278                         /* prints out a directory data */
279 PrintDir(dhp, pgCount)
280      struct DirHeader *dhp;
281      int pgCount;               /* current page Number */
282 {
283     int i;
284     struct DirEntry *de;
285     struct PageHeader *pg;
286
287     if (pgCount == 0) {         /* first page */
288         printf("Alloc map: ");
289         for (i = 0; i < MAXPAGES; i++) {        /* read alloMap */
290             if ((i % 16) == 0)
291                 printf("\n");
292             printf("%.2x ", dhp->alloMap[i]);
293         }
294         printf("\nHash table:");
295         for (i = 0; i < NHASHENT; i++) {
296             if ((i % 16) == 0)
297                 printf("\n");
298             printf("%.2d ", dhp->hashTable[i]);
299         }
300         printf("\n");
301
302         /* print page header info */
303         printf("--------------- Page 0 ---------------\n");
304         printf("pgcnt      :%d\n", dhp->header.pgcount);
305         printf("tag        :%d\n", dhp->header.tag);
306         printf("freecnt    :%d(not used)\n", dhp->header.freecount);
307         printf("freebitmap :");
308         for (i = 0; i < EPP / 8; i++)
309             printf("%.2x ", (unsigned char)(dhp->header.freebitmap[i]));
310         printf("\n");
311
312         /* print slots in the first page of this directory */
313         de = ((struct DirPage0 *)dhp)->entry;
314         for (i = DHE + 1; i < EPP;
315              i++, de = (struct DirEntry *)((char *)de + 32))
316             printf("ent %d: f=%d l=%d n=%d vn=%d vu=%d name:%s\n", i,
317                    de->flag, de->length, de->next, de->fid.vnode,
318                    de->fid.vunique, de->name);
319     } else {
320         pg = &((struct DirPage1 *)dhp)->header; /* page header */
321         de = ((struct DirPage1 *)dhp)->entry;
322
323         /* print page header info */
324         printf("--------------- Page %d ---------------\n", pgCount);
325         printf("pgcnt      :%d\n", pg->pgcount);
326         printf("tag        :%d\n", pg->tag);
327         printf("freecnt    :%d(not used)\n", pg->freecount);
328         printf("freebitmap :");
329         for (i = 0; i < EPP / 8; i++)
330             printf("%.2x ", (unsigned char)(pg->freebitmap[i]));
331         printf("\n");
332
333         /* print slots in this page */
334         for (i = 1; i < EPP; i++, de = (struct DirEntry *)((char *)de + 32))
335             printf("ent %d: f=%d l=%d n=%d vn=%d vu=%d name:%s\n", i,
336                    de->flag, de->length, de->next, de->fid.vnode,
337                    de->fid.vunique, de->name);
338     }
339 }
340
341 /*
342 ** Returns 0 if there are no more pages 
343 ** Returns 1 if there are more pages to be read 
344 */
345 ReadPage(fp, dhp, pageNo)       /* Read one page(pageNo) from file fp into dhp */
346      FILE *fp;
347      struct DirHeader *dhp;
348      int pageNo;
349 {
350     int pgcnt, page, freecnt, freebit[EPP / 8];
351     int tag;
352     char buf[READBUFSIZE];      /* read buffer */
353     int start;
354     int i, ent, f, l, n, vnode, unique;
355     char dirName[18];
356     struct DirEntry *dirEntry;
357     struct PageHeader *pageHeader;
358
359     if (fscanf(fp, "--------------- Page %d ---------------\n", &page) != 1) {
360         return 0;               /* no more pages */
361     }
362     /* defensive check */
363     if (page != pageNo) {
364         printf("Wrong page: pageNo %d does not match data in file %d\n",
365                pageNo, page);
366         exit(1);
367     }
368
369     if (fscanf(fp, "pgcnt      :%d", &pgcnt) != 1) {
370         printf("Error in looking for pgcnt:<int> in page %d\n", pageNo);
371         exit(1);
372     }
373     fgets(buf, READBUFSIZE, fp);        /* ignore trailing spaces */
374
375     if (fscanf(fp, "tag        :%d", &tag) != 1) {
376         printf("Error in looking for tag:<int> in page %d\n", pageNo);
377         exit(1);
378     }
379     fgets(buf, READBUFSIZE, fp);        /* ignore trailing spaces */
380
381     if (fscanf(fp, "freecnt    :%d", &freecnt) != 1) {
382         printf("Error in looking for freecnt:<int> in page %d\n", pageNo);
383         exit(1);
384     }
385     fgets(buf, READBUFSIZE, fp);        /* ignore trailing spaces */
386
387     if (fscanf
388         (fp, "freebitmap :%x %x %x %x %x %x %x %x", &freebit[0], &freebit[1],
389          &freebit[2], &freebit[3], &freebit[4], &freebit[5], &freebit[6],
390          &freebit[7]) != 8) {
391         printf("Error in looking for freecnt:<ints> in page %d\n", pageNo);
392         exit(1);
393     }
394     fgets(buf, READBUFSIZE, fp);        /* ignore trailing spaces */
395
396     if (pageNo == 0) {          /* first page */
397         start = DHE + 1;        /* this is 13 */
398         dirEntry = ((struct DirPage0 *)dhp)->entry;
399         pageHeader = &(dhp->header);
400     } else {
401         start = 1;
402         dirEntry = ((struct DirPage1 *)dhp)->entry;
403         pageHeader = &(((struct DirPage1 *)dhp)->header);
404     }
405
406     /* update page header */
407     pageHeader->pgcount = pgcnt;
408     pageHeader->tag = tag;
409     pageHeader->freecount = freecnt;    /* this is currently unused */
410     for (i = 0; i < EPP / 8; i++)
411         pageHeader->freebitmap[i] = freebit[i];
412
413     /* update directory entries */
414     for (; start < EPP; start++) {
415         if (fscanf
416             (fp, "ent %d: f=%d l=%d n=%d vn=%d vu=%d name:%s\n", &ent, &f, &l,
417              &n, &vnode, &unique, dirName) != 7) {
418             printf("Error in reading the %d th entry in page %d\n", start,
419                    pageNo);
420             exit(1);
421         }
422         if (ent != start) {
423             printf("Wrong dir entry: found %d, has to be %\n", ent, start);
424             exit(1);
425         }
426         dirEntry->flag = f;
427         dirEntry->length = l;
428         dirEntry->next = n;
429         dirEntry->fid.vnode = vnode;
430         dirEntry->fid.vunique = unique;
431         memcpy(dirEntry->name, dirName, 18);
432         strncpy(dirEntry->name, dirName);
433
434         dirEntry = (struct DirEntry *)((char *)dirEntry + 32);
435     }
436     return 1;                   /* there are more pages */
437 }