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