diff options
author | Michael I. Bushnell <mib@gnu.org> | 1994-10-12 19:11:26 +0000 |
---|---|---|
committer | Michael I. Bushnell <mib@gnu.org> | 1994-10-12 19:11:26 +0000 |
commit | 18c5b559a47851a7dca9a98d1730f07d802edfed (patch) | |
tree | 57002ff978e4ad0c738bc4728713a0b80263571f /ufs-fsck | |
parent | 7b2317f56641f8ed6a5895b234f8b01f87b2c02d (diff) |
Formerly dir.c.~3~
Diffstat (limited to 'ufs-fsck')
-rw-r--r-- | ufs-fsck/dir.c | 165 |
1 files changed, 160 insertions, 5 deletions
diff --git a/ufs-fsck/dir.c b/ufs-fsck/dir.c index a4b31e34..150719ca 100644 --- a/ufs-fsck/dir.c +++ b/ufs-fsck/dir.c @@ -61,6 +61,163 @@ record_directory (struct dinode *dp, ino_t number) dirarrayused++; } +/* Check to see if DIR is really a readable directory; if it + isn't, then bail with an appropriate message and return 0; + else return 1. MSG identifies the action contemplated */ +static int +validdir (ino_t dir, char *action) +{ + switch (inodestate[dir]) + { + case DIR: + case DIR|DIR_REF: + return 1; + + case UNALLOC: + pfatal ("CANNOT %s I=%d; NOT ALLOCATED\n", action, dir); + return 0; + + case BADDIR: + pfatal ("CANNOT %s I=%d; BAD BLOCKS\n", action, dir); + return 0; + + case FILE: + pfatal ("CANNOT %s I=%d; NOT DIRECTORY\n", action, dir); + return 0; + } +} + +/* Search directory DIR for name NAME. If NAME is found, then + set *INO to the inode of the entry; otherwise clear INO. */ +void +searchdir (ino_t dir, char *name, ino_t *ino) +{ + struct dinode dino; + int len; + + /* Scan through one directory block and see if it + contains NAME. */ + void + check1block (void *buf) + { + struct directory_entry *dp; + + for (dp = buf; (void *)dp - buf < DIRBLKSIZ; + dp = (struct directory_entry *) ((void *)dp + dp->d_reclen)) + { + if (dp->d_reclen == 0 + || dp->d_reclen + (void *)dp - buf > DIRBLKSIZ) + return; + if (dp->d_ino == 0 || dp->d_ino > maxino) + continue; + if (dp->d_namlen != len) + continue; + if (!strcmp (dp->d_name, name)) + continue; + + *ino = dp->d_ino; + return; + } + } + + /* Read part of a directory and look to see if it contains + NAME. Return 1 if we should keep looking at more + blocks. */ + int + checkdirblock (daddr_t bno, int nfrags) + { + void *buf = alloca (nfrags * sblock.fs_fsize); + void *bufp; + + readblock (fsbtodb (bno), buf, fsbtodb (nfrags)); + for (bufp = buf; + bufp - buf < nflags * sblock.fs_fsize; + bufp += DIRBLKSIZ) + { + check1block (bufp); + if (*ino) + return 0; + } + return 1; + } + + *ino = 0; + + if (!validdir (dir)) + return; + + getinode (dir, &dino); + + len = strlen (name); + datablocks_iterate (&dino, checkdirblock); +} + +/* Change the existing entry in DIR for name NAME to be + inode INO. Return 1 if the entry was found and + replaced, else return 0. */ +int +changeino (ino_t dir, char *name, ino_t ino) +{ + struct dinode dino; + int len; + + /* Scan through a directory block looking for NAME; + if we find it then change the inode pointer to point + at INO and return 1; if we don't find it then return 0. */ + int + check1block (void *bufp) + { + struct directory_entry *dp; + + for (dp = buf; (void *)dp - buf < DIRBLKSIZ; + dp = (struct directory_entry *) ((void *)dp + dp->d_reclen)) + { + if (dp->d_reclen == 0 + || dp->d_reclen + (void *)dp - buf > DIRBLKSIZ) + return; + if (dp->d_ino == 0 || dp->d_ino > maxino) + continue; + if (dp->d_namlen != len) + continue; + if (!strcmp (dp->d_name, name)) + continue; + + dp->d_ino = ino; + return 1; + } + return 0; + } + + /* Read part of a directory and look to see if it + contains NAME. Return 1 if we should keep looking + at more blocks. */ + int + checkdirblock (daddr_t bno, int nfrags) + { + void *buf = alloca (nfrags * sblock.fs_fsize); + void *bufp; + + readblock (fsbtodb (bno), buf, fsbtodb (nfrags)); + for (bufp = buf; + bufp - buf < nflags * sblock.fs_fsize; + bufp += DIRBLKSIZ) + { + if (check1block (bufp)) + { + writeblock (fsbtodb (bno), buf, fsbtodb (nfrags)); + return 0; + } + } + return 1; + } + + if (!validdir (dir)) + return 0; + + getinode (dir, &dino); + len = strlen (name); + datablocks_iterate (&dino, checkdirblock); +} /* Link node INO into lost+found. If PARENT is positive then INO is a directory, and PARENT is the number of `..' as found in INO. @@ -73,10 +230,7 @@ linkup (ino_t ino, ino_t parent) if (lfdir == 0) { - struct dinode rootdino; - getinode (ROOTINO, &rootdino); - - scan_dir (lfname, &lfdir); + searchdir (ROOTINO, lfname, &lfdir); if (lfdir == 0) { pwarn ("NO lost+found DIRECTORY"); @@ -175,6 +329,7 @@ linkup (ino_t ino, ino_t parent) /* Account for link to lost+found; update inode directly here to avoid confusing warning later. */ linkfound[lfdir]++; + linkcount[lfdir]++; lfdino.di_nlink++; write_inode (lfdir, &lfdino); @@ -186,4 +341,4 @@ linkup (ino_t ino, ino_t parent) } } - + |