Many files:
Checked in e2fsprogs 1.08.
diff --git a/lib/ext2fs/ChangeLog b/lib/ext2fs/ChangeLog
index dd6da6a..e191b7d 100644
--- a/lib/ext2fs/ChangeLog
+++ b/lib/ext2fs/ChangeLog
@@ -1,3 +1,73 @@
+Thu Apr 10 13:15:15 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * dblist.c (ext2fs_set_dir_block): New function which sets the
+ block of a dblist entry, given the directory inode and
+ blockcnt.
+
+Sat Apr 5 12:42:42 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * alloc_tables.c (ext2fs_allocate_tables): Allocate the bitmap and
+ inode bitmaps at staggered locations across the block
+ groups, to avoid concentrating the bitmaps on a small
+ number of disks when using striped RAID arrays.
+
+ * initialize.c (ext2fs_initialize): By default, choose the maximum
+ possible number of blocks per group (based on the size of
+ the bitmaps in the blocksize).
+
+Fri Apr 4 11:28:16 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * initialize.c (ext2fs_initialize): Add support for
+ EXT2_COMPAT_SPARSE_SUPER feature.
+
+ * closefs.c (ext2fs_bg_has_super): New function to determine
+ whether or a particular block group should have a
+ superblock and block group descriptor. Used for the
+ EXT2_COMPAT_SPARSE_SUPER feature is turned on.
+ (ext2fs_flush): Check ext2fs_bg_has_super to see whether
+ or not the superblock should be written out for the block
+ group.
+
+ * ext2fs.h (EXT2_COMPAT_SPARSE_SUPER): Define compatibility flag
+ for sparse duplicate superblocks.
+
+ * version.c (ext2fs_get_library_version): New function which
+ returns the library version.
+
+ * version.c (ext2fs_parse_version_string): New function which
+ parses a version string and returns a version number,
+ so application programs can compare version numbers as
+ integers.
+
+Wed Mar 26 00:43:52 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * icount.c (ext2fs_create_icount): Change function so that it also
+ takes a new argument which contains a "hint" icount
+ structure. This "hint" icount allows the create function
+ to set up the sorted list in advance. This reduces
+ significantly the amount of data moving needed to insert
+ these inodes into the list later.
+
+ * icount.c (ext2fs_icount_validate): New function which validates
+ that the icount structure's rep invariant.
+
+ * icount.c (get_icount_el): Completely revamped implementation
+ to subsume put_icount_el(). Put_icount_el() used to
+ use an O(N) implementation to insert in the middle
+ of the icount list. It now uses a O(ln N) to search
+ for where the icount should be inserted, and then uses
+ a memcpy to move the list down (instead of a for loop).
+
+ * icount.c (ext2fs_icount_fetch, ext2fs_icount_store,
+ ext2fs_icount_increment, ext2fs_icount_decrement): Check
+ to see if the inode is within bounds; if it isn't, return
+ EINVAL.
+
+ * bitops.h (ext2fs_test_generic_bitmap): Fix error message given
+ when a bad inode number is passed to test_generic_bitmap
+ to be EXT2FS_TEST_ERROR instead of the wrong
+ EXT2FS_UNMARK_ERROR.
+
Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o <tytso@mit.edu>
* Release of E2fsprogs version 1.07
diff --git a/lib/ext2fs/Makefile.in b/lib/ext2fs/Makefile.in
index 2867dce..cea8490 100644
--- a/lib/ext2fs/Makefile.in
+++ b/lib/ext2fs/Makefile.in
@@ -50,7 +50,8 @@
test_io.o \
unix_io.o \
unlink.o \
- valid_blk.o
+ valid_blk.o \
+ version.o
SRCS= ext2_err.c \
$(srcdir)/alloc.c \
@@ -95,7 +96,8 @@
$(srcdir)/test_io.c \
$(srcdir)/unix_io.c \
$(srcdir)/unlink.c \
- $(srcdir)/valid_blk.c
+ $(srcdir)/valid_blk.c \
+ $(srcdir)/version.c
HFILES= bitops.h ext2fs.h io.h
@@ -105,21 +107,21 @@
DLL_ADDRESS = 0x66900000
DLL_JUMPSIZE = 0x1000
DLL_GOTSIZE = 0x1000
-DLL_VERSION = 1.1
+DLL_VERSION = 1.2
DLL_IMAGE = libe2fs
DLL_STUB = libext2fs
DLL_LIBS = -L../.. -lcom_err
DLL_MYDIR = ext2fs
DLL_INSTALL_DIR = $(libdir)
-ELF_VERSION = 2.2
+ELF_VERSION = 2.3
ELF_SO_VERSION = 2
ELF_IMAGE = libext2fs
ELF_MYDIR = ext2fs
ELF_INSTALL_DIR = $(libdir)
ELF_OTHER_LIBS = -lc -L../.. -lcom_err
-BSDLIB_VERSION = 2.0
+BSDLIB_VERSION = 2.1
BSDLIB_IMAGE = libext2fs
BSDLIB_MYDIR = ext2fs
BSDLIB_INSTALL_DIR = $(libdir)
diff --git a/lib/ext2fs/alloc_tables.c b/lib/ext2fs/alloc_tables.c
index 97bceef..4bfc91d 100644
--- a/lib/ext2fs/alloc_tables.c
+++ b/lib/ext2fs/alloc_tables.c
@@ -29,37 +29,17 @@
errcode_t ext2fs_allocate_tables(ext2_filsys fs)
{
errcode_t retval;
- blk_t group_blk, last_blk, new_blk, blk;
+ blk_t group_blk, start_blk, last_blk, new_blk, blk;
int i, j;
group_blk = fs->super->s_first_data_block;
for (i = 0; i < fs->group_desc_count; i++) {
last_blk = group_blk + fs->super->s_blocks_per_group;
-
/*
- * Allocate the block bitmap
+ * Allocate the inode table
*/
- retval = ext2fs_get_free_blocks(fs, group_blk, last_blk,
- 1, fs->block_map, &new_blk);
- if (retval)
- return retval;
- ext2fs_mark_block_bitmap(fs->block_map, new_blk);
- fs->group_desc[i].bg_block_bitmap = new_blk;
-
- /*
- * ... and the inode bitmap
- */
- retval = ext2fs_get_free_blocks(fs, group_blk, last_blk,
- 1, fs->block_map, &new_blk);
- if (retval)
- return retval;
- ext2fs_mark_block_bitmap(fs->block_map, new_blk);
- fs->group_desc[i].bg_inode_bitmap = new_blk;
-
- /*
- * Finally, allocate the inode table
- */
- retval = ext2fs_get_free_blocks(fs, group_blk, last_blk,
+ start_blk = group_blk + 3 + fs->desc_blocks;
+ retval = ext2fs_get_free_blocks(fs, start_blk, last_blk,
fs->inode_blocks_per_group,
fs->block_map, &new_blk);
if (retval)
@@ -71,6 +51,25 @@
fs->group_desc[i].bg_inode_table = new_blk;
/*
+ * Allocate the block and inode bitmaps
+ */
+ start_blk += fs->inode_blocks_per_group +
+ ((2 * i) % (last_blk - start_blk));
+ retval = ext2fs_get_free_blocks(fs, start_blk, last_blk,
+ 1, fs->block_map, &new_blk);
+ if (retval)
+ return retval;
+ ext2fs_mark_block_bitmap(fs->block_map, new_blk);
+ fs->group_desc[i].bg_block_bitmap = new_blk;
+
+ retval = ext2fs_get_free_blocks(fs, start_blk, last_blk,
+ 1, fs->block_map, &new_blk);
+ if (retval)
+ return retval;
+ ext2fs_mark_block_bitmap(fs->block_map, new_blk);
+ fs->group_desc[i].bg_inode_bitmap = new_blk;
+
+ /*
* Increment the start of the block group
*/
group_blk += fs->super->s_blocks_per_group;
diff --git a/lib/ext2fs/bitops.h b/lib/ext2fs/bitops.h
index 24bd5a7..a20d395 100644
--- a/lib/ext2fs/bitops.h
+++ b/lib/ext2fs/bitops.h
@@ -353,7 +353,7 @@
blk_t bitno)
{
if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
- ext2fs_warn_bitmap2(bitmap, EXT2FS_UNMARK_ERROR, bitno);
+ ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, bitno);
return 0;
}
return ext2fs_test_bit(bitno - bitmap->start, bitmap->bitmap);
diff --git a/lib/ext2fs/closefs.c b/lib/ext2fs/closefs.c
index e24b6b6..a61f878 100644
--- a/lib/ext2fs/closefs.c
+++ b/lib/ext2fs/closefs.c
@@ -22,6 +22,38 @@
#include "ext2fsP.h"
+static int test_root(int a, int b)
+{
+ if (a == 0)
+ return 1;
+ while (1) {
+ if (a == 1)
+ return 1;
+ if (a % b)
+ return 0;
+ a = a / b;
+ }
+}
+
+int ext2fs_bg_has_super(ext2_filsys fs, int group_block)
+{
+#ifdef EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER
+ struct ext2fs_sb *s;
+
+ s = (struct ext2fs_sb *) fs->super;
+ if (!(s->s_feature_ro_compat & EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER))
+ return 1;
+
+ if (test_root(group_block, 3) || (test_root(group_block, 5)) ||
+ test_root(group_block, 7))
+ return 1;
+
+ return 0;
+#else
+ return 1;
+#endif
+}
+
errcode_t ext2fs_flush(ext2_filsys fs)
{
int i,j,maxgroup;
@@ -92,6 +124,9 @@
maxgroup = (fs->flags & EXT2_FLAG_MASTER_SB_ONLY) ? 1 :
fs->group_desc_count;
for (i = 0; i < maxgroup; i++) {
+ if (!ext2fs_bg_has_super(fs, i))
+ goto next_group;
+
if (i !=0 ) {
retval = io_channel_write_blk(fs->io, group_block,
-SUPERBLOCK_SIZE,
@@ -108,6 +143,7 @@
goto errout;
group_ptr += fs->blocksize;
}
+ next_group:
group_block += EXT2_BLOCKS_PER_GROUP(fs->super);
}
diff --git a/lib/ext2fs/dblist.c b/lib/ext2fs/dblist.c
index 72d5840..76c847f 100644
--- a/lib/ext2fs/dblist.c
+++ b/lib/ext2fs/dblist.c
@@ -128,6 +128,28 @@
}
/*
+ * Change the directory block to the directory block list
+ */
+errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ino_t ino, blk_t blk,
+ int blockcnt)
+{
+ struct ext2_db_entry *ent;
+ int i;
+
+ EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
+
+ for (i=0; i < dblist->count; i++) {
+ if ((dblist->list[i].ino != ino) ||
+ (dblist->list[i].blockcnt != blockcnt))
+ continue;
+ dblist->list[i].blk = blk;
+ dblist->sorted = 0;
+ return 0;
+ }
+ return ENOENT;
+}
+
+/*
* This function iterates over the directory block list
*/
errcode_t ext2fs_dblist_iterate(ext2_dblist dblist,
@@ -151,7 +173,6 @@
if (ret & DBLIST_ABORT)
return 0;
}
-
return 0;
}
diff --git a/lib/ext2fs/dll/jump.funcs b/lib/ext2fs/dll/jump.funcs
index 825844c..6084372 100644
--- a/lib/ext2fs/dll/jump.funcs
+++ b/lib/ext2fs/dll/jump.funcs
@@ -138,3 +138,7 @@
00000000 T _ext2fs_icount_decrement libext2fs icount
00000000 T _ext2fs_icount_store libext2fs icount
00000000 T _ext2fs_get_icount_size libext2fs icount
+00000000 T _ext2fs_create_icount2 libext2fs icount
+00000000 T _ext2fs_get_library_version libext2fs version
+00000000 T _ext2fs_parse_version_string libext2fs version
+00000000 T _ext2fs_set_dir_block libext2fs dblist
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index ce57e13..4e14fd6 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -341,7 +341,19 @@
char s_last_mounted[64]; /* directory where last mounted */
__u32 s_reserved[206]; /* Padding to the end of the block */
};
-
+
+/*
+ * Feature set definitions (that might not be in ext2_fs.h
+ * (was EXT2_COMPAT_SPARSE_SUPER)
+ */
+#ifndef EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER
+#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
+#endif
+
+#define EXT2_LIB_FEATURE_COMPAT_SUPP 0
+#define EXT2_LIB_FEATURE_INCOMPAT_SUPP 0
+#define EXT2_LIB_FEATURE_RO_COMPAT_SUPP EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER
+
/*
* function prototypes
*/
@@ -442,6 +454,7 @@
/* closefs.c */
extern errcode_t ext2fs_close(ext2_filsys fs);
extern errcode_t ext2fs_flush(ext2_filsys fs);
+extern int ext2fs_bg_has_super(ext2_filsys fs, int group_block);
/* cmp_bitmaps.c */
extern errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1,
@@ -461,6 +474,8 @@
struct ext2_db_entry *db_info,
void *private),
void *private);
+errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ino_t ino, blk_t blk,
+ int blockcnt);
/* dblist_dir.c */
extern errcode_t
@@ -544,6 +559,8 @@
/* icount.c */
extern void ext2fs_free_icount(ext2_icount_t icount);
+extern errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags, int size,
+ ext2_icount_t hint, ext2_icount_t *ret);
extern errcode_t ext2fs_create_icount(ext2_filsys fs, int flags, int size,
ext2_icount_t *ret);
extern errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ino_t ino,
@@ -555,6 +572,7 @@
extern errcode_t ext2fs_icount_store(ext2_icount_t icount, ino_t ino,
__u16 count);
extern ino_t ext2fs_get_icount_size(ext2_icount_t icount);
+errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *);
/* ismounted.c */
extern errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags);
@@ -621,7 +639,12 @@
struct ext2_inode *f, int hostorder);
/* valid_blk.c */
-int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode);
+extern int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode);
+
+/* version.c */
+extern int ext2fs_parse_version_string(const char *ver_string);
+extern int ext2fs_get_library_version(const char **ver_string,
+ const char **date_string);
/* inline functions */
extern void ext2fs_mark_super_dirty(ext2_filsys fs);
diff --git a/lib/ext2fs/icount.c b/lib/ext2fs/icount.c
index b9070a9..7c68680 100644
--- a/lib/ext2fs/icount.c
+++ b/lib/ext2fs/icount.c
@@ -71,13 +71,20 @@
free(icount);
}
-errcode_t ext2fs_create_icount(ext2_filsys fs, int flags, int size,
- ext2_icount_t *ret)
+errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags, int size,
+ ext2_icount_t hint, ext2_icount_t *ret)
{
ext2_icount_t icount;
errcode_t retval;
size_t bytes;
+ int i;
+ if (hint) {
+ EXT2_CHECK_MAGIC(hint, EXT2_ET_MAGIC_ICOUNT);
+ if (hint->size > size)
+ size = hint->size;
+ }
+
icount = malloc(sizeof(struct ext2_icount));
if (!icount)
return ENOMEM;
@@ -125,8 +132,18 @@
icount->cursor = 0;
icount->num_inodes = fs->super->s_inodes_count;
- *ret = icount;
+ /*
+ * Populate the sorted list with those entries which were
+ * found in the hint icount (since those are ones which will
+ * likely need to be in the sorted list this time around).
+ */
+ if (hint) {
+ for (i=0; i < hint->count; i++)
+ icount->list[i].ino = hint->list[i].ino;
+ icount->count = hint->count;
+ }
+ *ret = icount;
return 0;
errout:
@@ -134,65 +151,22 @@
return(retval);
}
-/*
- * get_icount_el() --- given an inode number, try to find icount
- * information in the sorted list. We use a binary search...
- */
-static struct ext2_icount_el *get_icount_el(ext2_icount_t icount, ino_t ino)
+errcode_t ext2fs_create_icount(ext2_filsys fs, int flags, int size,
+ ext2_icount_t *ret)
{
- int low, high, mid;
-
- if (!icount || !icount->list || !icount->count)
- return 0;
-
- if (icount->multiple &&
- !ext2fs_test_inode_bitmap(icount->multiple, ino))
- return 0;
-
- low = 0;
- high = icount->count-1;
- if (ino == icount->list[low].ino) {
- icount->cursor = low+1;
- return &icount->list[low];
- }
- if (ino == icount->list[high].ino) {
- icount->cursor = 0;
- return &icount->list[high];
- }
- if (icount->cursor >= icount->count)
- icount->cursor = 0;
- if (ino == icount->list[icount->cursor].ino)
- return &icount->list[icount->cursor++];
-#if 0
- printf("Non-cursor get_icount_el: %u\n", ino);
-#endif
-
- while (low < high) {
- mid = (low+high)/2;
- if (mid == low || mid == high)
- break;
- if (ino == icount->list[mid].ino) {
- icount->cursor = mid;
- return &icount->list[mid];
- }
- if (ino < icount->list[mid].ino)
- high = mid;
- else
- low = mid;
- }
- return 0;
+ return ext2fs_create_icount2(fs, flags, size, 0, ret);
}
/*
- * put_icount_el() --- given an inode number, create a new entry in
- * the sorted list. This function is optimized for adding values
- * in ascending order.
+ * insert_icount_el() --- Insert a new entry into the sorted list at a
+ * specified position.
*/
-static struct ext2_icount_el *put_icount_el(ext2_icount_t icount, ino_t ino)
+static struct ext2_icount_el *insert_icount_el(ext2_icount_t icount,
+ ino_t ino, int pos)
{
struct ext2_icount_el *el, *new_list;
ino_t new_size = 0;
- int i, j;
+ int num;
if (icount->count >= icount->size) {
if (icount->count) {
@@ -212,31 +186,112 @@
icount->size = new_size;
icount->list = new_list;
}
-
- /*
- * Normally, get_icount_el is called with each inode in
- * sequential order; but once in a while (like when pass 3
- * needs to recreate the root directory or lost+found
- * directory) it is called out of order.
- */
- if (icount->count && icount->list[icount->count-1].ino >= ino) {
- for (i = icount->count-1; i > 0; i--)
- if (icount->list[i-1].ino < ino)
- break;
- el = &icount->list[i];
- if (el->ino != ino) {
- for (j = icount->count++; j > i; j--)
- icount->list[j] = icount->list[j-1];
- el->count = 0;
- }
- } else {
- el = &icount->list[icount->count++];
- el->count = 0;
+ num = icount->count - pos;
+ if (num < 0)
+ return 0; /* should never happen */
+ if (num) {
+ memmove(&icount->list[pos+1], &icount->list[pos],
+ sizeof(struct ext2_icount_el) * num);
}
+ icount->count++;
+ el = &icount->list[pos];
+ el->count = 0;
el->ino = ino;
return el;
}
+
+/*
+ * get_icount_el() --- given an inode number, try to find icount
+ * information in the sorted list. If the create flag is set,
+ * and we can't find an entry, create one in the sorted list.
+ */
+static struct ext2_icount_el *get_icount_el(ext2_icount_t icount,
+ ino_t ino, int create)
+{
+ float range;
+ int low, high, mid;
+ ino_t lowval, highval;
+
+ if (!icount || !icount->list)
+ return 0;
+
+ if (create && ((icount->count == 0) ||
+ (ino > icount->list[icount->count-1].ino))) {
+ return insert_icount_el(icount, ino, icount->count);
+ }
+ if (icount->count == 0)
+ return 0;
+ if (icount->cursor >= icount->count)
+ icount->cursor = 0;
+ if (ino == icount->list[icount->cursor].ino)
+ return &icount->list[icount->cursor++];
+#if 0
+ printf("Non-cursor get_icount_el: %u\n", ino);
+#endif
+ low = 0;
+ high = icount->count-1;
+ while (low <= high) {
+#if 0
+ mid = (low+high)/2;
+#else
+ if (low == high)
+ mid = low;
+ else {
+ /* Interpolate for efficiency */
+ lowval = icount->list[low].ino;
+ highval = icount->list[high].ino;
+
+ if (ino < lowval)
+ range = 0;
+ else if (ino > highval)
+ range = 1;
+ else
+ range = ((float) (ino - lowval)) /
+ (highval - lowval);
+ mid = low + ((int) (range * (high-low)));
+ }
+#endif
+ if (ino == icount->list[mid].ino) {
+ icount->cursor = mid+1;
+ return &icount->list[mid];
+ }
+ if (ino < icount->list[mid].ino)
+ high = mid-1;
+ else
+ low = mid+1;
+ }
+ /*
+ * If we need to create a new entry, it should be right at
+ * low (where high will be left at low-1).
+ */
+ if (create)
+ return insert_icount_el(icount, ino, low);
+ return 0;
+}
+
+errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *out)
+{
+ errcode_t ret = 0;
+ int i;
+ const char *bad = "bad icount";
+
+ EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
+
+ if (icount->count > icount->size) {
+ fprintf(out, "%s: count > size\n", bad);
+ return EINVAL;
+ }
+ for (i=1; i < icount->count; i++) {
+ if (icount->list[i-1].ino >= icount->list[i].ino) {
+ fprintf(out, "%s: list[%d].ino=%u, list[%d].ino=%u\n",
+ bad, i-1, icount->list[i-1].ino,
+ i, icount->list[i].ino);
+ ret = EINVAL;
+ }
+ }
+ return ret;
+}
errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ino_t ino, __u16 *ret)
{
@@ -244,11 +299,19 @@
EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
+ if (!ino || (ino > icount->num_inodes))
+ return EINVAL;
+
if (ext2fs_test_inode_bitmap(icount->single, ino)) {
*ret = 1;
return 0;
}
- el = get_icount_el(icount, ino);
+ if (icount->multiple &&
+ !ext2fs_test_inode_bitmap(icount->multiple, ino)) {
+ *ret = 0;
+ return 0;
+ }
+ el = get_icount_el(icount, ino, 0);
if (!el) {
*ret = 0;
return 0;
@@ -264,14 +327,19 @@
EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
+ if (!ino || (ino > icount->num_inodes))
+ return EINVAL;
+
if (ext2fs_test_inode_bitmap(icount->single, ino)) {
/*
* If the existing count is 1, then we know there is
- * no entry in the list, so use put_icount_el().
+ * no entry in the list.
*/
- el = put_icount_el(icount, ino);
+ el = get_icount_el(icount, ino, 1);
if (!el)
return ENOMEM;
+ ext2fs_unmark_inode_bitmap(icount->single, ino);
+ el->count = 2;
} else if (icount->multiple) {
/*
* The count is either zero or greater than 1; if the
@@ -280,13 +348,10 @@
* get_icount_el().
*/
if (ext2fs_test_inode_bitmap(icount->multiple, ino)) {
- el = get_icount_el(icount, ino);
- if (!el) {
- /* should never happen */
- el = put_icount_el(icount, ino);
- if (!el)
- return ENOMEM;
- }
+ el = get_icount_el(icount, ino, 1);
+ if (!el)
+ return ENOMEM;
+ el->count++;
} else {
/*
* The count was zero; mark the single bitmap
@@ -303,20 +368,16 @@
* The count is either zero or greater than 1; try to
* find an entry in the list to determine which.
*/
- el = get_icount_el(icount, ino);
+ el = get_icount_el(icount, ino, 0);
if (!el) {
/* No entry means the count was zero */
goto zero_count;
}
- el = put_icount_el(icount, ino);
+ el = get_icount_el(icount, ino, 1);
if (!el)
return ENOMEM;
- }
- if (ext2fs_test_inode_bitmap(icount->single, ino)) {
- ext2fs_unmark_inode_bitmap(icount->single, ino);
- el->count = 2;
- } else
el->count++;
+ }
if (icount->multiple)
ext2fs_mark_inode_bitmap(icount->multiple, ino);
if (ret)
@@ -329,6 +390,9 @@
{
struct ext2_icount_el *el;
+ if (!ino || (ino > icount->num_inodes))
+ return EINVAL;
+
EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
if (ext2fs_test_inode_bitmap(icount->single, ino)) {
@@ -336,7 +400,7 @@
if (icount->multiple)
ext2fs_unmark_inode_bitmap(icount->multiple, ino);
else {
- el = get_icount_el(icount, ino);
+ el = get_icount_el(icount, ino, 0);
if (el)
el->count = 0;
}
@@ -345,8 +409,12 @@
return 0;
}
- el = get_icount_el(icount, ino);
- if (!el)
+ if (icount->multiple &&
+ !ext2fs_test_inode_bitmap(icount->multiple, ino))
+ return EINVAL;
+
+ el = get_icount_el(icount, ino, 0);
+ if (!el || el->count == 0)
return EINVAL;
el->count--;
@@ -365,6 +433,9 @@
{
struct ext2_icount_el *el;
+ if (!ino || (ino > icount->num_inodes))
+ return EINVAL;
+
EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
if (count == 1) {
@@ -382,7 +453,7 @@
*/
ext2fs_unmark_inode_bitmap(icount->multiple, ino);
} else {
- el = get_icount_el(icount, ino);
+ el = get_icount_el(icount, ino, 0);
if (el)
el->count = 0;
}
@@ -392,7 +463,7 @@
/*
* Get the icount element
*/
- el = put_icount_el(icount, ino);
+ el = get_icount_el(icount, ino, 1);
if (!el)
return ENOMEM;
el->count = count;
diff --git a/lib/ext2fs/initialize.c b/lib/ext2fs/initialize.c
index 6db5a0c..72f40ea 100644
--- a/lib/ext2fs/initialize.c
+++ b/lib/ext2fs/initialize.c
@@ -58,6 +58,7 @@
ext2_filsys fs;
errcode_t retval;
struct ext2_super_block *super;
+ struct ext2fs_sb *s;
int frags_per_block;
int rem;
int overhead = 0;
@@ -91,9 +92,12 @@
goto cleanup;
}
memset(super, 0, SUPERBLOCK_SIZE);
+ s = (struct ext2fs_sb *) super;
#define set_field(field, default) (super->field = param->field ? \
param->field : (default))
+#define set_ext2_field(field, default) (s->field = param->field ? \
+ param->field : (default))
super->s_magic = EXT2_SUPER_MAGIC;
super->s_state = EXT2_VALID_FS;
@@ -103,7 +107,13 @@
set_field(s_first_data_block, super->s_log_block_size ? 0 : 1);
set_field(s_max_mnt_count, EXT2_DFL_MAX_MNT_COUNT);
set_field(s_errors, EXT2_ERRORS_DEFAULT);
-
+ set_ext2_field(s_feature_compat, 0);
+ set_ext2_field(s_feature_incompat, 0);
+ set_ext2_field(s_feature_ro_compat, 0);
+ if (s->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)
+ return EXT2_ET_UNSUPP_FEATURE;
+ if (s->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP)
+ return EXT2_ET_RO_UNSUPP_FEATURE;
#ifdef EXT2_DYNAMIC_REV
set_field(s_rev_level, EXT2_GOOD_OLD_REV);
@@ -122,7 +132,8 @@
fs->fragsize = EXT2_FRAG_SIZE(super);
frags_per_block = fs->blocksize / fs->fragsize;
- set_field(s_blocks_per_group, 8192); /* default: 8192 blocks/group */
+ /* default: (fs->blocksize*8) blocks/group */
+ set_field(s_blocks_per_group, fs->blocksize*8);
super->s_frags_per_group = super->s_blocks_per_group * frags_per_block;
super->s_blocks_count = param->s_blocks_count;
@@ -188,16 +199,6 @@
super->s_free_inodes_count = super->s_inodes_count;
/*
- * Overhead is the number of bookkeeping blocks per group. It
- * includes the superblock backup, the group descriptor
- * backups, the inode bitmap, the block bitmap, and the inode
- * table.
- */
- overhead = 3 + fs->desc_blocks + fs->inode_blocks_per_group;
- super->s_free_blocks_count = super->s_blocks_count -
- super->s_first_data_block - (overhead*fs->group_desc_count);
-
- /*
* See if the last group is big enough to support the
* necessary data structures. If not, we need to get rid of
* it.
@@ -250,11 +251,8 @@
* by this routine), they are accounted for nevertheless.
*/
group_block = super->s_first_data_block;
+ super->s_free_blocks_count = 0;
for (i = 0; i < fs->group_desc_count; i++) {
- for (j=0; j < fs->desc_blocks+1; j++)
- ext2fs_mark_block_bitmap(fs->block_map,
- group_block + j);
-
if (i == fs->group_desc_count-1) {
numblocks = (fs->super->s_blocks_count -
fs->super->s_first_data_block) %
@@ -263,8 +261,17 @@
numblocks = fs->super->s_blocks_per_group;
} else
numblocks = fs->super->s_blocks_per_group;
- numblocks -= 3 + fs->desc_blocks + fs->inode_blocks_per_group;
+
+ if (ext2fs_bg_has_super(fs, i)) {
+ for (j=0; j < fs->desc_blocks+1; j++)
+ ext2fs_mark_block_bitmap(fs->block_map,
+ group_block + j);
+ numblocks -= 1 + fs->desc_blocks;
+ }
+ numblocks -= 2 + fs->inode_blocks_per_group;
+
+ super->s_free_blocks_count += numblocks;
fs->group_desc[i].bg_free_blocks_count = numblocks;
fs->group_desc[i].bg_free_inodes_count =
fs->super->s_inodes_per_group;
diff --git a/lib/ext2fs/inode.c b/lib/ext2fs/inode.c
index 8fd5e7e..7194fb0 100644
--- a/lib/ext2fs/inode.c
+++ b/lib/ext2fs/inode.c
@@ -51,6 +51,7 @@
{
ext2_inode_scan scan;
errcode_t retval;
+ errcode_t (*save_get_blocks)(ext2_filsys fs, ino_t ino, blk_t *blocks);
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
@@ -59,11 +60,18 @@
* scanning functions require it.
*/
if (fs->badblocks == 0) {
+ /*
+ * Temporarly save fs->get_blocks and set it to zero,
+ * for compatibility with old e2fsck's.
+ */
+ save_get_blocks = fs->get_blocks;
+ fs->get_blocks = 0;
retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
if (retval && fs->badblocks) {
badblocks_list_free(fs->badblocks);
fs->badblocks = 0;
}
+ fs->get_blocks = save_get_blocks;
}
scan = (ext2_inode_scan) malloc(sizeof(struct ext2_struct_inode_scan));
diff --git a/lib/ext2fs/openfs.c b/lib/ext2fs/openfs.c
index b2e2393..a1c0d5b 100644
--- a/lib/ext2fs/openfs.c
+++ b/lib/ext2fs/openfs.c
@@ -126,12 +126,13 @@
*/
if (!(flags & EXT2_FLAG_FORCE)) {
s = (struct ext2fs_sb *) fs->super;
- if (s->s_feature_incompat) {
+ if (s->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP) {
retval = EXT2_ET_UNSUPP_FEATURE;
goto cleanup;
}
if ((flags & EXT2_FLAG_RW) &&
- s->s_feature_ro_compat) {
+ (s->s_feature_ro_compat &
+ ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP)) {
retval = EXT2_ET_RO_UNSUPP_FEATURE;
goto cleanup;
}
diff --git a/lib/ext2fs/version.c b/lib/ext2fs/version.c
new file mode 100644
index 0000000..df7236e
--- /dev/null
+++ b/lib/ext2fs/version.c
@@ -0,0 +1,53 @@
+/*
+ * version.c --- Return the version of the ext2 library
+ *
+ * Copyright (C) 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <et/com_err.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include <linux/ext2_fs.h>
+#include "ext2fs.h"
+
+#include "../../version.h"
+
+static const char *lib_version = E2FSPROGS_VERSION;
+static const char *lib_date = E2FSPROGS_DATE;
+
+int ext2fs_parse_version_string(const char *ver_string)
+{
+ const char *cp;
+ int version = 0;
+
+ for (cp = lib_version; *cp; cp++) {
+ if (!isdigit(*cp))
+ continue;
+ version = (version * 10) + (*cp - '0');
+ }
+ return version;
+}
+
+
+int ext2fs_get_library_version(const char **ver_string,
+ const char **date_string)
+{
+ if (ver_string)
+ *ver_string = lib_version;
+ if (date_string)
+ *date_string = lib_date;
+
+ return ext2fs_parse_version_string(lib_version);
+}