2 * Copyright 2000, International Business Machines Corporation and others.
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
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.
17 #include <afsconfig.h>
18 #include <afs/param.h>
24 #include <afs/afsint.h>
26 #include <sys/param.h>
27 #if !defined(AFS_SGI_ENV)
30 #else /* AFS_OSF_ENV */
31 #ifdef AFS_VFSINCL_ENV
34 #include <sys/fs/ufs_fs.h>
38 #else /* AFS_VFSINCL_ENV */
42 #endif /* AFS_VFSINCL_ENV */
43 #endif /* AFS_OSF_ENV */
44 #endif /* AFS_SGI_ENV */
45 #include <sys/errno.h>
49 #if defined(AFS_SGI_ENV) || (defined(AFS_SUN_ENV) && !defined(AFS_BSD_ENV))
62 #if defined(AFS_SUN_ENV) || defined(AFS_SUN5_ENV)
64 #include <sys/mnttab.h>
65 #include <sys/mntent.h>
70 #if defined(AFS_SGI_ENV)
75 #include <sys/fs/efs.h>
77 #include "efs.h" /* until 5.1 release */
79 #define ROOTINO EFS_ROOTINO
83 #endif /* AFS_SGI_ENV */
84 #endif /* AFS_HPUX_ENV */
87 #include <netinet/in.h>
92 #endif /* ITIMER_REAL */
95 #include <afs/errors.h>
101 #include "partition.h"
102 #include "afs/assert.h"
103 #include "filesignal.h"
105 #include "daemon_com.h"
107 #include <afs/auxinode.h>
112 extern void *calloc(), *realloc();
116 int VolumeChanged; /* to satisfy library libdir use */
118 #include "listVicepx.h"
119 char *orphan_NoVnode = "ORPHANED_NoVnode";
120 char *orphan_NoUnique = "ORPHANED_NoUnique";
121 #define READBUFSIZE 5*1024
126 #define update 0x02 /* update specified dir inode */
134 ("Usage is %s -p <partition name> -v <volume name> -dirInode <directory inode> -f <directoryFileName> -verbose\n",
144 char fullName[32 + VNAMESIZE + sizeof(VHDREXT) + 4];
145 char partition[32], volume[VNAMESIZE];
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 */
153 for (i = 1; i < argc; i++) {
154 if (!strcmp(argv[i], "-p")) {
157 assert(strlen(argv[i + 1]) < 32);
158 strcpy(partition, argv[++i]);
160 } else if (!strcmp(argv[i], "-v")) {
163 assert(strlen(argv[i + 1]) < VNAMESIZE);
164 strcpy(volume, argv[++i]);
166 } else if (!strcmp(argv[i], "-dirInode")) {
169 dirInode = atoi(argv[++i]);
172 } else if (!strcmp(argv[i], "-f")) {
175 fileName = argv[++i];
177 } else if (!strcmp(argv[i], "-verbose"))
183 /* option to verify whether input file is syntactically good */
184 if (sawDirFile && !sawPart && !sawVolume && !sawDirContents) {
185 scanDirFile(0, 0, fileName, option);
189 /* check input parameters */
190 if (!sawPart || !sawVolume || !sawDirFile || !sawDirContents)
193 /* extract volume id */
194 volumeId = atoi(volume);
196 /* construct unix file name */
197 strcpy(fullName, partition);
198 strcat(fullName, "/V");
199 strcat(fullName, volume);
200 strcat(fullName, VHDREXT);
202 /* check to see that volume exists */
203 if (stat(fullName, &statBuf) < 0) {
204 printf("Error in stat(%s) : %d\n", fullName, errno);
208 /* read volume header */
209 if ((fd = open(fullName, O_RDONLY)) < 0) {
210 printf("Error in open(%s) : %d\n", fullName, errno);
213 if (read(fd, &volumeHeader, sizeof(struct VolumeHeader)) <
214 sizeof(struct VolumeHeader)) {
215 printf("Error in reading Volume Header : %d\n", errno);
219 scanDirFile(statBuf.st_dev, dirInode, fileName, option);
224 scanDirFile(dev, node, fileName, option)
226 Inode node; /* destination directory inode number */
227 char *fileName; /* source file to update from */
228 char option; /* user options */
233 char buf[READBUFSIZE]; /* read buffer */
234 struct DirHeader *dhp = (struct DirHeader *)&dirPage[0];
236 int pgCount = 0; /* current page */
238 /* open this directory source file */
239 if ((fp = fopen(fileName, "r")) == 0) {
240 printf("fopen of %s failed : %d\n", fileName, errno);
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;
249 fgets(buf, READBUFSIZE, fp); /* ignore trailing spaces */
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;
256 fgets(buf, READBUFSIZE, fp); /* ignore trailing spaces */
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",
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);
280 /* prints out a directory data */
281 PrintDir(dhp, pgCount)
282 struct DirHeader *dhp;
283 int pgCount; /* current page Number */
287 struct PageHeader *pg;
289 if (pgCount == 0) { /* first page */
290 printf("Alloc map: ");
291 for (i = 0; i < MAXPAGES; i++) { /* read alloMap */
294 printf("%.2x ", dhp->alloMap[i]);
296 printf("\nHash table:");
297 for (i = 0; i < NHASHENT; i++) {
300 printf("%.2d ", dhp->hashTable[i]);
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]));
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);
322 pg = &((struct DirPage1 *)dhp)->header; /* page header */
323 de = ((struct DirPage1 *)dhp)->entry;
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]));
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);
344 ** Returns 0 if there are no more pages
345 ** Returns 1 if there are more pages to be read
347 ReadPage(fp, dhp, pageNo) /* Read one page(pageNo) from file fp into dhp */
349 struct DirHeader *dhp;
352 int pgcnt, page, freecnt, freebit[EPP / 8];
354 char buf[READBUFSIZE]; /* read buffer */
356 int i, ent, f, l, n, vnode, unique;
358 struct DirEntry *dirEntry;
359 struct PageHeader *pageHeader;
361 if (fscanf(fp, "--------------- Page %d ---------------\n", &page) != 1) {
362 return 0; /* no more pages */
364 /* defensive check */
365 if (page != pageNo) {
366 printf("Wrong page: pageNo %d does not match data in file %d\n",
371 if (fscanf(fp, "pgcnt :%d", &pgcnt) != 1) {
372 printf("Error in looking for pgcnt:<int> in page %d\n", pageNo);
375 fgets(buf, READBUFSIZE, fp); /* ignore trailing spaces */
377 if (fscanf(fp, "tag :%d", &tag) != 1) {
378 printf("Error in looking for tag:<int> in page %d\n", pageNo);
381 fgets(buf, READBUFSIZE, fp); /* ignore trailing spaces */
383 if (fscanf(fp, "freecnt :%d", &freecnt) != 1) {
384 printf("Error in looking for freecnt:<int> in page %d\n", pageNo);
387 fgets(buf, READBUFSIZE, fp); /* ignore trailing spaces */
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],
393 printf("Error in looking for freecnt:<ints> in page %d\n", pageNo);
396 fgets(buf, READBUFSIZE, fp); /* ignore trailing spaces */
398 if (pageNo == 0) { /* first page */
399 start = DHE + 1; /* this is 13 */
400 dirEntry = ((struct DirPage0 *)dhp)->entry;
401 pageHeader = &(dhp->header);
404 dirEntry = ((struct DirPage1 *)dhp)->entry;
405 pageHeader = &(((struct DirPage1 *)dhp)->header);
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];
415 /* update directory entries */
416 for (; start < EPP; start++) {
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,
425 printf("Wrong dir entry: found %d, has to be %\n", ent, start);
429 dirEntry->length = l;
431 dirEntry->fid.vnode = vnode;
432 dirEntry->fid.vunique = unique;
433 memcpy(dirEntry->name, dirName, 18);
434 strncpy(dirEntry->name, dirName);
436 dirEntry = (struct DirEntry *)((char *)dirEntry + 32);
438 return 1; /* there are more pages */