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

« back to all changes in this revision

Viewing changes to src/vfsck/pass2.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 (c) 1980, 1986 The Regents of the University of California.
 
3
 * All rights reserved.
 
4
 *
 
5
 * Redistribution and use in source and binary forms are permitted
 
6
 * provided that the above copyright notice and this paragraph are
 
7
 * duplicated in all such forms and that any documentation,
 
8
 * advertising materials, and other materials related to such
 
9
 * distribution and use acknowledge that the software was developed
 
10
 * by the University of California, Berkeley.  The name of the
 
11
 * University may not be used to endorse or promote products derived
 
12
 * from this software without specific prior written permission.
 
13
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 
14
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 
15
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
16
 */
 
17
 
 
18
#include <afsconfig.h>
 
19
#include <afs/param.h>
 
20
 
 
21
RCSID("$Header: /afs/sipb.mit.edu/project/openafs/debian/cvs/openafs/src/vfsck/pass2.c,v 1.1.1.4 2001/09/11 14:35:30 hartmans Exp $");
 
22
 
 
23
#define VICE
 
24
#include <sys/time.h>
 
25
#include <sys/param.h>
 
26
#ifdef  AFS_OSF_ENV
 
27
#include <sys/vnode.h>
 
28
#include <sys/mount.h>
 
29
#include <ufs/inode.h>
 
30
#include <ufs/fs.h>
 
31
#define _BSD
 
32
#define _KERNEL
 
33
#include <ufs/dir.h>
 
34
#undef  _KERNEL
 
35
#undef  _BSD
 
36
#include <stdio.h>
 
37
#else   /* AFS_OSF_ENV */
 
38
#ifdef AFS_VFSINCL_ENV
 
39
#include <sys/vnode.h>
 
40
#ifdef    AFS_SUN5_ENV
 
41
#include <stdio.h>
 
42
#include <unistd.h>
 
43
#include <sys/fs/ufs_inode.h>
 
44
#include <sys/fs/ufs_fs.h>
 
45
#define _KERNEL
 
46
#include <sys/fs/ufs_fsdir.h>
 
47
#undef _KERNEL
 
48
#include <sys/fs/ufs_mount.h>
 
49
#else
 
50
#include <ufs/inode.h>
 
51
#include <ufs/fs.h>
 
52
#include <ufs/fsdir.h>
 
53
#endif
 
54
#else /* AFS_VFSINCL_ENV */
 
55
#include <sys/inode.h>
 
56
#ifdef  AFS_HPUX_ENV
 
57
#include <ctype.h>
 
58
#define LONGFILENAMES   1
 
59
#include <sys/sysmacros.h>
 
60
#include <sys/ino.h>
 
61
#define DIRSIZ_MACRO
 
62
#include <ndir.h>
 
63
#else
 
64
#include <sys/dir.h>
 
65
#endif
 
66
#include <sys/fs.h>
 
67
 
 
68
#endif /* AFS_VFSINCL_ENV */
 
69
#endif  /* AFS_OSF_ENV */
 
70
#include <afs/osi_inode.h>
 
71
 
 
72
#ifdef  AFS_SUN5_ENV
 
73
#include <string.h>
 
74
#else
 
75
#include <strings.h>
 
76
#endif
 
77
#include "fsck.h"
 
78
 
 
79
int     pass2check();
 
80
 
 
81
pass2()
 
82
{
 
83
        register struct dinode *dp;
 
84
        struct inodesc rootdesc;
 
85
 
 
86
        memset((char *)&rootdesc, 0, sizeof(struct inodesc));
 
87
        rootdesc.id_type = ADDR;
 
88
        rootdesc.id_func = pass2check;
 
89
        rootdesc.id_number = ROOTINO;
 
90
        pathp = pathname;
 
91
#if defined(ACLS) && defined(AFS_HPUX_ENV)
 
92
        switch (statemap[ROOTINO] & STATE) {
 
93
#else /* no ACLS */
 
94
        switch (statemap[ROOTINO]) {
 
95
#endif /* ACLS */
 
96
 
 
97
        case USTATE:
 
98
                pfatal("ROOT INODE UNALLOCATED");
 
99
                if (reply("ALLOCATE") == 0)
 
100
                        errexit("");
 
101
                if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO)
 
102
                        errexit("CANNOT ALLOCATE ROOT INODE\n");
 
103
                descend(&rootdesc, ROOTINO);
 
104
                break;
 
105
 
 
106
        case DCLEAR:
 
107
                pfatal("DUPS/BAD IN ROOT INODE");
 
108
                if (reply("REALLOCATE")) {
 
109
                        freeino(ROOTINO);
 
110
                        if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO)
 
111
                                errexit("CANNOT ALLOCATE ROOT INODE\n");
 
112
                        descend(&rootdesc, ROOTINO);
 
113
                        break;
 
114
                }
 
115
                if (reply("CONTINUE") == 0)
 
116
                        errexit("");
 
117
                statemap[ROOTINO] = DSTATE;
 
118
                descend(&rootdesc, ROOTINO);
 
119
                break;
 
120
 
 
121
#ifdef VICE     
 
122
        case VSTATE:
 
123
#endif /* VICE */
 
124
        case FSTATE:
 
125
        case FCLEAR:
 
126
                pfatal("ROOT INODE NOT DIRECTORY");
 
127
                if (reply("REALLOCATE")) {
 
128
                        freeino(ROOTINO);
 
129
                        if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO)
 
130
                                errexit("CANNOT ALLOCATE ROOT INODE\n");
 
131
                        descend(&rootdesc, ROOTINO);
 
132
                        break;
 
133
                }
 
134
                if (reply("FIX") == 0)
 
135
                        errexit("");
 
136
                dp = ginode(ROOTINO);
 
137
                dp->di_mode &= ~IFMT;
 
138
                dp->di_mode |= IFDIR;
 
139
#ifdef  AFS_SUN5_ENV
 
140
                dp->di_smode = dp->di_mode;
 
141
#endif
 
142
                inodirty();
 
143
#if defined(ACLS) && defined(AFS_HPUX_ENV)
 
144
                /*
 
145
                 * Keep any info on associated continuation inode
 
146
                 */
 
147
                if (statemap[ROOTINO] & HASCINODE)
 
148
                    statemap[ROOTINO] = DSTATE|HASCINODE;
 
149
                else
 
150
                    statemap[ROOTINO] = DSTATE;
 
151
#else /* no ACLS */
 
152
                statemap[ROOTINO] = DSTATE;
 
153
#endif /* ACLS */
 
154
                /* fall into ... */
 
155
 
 
156
        case DSTATE:
 
157
                descend(&rootdesc, ROOTINO);
 
158
                break;
 
159
 
 
160
        default:
 
161
                errexit("BAD STATE %d FOR ROOT INODE", statemap[ROOTINO]);
 
162
        }
 
163
}
 
164
 
 
165
pass2check(idesc)
 
166
        struct inodesc *idesc;
 
167
{
 
168
        register struct direct *dirp = idesc->id_dirp;
 
169
        char *curpathloc;
 
170
        int n, entrysize, ret = 0;
 
171
        struct dinode *dp;
 
172
        struct direct proto;
 
173
        char namebuf[BUFSIZ];
 
174
#if defined(ACLS) && defined(AFS_HPUX_ENV)
 
175
        int holdstate;
 
176
#endif /* ACLS */
 
177
 
 
178
        /* 
 
179
         * check for "."
 
180
         */
 
181
        if (idesc->id_entryno != 0)
 
182
                goto chk1;
 
183
        if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") == 0) {
 
184
                if (dirp->d_ino != idesc->id_number) {
 
185
                        direrror(idesc->id_number, "BAD INODE NUMBER FOR '.'");
 
186
                        dirp->d_ino = idesc->id_number;
 
187
                        if (reply("FIX") == 1)
 
188
                                ret |= ALTERED;
 
189
                }
 
190
                goto chk1;
 
191
        }
 
192
        direrror(idesc->id_number, "MISSING '.'");
 
193
        proto.d_ino = idesc->id_number;
 
194
        proto.d_namlen = 1;
 
195
        (void)strcpy(proto.d_name, ".");
 
196
        entrysize = DIRSIZ(&proto);
 
197
        if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") != 0) {
 
198
                pfatal("CANNOT FIX, FIRST ENTRY IN DIRECTORY CONTAINS %s\n",
 
199
                        dirp->d_name);
 
200
#if     defined(AFS_SUN_ENV) || defined(AFS_DEC_ENV)
 
201
                iscorrupt = 1;          
 
202
#endif
 
203
        } else if (dirp->d_reclen < entrysize) {
 
204
                pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '.'\n");
 
205
#if     defined(AFS_SUN_ENV) || defined(AFS_DEC_ENV)
 
206
                iscorrupt = 1;          
 
207
#endif
 
208
        } else if (dirp->d_reclen < 2 * entrysize) {
 
209
                proto.d_reclen = dirp->d_reclen;
 
210
                memcpy((char *)dirp, (char *)&proto, entrysize);
 
211
                if (reply("FIX") == 1)
 
212
                        ret |= ALTERED;
 
213
        } else {
 
214
                n = dirp->d_reclen - entrysize;
 
215
                proto.d_reclen = entrysize;
 
216
                memcpy((char *)dirp, (char *)&proto, entrysize);
 
217
                idesc->id_entryno++;
 
218
                lncntp[dirp->d_ino]--;
 
219
                dirp = (struct direct *)((char *)(dirp) + entrysize);
 
220
                memset((char *)dirp, 0, n);
 
221
                dirp->d_reclen = n;
 
222
                if (reply("FIX") == 1)
 
223
                        ret |= ALTERED;
 
224
        }
 
225
chk1:
 
226
        if (idesc->id_entryno > 1)
 
227
                goto chk2;
 
228
        proto.d_ino = idesc->id_parent;
 
229
        proto.d_namlen = 2;
 
230
        (void)strcpy(proto.d_name, "..");
 
231
        entrysize = DIRSIZ(&proto);
 
232
        if (idesc->id_entryno == 0) {
 
233
                n = DIRSIZ(dirp);
 
234
                if (dirp->d_reclen < n + entrysize)
 
235
                        goto chk2;
 
236
                proto.d_reclen = dirp->d_reclen - n;
 
237
                dirp->d_reclen = n;
 
238
                idesc->id_entryno++;
 
239
                lncntp[dirp->d_ino]--;
 
240
                dirp = (struct direct *)((char *)(dirp) + n);
 
241
                memset((char *)dirp, 0, n);
 
242
                dirp->d_reclen = n;
 
243
        }
 
244
        if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") == 0) {
 
245
                if (dirp->d_ino != idesc->id_parent) {
 
246
                        direrror(idesc->id_number, "BAD INODE NUMBER FOR '..'");
 
247
                        dirp->d_ino = idesc->id_parent;
 
248
                        if (reply("FIX") == 1)
 
249
                                ret |= ALTERED;
 
250
                }
 
251
                goto chk2;
 
252
        }
 
253
        direrror(idesc->id_number, "MISSING '..'");
 
254
        if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") != 0) {
 
255
                pfatal("CANNOT FIX, SECOND ENTRY IN DIRECTORY CONTAINS %s\n",
 
256
                        dirp->d_name);
 
257
#if     defined(AFS_SUN_ENV) || defined(AFS_DEC_ENV)
 
258
                iscorrupt = 1;          
 
259
#endif
 
260
        } else if (dirp->d_reclen < entrysize) {
 
261
                pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '..'\n");
 
262
#if     defined(AFS_SUN_ENV) || defined(AFS_DEC_ENV)
 
263
                iscorrupt = 1;          
 
264
#endif
 
265
        } else {
 
266
                proto.d_reclen = dirp->d_reclen;
 
267
                memcpy((char *)dirp, (char *)&proto, entrysize);
 
268
                if (reply("FIX") == 1)
 
269
                        ret |= ALTERED;
 
270
        }
 
271
chk2:
 
272
        if (dirp->d_ino == 0)
 
273
                return (ret|KEEPON);
 
274
        if (dirp->d_namlen <= 2 &&
 
275
            dirp->d_name[0] == '.' &&
 
276
            idesc->id_entryno >= 2) {
 
277
                if (dirp->d_namlen == 1) {
 
278
                        direrror(idesc->id_number, "EXTRA '.' ENTRY");
 
279
                        dirp->d_ino = 0;
 
280
                        if (reply("FIX") == 1)
 
281
                                ret |= ALTERED;
 
282
                        return (KEEPON | ret);
 
283
                }
 
284
                if (dirp->d_name[1] == '.') {
 
285
                        direrror(idesc->id_number, "EXTRA '..' ENTRY");
 
286
                        dirp->d_ino = 0;
 
287
                        if (reply("FIX") == 1)
 
288
                                ret |= ALTERED;
 
289
                        return (KEEPON | ret);
 
290
                }
 
291
        }
 
292
        curpathloc = pathp;
 
293
        *pathp++ = '/';
 
294
        if (pathp + dirp->d_namlen >= endpathname) {
 
295
                *pathp = '\0';
 
296
                errexit("NAME TOO LONG %s%s\n", pathname, dirp->d_name);
 
297
        }
 
298
        memcpy(pathp, dirp->d_name, (int)dirp->d_namlen + 1);
 
299
        pathp += dirp->d_namlen;
 
300
        idesc->id_entryno++;
 
301
        n = 0;
 
302
        if (dirp->d_ino > maxino || dirp->d_ino <= 0) {
 
303
                direrror(dirp->d_ino, "I OUT OF RANGE");
 
304
                n = reply("REMOVE");
 
305
        } else {
 
306
again:
 
307
#if defined(ACLS) && defined(AFS_HPUX_ENV)
 
308
                switch (statemap[dirp->d_ino] & STATE) {
 
309
#else /* no ACLS */
 
310
                switch (statemap[dirp->d_ino]) {
 
311
#endif /* ACLS */
 
312
                case USTATE:
 
313
                        direrror(dirp->d_ino, "UNALLOCATED");
 
314
                        n = reply("REMOVE");
 
315
                        break;
 
316
 
 
317
                case DCLEAR:
 
318
                case FCLEAR:
 
319
                        direrror(dirp->d_ino, "DUP/BAD");
 
320
                        if ((n = reply("REMOVE")) == 1)
 
321
                                break;
 
322
                        dp = ginode(dirp->d_ino);
 
323
#ifdef VICE
 
324
#if defined(ACLS) && defined(AFS_HPUX_ENV)
 
325
                        holdstate = (dp->di_mode & IFMT) == IFDIR ? DSTATE : (VICEINODE? VSTATE: FSTATE);
 
326
                        if (statemap[dirp->d_ino] & HASCINODE)
 
327
                                statemap[dirp->d_ino] = holdstate|HASCINODE;
 
328
                        else
 
329
                                statemap[dirp->d_ino] = holdstate;
 
330
#else
 
331
                        statemap[dirp->d_ino] = (dp->di_mode & IFMT) == IFDIR ? DSTATE : (VICEINODE? VSTATE: FSTATE);
 
332
#endif
 
333
#else /* VICE */
 
334
#if defined(ACLS) && defined(AFS_HPUX_ENV)
 
335
                        holdstate = (dp->di_mode & IFMT) == IFDIR ? DSTATE : FSTATE;
 
336
                        if (statemap[dirp->d_ino] & HASCINODE)
 
337
                                statemap[dirp->d_ino] = holdstate|HASCINODE;
 
338
                        else
 
339
                                statemap[dirp->d_ino] = holdstate;
 
340
#else
 
341
                        statemap[dirp->d_ino] = (dp->di_mode & IFMT) == IFDIR ? DSTATE : FSTATE;
 
342
#endif
 
343
#endif /* VICE */
 
344
                        lncntp[dirp->d_ino] = dp->di_nlink;
 
345
                        goto again;
 
346
 
 
347
                case DFOUND:
 
348
                        if (idesc->id_entryno > 2) {
 
349
                                getpathname(namebuf, dirp->d_ino, dirp->d_ino);
 
350
                                pwarn("%s %s %s\n", pathname,
 
351
                                    "IS AN EXTRANEOUS HARD LINK TO DIRECTORY",
 
352
                                    namebuf);
 
353
                                if (preen)
 
354
                                        printf(" (IGNORED)\n");
 
355
                                else if ((n = reply("REMOVE")) == 1)
 
356
                                        break;
 
357
                        }
 
358
                        /* fall through */
 
359
 
 
360
                case FSTATE:
 
361
#ifdef VICE
 
362
filecase:
 
363
#endif /* VICE */
 
364
                        lncntp[dirp->d_ino]--;
 
365
                        break;
 
366
 
 
367
#ifdef VICE
 
368
                case VSTATE:
 
369
                        direrror(dirp->d_ino, "VICE INODE REFERENCED BY DIRECTORY");
 
370
                        if (reply("CONVERT TO REGULAR FILE") != 1)
 
371
                                break;
 
372
                        if ((dp = ginode(dirp->d_ino)) == NULL)
 
373
                                break;
 
374
#if     defined(AFS_SUN_ENV) && !defined(AFS_SUN56_ENV)
 
375
                        dp->di_gen = dp->di_ic.ic_flags = dp->di_ic.ic_size.val[0] = 0;
 
376
#else
 
377
                        CLEAR_DVICEMAGIC(dp);
 
378
#endif
 
379
                        inodirty();
 
380
                        statemap[dirp->d_ino] = FSTATE;
 
381
                        ret |= ALTERED;
 
382
                        goto filecase;
 
383
#endif /* VICE */
 
384
                        
 
385
 
 
386
                case DSTATE:
 
387
                        descend(idesc, dirp->d_ino);
 
388
                        if (statemap[dirp->d_ino] == DFOUND) {
 
389
                                lncntp[dirp->d_ino]--;
 
390
                        } else if (statemap[dirp->d_ino] == DCLEAR) {
 
391
                                dirp->d_ino = 0;
 
392
                                ret |= ALTERED;
 
393
                        } else
 
394
                                errexit("BAD RETURN STATE %d FROM DESCEND",
 
395
                                    statemap[dirp->d_ino]);
 
396
                        break;
 
397
 
 
398
#if defined(ACLS) && defined(AFS_HPUX_ENV)
 
399
                /* hpux has more dynamic states (CSTATE, CRSTATE) */
 
400
                case CSTATE: 
 
401
                        break;
 
402
                case CRSTATE: 
 
403
                        break;
 
404
#endif
 
405
                default:
 
406
                        errexit("BAD STATE %d FOR INODE I=%d",
 
407
                            statemap[dirp->d_ino], dirp->d_ino);
 
408
                }
 
409
        }
 
410
        pathp = curpathloc;
 
411
        *pathp = '\0';
 
412
        if (n == 0)
 
413
                return (ret|KEEPON);
 
414
        dirp->d_ino = 0;
 
415
        return (ret|KEEPON|ALTERED);
 
416
}