summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNiall O'Higgins <niallo@cvs.openbsd.org>2005-04-30 13:56:17 +0000
committerNiall O'Higgins <niallo@cvs.openbsd.org>2005-04-30 13:56:17 +0000
commite723898372517d7a195b4eb18912751f9316ae2e (patch)
tree4a6149adbaa52b0539597497fd19f2cfd9cf066e
parent8153e99f0a02eb7725ff3061033d08113ee83991 (diff)
Support checking filesystems which have or once had large files (>4 GB)
on them. From NetBSD
-rw-r--r--sbin/fsck_ext2fs/dir.c16
-rw-r--r--sbin/fsck_ext2fs/extern.h5
-rw-r--r--sbin/fsck_ext2fs/fsck.h4
-rw-r--r--sbin/fsck_ext2fs/inode.c72
-rw-r--r--sbin/fsck_ext2fs/pass1.c24
-rw-r--r--sbin/fsck_ext2fs/pass2.c8
-rw-r--r--sbin/fsck_ext2fs/pass4.c4
-rw-r--r--sbin/fsck_ext2fs/setup.c5
8 files changed, 94 insertions, 44 deletions
diff --git a/sbin/fsck_ext2fs/dir.c b/sbin/fsck_ext2fs/dir.c
index b67261ba0ec..d6790e5dfdf 100644
--- a/sbin/fsck_ext2fs/dir.c
+++ b/sbin/fsck_ext2fs/dir.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dir.c,v 1.12 2003/07/29 18:38:35 deraadt Exp $ */
+/* $OpenBSD: dir.c,v 1.13 2005/04/30 13:56:15 niallo Exp $ */
/* $NetBSD: dir.c,v 1.5 2000/01/28 16:01:46 bouyer Exp $ */
/*
@@ -363,7 +363,7 @@ linkup(ino_t orphan, ino_t parentdir)
lostdir = (fs2h16(dp->e2di_mode) & IFMT) == IFDIR;
pwarn("UNREF %s ", lostdir ? "DIR" : "FILE");
pinode(orphan);
- if (preen && fs2h32(dp->e2di_size) == 0)
+ if (preen && inosize(dp) == 0)
return (0);
if (preen)
printf(" (RECONNECTED)\n");
@@ -491,9 +491,8 @@ makeentry(ino_t parent, ino_t ino, char *name)
idesc.id_fix = DONTKNOW;
idesc.id_name = name;
dp = ginode(parent);
- if (fs2h32(dp->e2di_size) % sblock.e2fs_bsize) {
- dp->e2di_size =
- h2fs32(roundup(fs2h32(dp->e2di_size), sblock.e2fs_bsize));
+ if (inosize(dp) % sblock.e2fs_bsize) {
+ inossize(dp, roundup(inosize(dp), sblock.e2fs_bsize));
inodirty();
}
if ((ckinode(dp, &idesc) & ALTERED) != 0)
@@ -520,15 +519,15 @@ expanddir(struct ext2fs_dinode *dp, char *name)
exit(8);
}
- lastbn = lblkno(&sblock, fs2h32(dp->e2di_size));
+ lastbn = lblkno(&sblock, inosize(dp));
if (lastbn >= NDADDR - 1 || fs2h32(dp->e2di_blocks[lastbn]) == 0 ||
- fs2h32(dp->e2di_size) == 0)
+ inosize(dp) == 0)
return (0);
if ((newblk = allocblk()) == 0)
return (0);
dp->e2di_blocks[lastbn + 1] = dp->e2di_blocks[lastbn];
dp->e2di_blocks[lastbn] = h2fs32(newblk);
- dp->e2di_size = h2fs32(fs2h32(dp->e2di_size) + sblock.e2fs_bsize);
+ inossize(dp, inosize(dp) + sblock.e2fs_bsize);
dp->e2di_nblock = h2fs32(fs2h32(dp->e2di_nblock) + 1);
bp = getdirblk(fs2h32(dp->e2di_blocks[lastbn + 1]),
sblock.e2fs_bsize);
@@ -558,6 +557,7 @@ bad:
dp->e2di_blocks[lastbn] = dp->e2di_blocks[lastbn + 1];
dp->e2di_blocks[lastbn + 1] = 0;
dp->e2di_size = h2fs32(fs2h32(dp->e2di_size) - sblock.e2fs_bsize);
+ inossize(dp, inosize(dp) - sblock.e2fs_bsize);
dp->e2di_nblock = h2fs32(fs2h32(dp->e2di_nblock) - 1);
freeblk(newblk);
return (0);
diff --git a/sbin/fsck_ext2fs/extern.h b/sbin/fsck_ext2fs/extern.h
index 82f4f70f855..091af9875d7 100644
--- a/sbin/fsck_ext2fs/extern.h
+++ b/sbin/fsck_ext2fs/extern.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: extern.h,v 1.5 2003/04/17 06:48:47 tedu Exp $ */
+/* $OpenBSD: extern.h,v 1.6 2005/04/30 13:56:16 niallo Exp $ */
/* $NetBSD: extern.h,v 1.1 1997/06/11 11:21:46 bouyer Exp $ */
/*
@@ -35,7 +35,6 @@ void bufinit(void);
void bwrite(int, char *, daddr_t, long);
void cacheino(struct ext2fs_dinode *, ino_t);
int changeino(ino_t, char *, ino_t);
-struct fstab;
int chkrange(daddr_t, int);
void ckfini(int);
int ckinode(struct ext2fs_dinode *, struct inodesc *);
@@ -55,6 +54,8 @@ int ftypeok(struct ext2fs_dinode *);
void getpathname(char *, size_t, ino_t, ino_t);
void inocleanup(void);
void inodirty(void);
+u_int64_t inosize(struct ext2fs_dinode *);
+void inossize(struct ext2fs_dinode *, u_int64_t);
int linkup(ino_t, ino_t);
int makeentry(ino_t, ino_t, char *);
void pass1(void);
diff --git a/sbin/fsck_ext2fs/fsck.h b/sbin/fsck_ext2fs/fsck.h
index f01bb88b8d9..88a54cd1f6c 100644
--- a/sbin/fsck_ext2fs/fsck.h
+++ b/sbin/fsck_ext2fs/fsck.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: fsck.h,v 1.8 2003/06/02 20:06:15 millert Exp $ */
+/* $OpenBSD: fsck.h,v 1.9 2005/04/30 13:56:16 niallo Exp $ */
/* $NetBSD: fsck.h,v 1.1 1997/06/11 11:21:47 bouyer Exp $ */
/*
@@ -155,7 +155,7 @@ struct inoinfo {
ino_t i_number; /* inode number of this entry */
ino_t i_parent; /* inode number of parent */
ino_t i_dotdot; /* inode number of `..' */
- size_t i_isize; /* size of inode */
+ u_int64_t i_isize; /* size of inode */
u_int i_numblks; /* size of block array in bytes */
daddr_t i_blks[1]; /* actually longer */
} **inphead, **inpsort;
diff --git a/sbin/fsck_ext2fs/inode.c b/sbin/fsck_ext2fs/inode.c
index 1b6fa1ac251..69c34bcfbc2 100644
--- a/sbin/fsck_ext2fs/inode.c
+++ b/sbin/fsck_ext2fs/inode.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: inode.c,v 1.14 2003/07/29 18:38:35 deraadt Exp $ */
+/* $OpenBSD: inode.c,v 1.15 2005/04/30 13:56:16 niallo Exp $ */
/* $NetBSD: inode.c,v 1.8 2000/01/28 16:01:46 bouyer Exp $ */
/*
@@ -62,6 +62,53 @@
static ino_t startinum;
static int iblock(struct inodesc *, long, u_int64_t);
+static int setlarge(void);
+
+static int
+setlarge(void)
+{
+ if (sblock.e2fs.e2fs_rev < E2FS_REV1) {
+ pfatal("LARGE FILES UNSUPPORTED ON REVISION 0 FILESYSTEMS");
+ return 0;
+ }
+ if (!(sblock.e2fs.e2fs_features_rocompat & EXT2F_ROCOMPAT_LARGEFILE)) {
+ if (preen)
+ pwarn("SETTING LARGE FILE INDICATOR\n");
+ else if (!reply("SET LARGE FILE INDICATOR"))
+ return 0;
+ sblock.e2fs.e2fs_features_rocompat |= EXT2F_ROCOMPAT_LARGEFILE;
+ sbdirty();
+ }
+ return 1;
+}
+
+u_int64_t
+inosize(struct ext2fs_dinode *dp)
+{
+ u_int64_t size = fs2h32(dp->e2di_size);
+
+ if ((fs2h16(dp->e2di_mode) & IFMT) == IFREG)
+ size |= (u_int64_t)fs2h32(dp->e2di_dacl) << 32;
+ if (size >= 0x80000000U)
+ (void)setlarge();
+ return size;
+}
+
+void
+inossize(struct ext2fs_dinode *dp, u_int64_t size)
+{
+ if ((fs2h16(dp->e2di_mode) & IFMT) == IFREG) {
+ dp->e2di_dacl = h2fs32(size >> 32);
+ if (size >= 0x80000000U)
+ if (!setlarge())
+ return;
+ } else if (size >= 0x80000000U) {
+ pfatal("TRYING TO SET FILESIZE TO %llu ON MODE %x FILE\n",
+ (unsigned long long)size, fs2h16(dp->e2di_mode) & IFMT);
+ return;
+ }
+ dp->e2di_size = h2fs32(size);
+}
int
ckinode(struct ext2fs_dinode *dp, struct inodesc *idesc)
@@ -76,13 +123,13 @@ ckinode(struct ext2fs_dinode *dp, struct inodesc *idesc)
if (idesc->id_fix != IGNORE)
idesc->id_fix = DONTKNOW;
idesc->id_entryno = 0;
- idesc->id_filesize = fs2h32(dp->e2di_size);
+ idesc->id_filesize = inosize(dp);
mode = fs2h16(dp->e2di_mode) & IFMT;
if (mode == IFBLK || mode == IFCHR || mode == IFIFO ||
- (mode == IFLNK && (fs2h32(dp->e2di_size) < EXT2_MAXSYMLINKLEN)))
+ (mode == IFLNK && (inosize(dp) < EXT2_MAXSYMLINKLEN)))
return (KEEPON);
dino = *dp;
- ndb = howmany(fs2h32(dino.e2di_size), sblock.e2fs_bsize);
+ ndb = howmany(inosize(&dino), sblock.e2fs_bsize);
for (ap = &dino.e2di_blocks[0]; ap < &dino.e2di_blocks[NDADDR];
ap++,ndb--) {
idesc->id_numfrags = 1;
@@ -95,7 +142,8 @@ ckinode(struct ext2fs_dinode *dp, struct inodesc *idesc)
pathbuf);
if (reply("ADJUST LENGTH") == 1) {
dp = ginode(idesc->id_number);
- dp->e2di_size = h2fs32((ap - &dino.e2di_blocks[0]) *
+ inossize(dp,
+ (ap - &dino.e2di_blocks[0]) *
sblock.e2fs_bsize);
printf(
"YOU MUST RERUN FSCK AFTERWARDS\n");
@@ -114,7 +162,7 @@ ckinode(struct ext2fs_dinode *dp, struct inodesc *idesc)
return (ret);
}
idesc->id_numfrags = 1;
- remsize = fs2h32(dino.e2di_size) - sblock.e2fs_bsize * NDADDR;
+ remsize = inosize(&dino) - sblock.e2fs_bsize * NDADDR;
sizepb = sblock.e2fs_bsize;
for (ap = &dino.e2di_blocks[NDADDR], n = 1; n <= NIADDR; ap++, n++) {
if (*ap) {
@@ -131,7 +179,7 @@ ckinode(struct ext2fs_dinode *dp, struct inodesc *idesc)
pathbuf);
if (reply("ADJUST LENGTH") == 1) {
dp = ginode(idesc->id_number);
- dp->e2di_size = h2fs32(fs2h32(dp->e2di_size) - remsize);
+ inossize(dp, inosize(dp) - remsize);
remsize = 0;
printf(
"YOU MUST RERUN FSCK AFTERWARDS\n");
@@ -211,7 +259,7 @@ iblock(struct inodesc *idesc, long ilevel, u_int64_t isize)
pathbuf);
if (reply("ADJUST LENGTH") == 1) {
dp = ginode(idesc->id_number);
- dp->e2di_size = h2fs32(fs2h32(dp->e2di_size) - isize);
+ inossize(dp, inosize(dp) - isize);
isize = 0;
printf(
"YOU MUST RERUN FSCK AFTERWARDS\n");
@@ -377,7 +425,7 @@ cacheino(struct ext2fs_dinode *dp, ino_t inumber)
struct inoinfo **inpp;
unsigned int blks;
- blks = howmany(fs2h32(dp->e2di_size), sblock.e2fs_bsize);
+ blks = howmany(inosize(dp), sblock.e2fs_bsize);
if (blks > NDADDR)
blks = NDADDR + NIADDR;
inp = (struct inoinfo *)
@@ -394,7 +442,7 @@ cacheino(struct ext2fs_dinode *dp, ino_t inumber)
inp->i_parent = (ino_t)0;
inp->i_dotdot = (ino_t)0;
inp->i_number = inumber;
- inp->i_isize = fs2h32(dp->e2di_size);
+ inp->i_isize = inosize(dp);
inp->i_numblks = blks * sizeof(daddr_t);
memcpy(&inp->i_blks[0], &dp->e2di_blocks[0], (size_t)inp->i_numblks);
if (inplast == listmax) {
@@ -522,7 +570,7 @@ pinode(ino_t ino)
printf("MODE=%o\n", fs2h16(dp->e2di_mode));
if (preen)
printf("%s: ", cdevname());
- printf("SIZE=%u ", fs2h32(dp->e2di_size));
+ printf("SIZE=%llu ", (long long)inosize(dp));
t = fs2h32(dp->e2di_mtime);
p = ctime(&t);
printf("MTIME=%12.12s %4.4s ", &p[4], &p[20]);
@@ -598,7 +646,7 @@ allocino(ino_t request, int type)
dp->e2di_atime = h2fs32(t);
dp->e2di_mtime = dp->e2di_ctime = dp->e2di_atime;
dp->e2di_dtime = 0;
- dp->e2di_size = h2fs32(sblock.e2fs_bsize);
+ inossize(dp, sblock.e2fs_bsize);
dp->e2di_nblock = h2fs32(btodb(sblock.e2fs_bsize));
n_files++;
inodirty();
diff --git a/sbin/fsck_ext2fs/pass1.c b/sbin/fsck_ext2fs/pass1.c
index 15805efc916..e32a79030eb 100644
--- a/sbin/fsck_ext2fs/pass1.c
+++ b/sbin/fsck_ext2fs/pass1.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pass1.c,v 1.10 2003/06/11 06:22:13 deraadt Exp $ */
+/* $OpenBSD: pass1.c,v 1.11 2005/04/30 13:56:16 niallo Exp $ */
/* $NetBSD: pass1.c,v 1.9 2000/01/31 11:40:12 bouyer Exp $ */
/*
@@ -135,7 +135,7 @@ checkinode(ino_t inumber, struct inodesc *idesc)
if (mode == 0 && (
memcmp(dp->e2di_blocks, zino.e2di_blocks,
(NDADDR + NIADDR) * sizeof(u_int32_t)) ||
- dp->e2di_mode || dp->e2di_size)) {
+ dp->e2di_mode || inosize(dp))) {
pfatal("PARTIALLY ALLOCATED INODE I=%u", inumber);
if (reply("CLEAR") == 1) {
dp = ginode(inumber);
@@ -175,24 +175,22 @@ checkinode(ino_t inumber, struct inodesc *idesc)
inodirty();
}
}
- if (/* dp->di_size < 0 || */
- fs2h32(dp->e2di_size) + sblock.e2fs_bsize - 1 <
- fs2h32(dp->e2di_size)) {
+ if (inosize(dp) + sblock.e2fs_bsize - 1 < inosize(dp)) {
if (debug)
- printf("bad size %lu:", (u_long)fs2h32(dp->e2di_size));
+ printf("bad size %llu:", (unsigned long long)inosize(dp));
goto unknown;
}
if (!preen && mode == IFMT && reply("HOLD BAD BLOCK") == 1) {
dp = ginode(inumber);
- dp->e2di_size = h2fs32(sblock.e2fs_bsize);
dp->e2di_mode = h2fs16(IFREG|0600);
+ inossize(dp, sblock.e2fs_bsize);
inodirty();
}
- ndb = howmany(fs2h32(dp->e2di_size), sblock.e2fs_bsize);
+ ndb = howmany(inosize(dp), sblock.e2fs_bsize);
if (ndb < 0) {
if (debug)
- printf("bad size %lu ndb %d:",
- (u_long)fs2h32(dp->e2di_size), ndb);
+ printf("bad size %llu ndb %d:",
+ (unsigned long long)inosize(dp), ndb);
goto unknown;
}
if (mode == IFBLK || mode == IFCHR)
@@ -202,9 +200,9 @@ checkinode(ino_t inumber, struct inodesc *idesc)
* Fake ndb value so direct/indirect block checks below
* will detect any garbage after symlink string.
*/
- if (fs2h32(dp->e2di_size) < EXT2_MAXSYMLINKLEN ||
+ if (inosize(dp) < EXT2_MAXSYMLINKLEN ||
(EXT2_MAXSYMLINKLEN == 0 && dp->e2di_blocks == 0)) {
- ndb = howmany(fs2h32(dp->e2di_size), sizeof(u_int32_t));
+ ndb = howmany(inosize(dp), sizeof(u_int32_t));
if (ndb > NDADDR) {
j = ndb - NDADDR;
for (ndb = 1; j > 1; j--)
@@ -250,7 +248,7 @@ checkinode(ino_t inumber, struct inodesc *idesc)
}
}
if (mode == IFDIR) {
- if (dp->e2di_size == 0)
+ if (inosize(dp) == 0)
statemap[inumber] = DCLEAR;
else
statemap[inumber] = DSTATE;
diff --git a/sbin/fsck_ext2fs/pass2.c b/sbin/fsck_ext2fs/pass2.c
index 5dc7fcd5892..828726978f1 100644
--- a/sbin/fsck_ext2fs/pass2.c
+++ b/sbin/fsck_ext2fs/pass2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pass2.c,v 1.10 2003/06/11 06:22:13 deraadt Exp $ */
+/* $OpenBSD: pass2.c,v 1.11 2005/04/30 13:56:16 niallo Exp $ */
/* $NetBSD: pass2.c,v 1.6 2000/01/28 16:01:46 bouyer Exp $ */
/*
@@ -127,7 +127,7 @@ pass2(void)
inp->i_isize = roundup(MINDIRSIZE, sblock.e2fs_bsize);
if (reply("FIX") == 1) {
dp = ginode(inp->i_number);
- dp->e2di_size = h2fs32(inp->i_isize);
+ inossize(dp, inp->i_isize);
inodirty();
}
} else if ((inp->i_isize & (sblock.e2fs_bsize - 1)) != 0) {
@@ -140,13 +140,13 @@ pass2(void)
inp->i_isize = roundup(inp->i_isize, sblock.e2fs_bsize);
if (preen || reply("ADJUST") == 1) {
dp = ginode(inp->i_number);
- dp->e2di_size = h2fs32(inp->i_isize);
+ inossize(dp, inp->i_isize);
inodirty();
}
}
memset(&dino, 0, sizeof(struct ext2fs_dinode));
dino.e2di_mode = h2fs16(IFDIR);
- dino.e2di_size = h2fs32(inp->i_isize);
+ inossize(&dino, inp->i_isize);
memcpy(&dino.e2di_blocks[0], &inp->i_blks[0], (size_t)inp->i_numblks);
curino.id_number = inp->i_number;
curino.id_parent = inp->i_parent;
diff --git a/sbin/fsck_ext2fs/pass4.c b/sbin/fsck_ext2fs/pass4.c
index 8cb0edff0ba..6c363d268c9 100644
--- a/sbin/fsck_ext2fs/pass4.c
+++ b/sbin/fsck_ext2fs/pass4.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pass4.c,v 1.6 2003/06/11 06:22:13 deraadt Exp $ */
+/* $OpenBSD: pass4.c,v 1.7 2005/04/30 13:56:16 niallo Exp $ */
/* $NetBSD: pass4.c,v 1.2 1997/09/14 14:27:29 lukem Exp $ */
/*
@@ -84,7 +84,7 @@ pass4(void)
case DCLEAR:
dp = ginode(inumber);
- if (dp->e2di_size == 0) {
+ if (inosize(dp) == 0) {
clri(&idesc, "ZERO LENGTH", 1);
break;
}
diff --git a/sbin/fsck_ext2fs/setup.c b/sbin/fsck_ext2fs/setup.c
index 5156cdf29d6..7a3767982bf 100644
--- a/sbin/fsck_ext2fs/setup.c
+++ b/sbin/fsck_ext2fs/setup.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: setup.c,v 1.12 2003/07/29 18:38:35 deraadt Exp $ */
+/* $OpenBSD: setup.c,v 1.13 2005/04/30 13:56:16 niallo Exp $ */
/* $NetBSD: setup.c,v 1.1 1997/06/11 11:22:01 bouyer Exp $ */
/*
@@ -326,6 +326,9 @@ readsb(int 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;
+ asblk.b_un.b_fs->e2fs_features_rocompat &= ~EXT2F_ROCOMPAT_LARGEFILE;
+ asblk.b_un.b_fs->e2fs_features_rocompat |=
+ sblk.b_un.b_fs->e2fs_features_rocompat & EXT2F_ROCOMPAT_LARGEFILE;
if (sblock.e2fs.e2fs_rev > E2FS_REV0 &&
((sblock.e2fs.e2fs_features_incompat & ~EXT2F_INCOMPAT_SUPP) ||
(sblock.e2fs.e2fs_features_rocompat & ~EXT2F_ROCOMPAT_SUPP))) {