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