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