summaryrefslogtreecommitdiffstats
path: root/sbin/fsck_ffs/dir.c
diff options
context:
space:
mode:
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