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