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