2
* Copyright (c) 1980, 1986 The Regents of the University of California.
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.
18
#include <afsconfig.h>
19
#include <afs/param.h>
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 $");
25
#include <sys/param.h>
27
#include <sys/vnode.h>
28
#include <sys/mount.h>
29
#include <ufs/inode.h>
37
#else /* AFS_OSF_ENV */
38
#ifdef AFS_VFSINCL_ENV
39
#include <sys/vnode.h>
43
#include <sys/fs/ufs_inode.h>
44
#include <sys/fs/ufs_fs.h>
46
#include <sys/fs/ufs_fsdir.h>
48
#include <sys/fs/ufs_mount.h>
50
#include <ufs/inode.h>
52
#include <ufs/fsdir.h>
54
#else /* AFS_VFSINCL_ENV */
55
#include <sys/inode.h>
58
#define LONGFILENAMES 1
59
#include <sys/sysmacros.h>
68
#endif /* AFS_VFSINCL_ENV */
69
#endif /* AFS_OSF_ENV */
70
#include <afs/osi_inode.h>
83
register struct dinode *dp;
84
struct inodesc rootdesc;
86
memset((char *)&rootdesc, 0, sizeof(struct inodesc));
87
rootdesc.id_type = ADDR;
88
rootdesc.id_func = pass2check;
89
rootdesc.id_number = ROOTINO;
91
#if defined(ACLS) && defined(AFS_HPUX_ENV)
92
switch (statemap[ROOTINO] & STATE) {
94
switch (statemap[ROOTINO]) {
98
pfatal("ROOT INODE UNALLOCATED");
99
if (reply("ALLOCATE") == 0)
101
if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO)
102
errexit("CANNOT ALLOCATE ROOT INODE\n");
103
descend(&rootdesc, ROOTINO);
107
pfatal("DUPS/BAD IN ROOT INODE");
108
if (reply("REALLOCATE")) {
110
if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO)
111
errexit("CANNOT ALLOCATE ROOT INODE\n");
112
descend(&rootdesc, ROOTINO);
115
if (reply("CONTINUE") == 0)
117
statemap[ROOTINO] = DSTATE;
118
descend(&rootdesc, ROOTINO);
126
pfatal("ROOT INODE NOT DIRECTORY");
127
if (reply("REALLOCATE")) {
129
if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO)
130
errexit("CANNOT ALLOCATE ROOT INODE\n");
131
descend(&rootdesc, ROOTINO);
134
if (reply("FIX") == 0)
136
dp = ginode(ROOTINO);
137
dp->di_mode &= ~IFMT;
138
dp->di_mode |= IFDIR;
140
dp->di_smode = dp->di_mode;
143
#if defined(ACLS) && defined(AFS_HPUX_ENV)
145
* Keep any info on associated continuation inode
147
if (statemap[ROOTINO] & HASCINODE)
148
statemap[ROOTINO] = DSTATE|HASCINODE;
150
statemap[ROOTINO] = DSTATE;
152
statemap[ROOTINO] = DSTATE;
157
descend(&rootdesc, ROOTINO);
161
errexit("BAD STATE %d FOR ROOT INODE", statemap[ROOTINO]);
166
struct inodesc *idesc;
168
register struct direct *dirp = idesc->id_dirp;
170
int n, entrysize, ret = 0;
173
char namebuf[BUFSIZ];
174
#if defined(ACLS) && defined(AFS_HPUX_ENV)
181
if (idesc->id_entryno != 0)
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)
192
direrror(idesc->id_number, "MISSING '.'");
193
proto.d_ino = idesc->id_number;
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",
200
#if defined(AFS_SUN_ENV) || defined(AFS_DEC_ENV)
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)
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)
214
n = dirp->d_reclen - entrysize;
215
proto.d_reclen = entrysize;
216
memcpy((char *)dirp, (char *)&proto, entrysize);
218
lncntp[dirp->d_ino]--;
219
dirp = (struct direct *)((char *)(dirp) + entrysize);
220
memset((char *)dirp, 0, n);
222
if (reply("FIX") == 1)
226
if (idesc->id_entryno > 1)
228
proto.d_ino = idesc->id_parent;
230
(void)strcpy(proto.d_name, "..");
231
entrysize = DIRSIZ(&proto);
232
if (idesc->id_entryno == 0) {
234
if (dirp->d_reclen < n + entrysize)
236
proto.d_reclen = dirp->d_reclen - n;
239
lncntp[dirp->d_ino]--;
240
dirp = (struct direct *)((char *)(dirp) + n);
241
memset((char *)dirp, 0, n);
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)
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",
257
#if defined(AFS_SUN_ENV) || defined(AFS_DEC_ENV)
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)
266
proto.d_reclen = dirp->d_reclen;
267
memcpy((char *)dirp, (char *)&proto, entrysize);
268
if (reply("FIX") == 1)
272
if (dirp->d_ino == 0)
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");
280
if (reply("FIX") == 1)
282
return (KEEPON | ret);
284
if (dirp->d_name[1] == '.') {
285
direrror(idesc->id_number, "EXTRA '..' ENTRY");
287
if (reply("FIX") == 1)
289
return (KEEPON | ret);
294
if (pathp + dirp->d_namlen >= endpathname) {
296
errexit("NAME TOO LONG %s%s\n", pathname, dirp->d_name);
298
memcpy(pathp, dirp->d_name, (int)dirp->d_namlen + 1);
299
pathp += dirp->d_namlen;
302
if (dirp->d_ino > maxino || dirp->d_ino <= 0) {
303
direrror(dirp->d_ino, "I OUT OF RANGE");
307
#if defined(ACLS) && defined(AFS_HPUX_ENV)
308
switch (statemap[dirp->d_ino] & STATE) {
310
switch (statemap[dirp->d_ino]) {
313
direrror(dirp->d_ino, "UNALLOCATED");
319
direrror(dirp->d_ino, "DUP/BAD");
320
if ((n = reply("REMOVE")) == 1)
322
dp = ginode(dirp->d_ino);
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;
329
statemap[dirp->d_ino] = holdstate;
331
statemap[dirp->d_ino] = (dp->di_mode & IFMT) == IFDIR ? DSTATE : (VICEINODE? VSTATE: FSTATE);
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;
339
statemap[dirp->d_ino] = holdstate;
341
statemap[dirp->d_ino] = (dp->di_mode & IFMT) == IFDIR ? DSTATE : FSTATE;
344
lncntp[dirp->d_ino] = dp->di_nlink;
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",
354
printf(" (IGNORED)\n");
355
else if ((n = reply("REMOVE")) == 1)
364
lncntp[dirp->d_ino]--;
369
direrror(dirp->d_ino, "VICE INODE REFERENCED BY DIRECTORY");
370
if (reply("CONVERT TO REGULAR FILE") != 1)
372
if ((dp = ginode(dirp->d_ino)) == NULL)
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;
377
CLEAR_DVICEMAGIC(dp);
380
statemap[dirp->d_ino] = FSTATE;
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) {
394
errexit("BAD RETURN STATE %d FROM DESCEND",
395
statemap[dirp->d_ino]);
398
#if defined(ACLS) && defined(AFS_HPUX_ENV)
399
/* hpux has more dynamic states (CSTATE, CRSTATE) */
406
errexit("BAD STATE %d FOR INODE I=%d",
407
statemap[dirp->d_ino], dirp->d_ino);
415
return (ret|KEEPON|ALTERED);