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