~ubuntu-branches/ubuntu/warty/openafs/warty

« back to all changes in this revision

Viewing changes to src/vol/listinodes.c

  • Committer: Bazaar Package Importer
  • Author(s): Sam Hartman
  • Date: 2004-01-10 16:37:33 UTC
  • Revision ID: james.westby@ubuntu.com-20040110163733-jvr0n1uahshlb1uu
Tags: upstream-1.2.11
ImportĀ upstreamĀ versionĀ 1.2.11

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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: /afs/sipb.mit.edu/project/openafs/debian/cvs/openafs/src/vol/listinodes.c,v 1.1.1.10 2002/09/26 19:09:23 hartmans Exp $");
 
24
 
 
25
#ifndef AFS_NAMEI_ENV
 
26
#if defined(AFS_LINUX20_ENV) || defined(AFS_SUN4_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 this platform!\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_XBSD_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_XBSD_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 */