First cut at ext2fs rev 1 support (as of mke2fs 1.18): supports the filetype

option read/write and the sparse option read-only.
This commit is contained in:
bouyer 2000-01-26 16:21:31 +00:00
parent 063cb5e5dc
commit 5fb6bc4e18
14 changed files with 296 additions and 146 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: dir.c,v 1.3 1997/10/09 13:19:34 bouyer Exp $ */
/* $NetBSD: dir.c,v 1.4 2000/01/26 16:21:31 bouyer Exp $ */
/*
* Copyright (c) 1997 Manuel Bouyer.
@ -39,12 +39,13 @@
#if 0
static char sccsid[] = "@(#)dir.c 8.5 (Berkeley) 12/8/94";
#else
__RCSID("$NetBSD: dir.c,v 1.3 1997/10/09 13:19:34 bouyer Exp $");
__RCSID("$NetBSD: dir.c,v 1.4 2000/01/26 16:21:31 bouyer Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/ufs/dir.h>
#include <ufs/ext2fs/ext2fs_dinode.h>
#include <ufs/ext2fs/ext2fs_dir.h>
#include <ufs/ext2fs/ext2fs.h>
@ -61,12 +62,10 @@ __RCSID("$NetBSD: dir.c,v 1.3 1997/10/09 13:19:34 bouyer Exp $");
char *lfname = "lost+found";
int lfmode = 01777;
/* XXX DIRBLKSIZ id bsize ! */
#define DIRBLKSIZ 0 /* just for now */
struct ext2fs_dirtemplate emptydir = { 0, DIRBLKSIZ };
struct ext2fs_dirtemplate dirhead = {
0, 12, 1, ".",
0, DIRBLKSIZ - 12, 2, ".."
0, 12, 1, IFTODT(EXT2_IFDIR), ".",
0, DIRBLKSIZ - 12, 2, IFTODT(EXT2_IFDIR), ".."
};
#undef DIRBLKSIZ
@ -189,6 +188,7 @@ fsck_readdir(idesc)
dp->e2d_reclen = h2fs16(sblock.e2fs_bsize);
dp->e2d_ino = 0;
dp->e2d_namlen = 0;
dp->e2d_type = 0;
dp->e2d_name[0] = '\0';
if (fix)
dirty(bp);
@ -235,7 +235,6 @@ dircheck(idesc, dp)
int size;
char *cp;
int spaceleft;
u_int16_t namlen;
u_int16_t reclen = fs2h16(dp->e2d_reclen);
spaceleft = sblock.e2fs_bsize - (idesc->id_loc % sblock.e2fs_bsize);
@ -246,13 +245,16 @@ dircheck(idesc, dp)
return (0);
if (dp->e2d_ino == 0)
return (1);
namlen = fs2h16(dp->e2d_namlen);
size = EXT2FS_DIRSIZ(namlen);
if (sblock.e2fs.e2fs_rev < E2FS_REV0 ||
(sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE) == 0)
if (dp->e2d_type != 0)
return (1);
size = EXT2FS_DIRSIZ(dp->e2d_namlen);
if (reclen < size ||
idesc->id_filesize < size ||
namlen > EXT2FS_MAXNAMLEN)
dp->e2d_namlen > EXT2FS_MAXNAMLEN)
return (0);
for (cp = dp->e2d_name, size = 0; size < namlen; size++)
for (cp = dp->e2d_name, size = 0; size < dp->e2d_namlen; size++)
if (*cp == '\0' || (*cp++ == '/'))
return (0);
return (1);
@ -330,10 +332,13 @@ mkentry(idesc)
struct ext2fs_direct newent;
int newlen, oldlen;
newent.e2d_namlen = h2fs16(strlen(idesc->id_name));
newlen = EXT2FS_DIRSIZ(fs2h16(newent.e2d_namlen));
newent.e2d_namlen = strlen(idesc->id_name);
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
(sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE))
newent.e2d_type = typemap[idesc->id_parent];
newlen = EXT2FS_DIRSIZ(newent.e2d_namlen);
if (dirp->e2d_ino != 0)
oldlen = EXT2FS_DIRSIZ(fs2h16(dirp->e2d_namlen));
oldlen = EXT2FS_DIRSIZ(dirp->e2d_namlen);
else
oldlen = 0;
if (fs2h16(dirp->e2d_reclen) - oldlen < newlen)
@ -344,7 +349,8 @@ mkentry(idesc)
dirp->e2d_ino = h2fs32(idesc->id_parent); /* ino to be entered is in id_parent */
dirp->e2d_reclen = newent.e2d_reclen;
dirp->e2d_namlen = newent.e2d_namlen;
memcpy(dirp->e2d_name, idesc->id_name, (size_t)fs2h16(dirp->e2d_namlen));
dirp->e2d_type = newent.e2d_type;
memcpy(dirp->e2d_name, idesc->id_name, (size_t)(dirp->e2d_namlen));
return (ALTERED|STOP);
}
@ -353,12 +359,17 @@ chgino(idesc)
struct inodesc *idesc;
{
struct ext2fs_direct *dirp = idesc->id_dirp;
u_int16_t namlen = fs2h16(dirp->e2d_namlen);
u_int16_t namlen = dirp->e2d_namlen;
if (strlen(idesc->id_name) != namlen ||
strncmp(dirp->e2d_name, idesc->id_name, (int)namlen))
return (KEEPON);
dirp->e2d_ino = h2fs32(idesc->id_parent);
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
(sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE))
dirp->e2d_type = typemap[idesc->id_parent];
else
dirp->e2d_type = 0;
return (ALTERED|STOP);
}
@ -601,8 +612,18 @@ allocdir(parent, request, mode)
ino = allocino(request, IFDIR|mode);
dirhead.dot_reclen = h2fs16(12); /* XXX */
dirhead.dotdot_reclen = h2fs16(sblock.e2fs_bsize - 12); /* XXX */
dirhead.dot_namlen = h2fs16(1);
dirhead.dotdot_namlen = h2fs16(2);
dirhead.dot_namlen = 1;
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
(sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE))
dirhead.dot_type = IFTODT(EXT2_IFDIR);
else
dirhead.dot_type = 0;
dirhead.dotdot_namlen = 2;
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
(sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE))
dirhead.dotdot_type = IFTODT(EXT2_IFDIR);
else
dirhead.dotdot_type = 0;
dirp = &dirhead;
dirp->dot_ino = h2fs32(ino);
dirp->dotdot_ino = h2fs32(parent);

View File

@ -1,4 +1,4 @@
/* $NetBSD: fsck.h,v 1.2 1997/10/09 13:19:35 bouyer Exp $ */
/* $NetBSD: fsck.h,v 1.3 2000/01/26 16:21:31 bouyer Exp $ */
/*
* Copyright (c) 1997 Manuel Bouyer.
@ -184,6 +184,7 @@ char *blockmap; /* ptr to primary blk allocation map */
ino_t maxino; /* number of inodes in file system */
ino_t lastino; /* last inode in use */
char *statemap; /* ptr to inode state table */
u_char *typemap; /* ptr to inode type table */
int16_t *lncntp; /* ptr to link count table */
ino_t lfdir; /* lost & found directory inode number */

View File

@ -1,4 +1,4 @@
/* $NetBSD: inode.c,v 1.6 1999/02/17 13:11:19 bouyer Exp $ */
/* $NetBSD: inode.c,v 1.7 2000/01/26 16:21:32 bouyer Exp $ */
/*
* Copyright (c) 1997 Manuel Bouyer.
@ -39,7 +39,7 @@
#if 0
static char sccsid[] = "@(#)inode.c 8.5 (Berkeley) 2/8/95";
#else
__RCSID("$NetBSD: inode.c,v 1.6 1999/02/17 13:11:19 bouyer Exp $");
__RCSID("$NetBSD: inode.c,v 1.7 2000/01/26 16:21:32 bouyer Exp $");
#endif
#endif /* not lint */
@ -50,6 +50,7 @@ __RCSID("$NetBSD: inode.c,v 1.6 1999/02/17 13:11:19 bouyer Exp $");
#include <ufs/ext2fs/ext2fs.h>
#include <ufs/ufs/dinode.h> /* for IFMT & friends */
#include <ufs/ufs/dir.h> /* for IFTODT & friends */
#ifndef SMALL
#include <pwd.h>
#endif
@ -502,7 +503,7 @@ findname(idesc)
struct inodesc *idesc;
{
struct ext2fs_direct *dirp = idesc->id_dirp;
u_int16_t namlen = fs2h16(dirp->e2d_namlen);
u_int16_t namlen = dirp->e2d_namlen;
if (fs2h32(dirp->e2d_ino) != idesc->id_parent)
return (KEEPON);
@ -637,6 +638,7 @@ allocino(request, type)
dp->e2di_nblock = h2fs32(btodb(sblock.e2fs_bsize));
n_files++;
inodirty();
typemap[ino] = IFTODT(type);
return (ino);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: main.c,v 1.6 1998/07/26 20:27:20 mycroft Exp $ */
/* $NetBSD: main.c,v 1.7 2000/01/26 16:21:32 bouyer Exp $ */
/*
* Copyright (c) 1997 Manuel Bouyer.
@ -44,7 +44,7 @@ __COPYRIGHT("@(#) Copyright (c) 1980, 1986, 1993\n\
#if 0
static char sccsid[] = "@(#)main.c 8.2 (Berkeley) 1/23/94";
#else
__RCSID("$NetBSD: main.c,v 1.6 1998/07/26 20:27:20 mycroft Exp $");
__RCSID("$NetBSD: main.c,v 1.7 2000/01/26 16:21:32 bouyer Exp $");
#endif
#endif /* not lint */
@ -193,6 +193,10 @@ checkfilesys(filesys, mntpt, auxdata, child)
* 1: scan inodes tallying blocks used
*/
if (preen == 0) {
if (sblock.e2fs.e2fs_rev > E2FS_REV0) {
printf("** Last Mounted on %s\n",
sblock.e2fs.e2fs_fsmnt);
}
if (hotroot())
printf("** Root file system\n");
printf("** Phase 1 - Check Blocks and Sizes\n");

View File

@ -1,4 +1,4 @@
/* $NetBSD: pass1.c,v 1.6 1999/02/17 13:11:19 bouyer Exp $ */
/* $NetBSD: pass1.c,v 1.7 2000/01/26 16:21:32 bouyer Exp $ */
/*
* Copyright (c) 1997 Manuel Bouyer.
@ -39,7 +39,7 @@
#if 0
static char sccsid[] = "@(#)pass1.c 8.1 (Berkeley) 6/5/93";
#else
__RCSID("$NetBSD: pass1.c,v 1.6 1999/02/17 13:11:19 bouyer Exp $");
__RCSID("$NetBSD: pass1.c,v 1.7 2000/01/26 16:21:32 bouyer Exp $");
#endif
#endif /* not lint */
@ -50,6 +50,7 @@ __RCSID("$NetBSD: pass1.c,v 1.6 1999/02/17 13:11:19 bouyer Exp $");
#include <ufs/ext2fs/ext2fs.h>
#include <ufs/ufs/dinode.h> /* for IFMT & friends */
#include <ufs/ufs/dir.h> /* for IFTODT & friends */
#include <stdio.h>
#include <stdlib.h>
@ -247,6 +248,7 @@ checkinode(inumber, idesc)
} else {
statemap[inumber] = FSTATE;
}
typemap[inumber] = IFTODT(mode);
badblk = dupblk = 0;
idesc->id_number = inumber;
(void)ckinode(dp, idesc);

View File

@ -1,4 +1,4 @@
/* $NetBSD: pass2.c,v 1.4 1997/10/09 13:19:38 bouyer Exp $ */
/* $NetBSD: pass2.c,v 1.5 2000/01/26 16:21:32 bouyer Exp $ */
/*
* Copyright (c) 1997 Manuel Bouyer.
@ -39,7 +39,7 @@
#if 0
static char sccsid[] = "@(#)pass2.c 8.6 (Berkeley) 10/27/94";
#else
__RCSID("$NetBSD: pass2.c,v 1.4 1997/10/09 13:19:38 bouyer Exp $");
__RCSID("$NetBSD: pass2.c,v 1.5 2000/01/26 16:21:32 bouyer Exp $");
#endif
#endif /* not lint */
@ -50,6 +50,7 @@ __RCSID("$NetBSD: pass2.c,v 1.4 1997/10/09 13:19:38 bouyer Exp $");
#include <ufs/ext2fs/ext2fs.h>
#include <ufs/ufs/dinode.h> /* for IFMT & friends */
#include <ufs/ufs/dir.h> /* for IFTODT & friends */
#include <stdio.h>
#include <stdlib.h>
@ -216,7 +217,7 @@ pass2check(idesc)
*/
if (idesc->id_entryno != 0)
goto chk1;
if (fs2h32(dirp->e2d_ino) != 0 && fs2h16(dirp->e2d_namlen) == 1 &&
if (fs2h32(dirp->e2d_ino) != 0 && dirp->e2d_namlen == 1 &&
dirp->e2d_name[0] == '.') {
if (fs2h32(dirp->e2d_ino) != idesc->id_number) {
direrror(idesc->id_number, "BAD INODE NUMBER FOR '.'");
@ -224,13 +225,26 @@ pass2check(idesc)
if (reply("FIX") == 1)
ret |= ALTERED;
}
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
(sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE)
&& (dirp->e2d_type != IFTODT(EXT2_IFDIR))) {
direrror(idesc->id_number, "BAD TYPE VALUE FOR '.'");
dirp->e2d_type = IFTODT(EXT2_IFDIR);
if (reply("FIX") == 1)
ret |= ALTERED;
}
goto chk1;
}
direrror(idesc->id_number, "MISSING '.'");
proto.e2d_ino = h2fs32(idesc->id_number);
proto.e2d_namlen = h2fs16(1);
proto.e2d_namlen = 1;
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
(sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE))
proto.e2d_type = IFTODT(EXT2_IFDIR);
else
proto.e2d_type = 0;
(void)strcpy(proto.e2d_name, ".");
entrysize = EXT2FS_DIRSIZ(fs2h16(proto.e2d_namlen));
entrysize = EXT2FS_DIRSIZ(proto.e2d_namlen);
if (fs2h32(dirp->e2d_ino) != 0 && strcmp(dirp->e2d_name, "..") != 0) {
pfatal("CANNOT FIX, FIRST ENTRY IN DIRECTORY CONTAINS %s\n",
dirp->e2d_name);
@ -258,11 +272,16 @@ chk1:
goto chk2;
inp = getinoinfo(idesc->id_number);
proto.e2d_ino = h2fs32(inp->i_parent);
proto.e2d_namlen = h2fs16(2);
proto.e2d_namlen = 2;
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
(sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE))
proto.e2d_type = IFTODT(EXT2_IFDIR);
else
proto.e2d_type = 0;
(void)strcpy(proto.e2d_name, "..");
entrysize = EXT2FS_DIRSIZ(2);
if (idesc->id_entryno == 0) {
n = EXT2FS_DIRSIZ(fs2h16(dirp->e2d_namlen));
n = EXT2FS_DIRSIZ(dirp->e2d_namlen);
if (fs2h16(dirp->e2d_reclen) < n + entrysize)
goto chk2;
proto.e2d_reclen = h2fs16(fs2h16(dirp->e2d_reclen) - n);
@ -274,13 +293,21 @@ chk1:
dirp->e2d_reclen = proto.e2d_reclen;
}
if (fs2h32(dirp->e2d_ino) != 0 &&
fs2h16(dirp->e2d_namlen) == 2 &&
dirp->e2d_namlen == 2 &&
strncmp(dirp->e2d_name, "..", 2) == 0) {
inp->i_dotdot = fs2h32(dirp->e2d_ino);
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
(sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE)
&& dirp->e2d_type != IFTODT(EXT2_IFDIR)) {
direrror(idesc->id_number, "BAD TYPE VALUE FOR '..'");
dirp->e2d_type = IFTODT(EXT2_IFDIR);
if (reply("FIX") == 1)
ret |= ALTERED;
}
goto chk2;
}
if (fs2h32(dirp->e2d_ino) != 0 &&
fs2h16(dirp->e2d_namlen) == 1 &&
dirp->e2d_namlen == 1 &&
strncmp(dirp->e2d_name, ".", 1) != 0) {
fileerror(inp->i_parent, idesc->id_number, "MISSING '..'");
pfatal("CANNOT FIX, SECOND ENTRY IN DIRECTORY CONTAINS %s\n",
@ -308,10 +335,10 @@ chk1:
chk2:
if (fs2h32(dirp->e2d_ino) == 0)
return (ret|KEEPON);
if (fs2h16(dirp->e2d_namlen) <= 2 &&
if (dirp->e2d_namlen <= 2 &&
dirp->e2d_name[0] == '.' &&
idesc->id_entryno >= 2) {
if (fs2h16(dirp->e2d_namlen) == 1) {
if (dirp->e2d_namlen == 1) {
direrror(idesc->id_number, "EXTRA '.' ENTRY");
dirp->e2d_ino = 0;
if (reply("FIX") == 1)
@ -385,6 +412,17 @@ again:
/* fall through */
case FSTATE:
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
(sblock.e2fs.e2fs_features_incompat &
EXT2F_INCOMPAT_FTYPE) &&
dirp->e2d_type != typemap[fs2h32(dirp->e2d_ino)]) {
dirp->e2d_type = typemap[fs2h32(dirp->e2d_ino)];
fileerror(idesc->id_number,
fs2h32(dirp->e2d_ino),
"BAD TYPE VALUE");
if (reply("FIX") == 1)
ret |= ALTERED;
}
lncntp[fs2h32(dirp->e2d_ino)]--;
break;

View File

@ -1,4 +1,4 @@
/* $NetBSD: setup.c,v 1.10 1999/02/17 13:11:19 bouyer Exp $ */
/* $NetBSD: setup.c,v 1.11 2000/01/26 16:21:32 bouyer Exp $ */
/*
* Copyright (c) 1997 Manuel Bouyer.
@ -39,7 +39,7 @@
#if 0
static char sccsid[] = "@(#)setup.c 8.5 (Berkeley) 11/23/94";
#else
__RCSID("$NetBSD: setup.c,v 1.10 1999/02/17 13:11:19 bouyer Exp $");
__RCSID("$NetBSD: setup.c,v 1.11 2000/01/26 16:21:32 bouyer Exp $");
#endif
#endif /* not lint */
@ -224,6 +224,12 @@ setup(dev)
(unsigned)(maxino + 1));
goto badsblabel;
}
typemap = calloc((unsigned)(maxino + 1), sizeof(char));
if (typemap == NULL) {
printf("cannot alloc %u bytes for typemap\n",
(unsigned)(maxino + 1));
goto badsblabel;
}
lncntp = (int16_t *)calloc((unsigned)(maxino + 1), sizeof(int16_t));
if (lncntp == NULL) {
printf("cannot alloc %u bytes for lncntp\n",
@ -364,17 +370,17 @@ readsb(listerr)
asblk.b_un.b_fs->e2fs_rgid = sblk.b_un.b_fs->e2fs_rgid;
asblk.b_un.b_fs->e2fs_block_group_nr =
sblk.b_un.b_fs->e2fs_block_group_nr;
if (sblk.b_un.b_fs->e2fs_features_compat != 0 ||
sblk.b_un.b_fs->e2fs_features_incompat != 0 ||
sblk.b_un.b_fs->e2fs_features_compat_ro != 0) {
if (sblk.b_un.b_fs->e2fs_rev > E2FS_REV0 &&
((sblk.b_un.b_fs->e2fs_features_incompat & ~EXT2F_INCOMPAT_SUPP) ||
(sblk.b_un.b_fs->e2fs_features_rocompat & ~EXT2F_ROCOMPAT_SUPP))) {
if (debug) {
printf("compat 0x%08x, incompat 0x%08x, compat_ro "
"0x%08x\n",
sblk.b_un.b_fs->e2fs_features_compat,
sblk.b_un.b_fs->e2fs_features_incompat,
sblk.b_un.b_fs->e2fs_features_compat_ro);
sblk.b_un.b_fs->e2fs_features_rocompat);
}
badsb(listerr,"UNKNOWN FEATURE BITS IN SUPER BLOCK");
badsb(listerr,"INCOMPATIBLE FEATURE BITS IN SUPER BLOCK");
return 0;
}
if (memcmp(sblk.b_un.b_fs, asblk.b_un.b_fs, SBSIZE)) {

View File

@ -1,4 +1,4 @@
/* $NetBSD: ext2fs.h,v 1.8 1999/02/17 13:09:43 bouyer Exp $ */
/* $NetBSD: ext2fs.h,v 1.9 2000/01/26 16:21:33 bouyer Exp $ */
/*
* Copyright (c) 1997 Manuel Bouyer.
@ -119,7 +119,7 @@ struct ext2fs {
u_int16_t e2fs_magic; /* magic number */
u_int16_t e2fs_state; /* file system state */
u_int16_t e2fs_beh; /* behavior on errors */
u_int16_t reserved;
u_int16_t e2fs_minrev; /* minor revision level */
u_int32_t e2fs_lastfsck; /* time of last fsck */
u_int32_t e2fs_fsckintv; /* max time between fscks */
u_int32_t e2fs_creator; /* creator OS */
@ -130,10 +130,17 @@ struct ext2fs {
u_int32_t e2fs_first_ino; /* first non-reserved inode */
u_int16_t e2fs_inode_size; /* size of inode structure */
u_int16_t e2fs_block_group_nr; /* block grp number of this sblk*/
u_int32_t e2fs_features_compat; /* OK to mount if unknown */
u_int32_t e2fs_features_incompat; /* not OK to mount if unknown */
u_int32_t e2fs_features_compat_ro; /* OK to mount ro if unknown */
u_int32_t reserved2[230];
u_int32_t e2fs_features_compat; /* compatible feature set */
u_int32_t e2fs_features_incompat; /* incompatible feature set */
u_int32_t e2fs_features_rocompat; /* RO-compatible feature set */
u_int8_t e2fs_uuid[16]; /* 128-bit uuid for volume */
char e2fs_vname[16]; /* volume name */
char e2fs_fsmnt[64]; /* name mounted on */
u_int32_t e2fs_algo; /* For compression */
u_int8_t e2fs_prealloc; /* # of blocks to preallocate */
u_int8_t e2fs_dir_prealloc; /* # of blocks to preallocate for dir */
u_int16_t pad1;
u_int32_t reserved2[204];
};
@ -161,7 +168,23 @@ struct m_ext2fs {
* Filesystem identification
*/
#define E2FS_MAGIC 0xef53 /* the ext2fs magic number */
#define E2FS_REV 0 /* revision level */
#define E2FS_REV0 0 /* revision levels */
#define E2FS_REV1 1 /* revision levels */
/* compatible/imcompatible features */
#define EXT2F_COMPAT_PREALLOC 0x0001
#define EXT2F_ROCOMPAT_SPARSESUPER 0x0001
#define EXT2F_ROCOMPAT_LARGEFILE 0x0002
#define EXT2F_ROCOMPAT_BTREE_DIR 0x0004
#define EXT2F_INCOMPAT_COMP 0x0001
#define EXT2F_INCOMPAT_FTYPE 0x0002
/* features supported in this implementation */
#define EXT2F_COMPAT_SUPP 0x0000
#define EXT2F_ROCOMPAT_SUPP 0x0000
#define EXT2F_INCOMPAT_SUPP EXT2F_INCOMPAT_FTYPE
/*
* OS identification

View File

@ -1,4 +1,4 @@
/* $NetBSD: ext2fs_bswap.c,v 1.2 1998/08/09 20:15:38 perry Exp $ */
/* $NetBSD: ext2fs_bswap.c,v 1.3 2000/01/26 16:21:33 bouyer Exp $ */
/*
* Copyright (c) 1997 Manuel Bouyer.
@ -59,17 +59,25 @@ e2fs_sb_bswap(old, new)
new->e2fs_ipg = bswap32(old->e2fs_ipg);
new->e2fs_mtime = bswap32(old->e2fs_mtime);
new->e2fs_wtime = bswap32(old->e2fs_wtime);
new->e2fs_lastfsck = bswap32(old->e2fs_lastfsck);
new->e2fs_fsckintv = bswap32(old->e2fs_fsckintv);
new->e2fs_creator = bswap32(old->e2fs_creator);
new->e2fs_rev = bswap32(old->e2fs_rev);
new->e2fs_mnt_count = bswap16(old->e2fs_mnt_count);
new->e2fs_max_mnt_count = bswap16(old->e2fs_max_mnt_count);
new->e2fs_magic = bswap16(old->e2fs_magic);
new->e2fs_state = bswap16(old->e2fs_state);
new->e2fs_beh = bswap16(old->e2fs_beh);
new->e2fs_minrev = bswap16(old->e2fs_minrev);
new->e2fs_lastfsck = bswap32(old->e2fs_lastfsck);
new->e2fs_fsckintv = bswap32(old->e2fs_fsckintv);
new->e2fs_creator = bswap32(old->e2fs_creator);
new->e2fs_rev = bswap32(old->e2fs_rev);
new->e2fs_ruid = bswap16(old->e2fs_ruid);
new->e2fs_rgid = bswap16(old->e2fs_rgid);
new->e2fs_first_ino = bswap32(old->e2fs_first_ino);
new->e2fs_inode_size = bswap16(old->e2fs_inode_size);
new->e2fs_block_group_nr = bswap16(old->e2fs_block_group_nr);
new->e2fs_features_compat = bswap32(old->e2fs_features_compat);
new->e2fs_features_incompat = bswap32(old->e2fs_features_incompat);
new->e2fs_features_rocompat = bswap32(old->e2fs_features_rocompat);
new->e2fs_algo = bswap32(old->e2fs_algo);
}
void e2fs_cg_bswap(old, new, size)

View File

@ -1,4 +1,4 @@
/* $NetBSD: ext2fs_dinode.h,v 1.5 1998/10/23 00:33:24 thorpej Exp $ */
/* $NetBSD: ext2fs_dinode.h,v 1.6 2000/01/26 16:21:33 bouyer Exp $ */
/*
* Copyright (c) 1997 Manuel Bouyer.
@ -79,7 +79,7 @@ struct ext2fs_dinode {
u_int32_t e2di_flags; /* 32: Status flags (chflags) */
u_int32_t e2di_linux_reserved1; /* 36 */
u_int32_t e2di_blocks[NDADDR+NIADDR]; /* 40: disk blocks */
u_int32_t e2di_gen; /* 100: generation number (file version) */
u_int32_t e2di_gen; /* 100: generation number */
u_int32_t e2di_facl; /* 104: file ACL (not implemented) */
u_int32_t e2di_dacl; /* 108: dir ACL (not implemented) */
u_int32_t e2di_faddr; /* 112: fragment address */

View File

@ -1,4 +1,4 @@
/* $NetBSD: ext2fs_dir.h,v 1.2 1998/09/13 15:14:40 christos Exp $ */
/* $NetBSD: ext2fs_dir.h,v 1.3 2000/01/26 16:21:33 bouyer Exp $ */
/*
* Copyright (c) 1997 Manuel Bouyer.
@ -75,6 +75,9 @@
* a directory block is free, then its dp->e2d_ino is set to 0.
* Entries other than the first in a directory do not normally have
* dp->e2d_ino set to 0.
* Ext2 rev 0 has a 16 bits e2d_namlen. For Ext2 vev 1 this has been split
* into a 8 bits e2d_namlen and 8 bits e2d_type (looks like ffs, isnt't it ? :)
* It's safe to use this for rev 0 as well because all ext2 are little-endian.
*/
#define EXT2FS_MAXNAMLEN 255
@ -82,7 +85,8 @@
struct ext2fs_direct {
u_int32_t e2d_ino; /* inode number of entry */
u_int16_t e2d_reclen; /* length of this record */
u_int16_t e2d_namlen; /* length of string in d_name */
u_int8_t e2d_namlen; /* length of string in d_name */
u_int8_t e2d_type; /* file type */
char e2d_name[EXT2FS_MAXNAMLEN];/* name with length <= EXT2FS_MAXNAMLEN */
};
@ -103,11 +107,13 @@ struct ext2fs_direct {
struct ext2fs_dirtemplate {
u_int32_t dot_ino;
int16_t dot_reclen;
u_int16_t dot_namlen;
u_int8_t dot_namlen;
u_int8_t dot_type;
char dot_name[4]; /* must be multiple of 4 */
u_int32_t dotdot_ino;
int16_t dotdot_reclen;
u_int16_t dotdot_namlen;
u_int8_t dotdot_namlen;
u_int8_t dotdot_type;
char dotdot_name[4]; /* ditto */
};

View File

@ -1,4 +1,4 @@
/* $NetBSD: ext2fs_lookup.c,v 1.12 1999/09/05 14:26:34 jdolecek Exp $ */
/* $NetBSD: ext2fs_lookup.c,v 1.13 2000/01/26 16:21:33 bouyer Exp $ */
/*
* Modified for NetBSD 1.2E
@ -95,7 +95,7 @@ ext2fs_dirconv2ffs( e2dir, ffsdir)
{
memset(ffsdir, 0, sizeof(struct dirent));
ffsdir->d_fileno = fs2h32(e2dir->e2d_ino);
ffsdir->d_namlen = fs2h16(e2dir->e2d_namlen);
ffsdir->d_namlen = e2dir->e2d_namlen;
ffsdir->d_type = DT_UNKNOWN; /* don't know more here */
#ifdef DIAGNOSTIC
@ -103,7 +103,7 @@ ext2fs_dirconv2ffs( e2dir, ffsdir)
* XXX Rigth now this can't happen, but if one day
* MAXNAMLEN != E2FS_MAXNAMLEN we should handle this more gracefully !
*/
if (fs2h16(e2dir->e2d_namlen) > MAXNAMLEN)
if (e2dir->e2d_namlen > MAXNAMLEN)
panic("ext2fs: e2dir->e2d_namlen\n");
#endif
strncpy(ffsdir->d_name, e2dir->e2d_name, ffsdir->d_namlen);
@ -415,7 +415,7 @@ searchloop:
int size = fs2h16(ep->e2d_reclen);
if (ep->e2d_ino != 0)
size -= EXT2FS_DIRSIZ(fs2h16(ep->e2d_namlen));
size -= EXT2FS_DIRSIZ(ep->e2d_namlen);
if (size > 0) {
if (size >= slotneeded) {
slotstatus = FOUND;
@ -438,7 +438,7 @@ searchloop:
* Check for a name match.
*/
if (ep->e2d_ino) {
namlen = fs2h16(ep->e2d_namlen);
namlen = ep->e2d_namlen;
if (namlen == cnp->cn_namelen &&
!memcmp(cnp->cn_nameptr, ep->e2d_name,
(unsigned)namlen)) {
@ -538,11 +538,11 @@ found:
* Check that directory length properly reflects presence
* of this entry.
*/
if (entryoffsetinblock + EXT2FS_DIRSIZ(fs2h16(ep->e2d_namlen))
if (entryoffsetinblock + EXT2FS_DIRSIZ(ep->e2d_namlen)
> dp->i_e2fs_size) {
ufs_dirbad(dp, dp->i_offset, "i_size too small");
dp->i_e2fs_size = entryoffsetinblock +
EXT2FS_DIRSIZ(fs2h16(ep->e2d_namlen));
EXT2FS_DIRSIZ(ep->e2d_namlen);
dp->i_flag |= IN_CHANGE | IN_UPDATE;
}
@ -713,7 +713,7 @@ ext2fs_dirbadentry(dp, de, entryoffsetinblock)
char * error_msg = NULL;
int reclen = fs2h16(de->e2d_reclen);
int namlen = fs2h16(de->e2d_namlen);
int namlen = de->e2d_namlen;
if (reclen < EXT2FS_DIRSIZ(1)) /* e2d_namlen = 1 */
error_msg = "rec_len is smaller than minimal";
@ -770,7 +770,13 @@ ext2fs_direnter(ip, dvp, cnp)
#endif
dp = VTOI(dvp);
newdir.e2d_ino = h2fs32(ip->i_number);
newdir.e2d_namlen = h2fs16(cnp->cn_namelen);
newdir.e2d_namlen = cnp->cn_namelen;
if (ip->i_e2fs->e2fs.e2fs_rev > E2FS_REV0 &&
(ip->i_e2fs->e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE)) {
newdir.e2d_type = IFTODT(ip->i_ffs_mode);
} else {
newdir.e2d_type = 0;
};
memcpy(newdir.e2d_name, cnp->cn_nameptr, (unsigned)cnp->cn_namelen + 1);
newentrysize = EXT2FS_DIRSIZ(cnp->cn_namelen);
if (dp->i_count == 0) {
@ -826,7 +832,7 @@ ext2fs_direnter(ip, dvp, cnp)
* space.
*/
ep = (struct ext2fs_direct *)dirbuf;
dsize = EXT2FS_DIRSIZ(fs2h16(ep->e2d_namlen));
dsize = EXT2FS_DIRSIZ(ep->e2d_namlen);
spacefree = fs2h16(ep->e2d_reclen) - dsize;
for (loc = fs2h16(ep->e2d_reclen); loc < dp->i_count; ) {
nep = (struct ext2fs_direct *)(dirbuf + loc);
@ -838,7 +844,7 @@ ext2fs_direnter(ip, dvp, cnp)
/* overwrite; nothing there; header is ours */
spacefree += dsize;
}
dsize = EXT2FS_DIRSIZ(fs2h16(nep->e2d_namlen));
dsize = EXT2FS_DIRSIZ(nep->e2d_namlen);
spacefree += fs2h16(nep->e2d_reclen) - dsize;
loc += fs2h16(nep->e2d_reclen);
memcpy((caddr_t)ep, (caddr_t)nep, dsize);
@ -942,6 +948,12 @@ ext2fs_dirrewrite(dp, ip, cnp)
if (error != 0)
return (error);
ep->e2d_ino = h2fs32(ip->i_number);
if (ip->i_e2fs->e2fs.e2fs_rev > E2FS_REV0 &&
(ip->i_e2fs->e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE)) {
ep->e2d_type = IFTODT(ip->i_ffs_mode);
} else {
ep->e2d_type = 0;
}
error = VOP_BWRITE(bp);
dp->i_flag |= IN_CHANGE | IN_UPDATE;
return (error);
@ -986,7 +998,7 @@ ext2fs_dirempty(ip, parentino, cred)
if (dp->e2d_ino == 0)
continue;
/* accept only "." and ".." */
namlen = fs2h16(dp->e2d_namlen);
namlen = dp->e2d_namlen;
if (namlen > 2)
return (0);
if (dp->e2d_name[0] != '.')
@ -1041,7 +1053,7 @@ ext2fs_checkpath(source, target, cred)
(struct proc *)0);
if (error != 0)
break;
namlen = fs2h16(dirbuf.dotdot_namlen);
namlen = dirbuf.dotdot_namlen;
if (namlen != 2 ||
dirbuf.dotdot_name[0] != '.' ||
dirbuf.dotdot_name[1] != '.') {

View File

@ -1,4 +1,4 @@
/* $NetBSD: ext2fs_vfsops.c,v 1.30 1999/11/15 18:49:13 fvdl Exp $ */
/* $NetBSD: ext2fs_vfsops.c,v 1.31 2000/01/26 16:21:34 bouyer Exp $ */
/*
* Copyright (c) 1997 Manuel Bouyer.
@ -74,6 +74,7 @@
extern struct lock ufs_hashlock;
int ext2fs_sbupdate __P((struct ufsmount *, int));
static int ext2fs_checksb __P((struct ext2fs *, int));
extern struct vnodeopv_desc ext2fs_vnodeop_opv_desc;
extern struct vnodeopv_desc ext2fs_specop_opv_desc;
@ -168,7 +169,12 @@ ext2fs_mountroot()
fs = ump->um_e2fs;
memset(fs->e2fs_fsmnt, 0, sizeof(fs->e2fs_fsmnt));
(void) copystr(mp->mnt_stat.f_mntonname, fs->e2fs_fsmnt,
MNAMELEN - 1, 0);
sizeof(fs->e2fs_fsmnt) - 1, 0);
if (fs->e2fs.e2fs_rev > E2FS_REV0) {
memset(fs->e2fs.e2fs_fsmnt, 0, sizeof(fs->e2fs.e2fs_fsmnt));
(void) copystr(mp->mnt_stat.f_mntonname, fs->e2fs.e2fs_fsmnt,
sizeof(fs->e2fs.e2fs_fsmnt) - 1, 0);
}
(void)ext2fs_statfs(mp, &mp->mnt_stat, p);
vfs_unbusy(mp);
inittodr(fs->e2fs.e2fs_wtime);
@ -301,8 +307,15 @@ ext2fs_mount(mp, path, data, ndp, p)
}
ump = VFSTOUFS(mp);
fs = ump->um_e2fs;
(void) copyinstr(path, fs->e2fs_fsmnt, sizeof(fs->e2fs_fsmnt) - 1, &size);
(void) copyinstr(path, fs->e2fs_fsmnt, sizeof(fs->e2fs_fsmnt) - 1,
&size);
memset(fs->e2fs_fsmnt + size, 0, sizeof(fs->e2fs_fsmnt) - size);
if (fs->e2fs.e2fs_rev > E2FS_REV0) {
(void) copystr(mp->mnt_stat.f_mntonname, fs->e2fs.e2fs_fsmnt,
sizeof(fs->e2fs.e2fs_fsmnt) - 1, &size);
memset(fs->e2fs.e2fs_fsmnt, 0,
sizeof(fs->e2fs.e2fs_fsmnt) - size);
}
memcpy(mp->mnt_stat.f_mntonname, fs->e2fs_fsmnt, MNAMELEN);
(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
&size);
@ -368,27 +381,11 @@ ext2fs_reload(mountp, cred, p)
return (error);
}
newfs = (struct ext2fs *)bp->b_data;
if (fs2h16(newfs->e2fs_magic) != E2FS_MAGIC) {
error = ext2fs_checksb(newfs, (mountp->mnt_flag & MNT_RDONLY) != 0);
if (error) {
brelse(bp);
return (EIO); /* XXX needs translation */
return (error);
}
if (fs2h32(newfs->e2fs_rev) != E2FS_REV) {
#ifdef DIAGNOSTIC
printf("Ext2 fs: unsupported revision number: %x (expected %x)\n",
fs2h32(newfs->e2fs_rev), E2FS_REV);
#endif
brelse(bp);
return (EIO); /* XXX needs translation */
}
if (fs2h32(newfs->e2fs_log_bsize) > 2) { /* block size = 1024|2048|4096 */
#ifdef DIAGNOSTIC
printf("Ext2 fs: bad block size: %d (expected <=2 for ext2 fs)\n",
fs2h32(newfs->e2fs_log_bsize));
#endif
brelse(bp);
return (EIO); /* XXX needs translation */
}
fs = VFSTOUFS(mountp)->um_e2fs;
/*
@ -528,23 +525,9 @@ ext2fs_mountfs(devvp, mp, p)
error = EINVAL; /* XXX needs translation */
goto out;
}
if (fs2h32(fs->e2fs_rev) != E2FS_REV) {
#ifdef DIAGNOSTIC
printf("Ext2 fs: unsupported revision number: %x (expected %x)\n",
fs2h32(fs->e2fs_rev), E2FS_REV);
#endif
error = EINVAL; /* XXX needs translation */
error = ext2fs_checksb(fs, ronly);
if (error)
goto out;
}
if (fs2h32(fs->e2fs_log_bsize) > 2) { /* block size = 1024|2048|4096 */
#ifdef DIAGNOSTIC
printf("Ext2 fs: bad block size: %d (expected <=2 for ext2 fs)\n",
fs2h32(fs->e2fs_log_bsize));
#endif
error = EINVAL; /* XXX needs translation */
goto out;
}
ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
memset((caddr_t)ump, 0, sizeof *ump);
ump->um_e2fs = malloc(sizeof(struct m_ext2fs), M_UFSMNT, M_WAITOK);
@ -1045,3 +1028,39 @@ ext2fs_cgupdate(mp, waitfor)
allerror = error;
return (allerror);
}
static int
ext2fs_checksb(fs, ronly)
struct ext2fs *fs;
int ronly;
{
if (fs2h16(fs->e2fs_magic) != E2FS_MAGIC) {
return (EIO); /* XXX needs translation */
}
if (fs2h32(fs->e2fs_rev) > E2FS_REV1) {
#ifdef DIAGNOSTIC
printf("Ext2 fs: unsupported revision number: %x\n",
fs2h32(fs->e2fs_rev));
#endif
return (EIO); /* XXX needs translation */
}
if (fs2h32(fs->e2fs_log_bsize) > 2) { /* block size = 1024|2048|4096 */
#ifdef DIAGNOSTIC
printf("Ext2 fs: bad block size: %d (expected <=2 for ext2 fs)\n",
fs2h32(fs->e2fs_log_bsize));
#endif
return (EIO); /* XXX needs translation */
}
if (fs2h32(fs->e2fs_rev) > E2FS_REV0) {
if (fs2h32(fs->e2fs_features_incompat) &
~EXT2F_INCOMPAT_SUPP) {
printf("Ext2 fs: unsupported optionnal feature\n");
return (EIO); /* XXX needs translation */
}
if (!ronly && fs2h32(fs->e2fs_features_rocompat) &
~EXT2F_ROCOMPAT_SUPP) {
return (EROFS); /* XXX needs translation */
}
}
return (0);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: ext2fs_vnops.c,v 1.21 1999/08/03 20:19:21 wrstuden Exp $ */
/* $NetBSD: ext2fs_vnops.c,v 1.22 2000/01/26 16:21:34 bouyer Exp $ */
/*
* Copyright (c) 1997 Manuel Bouyer.
@ -930,7 +930,7 @@ abortit:
UIO_SYSSPACE, IO_NODELOCKED,
tcnp->cn_cred, (size_t *)0, (struct proc *)0);
if (error == 0) {
namlen = fs2h16(dirbuf.dotdot_namlen);
namlen = dirbuf.dotdot_namlen;
if (namlen != 2 ||
dirbuf.dotdot_name[0] != '.' ||
dirbuf.dotdot_name[1] != '.') {
@ -1042,11 +1042,19 @@ ext2fs_mkdir(v)
memset(&dirtemplate, 0, sizeof(dirtemplate));
dirtemplate.dot_ino = h2fs32(ip->i_number);
dirtemplate.dot_reclen = h2fs16(12);
dirtemplate.dot_namlen = h2fs16(1);
dirtemplate.dot_namlen = 1;
if (ip->i_e2fs->e2fs.e2fs_rev > E2FS_REV0 &&
(ip->i_e2fs->e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE)) {
dirtemplate.dot_type = IFTODT(EXT2_IFDIR);
}
dirtemplate.dot_name[0] = '.';
dirtemplate.dotdot_ino = h2fs32(dp->i_number);
dirtemplate.dotdot_reclen = h2fs16(VTOI(dvp)->i_e2fs->e2fs_bsize - 12);
dirtemplate.dotdot_namlen = h2fs16(2);
dirtemplate.dotdot_namlen = 2;
if (ip->i_e2fs->e2fs.e2fs_rev > E2FS_REV0 &&
(ip->i_e2fs->e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE)) {
dirtemplate.dotdot_type = IFTODT(EXT2_IFDIR);
}
dirtemplate.dotdot_name[0] = dirtemplate.dotdot_name[1] = '.';
error = vn_rdwr(UIO_WRITE, tvp, (caddr_t)&dirtemplate,
sizeof (dirtemplate), (off_t)0, UIO_SYSSPACE,