Update NEWS for 1.6.22
[pkg-k5-afs_openafs.git] / src / vol / test / listVicepx.c
blobfe75420c22c0ef858bd211d14fcc796545526497
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 */
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>
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>
73 #include <sys/fs/efs.h>
75 #include "efs.h" /* until 5.1 release */
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 */
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/afs_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>
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 */
116 #include "listVicepx.h"
117 char *orphan_NoVnode = "ORPHANED_NoVnode";
118 char *orphan_NoUnique = "ORPHANED_NoUnique";
120 #define allNull 0x00
121 #define allFiles 0x01 /* equivalent to /bin/ls */
122 #define lFlag 0x02 /* equivalent to /bin/ls -l */
123 #define allDirs 0x04 /* equivalent to /bin/ls -ld */
124 #define contentsDInode 0x08 /* list contents of dir inode */
125 #define volInfo 0x10 /* list info from vol header */
127 extern DirEnt *lookup();
128 extern char *getFileName(), *getDirName(), *printStack();
129 extern DirEnt *hash[];
132 Usage(name)
133 char *name;
135 assert(name);
136 printf
137 ("Usage is %s -p <partition name> -v <volume name> [-ls | -lsl | -ld] [-volInfo] [-dir <directory inode>] \n",
138 name);
139 printf("-ls : lists all files\n");
140 printf("-lsl : lists all files along with its properties\n");
141 printf("-ld : lists all directories\n");
142 printf("-volInfo : lists volume header \n");
143 printf("-dir <inode number>: prints contents of directory inode\n");
144 exit(1);
148 main(argc, argv)
149 int argc;
150 char *argv[];
152 char fullName[32 + VNAMESIZE + sizeof(VHDREXT) + 4];
153 char partition[32], volume[VNAMESIZE];
154 struct stat statBuf;
155 struct VolumeHeader volumeHeader;
156 int fd, i, sawPart = 0, sawVolume = 0, sawDirContents = 0;
157 char option = allNull; /* no default options */
158 Inode dirInode; /* list contents of this dir Inode */
160 for (i = 1; i < argc; i++) {
161 if (!strcmp(argv[i], "-p")) {
162 if ((i + 1) >= argc)
163 Usage(argv[0]);
164 assert(strlen(argv[i + 1]) < 32);
165 strcpy(partition, argv[++i]);
166 sawPart = 1;
167 } else if (!strcmp(argv[i], "-v")) {
168 if ((i + 1) >= argc)
169 Usage(argv[0]);
170 assert(strlen(argv[i + 1]) < VNAMESIZE);
171 strcpy(volume, argv[++i]);
172 sawVolume = 1;
173 } else if (!strcmp(argv[i], "-dir")) {
174 if ((i + 1) >= argc)
175 Usage(argv[0]);
176 dirInode = atoi(argv[++i]);
177 option |= contentsDInode;
178 sawDirContents = 1;
179 } else if (!strcmp(argv[i], "-ls"))
180 option |= allFiles;
181 else if (!strcmp(argv[i], "-lsl"))
182 option |= (allFiles | lFlag);
183 else if (!strcmp(argv[i], "-ld"))
184 option |= allDirs;
185 else if (!strcmp(argv[i], "-volInfo"))
186 option |= volInfo;
187 else
188 Usage(argv[0]);
190 /* check input parameters */
191 if (!sawPart || !sawVolume)
192 Usage(argv[0]);
194 /* extract volume id */
195 volumeId = atoi(volume);
197 /* construct unix file name */
198 strcpy(fullName, partition);
199 strcat(fullName, "/V");
200 strcat(fullName, volume);
201 strcat(fullName, VHDREXT);
203 /* check to see that volume exists */
204 if (stat(fullName, &statBuf) < 0) {
205 printf("Error in stat(%s) : %d\n", fullName, errno);
206 exit(2);
209 /* read volume header */
210 if ((fd = open(fullName, O_RDONLY)) < 0) {
211 printf("Error in open(%s) : %d\n", fullName, errno);
212 exit(3);
214 if (read(fd, &volumeHeader, sizeof(struct VolumeHeader)) <
215 sizeof(struct VolumeHeader)) {
216 printf("Error in reading Volume Header : %d\n", errno);
217 exit(4);
220 switch (option) {
221 case volInfo: /* volume header info */
222 printf
223 ("VolId:%d VolInfo:%d mag:%x vers:%d smallVnodeIndex:%d largeVnodeIndex:%d VoAcl:%d volMntTab:%d\n",
224 volumeHeader.id, volumeHeader.volumeInfo,
225 volumeHeader.stamp.magic, volumeHeader.stamp.version,
226 volumeHeader.smallVnodeIndex, volumeHeader.largeVnodeIndex,
227 volumeHeader.volumeAcl, volumeHeader.volumeMountTable);
228 break;
230 case contentsDInode: /* list directory entries */
231 printContentsOfDirInode(statBuf.st_dev, dirInode, fullName, option);
232 break;
235 scanLargeVnode(statBuf.st_dev, volumeHeader.largeVnodeIndex, fullName,
236 option);
237 if (option & allDirs)
238 printDirs(fullName);
240 if (option & allFiles)
241 scanSmallVnode(statBuf.st_dev, volumeHeader.smallVnodeIndex, fullName,
242 option);
243 close(fd);
247 scanLargeVnode(dev, node, partitionName, option)
248 dev_t dev;
249 Inode node;
250 char *partitionName;
251 char option; /* user options */
253 afs_int32 diskSize = SIZEOF_LARGEDISKVNODE;
254 int nVnodes, fdi, vnodeIndex, offset = 0;
255 char buf[SIZEOF_LARGEDISKVNODE];
256 struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)buf;
257 FILE *file;
258 struct stat statBuf;
260 /* open this largeVodeIndex */
261 if ((fdi = iopen(dev, node, O_RDONLY)) < 0) {
262 printf("Error in reading node : %d\n", errno);
263 exit(5);
266 /* get a FILE pointer */
267 if ((file = fdopen(fdi, "r")) == 0) {
268 printf("fdopen failed : %d\n", errno);
269 exit(6);
272 /*find out how many directories are there in this volume */
273 if (fstat(fdi, &statBuf) < 0) {
274 printf("Error in stat(fd=%d): %d\n", fdi, errno);
275 exit(6);
277 nVnodes = (statBuf.st_size / diskSize) - 1;
278 if (nVnodes > 0)
279 fseek(file, diskSize, 0);
280 else
281 nVnodes = 0;
283 /* scan all entries in this volume */
284 DInit(10); /* initialise directory buffer */
286 for (vnodeIndex = 0; nVnodes && fread(vnode, diskSize, 1, file) == 1;
287 nVnodes--, vnodeIndex++, offset += diskSize) {
288 /* scan this directory */
289 int createDirEnt();
290 if ((vnode->type == vDirectory) && (vnode->inodeNumber)) {
291 DirHandle dir;
292 DirEnt *dirEntry;
294 dir.volume = volumeId;
295 dir.device = dev;
296 dir.cacheCheck = 0;
297 dir.inode = vnode->inodeNumber;
298 #ifdef DEBUG
299 printf
300 ("Directory inode %d (parent vnode = %d) contains the entries :\n",
301 vnode->inodeNumber, vnode->parent);
302 #endif
304 assert(dirEntry = (DirEnt *) malloc(sizeof(DirEnt)));
305 dirEntry->inode = vnode->inodeNumber;
306 dirEntry->numEntries = 0;
307 dirEntry->vnodeName = NULL;
308 EnumerateDir(&dir, &createDirEnt, dirEntry);
309 insertHash(dirEntry); /* insert in hash table */
312 fclose(file);
313 #ifdef DEBUG
314 printHash();
315 #endif
321 createDirEnt(dirEntry, fileName, vnode, unique)
322 DirEnt *dirEntry;
323 char *fileName;
324 afs_int32 vnode;
325 afs_int32 unique;
327 int fdi;
328 FILE *file;
329 struct stat statBuf;
331 /* fil up special fields for itself and parent */
332 if (strcmp(fileName, ".") == 0) {
333 dirEntry->vnode = vnode;
334 return;
336 if (strcmp(fileName, "..") == 0) {
337 dirEntry->vnodeParent = vnode;
338 return;
341 (dirEntry->numEntries)++;
342 assert(dirEntry->vnodeName =
343 (VnodeName *) realloc(dirEntry->vnodeName,
344 dirEntry->numEntries * sizeof(VnodeName)));
345 dirEntry->vnodeName[dirEntry->numEntries - 1].vnode = vnode;
346 dirEntry->vnodeName[dirEntry->numEntries - 1].vunique = unique;
347 dirEntry->vnodeName[dirEntry->numEntries - 1].name =
348 (char *)malloc(strlen(fileName) + 1);
349 assert(dirEntry->vnodeName[dirEntry->numEntries - 1].name);
350 strcpy(dirEntry->vnodeName[dirEntry->numEntries - 1].name, fileName);
355 scanSmallVnode(dev, node, partitionName, option)
356 dev_t dev;
357 Inode node;
358 char *partitionName;
359 char option; /* user options */
361 afs_int32 diskSize = SIZEOF_SMALLDISKVNODE;
362 int nVnodes, fdi, vnodeIndex, offset = 0;
363 char buf[SIZEOF_LARGEDISKVNODE];
364 struct VnodeDiskObject *vnode = (struct VnodeDiskObject *)buf;
365 FILE *file;
366 struct stat statBuf;
368 /* open this smallVodeIndex */
369 if ((fdi = iopen(dev, node, O_RDONLY)) < 0) {
370 printf("Error in reading node : %d\n", errno);
371 exit(5);
374 /* get a FILE pointer */
375 if ((file = fdopen(fdi, "r")) == 0) {
376 printf("fdopen failed : %d\n", errno);
377 exit(6);
380 /*find out how many files are there in this volume */
381 if (fstat(fdi, &statBuf) < 0) {
382 printf("Error in stat(fd=%d): %d\n", fdi, errno);
383 exit(6);
385 nVnodes = (statBuf.st_size / diskSize) - 1;
386 if (nVnodes > 0)
387 fseek(file, diskSize, 0);
388 else
389 nVnodes = 0;
391 /* scan all entries in this volume */
392 for (vnodeIndex = 0; nVnodes && fread(vnode, diskSize, 1, file) == 1;
393 nVnodes--, vnodeIndex++, offset += 1)
394 if ((vnode->type == vFile) || (vnode->type == vSymlink)) {
395 char *name, *fullPathName;
396 int pNode, nNode, orphan = 0;
397 DirEnt *dir;
398 #ifdef FILE_DEBUG
399 printf(" File Inode = %d parent vnode=%d ", vnode->inodeNumber,
400 vnode->parent);
401 #endif
403 if ((dir = lookup(vnode->parent)) == 0) /* orphaned */
404 orphan = 1, pushStack(orphan_NoVnode);
405 if (!orphan) {
406 name = getFileName(dir, vnode->uniquifier);
407 if (name == 0)
408 orphan = 1, pushStack(orphan_NoUnique);
410 if (!orphan) {
411 /* push the file name on stack */
412 pushStack(name);
413 pNode = vnode->parent;
414 nNode = dir->vnodeParent;
416 while (!orphan && (pNode != nNode)) {
417 if ((dir = lookup(nNode)) == 0) {
418 orphan = 1, pushStack(orphan_NoVnode);
419 break;
421 if ((name = getDirName(dir, pNode)) == 0) {
422 orphan = 1, pushStack(orphan_NoVnode);
423 break;
425 pushStack(name);
426 pNode = nNode;
427 nNode = dir->vnodeParent;
429 fullPathName = printStack(); /* full name of file or symLink */
430 if (vnode->type == vSymlink) { /* check if mount point */
431 /* read contents of link */
432 struct stat statLink;
433 int fdLink;
434 char *symLink;
435 if ((fdLink = iopen(dev, vnode->inodeNumber, O_RDONLY)) < 0) {
436 printf("Error in opening symbolic link : %d\n", errno);
437 exit(10);
439 if (fstat(fdLink, &statLink) < 0) {
440 printf("Error in symLink stat(fd=%d): %d\n", fdLink,
441 errno);
442 exit(12);
444 assert(symLink = (char *)malloc(statLink.st_size + 1));
445 if (read(fdLink, symLink, statLink.st_size) < 0) {
446 printf("Error in reading symbolic link : %d\n", errno);
447 exit(11);
449 symLink[statLink.st_size] = 0; /* null termination */
450 if (symLink[0] == '#') /* this is a mount point */
451 printf("Volume %s mounted on %s%s\n", symLink,
452 partitionName, fullPathName);
453 free(symLink);
454 close(fdLink);
456 if (option & allFiles) {
457 if (option & lFlag) {
458 switch (vnode->type) {
459 case vFile:
460 printf("F ");
461 break;
462 case vDirectory:
463 printf("D ");
464 break;
465 case vSymlink:
466 printf("S ");
467 break;
468 default:
469 printf("U ");
470 break;
472 printf("Ind:%d ", vnode->inodeNumber);
473 printf("Mod:%x ", vnode->modeBits);
474 printf("Lnk:%d ", vnode->linkCount);
475 printf("Own:%d ", vnode->owner);
476 printf("Grp:%d ", vnode->group);
477 printf("Siz:%d ", vnode->length);
479 printf("~%s\n", fullPathName);
483 fclose(file);
486 /* Lists all directories in the volume */
487 printDirs(partitionName)
488 char *partitionName;
490 int i, j, vnode, inode;
491 DirEnt *ptr, *dir, *tmpDir;
493 /* The root level vnode for this volume */
494 tmpDir = lookup(1); /* root vnode is 1 */
495 if (tmpDir == 0)
496 printf("Root vnode(1) does not exists :%s\n", partitionName);
497 else
498 printf("D Ind:%d Vnd:1 ~\n", tmpDir->inode);
500 for (i = 0; i < MAX_HASH_SIZE; i++)
501 for (ptr = (DirEnt *) hash[i]; ptr; ptr = ptr->next)
502 for (j = 0; j < ptr->numEntries; j++) {
503 int nVnode, pVnode;
504 char *fullPathName, *name;
506 pVnode = ptr->vnodeParent; /* parent vnode */
507 nVnode = ptr->vnode; /* this dir vnode */
508 vnode = ptr->vnodeName[j].vnode; /* my Vnode */
510 /* directory vnode numbers are odd */
511 if ((vnode % 2) == 0)
512 continue;
514 tmpDir = lookup(vnode);
515 if (!tmpDir) { /* orphaned directory */
516 printf("%s : vnode:%d \n", orphan_NoVnode, vnode);
517 continue;
519 inode = tmpDir->inode; /* the inode for this vnode */
521 pushStack(ptr->vnodeName[j].name);
523 while (pVnode != 1) {
524 dir = lookup(pVnode);
525 if (dir == 0) { /* orphan */
526 pushStack(orphan_NoVnode);
527 break;
529 name = getDirName(dir, nVnode);
530 if (name == 0) {
531 pushStack(orphan_NoVnode);
532 break;
534 pushStack(name);
535 nVnode = pVnode;
536 pVnode = dir->vnodeParent;
538 fullPathName = printStack(); /* full path name of directory */
539 printf("D Ind:%d Vnd:%d ~%s\n", inode, vnode, fullPathName);
543 /* figure out how many pages in use in a directory, given ptr to its (locked) he
544 ader */
545 static
546 ComputeUsedPages(dhp)
547 struct DirHeader *dhp;
549 afs_int32 usedPages, i;
551 if (dhp->header.pgcount != 0) {
552 /* new style */
553 usedPages = ntohs(dhp->header.pgcount);
554 } else {
555 /* old style */
556 usedPages = 0;
557 for (i = 0; i < MAXPAGES; i++) {
558 if (dhp->alloMap[i] == EPP) {
559 usedPages = i;
560 break;
563 if (usedPages == 0)
564 usedPages = MAXPAGES;
566 return usedPages;
569 printContentsOfDirInode(device, dirInode, fullName, options)
570 dev_t device;
571 Inode dirInode;
572 char *fullName;
573 char options;
575 int fd, i, j, usedPages, pages;
576 FILE *file;
577 struct stat statBuf;
578 char dirPage[2048];
579 struct DirHeader *dhp = (struct DirHeader *)&dirPage[0];
580 struct DirEntry *de;
581 struct PageHeader *pg;
583 fd = iopen(device, dirInode, O_RDONLY);
584 if (fd <= 0) {
585 printf("Cannot open direcory inode %d\n", dirInode);
586 return -1;
588 if ((file = fdopen(fd, "r")) == 0) { /* for buffered read */
589 printf("fdopen failed : %d\n", errno);
590 close(fd);
591 return -1;
593 if (fstat(fd, &statBuf) < 0) {
594 printf("Error in stat(fd=%d): %d\n", fd, errno);
595 return -1;
597 /* read first page */
598 if (fread(&dirPage, sizeof(dirPage), 1, file) != 1) {
599 printf("Cannot read dir header from inode %d(errno %d)\n", dirInode,
600 errno);
601 fclose(file);
602 return -1;
604 usedPages = ComputeUsedPages(dhp);
606 printf("Alloc map: ");
607 for (i = 0; i < MAXPAGES; i++) {
608 if ((i % 16) == 0)
609 printf("\n");
610 printf("%.2x ", (unsigned char)dhp->alloMap[i]);
612 printf("\nHash table:");
613 for (i = 0; i < NHASHENT; i++) {
614 if ((i % 16) == 0)
615 printf("\n");
616 printf("%.2d ", dhp->hashTable[i]);
618 printf("\n");
620 /* print header of first page */
621 printf("--------------- Page 0 ---------------\n");
622 printf("pgcnt :%d\n", usedPages);
623 printf("tag :%d\n", dhp->header.tag);
624 printf("freecnt :%d(not used)\n", dhp->header.freecount);
625 printf("freebitmap :");
626 for (i = 0; i < EPP / 8; i++)
627 printf("%.2x ", (unsigned char)(dhp->header.freebitmap[i]));
628 printf("\n");
630 /* print slots in the first page of this directory */
631 de = ((struct DirPage0 *)dirPage)->entry;
632 for (i = DHE + 1; i < EPP; i++, de = (struct DirEntry *)((char *)de + 32))
633 printf("ent %d: f=%d l=%d n=%d vn=%d vu=%d name:%s\n", i, de->flag,
634 de->length, de->next, de->fid.vnode, de->fid.vunique,
635 de->name);
637 /* read all succeeding pages of this directory */
638 for (pages = 1; pages < usedPages; pages++) {
639 if (fread(&dirPage, sizeof(dirPage), 1, file) != 1) {
640 printf("Cannot read %s page from inode %d(errno %d)\n", pages,
641 dirInode, errno);
642 fclose(file);
643 return -1;
645 pg = &((struct DirPage1 *)dirPage)->header; /* page header */
646 de = ((struct DirPage1 *)dirPage)->entry;
648 /* print page header info */
649 printf("--------------- Page %d ---------------\n", pages);
650 printf("pgcnt :%d\n", pg->pgcount);
651 printf("tag :%d\n", pg->tag);
652 printf("freecnt :%d(not used)\n", pg->freecount);
653 printf("freebitmap :");
654 for (i = 0; i < EPP / 8; i++)
655 printf("%.2x ", (unsigned char)(pg->freebitmap[i]));
656 printf("\n");
658 /* print slots in this page */
659 for (i = 1; i < EPP; i++, de = (struct DirEntry *)((char *)de + 32))
660 printf("ent %d: f=%d l=%d n=%d vn=%d vu=%d name:%s\n", i,
661 de->flag, de->length, de->next, de->fid.vnode,
662 de->fid.vunique, de->name);
665 fclose(file);
666 return 0;