Many files:
Checked in e2fsprogs-1.07
diff --git a/lib/ext2fs/dll/jump.funcs b/lib/ext2fs/dll/jump.funcs
index 489bd62..825844c 100644
--- a/lib/ext2fs/dll/jump.funcs
+++ b/lib/ext2fs/dll/jump.funcs
@@ -71,7 +71,7 @@
00000000 T _ext2fs_update_bb_inode libext2fs bb_inode
00000000 T _ext2fs_read_bb_FILE libext2fs read_bb_file
00000000 T _initialize_ext2_error_table libext2fs ext2_err
-00000000 T _ext2_llseek libext2fs llseek
+00000000 T _ext2fs_llseek libext2fs llseek
00000000 T _ext2fs_set_inode_callback libext2fs inode
00000000 T _ext2fs_compare_block_bitmap libext2fs cmp_bitmaps
00000000 T _ext2fs_compare_inode_bitmap libext2fs cmp_bitmaps
@@ -93,3 +93,48 @@
00000000 T _ext2fs_swap_group_desc libext2fs swapfs
00000000 T _ext2fs_get_device_size libext2fs getsize
00000000 T _ext2fs_check_if_mounted libext2fs ismounted
+00000000 T _ext2fs_allocate_tables libext2fs alloc_tables
+00000000 T _ext2fs_allocate_generic_bitmap libext2fs bitmaps
+00000000 T _ext2fs_warn_bitmap2 libext2fs bitops
+00000000 T _ext2fs_free_generic_bitmap libext2fs freefs
+00000000 T _ext2fs_mark_generic_bitmap libext2fs inline
+00000000 T _ext2fs_unmark_generic_bitmap libext2fs inline
+00000000 T _ext2fs_test_generic_bitmap libext2fs inline
+00000000 T _ext2fs_namei_follow libext2fs namei
+00000000 T _ext2fs_follow_link libext2fs namei
+00000000 T _ext2fs_native_flag libext2fs native
+00000000 T _ext2fs_swap_inode libext2fs swapfs
+00000000 T _ext2fs_block_iterate2 libext2fs block
+00000000 T _ext2fs_inode_scan_goto_blockgroup libext2fs inode
+00000000 T _ext2fs_badblocks_list_create libext2fs badblocks
+00000000 T _ext2fs_badblocks_list_add libext2fs badblocks
+00000000 T _ext2fs_badblocks_list_test libext2fs badblocks
+00000000 T _ext2fs_badblocks_list_iterate_begin libext2fs badblocks
+00000000 T _ext2fs_badblocks_list_iterate libext2fs badblocks
+00000000 T _ext2fs_badblocks_list_iterate_end libext2fs badblocks
+00000000 T _ext2fs_brel_memarray_create libext2fs brel_ma
+00000000 T _ext2fs_badblocks_list_free libext2fs closefs
+00000000 T _ext2fs_free_dblist libext2fs closefs
+00000000 T _ext2fs_get_num_dirs libext2fs dblist
+00000000 T _ext2fs_init_dblist libext2fs dblist
+00000000 T _ext2fs_add_dir_block libext2fs dblist
+00000000 T _ext2fs_dblist_iterate libext2fs dblist
+00000000 T _ext2fs_dblist_dir_iterate libext2fs dblist_dir
+00000000 T _ext2fs_process_dir_block libext2fs dir_iterate
+00000000 T _ext2fs_test_block_bitmap_range libext2fs inline
+00000000 T _ext2fs_fast_test_block_bitmap_range libext2fs inline
+00000000 T _ext2fs_mark_block_bitmap_range libext2fs inline
+00000000 T _ext2fs_fast_mark_block_bitmap_range libext2fs inline
+00000000 T _ext2fs_unmark_block_bitmap_range libext2fs inline
+00000000 T _ext2fs_fast_unmark_block_bitmap_range libext2fs inline
+00000000 T _ext2fs_inode_scan_flags libext2fs inode
+00000000 T _ext2fs_irel_memarray_create libext2fs irel_ma
+00000000 T _ext2fs_resize_generic_bitmap libext2fs rs_bitmap
+00000000 T _ext2fs_inode_has_valid_blocks libext2fs valid_blk
+00000000 T _ext2fs_free_icount libext2fs icount
+00000000 T _ext2fs_create_icount libext2fs icount
+00000000 T _ext2fs_icount_fetch libext2fs icount
+00000000 T _ext2fs_icount_increment libext2fs icount
+00000000 T _ext2fs_icount_decrement libext2fs icount
+00000000 T _ext2fs_icount_store libext2fs icount
+00000000 T _ext2fs_get_icount_size libext2fs icount
diff --git a/lib/ext2fs/dll/jump.vars b/lib/ext2fs/dll/jump.vars
index edbbf7c..5f219d3 100644
--- a/lib/ext2fs/dll/jump.vars
+++ b/lib/ext2fs/dll/jump.vars
@@ -1 +1,6 @@
00000004 D _unix_io_manager libext2fs unix_io
+00000004 D _test_io_manager libext2fs test_io
+00000004 D _test_io_backing_manager libext2fs test_io
+00000004 D _test_io_cb_read_blk libext2fs test_io
+00000004 D _test_io_cb_write_blk libext2fs test_io
+00000004 D _test_io_cb_set_blksize libext2fs test_io
diff --git a/lib/ext2fs/expanddir.c b/lib/ext2fs/expanddir.c
index b2597c9..852b40f 100644
--- a/lib/ext2fs/expanddir.c
+++ b/lib/ext2fs/expanddir.c
@@ -1,8 +1,12 @@
/*
* expand.c --- expand an ext2fs directory
*
- * Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
- * under the terms of the GNU Public License.
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
#include <stdio.h>
diff --git a/lib/ext2fs/ext2_err.et.in b/lib/ext2fs/ext2_err.et.in
index 81e0c1e..075acee 100644
--- a/lib/ext2fs/ext2_err.et.in
+++ b/lib/ext2fs/ext2_err.et.in
@@ -1,6 +1,10 @@
#
-# Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. This file may be
-# redistributed under the terms of the GNU Public License.
+# Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+#
+# %Begin-Header%
+# This file may be redistributed under the terms of the GNU Public
+# License.
+# %End-Header%
#
error_table ext2
@@ -37,14 +41,14 @@
ec EXT2_ET_MAGIC_GENERIC_BITMAP,
"Wrong magic number for generic_bitmap structure"
-ec EXT2_ET_MAGIC_RESERVED_2,
- "Wrong magic number --- RESERVED_2"
+ec EXT2_ET_MAGIC_TEST_IO_CHANNEL,
+ "Wrong magic number for test io_channel structure"
-ec EXT2_ET_MAGIC_RESERVED_3,
- "Wrong magic number --- RESERVED_3"
+ec EXT2_ET_MAGIC_DBLIST,
+ "Wrong magic number for directory block list structure"
-ec EXT2_ET_MAGIC_RESERVED_4,
- "Wrong magic number --- RESERVED_4"
+ec EXT2_ET_MAGIC_ICOUNT,
+ "Wrong magic number for icount structure"
ec EXT2_ET_MAGIC_RESERVED_5,
"Wrong magic number --- RESERVED_5"
@@ -211,4 +215,13 @@
ec EXT2_ET_CALLBACK_NOTHANDLED,
"The callback function will not handle this case"
+ec EXT2_ET_BAD_BLOCK_IN_INODE_TABLE,
+ "The inode is from a bad block in the inode table"
+
+ec EXT2_ET_UNSUPP_FEATURE,
+ "Filesystem has unsupported feature(s)"
+
+ec EXT2_ET_RO_UNSUPP_FEATURE,
+ "Filesystem has unsupported read-only feature(s)"
+
end
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index de74681..ce57e13 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -1,11 +1,22 @@
/*
* ext2fs.h --- ext2fs
*
- * Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
- * under the terms of the GNU Public License.
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
/*
+ * Non-GNU C compilers won't necessarily understand inline
+ */
+#ifndef __GNUC__
+#define NO_INLINE_FUNCS
+#endif
+
+/*
* Where the master copy of the superblock is located, and how big
* superblocks are supposed to be. We define SUPERBLOCK_SIZE because
* the size of the superblock structure is not necessarily trustworthy
@@ -49,9 +60,7 @@
#define EXT2FS_TEST_ERROR 2
typedef struct ext2fs_struct_generic_bitmap *ext2fs_generic_bitmap;
-
typedef struct ext2fs_struct_generic_bitmap *ext2fs_inode_bitmap;
-
typedef struct ext2fs_struct_generic_bitmap *ext2fs_block_bitmap;
#ifdef EXT2_DYNAMIC_REV
@@ -62,19 +71,46 @@
#endif
/*
+ * badblocks list definitions
+ */
+
+typedef struct ext2_struct_badblocks_list *ext2_badblocks_list;
+typedef struct ext2_struct_badblocks_iterate *ext2_badblocks_iterate;
+
+/* old */
+typedef struct ext2_struct_badblocks_list *badblocks_list;
+typedef struct ext2_struct_badblocks_iterate *badblocks_iterate;
+
+#define BADBLOCKS_FLAG_DIRTY 1
+
+/*
+ * ext2_dblist structure and abstractions (see dblist.c)
+ */
+struct ext2_db_entry {
+ ino_t ino;
+ blk_t blk;
+ int blockcnt;
+};
+
+typedef struct ext2_struct_dblist *ext2_dblist;
+
+#define DBLIST_ABORT 1
+
+/*
* Flags for the ext2_filsys structure
*/
-#define EXT2_FLAG_RW 0x01
-#define EXT2_FLAG_CHANGED 0x02
-#define EXT2_FLAG_DIRTY 0x04
-#define EXT2_FLAG_VALID 0x08
-#define EXT2_FLAG_IB_DIRTY 0x10
-#define EXT2_FLAG_BB_DIRTY 0x20
+#define EXT2_FLAG_RW 0x01
+#define EXT2_FLAG_CHANGED 0x02
+#define EXT2_FLAG_DIRTY 0x04
+#define EXT2_FLAG_VALID 0x08
+#define EXT2_FLAG_IB_DIRTY 0x10
+#define EXT2_FLAG_BB_DIRTY 0x20
#define EXT2_FLAG_SWAP_BYTES 0x40
#define EXT2_FLAG_SWAP_BYTES_READ 0x80
#define EXT2_FLAG_SWAP_BYTES_WRITE 0x100
#define EXT2_FLAG_MASTER_SB_ONLY 0x200
+#define EXT2_FLAG_FORCE 0x400
/*
* Special flag in the ext2 inode i_flag field that means that this is
@@ -103,7 +139,12 @@
struct ext2_inode *inode);
errcode_t (*write_inode)(ext2_filsys fs, ino_t ino,
struct ext2_inode *inode);
- __u32 reserved[14];
+ badblocks_list badblocks;
+ ext2_dblist dblist;
+ /*
+ * Reserved for future expansion
+ */
+ __u32 reserved[12];
/*
* Not used by ext2fs library; reserved for the use of the
@@ -112,32 +153,6 @@
void * private;
};
-/*
- * badblocks list definitions
- */
-
-typedef struct struct_badblocks_list *badblocks_list;
-
-struct struct_badblocks_list {
- int magic;
- int num;
- int size;
- blk_t *list;
- int badblocks_flags;
- int reserved[8];
-};
-
-#define BADBLOCKS_FLAG_DIRTY 1
-
-typedef struct struct_badblocks_iterate *badblocks_iterate;
-
-struct struct_badblocks_iterate {
- int magic;
- badblocks_list bb;
- int ptr;
- int reserved[8];
-};
-
#include "ext2fs/bitops.h"
/*
@@ -191,38 +206,30 @@
#define DIRENT_FLAG_INCLUDE_EMPTY 1
+
+#define DIRENT_DOT_FILE 1
+#define DIRENT_DOT_DOT_FILE 2
+#define DIRENT_OTHER_FILE 3
+
/*
* Inode scan definitions
*/
typedef struct ext2_struct_inode_scan *ext2_inode_scan;
-struct ext2_struct_inode_scan {
- int magic;
- ext2_filsys fs;
- ino_t current_inode;
- blk_t current_block;
- dgrp_t current_group;
- int inodes_left, blocks_left, groups_left;
- int inode_buffer_blocks;
- char * inode_buffer;
- int inode_size;
- char * ptr;
- int bytes_left;
- char *temp_buffer;
- errcode_t (*done_group)(ext2_filsys fs,
- ext2_inode_scan scan,
- dgrp_t group,
- void * private);
- void * done_group_data;
- int reserved[8];
-};
+/*
+ * ext2fs_scan flags
+ */
+#define EXT2_SF_CHK_BADBLOCKS 0x0001
+#define EXT2_SF_BAD_INODE_BLK 0x0002
+#define EXT2_SF_BAD_EXTRA_BYTES 0x0004
+#define EXT2_SF_SKIP_MISSING_ITABLE 0x0008
/*
* ext2fs_check_if_mounted flags
*/
#define EXT2_MF_MOUNTED 1
#define EXT2_MF_ISROOT 2
-#define EXT2_MF_READONLY 4
+#define EXT2_MF_READONLY 4
/*
* Ext2/linux mode flags. We define them here so that we don't need
@@ -265,6 +272,13 @@
#define LINUX_S_ISSOCK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFSOCK)
/*
+ * ext2_icount_t abstraction
+ */
+#define EXT2_ICOUNT_OPT_INCREMENT 0x01
+
+typedef struct ext2_icount *ext2_icount_t;
+
+/*
* For checking structure magic numbers...
*/
@@ -342,7 +356,25 @@
ext2fs_block_bitmap map,
blk_t *ret);
+/* allocate_tables.c */
+errcode_t ext2fs_allocate_tables(ext2_filsys fs);
+
/* badblocks.c */
+extern errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret,
+ int size);
+extern void ext2fs_badblocks_list_free(ext2_badblocks_list bb);
+extern errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb,
+ blk_t blk);
+extern int ext2fs_badblocks_list_test(ext2_badblocks_list bb,
+ blk_t blk);
+extern errcode_t
+ ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb,
+ ext2_badblocks_iterate *ret);
+extern int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter,
+ blk_t *blk);
+extern void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter);
+
+/* bb_compat */
extern errcode_t badblocks_list_create(badblocks_list *ret, int size);
extern void badblocks_list_free(badblocks_list bb);
extern errcode_t badblocks_list_add(badblocks_list bb, blk_t blk);
@@ -354,7 +386,7 @@
/* bb_inode.c */
extern errcode_t ext2fs_update_bb_inode(ext2_filsys fs,
- badblocks_list bb_list);
+ ext2_badblocks_list bb_list);
/* bitmaps.c */
extern errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs);
@@ -392,6 +424,18 @@
void *private),
void *private);
+errcode_t ext2fs_block_iterate2(ext2_filsys fs,
+ ino_t ino,
+ int flags,
+ char *block_buf,
+ int (*func)(ext2_filsys fs,
+ blk_t *blocknr,
+ int blockcnt,
+ blk_t ref_blk,
+ int ref_offset,
+ void *private),
+ void *private);
+
/* check_desc.c */
extern errcode_t ext2fs_check_desc(ext2_filsys fs);
@@ -405,6 +449,32 @@
extern errcode_t ext2fs_compare_inode_bitmap(ext2fs_inode_bitmap bm1,
ext2fs_inode_bitmap bm2);
+/* dblist.c */
+
+errcode_t ext2fs_get_num_dirs(ext2_filsys fs, ino_t *ret_num_dirs);
+errcode_t ext2fs_init_dblist(ext2_filsys fs, ext2_dblist *ret_dblist);
+void ext2fs_free_dblist(ext2_dblist dblist);
+errcode_t ext2fs_add_dir_block(ext2_dblist dblist, ino_t ino, blk_t blk,
+ int blockcnt);
+errcode_t ext2fs_dblist_iterate(ext2_dblist dblist,
+ int (*func)(ext2_filsys fs,
+ struct ext2_db_entry *db_info,
+ void *private),
+ void *private);
+
+/* dblist_dir.c */
+extern errcode_t
+ ext2fs_dblist_dir_iterate(ext2_dblist dblist,
+ int flags,
+ char *block_buf,
+ int (*func)(ino_t dir,
+ int entry,
+ struct ext2_dir_entry *dirent,
+ int offset,
+ int blocksize,
+ char *buf,
+ void *private),
+ void *private);
/* dirblock.c */
extern errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
@@ -412,6 +482,24 @@
extern errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
void *buf);
+/* dir_iterate.c */
+extern errcode_t ext2fs_dir_iterate(ext2_filsys fs,
+ ino_t dir,
+ int flags,
+ char *block_buf,
+ int (*func)(struct ext2_dir_entry *dirent,
+ int offset,
+ int blocksize,
+ char *buf,
+ void *private),
+ void *private);
+ /* private to library */
+extern int ext2fs_process_dir_block(ext2_filsys fs,
+ blk_t *blocknr,
+ int blockcnt,
+ void *private);
+
+
/* expanddir.c */
extern errcode_t ext2fs_expand_dir(ext2_filsys fs, ino_t dir);
@@ -436,39 +524,42 @@
extern void ext2fs_close_inode_scan(ext2_inode_scan scan);
extern errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ino_t *ino,
struct ext2_inode *inode);
-void ext2fs_set_inode_callback(ext2_inode_scan scan,
- errcode_t (*done_group)(ext2_filsys fs,
- ext2_inode_scan scan,
- dgrp_t group,
- void * private),
- void *done_group_data);
-void ext2fs_set_inode_callback(ext2_inode_scan scan,
- errcode_t (*done_group)(ext2_filsys fs,
- ext2_inode_scan scan,
- dgrp_t group,
- void * private),
- void *done_group_data);
-extern errcode_t ext2fs_read_inode (ext2_filsys fs, unsigned long ino,
+extern errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan,
+ int group);
+extern void ext2fs_set_inode_callback
+ (ext2_inode_scan scan,
+ errcode_t (*done_group)(ext2_filsys fs,
+ ext2_inode_scan scan,
+ dgrp_t group,
+ void * private),
+ void *done_group_data);
+extern int ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags,
+ int clear_flags);
+extern errcode_t ext2fs_read_inode (ext2_filsys fs, ino_t ino,
struct ext2_inode * inode);
-extern errcode_t ext2fs_write_inode(ext2_filsys fs, unsigned long ino,
+extern errcode_t ext2fs_write_inode(ext2_filsys fs, ino_t ino,
struct ext2_inode * inode);
extern errcode_t ext2fs_get_blocks(ext2_filsys fs, ino_t ino, blk_t *blocks);
extern errcode_t ext2fs_check_directory(ext2_filsys fs, ino_t ino);
+/* icount.c */
+extern void ext2fs_free_icount(ext2_icount_t icount);
+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,
+ __u16 *ret);
+extern errcode_t ext2fs_icount_increment(ext2_icount_t icount, ino_t ino,
+ __u16 *ret);
+extern errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ino_t ino,
+ __u16 *ret);
+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);
+
/* ismounted.c */
extern errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags);
/* namei.c */
-extern errcode_t ext2fs_dir_iterate(ext2_filsys fs,
- ino_t dir,
- int flags,
- char *block_buf,
- int (*func)(struct ext2_dir_entry *dirent,
- int offset,
- int blocksize,
- char *buf,
- void *private),
- void *private);
extern errcode_t ext2fs_lookup(ext2_filsys fs, ino_t dir, const char *name,
int namelen, char *buf, ino_t *inode);
extern errcode_t ext2fs_namei(ext2_filsys fs, ino_t root, ino_t cwd,
@@ -505,20 +596,32 @@
ino_t ino, int flags);
/* read_bb.c */
-extern errcode_t ext2fs_read_bb_inode(ext2_filsys fs, badblocks_list *bb_list);
+extern errcode_t ext2fs_read_bb_inode(ext2_filsys fs,
+ ext2_badblocks_list *bb_list);
/* read_bb_file.c */
extern errcode_t ext2fs_read_bb_FILE(ext2_filsys fs, FILE *f,
- badblocks_list *bb_list,
+ ext2_badblocks_list *bb_list,
void (*invalid)(ext2_filsys fs,
blk_t blk));
+/* rs_bitmap.c */
+extern errcode_t ext2fs_resize_generic_bitmap(__u32 new_end,
+ __u32 new_real_end,
+ ext2fs_generic_bitmap bmap);
+extern errcode_t ext2fs_resize_inode_bitmap(__u32 new_end, __u32 new_real_end,
+ ext2fs_inode_bitmap bmap);
+extern errcode_t ext2fs_resize_block_bitmap(__u32 new_end, __u32 new_real_end,
+ ext2fs_block_bitmap bmap);
+
/* swapfs.c */
extern void ext2fs_swap_super(struct ext2_super_block * super);
extern void ext2fs_swap_group_desc(struct ext2_group_desc *gdp);
extern void ext2fs_swap_inode(ext2_filsys fs,struct ext2_inode *t,
struct ext2_inode *f, int hostorder);
+/* valid_blk.c */
+int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode);
/* inline functions */
extern void ext2fs_mark_super_dirty(ext2_filsys fs);
diff --git a/lib/ext2fs/ext2fsP.h b/lib/ext2fs/ext2fsP.h
new file mode 100644
index 0000000..5cf83b5
--- /dev/null
+++ b/lib/ext2fs/ext2fsP.h
@@ -0,0 +1,74 @@
+/*
+ * ext2fsP.h --- private header file for 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 "ext2fs.h"
+
+/*
+ * Badblocks list
+ */
+struct ext2_struct_badblocks_list {
+ int magic;
+ int num;
+ int size;
+ blk_t *list;
+ int badblocks_flags;
+};
+
+struct ext2_struct_badblocks_iterate {
+ int magic;
+ badblocks_list bb;
+ int ptr;
+};
+
+
+/*
+ * Directory block iterator definition
+ */
+struct ext2_struct_dblist {
+ int magic;
+ ext2_filsys fs;
+ ino_t size;
+ ino_t count;
+ int sorted;
+ struct ext2_db_entry * list;
+};
+
+/*
+ * For directory iterators
+ */
+struct dir_context {
+ ino_t dir;
+ int flags;
+ char *buf;
+ int (*func)(struct ext2_dir_entry *dirent,
+ int offset,
+ int blocksize,
+ char *buf,
+ void *private);
+ int (*func2)(ino_t dir,
+ int entry,
+ struct ext2_dir_entry *dirent,
+ int offset,
+ int blocksize,
+ char *buf,
+ void *private);
+ void *private;
+ errcode_t errcode;
+};
+
+
+/* Function prototypes */
+
+extern int ext2_process_dir_block(ext2_filsys fs,
+ blk_t *blocknr,
+ int blockcnt,
+ void *private);
+
diff --git a/lib/ext2fs/freefs.c b/lib/ext2fs/freefs.c
index 5c70983..215d1fb 100644
--- a/lib/ext2fs/freefs.c
+++ b/lib/ext2fs/freefs.c
@@ -1,8 +1,12 @@
/*
* freefs.c --- free an ext2 filesystem
*
- * Copyright (C) 1993, 1994 Theodore Ts'o. This file may be redistributed
- * under the terms of the GNU Public License.
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
#include <stdio.h>
@@ -30,6 +34,16 @@
ext2fs_free_block_bitmap(fs->block_map);
if (fs->inode_map)
ext2fs_free_inode_bitmap(fs->inode_map);
+
+ if (fs->badblocks)
+ badblocks_list_free(fs->badblocks);
+ fs->badblocks = 0;
+
+ if (fs->dblist)
+ ext2fs_free_dblist(fs->dblist);
+
+ fs->magic = 0;
+
free(fs);
}
diff --git a/lib/ext2fs/get_pathname.c b/lib/ext2fs/get_pathname.c
index da6b249..8c94e93 100644
--- a/lib/ext2fs/get_pathname.c
+++ b/lib/ext2fs/get_pathname.c
@@ -1,8 +1,21 @@
/*
* get_pathname.c --- do directry/inode -> name translation
*
- * Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
- * under the terms of the GNU Public License.
+ * Copyright (C) 1993, 1994, 1995 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ *
+ * ext2fs_get_pathname(fs, dir, ino, name)
+ *
+ * This function translates takes two inode numbers into a
+ * string, placing the result in <name>. <dir> is the containing
+ * directory inode, and <ino> is the inode number itself. If
+ * <ino> is zero, then ext2fs_get_pathname will return pathname
+ * of the the directory <dir>.
+ *
*/
#include <stdio.h>
diff --git a/lib/ext2fs/getsize.c b/lib/ext2fs/getsize.c
index 86b12d1..c9fc00a 100644
--- a/lib/ext2fs/getsize.c
+++ b/lib/ext2fs/getsize.c
@@ -1,8 +1,12 @@
/*
* getsize.c --- get the size of a partition.
*
- * Copyright (C) 1995 Theodore Ts'o. This file may be
- * redistributed under the terms of the GNU Public License.
+ * Copyright (C) 1995, 1995 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
#include <stdio.h>
@@ -35,7 +39,7 @@
{
char ch;
- if (ext2_llseek (fd, offset, 0) < 0)
+ if (ext2fs_llseek (fd, offset, 0) < 0)
return 0;
if (read (fd, &ch, 1) < 1)
return 0;
@@ -49,12 +53,13 @@
blk_t *retblocks)
{
int fd;
- int size;
+ long size;
ext2_loff_t high, low;
#ifdef FDGETPRM
struct floppy_struct this_floppy;
#endif
#ifdef HAVE_SYS_DISKLABEL_H
+ int part;
struct disklabel lab;
struct partition *pp;
char ch;
@@ -79,18 +84,18 @@
}
#endif
#ifdef HAVE_SYS_DISKLABEL_H
- size = strlen(file) - 1;
- if (size >= 0) {
- ch = file[size];
+ part = strlen(file) - 1;
+ if (part >= 0) {
+ ch = file[part];
if (isdigit(ch))
- size = 0;
+ part = 0;
else if (ch >= 'a' && ch <= 'h')
- size = ch - 'a';
+ part = ch - 'a';
else
- size = -1;
+ part = -1;
}
- if (size >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) {
- pp = &lab.d_partitions[size];
+ if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) {
+ pp = &lab.d_partitions[part];
if (pp->p_size) {
close(fd);
*retblocks = pp->p_size / (blocksize / 512);
@@ -101,7 +106,7 @@
/*
* OK, we couldn't figure it out by using a specialized ioctl,
- * which is generally the besy way. So do binary search to
+ * which is generally the best way. So do binary search to
* find the size of the partition.
*/
low = 0;
diff --git a/lib/ext2fs/icount.c b/lib/ext2fs/icount.c
new file mode 100644
index 0000000..b9070a9
--- /dev/null
+++ b/lib/ext2fs/icount.c
@@ -0,0 +1,411 @@
+/*
+ * icount.c --- an efficient inode count abstraction
+ *
+ * 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>
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include <linux/ext2_fs.h>
+#include "ext2fs.h"
+
+/*
+ * The data storage strategy used by icount relies on the observation
+ * that most inode counts are either zero (for non-allocated inodes),
+ * one (for most files), and only a few that are two or more
+ * (directories and files that are linked to more than one directory).
+ *
+ * Also, e2fsck tends to load the icount data sequentially.
+ *
+ * So, we use an inode bitmap to indicate which inodes have a count of
+ * one, and then use a sorted list to store the counts for inodes
+ * which are greater than one.
+ *
+ * We also use an optional bitmap to indicate which inodes are already
+ * in the sorted list, to speed up the use of this abstraction by
+ * e2fsck's pass 2. Pass 2 increments inode counts as it finds them,
+ * so this extra bitmap avoids searching the sorted list to see if a
+ * particular inode is on the sorted list already.
+ */
+
+struct ext2_icount_el {
+ ino_t ino;
+ __u16 count;
+};
+
+struct ext2_icount {
+ int magic;
+ ext2fs_inode_bitmap single;
+ ext2fs_inode_bitmap multiple;
+ ino_t count;
+ ino_t size;
+ ino_t num_inodes;
+ int cursor;
+ struct ext2_icount_el *list;
+};
+
+void ext2fs_free_icount(ext2_icount_t icount)
+{
+ if (!icount)
+ return;
+
+ icount->magic = 0;
+ if (icount->list)
+ free(icount->list);
+ if (icount->single)
+ ext2fs_free_inode_bitmap(icount->single);
+ if (icount->multiple)
+ ext2fs_free_inode_bitmap(icount->multiple);
+ free(icount);
+}
+
+errcode_t ext2fs_create_icount(ext2_filsys fs, int flags, int size,
+ ext2_icount_t *ret)
+{
+ ext2_icount_t icount;
+ errcode_t retval;
+ size_t bytes;
+
+ icount = malloc(sizeof(struct ext2_icount));
+ if (!icount)
+ return ENOMEM;
+ memset(icount, 0, sizeof(struct ext2_icount));
+
+ retval = ext2fs_allocate_inode_bitmap(fs, 0,
+ &icount->single);
+ if (retval)
+ goto errout;
+
+ if (flags & EXT2_ICOUNT_OPT_INCREMENT) {
+ retval = ext2fs_allocate_inode_bitmap(fs, 0,
+ &icount->multiple);
+ if (retval)
+ goto errout;
+ } else
+ icount->multiple = 0;
+
+ if (size) {
+ icount->size = size;
+ } else {
+ /*
+ * Figure out how many special case inode counts we will
+ * have. We know we will need one for each directory;
+ * we also need to reserve some extra room for file links
+ */
+ retval = ext2fs_get_num_dirs(fs, &icount->size);
+ if (retval)
+ goto errout;
+ icount->size += fs->super->s_inodes_count / 50;
+ }
+
+ bytes = icount->size * sizeof(struct ext2_icount_el);
+#if 0
+ printf("Icount allocated %d entries, %d bytes.\n",
+ icount->size, bytes);
+#endif
+ icount->list = malloc(bytes);
+ if (!icount->list)
+ goto errout;
+ memset(icount->list, 0, bytes);
+
+ icount->magic = EXT2_ET_MAGIC_ICOUNT;
+ icount->count = 0;
+ icount->cursor = 0;
+ icount->num_inodes = fs->super->s_inodes_count;
+
+ *ret = icount;
+
+ return 0;
+
+errout:
+ ext2fs_free_icount(icount);
+ 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)
+{
+ 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;
+}
+
+/*
+ * 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.
+ */
+static struct ext2_icount_el *put_icount_el(ext2_icount_t icount, ino_t ino)
+{
+ struct ext2_icount_el *el, *new_list;
+ ino_t new_size = 0;
+ int i, j;
+
+ if (icount->count >= icount->size) {
+ if (icount->count) {
+ new_size = icount->list[icount->count-1].ino;
+ new_size = icount->count *
+ ((float) new_size / icount->num_inodes);
+ }
+ if (new_size < (icount->size + 100))
+ new_size = icount->size + 100;
+#if 0
+ printf("Reallocating icount %d entries...\n", new_size);
+#endif
+ new_list = realloc(icount->list,
+ new_size * sizeof(struct ext2_icount_el));
+ if (!new_list)
+ return 0;
+ 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;
+ }
+ el->ino = ino;
+ return el;
+}
+
+
+errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ino_t ino, __u16 *ret)
+{
+ struct ext2_icount_el *el;
+
+ EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
+
+ if (ext2fs_test_inode_bitmap(icount->single, ino)) {
+ *ret = 1;
+ return 0;
+ }
+ el = get_icount_el(icount, ino);
+ if (!el) {
+ *ret = 0;
+ return 0;
+ }
+ *ret = el->count;
+ return 0;
+}
+
+errcode_t ext2fs_icount_increment(ext2_icount_t icount, ino_t ino,
+ __u16 *ret)
+{
+ struct ext2_icount_el *el;
+
+ EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
+
+ 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().
+ */
+ el = put_icount_el(icount, ino);
+ if (!el)
+ return ENOMEM;
+ } else if (icount->multiple) {
+ /*
+ * The count is either zero or greater than 1; if the
+ * inode is set in icount->multiple, then there should
+ * be an entry in the list, so find it using
+ * 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;
+ }
+ } else {
+ /*
+ * The count was zero; mark the single bitmap
+ * and return.
+ */
+ zero_count:
+ ext2fs_mark_inode_bitmap(icount->single, ino);
+ if (ret)
+ *ret = 1;
+ return 0;
+ }
+ } else {
+ /*
+ * 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);
+ if (!el) {
+ /* No entry means the count was zero */
+ goto zero_count;
+ }
+ el = put_icount_el(icount, ino);
+ 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)
+ *ret = el->count;
+ return 0;
+}
+
+errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ino_t ino,
+ __u16 *ret)
+{
+ struct ext2_icount_el *el;
+
+ EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
+
+ if (ext2fs_test_inode_bitmap(icount->single, ino)) {
+ ext2fs_unmark_inode_bitmap(icount->single, ino);
+ if (icount->multiple)
+ ext2fs_unmark_inode_bitmap(icount->multiple, ino);
+ else {
+ el = get_icount_el(icount, ino);
+ if (el)
+ el->count = 0;
+ }
+ if (ret)
+ *ret = 0;
+ return 0;
+ }
+
+ el = get_icount_el(icount, ino);
+ if (!el)
+ return EINVAL;
+
+ el->count--;
+ if (el->count == 1)
+ ext2fs_mark_inode_bitmap(icount->single, ino);
+ if ((el->count == 0) && icount->multiple)
+ ext2fs_unmark_inode_bitmap(icount->multiple, ino);
+
+ if (ret)
+ *ret = el->count;
+ return 0;
+}
+
+errcode_t ext2fs_icount_store(ext2_icount_t icount, ino_t ino,
+ __u16 count)
+{
+ struct ext2_icount_el *el;
+
+ EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
+
+ if (count == 1) {
+ ext2fs_mark_inode_bitmap(icount->single, ino);
+ if (icount->multiple)
+ ext2fs_unmark_inode_bitmap(icount->multiple, ino);
+ return 0;
+ }
+ if (count == 0) {
+ ext2fs_unmark_inode_bitmap(icount->single, ino);
+ if (icount->multiple) {
+ /*
+ * If the icount->multiple bitmap is enabled,
+ * we can just clear both bitmaps and we're done
+ */
+ ext2fs_unmark_inode_bitmap(icount->multiple, ino);
+ } else {
+ el = get_icount_el(icount, ino);
+ if (el)
+ el->count = 0;
+ }
+ return 0;
+ }
+
+ /*
+ * Get the icount element
+ */
+ el = put_icount_el(icount, ino);
+ if (!el)
+ return ENOMEM;
+ el->count = count;
+ ext2fs_unmark_inode_bitmap(icount->single, ino);
+ if (icount->multiple)
+ ext2fs_mark_inode_bitmap(icount->multiple, ino);
+ return 0;
+}
+
+ino_t ext2fs_get_icount_size(ext2_icount_t icount)
+{
+ if (!icount || icount->magic != EXT2_ET_MAGIC_ICOUNT)
+ return 0;
+
+ return icount->size;
+}
diff --git a/lib/ext2fs/initialize.c b/lib/ext2fs/initialize.c
index 4349244..6db5a0c 100644
--- a/lib/ext2fs/initialize.c
+++ b/lib/ext2fs/initialize.c
@@ -4,8 +4,10 @@
*
* Copyright (C) 1994, 1995, 1996 Theodore Ts'o.
*
+ * %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
+ * %End-Header%
*/
#include <stdio.h>
diff --git a/lib/ext2fs/inline.c b/lib/ext2fs/inline.c
index 599fceb..3451c35 100644
--- a/lib/ext2fs/inline.c
+++ b/lib/ext2fs/inline.c
@@ -3,8 +3,12 @@
* files as standalone functions, in case the application program
* is compiled with inlining turned off.
*
- * Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
- * under the terms of the GNU Public License.
+ * Copyright (C) 1993, 1994 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
diff --git a/lib/ext2fs/inode.c b/lib/ext2fs/inode.c
index 8743476..8fd5e7e 100644
--- a/lib/ext2fs/inode.c
+++ b/lib/ext2fs/inode.c
@@ -1,8 +1,12 @@
/*
* inode.c --- utility routines to read and write inodes
*
- * Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
- * under the terms of the GNU Public License.
+ * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
#include <stdio.h>
@@ -17,15 +21,51 @@
#include <linux/ext2_fs.h>
-#include "ext2fs.h"
+#include "ext2fsP.h"
+
+struct ext2_struct_inode_scan {
+ int magic;
+ ext2_filsys fs;
+ ino_t current_inode;
+ blk_t current_block;
+ dgrp_t current_group;
+ int inodes_left, blocks_left, groups_left;
+ int inode_buffer_blocks;
+ char * inode_buffer;
+ int inode_size;
+ char * ptr;
+ int bytes_left;
+ char *temp_buffer;
+ errcode_t (*done_group)(ext2_filsys fs,
+ ext2_inode_scan scan,
+ dgrp_t group,
+ void * private);
+ void * done_group_data;
+ int bad_block_ptr;
+ int scan_flags;
+ int reserved[6];
+};
errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks,
ext2_inode_scan *ret_scan)
{
ext2_inode_scan scan;
+ errcode_t retval;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+ /*
+ * If fs->badblocks isn't set, then set it --- since the inode
+ * scanning functions require it.
+ */
+ if (fs->badblocks == 0) {
+ retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
+ if (retval && fs->badblocks) {
+ badblocks_list_free(fs->badblocks);
+ fs->badblocks = 0;
+ }
+ }
+
scan = (ext2_inode_scan) malloc(sizeof(struct ext2_struct_inode_scan));
if (!scan)
return ENOMEM;
@@ -41,6 +81,7 @@
scan->inode_buffer = malloc(scan->inode_buffer_blocks * fs->blocksize);
scan->done_group = 0;
scan->done_group_data = 0;
+ scan->bad_block_ptr = 0;
if (!scan->inode_buffer) {
free(scan);
return ENOMEM;
@@ -51,6 +92,8 @@
free(scan);
return ENOMEM;
}
+ if (scan->fs->badblocks && scan->fs->badblocks->num)
+ scan->scan_flags |= EXT2_SF_CHK_BADBLOCKS;
*ret_scan = scan;
return 0;
}
@@ -82,11 +125,168 @@
scan->done_group_data = done_group_data;
}
+int ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags,
+ int clear_flags)
+{
+ int old_flags;
+
+ if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN))
+ return 0;
+
+ old_flags = scan->scan_flags;
+ scan->scan_flags &= ~clear_flags;
+ scan->scan_flags |= set_flags;
+ return old_flags;
+}
+
+/*
+ * This function is called by ext2fs_get_next_inode when it needs to
+ * get ready to read in a new blockgroup.
+ */
+static errcode_t get_next_blockgroup(ext2_inode_scan scan)
+{
+ scan->current_group++;
+ scan->groups_left--;
+
+ scan->current_block = scan->fs->
+ group_desc[scan->current_group].bg_inode_table;
+
+ scan->bytes_left = 0;
+ scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super);
+ scan->blocks_left = scan->fs->inode_blocks_per_group;
+ return 0;
+}
+
+errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan,
+ int group)
+{
+ scan->current_group = group - 1;
+ scan->groups_left = scan->fs->group_desc_count - group;
+ return get_next_blockgroup(scan);
+}
+
+/*
+ * This function is called by get_next_blocks() to check for bad
+ * blocks in the inode table.
+ *
+ * This function assumes that badblocks_list->list is sorted in
+ * increasing order.
+ */
+static errcode_t check_for_inode_bad_blocks(ext2_inode_scan scan,
+ int *num_blocks)
+{
+ blk_t blk = scan->current_block;
+ badblocks_list bb = scan->fs->badblocks;
+
+ /*
+ * If the inode table is missing, then obviously there are no
+ * bad blocks. :-)
+ */
+ if (blk == 0)
+ return 0;
+
+ /*
+ * If the current block is greater than the bad block listed
+ * in the bad block list, then advance the pointer until this
+ * is no longer the case. If we run out of bad blocks, then
+ * we don't need to do any more checking!
+ */
+ while (blk > bb->list[scan->bad_block_ptr]) {
+ if (++scan->bad_block_ptr >= bb->num) {
+ scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS;
+ return 0;
+ }
+ }
+
+ /*
+ * If the current block is equal to the bad block listed in
+ * the bad block list, then handle that one block specially.
+ * (We could try to handle runs of bad blocks, but that
+ * only increases CPU efficiency by a small amount, at the
+ * expense of a huge expense of code complexity, and for an
+ * uncommon case at that.)
+ */
+ if (blk == bb->list[scan->bad_block_ptr]) {
+ scan->scan_flags |= EXT2_SF_BAD_INODE_BLK;
+ *num_blocks = 1;
+ if (++scan->bad_block_ptr >= bb->num)
+ scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS;
+ return 0;
+ }
+
+ /*
+ * If there is a bad block in the range that we're about to
+ * read in, adjust the number of blocks to read so that we we
+ * don't read in the bad block. (Then the next block to read
+ * will be the bad block, which is handled in the above case.)
+ */
+ if ((blk + *num_blocks) > bb->list[scan->bad_block_ptr])
+ *num_blocks = bb->list[scan->bad_block_ptr] - blk;
+
+ return 0;
+}
+
+/*
+ * This function is called by ext2fs_get_next_inode when it needs to
+ * read in more blocks from the current blockgroup's inode table.
+ */
+static errcode_t get_next_blocks(ext2_inode_scan scan)
+{
+ int num_blocks;
+ errcode_t retval;
+
+ /*
+ * Figure out how many blocks to read; we read at most
+ * inode_buffer_blocks, and perhaps less if there aren't that
+ * many blocks left to read.
+ */
+ num_blocks = scan->inode_buffer_blocks;
+ if (num_blocks > scan->blocks_left)
+ num_blocks = scan->blocks_left;
+
+ /*
+ * If the past block "read" was a bad block, then mark the
+ * left-over extra bytes as also being bad.
+ */
+ if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK) {
+ if (scan->bytes_left)
+ scan->scan_flags |= EXT2_SF_BAD_EXTRA_BYTES;
+ scan->scan_flags &= ~EXT2_SF_BAD_INODE_BLK;
+ }
+
+ /*
+ * Do inode bad block processing, if necessary.
+ */
+ if (scan->scan_flags & EXT2_SF_CHK_BADBLOCKS) {
+ retval = check_for_inode_bad_blocks(scan, &num_blocks);
+ if (retval)
+ return retval;
+ }
+
+ if ((scan->scan_flags & EXT2_SF_BAD_INODE_BLK) ||
+ (scan->current_block == 0)) {
+ memset(scan->inode_buffer, 0,
+ num_blocks * scan->fs->blocksize);
+ } else {
+ retval = io_channel_read_blk(scan->fs->io,
+ scan->current_block,
+ num_blocks, scan->inode_buffer);
+ if (retval)
+ return EXT2_ET_NEXT_INODE_READ;
+ }
+ scan->ptr = scan->inode_buffer;
+ scan->bytes_left = num_blocks * scan->fs->blocksize;
+
+ scan->blocks_left -= num_blocks;
+ if (scan->current_block)
+ scan->current_block += num_blocks;
+ return 0;
+}
+
errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ino_t *ino,
struct ext2_inode *inode)
{
errcode_t retval;
- int num_blocks;
int extra_bytes = 0;
EXT2_CHECK_MAGIC(scan, EXT2_ET_MAGIC_INODE_SCAN);
@@ -95,10 +295,10 @@
* Do we need to start reading a new block group?
*/
if (scan->inodes_left <= 0) {
+ retry:
if (scan->done_group) {
retval = (scan->done_group)
- (scan->fs, scan,
- scan->current_group,
+ (scan->fs, scan, scan->current_group,
scan->done_group_data);
if (retval)
return retval;
@@ -107,17 +307,15 @@
*ino = 0;
return 0;
}
- scan->current_group++;
- scan->groups_left--;
-
- scan->current_block = scan->fs->
- group_desc[scan->current_group].bg_inode_table;
-
- if (scan->current_block == 0)
- return EXT2_ET_MISSING_INODE_TABLE;
- scan->bytes_left = 0;
- scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super);
- scan->blocks_left = scan->fs->inode_blocks_per_group;
+ retval = get_next_blockgroup(scan);
+ if (retval)
+ return retval;
+ if (scan->current_block == 0) {
+ if (scan->scan_flags & EXT2_SF_SKIP_MISSING_ITABLE) {
+ goto retry;
+ } else
+ return EXT2_ET_MISSING_INODE_TABLE;
+ }
}
/*
@@ -127,22 +325,13 @@
if (scan->bytes_left < scan->inode_size) {
memcpy(scan->temp_buffer, scan->ptr, scan->bytes_left);
extra_bytes = scan->bytes_left;
-
- scan->blocks_left -= scan->inode_buffer_blocks;
- num_blocks = scan->inode_buffer_blocks;
- if (scan->blocks_left < 0)
- num_blocks += scan->blocks_left;
-
- retval = io_channel_read_blk(scan->fs->io, scan->current_block,
- num_blocks, scan->inode_buffer);
+
+ retval = get_next_blocks(scan);
if (retval)
- return EXT2_ET_NEXT_INODE_READ;
- scan->ptr = scan->inode_buffer;
- scan->bytes_left = num_blocks * scan->fs->blocksize;
-
- scan->current_block += scan->inode_buffer_blocks;
+ return retval;
}
+ retval = 0;
if (extra_bytes) {
memcpy(scan->temp_buffer+extra_bytes, scan->ptr,
scan->inode_size - extra_bytes);
@@ -155,6 +344,9 @@
(struct ext2_inode *) scan->temp_buffer, 0);
else
*inode = *((struct ext2_inode *) scan->temp_buffer);
+ if (scan->scan_flags & EXT2_SF_BAD_EXTRA_BYTES)
+ retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE;
+ scan->scan_flags &= ~EXT2_SF_BAD_EXTRA_BYTES;
} else {
if ((scan->fs->flags & EXT2_FLAG_SWAP_BYTES) ||
(scan->fs->flags & EXT2_FLAG_SWAP_BYTES_READ))
@@ -164,12 +356,14 @@
*inode = *((struct ext2_inode *) scan->ptr);
scan->ptr += scan->inode_size;
scan->bytes_left -= scan->inode_size;
+ if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK)
+ retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE;
}
scan->inodes_left--;
scan->current_inode++;
*ino = scan->current_inode;
- return 0;
+ return retval;
}
/*
@@ -188,7 +382,7 @@
#endif
-errcode_t ext2fs_read_inode (ext2_filsys fs, unsigned long ino,
+errcode_t ext2fs_read_inode (ext2_filsys fs, ino_t ino,
struct ext2_inode * inode)
{
unsigned long group, block, block_nr, offset;
@@ -234,6 +428,8 @@
offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
EXT2_INODE_SIZE(fs->super);
block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
+ if (!fs->group_desc[group].bg_inode_table)
+ return EXT2_ET_MISSING_INODE_TABLE;
block_nr = fs->group_desc[group].bg_inode_table + block;
if (block_nr != inode_buffer_block) {
retval = io_channel_read_blk(fs->io, block_nr, 1,
@@ -280,8 +476,8 @@
return 0;
}
-errcode_t ext2fs_write_inode(ext2_filsys fs, unsigned long ino,
- struct ext2_inode * inode)
+errcode_t ext2fs_write_inode(ext2_filsys fs, ino_t ino,
+ struct ext2_inode * inode)
{
unsigned long group, block, block_nr, offset;
errcode_t retval;
@@ -332,11 +528,14 @@
offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) *
EXT2_INODE_SIZE(fs->super);
block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super);
+ if (!fs->group_desc[group].bg_inode_table)
+ return EXT2_ET_MISSING_INODE_TABLE;
block_nr = fs->group_desc[group].bg_inode_table + block;
offset &= (EXT2_BLOCK_SIZE(fs->super) - 1);
ptr = (char *) inode_buffer + offset;
length = EXT2_INODE_SIZE(fs->super);
+ clen = length;
if (length > sizeof(struct ext2_inode))
length = sizeof(struct ext2_inode);
@@ -350,12 +549,11 @@
if ((offset + length) > EXT2_BLOCK_SIZE(fs->super)) {
clen = EXT2_BLOCK_SIZE(fs->super) - offset;
- memcpy(ptr, &temp_inode, clen);
length -= clen;
} else {
- memcpy(ptr, &temp_inode, length);
length = 0;
}
+ memcpy(ptr, &temp_inode, clen);
retval = io_channel_write_blk(fs->io, block_nr, 1, inode_buffer);
if (retval)
return retval;
@@ -419,7 +617,7 @@
if (retval)
return retval;
if (!LINUX_S_ISDIR(inode.i_mode))
- return ENOTDIR;
+ return ENOTDIR;
return 0;
}
diff --git a/lib/ext2fs/io.h b/lib/ext2fs/io.h
index 7a44a11..6b28fee 100644
--- a/lib/ext2fs/io.h
+++ b/lib/ext2fs/io.h
@@ -1,8 +1,12 @@
/*
* io.h --- the I/O manager abstraction
*
- * Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
- * under the terms of the GNU Public License.
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
/*
@@ -15,7 +19,7 @@
#endif
/* llseek.c */
-ext2_loff_t ext2_llseek (unsigned int, ext2_loff_t, unsigned int);
+ext2_loff_t ext2fs_llseek (unsigned int, ext2_loff_t, unsigned int);
typedef struct struct_io_manager *io_manager;
typedef struct struct_io_channel *io_channel;
@@ -68,8 +72,14 @@
#define io_channel_write_blk(c,b,n,d) ((c)->manager->write_blk((c),b,n,d))
#define io_channel_flush(c) ((c)->manager->flush((c)))
+/* unix_io.c */
extern io_manager unix_io_manager;
-
-
-
+/* test_io.c */
+extern io_manager test_io_manager, test_io_backing_manager;
+extern void (*test_io_cb_read_blk)
+ (unsigned long block, int count, errcode_t err);
+extern void (*test_io_cb_write_blk)
+ (unsigned long block, int count, errcode_t err);
+extern void (*test_io_cb_set_blksize)
+ (int blksize, errcode_t err);
diff --git a/lib/ext2fs/irel.h b/lib/ext2fs/irel.h
new file mode 100644
index 0000000..9c7529a
--- /dev/null
+++ b/lib/ext2fs/irel.h
@@ -0,0 +1,114 @@
+/*
+ * irel.h
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+struct ext2_inode_reference {
+ blk_t block;
+ __u16 offset;
+};
+
+struct ext2_inode_relocate_entry {
+ ino_t new;
+ ino_t orig;
+ __u16 flags;
+ __u16 max_refs;
+};
+
+typedef struct ext2_inode_relocation_table *ext2_irel;
+
+struct ext2_inode_relocation_table {
+ __u32 magic;
+ char *name;
+ ino_t current;
+ void *private;
+
+ /*
+ * Add an inode relocation entry.
+ */
+ errcode_t (*put)(ext2_irel irel, ino_t old,
+ struct ext2_inode_relocate_entry *ent);
+ /*
+ * Get an inode relocation entry.
+ */
+ errcode_t (*get)(ext2_irel irel, ino_t old,
+ struct ext2_inode_relocate_entry *ent);
+
+ /*
+ * Get an inode relocation entry by its original inode number
+ */
+ errcode_t (*get_by_orig)(ext2_irel irel, ino_t orig, ino_t *old,
+ struct ext2_inode_relocate_entry *ent);
+
+ /*
+ * Initialize for iterating over the inode relocation entries.
+ */
+ errcode_t (*start_iter)(ext2_irel irel);
+
+ /*
+ * The iterator function for the inode relocation entries.
+ * Returns an inode number of 0 when out of entries.
+ */
+ errcode_t (*next)(ext2_irel irel, ino_t *old,
+ struct ext2_inode_relocate_entry *ent);
+
+ /*
+ * Add an inode reference (i.e., note the fact that a
+ * particular block/offset contains a reference to an inode)
+ */
+ errcode_t (*add_ref)(ext2_irel irel, ino_t ino,
+ struct ext2_inode_reference *ref);
+
+ /*
+ * Initialize for iterating over the inode references for a
+ * particular inode.
+ */
+ errcode_t (*start_iter_ref)(ext2_irel irel, ino_t ino);
+
+ /*
+ * The iterator function for the inode references for an
+ * inode. The references for only one inode can be interator
+ * over at a time, as the iterator state is stored in ext2_irel.
+ */
+ errcode_t (*next_ref)(ext2_irel irel,
+ struct ext2_inode_reference *ref);
+
+ /*
+ * Move the inode relocation table from one inode number to
+ * another. Note that the inode references also must move.
+ */
+ errcode_t (*move)(ext2_irel irel, ino_t old, ino_t new);
+
+ /*
+ * Remove an inode relocation entry, along with all of the
+ * inode references.
+ */
+ errcode_t (*delete)(ext2_irel irel, ino_t old);
+
+ /*
+ * Free the inode relocation table.
+ */
+ errcode_t (*free)(ext2_irel irel);
+};
+
+errcode_t ext2fs_irel_memarray_create(char *name, ino_t max_inode,
+ ext2_irel *irel);
+
+#define ext2fs_irel_put(irel, old, ent) ((irel)->put((irel), old, ent))
+#define ext2fs_irel_get(irel, old, ent) ((irel)->get((irel), old, ent))
+#define ext2fs_irel_get_by_orig(irel, orig, old, ent) \
+ ((irel)->get_by_orig((irel), orig, old, ent))
+#define ext2fs_irel_start_iter(irel) ((irel)->start_iter((irel)))
+#define ext2fs_irel_next(irel, old, ent) ((irel)->next((irel), old, ent))
+#define ext2fs_irel_add_ref(irel, ino, ref) ((irel)->add_ref((irel), ino, ref))
+#define ext2fs_irel_start_iter_ref(irel, ino) ((irel)->start_iter_ref((irel), ino))
+#define ext2fs_irel_next_ref(irel, ref) ((irel)->next_ref((irel), ref))
+#define ext2fs_irel_move(irel, old, new) ((irel)->move((irel), old, new))
+#define ext2fs_irel_delete(irel, old) ((irel)->delete((irel), old))
+#define ext2fs_irel_free(irel) ((irel)->free((irel)))
diff --git a/lib/ext2fs/irel_ma.c b/lib/ext2fs/irel_ma.c
new file mode 100644
index 0000000..1bb3af6
--- /dev/null
+++ b/lib/ext2fs/irel_ma.c
@@ -0,0 +1,364 @@
+/*
+ * irel_ma.c
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <linux/ext2_fs.h>
+
+#include "ext2fs.h"
+#include "irel.h"
+
+static errcode_t ima_put(ext2_irel irel, ino_t old,
+ struct ext2_inode_relocate_entry *ent);
+static errcode_t ima_get(ext2_irel irel, ino_t old,
+ struct ext2_inode_relocate_entry *ent);
+static errcode_t ima_get_by_orig(ext2_irel irel, ino_t orig, ino_t *old,
+ struct ext2_inode_relocate_entry *ent);
+static errcode_t ima_start_iter(ext2_irel irel);
+static errcode_t ima_next(ext2_irel irel, ino_t *old,
+ struct ext2_inode_relocate_entry *ent);
+static errcode_t ima_add_ref(ext2_irel irel, ino_t ino,
+ struct ext2_inode_reference *ref);
+static errcode_t ima_start_iter_ref(ext2_irel irel, ino_t ino);
+static errcode_t ima_next_ref(ext2_irel irel, struct ext2_inode_reference *ref);
+static errcode_t ima_move(ext2_irel irel, ino_t old, ino_t new);
+static errcode_t ima_delete(ext2_irel irel, ino_t old);
+static errcode_t ima_free(ext2_irel irel);
+
+/*
+ * This data structure stores the array of inode references; there is
+ * a structure for each inode.
+ */
+struct inode_reference_entry {
+ __u16 num;
+ struct ext2_inode_reference *refs;
+};
+
+struct irel_ma {
+ __u32 magic;
+ ino_t max_inode;
+ ino_t ref_current;
+ int ref_iter;
+ ino_t *orig_map;
+ struct ext2_inode_relocate_entry *entries;
+ struct inode_reference_entry *ref_entries;
+};
+
+errcode_t ext2fs_irel_memarray_create(char *name, ino_t max_inode,
+ ext2_irel *new_irel)
+{
+ ext2_irel irel = 0;
+ errcode_t retval;
+ struct irel_ma *ma = 0;
+ size_t size;
+
+ *new_irel = 0;
+
+ /*
+ * Allocate memory structures
+ */
+ retval = ENOMEM;
+ irel = malloc(sizeof(struct ext2_inode_relocation_table));
+ if (!irel)
+ goto errout;
+ memset(irel, 0, sizeof(struct ext2_inode_relocation_table));
+
+ irel->name = malloc(strlen(name)+1);
+ if (!irel->name)
+ goto errout;
+ strcpy(irel->name, name);
+
+ ma = malloc(sizeof(struct irel_ma));
+ if (!ma)
+ goto errout;
+ memset(ma, 0, sizeof(struct irel_ma));
+ irel->private = ma;
+
+ size = sizeof(ino_t) * (max_inode+1);
+ ma->orig_map = malloc(size);
+ if (!ma->orig_map)
+ goto errout;
+ memset(ma->orig_map, 0, size);
+
+ size = sizeof(struct ext2_inode_relocate_entry) * (max_inode+1);
+ ma->entries = malloc(size);
+ if (!ma->entries)
+ goto errout;
+ memset(ma->entries, 0, size);
+
+ size = sizeof(struct inode_reference_entry) * (max_inode+1);
+ ma->ref_entries = malloc(size);
+ if (!ma->ref_entries)
+ goto errout;
+ memset(ma->ref_entries, 0, size);
+ ma->max_inode = max_inode;
+
+ /*
+ * Fill in the irel data structure
+ */
+ irel->put = ima_put;
+ irel->get = ima_get;
+ irel->get_by_orig = ima_get_by_orig;
+ irel->start_iter = ima_start_iter;
+ irel->next = ima_next;
+ irel->add_ref = ima_add_ref;
+ irel->start_iter_ref = ima_start_iter_ref;
+ irel->next_ref = ima_next_ref;
+ irel->move = ima_move;
+ irel->delete = ima_delete;
+ irel->free = ima_free;
+
+ *new_irel = irel;
+ return 0;
+
+errout:
+ ima_free(irel);
+ return retval;
+}
+
+static errcode_t ima_put(ext2_irel irel, ino_t old,
+ struct ext2_inode_relocate_entry *ent)
+{
+ struct irel_ma *ma;
+ struct inode_reference_entry *ref_ent;
+ struct ext2_inode_reference *new_refs;
+ int size;
+
+ ma = irel->private;
+ if (old > ma->max_inode)
+ return EINVAL;
+
+ /*
+ * Force the orig field to the correct value; the application
+ * program shouldn't be messing with this field.
+ */
+ if (ma->entries[old].new == 0)
+ ent->orig = old;
+ else
+ ent->orig = ma->entries[old].orig;
+
+ /*
+ * If max_refs has changed, reallocate the refs array
+ */
+ ref_ent = ma->ref_entries + old;
+ if (ref_ent->refs && ent->max_refs != ma->entries[old].max_refs) {
+ size = (sizeof(struct ext2_inode_reference) * ent->max_refs);
+ new_refs = realloc(ref_ent->refs, size);
+ if (!new_refs)
+ return ENOMEM;
+ ref_ent->refs = new_refs;
+ }
+
+ ma->entries[old] = *ent;
+ ma->orig_map[ent->orig] = old;
+ return 0;
+}
+
+static errcode_t ima_get(ext2_irel irel, ino_t old,
+ struct ext2_inode_relocate_entry *ent)
+{
+ struct irel_ma *ma;
+
+ ma = irel->private;
+ if (old > ma->max_inode)
+ return EINVAL;
+ if (ma->entries[old].new == 0)
+ return ENOENT;
+ *ent = ma->entries[old];
+ return 0;
+}
+
+static errcode_t ima_get_by_orig(ext2_irel irel, ino_t orig, ino_t *old,
+ struct ext2_inode_relocate_entry *ent)
+{
+ struct irel_ma *ma;
+ ino_t ino;
+
+ ma = irel->private;
+ if (orig > ma->max_inode)
+ return EINVAL;
+ ino = ma->orig_map[orig];
+ if (ino == 0)
+ return ENOENT;
+ *old = ino;
+ *ent = ma->entries[ino];
+ return 0;
+}
+
+static errcode_t ima_start_iter(ext2_irel irel)
+{
+ irel->current = 0;
+ return 0;
+}
+
+static errcode_t ima_next(ext2_irel irel, ino_t *old,
+ struct ext2_inode_relocate_entry *ent)
+{
+ struct irel_ma *ma;
+
+ ma = irel->private;
+ while (++irel->current < ma->max_inode) {
+ if (ma->entries[irel->current].new == 0)
+ continue;
+ *old = irel->current;
+ *ent = ma->entries[irel->current];
+ return 0;
+ }
+ *old = 0;
+ return 0;
+}
+
+static errcode_t ima_add_ref(ext2_irel irel, ino_t ino,
+ struct ext2_inode_reference *ref)
+{
+ struct irel_ma *ma;
+ size_t size;
+ struct inode_reference_entry *ref_ent;
+ struct ext2_inode_relocate_entry *ent;
+
+ ma = irel->private;
+ if (ino > ma->max_inode)
+ return EINVAL;
+
+ ref_ent = ma->ref_entries + ino;
+ ent = ma->entries + ino;
+
+ /*
+ * If the inode reference array doesn't exist, create it.
+ */
+ if (ref_ent->refs == 0) {
+ size = (sizeof(struct ext2_inode_reference) * ent->max_refs);
+ ref_ent->refs = malloc(size);
+ if (ref_ent->refs == 0)
+ return ENOMEM;
+ memset(ref_ent->refs, 0, size);
+ ref_ent->num = 0;
+ }
+
+ if (ref_ent->num >= ent->max_refs)
+ return ENOSPC;
+
+ ref_ent->refs[ref_ent->num++] = *ref;
+ return 0;
+}
+
+static errcode_t ima_start_iter_ref(ext2_irel irel, ino_t ino)
+{
+ struct irel_ma *ma;
+
+ ma = irel->private;
+ if (ino > ma->max_inode)
+ return EINVAL;
+ if (ma->entries[ino].new == 0)
+ return ENOENT;
+ ma->ref_current = ino;
+ ma->ref_iter = 0;
+ return 0;
+}
+
+static errcode_t ima_next_ref(ext2_irel irel,
+ struct ext2_inode_reference *ref)
+{
+ struct irel_ma *ma;
+ struct inode_reference_entry *ref_ent;
+
+ ma = irel->private;
+
+ ref_ent = ma->ref_entries + ma->ref_current;
+
+ if ((ref_ent->refs == NULL) ||
+ (ma->ref_iter >= ref_ent->num)) {
+ ref->block = 0;
+ ref->offset = 0;
+ return 0;
+ }
+ *ref = ref_ent->refs[ma->ref_iter++];
+ return 0;
+}
+
+
+static errcode_t ima_move(ext2_irel irel, ino_t old, ino_t new)
+{
+ struct irel_ma *ma;
+
+ ma = irel->private;
+ if ((old > ma->max_inode) || (new > ma->max_inode))
+ return EINVAL;
+ if (ma->entries[old].new == 0)
+ return ENOENT;
+
+ ma->entries[new] = ma->entries[old];
+ if (ma->ref_entries[new].refs)
+ free(ma->ref_entries[new].refs);
+ ma->ref_entries[new] = ma->ref_entries[old];
+
+ ma->entries[old].new = 0;
+ ma->ref_entries[old].num = 0;
+ ma->ref_entries[old].refs = 0;
+
+ ma->orig_map[ma->entries[new].orig] = new;
+ return 0;
+}
+
+static errcode_t ima_delete(ext2_irel irel, ino_t old)
+{
+ struct irel_ma *ma;
+
+ ma = irel->private;
+ if (old > ma->max_inode)
+ return EINVAL;
+ if (ma->entries[old].new == 0)
+ return ENOENT;
+
+ ma->entries[old].new = 0;
+ if (ma->ref_entries[old].refs)
+ free(ma->ref_entries[old].refs);
+ ma->orig_map[ma->entries[old].orig] = 0;
+
+ ma->ref_entries[old].num = 0;
+ ma->ref_entries[old].refs = 0;
+ return 0;
+}
+
+static errcode_t ima_free(ext2_irel irel)
+{
+ struct irel_ma *ma;
+ ino_t ino;
+
+ if (!irel)
+ return 0;
+
+ ma = irel->private;
+
+ if (ma) {
+ if (ma->orig_map)
+ free (ma->orig_map);
+ if (ma->entries)
+ free (ma->entries);
+ if (ma->ref_entries) {
+ for (ino = 0; ino <= ma->max_inode; ino++) {
+ if (ma->ref_entries[ino].refs)
+ free(ma->ref_entries[ino].refs);
+ }
+ free(ma->ref_entries);
+ }
+ free(ma);
+ }
+ if (irel->name)
+ free(irel->name);
+ free (irel);
+ return 0;
+}
diff --git a/lib/ext2fs/ismounted.c b/lib/ext2fs/ismounted.c
index 781bfdf..9c2593c 100644
--- a/lib/ext2fs/ismounted.c
+++ b/lib/ext2fs/ismounted.c
@@ -1,8 +1,12 @@
/*
- * getsize.c --- get the size of a partition.
+ * ismounted.c --- Check to see if the filesystem was mounted
*
- * Copyright (C) 1995 Theodore Ts'o. This file may be
- * redistributed under the terms of the GNU Public License.
+ * Copyright (C) 1995 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
#include <stdio.h>
diff --git a/lib/ext2fs/link.c b/lib/ext2fs/link.c
index 042183b..933dfa8 100644
--- a/lib/ext2fs/link.c
+++ b/lib/ext2fs/link.c
@@ -1,8 +1,12 @@
/*
- * link.c --- create or delete links in a ext2fs directory
+ * link.c --- create links in a ext2fs directory
*
- * Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
- * under the terms of the GNU Public License.
+ * Copyright (C) 1993, 1994 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
#include <stdio.h>
@@ -104,48 +108,3 @@
return (ls.done) ? 0 : EXT2_ET_DIR_NO_SPACE;
}
-
-static int unlink_proc(struct ext2_dir_entry *dirent,
- int offset,
- int blocksize,
- char *buf,
- void *private)
-{
- struct link_struct *ls = (struct link_struct *) private;
-
- if (ls->name && (dirent->name_len != ls->namelen))
- return 0;
- if (ls->name && strncmp(ls->name, dirent->name, dirent->name_len))
- return 0;
- if (ls->inode && (dirent->inode != ls->inode))
- return 0;
-
- dirent->inode = 0;
- ls->done++;
- return DIRENT_ABORT|DIRENT_CHANGED;
-}
-
-errcode_t ext2fs_unlink(ext2_filsys fs, ino_t dir, const char *name, ino_t ino,
- int flags)
-{
- errcode_t retval;
- struct link_struct ls;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- if (!(fs->flags & EXT2_FLAG_RW))
- return EXT2_ET_RO_FILSYS;
-
- ls.name = name;
- ls.namelen = name ? strlen(name) : 0;
- ls.inode = ino;
- ls.flags = 0;
- ls.done = 0;
-
- retval = ext2fs_dir_iterate(fs, dir, 0, 0, unlink_proc, &ls);
- if (retval)
- return retval;
-
- return (ls.done) ? 0 : EXT2_ET_DIR_NO_SPACE;
-}
-
diff --git a/lib/ext2fs/llseek.c b/lib/ext2fs/llseek.c
index 02e0ede..71a9d91 100644
--- a/lib/ext2fs/llseek.c
+++ b/lib/ext2fs/llseek.c
@@ -1,8 +1,12 @@
/*
* llseek.c -- stub calling the llseek system call
*
- * Copyright (C) 1994 Remy Card. This file may be redistributed
- * under the terms of the GNU Public License.
+ * Copyright (C) 1994, 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
#include <sys/types.h>
@@ -55,7 +59,7 @@
#endif /* __alpha__ */
-ext2_loff_t ext2_llseek (unsigned int fd, ext2_loff_t offset,
+ext2_loff_t ext2fs_llseek (unsigned int fd, ext2_loff_t offset,
unsigned int origin)
{
ext2_loff_t result;
@@ -84,7 +88,7 @@
#else /* !linux */
-ext2_loff_t ext2_llseek (unsigned int fd, ext2_loff_t offset,
+ext2_loff_t ext2fs_llseek (unsigned int fd, ext2_loff_t offset,
unsigned int origin)
{
if ((sizeof(off_t) < sizeof(ext2_loff_t)) &&
diff --git a/lib/ext2fs/lookup.c b/lib/ext2fs/lookup.c
new file mode 100644
index 0000000..5cded5f
--- /dev/null
+++ b/lib/ext2fs/lookup.c
@@ -0,0 +1,69 @@
+/*
+ * lookup.c --- ext2fs directory lookup operations
+ *
+ * Copyright (C) 1993, 1994, 1994, 1995 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include <linux/ext2_fs.h>
+
+#include "ext2fs.h"
+
+struct lookup_struct {
+ const char *name;
+ int len;
+ ino_t *inode;
+ int found;
+};
+
+static int lookup_proc(struct ext2_dir_entry *dirent,
+ int offset,
+ int blocksize,
+ char *buf,
+ void *private)
+{
+ struct lookup_struct *ls = (struct lookup_struct *) private;
+
+ if (ls->len != dirent->name_len)
+ return 0;
+ if (strncmp(ls->name, dirent->name, dirent->name_len))
+ return 0;
+ *ls->inode = dirent->inode;
+ ls->found++;
+ return DIRENT_ABORT;
+}
+
+
+errcode_t ext2fs_lookup(ext2_filsys fs, ino_t dir, const char *name,
+ int namelen, char *buf, ino_t *inode)
+{
+ errcode_t retval;
+ struct lookup_struct ls;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ ls.name = name;
+ ls.len = namelen;
+ ls.inode = inode;
+ ls.found = 0;
+
+ retval = ext2fs_dir_iterate(fs, dir, 0, buf, lookup_proc, &ls);
+ if (retval)
+ return retval;
+
+ return (ls.found) ? 0 : ENOENT;
+}
+
+
diff --git a/lib/ext2fs/mkdir.c b/lib/ext2fs/mkdir.c
index af3b9b7..67a2046 100644
--- a/lib/ext2fs/mkdir.c
+++ b/lib/ext2fs/mkdir.c
@@ -1,8 +1,12 @@
/*
* mkdir.c --- make a directory in the filesystem
*
- * Copyright (C) 1994 Theodore Ts'o. This file may be redistributed
- * under the terms of the GNU Public License.
+ * Copyright (C) 1994, 1995 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
#include <stdio.h>
diff --git a/lib/ext2fs/namei.c b/lib/ext2fs/namei.c
index 8fc71b0..ae39eec 100644
--- a/lib/ext2fs/namei.c
+++ b/lib/ext2fs/namei.c
@@ -1,8 +1,12 @@
/*
* namei.c --- ext2fs directory lookup operations
*
- * Copyright (C) 1993, 1994 Theodore Ts'o. This file may be
- * redistributed under the terms of the GNU Public License.
+ * Copyright (C) 1993, 1994, 1994, 1995 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
#include <stdio.h>
@@ -19,163 +23,6 @@
#include "ext2fs.h"
-struct dir_context {
- ino_t dir;
- int flags;
- char *buf;
- int (*func)(struct ext2_dir_entry *dirent,
- int offset,
- int blocksize,
- char *buf,
- void *private);
- void *private;
- errcode_t errcode;
-};
-
-static int process_dir_block(ext2_filsys fs,
- blk_t *blocknr,
- int blockcnt,
- void *private);
-
-errcode_t ext2fs_dir_iterate(ext2_filsys fs,
- ino_t dir,
- int flags,
- char *block_buf,
- int (*func)(struct ext2_dir_entry *dirent,
- int offset,
- int blocksize,
- char *buf,
- void *private),
- void *private)
-{
- struct dir_context ctx;
- errcode_t retval;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- retval = ext2fs_check_directory(fs, dir);
- if (retval)
- return retval;
-
- ctx.dir = dir;
- ctx.flags = flags;
- if (block_buf)
- ctx.buf = block_buf;
- else {
- ctx.buf = malloc(fs->blocksize);
- if (!ctx.buf)
- return ENOMEM;
- }
- ctx.func = func;
- ctx.private = private;
- ctx.errcode = 0;
- retval = ext2fs_block_iterate(fs, dir, 0, 0, process_dir_block, &ctx);
- if (!block_buf)
- free(ctx.buf);
- if (retval)
- return retval;
- return ctx.errcode;
-}
-
-static int process_dir_block(ext2_filsys fs,
- blk_t *blocknr,
- int blockcnt,
- void *private)
-{
- struct dir_context *ctx = (struct dir_context *) private;
- int offset = 0;
- int ret;
- int changed = 0;
- int do_abort = 0;
- struct ext2_dir_entry *dirent;
-
- if (blockcnt < 0)
- return 0;
-
- ctx->errcode = ext2fs_read_dir_block(fs, *blocknr, ctx->buf);
- if (ctx->errcode)
- return BLOCK_ABORT;
-
- while (offset < fs->blocksize) {
- dirent = (struct ext2_dir_entry *) (ctx->buf + offset);
- if (!dirent->inode &&
- !(ctx->flags & DIRENT_FLAG_INCLUDE_EMPTY))
- goto next;
-
- ret = (ctx->func)(dirent, offset, fs->blocksize,
- ctx->buf, ctx->private);
- if (ret & DIRENT_CHANGED)
- changed++;
- if (ret & DIRENT_ABORT) {
- do_abort++;
- break;
- }
-next:
- if (((offset + dirent->rec_len) > fs->blocksize) ||
- (dirent->rec_len < 8) ||
- ((dirent->name_len+8) > dirent->rec_len)) {
- ctx->errcode = EXT2_ET_DIR_CORRUPTED;
- return BLOCK_ABORT;
- }
- offset += dirent->rec_len;
- }
-
- if (changed) {
- ctx->errcode = ext2fs_write_dir_block(fs, *blocknr, ctx->buf);
- if (ctx->errcode)
- return BLOCK_ABORT;
- }
- if (do_abort)
- return BLOCK_ABORT;
- return 0;
-}
-
-struct lookup_struct {
- const char *name;
- int len;
- ino_t *inode;
- int found;
-};
-
-static int lookup_proc(struct ext2_dir_entry *dirent,
- int offset,
- int blocksize,
- char *buf,
- void *private)
-{
- struct lookup_struct *ls = (struct lookup_struct *) private;
-
- if (ls->len != dirent->name_len)
- return 0;
- if (strncmp(ls->name, dirent->name, dirent->name_len))
- return 0;
- *ls->inode = dirent->inode;
- ls->found++;
- return DIRENT_ABORT;
-}
-
-
-errcode_t ext2fs_lookup(ext2_filsys fs, ino_t dir, const char *name,
- int namelen, char *buf, ino_t *inode)
-{
- errcode_t retval;
- struct lookup_struct ls;
-
- EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
-
- ls.name = name;
- ls.len = namelen;
- ls.inode = inode;
- ls.found = 0;
-
- retval = ext2fs_dir_iterate(fs, dir, 0, buf, lookup_proc, &ls);
- if (retval)
- return retval;
-
- return (ls.found) ? 0 : ENOENT;
-}
-
-
static errcode_t open_namei(ext2_filsys fs, ino_t root, ino_t base,
const char *pathname, int pathlen, int follow,
int link_count, char *buf, ino_t *res_inode);
diff --git a/lib/ext2fs/native.c b/lib/ext2fs/native.c
index 2f84bf7..3fdc4a0 100644
--- a/lib/ext2fs/native.c
+++ b/lib/ext2fs/native.c
@@ -3,8 +3,10 @@
*
* Copyright (C) 1996 Theodore Ts'o.
*
+ * %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
+ * %End-Header%
*/
#include <stdio.h>
diff --git a/lib/ext2fs/newdir.c b/lib/ext2fs/newdir.c
index 2254726..863960f 100644
--- a/lib/ext2fs/newdir.c
+++ b/lib/ext2fs/newdir.c
@@ -1,8 +1,12 @@
/*
* newdir.c --- create a new directory block
*
- * Copyright (C) 1994 Theodore Ts'o. This file may be redistributed
- * under the terms of the GNU Public License.
+ * Copyright (C) 1994, 1995 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
#include <stdio.h>
diff --git a/lib/ext2fs/openfs.c b/lib/ext2fs/openfs.c
index 389bfc7..b2e2393 100644
--- a/lib/ext2fs/openfs.c
+++ b/lib/ext2fs/openfs.c
@@ -1,10 +1,12 @@
/*
* openfs.c --- open an ext2 filesystem
*
- * Copyright (C) 1993, 1994, 1995 Theodore Ts'o.
+ * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
*
+ * %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
+ * %End-Header%
*/
#include <stdio.h>
@@ -30,6 +32,12 @@
/*
* Note: if superblock is non-zero, block-size must also be non-zero.
* Superblock and block_size can be zero to use the default size.
+ *
+ * Valid flags for ext2fs_open()
+ *
+ * EXT2_FLAG_RW - Open the filesystem for read/write.
+ * EXT2_FLAG_FORCE - Open the filesystem even if some of the
+ * features aren't supported.
*/
errcode_t ext2fs_open(const char *name, int flags, int superblock,
int block_size, io_manager manager, ext2_filsys *ret_fs)
@@ -39,6 +47,7 @@
int i, j, group_block, groups_per_block;
char *dest;
struct ext2_group_desc *gdp;
+ struct ext2fs_sb *s;
EXT2_CHECK_MAGIC(manager, EXT2_ET_MAGIC_IO_MANAGER);
@@ -112,6 +121,22 @@
}
#endif
#endif
+ /*
+ * Check for feature set incompatibility
+ */
+ if (!(flags & EXT2_FLAG_FORCE)) {
+ s = (struct ext2fs_sb *) fs->super;
+ if (s->s_feature_incompat) {
+ retval = EXT2_ET_UNSUPP_FEATURE;
+ goto cleanup;
+ }
+ if ((flags & EXT2_FLAG_RW) &&
+ s->s_feature_ro_compat) {
+ retval = EXT2_ET_RO_UNSUPP_FEATURE;
+ goto cleanup;
+ }
+ }
+
fs->blocksize = EXT2_BLOCK_SIZE(fs->super);
if (fs->blocksize == 0) {
retval = EXT2_ET_CORRUPT_SUPERBLOCK;
diff --git a/lib/ext2fs/read_bb.c b/lib/ext2fs/read_bb.c
index 1a9f774..3fabddd 100644
--- a/lib/ext2fs/read_bb.c
+++ b/lib/ext2fs/read_bb.c
@@ -1,8 +1,12 @@
/*
* read_bb --- read the bad blocks inode
*
- * Copyright (C) 1994 Theodore Ts'o. This file may be redistributed
- * under the terms of the GNU Public License.
+ * Copyright (C) 1994 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
#include <stdio.h>
@@ -19,7 +23,7 @@
#include "ext2fs.h"
struct read_bb_record {
- badblocks_list bb_list;
+ ext2_badblocks_list bb_list;
errcode_t err;
};
@@ -34,7 +38,7 @@
if (blockcnt < 0)
return 0;
- rb->err = badblocks_list_add(rb->bb_list, *block_nr);
+ rb->err = ext2fs_badblocks_list_add(rb->bb_list, *block_nr);
if (rb->err)
return BLOCK_ABORT;
return 0;
@@ -43,7 +47,7 @@
/*
* Reads the current bad blocks from the bad blocks inode.
*/
-errcode_t ext2fs_read_bb_inode(ext2_filsys fs, badblocks_list *bb_list)
+errcode_t ext2fs_read_bb_inode(ext2_filsys fs, ext2_badblocks_list *bb_list)
{
errcode_t retval;
struct read_bb_record rb;
@@ -57,7 +61,7 @@
if (retval)
return retval;
numblocks = (inode.i_blocks / (fs->blocksize / 512)) + 20;
- retval = badblocks_list_create(bb_list, numblocks);
+ retval = ext2fs_badblocks_list_create(bb_list, numblocks);
if (retval)
return retval;
}
diff --git a/lib/ext2fs/read_bb_file.c b/lib/ext2fs/read_bb_file.c
index 04e1581..16c2e0b 100644
--- a/lib/ext2fs/read_bb_file.c
+++ b/lib/ext2fs/read_bb_file.c
@@ -1,8 +1,12 @@
/*
* read_bb_file.c --- read a list of bad blocks for a FILE *
*
- * Copyright (C) 1994 Theodore Ts'o. This file may be redistributed
- * under the terms of the GNU Public License.
+ * Copyright (C) 1994, 1995 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
#include <stdio.h>
@@ -22,7 +26,7 @@
* Reads a list of bad blocks from a FILE *
*/
errcode_t ext2fs_read_bb_FILE(ext2_filsys fs, FILE *f,
- badblocks_list *bb_list,
+ ext2_badblocks_list *bb_list,
void (*invalid)(ext2_filsys fs, blk_t blk))
{
errcode_t retval;
@@ -33,7 +37,7 @@
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
if (!*bb_list) {
- retval = badblocks_list_create(bb_list, 10);
+ retval = ext2fs_badblocks_list_create(bb_list, 10);
if (retval)
return retval;
}
@@ -50,7 +54,7 @@
(invalid)(fs, blockno);
continue;
}
- retval = badblocks_list_add(*bb_list, blockno);
+ retval = ext2fs_badblocks_list_add(*bb_list, blockno);
if (retval)
return retval;
}
diff --git a/lib/ext2fs/rs_bitmap.c b/lib/ext2fs/rs_bitmap.c
new file mode 100644
index 0000000..9017853
--- /dev/null
+++ b/lib/ext2fs/rs_bitmap.c
@@ -0,0 +1,92 @@
+/*
+ * rs_bitmap.c --- routine for changing the size of a bitmap
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include <linux/ext2_fs.h>
+
+#include "ext2fs.h"
+
+errcode_t ext2fs_resize_generic_bitmap(__u32 new_end, __u32 new_real_end,
+ ext2fs_generic_bitmap bmap)
+{
+ size_t size, new_size;
+ char *new_bitmap;
+
+ if (!bmap)
+ return EINVAL;
+
+ EXT2_CHECK_MAGIC(bmap, EXT2_ET_MAGIC_GENERIC_BITMAP);
+
+ if (new_real_end == bmap->real_end) {
+ bmap->end = new_end;
+ return 0;
+ }
+
+ size = ((bmap->real_end - bmap->start) / 8) + 1;
+ new_size = ((new_real_end - bmap->start) / 8) + 1;
+
+ new_bitmap = realloc(bmap->bitmap, new_size);
+ if (!new_bitmap)
+ return ENOMEM;
+ if (new_size > size)
+ memset(new_bitmap + size, 0, new_size - size);
+
+ bmap->bitmap = new_bitmap;
+ bmap->end = new_end;
+ bmap->real_end = new_real_end;
+ return 0;
+}
+
+errcode_t ext2fs_resize_inode_bitmap(__u32 new_end, __u32 new_real_end,
+ ext2fs_inode_bitmap bmap)
+{
+ errcode_t retval;
+
+ if (!bmap)
+ return EINVAL;
+
+ EXT2_CHECK_MAGIC(bmap, EXT2_ET_MAGIC_INODE_BITMAP);
+
+ bmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
+ retval = ext2fs_resize_generic_bitmap(new_end, new_real_end,
+ bmap);
+ bmap->magic = EXT2_ET_MAGIC_INODE_BITMAP;
+ return retval;
+}
+
+errcode_t ext2fs_resize_block_bitmap(__u32 new_end, __u32 new_real_end,
+ ext2fs_block_bitmap bmap)
+{
+ errcode_t retval;
+
+ if (!bmap)
+ return EINVAL;
+
+ EXT2_CHECK_MAGIC(bmap, EXT2_ET_MAGIC_BLOCK_BITMAP);
+
+ bmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP;
+ retval = ext2fs_resize_generic_bitmap(new_end, new_real_end,
+ bmap);
+ bmap->magic = EXT2_ET_MAGIC_BLOCK_BITMAP;
+ return retval;
+}
+
diff --git a/lib/ext2fs/rw_bitmaps.c b/lib/ext2fs/rw_bitmaps.c
index 3a3f51f..e9bb58c 100644
--- a/lib/ext2fs/rw_bitmaps.c
+++ b/lib/ext2fs/rw_bitmaps.c
@@ -1,8 +1,12 @@
/*
* rw_bitmaps.c --- routines to read and write the inode and block bitmaps.
*
- * Copyright (C) 1993,1994 Theodore Ts'o. This file may be redistributed
- * under the terms of the GNU Public License.
+ * Copyright (C) 1993, 1994, 1994, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
#include <stdio.h>
@@ -28,6 +32,7 @@
errcode_t retval;
char * inode_bitmap = fs->inode_map->bitmap;
char * bitmap_block = NULL;
+ blk_t blk;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
@@ -43,11 +48,13 @@
memset(bitmap_block, 0xff, fs->blocksize);
for (i = 0; i < fs->group_desc_count; i++) {
memcpy(bitmap_block, inode_bitmap, nbytes);
- retval = io_channel_write_blk(fs->io,
- fs->group_desc[i].bg_inode_bitmap, 1,
- bitmap_block);
- if (retval)
- return EXT2_ET_INODE_BITMAP_WRITE;
+ blk = fs->group_desc[i].bg_inode_bitmap;
+ if (blk) {
+ retval = io_channel_write_blk(fs->io, blk, 1,
+ bitmap_block);
+ if (retval)
+ return EXT2_ET_INODE_BITMAP_WRITE;
+ }
inode_bitmap += nbytes;
}
fs->flags |= EXT2_FLAG_CHANGED;
@@ -65,6 +72,7 @@
errcode_t retval;
char * block_bitmap = fs->block_map->bitmap;
char * bitmap_block = NULL;
+ blk_t blk;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
@@ -88,11 +96,13 @@
for (j = nbits; j < fs->blocksize * 8; j++)
ext2fs_set_bit(j, bitmap_block);
}
- retval = io_channel_write_blk(fs->io,
- fs->group_desc[i].bg_block_bitmap, 1,
- bitmap_block);
- if (retval)
- return EXT2_ET_BLOCK_BITMAP_WRITE;
+ blk = fs->group_desc[i].bg_block_bitmap;
+ if (blk) {
+ retval = io_channel_write_blk(fs->io, blk, 1,
+ bitmap_block);
+ if (retval)
+ return EXT2_ET_BLOCK_BITMAP_WRITE;
+ }
block_bitmap += nbytes;
}
fs->flags |= EXT2_FLAG_CHANGED;
@@ -109,6 +119,7 @@
errcode_t retval;
int block_nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8;
int inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8;
+ blk_t blk;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
@@ -137,25 +148,29 @@
for (i = 0; i < fs->group_desc_count; i++) {
if (block_bitmap) {
- retval = io_channel_read_blk
- (fs->io,
- fs->group_desc[i].bg_block_bitmap,
- -block_nbytes, block_bitmap);
- if (retval) {
- retval = EXT2_ET_BLOCK_BITMAP_READ;
- goto cleanup;
- }
+ blk = fs->group_desc[i].bg_block_bitmap;
+ if (blk) {
+ retval = io_channel_read_blk(fs->io, blk,
+ -block_nbytes, block_bitmap);
+ if (retval) {
+ retval = EXT2_ET_BLOCK_BITMAP_READ;
+ goto cleanup;
+ }
+ } else
+ memset(block_bitmap, 0, block_nbytes);
block_bitmap += block_nbytes;
}
if (inode_bitmap) {
- retval = io_channel_read_blk
- (fs->io,
- fs->group_desc[i].bg_inode_bitmap,
- -inode_nbytes, inode_bitmap);
- if (retval) {
- retval = EXT2_ET_INODE_BITMAP_READ;
- goto cleanup;
- }
+ blk = fs->group_desc[i].bg_inode_bitmap;
+ if (blk) {
+ retval = io_channel_read_blk(fs->io, blk,
+ -inode_nbytes, inode_bitmap);
+ if (retval) {
+ retval = EXT2_ET_INODE_BITMAP_READ;
+ goto cleanup;
+ }
+ } else
+ memset(inode_bitmap, 0, inode_nbytes);
inode_bitmap += inode_nbytes;
}
}
diff --git a/lib/ext2fs/swapfs.c b/lib/ext2fs/swapfs.c
index 968f41c..de347ac 100644
--- a/lib/ext2fs/swapfs.c
+++ b/lib/ext2fs/swapfs.c
@@ -1,8 +1,12 @@
/*
* swapfs.c --- swap ext2 filesystem data structures
*
- * Copyright (C) 1995 Theodore Ts'o. This file may be redistributed
- * under the terms of the GNU Public License.
+ * Copyright (C) 1995, 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
#include <stdio.h>
@@ -98,9 +102,15 @@
switch (fs->super->s_creator_os) {
case EXT2_OS_LINUX:
+ t->osd1.linux1.l_i_reserved1 =
+ ext2fs_swab32(f->osd1.linux1.l_i_reserved1);
t->osd2.linux2.l_i_frag = f->osd2.linux2.l_i_frag;
t->osd2.linux2.l_i_fsize = f->osd2.linux2.l_i_fsize;
t->osd2.linux2.i_pad1 = ext2fs_swab16(f->osd2.linux2.i_pad1);
+ t->osd2.linux2.l_i_reserved2[0] =
+ ext2fs_swab32(f->osd2.linux2.l_i_reserved2[0]);
+ t->osd2.linux2.l_i_reserved2[1] =
+ ext2fs_swab32(f->osd2.linux2.l_i_reserved2[1]);
break;
case EXT2_OS_HURD:
t->osd1.hurd1.h_i_translator =
@@ -117,9 +127,15 @@
ext2fs_swab32 (f->osd2.hurd2.h_i_author);
break;
case EXT2_OS_MASIX:
+ t->osd1.masix1.m_i_reserved1 =
+ ext2fs_swab32(f->osd1.masix1.m_i_reserved1);
t->osd2.masix2.m_i_frag = f->osd2.masix2.m_i_frag;
t->osd2.masix2.m_i_fsize = f->osd2.masix2.m_i_fsize;
t->osd2.masix2.m_pad1 = ext2fs_swab16(f->osd2.masix2.m_pad1);
+ t->osd2.masix2.m_i_reserved2[0] =
+ ext2fs_swab32(f->osd2.masix2.m_i_reserved2[0]);
+ t->osd2.masix2.m_i_reserved2[1] =
+ ext2fs_swab32(f->osd2.masix2.m_i_reserved2[1]);
break;
}
}
diff --git a/lib/ext2fs/test_io.c b/lib/ext2fs/test_io.c
new file mode 100644
index 0000000..1bd09b1
--- /dev/null
+++ b/lib/ext2fs/test_io.c
@@ -0,0 +1,227 @@
+/*
+ * test_io.c --- This is the Test I/O interface.
+ *
+ * Copyright (C) 1996 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "et/com_err.h"
+#include "ext2fs/ext2_err.h"
+#include "io.h"
+
+/*
+ * For checking structure magic numbers...
+ */
+
+#define EXT2_CHECK_MAGIC(struct, code) \
+ if ((struct)->magic != (code)) return (code)
+
+struct test_private_data {
+ int magic;
+ io_channel real;
+ void (*read_blk)(unsigned long block, int count, errcode_t err);
+ void (*write_blk)(unsigned long block, int count, errcode_t err);
+ void (*set_blksize)(int blksize, errcode_t err);
+};
+
+static errcode_t test_open(const char *name, int flags, io_channel *channel);
+static errcode_t test_close(io_channel channel);
+static errcode_t test_set_blksize(io_channel channel, int blksize);
+static errcode_t test_read_blk(io_channel channel, unsigned long block,
+ int count, void *data);
+static errcode_t test_write_blk(io_channel channel, unsigned long block,
+ int count, const void *data);
+static errcode_t test_flush(io_channel channel);
+
+static struct struct_io_manager struct_test_manager = {
+ EXT2_ET_MAGIC_IO_MANAGER,
+ "Test I/O Manager",
+ test_open,
+ test_close,
+ test_set_blksize,
+ test_read_blk,
+ test_write_blk,
+ test_flush
+};
+
+io_manager test_io_manager = &struct_test_manager;
+
+/*
+ * These global variable can be set by the test program as
+ * necessary *before* calling test_open
+ */
+io_manager test_io_backing_manager = 0;
+void (*test_io_cb_read_blk)
+ (unsigned long block, int count, errcode_t err) = 0;
+void (*test_io_cb_write_blk)
+ (unsigned long block, int count, errcode_t err) = 0;
+void (*test_io_cb_set_blksize)
+ (int blksize, errcode_t err) = 0;
+
+static errcode_t test_open(const char *name, int flags, io_channel *channel)
+{
+ io_channel io = NULL;
+ struct test_private_data *data = NULL;
+ errcode_t retval;
+
+ if (name == 0)
+ return EXT2_ET_BAD_DEVICE_NAME;
+ io = (io_channel) malloc(sizeof(struct struct_io_channel));
+ if (!io)
+ return ENOMEM;
+ memset(io, 0, sizeof(struct struct_io_channel));
+ io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
+ data = (struct test_private_data *)
+ malloc(sizeof(struct test_private_data));
+ if (!data) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ io->manager = test_io_manager;
+ io->name = malloc(strlen(name)+1);
+ if (!io->name) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ strcpy(io->name, name);
+ io->private_data = data;
+ io->block_size = 1024;
+ io->read_error = 0;
+ io->write_error = 0;
+
+ memset(data, 0, sizeof(struct test_private_data));
+ data->magic = EXT2_ET_MAGIC_TEST_IO_CHANNEL;
+ if (test_io_backing_manager) {
+ retval = test_io_backing_manager->open(name, flags,
+ &data->real);
+ if (retval)
+ goto cleanup;
+ } else
+ data->real = 0;
+ data->read_blk = test_io_cb_read_blk;
+ data->write_blk = test_io_cb_write_blk;
+ data->set_blksize = test_io_cb_set_blksize;
+
+ *channel = io;
+ return 0;
+
+cleanup:
+ if (io)
+ free(io);
+ if (data)
+ free(data);
+ return retval;
+}
+
+static errcode_t test_close(io_channel channel)
+{
+ struct test_private_data *data;
+ errcode_t retval = 0;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ data = (struct test_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
+
+ if (data->real)
+ retval = io_channel_close(data->real);
+
+ if (channel->private_data)
+ free(channel->private_data);
+ if (channel->name)
+ free(channel->name);
+ free(channel);
+ return retval;
+}
+
+static errcode_t test_set_blksize(io_channel channel, int blksize)
+{
+ struct test_private_data *data;
+ errcode_t retval = 0;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ data = (struct test_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
+
+ if (data->real)
+ retval = io_channel_set_blksize(data->real, blksize);
+ if (data->set_blksize)
+ data->set_blksize(blksize, retval);
+ else
+ printf("Test_io: set_blksize(%d) returned %s\n",
+ blksize, retval ? error_message(retval) : "OK");
+ return retval;
+}
+
+
+static errcode_t test_read_blk(io_channel channel, unsigned long block,
+ int count, void *buf)
+{
+ struct test_private_data *data;
+ errcode_t retval = 0;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ data = (struct test_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
+
+ if (data->real)
+ retval = io_channel_read_blk(data->real, block, count, buf);
+ if (data->read_blk)
+ data->read_blk(block, count, retval);
+ else
+ printf("Test_io: read_blk(%lu, %d) returned %s\n",
+ block, count, retval ? error_message(retval) : "OK");
+ return retval;
+}
+
+static errcode_t test_write_blk(io_channel channel, unsigned long block,
+ int count, const void *buf)
+{
+ struct test_private_data *data;
+ errcode_t retval = 0;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ data = (struct test_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
+
+ if (data->real)
+ retval = io_channel_write_blk(data->real, block, count, buf);
+ if (data->write_blk)
+ data->write_blk(block, count, retval);
+ else
+ printf("Test_io: write_blk(%lu, %d) returned %s\n",
+ block, count, retval ? error_message(retval) : "OK");
+ return retval;
+}
+
+/*
+ * Flush data buffers to disk.
+ */
+static errcode_t test_flush(io_channel channel)
+{
+ struct test_private_data *data;
+
+ EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
+ data = (struct test_private_data *) channel->private_data;
+ EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL);
+
+ if (data->real)
+ return io_channel_flush(data->real);
+ return 0;
+}
+
diff --git a/lib/ext2fs/tst_badblocks.c b/lib/ext2fs/tst_badblocks.c
new file mode 100644
index 0000000..d071406
--- /dev/null
+++ b/lib/ext2fs/tst_badblocks.c
@@ -0,0 +1,162 @@
+/*
+ * This testing program makes sure the badblocks implementation works.
+ *
+ * Copyright (C) 1996 by Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include <linux/ext2_fs.h>
+
+#include "ext2fs.h"
+
+blk_t test1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0 };
+blk_t test2[] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
+blk_t test3[] = { 3, 1, 4, 5, 9, 2, 7, 10, 6, 8, 0 };
+blk_t test4[] = { 20, 50, 12, 17, 13, 2, 66, 23, 56, 0 };
+blk_t test4a[] = {
+ 20, 1,
+ 50, 1,
+ 3, 0,
+ 17, 1,
+ 18, 0,
+ 16, 0,
+ 11, 0,
+ 12, 1,
+ 13, 1,
+ 14, 0,
+ 80, 0,
+ 45, 0,
+ 66, 1,
+ 0 };
+
+static int test_fail = 0;
+
+static errcode_t create_test_list(blk_t *vec, badblocks_list *ret)
+{
+ errcode_t retval;
+ badblocks_list bb;
+ int i;
+
+ retval = badblocks_list_create(&bb, 5);
+ if (retval) {
+ com_err("create_test_list", retval, "while creating list");
+ return retval;
+ }
+ for (i=0; vec[i]; i++) {
+ retval = badblocks_list_add(bb, vec[i]);
+ if (retval) {
+ com_err("create_test_list", retval,
+ "while adding test vector %d", i);
+ badblocks_list_free(bb);
+ return retval;
+ }
+ }
+ *ret = bb;
+ return 0;
+}
+
+static void print_list(badblocks_list bb, int verify)
+{
+ errcode_t retval;
+ badblocks_iterate iter;
+ blk_t blk;
+ int i, ok;
+
+ retval = badblocks_list_iterate_begin(bb, &iter);
+ if (retval) {
+ com_err("print_list", retval, "while setting up iterator");
+ return;
+ }
+ ok = i = 1;
+ while (badblocks_list_iterate(iter, &blk)) {
+ printf("%d ", blk);
+ if (i++ != blk)
+ ok = 0;
+ }
+ badblocks_list_iterate_end(iter);
+ if (verify) {
+ if (ok)
+ printf("--- OK");
+ else {
+ printf("--- NOT OK");
+ test_fail++;
+ }
+ }
+}
+
+static void validate_test_seq(badblocks_list bb, blk_t *vec)
+{
+ int i, match, ok;
+
+ for (i = 0; vec[i]; i += 2) {
+ match = badblocks_list_test(bb, vec[i]);
+ if (match == vec[i+1])
+ ok = 1;
+ else {
+ ok = 0;
+ test_fail++;
+ }
+ printf("\tblock %d is %s --- %s\n", vec[i],
+ match ? "present" : "absent",
+ ok ? "OK" : "NOT OK");
+ }
+}
+
+int main(int argc, char *argv)
+{
+ badblocks_list bb;
+ errcode_t retval;
+
+ printf("test1: ");
+ retval = create_test_list(test1, &bb);
+ if (retval == 0) {
+ print_list(bb, 1);
+ badblocks_list_free(bb);
+ }
+ printf("\n");
+
+ printf("test2: ");
+ retval = create_test_list(test2, &bb);
+ if (retval == 0) {
+ print_list(bb, 1);
+ badblocks_list_free(bb);
+ }
+ printf("\n");
+
+ printf("test3: ");
+ retval = create_test_list(test3, &bb);
+ if (retval == 0) {
+ print_list(bb, 1);
+ badblocks_list_free(bb);
+ }
+ printf("\n");
+
+ printf("test4: ");
+ retval = create_test_list(test4, &bb);
+ if (retval == 0) {
+ print_list(bb, 0);
+ printf("\n");
+ validate_test_seq(bb, test4a);
+ badblocks_list_free(bb);
+ }
+ printf("\n");
+ if (test_fail == 0)
+ printf("ext2fs library badblocks tests checks out OK!\n");
+ return test_fail;
+}
diff --git a/lib/ext2fs/tst_iscan.c b/lib/ext2fs/tst_iscan.c
new file mode 100644
index 0000000..dbf0813
--- /dev/null
+++ b/lib/ext2fs/tst_iscan.c
@@ -0,0 +1,218 @@
+/*
+ * tst_inode.c --- this function tests the inode scan function
+ *
+ * Copyright (C) 1996 by Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include <linux/ext2_fs.h>
+
+#include "ext2fs.h"
+
+blk_t test_vec[] = { 8, 12, 24, 34, 43, 44, 100, 0 };
+
+ext2_filsys test_fs;
+ext2fs_block_bitmap bad_block_map, touched_map;
+ext2fs_inode_bitmap bad_inode_map;
+badblocks_list test_badblocks;
+
+int first_no_comma = 1;
+int failed = 0;
+
+static void test_read_blk(unsigned long block, int count, errcode_t err)
+{
+ int i;
+
+ if (first_no_comma)
+ first_no_comma = 0;
+ else
+ printf(", ");
+
+ if (count > 1)
+ printf("%lu-%lu", block, block+count-1);
+ else
+ printf("%lu", block);
+
+ for (i=0; i < count; i++, block++) {
+ if (ext2fs_test_block_bitmap(touched_map, block)) {
+ printf("\nDuplicate block?!? --- %lu\n", block);
+ failed++;
+ first_no_comma = 1;
+ }
+ ext2fs_mark_block_bitmap(touched_map, block);
+ }
+}
+
+/*
+ * Setup the variables for doing the inode scan test.
+ */
+static void setup(void)
+{
+ errcode_t retval;
+ int i;
+ struct ext2_super_block param;
+
+ initialize_ext2_error_table();
+
+ memset(¶m, 0, sizeof(param));
+ param.s_blocks_count = 12000;
+
+
+ test_io_cb_read_blk = test_read_blk;
+
+ retval = ext2fs_initialize("test fs", 0, ¶m,
+ test_io_manager, &test_fs);
+ if (retval) {
+ com_err("setup", retval,
+ "While initializing filesystem");
+ exit(1);
+ }
+ retval = ext2fs_allocate_tables(test_fs);
+ if (retval) {
+ com_err("setup", retval,
+ "While allocating tables for test filesystem");
+ exit(1);
+ }
+ retval = ext2fs_allocate_block_bitmap(test_fs, "bad block map",
+ &bad_block_map);
+ if (retval) {
+ com_err("setup", retval,
+ "While allocating bad_block bitmap");
+ exit(1);
+ }
+ retval = ext2fs_allocate_block_bitmap(test_fs, "touched map",
+ &touched_map);
+ if (retval) {
+ com_err("setup", retval,
+ "While allocating touched block bitmap");
+ exit(1);
+ }
+ retval = ext2fs_allocate_inode_bitmap(test_fs, "bad inode map",
+ &bad_inode_map);
+ if (retval) {
+ com_err("setup", retval,
+ "While allocating bad inode bitmap");
+ exit(1);
+ }
+
+ retval = badblocks_list_create(&test_badblocks, 5);
+ if (retval) {
+ com_err("setup", retval, "while creating badblocks list");
+ exit(1);
+ }
+ for (i=0; test_vec[i]; i++) {
+ retval = badblocks_list_add(test_badblocks, test_vec[i]);
+ if (retval) {
+ com_err("setup", retval,
+ "while adding test vector %d", i);
+ exit(1);
+ }
+ ext2fs_mark_block_bitmap(bad_block_map, test_vec[i]);
+ }
+ test_fs->badblocks = test_badblocks;
+}
+
+/*
+ * Iterate using inode_scan
+ */
+static void iterate(void)
+{
+ struct ext2_inode inode;
+ ext2_inode_scan scan;
+ errcode_t retval;
+ ino_t ino;
+
+ retval = ext2fs_open_inode_scan(test_fs, 8, &scan);
+ if (retval) {
+ com_err("iterate", retval, "While opening inode scan");
+ exit(1);
+ }
+ printf("Reading blocks: ");
+ retval = ext2fs_get_next_inode(scan, &ino, &inode);
+ if (retval) {
+ com_err("iterate", retval, "while reading first inode");
+ exit(1);
+ }
+ while (ino) {
+ retval = ext2fs_get_next_inode(scan, &ino, &inode);
+ if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
+ ext2fs_mark_inode_bitmap(bad_inode_map, ino);
+ continue;
+ }
+ if (retval) {
+ com_err("iterate", retval,
+ "while getting next inode");
+ exit(1);
+ }
+ }
+ printf("\n");
+ ext2fs_close_inode_scan(scan);
+}
+
+/*
+ * Verify the touched map
+ */
+static void check_map(void)
+{
+ int i, j, first=1;
+ unsigned long blk;
+
+ for (i=0; test_vec[i]; i++) {
+ if (ext2fs_test_block_bitmap(touched_map, test_vec[i])) {
+ printf("Bad block was touched --- %d\n", test_vec[i]);
+ failed++;
+ first_no_comma = 1;
+ }
+ ext2fs_mark_block_bitmap(touched_map, test_vec[i]);
+ }
+ for (i = 0; i < test_fs->group_desc_count; i++) {
+ for (j=0, blk = test_fs->group_desc[i].bg_inode_table;
+ j < test_fs->inode_blocks_per_group;
+ j++, blk++) {
+ if (!ext2fs_test_block_bitmap(touched_map, blk) &&
+ !ext2fs_test_block_bitmap(bad_block_map, blk)) {
+ printf("Missing block --- %lu\n", blk);
+ failed++;
+ }
+ }
+ }
+ printf("Bad inodes: ");
+ for (i=1; i <= test_fs->super->s_inodes_count; i++) {
+ if (ext2fs_test_inode_bitmap(bad_inode_map, i)) {
+ if (first)
+ first = 0;
+ else
+ printf(", ");
+ printf("%d", i);
+ }
+ }
+ printf("\n");
+}
+
+
+int main(int argc, char **argv)
+{
+ setup();
+ iterate();
+ check_map();
+ if (!failed)
+ printf("Inode scan tested OK!\n");
+ return failed;
+}
+
diff --git a/lib/ext2fs/unix_io.c b/lib/ext2fs/unix_io.c
index b995515..5083771 100644
--- a/lib/ext2fs/unix_io.c
+++ b/lib/ext2fs/unix_io.c
@@ -3,8 +3,12 @@
*
* Implements a one-block write-through cache.
*
- * Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
- * under the terms of the GNU Public License.
+ * Copyright (C) 1993, 1994, 1995 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
#include <stdio.h>
@@ -184,7 +188,7 @@
#endif
size = (count < 0) ? -count : count * channel->block_size;
location = (ext2_loff_t) block * channel->block_size;
- if (ext2_llseek(data->dev, location, SEEK_SET) != location) {
+ if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
retval = errno;
goto error_out;
}
@@ -233,7 +237,7 @@
}
location = (ext2_loff_t) block * channel->block_size;
- if (ext2_llseek(data->dev, location, SEEK_SET) != location) {
+ if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) {
retval = errno;
goto error_out;
}
diff --git a/lib/ext2fs/unlink.c b/lib/ext2fs/unlink.c
new file mode 100644
index 0000000..e0309aa
--- /dev/null
+++ b/lib/ext2fs/unlink.c
@@ -0,0 +1,72 @@
+/*
+ * unlink.c --- delete links in a ext2fs directory
+ *
+ * Copyright (C) 1993, 1994, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <linux/ext2_fs.h>
+
+#include "ext2fs.h"
+
+struct link_struct {
+ const char *name;
+ int namelen;
+ ino_t inode;
+ int flags;
+ int done;
+};
+
+static int unlink_proc(struct ext2_dir_entry *dirent,
+ int offset,
+ int blocksize,
+ char *buf,
+ void *private)
+{
+ struct link_struct *ls = (struct link_struct *) private;
+
+ if (ls->name && (dirent->name_len != ls->namelen))
+ return 0;
+ if (ls->name && strncmp(ls->name, dirent->name, dirent->name_len))
+ return 0;
+ if (ls->inode && (dirent->inode != ls->inode))
+ return 0;
+
+ dirent->inode = 0;
+ ls->done++;
+ return DIRENT_ABORT|DIRENT_CHANGED;
+}
+
+errcode_t ext2fs_unlink(ext2_filsys fs, ino_t dir, const char *name, ino_t ino,
+ int flags)
+{
+ errcode_t retval;
+ struct link_struct ls;
+
+ EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
+
+ if (!(fs->flags & EXT2_FLAG_RW))
+ return EXT2_ET_RO_FILSYS;
+
+ ls.name = name;
+ ls.namelen = name ? strlen(name) : 0;
+ ls.inode = ino;
+ ls.flags = 0;
+ ls.done = 0;
+
+ retval = ext2fs_dir_iterate(fs, dir, 0, 0, unlink_proc, &ls);
+ if (retval)
+ return retval;
+
+ return (ls.done) ? 0 : EXT2_ET_DIR_NO_SPACE;
+}
+
diff --git a/lib/ext2fs/valid_blk.c b/lib/ext2fs/valid_blk.c
new file mode 100644
index 0000000..3a0cb3e
--- /dev/null
+++ b/lib/ext2fs/valid_blk.c
@@ -0,0 +1,49 @@
+/*
+ * valid_blk.c --- does the inode have valid blocks?
+ *
+ * Copyright 1997 by Theodore Ts'o
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ *
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include <linux/ext2_fs.h>
+
+#include "ext2fs.h"
+
+/*
+ * This function returns 1 if the inode's block entries actually
+ * contain block entries.
+ */
+int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode)
+{
+ /*
+ * Only directories, regular files, and some symbolic links
+ * have valid block entries.
+ */
+ if (!LINUX_S_ISDIR(inode->i_mode) && !LINUX_S_ISREG(inode->i_mode) &&
+ !LINUX_S_ISLNK(inode->i_mode))
+ return 0;
+
+ /*
+ * If the symbolic link is a "fast symlink", then the symlink
+ * target is stored in the block entries.
+ */
+ if (LINUX_S_ISLNK (inode->i_mode) && inode->i_blocks == 0 &&
+ inode->i_size < EXT2_N_BLOCKS * sizeof (unsigned long))
+ return 0;
+
+ return 1;
+}
diff --git a/lib/ss/ChangeLog b/lib/ss/ChangeLog
index 2aca3d9..e5467a0 100644
--- a/lib/ss/ChangeLog
+++ b/lib/ss/ChangeLog
@@ -1,3 +1,20 @@
+Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o <tytso@mit.edu>
+
+ * Release of E2fsprogs version 1.07
+
+Wed Mar 12 21:54:32 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * help.c, pager.c, ss.h: Don't use "extern int errno", but use
+ #include <errno.h> instead.
+
+Thu Jan 2 00:16:03 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * parse.c: Put in an include of string.h
+
+Tue Oct 8 02:02:03 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs version 1.06
+
Thu Sep 12 15:23:07 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* Release of E2fsprogs version 1.05
diff --git a/lib/ss/Makefile.in b/lib/ss/Makefile.in
index 777c34b..d3b6bf4 100644
--- a/lib/ss/Makefile.in
+++ b/lib/ss/Makefile.in
@@ -29,6 +29,7 @@
ELF_IMAGE = libss
ELF_MYDIR = ss
ELF_INSTALL_DIR = $(libdir)
+ELF_OTHER_LIBS = -lc -L../.. -lcom_err
BSDLIB_VERSION = 1.0
BSDLIB_IMAGE = libss
@@ -46,7 +47,7 @@
.c.o:
$(CC) $(ALL_CFLAGS) -c $<
-@PROFILE_CMT@ $(CC) $(ALL_CFLAGS) -pg -o profiled/$*.o -c $<
+@PROFILE_CMT@ $(CC) $(ALL_CFLAGS) -g -pg -o profiled/$*.o -c $<
@CHECKER_CMT@ $(CC) $(ALL_CFLAGS) -checker -g -o checker/$*.o -c $<
@DLL_CMT@ (export JUMP_DIR=`pwd`/jump; $(CC) -B$(JUMP_PREFIX) \
@DLL_CMT@ $(ALL_CFLAGS) -o jump/$*.o -c $<)
diff --git a/lib/ss/help.c b/lib/ss/help.c
index 3f3c7f5..5a17164 100644
--- a/lib/ss/help.c
+++ b/lib/ss/help.c
@@ -10,6 +10,11 @@
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#else
+extern int errno;
+#endif
#include <fcntl.h>
#include <sys/param.h>
#include <sys/types.h>
@@ -22,8 +27,6 @@
#include "ss_internal.h"
#include "copyright.h"
-extern int errno;
-
void ss_help (argc, argv, sci_idx, info_ptr)
int argc;
char const * const *argv;
diff --git a/lib/ss/pager.c b/lib/ss/pager.c
index bc5c9b5..1a70773 100644
--- a/lib/ss/pager.c
+++ b/lib/ss/pager.c
@@ -12,6 +12,8 @@
#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
+#else
+extern int errno;
#endif
#include "ss_internal.h"
@@ -24,7 +26,6 @@
static char MORE[] = "more";
extern char *_ss_pager_name;
extern char *getenv();
-extern int errno;
/*
* this needs a *lot* of work....
diff --git a/lib/ss/parse.c b/lib/ss/parse.c
index 38b8e5b..80175d3 100644
--- a/lib/ss/parse.c
+++ b/lib/ss/parse.c
@@ -7,6 +7,7 @@
#ifdef HAS_STDLIB_H
#include <stdlib.h>
#endif
+#include <string.h>
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
diff --git a/lib/ss/ss.h b/lib/ss/ss.h
index 3b86f87..104e038 100644
--- a/lib/ss/ss.h
+++ b/lib/ss/ss.h
@@ -10,8 +10,6 @@
#include <ss/copyright.h>
#include <ss/ss_err.h>
-extern int errno;
-
#ifdef __STDC__
#define __SS_CONST const
#define __SS_PROTO (int, const char * const *, int, void *)
diff --git a/lib/ss/test_ss.c b/lib/ss/test_ss.c
index a4601f6..64f0e2a 100644
--- a/lib/ss/test_ss.c
+++ b/lib/ss/test_ss.c
@@ -9,8 +9,8 @@
* $Locker$
*
* $Log$
- * Revision 1.9 1997/04/29 15:29:28 tytso
- * Checked in e2fsprogs 1.06
+ * Revision 1.10 1997/04/29 16:15:48 tytso
+ * Checked in e2fsprogs-1.07
*
* Revision 1.1 1993/06/03 12:31:25 tytso
* Initial revision
diff --git a/lib/uuid/ChangeLog b/lib/uuid/ChangeLog
index b276ddb..6739575 100644
--- a/lib/uuid/ChangeLog
+++ b/lib/uuid/ChangeLog
@@ -1,3 +1,34 @@
+Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o <tytso@mit.edu>
+
+ * Release of E2fsprogs version 1.07
+
+Sun Mar 2 16:45:36 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Makefile.in (ELF_VERSION): Change version to be 1.1
+
+Thu Feb 6 23:08:07 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * gen_uuid.c (uuid_generate): Set Multicast bit when picking a
+ random node_id, to prevent conflicts with IEEE 802
+ addresses obtained from network cards.
+
+Wed Jan 1 23:51:09 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * unpack.c, pack.c: Include string.h, since we use memcpy().
+
+Tue Dec 3 13:05:11 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * parse.c: Add #include of ctype.h and stdlib.h, to pull in the
+ required prototypes.
+
+Fri Oct 11 17:15:10 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Makefile.in (DLL_ADDRESS): Updated DLL address for libuuid.
+
+Tue Oct 8 02:02:03 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs version 1.06
+
Thu Sep 12 15:23:07 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* Release of E2fsprogs version 1.05
diff --git a/lib/uuid/Makefile.in b/lib/uuid/Makefile.in
index c226197..a186f2a 100644
--- a/lib/uuid/Makefile.in
+++ b/lib/uuid/Makefile.in
@@ -39,20 +39,21 @@
LIBRARY= libuuid
LIBDIR= uuid
-DLL_ADDRESS = 0x66980000
+DLL_ADDRESS = 0x67900000
DLL_JUMPSIZE = 0x1000
DLL_GOTSIZE = 0x1000
-DLL_VERSION = 1.0
+DLL_VERSION = 0.0
DLL_IMAGE = libuuid
DLL_STUB = libuuid
DLL_MYDIR = uuid
DLL_INSTALL_DIR = $(libdir)
-ELF_VERSION = 1.0
+ELF_VERSION = 1.1
ELF_SO_VERSION = 1
ELF_IMAGE = libuuid
ELF_MYDIR = uuid
ELF_INSTALL_DIR = $(libdir)
+ELF_OTHER_LIBS = -lc
BSDLIB_VERSION = 1.0
BSDLIB_IMAGE = libuuid
@@ -68,7 +69,7 @@
.c.o:
$(CC) $(ALL_CFLAGS) -c $< -o $@
-@PROFILE_CMT@ $(CC) $(ALL_CFLAGS) -pg -o profiled/$*.o -c $<
+@PROFILE_CMT@ $(CC) $(ALL_CFLAGS) -g -pg -o profiled/$*.o -c $<
@CHECKER_CMT@ $(CC) $(ALL_CFLAGS) -checker -g -o checker/$*.o -c $<
@DLL_CMT@ (export JUMP_DIR=`pwd`/jump; $(CC) -B$(JUMP_PREFIX) $(ALL_CFLAGS) \
@DLL_CMT@ -o jump/$*.o -c $<)
@@ -77,6 +78,9 @@
all:: tst_uuid
+tst_uuid.o: $(srcdir)/tst_uuid.c
+ $(CC) $(ALL_CFLAGS) -c $(srcdir)/tst_uuid.c -o tst_uuid.o
+
tst_uuid: tst_uuid.o $(LIBUUID)
$(CC) $(ALL_LDFLAGS) -o tst_uuid tst_uuid.o $(LIBUUID)
diff --git a/lib/uuid/clear.c b/lib/uuid/clear.c
index 5127e01..32e26d4 100644
--- a/lib/uuid/clear.c
+++ b/lib/uuid/clear.c
@@ -1,7 +1,16 @@
/*
* clear.c -- Clear a UUID
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
+#include "string.h"
+
#include "uuidP.h"
void uuid_clear(uuid_t uu)
diff --git a/lib/uuid/compare.c b/lib/uuid/compare.c
index 44052c3..7bca4fa 100644
--- a/lib/uuid/compare.c
+++ b/lib/uuid/compare.c
@@ -2,6 +2,13 @@
* compare.c --- compare whether or not two UUID's are the same
*
* Returns 0 if the two UUID's are different, and 1 if they are the same.
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
#include "uuidP.h"
diff --git a/lib/uuid/copy.c b/lib/uuid/copy.c
index 739e2dd..5d0efc4 100644
--- a/lib/uuid/copy.c
+++ b/lib/uuid/copy.c
@@ -1,5 +1,12 @@
/*
* copy.c --- copy UUIDs
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
#include "uuidP.h"
diff --git a/lib/uuid/dll/jump.funcs b/lib/uuid/dll/jump.funcs
new file mode 100644
index 0000000..cd75bb8
--- /dev/null
+++ b/lib/uuid/dll/jump.funcs
@@ -0,0 +1,9 @@
+00000000 T _uuid_clear libuuid clear
+00000000 T _uuid_compare libuuid compare
+00000000 T _uuid_copy libuuid copy
+00000000 T _uuid_generate libuuid gen_uuid
+00000000 T _uuid_is_null libuuid isnull
+00000000 T _uuid_pack libuuid pack
+00000000 T _uuid_parse libuuid parse
+00000000 T _uuid_unpack libuuid unpack
+00000000 T _uuid_unparse libuuid unparse
diff --git a/lib/uuid/dll/jump.ignore b/lib/uuid/dll/jump.ignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/uuid/dll/jump.ignore
diff --git a/lib/uuid/dll/jump.import b/lib/uuid/dll/jump.import
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/uuid/dll/jump.import
diff --git a/lib/uuid/dll/jump.params b/lib/uuid/dll/jump.params
new file mode 100644
index 0000000..efd3513
--- /dev/null
+++ b/lib/uuid/dll/jump.params
@@ -0,0 +1,6 @@
+Name=libuuid
+Text=0x67900000
+Data=0x00000000
+Jump=0x00001000
+GOT=0x00001000
+Version=0.0.0
diff --git a/lib/uuid/dll/jump.undefs b/lib/uuid/dll/jump.undefs
new file mode 100644
index 0000000..1fa6c91
--- /dev/null
+++ b/lib/uuid/dll/jump.undefs
@@ -0,0 +1 @@
+67903014 D __NEEDS_SHRLIB_libc_4
diff --git a/lib/uuid/dll/jump.vars b/lib/uuid/dll/jump.vars
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/uuid/dll/jump.vars
diff --git a/lib/uuid/gen_uuid.c b/lib/uuid/gen_uuid.c
index 8eaab4a..a0c815b 100644
--- a/lib/uuid/gen_uuid.c
+++ b/lib/uuid/gen_uuid.c
@@ -1,5 +1,12 @@
/*
* gen_uuid.c --- generate a DCE-compatible uuid
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
#ifdef HAVE_UNISTD_H
@@ -185,8 +192,15 @@
__u32 clock_mid;
if (!has_init) {
- if (get_node_id(node_id) <= 0)
+ if (get_node_id(node_id) <= 0) {
get_random_bytes(node_id, 6);
+ /*
+ * Set multicast bit, to prevent conflicts
+ * with IEEE 802 addresses obtained from
+ * network cards
+ */
+ node_id[0] |= 0x80;
+ }
has_init = 1;
}
get_clock(&clock_mid, &uu.time_low, &uu.clock_seq);
diff --git a/lib/uuid/isnull.c b/lib/uuid/isnull.c
index f72e8fb..43b81f8 100644
--- a/lib/uuid/isnull.c
+++ b/lib/uuid/isnull.c
@@ -1,5 +1,12 @@
/*
* isnull.c --- Check whether or not the UUID is null
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
#include "uuidP.h"
diff --git a/lib/uuid/pack.c b/lib/uuid/pack.c
index 476b7a1..c4d03c8 100644
--- a/lib/uuid/pack.c
+++ b/lib/uuid/pack.c
@@ -1,7 +1,15 @@
/*
* Internal routine for packing UUID's
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
+#include <string.h>
#include "uuidP.h"
void uuid_pack(struct uuid *uu, uuid_t ptr)
diff --git a/lib/uuid/parse.c b/lib/uuid/parse.c
index ce3f88d..580c1fc 100644
--- a/lib/uuid/parse.c
+++ b/lib/uuid/parse.c
@@ -1,8 +1,17 @@
/*
* parse.c --- UUID parsing
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
+#include <stdlib.h>
#include <stdio.h>
+#include <ctype.h>
#include "uuidP.h"
diff --git a/lib/uuid/tst_uuid.c b/lib/uuid/tst_uuid.c
index 068eea8..c60e9f8 100644
--- a/lib/uuid/tst_uuid.c
+++ b/lib/uuid/tst_uuid.c
@@ -1,3 +1,14 @@
+/*
+ * tst_uuid.c --- test program from the UUID library
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
#include <stdio.h>
#include <linux/ext2_fs.h>
diff --git a/lib/uuid/unpack.c b/lib/uuid/unpack.c
index 406587d..97a9dd8 100644
--- a/lib/uuid/unpack.c
+++ b/lib/uuid/unpack.c
@@ -1,7 +1,15 @@
/*
* Internal routine for unpacking UUID
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
+#include <string.h>
#include "uuidP.h"
void uuid_unpack(uuid_t in, struct uuid *uu)
diff --git a/lib/uuid/unparse.c b/lib/uuid/unparse.c
index 32f7995..ab904bc 100644
--- a/lib/uuid/unparse.c
+++ b/lib/uuid/unparse.c
@@ -1,5 +1,12 @@
/*
- * uuid_to_str.c -- convert a UUID to string
+ * unparse.c -- convert a UUID to string
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
#include <stdio.h>
diff --git a/lib/uuid/uuid.h b/lib/uuid/uuid.h
index 9568c03..08f924c 100644
--- a/lib/uuid/uuid.h
+++ b/lib/uuid/uuid.h
@@ -1,5 +1,12 @@
/*
* Public include file for the UUID library
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
typedef unsigned char uuid_t[16];
diff --git a/lib/uuid/uuidP.h b/lib/uuid/uuidP.h
index 0ef9261..69f9af9 100644
--- a/lib/uuid/uuidP.h
+++ b/lib/uuid/uuidP.h
@@ -1,5 +1,12 @@
/*
* uuid.h -- private header file for uuids
+ *
+ * Copyright (C) 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
#include <sys/types.h>
diff --git a/misc/ChangeLog b/misc/ChangeLog
index 11f7c04..8886779 100644
--- a/misc/ChangeLog
+++ b/misc/ChangeLog
@@ -1,3 +1,50 @@
+Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o <tytso@mit.edu>
+
+ * Release of E2fsprogs version 1.07
+
+Thu Mar 6 17:15:05 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * mke2fs.c (create_root_dir): Set the root directory's i_uid and
+ i_gid to be the real user and group id.
+
+Tue Mar 4 10:14:33 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * mke2fs.c (check_plausibility): Add more intelligent error
+ messages when the device doesn't exist.
+
+Sat Mar 1 10:43:32 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * fsck.c (main): Fix bug where the PATH environment variable isn't
+ set when it is unset.
+
+Tue Jan 14 12:30:45 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * mke2fs.c (write_inode_tables): Fixed bug in write_inode_tables
+ where a loop variable was getting reused in a nested loop.
+ This caused the inode table to not be correctly
+ initialized.
+
+Thu Jan 2 00:00:37 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * lsattr.c, chattr.c: Include string.h, since we use memcpy().
+
+ * findsuper.c: Use time_t for ctime(), not __u32.
+
+Sat Dec 28 23:39:18 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * badblocks.c: Adapted -vv modifications from Rik Faith so that
+ they frequently update the block number field.
+
+ * badblocks.8.in: Document the optional start-block parameter
+
+Mon Oct 14 11:52:58 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * mke2fs.c: Updated to use new ext2fs_allocate_tables() function.
+
+Tue Oct 8 02:02:03 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs version 1.06
+
Mon Oct 7 00:56:24 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* chattr.1.in: Documented the 'A' (noatime) attribute.
diff --git a/misc/Makefile.in b/misc/Makefile.in
index b0d06a2..2bff422 100644
--- a/misc/Makefile.in
+++ b/misc/Makefile.in
@@ -161,11 +161,11 @@
# Makefile dependencies follow. This must be the last section in
# the Makefile.in file
#
-tune2fs.o: $(srcdir)/tune2fs.c $(top_srcdir)/lib/ext2fs/ext2fs.h \
- $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/io.h \
- $(top_builddir)/lib/ext2fs/ext2_err.h $(top_srcdir)/lib/ext2fs/bitops.h \
- $(top_srcdir)/lib/uuid/uuid.h $(top_srcdir)/lib/e2p/e2p.h \
- $(srcdir)/../version.h
+tune2fs.o: $(srcdir)/tune2fs.c \
+ $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
+ $(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(top_srcdir)/lib/ext2fs/bitops.h $(srcdir)/../version.h \
+ $(top_srcdir)/lib/uuid/uuid.h $(top_srcdir)/lib/e2p/e2p.h
mklost+found.o: $(srcdir)/mklost+found.c $(srcdir)/../version.h
mke2fs.o: $(srcdir)/mke2fs.c $(top_srcdir)/lib/et/com_err.h \
$(top_srcdir)/lib/uuid/uuid.h $(top_srcdir)/lib/ext2fs/ext2fs.h \
@@ -175,10 +175,11 @@
$(top_srcdir)/lib/e2p/e2p.h $(srcdir)/../version.h
lsattr.o: $(srcdir)/lsattr.c $(top_srcdir)/lib/et/com_err.h \
$(top_srcdir)/lib/e2p/e2p.h $(srcdir)/../version.h
-dumpe2fs.o: $(srcdir)/dumpe2fs.c $(top_srcdir)/lib/ext2fs/ext2fs.h \
- $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/io.h \
- $(top_builddir)/lib/ext2fs/ext2_err.h $(top_srcdir)/lib/ext2fs/bitops.h \
- $(top_srcdir)/lib/e2p/e2p.h $(srcdir)/../version.h
+dumpe2fs.o: $(srcdir)/dumpe2fs.c $(srcdir)/../version.h \
+ $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
+ $(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(top_srcdir)/lib/ext2fs/bitops.h $(top_srcdir)/lib/e2p/e2p.h
badblocks.o: $(srcdir)/badblocks.c $(top_srcdir)/lib/et/com_err.h \
$(top_srcdir)/lib/ext2fs/io.h
fsck.o: $(srcdir)/fsck.c $(srcdir)/../version.h $(srcdir)/fsck.h
+
diff --git a/misc/badblocks.8.in b/misc/badblocks.8.in
index 1c4069c..f513318 100644
--- a/misc/badblocks.8.in
+++ b/misc/badblocks.8.in
@@ -19,7 +19,7 @@
.B \-w
]
device
-blocks-count
+blocks-count [ start-block ]
.SH DESCRIPTION
.B badblocks
is used to search for bad blocks on a device (usually a disk partition).
diff --git a/misc/badblocks.c b/misc/badblocks.c
index dd9968b..aba1d18 100644
--- a/misc/badblocks.c
+++ b/misc/badblocks.c
@@ -5,11 +5,15 @@
* Laboratoire MASI, Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
+ * Copyright 1995, 1996, 1997 by Theodore Ts'o
+ *
* This file is based on the minix file system programs fsck and mkfs
* written and copyrighted by Linus Torvalds <Linus.Torvalds@cs.helsinki.fi>
- *
- * This file can be redistributed under the terms of the GNU General
- * Public License
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
/*
@@ -53,6 +57,27 @@
exit (1);
}
+static unsigned long currently_testing = 0;
+static unsigned long num_blocks = 0;
+
+static void print_status(void)
+{
+ fprintf(stderr, "%9ld/%9ld", currently_testing, num_blocks);
+ fprintf(stderr, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
+ fflush (stderr);
+}
+
+static void alarm_intr (int alnum)
+{
+ signal (SIGALRM, alarm_intr);
+ alarm(1);
+ if (!num_blocks)
+ return;
+ fprintf(stderr, "%9ld/%9ld", currently_testing, num_blocks);
+ fprintf(stderr, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
+ fflush (stderr);
+}
+
/*
* Perform a test of a block; return the number of blocks readable/writeable.
*/
@@ -61,8 +86,11 @@
{
long got;
+ if (v_flag > 1)
+ print_status();
+
/* Seek to the correct loc. */
- if (ext2_llseek (dev, (ext2_loff_t) current_block * block_size,
+ if (ext2fs_llseek (dev, (ext2_loff_t) current_block * block_size,
SEEK_SET) != (ext2_loff_t) current_block * block_size)
com_err (program_name, errno, "during seek");
@@ -78,20 +106,6 @@
return got;
}
-static unsigned long currently_testing = 0;
-static unsigned long num_blocks = 0;
-
-static void alarm_intr (int alnum)
-{
- signal (SIGALRM, alarm_intr);
- alarm(1);
- if (!num_blocks)
- return;
- fprintf(stderr, "%9ld/%9ld", currently_testing, num_blocks);
- fprintf(stderr, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
- fflush (stderr);
-}
-
static void flush_bufs (int dev, int sync)
{
if (v_flag
@@ -136,9 +150,10 @@
try = TEST_BUFFER_BLOCKS;
currently_testing = from_count;
num_blocks = blocks_count;
- if (s_flag) {
+ if (s_flag || v_flag > 1) {
fprintf(stderr, "Checking for bad blocks (read-only test): ");
- alarm_intr(SIGALRM);
+ if (v_flag <= 1)
+ alarm_intr(SIGALRM);
}
while (currently_testing < blocks_count)
{
@@ -157,7 +172,7 @@
}
num_blocks = 0;
alarm(0);
- if (s_flag)
+ if (s_flag || v_flag > 1)
fprintf(stderr, "done \n");
fflush (stderr);
free (blkbuf);
@@ -180,28 +195,33 @@
flush_bufs (dev, 0);
- if (v_flag)
- fprintf (stderr, "Checking for bad blocks in read-write mode\n");
- for (i = 0; i < sizeof (pattern); i++)
- {
+ if (v_flag) {
+ fprintf(stderr,
+ "Checking for bad blocks in read-write mode\n");
+ fprintf(stderr, "From block %lu to %lu\n",
+ from_count, blocks_count);
+ }
+ for (i = 0; i < sizeof (pattern); i++) {
memset (buffer, pattern[i], block_size);
if (s_flag | v_flag)
fprintf (stderr, "Writing pattern 0x%08x: ",
*((int *) buffer));
num_blocks = blocks_count;
currently_testing = from_count;
- if (s_flag)
+ if (s_flag && v_flag <= 1)
alarm_intr(SIGALRM);
for (;
currently_testing < blocks_count;
currently_testing++)
{
- if (ext2_llseek (dev, (ext2_loff_t) currently_testing *
+ if (ext2fs_llseek (dev, (ext2_loff_t) currently_testing *
block_size, SEEK_SET) !=
(ext2_loff_t) currently_testing * block_size)
com_err (program_name, errno,
"during seek on block %d",
currently_testing);
+ if (v_flag > 1)
+ print_status();
write (dev, buffer, block_size);
}
num_blocks = 0;
@@ -213,18 +233,20 @@
fprintf (stderr, "Reading and comparing: ");
num_blocks = blocks_count;
currently_testing = from_count;
- if (s_flag)
+ if (s_flag && v_flag <= 1)
alarm_intr(SIGALRM);
for (;
currently_testing < blocks_count;
currently_testing++)
{
- if (ext2_llseek (dev, (ext2_loff_t) currently_testing *
+ if (ext2fs_llseek (dev, (ext2_loff_t) currently_testing *
block_size, SEEK_SET) !=
(ext2_loff_t) currently_testing * block_size)
com_err (program_name, errno,
"during seek on block %d",
currently_testing);
+ if (v_flag > 1)
+ print_status();
if (read (dev, buffer + block_size, block_size) < block_size)
fprintf (out, "%ld\n", currently_testing);
else if (memcmp (buffer, buffer + block_size, block_size))
@@ -270,7 +292,7 @@
s_flag = 1;
break;
case 'v':
- v_flag = 1;
+ v_flag++;
break;
case 'w':
w_flag = 1;
diff --git a/misc/chattr.c b/misc/chattr.c
index 45e2c8f..3bee82f 100644
--- a/misc/chattr.c
+++ b/misc/chattr.c
@@ -25,6 +25,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
+#include <string.h>
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
diff --git a/misc/dumpe2fs.c b/misc/dumpe2fs.c
index 069ad64..448e4eb 100644
--- a/misc/dumpe2fs.c
+++ b/misc/dumpe2fs.c
@@ -6,8 +6,12 @@
* Laboratoire MASI, Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
- * This file can be redistributed under the terms of the GNU General
- * Public License
+ * Copyright 1995, 1996, 1997 by Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
/*
diff --git a/misc/findsuper.c b/misc/findsuper.c
index 1832de5..4cc3e40 100644
--- a/misc/findsuper.c
+++ b/misc/findsuper.c
@@ -42,47 +42,53 @@
main(int argc, char *argv[])
{
- int i;
- int skiprate=512; /* one sector */
- long sk=0; /* limited to 2G filesystems!! */
- FILE *f;
- char *s;
+ int i;
+ int skiprate=512; /* one sector */
+ long sk=0; /* limited to 2G filesystems!! */
+ FILE *f;
+ char *s;
+ time_t tm;
- struct ext2_super_block ext2;
- /* interesting fields: EXT2_SUPER_MAGIC
- s_blocks_count s_log_block_size s_mtime s_magic s_lastcheck */
+ struct ext2_super_block ext2;
+ /* interesting fields: EXT2_SUPER_MAGIC
+ * s_blocks_count s_log_block_size s_mtime s_magic s_lastcheck */
- if (argc<2) {
- fprintf(stderr,"Usage: findsuper device [skiprate [start]]\n");
- exit(1);
- }
- if (argc>2) skiprate=atoi(argv[2]);
- if (skiprate<512){
- fprintf(stderr,"Do you really want to skip less than a sector??\n");
- exit(2);
- }
- if (argc>3) sk=atol(argv[3]);
- if (sk<0) {
- fprintf(stderr,"Have to start at 0 or greater,not %ld\n",sk);
- exit(1);
- }
- f=fopen(argv[1],"r");
- if (!f){
- perror(argv[1]);
- exit(1);
- }
+ if (argc<2) {
+ fprintf(stderr,
+ "Usage: findsuper device [skiprate [start]]\n");
+ exit(1);
+ }
+ if (argc>2)
+ skiprate=atoi(argv[2]);
+ if (skiprate<512) {
+ fprintf(stderr,
+ "Do you really want to skip less than a sector??\n");
+ exit(2);
+ }
+ if (argc>3)
+ sk=atol(argv[3]);
+ if (sk<0) {
+ fprintf(stderr,"Have to start at 0 or greater,not %ld\n",sk);
+ exit(1);
+ }
+ f=fopen(argv[1],"r");
+ if (!f) {
+ perror(argv[1]);
+ exit(1);
+ }
- /* Now, go looking for the superblock ! */
- printf(" thisoff block fs_blk_sz blksz last_mount\n");
- for (;!feof(f) && (i=fseek(f,sk,SEEK_SET))!= -1; sk+=skiprate){
- if (i=fread(&ext2,sizeof(ext2),1, f)!=1){
- perror("read failed");
- } else if (ext2.s_magic == EXT2_SUPER_MAGIC){
- s=ctime(&ext2.s_mtime);
- s[24]=0;
- printf("%9ld %9ld %9ld %5ld %s\n",sk,sk/1024,ext2.s_blocks_count,ext2.s_log_block_size,s);
- }
- }
- printf("Failed on %d at %ld\n",i,sk);
- fclose(f);
+ /* Now, go looking for the superblock ! */
+ printf(" thisoff block fs_blk_sz blksz last_mount\n");
+ for (;!feof(f) && (i=fseek(f,sk,SEEK_SET))!= -1; sk+=skiprate){
+ if (i=fread(&ext2,sizeof(ext2),1, f)!=1) {
+ perror("read failed");
+ } else if (ext2.s_magic == EXT2_SUPER_MAGIC){
+ tm = ext2.s_mtime;
+ s=ctime(&tm);
+ s[24]=0;
+ printf("%9ld %9ld %9ld %5ld %s\n",sk,sk/1024,ext2.s_blocks_count,ext2.s_log_block_size,s);
+ }
+ }
+ printf("Failed on %d at %ld\n", i, sk);
+ fclose(f);
}
diff --git a/misc/fsck.c b/misc/fsck.c
index 5228b91..93e8737 100644
--- a/misc/fsck.c
+++ b/misc/fsck.c
@@ -18,8 +18,12 @@
* can be added without changing this front-end.
* o -R flag skip root file system.
*
- * Copyright (C) 1993, 1994 Theodore Ts'o. This file may be
- * redistributed under the terms of the GNU Public License.
+ * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
#include <sys/types.h>
@@ -543,7 +547,7 @@
/* Check all file systems, using the /etc/fstab table. */
static int check_all(NOARGS)
{
- struct fs_info *fs;
+ struct fs_info *fs = NULL;
struct fsck_instance *inst;
int status = EXIT_OK;
int not_done_yet = 1;
@@ -764,7 +768,7 @@
strcat (fsck_path, ":");
strcat (fsck_path, oldpath);
} else {
- fsck_path = strdup(oldpath);
+ fsck_path = strdup(fsck_prefix_path);
}
/* If -A was specified ("check all"), do that! */
diff --git a/misc/lsattr.c b/misc/lsattr.c
index 3fe4b9a..60d60f0 100644
--- a/misc/lsattr.c
+++ b/misc/lsattr.c
@@ -31,6 +31,7 @@
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
+#include <string.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <linux/ext2_fs.h>
diff --git a/misc/mke2fs.c b/misc/mke2fs.c
index 0cdcc05..3723af5 100644
--- a/misc/mke2fs.c
+++ b/misc/mke2fs.c
@@ -1,8 +1,12 @@
/*
* mke2fs.c - Make a ext2fs filesystem.
*
- * Copyright (C) 1994 Theodore Ts'o. This file may be redistributed
- * under the terms of the GNU Public License.
+ * Copyright (C) 1994, 1995, 1996, 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
/* Usage: mke2fs [options] device
@@ -108,7 +112,11 @@
val = stat(device_name, &s);
if(val == -1) {
- perror("stat");
+ printf("Could not stat %s --- %s\n", device_name,
+ error_message(errno));
+ if (errno == ENOENT)
+ printf("\nThe device apparently does not exist; "
+ "did yo specify it correctly?\n");
exit(1);
}
if(!S_ISBLK(s.st_mode)) {
@@ -285,49 +293,12 @@
badblocks_list_iterate_end(bb_iter);
}
-static void new_table_block(ext2_filsys fs, blk_t first_block,
- const char *name, int num, int initialize,
- const char *buf, blk_t *new_block)
+static void write_inode_tables(ext2_filsys fs)
{
errcode_t retval;
blk_t blk;
- int i;
- int count;
-
- retval = ext2fs_get_free_blocks(fs, first_block,
- first_block + fs->super->s_blocks_per_group,
- num, fs->block_map, new_block);
- if (retval) {
- printf("Could not allocate %d block(s) for %s: %s\n",
- num, name, error_message(retval));
- ext2fs_unmark_valid(fs);
- return;
- }
- if (initialize) {
- blk = *new_block;
- for (i=0; i < num; i += STRIDE_LENGTH, blk += STRIDE_LENGTH) {
- if (num-i > STRIDE_LENGTH)
- count = STRIDE_LENGTH;
- else
- count = num - i;
- retval = io_channel_write_blk(fs->io, blk, count, buf);
- if (retval)
- printf("Warning: could not write %d blocks "
- "starting at %d for %s: %s\n",
- count, blk, name,
- error_message(retval));
- }
- }
- blk = *new_block;
- for (i = 0; i < num; i++, blk++)
- ext2fs_mark_block_bitmap(fs->block_map, blk);
-}
-
-static void alloc_tables(ext2_filsys fs)
-{
- blk_t group_blk;
- int i;
- char *buf;
+ int i, j, num, count;
+ char *buf;
buf = malloc(fs->blocksize * STRIDE_LENGTH);
if (!buf) {
@@ -336,25 +307,30 @@
}
memset(buf, 0, fs->blocksize * STRIDE_LENGTH);
- group_blk = fs->super->s_first_data_block;
if (!quiet)
printf("Writing inode tables: ");
for (i = 0; i < fs->group_desc_count; i++) {
if (!quiet)
printf("%4d/%4ld", i, fs->group_desc_count);
- new_table_block(fs, group_blk, "block bitmap", 1, 0, buf,
- &fs->group_desc[i].bg_block_bitmap);
- new_table_block(fs, group_blk, "inode bitmap", 1, 0, buf,
- &fs->group_desc[i].bg_inode_bitmap);
- new_table_block(fs, group_blk, "inode table",
- fs->inode_blocks_per_group,
- !super_only, buf,
- &fs->group_desc[i].bg_inode_table);
- group_blk += fs->super->s_blocks_per_group;
+ blk = fs->group_desc[i].bg_inode_table;
+ num = fs->inode_blocks_per_group;
+
+ for (j=0; j < num; j += STRIDE_LENGTH, blk += STRIDE_LENGTH) {
+ if (num-j > STRIDE_LENGTH)
+ count = STRIDE_LENGTH;
+ else
+ count = num - j;
+ retval = io_channel_write_blk(fs->io, blk, count, buf);
+ if (retval)
+ printf("Warning: could not write %d blocks "
+ "in inode table starting at %d: %s\n",
+ count, blk, error_message(retval));
+ }
if (!quiet)
printf("\b\b\b\b\b\b\b\b\b");
}
+ free(buf);
if (!quiet)
printf("done \n");
}
@@ -376,7 +352,9 @@
"while reading root inode");
exit(1);
}
- inode.i_uid = geteuid();
+ inode.i_uid = getuid();
+ if (inode.i_uid)
+ inode.i_gid = getgid();
retval = ext2fs_write_inode(fs, EXT2_ROOT_INO, &inode);
if (retval) {
com_err("ext2fs_write_inode", retval,
@@ -800,11 +778,17 @@
test_disk(fs, &bb_list);
handle_bad_blocks(fs, bb_list);
- alloc_tables(fs);
+ retval = ext2fs_allocate_tables(fs);
+ if (retval) {
+ com_err(program_name, retval,
+ "while trying to allocate filesystem tables");
+ exit(1);
+ }
if (super_only) {
fs->super->s_state |= EXT2_ERROR_FS;
fs->flags &= ~(EXT2_FLAG_IB_DIRTY|EXT2_FLAG_BB_DIRTY);
} else {
+ write_inode_tables(fs);
create_root_dir(fs);
create_lost_and_found(fs);
reserve_inodes(fs);
diff --git a/misc/tune2fs.c b/misc/tune2fs.c
index a6e2486..db3539e 100644
--- a/misc/tune2fs.c
+++ b/misc/tune2fs.c
@@ -6,8 +6,12 @@
* Laboratoire MASI, Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
- * This file can be redistributed under the terms of the GNU General
- * Public License
+ * Copyright 1995, 1996, 1997 by Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
*/
/*
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 9c89fe7..8850628 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,29 @@
+Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o <tytso@mit.edu>
+
+ * Release of E2fsprogs version 1.07
+
+Thu Mar 6 23:23:07 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * f_misstable: New test case which checks what happens when the
+ inode table for a block group is missing
+
+ * f_reconnect: New test case which makes sure a simple
+ disconnected inode is properly handled.
+
+Mon Dec 2 09:33:31 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * test_script.in: Add error checking to make sure a requested test
+ exists.
+
+Tue Oct 15 00:10:37 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * f_bbinode: New test case which exercises what happens when a bad
+ block appears in the inode table.
+
+Tue Oct 8 02:02:03 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * Release of E2fsprogs version 1.06
+
Mon Oct 7 07:52:41 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* f_preen: New test case which makes sure that e2fsck -p won't
diff --git a/tests/defaults/r_script b/tests/defaults/r_script
new file mode 100644
index 0000000..43e1cc2
--- /dev/null
+++ b/tests/defaults/r_script
@@ -0,0 +1,37 @@
+#
+# Default script for testing the relocation library routines
+# (irel -- inode relocation and brel -- block relocation)
+#
+
+if [ -f $test_dir/setup ]; then
+ . $test_dir/setup
+fi
+
+if [ "$class"x = x ]; then
+ class=`echo $test_name | sed -e 's/r_\([^_]*\)_\(.*\)/\1/'`
+ instance=`echo $test_name | sed -e 's/r_\([^_]*\)_\(.*\)/\2/'`
+fi
+if [ "$OUT"x = x ]; then
+ OUT=$test_name.log
+fi
+if [ "$EXPECT"x = x ]; then
+ EXPECT=$SRCDIR/progs/rel_test/expect.$class
+fi
+
+cat $SRCDIR/progs/rel_test/$instance.setup $SRCDIR/progs/rel_test/test.$class \
+ | $TEST_REL -f - > $OUT 2>&1
+
+cmp -s $EXPECT $OUT
+status=$?
+
+rm -f $test_name.failed $test_name.ok
+
+if [ "$status" = 0 ] ; then
+ echo "ok"
+ touch $test_name.ok
+else
+ echo "failed"
+ diff -c $EXPECT $OUT > $test_name.failed
+fi
+
+unset EXPECT OUT class instance
diff --git a/tests/f_badbblocks/expect.1 b/tests/f_badbblocks/expect.1
index fd60f67..208543f 100644
--- a/tests/f_badbblocks/expect.1
+++ b/tests/f_badbblocks/expect.1
@@ -1,12 +1,14 @@
Filesystem did not have a UUID; generating one.
+../e2fsck/e2fsck: Illegal indirect block found while reading bad blocks inode
+This doesn't bode well, but we'll try to go on...
Pass 1: Checking inodes, blocks, and sizes
-Remove illegal block(s) in bad block inode? yes
+Bad block inode has illegal block(s). Clear? yes
-Illegal block 101 in bad block inode. CLEARED
-Illegal block 103 in bad block inode. CLEARED
-Illegal block 234523 in bad block inode. CLEARED
-Illegal block 200 in bad block inode. CLEARED
+Illegal block #1 (101) in bad block inode. CLEARED.
+Illegal block #2 (103) in bad block inode. CLEARED.
+Illegal block #3 (234523) in bad block inode. CLEARED.
+Illegal block #-1 (200) in bad block inode. CLEARED.
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
diff --git a/tests/f_baddir/expect.1 b/tests/f_baddir/expect.1
index 766a0a5..f8f0255 100644
--- a/tests/f_baddir/expect.1
+++ b/tests/f_baddir/expect.1
@@ -1,14 +1,24 @@
Filesystem did not have a UUID; generating one.
Pass 1: Checking inodes, blocks, and sizes
-Directory 12, incorrect size, 182 (counted = 1024). Set size to counted? yes
+Inode 12, i_size is 182, should be 1024. Fix? yes
-Inode 13 is a zero length directory. Clear? yes
+Inode 13 is a zero-length directory. Clear? yes
Pass 2: Checking directory structure
-Entry 'zero' in / (2) has deleted/unused inode 13.
+Entry 'zero' in / (2) has deleted/unused inode 13. Clear? yes
+
+Entry 'foo/bar' in / (2) has illegal characters in its name.
+Fix? yes
+
+Entry 'root' in /test (14) is a link to the root inode.
Clear? yes
+Entry 'badino' in /test (14) has bad inode #: 123456.
+Clear? yes
+
+Entry 'dot' in /test (14) is a link to '.' Clear? yes
+
Directory inode 12, block 0, offset 0: directory corrupted
Salvage? yes
@@ -19,23 +29,20 @@
Fix? yes
Pass 3: Checking directory connectivity
-'..' in /block.h (12) is . (0), should be / (2).
+'..' in /block.h (12) is <The NULL inode> (0), should be / (2).
Fix? yes
Pass 4: Checking reference counts
-Inode 12 has ref count 1, expecting 2.
-Set i_nlinks to count? yes
+Inode 12 ref count is 1, should be 2. Fix? yes
Pass 5: Checking group summary information
Fix summary information? yes
Block bitmap differences: -22. FIXED
-Free blocks count wrong (76, counted=77). FIXED
+Free blocks count wrong (74, counted=75). FIXED
Inode bitmap differences: -13. FIXED
-Free inodes count wrong for group #0 (19, counted=20). FIXED
-Directories count wrong for group #0 (4, counted=3). FIXED
-Free inodes count wrong (19, counted=20). FIXED
+Directories count wrong for group #0 (5, counted=4). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
-test_filesys: 12/32 files (0.0% non-contiguous), 23/100 blocks
+test_filesys: 14/32 files (0.0% non-contiguous), 25/100 blocks
Exit status is 1
diff --git a/tests/f_baddir/expect.2 b/tests/f_baddir/expect.2
index 628a376..e848eff 100644
--- a/tests/f_baddir/expect.2
+++ b/tests/f_baddir/expect.2
@@ -3,5 +3,5 @@
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
-test_filesys: 12/32 files (0.0% non-contiguous), 23/100 blocks
+test_filesys: 14/32 files (0.0% non-contiguous), 25/100 blocks
Exit status is 0
diff --git a/tests/f_baddir/image.gz b/tests/f_baddir/image.gz
index 7f6a782..9d593fe 100644
--- a/tests/f_baddir/image.gz
+++ b/tests/f_baddir/image.gz
Binary files differ
diff --git a/tests/f_baddir/name b/tests/f_baddir/name
index ee1947a..9822221 100644
--- a/tests/f_baddir/name
+++ b/tests/f_baddir/name
@@ -1 +1 @@
-corrupted directory
+corrupted directory entries
diff --git a/tests/f_baddotdir/expect.1 b/tests/f_baddotdir/expect.1
index d24b281..77b8f8c 100644
--- a/tests/f_baddotdir/expect.1
+++ b/tests/f_baddotdir/expect.1
@@ -8,16 +8,20 @@
Missing '..' in directory inode 12.
Fix? yes
-First entry in directory inode 13 contains 'X' (inode=11)
-instead of '.'.
-Change to be '.'? yes
+First entry 'X' (inode=11) in directory inode 13 (/b) should be '.'
+Fix? yes
Missing '..' in directory inode 14.
Fix? yes
-Second entry in directory inode 15 contains 'XX' (inode=11)
-instead of '..'.
-Change to be '..'? yes
+Second entry 'XX' (inode=11) in directory inode 15 should be '..'
+Fix? yes
+
+'.' directory entry in directory inode 17 is not NULL terminated
+Fix? yes
+
+'..' directory entry in directory inode 17 is not NULL terminated
+Fix? yes
Missing '.' in directory inode 16.
Fix? yes
@@ -26,25 +30,28 @@
Fix? yes
Pass 3: Checking directory connectivity
-'..' in /a (12) is . (0), should be / (2).
+'..' in /a (12) is <The NULL inode> (0), should be / (2).
Fix? yes
-'..' in /c (14) is . (0), should be / (2).
+'..' in /c (14) is <The NULL inode> (0), should be / (2).
Fix? yes
-'..' in /d (15) is . (0), should be / (2).
+'..' in /d (15) is <The NULL inode> (0), should be / (2).
Fix? yes
-'..' in /e (16) is . (0), should be / (2).
+'..' in /e (16) is <The NULL inode> (0), should be / (2).
+Fix? yes
+
+'..' in /f (17) is <The NULL inode> (0), should be / (2).
Fix? yes
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Fix summary information? yes
-Free blocks count wrong for group 0 (72, counted=73). FIXED
-Free blocks count wrong (72, counted=73). FIXED
+Free blocks count wrong for group 0 (70, counted=71). FIXED
+Free blocks count wrong (70, counted=71). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
-test_filesys: 16/32 files (0.0% non-contiguous), 27/100 blocks
+test_filesys: 18/32 files (0.0% non-contiguous), 29/100 blocks
Exit status is 1
diff --git a/tests/f_baddotdir/expect.2 b/tests/f_baddotdir/expect.2
index 0ed37d7..8b3523c 100644
--- a/tests/f_baddotdir/expect.2
+++ b/tests/f_baddotdir/expect.2
@@ -3,5 +3,5 @@
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
-test_filesys: 16/32 files (0.0% non-contiguous), 27/100 blocks
+test_filesys: 18/32 files (0.0% non-contiguous), 29/100 blocks
Exit status is 0
diff --git a/tests/f_baddotdir/image.gz b/tests/f_baddotdir/image.gz
index a52bfb1..8ed90c5 100644
--- a/tests/f_baddotdir/image.gz
+++ b/tests/f_baddotdir/image.gz
Binary files differ
diff --git a/tests/f_badinode/expect.1 b/tests/f_badinode/expect.1
index c6842d2..b2da205 100644
--- a/tests/f_badinode/expect.1
+++ b/tests/f_badinode/expect.1
@@ -6,10 +6,10 @@
Clear? yes
i_fsize for inode 13 (/timings) is 4, should be zero.
-Clear i_fsize? yes
+Clear? yes
i_file_acl for inode 13 (/timings) is 39, should be zero.
-Clear i_file_acl? yes
+Clear? yes
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
diff --git a/tests/f_badroot/expect.1 b/tests/f_badroot/expect.1
index fd760a1..cd73a33 100644
--- a/tests/f_badroot/expect.1
+++ b/tests/f_badroot/expect.1
@@ -4,11 +4,10 @@
Root inode is not a directory. Clear? yes
Pass 2: Checking directory structure
-Entry '..' in ??? (11) has deleted/unused inode 2.
-Clear? yes
+Entry '..' in ??? (11) has deleted/unused inode 2. Clear? yes
Pass 3: Checking directory connectivity
-Root inode not allocated. Reallocate? yes
+Root inode not allocated. Allocate? yes
Unconnected directory inode 11 (...)
Connect to /lost+found? yes
@@ -16,14 +15,12 @@
/lost+found not found. Create? yes
Pass 4: Checking reference counts
-Inode 11 has ref count 3, expecting 2.
-Set i_nlinks to count? yes
+Inode 11 ref count is 3, should be 2. Fix? yes
Unattached inode 12
Connect to /lost+found? yes
-Inode 12 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 12 ref count is 2, should be 1. Fix? yes
Pass 5: Checking group summary information
Fix summary information? yes
diff --git a/tests/f_badtable/expect.1 b/tests/f_badtable/expect.1
index b8d2cd0..11bbc97 100644
--- a/tests/f_badtable/expect.1
+++ b/tests/f_badtable/expect.1
@@ -5,27 +5,27 @@
Group 0's inode bitmap (4) is bad. Relocate? yes
-WARNING: Severe data loss possible!!!!
-Bad block 6 in group 0's inode table. Relocate? yes
-
-WARNING: Severe data loss possible!!!!
-Bad block 8 in group 0's inode table. Relocate? yes
-
-Relocating group 0's block bitmap from 3 to 22...
-Relocating group 0's inode bitmap from 4 to 23...
-Relocating group 0's inode table from 5 to 24...
-Restarting e2fsck from the beginning...
-Pass 1: Checking inodes, blocks, and sizes
+Relocating group 0's block bitmap from 3 to 9...
+Relocating group 0's inode bitmap from 4 to 10...
Pass 2: Checking directory structure
+Entry 'lost+found' in / (2) points to inode (11) located in a bad block.
+Clear? yes
+
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
+Inode 2 ref count is 3, should be 2. Fix? yes
+
Pass 5: Checking group summary information
Fix summary information? yes
-Block bitmap differences: -5 -7 +22 +23 +24 +25 +26 +27. FIXED
-Free blocks count wrong for group 0 (78, counted=74). FIXED
-Free blocks count wrong (78, counted=74). FIXED
+Block bitmap differences: -11 -12 -13 -14 -15 -16 -17 -18 -19 -20. FIXED
+Free blocks count wrong for group 0 (78, counted=88). FIXED
+Free blocks count wrong (78, counted=88). FIXED
+Inode bitmap differences: +12 +13 +14 +15 +16 +25 +26 +27 +28 +29 +30 +31 +32. FIXED
+Free inodes count wrong for group #0 (21, counted=8). FIXED
+Directories count wrong for group #0 (2, counted=1). FIXED
+Free inodes count wrong (21, counted=8). FIXED
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
-test_filesys: 11/32 files (0.0% non-contiguous), 26/100 blocks
+test_filesys: 24/32 files (0.0% non-contiguous), 12/100 blocks
Exit status is 1
diff --git a/tests/f_badtable/expect.2 b/tests/f_badtable/expect.2
index 7614b9d..37ab108 100644
--- a/tests/f_badtable/expect.2
+++ b/tests/f_badtable/expect.2
@@ -3,5 +3,5 @@
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
-test_filesys: 11/32 files (0.0% non-contiguous), 26/100 blocks
+test_filesys: 24/32 files (0.0% non-contiguous), 12/100 blocks
Exit status is 0
diff --git a/tests/f_bbfile/expect.1 b/tests/f_bbfile/expect.1
index ea2f810..8dcbc4f 100644
--- a/tests/f_bbfile/expect.1
+++ b/tests/f_bbfile/expect.1
@@ -14,19 +14,19 @@
(There are 3 inodes containing duplicate/bad blocks.)
File /termcap (inode #12, mod time Sun Jan 2 08:29:13 1994)
- has 2 duplicate blocks, shared with 1 file:
+ has 2 duplicate block(s), shared with 1 file(s):
<The bad blocks inode> (inode #1, mod time Sun Jul 17 00:47:58 1994)
Clone duplicate/bad blocks? yes
File /lost+found (inode #11, mod time Sun Jan 2 08:28:40 1994)
- has 12 duplicate blocks, shared with 1 file:
+ has 12 duplicate block(s), shared with 1 file(s):
<The bad blocks inode> (inode #1, mod time Sun Jul 17 00:47:58 1994)
Clone duplicate/bad blocks? yes
File / (inode #2, mod time Sun Jan 2 08:29:13 1994)
- has 1 duplicate blocks, shared with 1 file:
+ has 1 duplicate block(s), shared with 1 file(s):
<The bad blocks inode> (inode #1, mod time Sun Jul 17 00:47:58 1994)
Clone duplicate/bad blocks? yes
diff --git a/tests/f_bbinode/expect.1 b/tests/f_bbinode/expect.1
new file mode 100644
index 0000000..91de746
--- /dev/null
+++ b/tests/f_bbinode/expect.1
@@ -0,0 +1,41 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Entry 'a6' in / (2) points to inode (17) located in a bad block.
+Clear? yes
+
+Entry 'a7' in / (2) points to inode (18) located in a bad block.
+Clear? yes
+
+Entry 'a8' in / (2) points to inode (19) located in a bad block.
+Clear? yes
+
+Entry 'b1' in / (2) points to inode (20) located in a bad block.
+Clear? yes
+
+Entry 'b2' in / (2) points to inode (21) located in a bad block.
+Clear? yes
+
+Entry 'b3' in / (2) points to inode (22) located in a bad block.
+Clear? yes
+
+Entry 'b4' in / (2) points to inode (23) located in a bad block.
+Clear? yes
+
+Entry 'b5' in / (2) points to inode (24) located in a bad block.
+Clear? yes
+
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+Fix summary information? yes
+
+Block bitmap differences: -83. FIXED
+Free blocks count wrong for group 0 (1962, counted=1965). FIXED
+Free blocks count wrong (1962, counted=1965). FIXED
+Inode bitmap differences: +41 +42 +43 +44 +45 +46 +47 +48. FIXED
+Free inodes count wrong for group #0 (485, counted=477). FIXED
+Free inodes count wrong (485, counted=477). FIXED
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 35/512 files (0.0% non-contiguous), 83/2048 blocks
+Exit status is 1
diff --git a/tests/f_bbinode/expect.2 b/tests/f_bbinode/expect.2
new file mode 100644
index 0000000..c65289d
--- /dev/null
+++ b/tests/f_bbinode/expect.2
@@ -0,0 +1,7 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 35/512 files (0.0% non-contiguous), 83/2048 blocks
+Exit status is 0
diff --git a/tests/f_bbinode/image.gz b/tests/f_bbinode/image.gz
new file mode 100644
index 0000000..34dcf48
--- /dev/null
+++ b/tests/f_bbinode/image.gz
Binary files differ
diff --git a/tests/f_bbinode/name b/tests/f_bbinode/name
new file mode 100644
index 0000000..c5db3e5
--- /dev/null
+++ b/tests/f_bbinode/name
@@ -0,0 +1 @@
+bad blocks in inode table
diff --git a/tests/f_dup/expect.1 b/tests/f_dup/expect.1
index 4359732..082c545 100644
--- a/tests/f_dup/expect.1
+++ b/tests/f_dup/expect.1
@@ -10,13 +10,13 @@
(There are 2 inodes containing duplicate/bad blocks.)
File /motd (inode #13, mod time Tue Sep 21 03:19:20 1993)
- has 2 duplicate blocks, shared with 1 file:
+ has 2 duplicate block(s), shared with 1 file(s):
/termcap (inode #12, mod time Tue Sep 21 03:19:14 1993)
Clone duplicate/bad blocks? yes
File /termcap (inode #12, mod time Tue Sep 21 03:19:14 1993)
- has 2 duplicate blocks, shared with 1 file:
+ has 2 duplicate block(s), shared with 1 file(s):
/motd (inode #13, mod time Tue Sep 21 03:19:20 1993)
Duplicated blocks already reassigned or cloned.
diff --git a/tests/f_dup2/expect.1 b/tests/f_dup2/expect.1
index 6ba93bd..f996295 100644
--- a/tests/f_dup2/expect.1
+++ b/tests/f_dup2/expect.1
@@ -11,20 +11,20 @@
(There are 3 inodes containing duplicate/bad blocks.)
File /pass1.c (inode #14, mod time Tue Sep 21 04:28:37 1993)
- has 2 duplicate blocks, shared with 1 file:
+ has 2 duplicate block(s), shared with 1 file(s):
/motd (inode #13, mod time Tue Sep 21 03:19:20 1993)
Clone duplicate/bad blocks? yes
File /motd (inode #13, mod time Tue Sep 21 03:19:20 1993)
- has 4 duplicate blocks, shared with 2 files:
+ has 4 duplicate block(s), shared with 2 file(s):
/pass1.c (inode #14, mod time Tue Sep 21 04:28:37 1993)
/termcap (inode #12, mod time Tue Sep 21 03:19:14 1993)
Clone duplicate/bad blocks? yes
File /termcap (inode #12, mod time Tue Sep 21 03:19:14 1993)
- has 2 duplicate blocks, shared with 1 file:
+ has 2 duplicate block(s), shared with 1 file(s):
/motd (inode #13, mod time Tue Sep 21 03:19:20 1993)
Duplicated blocks already reassigned or cloned.
diff --git a/tests/f_dupfsblks/expect.1 b/tests/f_dupfsblks/expect.1
index 9d1ed34..60aaaac 100644
--- a/tests/f_dupfsblks/expect.1
+++ b/tests/f_dupfsblks/expect.1
@@ -1,24 +1,21 @@
Filesystem did not have a UUID; generating one.
Pass 1: Checking inodes, blocks, and sizes
-Remove illegal block(s) in inode 12? yes
+Inode 12 has illegal block(s). Clear? yes
-Block #1 (3) is the block bitmap of group 0. CLEARED
-Block #2 (4) is the inode bitmap of group 0. CLEARED
-Block #3 (6) is in the inode table of group 0. CLEARED
-Directory 12, incorrect size, 4096 (counted = 1024). Set size to counted? yes
+Block #1 (3) overlaps filesystem metadata in inode 12. CLEARED.
+Block #2 (4) overlaps filesystem metadata in inode 12. CLEARED.
+Block #3 (6) overlaps filesystem metadata in inode 12. CLEARED.
+Inode 12, i_size is 4096, should be 1024. Fix? yes
-Inode 12, i_blocks wrong 8 (counted=2). Set i_blocks to counted? yes
+Inode 12, i_blocks is 8, should be 2. Fix? yes
Pass 2: Checking directory structure
-Directory inode 12 has a hole at block #1
-Allocate block? yes
+Directory inode 12 has an unallocated block #1. Allocate? yes
-Directory inode 12 has a hole at block #2
-Allocate block? yes
+Directory inode 12 has an unallocated block #2. Allocate? yes
-Directory inode 12 has a hole at block #3
-Allocate block? yes
+Directory inode 12 has an unallocated block #3. Allocate? yes
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
diff --git a/tests/f_dupsuper/expect.1 b/tests/f_dupsuper/expect.1
index e3aa122..5cb5468 100644
--- a/tests/f_dupsuper/expect.1
+++ b/tests/f_dupsuper/expect.1
@@ -1,12 +1,12 @@
Filesystem did not have a UUID; generating one.
Pass 1: Checking inodes, blocks, and sizes
-Remove illegal block(s) in inode 12? yes
+Inode 12 has illegal block(s). Clear? yes
-Block #4 (2) is in the group descriptors of group 0. CLEARED
-Block #5 (3) is the block bitmap of group 0. CLEARED
-Block #6 (1) is the superblock in group 0. CLEARED
-Inode 12, i_blocks wrong 34 (counted=28). Set i_blocks to counted? yes
+Block #4 (2) overlaps filesystem metadata in inode 12. CLEARED.
+Block #5 (3) overlaps filesystem metadata in inode 12. CLEARED.
+Block #6 (1) overlaps filesystem metadata in inode 12. CLEARED.
+Inode 12, i_blocks is 34, should be 28. Fix? yes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
diff --git a/tests/f_end-bitmap/name b/tests/f_end-bitmap/name
index 16baec6..b63b6d7 100644
--- a/tests/f_end-bitmap/name
+++ b/tests/f_end-bitmap/name
@@ -1,2 +1 @@
corruption at end of block bitmap
-
diff --git a/tests/f_expand/expect.1 b/tests/f_expand/expect.1
index e6ff784..86aba90 100644
--- a/tests/f_expand/expect.1
+++ b/tests/f_expand/expect.1
@@ -2,11 +2,10 @@
Root inode is not a directory. Clear? yes
Pass 2: Checking directory structure
-Entry '..' in ??? (11) has deleted/unused inode 2.
-Clear? yes
+Entry '..' in ??? (11) has deleted/unused inode 2. Clear? yes
Pass 3: Checking directory connectivity
-Root inode not allocated. Reallocate? yes
+Root inode not allocated. Allocate? yes
Unconnected directory inode 11 (...)
Connect to /lost+found? yes
@@ -14,610 +13,509 @@
/lost+found not found. Create? yes
Pass 4: Checking reference counts
-Inode 11 has ref count 3, expecting 2.
-Set i_nlinks to count? yes
+Inode 11 ref count is 3, should be 2. Fix? yes
Unattached inode 12
Connect to /lost+found? yes
-Inode 12 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 12 ref count is 2, should be 1. Fix? yes
Unattached inode 13
Connect to /lost+found? yes
-Inode 13 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 13 ref count is 2, should be 1. Fix? yes
Unattached inode 14
Connect to /lost+found? yes
-Inode 14 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 14 ref count is 2, should be 1. Fix? yes
Unattached inode 15
Connect to /lost+found? yes
-Inode 15 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 15 ref count is 2, should be 1. Fix? yes
Unattached inode 16
Connect to /lost+found? yes
-Inode 16 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 16 ref count is 2, should be 1. Fix? yes
Unattached inode 17
Connect to /lost+found? yes
-Inode 17 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 17 ref count is 2, should be 1. Fix? yes
Unattached inode 18
Connect to /lost+found? yes
-Inode 18 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 18 ref count is 2, should be 1. Fix? yes
Unattached inode 19
Connect to /lost+found? yes
-Inode 19 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 19 ref count is 2, should be 1. Fix? yes
Unattached inode 20
Connect to /lost+found? yes
-Inode 20 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 20 ref count is 2, should be 1. Fix? yes
Unattached inode 21
Connect to /lost+found? yes
-Inode 21 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 21 ref count is 2, should be 1. Fix? yes
Unattached inode 22
Connect to /lost+found? yes
-Inode 22 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 22 ref count is 2, should be 1. Fix? yes
Unattached inode 23
Connect to /lost+found? yes
-Inode 23 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 23 ref count is 2, should be 1. Fix? yes
Unattached inode 24
Connect to /lost+found? yes
-Inode 24 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 24 ref count is 2, should be 1. Fix? yes
Unattached inode 25
Connect to /lost+found? yes
-Inode 25 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 25 ref count is 2, should be 1. Fix? yes
Unattached inode 26
Connect to /lost+found? yes
-Inode 26 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 26 ref count is 2, should be 1. Fix? yes
Unattached inode 27
Connect to /lost+found? yes
-Inode 27 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 27 ref count is 2, should be 1. Fix? yes
Unattached inode 28
Connect to /lost+found? yes
-Inode 28 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 28 ref count is 2, should be 1. Fix? yes
Unattached inode 29
Connect to /lost+found? yes
-Inode 29 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 29 ref count is 2, should be 1. Fix? yes
Unattached inode 30
Connect to /lost+found? yes
-Inode 30 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 30 ref count is 2, should be 1. Fix? yes
Unattached inode 31
Connect to /lost+found? yes
-Inode 31 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 31 ref count is 2, should be 1. Fix? yes
Unattached inode 32
Connect to /lost+found? yes
-Inode 32 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 32 ref count is 2, should be 1. Fix? yes
Unattached inode 33
Connect to /lost+found? yes
-Inode 33 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 33 ref count is 2, should be 1. Fix? yes
Unattached inode 34
Connect to /lost+found? yes
-Inode 34 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 34 ref count is 2, should be 1. Fix? yes
Unattached inode 35
Connect to /lost+found? yes
-Inode 35 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 35 ref count is 2, should be 1. Fix? yes
Unattached inode 36
Connect to /lost+found? yes
-Inode 36 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 36 ref count is 2, should be 1. Fix? yes
Unattached inode 37
Connect to /lost+found? yes
-Inode 37 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 37 ref count is 2, should be 1. Fix? yes
Unattached inode 38
Connect to /lost+found? yes
-Inode 38 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 38 ref count is 2, should be 1. Fix? yes
Unattached inode 39
Connect to /lost+found? yes
-Inode 39 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 39 ref count is 2, should be 1. Fix? yes
Unattached inode 40
Connect to /lost+found? yes
-Inode 40 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 40 ref count is 2, should be 1. Fix? yes
Unattached inode 41
Connect to /lost+found? yes
-Inode 41 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 41 ref count is 2, should be 1. Fix? yes
Unattached inode 42
Connect to /lost+found? yes
-Inode 42 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 42 ref count is 2, should be 1. Fix? yes
Unattached inode 43
Connect to /lost+found? yes
-Inode 43 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 43 ref count is 2, should be 1. Fix? yes
Unattached inode 44
Connect to /lost+found? yes
-Inode 44 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 44 ref count is 2, should be 1. Fix? yes
Unattached inode 45
Connect to /lost+found? yes
-Inode 45 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 45 ref count is 2, should be 1. Fix? yes
Unattached inode 46
Connect to /lost+found? yes
-Inode 46 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 46 ref count is 2, should be 1. Fix? yes
Unattached inode 47
Connect to /lost+found? yes
-Inode 47 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 47 ref count is 2, should be 1. Fix? yes
Unattached inode 48
Connect to /lost+found? yes
-Inode 48 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 48 ref count is 2, should be 1. Fix? yes
Unattached inode 49
Connect to /lost+found? yes
-Inode 49 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 49 ref count is 2, should be 1. Fix? yes
Unattached inode 50
Connect to /lost+found? yes
-Inode 50 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 50 ref count is 2, should be 1. Fix? yes
Unattached inode 51
Connect to /lost+found? yes
-Inode 51 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 51 ref count is 2, should be 1. Fix? yes
Unattached inode 52
Connect to /lost+found? yes
-Inode 52 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 52 ref count is 2, should be 1. Fix? yes
Unattached inode 53
Connect to /lost+found? yes
-Inode 53 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 53 ref count is 2, should be 1. Fix? yes
Unattached inode 54
Connect to /lost+found? yes
-Inode 54 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 54 ref count is 2, should be 1. Fix? yes
Unattached inode 55
Connect to /lost+found? yes
-Inode 55 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 55 ref count is 2, should be 1. Fix? yes
Unattached inode 56
Connect to /lost+found? yes
-Inode 56 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 56 ref count is 2, should be 1. Fix? yes
Unattached inode 57
Connect to /lost+found? yes
-Inode 57 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 57 ref count is 2, should be 1. Fix? yes
Unattached inode 58
Connect to /lost+found? yes
-Inode 58 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 58 ref count is 2, should be 1. Fix? yes
Unattached inode 59
Connect to /lost+found? yes
-Inode 59 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 59 ref count is 2, should be 1. Fix? yes
Unattached inode 60
Connect to /lost+found? yes
-Inode 60 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 60 ref count is 2, should be 1. Fix? yes
Unattached inode 61
Connect to /lost+found? yes
-Inode 61 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 61 ref count is 2, should be 1. Fix? yes
Unattached inode 62
Connect to /lost+found? yes
-Inode 62 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 62 ref count is 2, should be 1. Fix? yes
Unattached inode 63
Connect to /lost+found? yes
-Inode 63 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 63 ref count is 2, should be 1. Fix? yes
Unattached inode 64
Connect to /lost+found? yes
-Inode 64 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 64 ref count is 2, should be 1. Fix? yes
Unattached inode 65
Connect to /lost+found? yes
-Inode 65 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 65 ref count is 2, should be 1. Fix? yes
Unattached inode 66
Connect to /lost+found? yes
-Inode 66 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 66 ref count is 2, should be 1. Fix? yes
Unattached inode 67
Connect to /lost+found? yes
-Inode 67 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 67 ref count is 2, should be 1. Fix? yes
Unattached inode 68
Connect to /lost+found? yes
-Inode 68 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 68 ref count is 2, should be 1. Fix? yes
Unattached inode 69
Connect to /lost+found? yes
-Inode 69 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 69 ref count is 2, should be 1. Fix? yes
Unattached inode 70
Connect to /lost+found? yes
-Inode 70 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 70 ref count is 2, should be 1. Fix? yes
Unattached inode 71
Connect to /lost+found? yes
-Inode 71 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 71 ref count is 2, should be 1. Fix? yes
Unattached inode 72
Connect to /lost+found? yes
-Inode 72 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 72 ref count is 2, should be 1. Fix? yes
Unattached inode 73
Connect to /lost+found? yes
-Inode 73 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 73 ref count is 2, should be 1. Fix? yes
Unattached inode 74
Connect to /lost+found? yes
-Inode 74 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 74 ref count is 2, should be 1. Fix? yes
Unattached inode 75
Connect to /lost+found? yes
-Inode 75 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 75 ref count is 2, should be 1. Fix? yes
Unattached inode 76
Connect to /lost+found? yes
-Inode 76 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 76 ref count is 2, should be 1. Fix? yes
Unattached inode 77
Connect to /lost+found? yes
-Inode 77 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 77 ref count is 2, should be 1. Fix? yes
Unattached inode 78
Connect to /lost+found? yes
-Inode 78 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 78 ref count is 2, should be 1. Fix? yes
Unattached inode 79
Connect to /lost+found? yes
-Inode 79 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 79 ref count is 2, should be 1. Fix? yes
Unattached inode 80
Connect to /lost+found? yes
-Inode 80 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 80 ref count is 2, should be 1. Fix? yes
Unattached inode 81
Connect to /lost+found? yes
-Inode 81 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 81 ref count is 2, should be 1. Fix? yes
Unattached inode 82
Connect to /lost+found? yes
-Inode 82 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 82 ref count is 2, should be 1. Fix? yes
Unattached inode 83
Connect to /lost+found? yes
-Inode 83 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 83 ref count is 2, should be 1. Fix? yes
Unattached inode 84
Connect to /lost+found? yes
-Inode 84 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 84 ref count is 2, should be 1. Fix? yes
Unattached inode 85
Connect to /lost+found? yes
-Inode 85 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 85 ref count is 2, should be 1. Fix? yes
Unattached inode 86
Connect to /lost+found? yes
-Inode 86 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 86 ref count is 2, should be 1. Fix? yes
Unattached inode 87
Connect to /lost+found? yes
-Inode 87 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 87 ref count is 2, should be 1. Fix? yes
Unattached inode 88
Connect to /lost+found? yes
-Inode 88 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 88 ref count is 2, should be 1. Fix? yes
Unattached inode 89
Connect to /lost+found? yes
-Inode 89 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 89 ref count is 2, should be 1. Fix? yes
Unattached inode 90
Connect to /lost+found? yes
-Inode 90 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 90 ref count is 2, should be 1. Fix? yes
Unattached inode 91
Connect to /lost+found? yes
-Inode 91 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 91 ref count is 2, should be 1. Fix? yes
Unattached inode 92
Connect to /lost+found? yes
-Inode 92 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 92 ref count is 2, should be 1. Fix? yes
Unattached inode 93
Connect to /lost+found? yes
-Inode 93 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 93 ref count is 2, should be 1. Fix? yes
Unattached inode 94
Connect to /lost+found? yes
-No room in /lost+found; expand /lost+found? yes
+No room in lost+found directory. Expand? yes
-Inode 94 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 94 ref count is 2, should be 1. Fix? yes
Unattached inode 95
Connect to /lost+found? yes
-Inode 95 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 95 ref count is 2, should be 1. Fix? yes
Unattached inode 96
Connect to /lost+found? yes
-Inode 96 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 96 ref count is 2, should be 1. Fix? yes
Unattached inode 97
Connect to /lost+found? yes
-Inode 97 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 97 ref count is 2, should be 1. Fix? yes
Unattached inode 98
Connect to /lost+found? yes
-Inode 98 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 98 ref count is 2, should be 1. Fix? yes
Unattached inode 99
Connect to /lost+found? yes
-Inode 99 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 99 ref count is 2, should be 1. Fix? yes
Unattached inode 100
Connect to /lost+found? yes
-Inode 100 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 100 ref count is 2, should be 1. Fix? yes
Unattached inode 101
Connect to /lost+found? yes
-Inode 101 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 101 ref count is 2, should be 1. Fix? yes
Unattached inode 102
Connect to /lost+found? yes
-Inode 102 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 102 ref count is 2, should be 1. Fix? yes
Unattached inode 103
Connect to /lost+found? yes
-Inode 103 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 103 ref count is 2, should be 1. Fix? yes
Unattached inode 104
Connect to /lost+found? yes
-Inode 104 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 104 ref count is 2, should be 1. Fix? yes
Unattached inode 105
Connect to /lost+found? yes
-Inode 105 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 105 ref count is 2, should be 1. Fix? yes
Unattached inode 106
Connect to /lost+found? yes
-Inode 106 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 106 ref count is 2, should be 1. Fix? yes
Unattached inode 107
Connect to /lost+found? yes
-Inode 107 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 107 ref count is 2, should be 1. Fix? yes
Unattached inode 108
Connect to /lost+found? yes
-Inode 108 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 108 ref count is 2, should be 1. Fix? yes
Unattached inode 109
Connect to /lost+found? yes
-Inode 109 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 109 ref count is 2, should be 1. Fix? yes
Unattached inode 110
Connect to /lost+found? yes
-Inode 110 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 110 ref count is 2, should be 1. Fix? yes
Unattached inode 111
Connect to /lost+found? yes
-Inode 111 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 111 ref count is 2, should be 1. Fix? yes
Pass 5: Checking group summary information
Fix summary information? yes
diff --git a/tests/f_holedir/expect.1 b/tests/f_holedir/expect.1
index ebf4539..05e0cbb 100644
--- a/tests/f_holedir/expect.1
+++ b/tests/f_holedir/expect.1
@@ -1,28 +1,21 @@
Filesystem did not have a UUID; generating one.
Pass 1: Checking inodes, blocks, and sizes
-Hole found in directory inode 11! (blkcnt=0)
-Hole found in directory inode 11! (blkcnt=3)
-Remove illegal block(s) in inode 11? yes
+Inode 11 has illegal block(s). Clear? yes
-Block #6 (200) > BLOCKS (100). CLEARED
-Hole found in directory inode 11! (blkcnt=11)
-Directory 11, incorrect size, 12288 (counted = 11264). Set size to counted? yes
+Illegal block #6 (200) in inode 11. CLEARED.
+Inode 11, i_size is 12288, should be 11264. Fix? yes
-Inode 11, i_blocks wrong 24 (counted=16). Set i_blocks to counted? yes
+Inode 11, i_blocks is 24, should be 16. Fix? yes
Pass 2: Checking directory structure
-Directory inode 11 has a hole at block #0
-Allocate block? yes
+Directory inode 11 has an unallocated block #0. Allocate? yes
-Directory inode 11 has a hole at block #3
-Allocate block? yes
+Directory inode 11 has an unallocated block #3. Allocate? yes
-Directory inode 11 has a hole at block #6
-Allocate block? yes
+Directory inode 11 has an unallocated block #6. Allocate? yes
-Directory inode 11 has a hole at block #11
-Allocate block? yes
+Directory inode 11 has an unallocated block #11. Allocate? yes
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
diff --git a/tests/f_illibitmap/expect.1 b/tests/f_illibitmap/expect.1
index ed9d579..a296ed8 100644
--- a/tests/f_illibitmap/expect.1
+++ b/tests/f_illibitmap/expect.1
@@ -5,7 +5,7 @@
the primary block group descriptor, and the backup block
group descriptor may be OK.
-Inode bitmap group 0 not in group. (block 4000)
+Inode bitmap for group 0 is not in group. (block 4000)
Relocate? yes
Filesystem did not have a UUID; generating one.
diff --git a/tests/f_illitable/expect.1 b/tests/f_illitable/expect.1
new file mode 100644
index 0000000..6c6b7f5
--- /dev/null
+++ b/tests/f_illitable/expect.1
@@ -0,0 +1,38 @@
+Note: if there is several inode or block bitmap blocks
+which require relocation, or one part of the inode table
+which must be moved, you may wish to try running e2fsck
+the '-b 8193' option first. The problem may lie only with
+the primary block group descriptor, and the backup block
+group descriptor may be OK.
+
+Inode table for group 0 is not in group. (block 40000)
+WARNING: SEVERE DATA LOSS POSSIBLE.
+Relocate? yes
+
+../e2fsck/e2fsck: A block group is missing an inode table while reading bad blocks inode
+This doesn't bode well, but we'll try to go on...
+Pass 1: Checking inodes, blocks, and sizes
+Relocating group 0's inode table to 5...
+Restarting e2fsck from the beginning...
+Pass 1: Checking inodes, blocks, and sizes
+Root inode is not a directory. Clear? yes
+
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Root inode not allocated. Allocate? yes
+
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+Fix summary information? yes
+
+Block bitmap differences: -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21. FIXED
+Free blocks count wrong for group 0 (78, counted=90). FIXED
+Free blocks count wrong (78, counted=90). FIXED
+Inode bitmap differences: -11. FIXED
+Free inodes count wrong for group #0 (21, counted=22). FIXED
+Directories count wrong for group #0 (2, counted=1). FIXED
+Free inodes count wrong (21, counted=22). FIXED
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 10/32 files (0.0% non-contiguous), 10/100 blocks
+Exit status is 1
diff --git a/tests/f_illitable/expect.2 b/tests/f_illitable/expect.2
new file mode 100644
index 0000000..86ea859
--- /dev/null
+++ b/tests/f_illitable/expect.2
@@ -0,0 +1,7 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 10/32 files (0.0% non-contiguous), 10/100 blocks
+Exit status is 0
diff --git a/tests/f_illitable/image.gz b/tests/f_illitable/image.gz
new file mode 100644
index 0000000..1b02194
--- /dev/null
+++ b/tests/f_illitable/image.gz
Binary files differ
diff --git a/tests/f_illitable/name b/tests/f_illitable/name
new file mode 100644
index 0000000..631e73b
--- /dev/null
+++ b/tests/f_illitable/name
@@ -0,0 +1 @@
+illegal inode table
diff --git a/tests/f_lotsbad/expect.1 b/tests/f_lotsbad/expect.1
index 1340520..fd491d5 100644
--- a/tests/f_lotsbad/expect.1
+++ b/tests/f_lotsbad/expect.1
@@ -1,35 +1,26 @@
Filesystem did not have a UUID; generating one.
Pass 1: Checking inodes, blocks, and sizes
-Remove illegal block(s) in inode 12? yes
+Inode 12 has illegal block(s). Clear? yes
-Block #12 (778398818) > BLOCKS (100). CLEARED
-Block #13 (1768444960) > BLOCKS (100). CLEARED
-Block #14 (1752375411) > BLOCKS (100). CLEARED
-Block #15 (1684829551) > BLOCKS (100). CLEARED
-Block #16 (1886349344) > BLOCKS (100). CLEARED
-Block #17 (1819633253) > BLOCKS (100). CLEARED
-Block #18 (1663072620) > BLOCKS (100). CLEARED
-Block #19 (1735287144) > BLOCKS (100). CLEARED
-Block #20 (1310731877) > BLOCKS (100). CLEARED
-Block #21 (560297071) > BLOCKS (100). CLEARED
-Block #22 (543512352) > BLOCKS (100). CLEARED
-Block #23 (1869835361) > BLOCKS (100). CLEARED
-Block #24 (1634231072) > BLOCKS (100). CLEARED
-Block #25 (543516526) > BLOCKS (100). CLEARED
-Block #26 (174418036) > BLOCKS (100). CLEARED
-Block #27 (1919819811) > BLOCKS (100). CLEARED
-Block #28 (543584032) > BLOCKS (100). CLEARED
-Block #29 (1701734764) > BLOCKS (100). CLEARED
-Block #30 (1869881459) > BLOCKS (100). CLEARED
+Illegal block #12 (778398818) in inode 12. CLEARED.
+Illegal block #13 (1768444960) in inode 12. CLEARED.
+Illegal block #14 (1752375411) in inode 12. CLEARED.
+Illegal block #15 (1684829551) in inode 12. CLEARED.
+Illegal block #16 (1886349344) in inode 12. CLEARED.
+Illegal block #17 (1819633253) in inode 12. CLEARED.
+Illegal block #18 (1663072620) in inode 12. CLEARED.
+Illegal block #19 (1735287144) in inode 12. CLEARED.
+Illegal block #20 (1310731877) in inode 12. CLEARED.
+Illegal block #21 (560297071) in inode 12. CLEARED.
+Illegal block #22 (543512352) in inode 12. CLEARED.
Too many illegal blocks in inode 12.
Clear inode? yes
Restarting e2fsck from the beginning...
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
-Entry 'termcap' in / (2) has deleted/unused inode 12.
-Clear? yes
+Entry 'termcap' in / (2) has deleted/unused inode 12. Clear? yes
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
diff --git a/tests/f_lpf/expect.1 b/tests/f_lpf/expect.1
index 0b8dca1..3803029 100644
--- a/tests/f_lpf/expect.1
+++ b/tests/f_lpf/expect.1
@@ -1,8 +1,7 @@
Filesystem did not have a UUID; generating one.
Pass 1: Checking inodes, blocks, and sizes
-Inode 13 is in use, but has dtime set
-Clear dtime? yes
+Inode 13 is in use, but has dtime set. Fix? yes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
@@ -12,20 +11,17 @@
/lost+found not found. Create? yes
-Inode 13 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 13 ref count is 2, should be 1. Fix? yes
Unattached inode 14
Connect to /lost+found? yes
-Inode 14 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 14 ref count is 2, should be 1. Fix? yes
Unattached inode 15
Connect to /lost+found? yes
-Inode 15 has ref count 2, expecting 1.
-Set i_nlinks to count? yes
+Inode 15 ref count is 2, should be 1. Fix? yes
Pass 5: Checking group summary information
Fix summary information? yes
diff --git a/tests/f_messy_inode/expect.1 b/tests/f_messy_inode/expect.1
index 3ea8de3..32b2a15 100644
--- a/tests/f_messy_inode/expect.1
+++ b/tests/f_messy_inode/expect.1
@@ -1,25 +1,25 @@
Filesystem did not have a UUID; generating one.
Pass 1: Checking inodes, blocks, and sizes
-Remove illegal block(s) in inode 14? yes
+Inode 14 has illegal block(s). Clear? yes
-Block #2 (4294901760) > BLOCKS (100). CLEARED
-Block #3 (4294901760) > BLOCKS (100). CLEARED
-Block #4 (4294901760) > BLOCKS (100). CLEARED
-Block #5 (4294901760) > BLOCKS (100). CLEARED
-Block #6 (4294901760) > BLOCKS (100). CLEARED
-Block #7 (4294901760) > BLOCKS (100). CLEARED
-Block #8 (4294901760) > BLOCKS (100). CLEARED
-Block #9 (4294901760) > BLOCKS (100). CLEARED
-Block #10 (4294901760) > BLOCKS (100). CLEARED
-Inode 14, i_blocks wrong 18 (counted=4). Set i_blocks to counted? yes
+Illegal block #2 (4294901760) in inode 14. CLEARED.
+Illegal block #3 (4294901760) in inode 14. CLEARED.
+Illegal block #4 (4294901760) in inode 14. CLEARED.
+Illegal block #5 (4294901760) in inode 14. CLEARED.
+Illegal block #6 (4294901760) in inode 14. CLEARED.
+Illegal block #7 (4294901760) in inode 14. CLEARED.
+Illegal block #8 (4294901760) in inode 14. CLEARED.
+Illegal block #9 (4294901760) in inode 14. CLEARED.
+Illegal block #10 (4294901760) in inode 14. CLEARED.
+Inode 14, i_blocks is 18, should be 4. Fix? yes
Pass 2: Checking directory structure
i_file_acl for inode 14 (/MAKEDEV) is 4294901760, should be zero.
-Clear i_file_acl? yes
+Clear? yes
i_dir_acl for inode 14 (/MAKEDEV) is 4294901760, should be zero.
-Clear i_dir_acl? yes
+Clear? yes
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
diff --git a/tests/f_misstable/expect.1 b/tests/f_misstable/expect.1
new file mode 100644
index 0000000..8351454
--- /dev/null
+++ b/tests/f_misstable/expect.1
@@ -0,0 +1,36 @@
+Group descriptors look bad... trying backup blocks...
+Inode table for group 1 is not in group. (block 0)
+WARNING: SEVERE DATA LOSS POSSIBLE.
+Relocate? yes
+
+Pass 1: Checking inodes, blocks, and sizes
+Relocating group 1's inode table to 8197...
+Restarting e2fsck from the beginning...
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Entry 'etc' in / (2) has deleted/unused inode 1505. Clear? yes
+
+Entry 'cache' in / (2) has deleted/unused inode 1514. Clear? yes
+
+Entry 'a' in / (2) has deleted/unused inode 1515. Clear? yes
+
+Entry 'b' in / (2) has deleted/unused inode 1516. Clear? yes
+
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Inode 2 ref count is 8, should be 4. Fix? yes
+
+Pass 5: Checking group summary information
+Fix summary information? yes
+
+Block bitmap differences: -8385 -8386 -8387 -8388 -8389 -8390 -8391 -8392 -8393 -8394 -8395 -8396 -8397 -8398 -8399 -8400 -8401 -8402 -8403 -8404 -8405. FIXED
+Free blocks count wrong for group 0 (7987, counted=7984). FIXED
+Free blocks count wrong (11602, counted=11599). FIXED
+Inode bitmap differences: -1505 -1506 -1507 -1508 -1509 -1510 -1511 -1512 -1513 -1514 -1515 -1516. FIXED
+Free inodes count wrong for group #0 (1493, counted=1489). FIXED
+Directories count wrong for group #0 (2, counted=3). FIXED
+Free inodes count wrong (2997, counted=2993). FIXED
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 15/3008 files (0.0% non-contiguous), 401/12000 blocks
+Exit status is 1
diff --git a/tests/f_misstable/expect.2 b/tests/f_misstable/expect.2
new file mode 100644
index 0000000..e8cd21a
--- /dev/null
+++ b/tests/f_misstable/expect.2
@@ -0,0 +1,7 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 15/3008 files (0.0% non-contiguous), 401/12000 blocks
+Exit status is 0
diff --git a/tests/f_misstable/image.gz b/tests/f_misstable/image.gz
new file mode 100644
index 0000000..b2aca9d
--- /dev/null
+++ b/tests/f_misstable/image.gz
Binary files differ
diff --git a/tests/f_misstable/name b/tests/f_misstable/name
new file mode 100644
index 0000000..10a1adc
--- /dev/null
+++ b/tests/f_misstable/name
@@ -0,0 +1 @@
+missing inode table
diff --git a/tests/f_mke2fs2b/expect.1 b/tests/f_mke2fs2b/expect.1
index 0ec5728..8722247 100644
--- a/tests/f_mke2fs2b/expect.1
+++ b/tests/f_mke2fs2b/expect.1
@@ -3,17 +3,14 @@
Pass 1: Checking inodes, blocks, and sizes
Root inode has dtime set (probably due to old mke2fs). Fix? yes
-Inode 11 is in use, but has dtime set
-Clear dtime? yes
+Inode 11 is in use, but has dtime set. Fix? yes
-Inode 15 is in use, but has dtime set
-Clear dtime? yes
+Inode 15 is in use, but has dtime set. Fix? yes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
-Unattached zero-length inode 15
-Clear? yes
+Unattached zero-length inode 15. Clear? yes
Pass 5: Checking group summary information
diff --git a/tests/f_noroot/expect.1 b/tests/f_noroot/expect.1
index 9099902..cef0227 100644
--- a/tests/f_noroot/expect.1
+++ b/tests/f_noroot/expect.1
@@ -1,18 +1,15 @@
Filesystem did not have a UUID; generating one.
Pass 1: Checking inodes, blocks, and sizes
-Inode 15 is in use, but has dtime set
-Clear dtime? yes
+Inode 15 is in use, but has dtime set. Fix? yes
Pass 2: Checking directory structure
-Entry '..' in /lost+found (11) has deleted/unused inode 2.
-Clear? yes
+Entry '..' in /lost+found (11) has deleted/unused inode 2. Clear? yes
-Entry '..' in /foo (12) has deleted/unused inode 2.
-Clear? yes
+Entry '..' in /foo (12) has deleted/unused inode 2. Clear? yes
Pass 3: Checking directory connectivity
-Root inode not allocated. Reallocate? yes
+Root inode not allocated. Allocate? yes
Unconnected directory inode 11 (...)
Connect to /lost+found? yes
@@ -23,14 +20,11 @@
Connect to /lost+found? yes
Pass 4: Checking reference counts
-Inode 11 has ref count 3, expecting 2.
-Set i_nlinks to count? yes
+Inode 11 ref count is 3, should be 2. Fix? yes
-Inode 12 has ref count 4, expecting 3.
-Set i_nlinks to count? yes
+Inode 12 ref count is 4, should be 3. Fix? yes
-Unattached zero-length inode 15
-Clear? yes
+Unattached zero-length inode 15. Clear? yes
Pass 5: Checking group summary information
Fix summary information? yes
diff --git a/tests/f_preen/expect.1 b/tests/f_preen/expect.1
index 7197232..297bb61 100644
--- a/tests/f_preen/expect.1
+++ b/tests/f_preen/expect.1
@@ -4,7 +4,7 @@
the primary block group descriptor, and the backup block
group descriptor may be OK.
-Block bitmap for group 0 is not in group. (block 0)
+test_filesys: Block bitmap for group 0 is not in group. (block 0)
test_filesys: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.
diff --git a/tests/f_reconnect/expect.1 b/tests/f_reconnect/expect.1
new file mode 100644
index 0000000..331d8b3
--- /dev/null
+++ b/tests/f_reconnect/expect.1
@@ -0,0 +1,24 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Unattached inode 12
+Connect to /lost+found? yes
+
+Inode 12 ref count is 2, should be 1. Fix? yes
+
+Unattached inode 13
+Connect to /lost+found? yes
+
+Inode 13 ref count is 2, should be 1. Fix? yes
+
+Unattached inode 14
+Connect to /lost+found? yes
+
+Inode 14 ref count is 2, should be 1. Fix? yes
+
+Pass 5: Checking group summary information
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 14/32 files (0.0% non-contiguous), 25/100 blocks
+Exit status is 1
diff --git a/tests/f_reconnect/expect.2 b/tests/f_reconnect/expect.2
new file mode 100644
index 0000000..e848eff
--- /dev/null
+++ b/tests/f_reconnect/expect.2
@@ -0,0 +1,7 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 14/32 files (0.0% non-contiguous), 25/100 blocks
+Exit status is 0
diff --git a/tests/f_reconnect/image.gz b/tests/f_reconnect/image.gz
new file mode 100644
index 0000000..56b92c3
--- /dev/null
+++ b/tests/f_reconnect/image.gz
Binary files differ
diff --git a/tests/f_reconnect/name b/tests/f_reconnect/name
new file mode 100644
index 0000000..c09c23f
--- /dev/null
+++ b/tests/f_reconnect/name
@@ -0,0 +1 @@
+simple disconnected file inode
diff --git a/tests/f_zero_group/expect.1 b/tests/f_zero_group/expect.1
new file mode 100644
index 0000000..c066e8c
--- /dev/null
+++ b/tests/f_zero_group/expect.1
@@ -0,0 +1,16 @@
+Group descriptors look bad... trying backup blocks...
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+Fix summary information? yes
+
+Free blocks count wrong for group 0 (7987, counted=7982). FIXED
+Free blocks count wrong (11602, counted=11597). FIXED
+Free inodes count wrong for group #0 (1493, counted=1488). FIXED
+Free inodes count wrong (2997, counted=2992). FIXED
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 16/3008 files (0.0% non-contiguous), 403/12000 blocks
+Exit status is 1
diff --git a/tests/f_zero_group/expect.2 b/tests/f_zero_group/expect.2
new file mode 100644
index 0000000..a833aef
--- /dev/null
+++ b/tests/f_zero_group/expect.2
@@ -0,0 +1,7 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 16/3008 files (0.0% non-contiguous), 403/12000 blocks
+Exit status is 0
diff --git a/tests/f_zero_group/image.gz b/tests/f_zero_group/image.gz
new file mode 100644
index 0000000..755493c
--- /dev/null
+++ b/tests/f_zero_group/image.gz
Binary files differ
diff --git a/tests/f_zero_group/name b/tests/f_zero_group/name
new file mode 100644
index 0000000..ccb3b96
--- /dev/null
+++ b/tests/f_zero_group/name
@@ -0,0 +1 @@
+fallback for damaged group descriptors
diff --git a/tests/f_zero_super/expect.1 b/tests/f_zero_super/expect.1
new file mode 100644
index 0000000..ff9e1b3
--- /dev/null
+++ b/tests/f_zero_super/expect.1
@@ -0,0 +1,16 @@
+Couldn't find ext2 superblock, trying backup blocks...
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+Fix summary information? yes
+
+Free blocks count wrong for group 0 (7987, counted=7982). FIXED
+Free blocks count wrong (11602, counted=11597). FIXED
+Free inodes count wrong for group #0 (1493, counted=1488). FIXED
+Free inodes count wrong (2997, counted=2992). FIXED
+
+test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
+test_filesys: 16/3008 files (0.0% non-contiguous), 403/12000 blocks
+Exit status is 1
diff --git a/tests/f_zero_super/expect.2 b/tests/f_zero_super/expect.2
new file mode 100644
index 0000000..a833aef
--- /dev/null
+++ b/tests/f_zero_super/expect.2
@@ -0,0 +1,7 @@
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 16/3008 files (0.0% non-contiguous), 403/12000 blocks
+Exit status is 0
diff --git a/tests/f_zero_super/image.gz b/tests/f_zero_super/image.gz
new file mode 100644
index 0000000..eea9140
--- /dev/null
+++ b/tests/f_zero_super/image.gz
Binary files differ
diff --git a/tests/f_zero_super/name b/tests/f_zero_super/name
new file mode 100644
index 0000000..5d99984
--- /dev/null
+++ b/tests/f_zero_super/name
@@ -0,0 +1 @@
+fallback for damaged superblock
diff --git a/tests/progs/Makefile.in b/tests/progs/Makefile.in
new file mode 100644
index 0000000..5ed3944
--- /dev/null
+++ b/tests/progs/Makefile.in
@@ -0,0 +1,58 @@
+#
+# Standard e2fsprogs prologue....
+#
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+top_builddir = ../..
+my_dir = tests/progs
+INSTALL = @INSTALL@
+
+@MCONFIG@
+
+MK_CMDS= ../../lib/ss/mk_cmds
+
+PROGS= test_rel
+
+TEST_REL_OBJS= test_rel.o test_rel_cmds.o
+
+SRCS= $(srcdir)/test_rel.c
+
+LIBS= $(LIBEXT2FS) $(LIBSS) $(LIBCOM_ERR)
+DEPLIBS= $(LIBEXT2FS) $(LIBSS) $(LIBCOM_ERR)
+
+.c.o:
+ $(CC) -c $(ALL_CFLAGS) $< -o $@
+
+all:: $(PROGS)
+
+test_rel: $(TEST_REL_OBJS)
+ $(LD) $(ALL_LDFLAGS) -o test_rel $(TEST_REL_OBJS) $(LIBS)
+
+test_rel_cmds.c: test_rel_cmds.ct
+ $(MK_CMDS) $(srcdir)/test_rel_cmds.ct
+
+clean:
+ $(RM) -f $(PROGS) test_rel_cmds.c \#* *.s *.o *.a *~ core
+
+install:
+
+check:
+
+mostlyclean: clean
+distclean: clean
+ $(RM) -f .depend Makefile
+
+# +++ Dependency line eater +++
+#
+# Makefile dependencies follow. This must be the last section in
+# the Makefile.in file
+#
+test_rel.o: $(srcdir)/test_rel.c $(top_srcdir)/lib/et/com_err.h \
+ $(top_srcdir)/lib/ss/ss.h $(top_srcdir)/lib/ss/copyright.h \
+ $(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/ext2fs/ext2fs.h \
+ $(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(top_srcdir)/lib/ext2fs/bitops.h $(top_srcdir)/lib/ext2fs/irel.h \
+ $(top_srcdir)/lib/ext2fs/brel.h $(srcdir)/test_rel.h
+
diff --git a/tests/progs/test_rel.c b/tests/progs/test_rel.c
new file mode 100644
index 0000000..d76c1f4
--- /dev/null
+++ b/tests/progs/test_rel.c
@@ -0,0 +1,764 @@
+/*
+ * test_rel.c
+ *
+ * Copyright (C) 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+#include <fcntl.h>
+
+#include <linux/ext2_fs.h>
+
+#include <et/com_err.h>
+#include <ss/ss.h>
+#include <ext2fs/ext2fs.h>
+#include <ext2fs/irel.h>
+#include <ext2fs/brel.h>
+
+#include "test_rel.h"
+
+extern ss_request_table test_cmds;
+
+ext2_irel irel = NULL;
+ext2_brel brel = NULL;
+
+/*
+ * Helper function which parses an inode number.
+ */
+static int parse_inode(const char *request, const char *desc,
+ const char *str, ino_t *ino)
+{
+ char *tmp;
+
+ *ino = strtoul(str, &tmp, 0);
+ if (*tmp) {
+ com_err(request, 0, "Bad %s - %s", desc, str);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Helper function which parses a block number.
+ */
+static int parse_block(const char *request, const char *desc,
+ const char *str, blk_t *blk)
+{
+ char *tmp;
+
+ *blk = strtoul(str, &tmp, 0);
+ if (*tmp) {
+ com_err(request, 0, "Bad %s - %s", desc, str);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Helper function which assures that a brel table is open
+ */
+static int check_brel(char *request)
+{
+ if (brel)
+ return 0;
+ com_err(request, 0, "A block relocation table must be open.");
+ return 1;
+}
+
+/*
+ * Helper function which assures that an irel table is open
+ */
+static int check_irel(char *request)
+{
+ if (irel)
+ return 0;
+ com_err(request, 0, "An inode relocation table must be open.");
+ return 1;
+}
+
+/*
+ * Helper function which displays a brel entry
+ */
+static void display_brel_entry(blk_t old,
+ struct ext2_block_relocate_entry *ent)
+{
+ printf("Old= %u, New= %u, Owner= %u:%u\n", old, ent->new,
+ ent->owner.block_ref, ent->offset);
+}
+
+/*
+ * Helper function which displays an irel entry
+ */
+static void display_irel_entry(ino_t old,
+ struct ext2_inode_relocate_entry *ent,
+ int do_refs)
+{
+ struct ext2_inode_reference ref;
+ errcode_t retval;
+ int first = 1;
+
+ printf("Old= %lu, New= %lu, Original=%lu, Max_refs=%u\n", old,
+ ent->new, ent->orig, ent->max_refs);
+ if (!do_refs)
+ return;
+
+ retval = ext2fs_irel_start_iter_ref(irel, old);
+ if (retval) {
+ printf("\tCouldn't get references: %s\n",
+ error_message(retval));
+ return;
+ }
+ while (1) {
+ retval = ext2fs_irel_next_ref(irel, &ref);
+ if (retval) {
+ printf("(%s) ", error_message(retval));
+ break;
+ }
+ if (ref.block == 0)
+ break;
+ if (first) {
+ fputc('\t', stdout);
+ first = 0;
+ } else
+ printf(", ");
+ printf("%u:%u", ref.block, ref.offset);
+ }
+ if (!first)
+ fputc('\n', stdout);
+}
+
+/*
+ * These are the actual command table procedures
+ */
+void do_brel_ma_create(int argc, char **argv)
+{
+ const char *usage = "Usage: %s name max_blocks\n";
+ errcode_t retval;
+ blk_t max_blk;
+
+ if (argc < 3) {
+ printf(usage, argv[0]);
+ return;
+ }
+ if (parse_block(argv[0], "max_blocks", argv[2], &max_blk))
+ return;
+ retval = ext2fs_brel_memarray_create(argv[1], max_blk, &brel);
+ if (retval) {
+ com_err(argv[0], retval, "while opening memarray brel");
+ return;
+ }
+ return;
+}
+
+void do_brel_free(int argc, char **argv)
+{
+ if (check_brel(argv[0]))
+ return;
+ ext2fs_brel_free(brel);
+ brel = NULL;
+ return;
+}
+
+void do_brel_put(int argc, char **argv)
+{
+ const char *usage = "usage: %s old_block new_block [owner] [offset]";
+ errcode_t retval;
+ struct ext2_block_relocate_entry ent;
+ blk_t old, new, offset=0, owner=0;
+
+ if (check_brel(argv[0]))
+ return;
+
+ if (argc < 3) {
+ printf(usage, argv[0]);
+ return;
+ }
+ if (parse_block(argv[0], "old block", argv[1], &old))
+ return;
+ if (parse_block(argv[0], "new block", argv[2], &new))
+ return;
+ if (argc > 3 &&
+ parse_block(argv[0], "owner block", argv[3], &owner))
+ return;
+ if (argc > 4 &&
+ parse_block(argv[0], "offset", argv[4], &offset))
+ return;
+ if (offset > 65535) {
+ printf("Offset too large.\n");
+ return;
+ }
+ ent.new = new;
+ ent.offset = (__u16) offset;
+ ent.flags = 0;
+ ent.owner.block_ref = owner;
+
+ retval = ext2fs_brel_put(brel, old, &ent);
+ if (retval) {
+ com_err(argv[0], retval, "while calling ext2fs_brel_put");
+ return;
+ }
+ return;
+}
+
+void do_brel_get(int argc, char **argv)
+{
+ const char *usage = "%s block";
+ errcode_t retval;
+ struct ext2_block_relocate_entry ent;
+ blk_t blk;
+
+ if (check_brel(argv[0]))
+ return;
+ if (argc < 2) {
+ printf(usage, argv[0]);
+ return;
+ }
+ if (parse_block(argv[0], "block", argv[1], &blk))
+ return;
+ retval = ext2fs_brel_get(brel, blk, &ent);
+ if (retval) {
+ com_err(argv[0], retval, "while calling ext2fs_brel_get");
+ return;
+ }
+ display_brel_entry(blk, &ent);
+ return;
+}
+
+void do_brel_start_iter(int argc, char **argv)
+{
+ errcode_t retval;
+
+ if (check_brel(argv[0]))
+ return;
+
+ retval = ext2fs_brel_start_iter(brel);
+ if (retval) {
+ com_err(argv[0], retval, "while calling ext2fs_brel_start_iter");
+ return;
+ }
+ return;
+}
+
+void do_brel_next(int argc, char **argv)
+{
+ errcode_t retval;
+ struct ext2_block_relocate_entry ent;
+ blk_t blk;
+
+ if (check_brel(argv[0]))
+ return;
+
+ retval = ext2fs_brel_next(brel, &blk, &ent);
+ if (retval) {
+ com_err(argv[0], retval, "while calling ext2fs_brel_next");
+ return;
+ }
+ if (blk == 0) {
+ printf("No more entries!\n");
+ return;
+ }
+ display_brel_entry(blk, &ent);
+ return;
+}
+
+void do_brel_dump(int argc, char **argv)
+{
+ errcode_t retval;
+ struct ext2_block_relocate_entry ent;
+ blk_t blk;
+
+ if (check_brel(argv[0]))
+ return;
+
+ retval = ext2fs_brel_start_iter(brel);
+ if (retval) {
+ com_err(argv[0], retval, "while calling ext2fs_brel_start_iter");
+ return;
+ }
+
+ while (1) {
+ retval = ext2fs_brel_next(brel, &blk, &ent);
+ if (retval) {
+ com_err(argv[0], retval, "while calling ext2fs_brel_next");
+ return;
+ }
+ if (blk == 0)
+ break;
+
+ display_brel_entry(blk, &ent);
+ }
+ return;
+}
+
+void do_brel_move(int argc, char **argv)
+{
+ const char *usage = "%s old_block new_block";
+ errcode_t retval;
+ blk_t old, new;
+
+ if (check_brel(argv[0]))
+ return;
+ if (argc < 2) {
+ printf(usage, argv[0]);
+ return;
+ }
+ if (parse_block(argv[0], "old block", argv[1], &old))
+ return;
+ if (parse_block(argv[0], "new block", argv[2], &new))
+ return;
+
+ retval = ext2fs_brel_move(brel, old, new);
+ if (retval) {
+ com_err(argv[0], retval, "while calling ext2fs_brel_move");
+ return;
+ }
+ return;
+}
+
+void do_brel_delete(int argc, char **argv)
+{
+ const char *usage = "%s block";
+ errcode_t retval;
+ blk_t blk;
+
+ if (check_brel(argv[0]))
+ return;
+ if (argc < 2) {
+ printf(usage, argv[0]);
+ return;
+ }
+ if (parse_block(argv[0], "block", argv[1], &blk))
+ return;
+
+ retval = ext2fs_brel_delete(brel, blk);
+ if (retval) {
+ com_err(argv[0], retval, "while calling ext2fs_brel_delete");
+ return;
+ }
+}
+
+void do_irel_ma_create(int argc, char **argv)
+{
+ const char *usage = "Usage: %s name max_inode\n";
+ errcode_t retval;
+ ino_t max_ino;
+
+ if (argc < 3) {
+ printf(usage, argv[0]);
+ return;
+ }
+ if (parse_inode(argv[0], "max_inodes", argv[2], &max_ino))
+ return;
+ retval = ext2fs_irel_memarray_create(argv[1], max_ino, &irel);
+ if (retval) {
+ com_err(argv[0], retval, "while opening memarray irel");
+ return;
+ }
+ return;
+}
+
+void do_irel_free(int argc, char **argv)
+{
+ if (check_irel(argv[0]))
+ return;
+
+ ext2fs_irel_free(irel);
+ irel = NULL;
+ return;
+}
+
+void do_irel_put(int argc, char **argv)
+{
+ const char *usage = "%s old new max_refs";
+ struct ext2_inode_relocate_entry ent;
+ errcode_t retval;
+ ino_t old, new, max_refs;
+
+ if (check_irel(argv[0]))
+ return;
+
+ if (argc < 4) {
+ printf(usage, argv[0]);
+ return;
+ }
+ if (parse_inode(argv[0], "old inode", argv[1], &old))
+ return;
+ if (parse_inode(argv[0], "new inode", argv[2], &new))
+ return;
+ if (parse_inode(argv[0], "max_refs", argv[3], &max_refs))
+ return;
+ if (max_refs > 65535) {
+ printf("max_refs too big\n");
+ return;
+ }
+ ent.new = new;
+ ent.max_refs = (__u16) max_refs;
+ ent.flags = 0;
+
+ retval = ext2fs_irel_put(irel, old, &ent);
+ if (retval) {
+ com_err(argv[0], retval, "while calling ext2fs_irel_put");
+ return;
+ }
+ return;
+}
+
+void do_irel_get(int argc, char **argv)
+{
+ const char *usage = "%s inode";
+ struct ext2_inode_relocate_entry ent;
+ errcode_t retval;
+ ino_t old;
+
+ if (check_irel(argv[0]))
+ return;
+
+ if (argc < 2) {
+ printf(usage, argv[0]);
+ return;
+ }
+ if (parse_inode(argv[0], "inode", argv[1], &old))
+ return;
+
+ retval = ext2fs_irel_get(irel, old, &ent);
+ if (retval) {
+ com_err(argv[0], retval, "while calling ext2fs_irel_get");
+ return;
+ }
+ display_irel_entry(old, &ent, 1);
+ return;
+}
+
+void do_irel_get_by_orig(int argc, char **argv)
+{
+ const char *usage = "%s orig_inode";
+ errcode_t retval;
+ struct ext2_inode_relocate_entry ent;
+ ino_t orig, old;
+
+ if (check_irel(argv[0]))
+ return;
+
+ if (argc < 2) {
+ printf(usage, argv[0]);
+ return;
+ }
+ if (parse_inode(argv[0], "original inode", argv[1], &orig))
+ return;
+
+ retval = ext2fs_irel_get_by_orig(irel, orig, &old, &ent);
+ if (retval) {
+ com_err(argv[0], retval, "while calling ext2fs_irel_get_by_orig");
+ return;
+ }
+ display_irel_entry(old, &ent, 1);
+ return;
+}
+
+void do_irel_start_iter(int argc, char **argv)
+{
+ errcode_t retval;
+
+ if (check_irel(argv[0]))
+ return;
+
+ retval = ext2fs_irel_start_iter(irel);
+ if (retval) {
+ com_err(argv[0], retval, "while calling ext2fs_irel_start_iter");
+ return;
+ }
+ return;
+}
+
+void do_irel_next(int argc, char **argv)
+{
+ errcode_t retval;
+ struct ext2_inode_relocate_entry ent;
+ ino_t old;
+
+ if (check_irel(argv[0]))
+ return;
+
+ retval = ext2fs_irel_next(irel, &old, &ent);
+ if (retval) {
+ com_err(argv[0], retval, "while calling ext2fs_irel_next");
+ return;
+ }
+ if (old == 0) {
+ printf("No more entries!\n");
+ return;
+ }
+ display_irel_entry(old, &ent, 1);
+ return;
+}
+
+void do_irel_dump(int argc, char **argv)
+{
+ errcode_t retval;
+ struct ext2_inode_relocate_entry ent;
+ ino_t ino;
+
+ if (check_irel(argv[0]))
+ return;
+
+ retval = ext2fs_irel_start_iter(irel);
+ if (retval) {
+ com_err(argv[0], retval, "while calling ext2fs_irel_start_iter");
+ return;
+ }
+
+ while (1) {
+ retval = ext2fs_irel_next(irel, &ino, &ent);
+ if (retval) {
+ com_err(argv[0], retval, "while calling ext2fs_irel_next");
+ return;
+ }
+ if (ino == 0)
+ break;
+
+ display_irel_entry(ino, &ent, 1);
+ }
+ return;
+}
+
+void do_irel_add_ref(int argc, char **argv)
+{
+ const char *usage = "%s inode block offset";
+ errcode_t retval;
+ struct ext2_inode_reference ref;
+ blk_t block, offset;
+ ino_t ino;
+
+
+ if (check_irel(argv[0]))
+ return;
+
+ if (argc < 4) {
+ printf(usage, argv[0]);
+ return;
+ }
+ if (parse_inode(argv[0], "inode", argv[1], &ino))
+ return;
+ if (parse_block(argv[0], "block", argv[2], &block))
+ return;
+ if (parse_block(argv[0], "offset", argv[3], &offset))
+ return;
+ if (offset > 65535) {
+ printf("Offset too big.\n");
+ return;
+ }
+ ref.block = block;
+ ref.offset = offset;
+
+ retval = ext2fs_irel_add_ref(irel, ino, &ref);
+ if (retval) {
+ com_err(argv[0], retval, "while calling ext2fs_irel_add_ref");
+ return;
+ }
+ return;
+}
+
+void do_irel_start_iter_ref(int argc, char **argv)
+{
+ const char *usage = "%s inode";
+ errcode_t retval;
+ ino_t ino;
+
+ if (check_irel(argv[0]))
+ return;
+
+ if (argc < 2) {
+ printf(usage, argv[0]);
+ return;
+ }
+
+ if (parse_inode(argv[0], "inode", argv[1], &ino))
+ return;
+ retval = ext2fs_irel_start_iter_ref(irel, ino);
+ if (retval) {
+ com_err(argv[0], retval, "while calling ext2fs_irel_start_iter_ref");
+ return;
+ }
+ return;
+}
+
+void do_irel_next_ref(int argc, char **argv)
+{
+ struct ext2_inode_reference ref;
+ errcode_t retval;
+
+ if (check_irel(argv[0]))
+ return;
+
+ retval = ext2fs_irel_next_ref(irel, &ref);
+ if (retval) {
+ com_err(argv[0], retval, "while calling ext2fs_irel_next_ref");
+ return;
+ }
+ printf("Inode reference: %u:%u\n", ref.block, ref.offset);
+ return;
+}
+
+void do_irel_move(int argc, char **argv)
+{
+ const char *usage = "%s old new";
+ errcode_t retval;
+ ino_t old, new;
+
+ if (check_irel(argv[0]))
+ return;
+
+ if (argc < 3) {
+ printf(usage, argv[0]);
+ return;
+ }
+ if (parse_inode(argv[0], "old inode", argv[1], &old))
+ return;
+ if (parse_inode(argv[0], "new inode", argv[2], &new))
+ return;
+
+ retval = ext2fs_irel_move(irel, old, new);
+ if (retval) {
+ com_err(argv[0], retval, "while calling ext2fs_irel_move");
+ return;
+ }
+ return;
+}
+
+void do_irel_delete(int argc, char **argv)
+{
+ const char *usage = "%s inode";
+ errcode_t retval;
+ ino_t ino;
+
+ if (check_irel(argv[0]))
+ return;
+
+ if (argc < 2) {
+ printf(usage, argv[0]);
+ return;
+ }
+ if (parse_inode(argv[0], "inode", argv[1], &ino))
+ return;
+
+ retval = ext2fs_irel_delete(irel, ino);
+ if (retval) {
+ com_err(argv[0], retval, "while calling ext2fs_irel_delete");
+ return;
+ }
+ return;
+}
+
+static int source_file(const char *cmd_file, int sci_idx)
+{
+ FILE *f;
+ char buf[256];
+ char *cp;
+ int exit_status = 0;
+ int retval;
+ int noecho;
+
+ if (strcmp(cmd_file, "-") == 0)
+ f = stdin;
+ else {
+ f = fopen(cmd_file, "r");
+ if (!f) {
+ perror(cmd_file);
+ exit(1);
+ }
+ }
+ setbuf(stdout, NULL);
+ setbuf(stderr, NULL);
+ while (!feof(f)) {
+ if (fgets(buf, sizeof(buf), f) == NULL)
+ break;
+ if (buf[0] == '#')
+ continue;
+ noecho = 0;
+ if (buf[0] == '-') {
+ noecho = 1;
+ buf[0] = ' ';
+ }
+ cp = strchr(buf, '\n');
+ if (cp)
+ *cp = 0;
+ cp = strchr(buf, '\r');
+ if (cp)
+ *cp = 0;
+ if (!noecho)
+ printf("test_rel: %s\n", buf);
+ retval = ss_execute_line(sci_idx, buf);
+ if (retval) {
+ ss_perror(sci_idx, retval, buf);
+ exit_status++;
+ }
+ }
+ return exit_status;
+}
+
+
+
+void main(int argc, char **argv)
+{
+ int retval;
+ int sci_idx;
+ const char *usage = "Usage: test_rel [-R request] [-f cmd_file]";
+ char c;
+ char *request = 0;
+ int exit_status = 0;
+ char *cmd_file = 0;
+
+ initialize_ext2_error_table();
+
+ while ((c = getopt (argc, argv, "wR:f:")) != EOF) {
+ switch (c) {
+ case 'R':
+ request = optarg;
+ break;
+ case 'f':
+ cmd_file = optarg;
+ break;
+ default:
+ com_err(argv[0], 0, usage);
+ return;
+ }
+ }
+ sci_idx = ss_create_invocation("test_rel", "0.0", (char *) NULL,
+ &test_cmds, &retval);
+ if (retval) {
+ ss_perror(sci_idx, retval, "creating invocation");
+ exit(1);
+ }
+
+ (void) ss_add_request_table (sci_idx, &ss_std_requests, 1, &retval);
+ if (retval) {
+ ss_perror(sci_idx, retval, "adding standard requests");
+ exit (1);
+ }
+ if (request) {
+ retval = 0;
+ retval = ss_execute_line(sci_idx, request);
+ if (retval) {
+ ss_perror(sci_idx, retval, request);
+ exit_status++;
+ }
+ } else if (cmd_file) {
+ exit_status = source_file(cmd_file, sci_idx);
+ } else {
+ ss_listen(sci_idx);
+ }
+
+ exit(exit_status);
+}
+
diff --git a/tests/progs/test_rel.h b/tests/progs/test_rel.h
new file mode 100644
index 0000000..be864c9
--- /dev/null
+++ b/tests/progs/test_rel.h
@@ -0,0 +1,35 @@
+/*
+ * test_rel.h
+ *
+ * Copyright (C) 1997 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+
+
+void do_brel_ma_create(int argc, char **argv);
+void do_brel_free(int argc, char **argv);
+void do_brel_put(int argc, char **argv);
+void do_brel_get(int argc, char **argv);
+void do_brel_start_iter(int argc, char **argv);
+void do_brel_next(int argc, char **argv);
+void do_brel_dump(int argc, char **argv);
+void do_brel_move(int argc, char **argv);
+void do_brel_delete(int argc, char **argv);
+void do_irel_ma_create(int argc, char **argv);
+void do_irel_free(int argc, char **argv);
+void do_irel_put(int argc, char **argv);
+void do_irel_get(int argc, char **argv);
+void do_irel_get_by_orig(int argc, char **argv);
+void do_irel_start_iter(int argc, char **argv);
+void do_irel_next(int argc, char **argv);
+void do_irel_dump(int argc, char **argv);
+void do_irel_add_ref(int argc, char **argv);
+void do_irel_start_iter_ref(int argc, char **argv);
+void do_irel_next_ref(int argc, char **argv);
+void do_irel_move(int argc, char **argv);
+void do_irel_delete(int argc, char **argv);
diff --git a/tests/progs/test_rel_cmds.ct b/tests/progs/test_rel_cmds.ct
new file mode 100644
index 0000000..5ed6ae2
--- /dev/null
+++ b/tests/progs/test_rel_cmds.ct
@@ -0,0 +1,82 @@
+#
+# Copyright (C) 1997 Theodore Ts'o. This file may be redistributed
+# under the terms of the GNU Public License.
+#
+command_table test_cmds;
+
+#
+# Block relocation table commands
+#
+
+request do_brel_ma_create, "Open a memory array block relocation table",
+ brel_ma_create, bma_create;
+
+request do_brel_free, "Free a block relocation table",
+ brel_free, bfree;
+
+request do_brel_put, "Add or modify a block relocation entry",
+ brel_put, bput;
+
+request do_brel_get, "Get a block relocation entry",
+ brel_get, bget;
+
+request do_brel_start_iter, "Start iterating over the block table",
+ brel_start_iter, bstart;
+
+request do_brel_next, "Get the next block relocation entry",
+ brel_next, bnext;
+
+request do_brel_dump, "Dump the block relocation table",
+ brel_dump, bdump;
+
+request do_brel_move, "Move an entry in the block relocation table",
+ brel_move, bmove;
+
+request do_brel_delete, "Delete an entry in the block relocation table",
+ brel_delete, bdelete, bdel;
+
+#
+# Inode relocation table commands
+#
+
+request do_irel_ma_create, "Open a memory array inode relocation table",
+ irel_ma_create, ima_create;
+
+request do_irel_free, "Free an inode relocation table",
+ irel_free, ifree;
+
+request do_irel_put, "Add or modify an inode relocation entry",
+ irel_put, iput;
+
+request do_irel_get, "Get an inode relocation entry",
+ irel_get, iget;
+
+request do_irel_get_by_orig,
+ "Get an inode relocation entry by its original number",
+ irel_get_by_orig, igetorig, igeto;
+
+request do_irel_start_iter, "Start iterating over the inode table",
+ irel_start_iter, istart;
+
+request do_irel_next, "Get the next block relocation entry",
+ irel_next, inext;
+
+request do_irel_dump, "Dump the inode relocation table",
+ irel_dump, idump;
+
+request do_irel_add_ref, "Add a reference to an inode entry",
+ irel_add_ref, iaddref, iaddr;
+
+request do_irel_start_iter_ref, "Start iterating over references to an inode",
+ irel_start_iter_ref, istartref, istartr;
+
+request do_irel_next_ref, "Get the next reference for an inode entry",
+ irel_next_ref, inextref, inextr;
+
+request do_irel_move, "Move an entry in the inode relocation table",
+ irel_move, imove;
+
+request do_irel_delete, "Delete an entry in the inode relocation table",
+ irel_delete, idelete, idel;
+
+end;
diff --git a/tests/test_config b/tests/test_config
index 5e3ebb2..6a42476 100644
--- a/tests/test_config
+++ b/tests/test_config
@@ -9,6 +9,7 @@
CHATTR=../misc/chattr
LSATTR=../misc/lsattr
DEBUGFS=../debugfs/debugfs
+TEST_REL=../tests/progs/test_rel
LD_LIBRARY_PATH=../lib:../lib/ext2fs:../lib/e2p:../lib/et:../lib/ss
TMPFILE=./test.img
export LD_LIBRARY_PATH
diff --git a/tests/test_script.in b/tests/test_script.in
index b06e905..fcb4cf3 100644
--- a/tests/test_script.in
+++ b/tests/test_script.in
@@ -24,6 +24,10 @@
for test_dir in $TESTS
do
test_name=`echo $test_dir | sed -e 's;.*/;;'`
+ if [ ! -d $test_dir ] ; then
+ echo "The test '$test_name' does not exist."
+ continue;
+ fi
if [ -f $test_dir/name ]; then
test_description=`cat $test_dir/name`
echo -n "$test_name: $test_description: "