DEVEL15-openafs-string-header-cleanup-20071030
[openafs.git] / src / vol / listinodes.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
12         System:         VICE-TWO
13         Module:         listinodes.c
14         Institution:    The Information Technology Center, Carnegie-Mellon University
15
16  */
17
18 #define ITC                     /* Required by inode.h */
19
20 #include <afsconfig.h>
21 #include <afs/param.h>
22
23 #include <string.h>
24
25 RCSID
26     ("$Header$");
27
28 #ifndef AFS_NAMEI_ENV
29 #if defined(AFS_LINUX20_ENV) || defined(AFS_SUN4_ENV)
30 /* ListViceInodes
31  *
32  * Return codes:
33  * 0 - success
34  * -1 - Unable to read the inodes.
35  * -2 - Unable to completely write temp file. Produces warning message in log.
36  */
37 int
38 ListViceInodes(char *devname, char *mountedOn, char *resultFile,
39                int (*judgeInode) (), int judgeParam, int *forcep, int forceR,
40                char *wpath, void *rock)
41 {
42     Log("ListViceInodes not implemented for this platform!\n");
43     return -1;
44 }
45 #else
46 #include <ctype.h>
47 #include <sys/param.h>
48 #if defined(AFS_SGI_ENV)
49 #else
50 #ifdef  AFS_OSF_ENV
51 #include <ufs/fs.h>
52 #else /* AFS_OSF_ENV */
53 #ifdef AFS_VFSINCL_ENV
54 #define VFS
55 #ifdef    AFS_SUN5_ENV
56 #include <sys/fs/ufs_fs.h>
57 #else
58 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
59 #include <ufs/ufs/dinode.h>
60 #include <ufs/ffs/fs.h>
61 #define itod ino_to_fsba
62 #else
63 #include <ufs/fs.h>
64 #endif
65 #endif
66 #else /* AFS_VFSINCL_ENV */
67 #ifdef  AFS_AIX_ENV
68 #include <sys/filsys.h>
69 #else
70 #include <sys/fs.h>
71 #endif
72 #endif /* AFS_VFSINCL_ENV */
73 #endif /* AFS_OSF_ENV */
74 #include <sys/time.h>
75 #ifdef AFS_VFSINCL_ENV
76 #include <sys/vnode.h>
77 #ifdef    AFS_SUN5_ENV
78 #include <sys/fs/ufs_inode.h>
79 #else
80 #if !defined(AFS_DARWIN_ENV)
81 #include <ufs/inode.h>
82 #endif
83 #endif
84 #else /* AFS_VFSINCL_ENV */
85 #ifdef  AFS_OSF_ENV
86 #include <ufs/inode.h>
87 #else /* AFS_OSF_ENV */
88 #include <sys/inode.h>
89 #endif
90 #endif /* AFS_VFSINCL_ENV */
91 #endif /* AFS_SGI_ENV */
92 #include <afs/osi_inode.h>
93 #include <sys/file.h>
94 #include <stdio.h>
95 #include <rx/xdr.h>
96 #include <afs/afsint.h>
97 #include "nfs.h"
98 #include <afs/afssyscalls.h>
99 #include "viceinode.h"
100 #include <sys/stat.h>
101 #if defined (AFS_AIX_ENV) || defined (AFS_HPUX_ENV)
102 #include <sys/ino.h>
103 #endif
104 #ifdef AFS_PTHREAD_ENV
105 #include <assert.h>
106 #else /* AFS_PTHREAD_ENV */
107 #include <afs/assert.h>
108 #endif /* AFS_PTHREAD_ENV */
109 #if defined(AFS_HPUX101_ENV)
110 #include <unistd.h>
111 #endif
112 #include "partition.h"
113
114 /*@+fcnmacros +macrofcndecl@*/
115 #ifdef O_LARGEFILE
116 #ifdef S_SPLINT_S
117 extern off64_t afs_lseek(int FD, off64_t O, int F);
118 #endif /*S_SPLINT_S */
119 #define afs_lseek(FD, O, F)   lseek64(FD, (off64_t) (O), F)
120 #define afs_stat      stat64
121 #define afs_fstat     fstat64
122 #define afs_open      open64
123 #define afs_fopen     fopen64
124 #else /* !O_LARGEFILE */
125 #ifdef S_SPLINT_S
126 extern off_t afs_lseek(int FD, off_t O, int F);
127 #endif /*S_SPLINT_S */
128 #define afs_lseek(FD, O, F)   lseek(FD, (off_t) (O), F)
129 #define afs_stat      stat
130 #define afs_fstat     fstat
131 #define afs_open      open
132 #define afs_fopen     fopen
133 #endif /* !O_LARGEFILE */
134 /*@=fcnmacros =macrofcndecl@*/
135
136 /* Notice:  parts of this module have been cribbed from vfsck.c */
137
138 #define ROOTINODE       2
139 static char *partition;
140 int Testing=0;
141 int pfd;
142
143 #ifdef  AFS_AIX32_ENV
144 #include <jfs/filsys.h>
145
146 #ifndef FSBSIZE
147 #define FSBSIZE         (4096)  /* filesystem block size        */
148 #define FSBSHIFT        (12)    /* log2(FSBSIZE)                */
149 #define FSBMASK         (FSBSIZE - 1)   /* FSBSIZE mask                 */
150
151 #define MIN_FSIZE       DISKMAP_B       /* minimum fs size (FSblocks)   */
152 #define LAST_RSVD_I     15      /* last reserved inode          */
153 #endif
154
155 #ifndef INOPB
156 /*
157  * This will hopefully eventually make it into the system include files
158  */
159 #define INOPB           (FSBSIZE / sizeof (struct dinode))
160 #endif
161
162 #ifdef AFS_AIX41_ENV
163 int fragsize;
164 int iagsize;
165 int ag512;
166 int agblocks;
167 #endif /* AFS_AIX41_ENV */
168
169 /*
170  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
171  XX This was lifted from some `com/cmd/fs/fshlpr_aix3/Fs.h', which indicated X
172  XX a longing to see it make it into a readily accessible include file. XXXXXX
173  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
174  *
175  * itoo - inode number to offset within disk block
176  */
177 #undef itoo
178 #define itoo(x)         (int) ((unsigned)(x) % INOPB)
179
180 int Bsize = FSBSIZE;            /* block size for this system                   */
181 daddr_t fmax;                   /* total number of blocks n file system         */
182 ino_t imax, inum;               /* total number of I-nodes in file system       */
183
184 static struct superblock fs;
185 struct dinode *ginode();
186
187
188 int
189 ListViceInodes(char *devname, char *mountedOn, char *resultFile,
190                int (*judgeInode) (), int judgeParam, int *forcep, int forceR,
191                char *wpath, void *rock)
192 {
193     FILE *inodeFile = NULL;
194     char dev[50], rdev[51];
195     struct stat status;
196     struct dinode *p;
197     struct ViceInodeInfo info;
198     struct stat root_inode;
199     int ninodes = 0, err = 0;
200
201     pfd = -1;                   /* initialize so we don't close on error output below. */
202     *forcep = 0;
203     sync();
204     sleep(1);                   /* simulate operator    */
205     sync();
206     sleep(1);
207     sync();
208     sleep(1);
209
210     partition = mountedOn;
211     sprintf(dev, "/dev/%s", devname);
212     sprintf(rdev, "/dev/r%s", devname);
213
214     if (stat(mountedOn, &root_inode) < 0) {
215         Log("cannot stat: %s\n", mountedOn);
216         return -1;
217     }
218
219     if (root_inode.st_ino != ROOTDIR_I) {
220         Log("%s is not root of a filesystem\n", mountedOn);
221         return -1;
222     }
223
224
225     /*
226      * done with the superblock, now try to read the raw device.
227      */
228     if (ReadSuper(&fs, dev) < 0)
229         return -1;
230
231     switch (fs.s_fmod) {
232     default:
233     case FM_CLEAN:              /* clean and unmounted                  */
234         Log("Most peculiar - Super blk in FM_CLEAN state!\n");
235         goto out;
236     case FM_MOUNT:              /* mounted cleanly                      */
237         break;
238
239     case FM_MDIRTY:             /* dirty when mounted or commit fail    */
240     case FM_LOGREDO:            /* log redo attempted but failed        */
241         Log("File system %s is in a bad state.\n", rdev);
242         Log("Call your IBM representative.\n");
243         return -1;
244     }
245 #ifdef AFS_AIX42_ENV
246     if (IsBigFilesFileSystem(&fs, (char *)0)) {
247         Log("%s is a big files filesystem, can't salvage.\n", mountedOn);
248         return -1;
249     }
250 #else
251     if (strncmp(fs.s_magic, fsv3magic, strlen(fsv3magic)) != 0) {
252 #ifdef  AFS_AIX41_ENV
253         if ((strncmp(fs.s_magic, fsv3pmagic, strlen(fsv3pmagic)) != 0)
254             || (fs.s_version != fsv3pvers)) {
255             Log("Super block doesn't have the problem magic (%s vs v3magic %s v3pmagic %s)\n", fs.s_magic, fsv3magic, fsv3pmagic);
256             return -1;
257         }
258 #else
259         Log("Super block doesn't have the problem magic (%s vs v3magic %s)\n",
260             fs.s_magic, fsv3magic);
261         return -1;
262 #endif
263     }
264 #endif
265
266 #ifdef AFS_AIX41_ENV
267     fragsize = (fs.s_fragsize) ? fs.s_fragsize : FSBSIZE;
268     iagsize = (fs.s_iagsize) ? fs.s_iagsize : fs.s_agsize;
269     ag512 = fragsize * fs.s_agsize / 512;
270     agblocks = fragsize * fs.s_agsize >> BSHIFT;
271 #endif /* AFS_AIX41_ENV */
272
273     fmax = fs.s_fsize / (FSBSIZE / 512);        /* first invalid blk num */
274
275     pfd = afs_open(rdev, O_RDONLY);
276     if (pfd < 0) {
277         Log("Unable to open `%s' inode for reading\n", rdev);
278         return -1;
279     }
280
281     inodeFile = fopen(resultFile, "w");
282     if (inodeFile == NULL) {
283         Log("Unable to create inode description file %s\n", resultFile);
284         goto out;
285     }
286
287     /*
288      * calculate the maximum number of inodes possible
289      */
290 #ifdef AFS_AIX41_ENV
291     imax = iagsize * (fs.s_fsize / ag512) - 1;
292 #else /* AFS_AIX41_ENV */
293     imax =
294         ((fmax / fs.s_agsize +
295           ((fmax % fs.s_agsize) >= fs.s_agsize / INOPB ? 1 : 0))
296          * fs.s_agsize) - 1;
297 #endif /* AFS_AIX41_ENV */
298
299     /*
300      * check for "FORCESALVAGE" equivalent:
301      *      LAST_RSVD_I is a vice inode, with dead beef, and
302      *      di_nlink == 2 to indicate the FORCE.
303      */
304     assert(p = ginode(LAST_RSVD_I));
305
306     if (p->di_vicemagic == VICEMAGIC && p->di_vicep1 == 0xdeadbeef
307         && p->di_nlink == 2) {
308         *forcep = 1;
309         idec(root_inode.st_dev, LAST_RSVD_I, 0xdeadbeef);
310     }
311
312     for (inum = LAST_RSVD_I + 1; inum <= imax; ++inum) {
313         if ((p = ginode(inum)) == NULL || p->di_vicemagic != VICEMAGIC
314             || (p->di_mode & IFMT) != IFREG)
315             continue;
316
317         info.inodeNumber = inum;
318         info.byteCount = p->di_size;
319         info.linkCount = p->di_nlink;
320         info.u.param[0] = p->di_vicep1;
321         info.u.param[1] = p->di_vicep2;
322         info.u.param[2] = p->di_vicep3;
323         info.u.param[3] = p->di_vicep4;
324
325         if (judgeInode && (*judgeInode) (&info, judgeParam, rock) == 0)
326             continue;
327
328         if (fwrite(&info, sizeof info, 1, inodeFile) != 1) {
329             Log("Error writing inode file for partition %s\n", partition);
330             goto out;
331         }
332         ++ninodes;
333     }
334
335     if (fflush(inodeFile) == EOF) {
336         Log("Unable to successfully flush inode file for %s\n", partition);
337         err = -2;
338         goto out1;
339     }
340     if (fsync(fileno(inodeFile)) == -1) {
341         Log("Unable to successfully fsync inode file for %s\n", partition);
342         err = -2;
343         goto out1;
344     }
345     if (fclose(inodeFile) == EOF) {
346         Log("Unable to successfully close inode file for %s\n", partition);
347         err = -2;
348         goto out1;
349     }
350
351     /*
352      * Paranoia:  check that the file is really the right size
353      */
354     if (stat(resultFile, &status) == -1) {
355         Log("Unable to successfully stat inode file for %s\n", partition);
356         err = -2;
357         goto out1;
358     }
359     if (status.st_size != ninodes * sizeof(struct ViceInodeInfo)) {
360         Log("Wrong size (%d instead of %d) in inode file for %s\n",
361             status.st_size, ninodes * sizeof(struct ViceInodeInfo),
362             partition);
363         err = -2;
364         goto out1;
365     }
366     close(pfd);
367     return 0;
368
369   out:
370     err = -1;
371   out1:
372     if (pfd >= 0)
373         close(pfd);
374     if (inodeFile)
375         fclose(inodeFile);
376
377     return err;
378 }
379
380 /* Read in the superblock for devName */
381 int
382 ReadSuper(struct superblock *fs, char *devName)
383 {
384     int pfd;
385
386     pfd = afs_open(devName, O_RDONLY);
387     if (pfd < 0) {
388         Log("Unable to open inode on %s for reading superblock.\n", devName);
389         return -1;
390     }
391
392     if (bread(pfd, fs, SUPER_B, sizeof(struct superblock)) < 0) {
393         Log("Unable to read superblock on %s.\n", devName);
394         return -1;
395     }
396     close(pfd);
397     return (0);
398 }
399
400 #ifdef AFS_AIX42_ENV
401 /* IsBigFilesFileSystem returns 1 if it's a big files filesystem, 0 otherwise. */
402 int
403 IsBigFilesFileSystem(struct superblock *sb)
404 {
405     if ((strncmp(sb->s_magic, fsv3pmagic, 4) == 0)
406         && (sb->s_version == fsbigfile)
407         && (sb->s_bigexp))
408         return 1;
409     else
410         return 0;
411 }
412 #endif
413
414 struct dinode *
415 ginode(inum)
416 {
417     int ag;
418     daddr_t pblk;
419     struct dinode *dp;
420     static char buf[FSBSIZE];
421     static daddr_t last_blk = -1;
422
423 #ifdef AFS_AIX41_ENV
424     ag = inum / iagsize;
425     pblk =
426         (ag ==
427          0) ? INODES_B + inum / INOPB : ag * agblocks + (inum -
428                                                          ag * iagsize) /
429         INOPB;
430 #else /* AFS_AIX41_ENV */
431     ag = inum / fs.s_agsize;
432     pblk =
433         (ag ==
434          0) ? INODES_B + inum / INOPB : ag * fs.s_agsize + (inum -
435                                                             ag *
436                                                             fs.s_agsize) /
437         INOPB;
438 #endif /* AFS_AIX41_ENV */
439
440     if (last_blk != pblk) {
441         if (bread(pfd, buf, pblk, sizeof(buf)) < 0) {
442             last_blk = -1;
443             return 0;
444         }
445         last_blk = pblk;
446     }
447
448     dp = (struct dinode *)buf;
449     dp += itoo(inum);
450     return (dp);
451 }
452
453 #else /* !AFS_AIX31_ENV       */
454
455 #if defined(AFS_SGI_ENV)
456
457 /* libefs.h includes <assert.h>, which we don't want */
458 #define __ASSERT_H__
459
460 #ifdef AFS_SGI_EFS_IOPS_ENV
461 #include "sgiefs/libefs.h"
462 extern int Log();
463
464 /* afs_efs_figet() replaces the SGI library routine because we are malloc'ing
465  * memory for all the inodes on all the cylinder groups without releasing
466  * it when we're done. Using afs_efs_figet ensures more efficient use of
467  * memory.
468  */
469 struct efs_dinode *
470 afs_efs_figet(EFS_MOUNT * mp, struct efs_dinode *dinodeBuf, int *last_cgno,
471               ino_t inum)
472 {
473     int cgno = EFS_ITOCG(mp->m_fs, inum);
474
475
476     if (cgno != *last_cgno) {
477         if (efs_readb
478             (mp->m_fd, (char *)dinodeBuf, EFS_CGIMIN(mp->m_fs, cgno),
479              mp->m_fs->fs_cgisize) != mp->m_fs->fs_cgisize) {
480             Log("Unable to read inodes for cylinder group %d.\n", cgno);
481             return NULL;
482         }
483         *last_cgno = cgno;
484     }
485
486     return dinodeBuf + (inum % (mp->m_fs->fs_cgisize * EFS_INOPBB));
487 }
488
489
490 int
491 efs_ListViceInodes(char *devname, char *mountedOn, char *resultFile,
492                    int (*judgeInode) (), int judgeParam, int *forcep,
493                    int forceR, char *wpath, void *rock)
494 {
495     FILE *inodeFile = NULL;
496     char dev[50], rdev[51];
497     struct stat status;
498     struct efs_dinode *p;
499     struct ViceInodeInfo info;
500     int ninodes = 0, err = 0;
501     struct efs_dinode *dinodeBuf = NULL;
502     int last_cgno;
503     EFS_MOUNT *mp;
504     ino_t imax, inum;           /* total number of I-nodes in file system */
505
506     *forcep = 0;
507
508     partition = mountedOn;
509     sprintf(dev, "/dev/dsk/%s", devname);
510     sprintf(rdev, "/dev/rdsk/%s", devname);
511
512
513     /*
514      * open raw device
515      */
516     efs_init(Log);
517     if ((stat(rdev, &status) == -1)
518         || ((mp = efs_mount(rdev, O_RDONLY)) == NULL)) {
519         sprintf(rdev, "/dev/r%s", devname);
520         mp = efs_mount(rdev, O_RDONLY);
521     }
522     if (mp == NULL) {
523         Log("Unable to open `%s' inode for reading\n", rdev);
524         return -1;
525     }
526
527     inodeFile = fopen(resultFile, "w");
528     if (inodeFile == NULL) {
529         Log("Unable to create inode description file %s\n", resultFile);
530         goto out;
531     }
532
533     /* Allocate space for one cylinder group's worth of inodes. */
534     dinodeBuf = (struct efs_dinode *)malloc(mp->m_fs->fs_cgisize * BBSIZE);
535     if (!dinodeBuf) {
536         Log("Unable to malloc %lu bytes for inode buffer.\n",
537             mp->m_fs->fs_cgisize * BBSIZE);
538         goto out;
539     }
540
541     /*
542      * calculate the maximum number of inodes possible
543      */
544     imax = mp->m_fs->fs_ncg * mp->m_fs->fs_ipcg;
545
546     last_cgno = -1;
547     for (inum = 2; inum < imax; ++inum) {
548         p = afs_efs_figet(mp, dinodeBuf, &last_cgno, inum);
549         if (!p) {
550             Log("Unable to read all inodes from partition.\n");
551             goto out;
552         }
553         if (!IS_DVICEMAGIC(p) || !((p->di_mode & IFMT) == IFREG)) {
554             continue;
555         }
556 #if defined(AFS_SGI_EXMAG)
557         /* volume ID */
558         info.u.param[0] =
559             dmag(p, 0) << 24 | dmag(p, 1) << 16 | dmag(p, 2) << 8 | dmag(p,
560                                                                          3) <<
561             0;
562         if ((p)->di_version == EFS_IVER_AFSSPEC) {
563             info.u.param[1] = INODESPECIAL;
564             /* type */
565             info.u.param[2] = dmag(p, 8);
566             /* parentId */
567             info.u.param[3] =
568                 dmag(p, 4) << 24 | dmag(p, 5) << 16 | dmag(p,
569                                                            6) << 8 | dmag(p,
570                                                                           7)
571                 << 0;
572         } else {
573             /* vnode number */
574             info.u.param[1] =
575                 dmag(p, 4) << 16 | dmag(p, 5) << 8 | dmag(p, 6) << 0;
576             /* disk uniqifier */
577             info.u.param[2] =
578                 dmag(p, 7) << 16 | dmag(p, 8) << 8 | dmag(p, 9) << 0;
579             /* data version */
580             info.u.param[3] =
581                 dmag(p, 10) << 16 | dmag(p, 11) << 8 | (p)->di_spare;
582         }
583 #else
584         BOMB ! !
585 #endif
586             info.inodeNumber = inum;
587         info.byteCount = p->di_size;
588         info.linkCount = p->di_nlink;
589 #ifdef notdef
590         Log("Ino=%d, bytes=%d, linkCnt=%d, [%x,%x,%x,%x]\n", inum, p->di_size,
591             p->di_nlink, info.u.param[0], info.u.param[1], info.u.param[2],
592             info.u.param[3]);
593 #endif
594         if (judgeInode && (*judgeInode) (&info, judgeParam, rock) == 0)
595             continue;
596
597         if (fwrite(&info, sizeof info, 1, inodeFile) != 1) {
598             Log("Error writing inode file for partition %s\n", partition);
599             goto out;
600         }
601         ++ninodes;
602     }
603
604     if (fflush(inodeFile) == EOF) {
605         Log("Unable to successfully flush inode file for %s\n", partition);
606         err = -2;
607         goto out1;
608     }
609     if (fsync(fileno(inodeFile)) == -1) {
610         Log("Unable to successfully fsync inode file for %s\n", partition);
611         err = -2;
612         goto out1;
613     }
614     if (fclose(inodeFile) == EOF) {
615         Log("Unable to successfully close inode file for %s\n", partition);
616         err = -2;
617         goto out1;
618     }
619
620     /*
621      * Paranoia:  check that the file is really the right size
622      */
623     if (stat(resultFile, &status) == -1) {
624         Log("Unable to successfully stat inode file for %s\n", partition);
625         err = -2;
626         goto out1;
627     }
628     if (status.st_size != ninodes * sizeof(struct ViceInodeInfo)) {
629         Log("Wrong size (%d instead of %d) in inode file for %s\n",
630             status.st_size, ninodes * sizeof(struct ViceInodeInfo),
631             partition);
632         err = -2;
633         goto out1;
634     }
635     efs_umount(mp);
636     if (dinodeBuf) {
637         free(dinodeBuf);
638     }
639     return 0;
640
641   out:
642     err = -1;
643   out1:
644     if (dinodeBuf) {
645         free(dinodeBuf);
646     }
647     efs_umount(mp);
648     if (inodeFile)
649         fclose(inodeFile);
650
651     return err;
652 }
653 #endif /* AFS_SGI_EFS_IOPS_ENV */
654
655 #ifdef AFS_SGI_XFS_IOPS_ENV
656 #include <dirent.h>
657 #include <afs/xfsattrs.h>
658 /* xfs_ListViceInodes
659  *
660  * xfs_ListViceInodes verifies and correct the XFS namespace as it collects
661  * the inode information. The name is required for the idec operation to work. 
662  * Steps 2 and 3 below are for the AFS_XFS_NAME_VERS == 1. If the name space
663  * changes, the algorithm will need to change. 
664  * 1) If the parent inode number does not match the directory's inod number,
665  *    change it in the attribute.
666  * 2) If the unqifier in the attribute does not match the name, rename the
667  *    file. This is done by doing an exclusive open, incrementing the tag
668  *    number until a file can be created. If the tag changes, then the
669  *    attribute will need updating.
670  * 3) If the tag in the attribute does not match the name, change the
671  *    attribute.
672  * 4) Verify uid = RW volume id and gid = XFS_VICEMAGIC.
673  *
674  */
675
676 /* xfs_VerifyInode
677  * 
678  * Does the verifications listed above.
679  * We can't change the names until the readdir is complete, so we set the
680  * rename flag if the file needs renaming.
681  */
682 int
683 xfs_VerifyInode(char *dir, uint64_t pino, char *name, i_list_inode_t * info,
684                 int *rename)
685 {
686     char path[1024];
687     int vno;
688     int update_pino = 0;
689     int update_tag = 0;
690     int update_chown = 0;
691     int retCode = 0;
692     char tmpName[32];
693     b64_string_t stmp;
694     int tag;
695
696     *rename = 0;
697     (void)sprintf(path, "%s/%s", dir, name);
698     /* Verify uid and gid fields */
699     if (info->ili_magic != XFS_VICEMAGIC) {
700         Log("%s  magic for %s/%s (inode %s) from %d to %d\n",
701             Testing ? "Would have changed" : "Changing", dir, name,
702             PrintInode(NULL, info->ili_info.inodeNumber), info->ili_magic,
703             XFS_VICEMAGIC);
704         if (!Testing)
705             update_chown = 1;
706     }
707
708     vno = info->ili_info.param[0];
709     if (info->ili_vno != AFS_XFS_VNO_CLIP(vno)) {
710         Log("%s volume id for %s/%s (inode %s) from %d to %d\n",
711             Testing ? "Would have changed" : "Changing", dir, name,
712             PrintInode(NULL, info->ili_info.inodeNumber), info->ili_vno,
713             AFS_XFS_VNO_CLIP(vno));
714         if (!Testing)
715             update_chown = 1;
716     }
717
718     if (update_chown) {
719         if (chown(path, AFS_XFS_VNO_CLIP(vno), XFS_VICEMAGIC) < 0) {
720             Log("Can't chown %s to uid=%d, gid=0x%x\n", path,
721                 AFS_XFS_VNO_CLIP(vno), XFS_VICEMAGIC);
722             retCode = -1;
723         }
724     }
725
726     /* Check Parent inode number. */
727     if (info->ili_pino != pino) {
728         afs_ino_str_t sino, sipino, spino;
729         (void)PrintInode(sino, info->ili_info.inodeNumber);
730         (void)PrintInode(sipino, info->ili_pino);
731         (void)PrintInode(spino, pino);
732         Log("%s parent ino for %s (inode %s) from %s to %s.\n",
733             Testing ? "Would have changed" : "Changing", path, sino, sipino,
734             spino);
735         if (!Testing)
736             update_pino = 1;
737     }
738
739     /* Verify the file name. */
740     (void)strcpy(tmpName, ".");
741     (void)strcat(tmpName, int_to_base64(stmp, info->ili_info.param[2]));
742     if (strncmp(name, tmpName, strlen(tmpName))) {
743         Log("%s name %s (inode %s) in directory %s, unique=%d, tag=%d\n",
744             Testing ? "Would have returned bad" : "Bad", name,
745             PrintInode(NULL, info->ili_info.inodeNumber), dir,
746             info->ili_info.param[2], info->ili_tag);
747         if (!Testing)
748             *rename = 1;
749     }
750
751     if (!*rename) {
752         /* update the tag? */
753         (void)strcat(tmpName, ".");
754         (void)strcat(tmpName, int_to_base64(stmp, info->ili_tag));
755         if (strcmp(name, tmpName)) {
756             char *p;
757             (void)strcpy(tmpName, name);
758             p = strchr(tmpName + 1, '.');
759             if (!p) {
760                 Log("No tag found on name %s (inode %s)in directory, %s.\n",
761                     name, PrintInode(NULL, info->ili_info.inodeNumber), dir,
762                     Testing ? "would have renamed" : "will rename");
763                 if (!Testing)
764                     *rename = 1;
765             } else {
766                 tag = base64_to_int(p + 1);
767                 Log("%s the tag for %s (inode %s) from %d to %d.\n",
768                     Testing ? "Would have changed" : "Will change", path,
769                     PrintInode(NULL, info->ili_info.inodeNumber), dir, tag,
770                     info->ili_tag);
771                 if (!Testing)
772                     update_tag = 1;
773             }
774         }
775     }
776
777     if (update_pino || update_tag) {
778         afs_xfs_attr_t attrs;
779         int length;
780
781         length = SIZEOF_XFS_ATTR_T;
782         if (attr_get(path, AFS_XFS_ATTR, (char *)&attrs, &length, ATTR_ROOT) <
783             0) {
784             Log("Can't get AFS attribute for %s\n", path);
785             return -1;
786         }
787         if (update_pino)
788             attrs.at_pino = pino;
789         if (update_tag)
790             attrs.at_tag = tag;
791         if (attr_set
792             (path, AFS_XFS_ATTR, (char *)&attrs, length,
793              ATTR_ROOT | ATTR_REPLACE) < 0) {
794             Log("Can't set AFS attribute into %s\n", path);
795             retCode = -1;
796         }
797     }
798
799     return retCode;
800 }
801
802 typedef struct {
803     int uniq;
804     char name[28];
805 } xfs_Rename_t;
806
807 int
808 xfs_RenameFiles(char *dir, xfs_Rename_t * renames, int n_renames)
809 {
810     int i, j;
811     char opath[128], nbase[128], npath[128];
812     afs_xfs_attr_t attrs;
813     int length = SIZEOF_XFS_ATTR_T;
814     b64_string_t stmp;
815     int tag;
816     int fd;
817
818     for (i = 0; i < n_renames; i++) {
819         (void)sprintf(opath, "%s/%s", dir, renames[i].name);
820         (void)sprintf(nbase, "%s/.%s", dir,
821                       int_to_base64(stmp, renames[i].uniq));
822         for (tag = 2, j = 0; j < 64; tag++, j++) {
823             (void)sprintf(npath, "%s.%s", nbase, int_to_base64(stmp, tag));
824             fd = afs_open(npath, O_CREAT | O_EXCL | O_RDWR, 0);
825             if (fd > 0) {
826                 close(fd);
827                 break;
828             }
829         }
830         if (j != 64) {
831             Log("Can't find a new name for %s\n", opath);
832             return -1;
833         }
834         if (rename(opath, npath) < 0) {
835             Log("Can't rename %s to %s\n", opath, npath);
836             return -1;
837         }
838         Log("Renamed %s to %s\n", opath, npath);
839         return 0;
840     }
841 }
842
843
844 int
845 xfs_ListViceInodes(char *devname, char *mountedOn, char *resultFile,
846                    int (*judgeInode) (), int judgeParam, int *forcep,
847                    int forceR, char *wpath, void *rock)
848 {
849     FILE *inodeFile = NULL;
850     i_list_inode_t info;
851     int info_size = sizeof(i_list_inode_t);
852     int fd;
853     DIR *top_dirp;
854     dirent64_t *top_direntp;
855     DIR *vol_dirp;
856     dirent64_t *vol_direntp;
857     struct stat64 sdirbuf;
858     struct stat64 sfilebuf;
859     afs_xfs_attr_t attrs;
860     afs_xfs_dattr_t dattrs;
861     int length;
862     char vol_dirname[1024];
863     int ninodes = 0;
864     int code = 0;
865     xfs_Rename_t *renames = (xfs_Rename_t *) 0;
866     int rename;
867 #define N_RENAME_STEP 64
868     int n_renames = 0;
869     int n_avail = 0;
870     uint64_t pino;
871     struct stat status;
872     int errors = 0;
873
874     *forcep = 0;
875
876     if (stat64(mountedOn, &sdirbuf) < 0) {
877         perror("xfs_ListViceInodes: stat64");
878         return -1;
879     }
880
881     inodeFile = fopen(resultFile, "w");
882     if (inodeFile == NULL) {
883         Log("Unable to create inode description file %s\n", resultFile);
884         return -1;
885     }
886
887     if ((top_dirp = opendir(mountedOn)) == NULL) {
888         Log("Can't open directory %s to read inodes.\n", mountedOn);
889         return -1;
890     }
891
892     while (top_direntp = readdir64(top_dirp)) {
893         /* Only descend directories with the AFSDIR attribute set.
894          * Could also verify the contents of the atribute, but currently
895          * they are not used.
896          * Performance could be improved for single volume salvages by
897          * only going through the directory containing the volume's inodes.
898          * But I'm being complete as a first pass.
899          */
900         (void)sprintf(vol_dirname, "%s/%s", mountedOn, top_direntp->d_name);
901         length = SIZEOF_XFS_DATTR_T;
902         if (attr_get
903             (vol_dirname, AFS_XFS_DATTR, (char *)&dattrs, &length, ATTR_ROOT))
904             continue;
905
906         if ((vol_dirp = opendir(vol_dirname)) == NULL) {
907             if (errno == ENOTDIR)
908                 continue;
909             Log("Can't open directory %s to read inodes.\n", vol_dirname);
910             goto err1_exit;
911         }
912
913         pino = top_direntp->d_ino;
914         n_renames = 0;
915         while (vol_direntp = readdir64(vol_dirp)) {
916             if (vol_direntp->d_name[1] == '\0'
917                 || vol_direntp->d_name[1] == '.')
918                 continue;
919
920             info.ili_version = AFS_XFS_ILI_VERSION;
921             info_size = sizeof(i_list_inode_t);
922             code =
923                 ilistinode64(sdirbuf.st_dev, vol_direntp->d_ino, &info,
924                              &info_size);
925             if (code) {
926                 /* Where possible, give more explicit messages. */
927                 switch (errno) {
928                 case ENXIO:
929                 case ENOSYS:
930                     Log("%s (device id %d) is not on an XFS filesystem.\n",
931                         vol_dirname, sdirbuf.st_dev);
932                     goto err1_exit;
933                     break;
934                 case EINVAL:
935                 case E2BIG:
936                     if (info_size != sizeof(i_list_inode_t)
937                         || info.ili_version != AFS_XFS_ILI_VERSION) {
938                         Log("Version skew between kernel and salvager.\n");
939                         goto err1_exit;
940                     }
941                     break;
942                 }
943                 /* Continue, so we collect all the errors in the first pass. */
944                 Log("Error listing inode named %s/%s: %s\n", vol_dirname,
945                     vol_direntp->d_name, strerror(errno));
946                 errors++;
947                 continue;
948             }
949
950             if (info.ili_attr_version != AFS_XFS_ATTR_VERS) {
951                 Log("Unrecognized XFS attribute version %d in %s/%s. Upgrade salvager\n", info.ili_attr_version, vol_dirname, vol_direntp->d_name);
952                 goto err1_exit;
953             }
954
955             if (judgeInode && (*judgeInode) (&info.ili_info, judgeParam, rock) == 0)
956                 continue;
957
958             rename = 0;
959             if (xfs_VerifyInode
960                 (vol_dirname, pino, vol_direntp->d_name, &info,
961                  &rename) < 0) {
962                 errors++;
963             }
964
965             if (rename) {
966                 /* Add this name to the list of items to rename. */
967                 if (n_renames >= n_avail) {
968                     n_avail += N_RENAME_STEP;
969                     if (n_avail == N_RENAME_STEP)
970                         renames = (xfs_Rename_t *)
971                             malloc(n_avail * sizeof(xfs_Rename_t));
972                     else
973                         renames = (xfs_Rename_t *)
974                             realloc((char *)renames,
975                                     n_avail * sizeof(xfs_Rename_t));
976                     if (!renames) {
977                         Log("Can't %salloc %lu bytes for rename list.\n",
978                             (n_avail == N_RENAME_STEP) ? "m" : "re",
979                             n_avail * sizeof(xfs_Rename_t));
980                         goto err1_exit;
981                     }
982                 }
983                 (void)strcpy(renames[n_renames].name, vol_direntp->d_name);
984                 renames[n_renames].uniq = info.ili_info.param[2];
985                 n_renames++;
986             }
987
988             if (fwrite
989                 (&info.ili_info, sizeof(vice_inode_info_t), 1, inodeFile)
990                 != 1) {
991                 Log("Error writing inode file for partition %s\n", mountedOn);
992                 goto err1_exit;
993             }
994             ninodes++;
995
996         }                       /* end while vol_direntp */
997
998         closedir(vol_dirp);
999         vol_dirp = (DIR *) 0;
1000         if (n_renames) {
1001             Log("Renaming files.\n");
1002             if (xfs_RenameFiles(vol_dirname, renames, n_renames) < 0) {
1003                 goto err1_exit;
1004             }
1005         }
1006     }
1007
1008     closedir(top_dirp);
1009     if (renames)
1010         free((char *)renames);
1011     if (fflush(inodeFile) == EOF) {
1012         ("Unable to successfully flush inode file for %s\n", mountedOn);
1013         fclose(inodeFile);
1014         return errors ? -1 : -2;
1015     }
1016     if (fsync(fileno(inodeFile)) == -1) {
1017         Log("Unable to successfully fsync inode file for %s\n", mountedOn);
1018         fclose(inodeFile);
1019         return errors ? -1 : -2;
1020     }
1021     if (fclose(inodeFile) == EOF) {
1022         Log("Unable to successfully close inode file for %s\n", mountedOn);
1023         return errors ? -1 : -2;
1024     }
1025     /*
1026      * Paranoia:  check that the file is really the right size
1027      */
1028     if (stat(resultFile, &status) == -1) {
1029         Log("Unable to successfully stat inode file for %s\n", partition);
1030         return errors ? -1 : -2;
1031     }
1032     if (status.st_size != ninodes * sizeof(struct ViceInodeInfo)) {
1033         Log("Wrong size (%d instead of %d) in inode file for %s\n",
1034             status.st_size, ninodes * sizeof(struct ViceInodeInfo),
1035             partition);
1036         return errors ? -1 : -2;
1037     }
1038
1039     if (errors) {
1040         Log("Errors encontered listing inodes, not salvaging partition.\n");
1041         return -1;
1042     }
1043
1044     return 0;
1045
1046   err1_exit:
1047     if (vol_dirp)
1048         closedir(vol_dirp);
1049     if (top_dirp)
1050         closedir(top_dirp);
1051     if (renames)
1052         free((char *)renames);
1053     if (inodeFile)
1054         fclose(inodeFile);
1055     return -1;
1056 }
1057
1058 #endif
1059
1060 int
1061 ListViceInodes(char *devname, char *mountedOn, char *resultFile,
1062                int (*judgeInode) (), int judgeParam, int *forcep, int forceR,
1063                char *wpath, void *rock)
1064 {
1065     FILE *inodeFile = NULL;
1066     char dev[50], rdev[51];
1067     struct stat status;
1068     struct efs_dinode *p;
1069     struct ViceInodeInfo info;
1070     struct stat root_inode;
1071     int ninodes = 0, err = 0;
1072     struct efs_dinode *dinodeBuf = NULL;
1073     int last_cgno;
1074 #ifdef AFS_SGI_EFS_IOPS_ENV
1075     EFS_MOUNT *mp;
1076 #endif
1077     ino_t imax, inum;           /* total number of I-nodes in file system */
1078
1079     *forcep = 0;
1080     sync();
1081     sleep(1);                   /* simulate operator    */
1082     sync();
1083     sleep(1);
1084     sync();
1085     sleep(1);
1086
1087     if (stat(mountedOn, &root_inode) < 0) {
1088         Log("cannot stat: %s\n", mountedOn);
1089         return -1;
1090     }
1091 #ifdef AFS_SGI_XFS_IOPS_ENV
1092     if (!strcmp("xfs", root_inode.st_fstype)) {
1093         return xfs_ListViceInodes(devname, mountedOn, resultFile, judgeInode,
1094                                   judgeParam, forcep, forceR, wpath, rock);
1095     } else
1096 #endif
1097 #ifdef AFS_SGI_EFS_IOPS_ENV
1098     if (root_inode.st_ino == EFS_ROOTINO) {
1099         return efs_ListViceInodes(devname, mountedOn, resultFile, judgeInode,
1100                                   judgeParam, forcep, forceR, wpath, rock);
1101     } else
1102 #endif
1103     {
1104         Log("%s is not root of a filesystem\n", mountedOn);
1105         return -1;
1106     }
1107 }
1108
1109 #else /* AFS_SGI_ENV */
1110
1111 #ifdef AFS_HPUX_ENV
1112 #define SPERB   (MAXBSIZE / sizeof(short))
1113 #define MAXNINDIR (MAXBSIZE / sizeof(daddr_t))
1114
1115 struct bufarea {
1116     struct bufarea *b_next;     /* must be first */
1117     daddr_t b_bno;
1118     int b_size;
1119     union {
1120         char b_buf[MAXBSIZE];   /* buffer space */
1121         short b_lnks[SPERB];    /* link counts */
1122         daddr_t b_indir[MAXNINDIR];     /* indirect block */
1123         struct fs b_fs;         /* super block */
1124         struct cg b_cg;         /* cylinder group */
1125     } b_un;
1126     char b_dirty;
1127 };
1128 typedef struct bufarea BUFAREA;
1129
1130 BUFAREA sblk;
1131 #define sblock sblk.b_un.b_fs
1132 #endif /* AFS_HPUX_ENV */
1133
1134 extern char *afs_rawname();
1135 int
1136 ListViceInodes(char *devname, char *mountedOn, char *resultFile,
1137                int (*judgeInode) (), int judgeParam, int *forcep, int forceR,
1138                char *wpath, void *rock)
1139 {
1140     union {
1141 #ifdef  AFS_AIX_ENV
1142         struct filsys fs;
1143         char block[BSIZE];
1144 #else                           /* !AFS_AIX_ENV */
1145         struct fs fs;
1146         char block[SBSIZE];
1147 #endif
1148     } super;
1149     int i, c, e, bufsize, code, err = 0;
1150     FILE *inodeFile = NULL;
1151     char dev[50], rdev[100], err1[512], *ptr1;
1152     struct dinode *inodes = NULL, *einodes, *dptr;
1153     struct stat status;
1154     int ninodes = 0;
1155     struct dinode *p;
1156     struct ViceInodeInfo info;
1157
1158     *forcep = 0;
1159     partition = mountedOn;
1160     sprintf(rdev, "%s/%s", wpath, devname);
1161     ptr1 = afs_rawname(rdev);
1162     strcpy(rdev, ptr1);
1163
1164     sync();
1165     /* Bletch:  this is terrible;  is there a better way to do this? Does this work? vfsck doesn't even sleep!! */
1166 #ifdef  AFS_AIX_ENV
1167     sleep(5);                   /* Trying a smaller one for aix */
1168 #else
1169     sleep(10);
1170 #endif
1171
1172     pfd = afs_open(rdev, O_RDONLY);
1173     if (pfd <= 0) {
1174         sprintf(err1, "Could not open device %s to get inode list\n", rdev);
1175         perror(err1);
1176         return -1;
1177     }
1178 #ifdef  AFS_AIX_ENV
1179     if (bread(pfd, (char *)&super.fs, SUPERB, sizeof super.fs) == -1) {
1180 #else
1181 #ifdef AFS_HPUX_ENV
1182     if (bread(pfd, (char *)&sblock, SBLOCK, SBSIZE) == -1) {
1183 #else
1184     if (bread(pfd, super.block, SBLOCK, SBSIZE) == -1) {
1185 #endif /* AFS_HPUX_ENV */
1186 #endif
1187         Log("Unable to read superblock, partition %s\n", partition);
1188         goto out;
1189     }
1190
1191     inodeFile = fopen(resultFile, "w");
1192     if (inodeFile == NULL) {
1193         Log("Unable to create inode description file %s\n", resultFile);
1194         goto out;
1195     }
1196 #ifdef  AFS_AIX_ENV
1197     /*
1198      * char *FSlabel(), *fslabel=0;
1199      * fslabel = FSlabel(&super.fs);
1200      */
1201     if (super.fs.s_bsize == 0)
1202         super.fs.s_bsize = 512;
1203     if (super.fs.s_bsize != BSIZE) {
1204         Log("SuperBlk: Cluster size not %d; run vfsck\n", BSIZE);
1205         goto out;
1206     }
1207     fmax = super.fs.s_fsize;    /* first invalid blk num */
1208     imax = ((ino_t) super.fs.s_isize - (SUPERB + 1)) * INOPB;
1209     if (imax == 0) {
1210         Log("Size check: imax==0!\n");
1211         goto out;
1212     }
1213     if (GetAuxInodeFile(partition, &status) == 0) {
1214         Log("Can't access Aux inode file for partition %s, aborting\n",
1215             partition);
1216         goto out;
1217     }
1218     for (inum = 1; inum <= imax; inum++) {
1219         struct dauxinode *auxp;
1220         if ((auxp = IsAfsInode(inum)) == NULL) {
1221             /* Not an afs inode, keep going */
1222             continue;
1223         }
1224         if ((p = ginode(inum)) == NULL)
1225             continue;
1226         /* deleted/non-existent inode when di_mode == 0 */
1227         if (!p->di_mode)
1228             continue;
1229         info.inodeNumber = (int)inum;
1230         info.byteCount = p->di_size;
1231         info.linkCount = p->di_nlink;
1232         info.u.param[0] = auxp->aux_param1;
1233         info.u.param[1] = auxp->aux_param2;
1234         info.u.param[2] = auxp->aux_param3;
1235         info.u.param[3] = auxp->aux_param4;
1236         if (judgeInode && (*judgeInode) (&info, judgeParam, rock) == 0)
1237             continue;
1238         if (fwrite(&info, sizeof info, 1, inodeFile) != 1) {
1239             Log("Error writing inode file for partition %s\n", partition);
1240             goto out;
1241         }
1242         ninodes++;
1243     }
1244 #else
1245     /*
1246      * run a few consistency checks of the superblock
1247      * (Cribbed from vfsck)
1248      */
1249 #ifdef AFS_HPUX_ENV
1250 #if defined(FD_FSMAGIC)
1251     if ((sblock.fs_magic != FS_MAGIC) && (sblock.fs_magic != FS_MAGIC_LFN)
1252         && (sblock.fs_magic != FD_FSMAGIC)
1253 #if     defined(AFS_HPUX101_ENV)
1254         && (sblock.fs_magic != FD_FSMAGIC_2)
1255 #endif
1256         ) {
1257 #else
1258     if ((sblock.fs_magic != FS_MAGIC) && (sblock.fs_magic != FS_MAGIC_LFN)) {
1259 #endif
1260         Log("There's something wrong with the superblock for partition %s; bad magic (%d) run vfsck\n", partition, sblock.fs_magic);
1261         goto out;
1262     }
1263     if (sblock.fs_ncg < 1) {
1264         Log("There's something wrong with the superblock for partition %s; NCG OUT OF RANGE (%d) run vfsck\n", partition, sblock.fs_ncg);
1265         goto out;
1266     }
1267     if (sblock.fs_cpg < 1 || sblock.fs_cpg > MAXCPG) {
1268         Log("There's something wrong with the superblock for partition %s; CPG OUT OF RANGE (%d) run vfsck\n", partition, sblock.fs_cpg);
1269         goto out;
1270     }
1271     if (sblock.fs_ncg * sblock.fs_cpg < sblock.fs_ncyl
1272         || (sblock.fs_ncg - 1) * sblock.fs_cpg >= sblock.fs_ncyl) {
1273         Log("There's something wrong with the superblock for partition %s; NCYL LESS THAN NCG*CPG run vfsck\n", partition);
1274         goto out;
1275     }
1276     if (sblock.fs_sbsize > SBSIZE) {
1277         Log("There's something wrong with the superblock for partition %s; bsize too large (%d vs. %d) run vfsck\n", partition, sblock.fs_sbsize, sblock.fs_bsize);
1278         goto out;
1279     }
1280 #else
1281     if ((super.fs.fs_magic != FS_MAGIC)
1282         || (super.fs.fs_ncg < 1)
1283 #if     defined(AFS_SUN_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
1284         || (super.fs.fs_cpg < 1)
1285 #else
1286         || (super.fs.fs_cpg < 1 || super.fs.fs_cpg > MAXCPG)
1287 #endif
1288         || (super.fs.fs_ncg * super.fs.fs_cpg < super.fs.fs_ncyl
1289             || (super.fs.fs_ncg - 1) * super.fs.fs_cpg >= super.fs.fs_ncyl)
1290         || (super.fs.fs_sbsize > SBSIZE)) {
1291         Log("There's something wrong with the superblock for partition %s; run vfsck\n", partition);
1292         goto out;
1293     }
1294 #endif /* AFS_HPUX_ENV */
1295
1296 #ifdef AFS_HPUX_ENV
1297     bufsize = sblock.fs_ipg * sizeof(struct dinode);
1298 #else
1299     bufsize = super.fs.fs_ipg * sizeof(struct dinode);
1300 #endif /* AFS_HPUX_ENV */
1301     inodes = (struct dinode *)malloc(bufsize);
1302     einodes = (struct dinode *)(((char *)inodes) + bufsize);
1303     if (inodes == NULL) {
1304         Log("Unable to allocate enough memory to scan inodes; help!\n");
1305         goto out;
1306     }
1307     Log("Scanning inodes on device %s...\n", rdev);
1308 #ifdef AFS_HPUX_ENV
1309     for (c = 0; c < sblock.fs_ncg; c++) {
1310         i = c * sblock.fs_ipg;
1311         e = i + sblock.fs_ipg;
1312 #if     defined(AFS_HPUX102_ENV)
1313         if (afs_lseek(pfd, dbtoo(fsbtodb(&sblock, itod(&sblock, i))), L_SET) ==
1314             -1) {
1315 #else
1316         if (afs_lseek(pfd, dbtob(fsbtodb(&sblock, itod(&sblock, i))), L_SET) ==
1317             -1) {
1318 #endif
1319 #else
1320     for (c = 0; c < super.fs.fs_ncg; c++) {
1321         daddr_t dblk1;
1322 #if defined(AFS_SUN5_ENV) || defined(AFS_DARWIN_ENV)
1323         daddr_t f1;
1324 #if defined(AFS_DARWIN_ENV)
1325 #define offset_t off_t
1326 #define llseek lseek
1327 #endif
1328         offset_t off;
1329 #endif /* AFS_SUN5_ENV */
1330         i = c * super.fs.fs_ipg;
1331         e = i + super.fs.fs_ipg;
1332 #ifdef  AFS_OSF_ENV
1333         dblk1 = fsbtodb(&super.fs, itod(&super.fs, i));
1334         if (afs_lseek(pfd, (off_t) ((off_t) dblk1 * DEV_BSIZE), L_SET) == -1) {
1335 #else
1336 #if defined(AFS_SUN5_ENV) || defined(AFS_DARWIN_ENV)
1337         f1 = fsbtodb(&super.fs, itod(&super.fs, i));
1338         off = (offset_t) f1 << DEV_BSHIFT;
1339         if (llseek(pfd, off, L_SET) == -1) {
1340 #else
1341         if (afs_lseek(pfd, dbtob(fsbtodb(&super.fs, itod(&super.fs, i))), L_SET)
1342             == -1) {
1343 #endif /* AFS_SUN5_ENV */
1344 #endif /* AFS_OSF_ENV */
1345 #endif /* AFS_HPUX_ENV */
1346             Log("Error reading inodes for partition %s; run vfsck\n",
1347                 partition);
1348             goto out;
1349         }
1350         while (i < e) {
1351             if (!forceR) {
1352                 if (read(pfd, inodes, bufsize) != bufsize) {
1353                     Log("Error reading inodes for partition %s; run vfsck\n",
1354                         partition);
1355                     goto out;
1356                 }
1357             } else {
1358                 register int bj, bk;
1359                 dptr = inodes;
1360                 for (bj = bk = 0; bj < bufsize; bj = bj + 512, bk++) {
1361                     if ((code = read(pfd, dptr, 512)) != 512) {
1362                         Log("Error reading inode %d? for partition %s (errno = %d); run vfsck\n", bk + i, partition, errno);
1363                         if (afs_lseek(pfd, 512, L_SET) == -1) {
1364                             Log("Lseek failed\n");
1365                             goto out;
1366                         }
1367                         dptr->di_mode = 0;
1368                         dptr++;
1369                         dptr->di_mode = 0;
1370                         dptr++;
1371                         dptr->di_mode = 0;
1372                         dptr++;
1373                         dptr->di_mode = 0;
1374                         dptr++;
1375                     } else
1376                         dptr += 4;
1377                 }
1378             }
1379             for (p = inodes; p < einodes && i < e; i++, p++) {
1380 #ifdef notdef
1381                 Log("Ino=%d, v1=%x, v2=%x, v3=%x, mode=%x size=%d, lcnt=%d\n",
1382                     i, p->di_vicep1, p->di_vicep2, p->di_vicep3, p->di_mode,
1383                     p->di_size, p->di_nlink);
1384                 printf
1385                     ("Ino=%d, v1=%x, v2=%x, v3=%x, mode=%x size=%d, lcnt=%d\n",
1386                      i, p->di_vicep1, p->di_vicep2, p->di_vicep3, p->di_mode,
1387                      p->di_size, p->di_nlink);
1388 #endif
1389 #ifdef AFS_OSF_ENV
1390 #ifdef AFS_3DISPARES
1391                 /* Check to see if this inode is a pre-"OSF1 4.0D" inode */
1392                 if ((p->di_uid || p->di_gid)
1393                     && !(p->di_flags & (IC_XUID | IC_XGID))) {
1394                     Log("Found unconverted inode %d: Use 'fs_conv_dux40D convert' on partition %s\n", i, partition);
1395                     goto out;
1396                 }
1397 #else
1398                 assert(0);      /* define AFS_3DISPARES in param.h */
1399 #endif
1400 #endif
1401 #if     defined(AFS_SUN56_ENV)
1402                 /* if this is a pre-sol2.6 unconverted inode, bail out */
1403                 {
1404                     afs_uint32 p1, p2, p3, p4;
1405                     int p5;
1406                     quad *q;
1407
1408                     q = (quad *) & (p->di_ic.ic_lsize);
1409                     p1 = p->di_gen;
1410                     p2 = p->di_ic.ic_flags;
1411                     p3 = q->val[0];
1412                     p4 = p->di_ic.ic_uid;
1413                     p5 = p->di_ic.ic_gid;
1414
1415                     if ((p2 || p3) && !p4 && (p5 == -2)) {
1416                         Log("Found unconverted inode %d\n", i);
1417                         Log("You should run the AFS file conversion utility\n");
1418                         goto out;
1419                     }
1420                 }
1421 #endif
1422                 if (IS_DVICEMAGIC(p) && (p->di_mode & IFMT) == IFREG) {
1423                     afs_uint32 p2 = p->di_vicep2, p3 = DI_VICEP3(p);
1424
1425                     info.u.param[0] = p->di_vicep1;
1426 #ifdef  AFS_3DISPARES
1427                     if (((p2 >> 3) == INODESPECIAL) && (p2 & 0x3)) {
1428                         info.u.param[1] = INODESPECIAL;
1429                         info.u.param[2] = p3;
1430                         info.u.param[3] = p2 & 0x3;
1431                     } else {
1432                         info.u.param[1] = ((p2 >> 27) << 16) + (p3 & 0xffff);
1433                         info.u.param[2] = (p2 & 0x3fffff);
1434                         info.u.param[3] =
1435                             (((p2 >> 22) & 0x1f) << 16) + (p3 >> 16);
1436                     }
1437 #else
1438                     info.u.param[1] = p->di_vicep2;
1439                     info.u.param[2] = DI_VICEP3(p);
1440                     info.u.param[3] = p->di_vicep4;
1441 #endif
1442                     info.inodeNumber = i;
1443                     info.byteCount = p->di_size;
1444                     info.linkCount = p->di_nlink;
1445                     if (judgeInode && (*judgeInode) (&info, judgeParam, rock) == 0)
1446                         continue;
1447                     if (fwrite(&info, sizeof info, 1, inodeFile) != 1) {
1448                         Log("Error writing inode file for partition %s\n",
1449                             partition);
1450                         goto out;
1451                     }
1452                     ninodes++;
1453                 }
1454             }
1455         }
1456     }
1457     if (inodes)
1458         free(inodes);
1459 #endif
1460     if (fflush(inodeFile) == EOF) {
1461         Log("Unable to successfully flush inode file for %s\n", partition);
1462         err = -2;
1463         goto out1;
1464     }
1465     if (fsync(fileno(inodeFile)) == -1) {
1466         Log("Unable to successfully fsync inode file for %s\n", partition);
1467         err = -2;
1468         goto out1;
1469     }
1470     if (fclose(inodeFile) == EOF) {
1471         Log("Unable to successfully close inode file for %s\n", partition);
1472         err = -2;
1473         goto out1;
1474     }
1475
1476     /*
1477      * Paranoia:  check that the file is really the right size
1478      */
1479     if (stat(resultFile, &status) == -1) {
1480         Log("Unable to successfully stat inode file for %s\n", partition);
1481         err = -2;
1482         goto out1;
1483     }
1484     if (status.st_size != ninodes * sizeof(struct ViceInodeInfo)) {
1485         Log("Wrong size (%d instead of %d) in inode file for %s\n",
1486             status.st_size, ninodes * sizeof(struct ViceInodeInfo),
1487             partition);
1488         err = -2;
1489         goto out1;
1490     }
1491     close(pfd);
1492     return 0;
1493
1494   out:
1495     err = -1;
1496   out1:
1497     close(pfd);
1498     if (inodeFile)
1499         fclose(inodeFile);
1500     if (inodes)
1501         free(inodes);
1502     return err;
1503 }
1504 #endif /* !AFS_SGI_ENV */
1505 #endif /* !AFS_AIX31_ENV       */
1506
1507 #ifdef AFS_DARWIN_ENV
1508 #undef dbtob
1509 #define dbtob(db) ((unsigned)(db) << DEV_BSHIFT)
1510 #endif
1511
1512 int
1513 bread(int fd, char *buf, daddr_t blk, afs_int32 size)
1514 {
1515 #ifdef  AFS_AIX_ENV
1516 #ifdef  AFS_AIX41_ENV
1517     offset_t off = (offset_t) blk << FSBSHIFT;
1518     if (llseek(fd, off, 0) < 0) {
1519         Log("Unable to seek to offset %llu for block %u\n", off, blk);
1520         return -1;
1521     }
1522 #else /* AFS_AIX41_ENV */
1523     if (afs_lseek(fd, blk * Bsize, 0) < 0) {
1524         Log("Unable to seek to offset %u for block %u\n", blk * Bsize, blk);
1525     }
1526 #endif /* AFS_AIX41_ENV */
1527 #else
1528     if (afs_lseek(fd, (off_t) dbtob(blk), L_SET) < 0) {
1529         Log("Unable to seek to offset %u for block %u\n", dbtob(blk), blk);
1530     }
1531 #endif
1532     if (read(fd, buf, size) != size) {
1533         Log("Unable to read block %d, partition %s\n", blk, partition);
1534         return -1;
1535     }
1536     return 0;
1537 }
1538
1539 #endif /* AFS_LINUX20_ENV */
1540 #endif /* AFS_NAMEI_ENV */