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>
22 #include <afs/afsint.h>
24 #include <sys/param.h>
25 #if !defined(AFS_SGI_ENV)
28 #else /* AFS_OSF_ENV */
29 #ifdef AFS_VFSINCL_ENV
32 #include <sys/fs/ufs_fs.h>
36 #else /* AFS_VFSINCL_ENV */
40 #endif /* AFS_VFSINCL_ENV */
41 #endif /* AFS_OSF_ENV */
42 #endif /* AFS_SGI_ENV */
43 #include <sys/errno.h>
47 #if defined(AFS_SGI_ENV) || (defined(AFS_SUN_ENV) && !defined(AFS_BSD_ENV))
60 #if defined(AFS_SUN_ENV) || defined(AFS_SUN5_ENV)
62 #include <sys/mnttab.h>
63 #include <sys/mntent.h>
68 #if defined(AFS_SGI_ENV)
73 #include <sys/fs/efs.h>
75 #include "efs.h" /* until 5.1 release */
77 #define ROOTINO EFS_ROOTINO
81 #endif /* AFS_SGI_ENV */
82 #endif /* AFS_HPUX_ENV */
85 #include <netinet/in.h>
90 #endif /* ITIMER_REAL */
93 #include <afs/errors.h>
99 #include "partition.h"
100 #include "afs/afs_assert.h"
101 #include "filesignal.h"
103 #include "daemon_com.h"
105 #include <afs/auxinode.h>
110 extern void *calloc(), *realloc();
114 int VolumeChanged
; /* to satisfy library libdir use */
116 #include "listVicepx.h"
117 char *orphan_NoVnode
= "ORPHANED_NoVnode";
118 char *orphan_NoUnique
= "ORPHANED_NoUnique";
119 #define READBUFSIZE 5*1024
124 #define update 0x02 /* update specified dir inode */
132 ("Usage is %s -p <partition name> -v <volume name> -dirInode <directory inode> -f <directoryFileName> -verbose\n",
142 char fullName
[32 + VNAMESIZE
+ sizeof(VHDREXT
) + 4];
143 char partition
[32], volume
[VNAMESIZE
];
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 */
151 for (i
= 1; i
< argc
; i
++) {
152 if (!strcmp(argv
[i
], "-p")) {
155 assert(strlen(argv
[i
+ 1]) < 32);
156 strcpy(partition
, argv
[++i
]);
158 } else if (!strcmp(argv
[i
], "-v")) {
161 assert(strlen(argv
[i
+ 1]) < VNAMESIZE
);
162 strcpy(volume
, argv
[++i
]);
164 } else if (!strcmp(argv
[i
], "-dirInode")) {
167 dirInode
= atoi(argv
[++i
]);
170 } else if (!strcmp(argv
[i
], "-f")) {
173 fileName
= argv
[++i
];
175 } else if (!strcmp(argv
[i
], "-verbose"))
181 /* option to verify whether input file is syntactically good */
182 if (sawDirFile
&& !sawPart
&& !sawVolume
&& !sawDirContents
) {
183 scanDirFile(0, 0, fileName
, option
);
187 /* check input parameters */
188 if (!sawPart
|| !sawVolume
|| !sawDirFile
|| !sawDirContents
)
191 /* extract volume id */
192 volumeId
= atoi(volume
);
194 /* construct unix file name */
195 strcpy(fullName
, partition
);
196 strcat(fullName
, "/V");
197 strcat(fullName
, volume
);
198 strcat(fullName
, VHDREXT
);
200 /* check to see that volume exists */
201 if (stat(fullName
, &statBuf
) < 0) {
202 printf("Error in stat(%s) : %d\n", fullName
, errno
);
206 /* read volume header */
207 if ((fd
= open(fullName
, O_RDONLY
)) < 0) {
208 printf("Error in open(%s) : %d\n", fullName
, errno
);
211 if (read(fd
, &volumeHeader
, sizeof(struct VolumeHeader
)) <
212 sizeof(struct VolumeHeader
)) {
213 printf("Error in reading Volume Header : %d\n", errno
);
217 scanDirFile(statBuf
.st_dev
, dirInode
, fileName
, option
);
222 scanDirFile(dev
, node
, fileName
, option
)
224 Inode node
; /* destination directory inode number */
225 char *fileName
; /* source file to update from */
226 char option
; /* user options */
231 char buf
[READBUFSIZE
]; /* read buffer */
232 struct DirHeader
*dhp
= (struct DirHeader
*)&dirPage
[0];
234 int pgCount
= 0; /* current page */
236 /* open this directory source file */
237 if ((fp
= fopen(fileName
, "r")) == 0) {
238 printf("fopen of %s failed : %d\n", fileName
, errno
);
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
;
247 fgets(buf
, READBUFSIZE
, fp
); /* ignore trailing spaces */
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
;
254 fgets(buf
, READBUFSIZE
, fp
); /* ignore trailing spaces */
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",
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
);
278 /* prints out a directory data */
279 PrintDir(dhp
, pgCount
)
280 struct DirHeader
*dhp
;
281 int pgCount
; /* current page Number */
285 struct PageHeader
*pg
;
287 if (pgCount
== 0) { /* first page */
288 printf("Alloc map: ");
289 for (i
= 0; i
< MAXPAGES
; i
++) { /* read alloMap */
292 printf("%.2x ", dhp
->alloMap
[i
]);
294 printf("\nHash table:");
295 for (i
= 0; i
< NHASHENT
; i
++) {
298 printf("%.2d ", dhp
->hashTable
[i
]);
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
]));
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
);
320 pg
= &((struct DirPage1
*)dhp
)->header
; /* page header */
321 de
= ((struct DirPage1
*)dhp
)->entry
;
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
]));
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
);
342 ** Returns 0 if there are no more pages
343 ** Returns 1 if there are more pages to be read
345 ReadPage(fp
, dhp
, pageNo
) /* Read one page(pageNo) from file fp into dhp */
347 struct DirHeader
*dhp
;
350 int pgcnt
, page
, freecnt
, freebit
[EPP
/ 8];
352 char buf
[READBUFSIZE
]; /* read buffer */
354 int i
, ent
, f
, l
, n
, vnode
, unique
;
356 struct DirEntry
*dirEntry
;
357 struct PageHeader
*pageHeader
;
359 if (fscanf(fp
, "--------------- Page %d ---------------\n", &page
) != 1) {
360 return 0; /* no more pages */
362 /* defensive check */
363 if (page
!= pageNo
) {
364 printf("Wrong page: pageNo %d does not match data in file %d\n",
369 if (fscanf(fp
, "pgcnt :%d", &pgcnt
) != 1) {
370 printf("Error in looking for pgcnt:<int> in page %d\n", pageNo
);
373 fgets(buf
, READBUFSIZE
, fp
); /* ignore trailing spaces */
375 if (fscanf(fp
, "tag :%d", &tag
) != 1) {
376 printf("Error in looking for tag:<int> in page %d\n", pageNo
);
379 fgets(buf
, READBUFSIZE
, fp
); /* ignore trailing spaces */
381 if (fscanf(fp
, "freecnt :%d", &freecnt
) != 1) {
382 printf("Error in looking for freecnt:<int> in page %d\n", pageNo
);
385 fgets(buf
, READBUFSIZE
, fp
); /* ignore trailing spaces */
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],
391 printf("Error in looking for freecnt:<ints> in page %d\n", pageNo
);
394 fgets(buf
, READBUFSIZE
, fp
); /* ignore trailing spaces */
396 if (pageNo
== 0) { /* first page */
397 start
= DHE
+ 1; /* this is 13 */
398 dirEntry
= ((struct DirPage0
*)dhp
)->entry
;
399 pageHeader
= &(dhp
->header
);
402 dirEntry
= ((struct DirPage1
*)dhp
)->entry
;
403 pageHeader
= &(((struct DirPage1
*)dhp
)->header
);
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
];
413 /* update directory entries */
414 for (; start
< EPP
; start
++) {
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
,
423 printf("Wrong dir entry: found %d, has to be %\n", ent
, start
);
427 dirEntry
->length
= l
;
429 dirEntry
->fid
.vnode
= vnode
;
430 dirEntry
->fid
.vunique
= unique
;
431 memcpy(dirEntry
->name
, dirName
, 18);
432 strncpy(dirEntry
->name
, dirName
);
434 dirEntry
= (struct DirEntry
*)((char *)dirEntry
+ 32);
436 return 1; /* there are more pages */