summaryrefslogtreecommitdiffstats
path: root/sbin/fsck_ffs/dir.c
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1997-03-11 12:20:21 +0000
committerpeter <peter@FreeBSD.org>1997-03-11 12:20:21 +0000
commitac28da2dc002612b2fd129500af8084d63aa8504 (patch)
tree8cadfc9709953ec63a6c3fe257fe499055b9f832 /sbin/fsck_ffs/dir.c
parent683ee3c015f8c8071f4de0e2cd952c8643315c98 (diff)
downloadFreeBSD-src-ac28da2dc002612b2fd129500af8084d63aa8504.zip
FreeBSD-src-ac28da2dc002612b2fd129500af8084d63aa8504.tar.gz
Merge from Lite2. Note that Lite2 has it's own filesystem clean check
skipping code that overrides ours sooner. One should be eliminated, but for now it works.
Diffstat (limited to 'sbin/fsck_ffs/dir.c')
-rw-r--r--sbin/fsck_ffs/dir.c143
1 files changed, 79 insertions, 64 deletions
diff --git a/sbin/fsck_ffs/dir.c b/sbin/fsck_ffs/dir.c
index 9a2b923..5662b6e 100644
--- a/sbin/fsck_ffs/dir.c
+++ b/sbin/fsck_ffs/dir.c
@@ -32,17 +32,20 @@
*/
#ifndef lint
-static const char sccsid[] = "@(#)dir.c 8.1 (Berkeley) 6/5/93";
+static const char sccsid[] = "@(#)dir.c 8.8 (Berkeley) 4/28/95";
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
+
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
#include <ufs/ffs/fs.h>
#include <stdio.h>
#include <stdlib.h>
+#include <err.h>
#include <string.h>
+
#include "fsck.h"
char *lfname = "lost+found";
@@ -57,15 +60,14 @@ struct odirtemplate odirhead = {
0, DIRBLKSIZ - 12, 2, ".."
};
-
-static int chgino __P((struct inodesc *idesc));
-static int dircheck __P((struct inodesc *idesc, struct direct *dp));
-static int expanddir __P((struct dinode *dp, char *name));
-static void freedir __P((ino_t ino, ino_t parent));
-static struct direct * fsck_readdir __P((struct inodesc *idesc));
-static struct bufarea * getdirblk __P((daddr_t blkno, long size));
-static int lftempname __P((char *bufp, ino_t ino));
-static int mkentry __P((struct inodesc *idesc));
+static int chgino __P((struct inodesc *));
+static int dircheck __P((struct inodesc *, struct direct *));
+static int expanddir __P((struct dinode *dp, char *name));
+static void freedir __P((ino_t ino, ino_t parent));
+static struct direct *fsck_readdir __P((struct inodesc *));
+static struct bufarea *getdirblk __P((ufs_daddr_t blkno, long size));
+static int lftempname __P((char *bufp, ino_t ino));
+static int mkentry __P((struct inodesc *));
/*
* Propagate connected state through the tree.
@@ -107,7 +109,7 @@ dirscan(idesc)
char dbuf[DIRBLKSIZ];
if (idesc->id_type != DATA)
- errexit("wrong type to dirscan %d\n", idesc->id_type);
+ errx(EEXIT, "wrong type to dirscan %d", idesc->id_type);
if (idesc->id_entryno == 0 &&
(idesc->id_filesize & (DIRBLKSIZ - 1)) != 0)
idesc->id_filesize = roundup(idesc->id_filesize, DIRBLKSIZ);
@@ -119,7 +121,7 @@ dirscan(idesc)
idesc->id_loc = 0;
for (dp = fsck_readdir(idesc); dp != NULL; dp = fsck_readdir(idesc)) {
dsize = dp->d_reclen;
- bcopy((char *)dp, dbuf, (size_t)dsize);
+ memmove(dbuf, dp, (size_t)dsize);
# if (BYTE_ORDER == LITTLE_ENDIAN)
if (!newinofmt) {
struct direct *tdp = (struct direct *)dbuf;
@@ -144,7 +146,7 @@ dirscan(idesc)
}
# endif
bp = getdirblk(idesc->id_blkno, blksiz);
- bcopy(dbuf, bp->b_un.b_buf + idesc->id_loc - dsize,
+ memmove(bp->b_un.b_buf + idesc->id_loc - dsize, dbuf,
(size_t)dsize);
dirty(bp);
sbdirty();
@@ -158,7 +160,7 @@ dirscan(idesc)
/*
* get next entry in a directory.
*/
-struct direct *
+static struct direct *
fsck_readdir(idesc)
register struct inodesc *idesc;
{
@@ -173,6 +175,8 @@ fsck_readdir(idesc)
dp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc);
if (dircheck(idesc, dp))
goto dpok;
+ if (idesc->id_fix == IGNORE)
+ return (0);
fix = dofix(idesc, "DIRECTORY CORRUPTED");
bp = getdirblk(idesc->id_blkno, blksiz);
dp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc);
@@ -202,6 +206,8 @@ dpok:
size = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ);
idesc->id_loc += size;
idesc->id_filesize -= size;
+ if (idesc->id_fix == IGNORE)
+ return (0);
fix = dofix(idesc, "DIRECTORY CORRUPTED");
bp = getdirblk(idesc->id_blkno, blksiz);
dp = (struct direct *)(bp->b_un.b_buf + dploc);
@@ -216,7 +222,7 @@ dpok:
* Verify that a directory entry is valid.
* This is a superset of the checks made in the kernel.
*/
-int
+static int
dircheck(idesc, dp)
struct inodesc *idesc;
register struct direct *dp;
@@ -226,8 +232,15 @@ dircheck(idesc, dp)
u_char namlen, type;
int spaceleft;
- size = DIRSIZ(!newinofmt, dp);
spaceleft = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ);
+ if (dp->d_ino >= maxino ||
+ dp->d_reclen == 0 ||
+ dp->d_reclen > spaceleft ||
+ (dp->d_reclen & 0x3) != 0)
+ return (0);
+ if (dp->d_ino == 0)
+ return (1);
+ size = DIRSIZ(!newinofmt, dp);
# if (BYTE_ORDER == LITTLE_ENDIAN)
if (!newinofmt) {
type = dp->d_namlen;
@@ -240,23 +253,17 @@ dircheck(idesc, dp)
namlen = dp->d_namlen;
type = dp->d_type;
# endif
- if (dp->d_ino < maxino &&
- dp->d_reclen != 0 &&
- dp->d_reclen <= spaceleft &&
- (dp->d_reclen & 0x3) == 0 &&
- dp->d_reclen >= size &&
- idesc->id_filesize >= size &&
- namlen <= MAXNAMLEN &&
- type <= 15) {
- if (dp->d_ino == 0)
- return (1);
- for (cp = dp->d_name, size = 0; size < namlen; size++)
- if (*cp == 0 || (*cp++ == '/'))
- return (0);
- if (*cp == 0)
- return (1);
- }
- return (0);
+ if (dp->d_reclen < size ||
+ idesc->id_filesize < size ||
+ namlen > MAXNAMLEN ||
+ type > 15)
+ return (0);
+ for (cp = dp->d_name, size = 0; size < namlen; size++)
+ if (*cp == '\0' || (*cp++ == '/'))
+ return (0);
+ if (*cp != '\0')
+ return (0);
+ return (1);
}
void
@@ -295,7 +302,7 @@ fileerror(cwd, ino, errmesg)
void
adjust(idesc, lcnt)
register struct inodesc *idesc;
- short lcnt;
+ int lcnt;
{
register struct dinode *dp;
@@ -323,7 +330,7 @@ adjust(idesc, lcnt)
}
}
-int
+static int
mkentry(idesc)
struct inodesc *idesc;
{
@@ -343,30 +350,38 @@ mkentry(idesc)
dirp->d_reclen = oldlen;
dirp = (struct direct *)(((char *)dirp) + oldlen);
dirp->d_ino = idesc->id_parent; /* ino to be entered is in id_parent */
- if (newinofmt) {
- dirp->d_type = typemap[idesc->id_parent];
- dirp->d_namlen = newent.d_namlen;
- } else {
-# if (BYTE_ORDER == LITTLE_ENDIAN)
- dirp->d_type = newent.d_namlen;
- dirp->d_namlen = 0;
-# else
- dirp->d_type = 0;
- dirp->d_namlen = newent.d_namlen;
-# endif
- }
dirp->d_reclen = newent.d_reclen;
- bcopy(idesc->id_name, dirp->d_name, (size_t)newent.d_namlen + 1);
+ if (newinofmt)
+ dirp->d_type = typemap[idesc->id_parent];
+ else
+ dirp->d_type = 0;
+ dirp->d_namlen = newent.d_namlen;
+ memmove(dirp->d_name, idesc->id_name, (size_t)newent.d_namlen + 1);
+# if (BYTE_ORDER == LITTLE_ENDIAN)
+ /*
+ * If the entry was split, dirscan() will only reverse the byte
+ * order of the original entry, and not the new one, before
+ * writing it back out. So, we reverse the byte order here if
+ * necessary.
+ */
+ if (oldlen != 0 && !newinofmt && !doinglevel2) {
+ u_char tmp;
+
+ tmp = dirp->d_namlen;
+ dirp->d_namlen = dirp->d_type;
+ dirp->d_type = tmp;
+ }
+# endif
return (ALTERED|STOP);
}
-int
+static int
chgino(idesc)
struct inodesc *idesc;
{
register struct direct *dirp = idesc->id_dirp;
- if (bcmp(dirp->d_name, idesc->id_name, (int)dirp->d_namlen + 1))
+ if (memcmp(dirp->d_name, idesc->id_name, (int)dirp->d_namlen + 1))
return (KEEPON);
dirp->d_ino = idesc->id_parent;
if (newinofmt)
@@ -387,7 +402,7 @@ linkup(orphan, parentdir)
struct inodesc idesc;
char tempname[BUFSIZ];
- bzero((char *)&idesc, sizeof(struct inodesc));
+ memset(&idesc, 0, sizeof(struct inodesc));
dp = ginode(orphan);
lostdir = (dp->di_mode & IFMT) == IFDIR;
pwarn("UNREF %s ", lostdir ? "DIR" : "FILE");
@@ -501,7 +516,7 @@ changeino(dir, name, newnum)
{
struct inodesc idesc;
- bzero((char *)&idesc, sizeof(struct inodesc));
+ memset(&idesc, 0, sizeof(struct inodesc));
idesc.id_type = DATA;
idesc.id_func = chgino;
idesc.id_number = dir;
@@ -526,7 +541,7 @@ makeentry(parent, ino, name)
if (parent < ROOTINO || parent >= maxino ||
ino < ROOTINO || ino >= maxino)
return (0);
- bzero((char *)&idesc, sizeof(struct inodesc));
+ memset(&idesc, 0, sizeof(struct inodesc));
idesc.id_type = DATA;
idesc.id_func = mkentry;
idesc.id_number = parent;
@@ -550,12 +565,12 @@ makeentry(parent, ino, name)
/*
* Attempt to expand the size of a directory
*/
-int
+static int
expanddir(dp, name)
register struct dinode *dp;
char *name;
{
- daddr_t lastbn, newblk;
+ ufs_daddr_t lastbn, newblk;
register struct bufarea *bp;
char *cp, firstblk[DIRBLKSIZ];
@@ -572,21 +587,21 @@ expanddir(dp, name)
(long)dblksize(&sblock, dp, lastbn + 1));
if (bp->b_errs)
goto bad;
- bcopy(bp->b_un.b_buf, firstblk, DIRBLKSIZ);
+ memmove(firstblk, bp->b_un.b_buf, DIRBLKSIZ);
bp = getdirblk(newblk, sblock.fs_bsize);
if (bp->b_errs)
goto bad;
- bcopy(firstblk, bp->b_un.b_buf, DIRBLKSIZ);
+ memmove(bp->b_un.b_buf, firstblk, DIRBLKSIZ);
for (cp = &bp->b_un.b_buf[DIRBLKSIZ];
cp < &bp->b_un.b_buf[sblock.fs_bsize];
cp += DIRBLKSIZ)
- bcopy((char *)&emptydir, cp, sizeof emptydir);
+ memmove(cp, &emptydir, sizeof emptydir);
dirty(bp);
bp = getdirblk(dp->di_db[lastbn + 1],
(long)dblksize(&sblock, dp, lastbn + 1));
if (bp->b_errs)
goto bad;
- bcopy((char *)&emptydir, bp->b_un.b_buf, sizeof emptydir);
+ memmove(bp->b_un.b_buf, &emptydir, sizeof emptydir);
pwarn("NO SPACE LEFT IN %s", name);
if (preen)
printf(" (EXPANDED)\n");
@@ -631,11 +646,11 @@ allocdir(parent, request, mode)
freeino(ino);
return (0);
}
- bcopy((char *)dirp, bp->b_un.b_buf, sizeof(struct dirtemplate));
+ memmove(bp->b_un.b_buf, dirp, sizeof(struct dirtemplate));
for (cp = &bp->b_un.b_buf[DIRBLKSIZ];
cp < &bp->b_un.b_buf[sblock.fs_fsize];
cp += DIRBLKSIZ)
- bcopy((char *)&emptydir, cp, sizeof emptydir);
+ memmove(cp, &emptydir, sizeof emptydir);
dirty(bp);
dp->di_nlink = 2;
inodirty();
@@ -680,7 +695,7 @@ freedir(ino, parent)
/*
* generate a temporary name for the lost+found directory.
*/
-int
+static int
lftempname(bufp, ino)
char *bufp;
ino_t ino;
@@ -707,9 +722,9 @@ lftempname(bufp, ino)
* Get a directory block.
* Insure that it is held until another is requested.
*/
-struct bufarea *
+static struct bufarea *
getdirblk(blkno, size)
- daddr_t blkno;
+ ufs_daddr_t blkno;
long size;
{
OpenPOWER on IntegriCloud