diff --git a/debugfs/ChangeLog b/debugfs/ChangeLog index 75c0c5d8..c143fc63 100644 --- a/debugfs/ChangeLog +++ b/debugfs/ChangeLog @@ -1,3 +1,8 @@ +Thu Apr 10 14:36:05 1997 Theodore Ts'o + + * ls.c: New file which implements the ls command. Added the -l + option. + Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o * Release of E2fsprogs version 1.07 diff --git a/debugfs/Makefile.in b/debugfs/Makefile.in index 31ea1605..dad1f907 100644 --- a/debugfs/Makefile.in +++ b/debugfs/Makefile.in @@ -16,9 +16,9 @@ MANPAGES= debugfs.8 MK_CMDS= ../lib/ss/mk_cmds -DEBUG_OBJS= debug_cmds.o debugfs.o util.o ncheck.o icheck.o lsdel.o dump.o +DEBUG_OBJS= debug_cmds.o debugfs.o util.o ncheck.o icheck.o ls.o lsdel.o dump.o -SRCS= debug_cmds.c $(srcdir)/debugfs.c $(srcdir)/util.c \ +SRCS= debug_cmds.c $(srcdir)/debugfs.c $(srcdir)/util.c $(srcdir)/ls.c \ $(srcdir)/ncheck.c $(srcdir)/icheck.c $(srcdir)/lsdel.c \ $(srcdir)/dump.c diff --git a/debugfs/debugfs.8.in b/debugfs/debugfs.8.in index dc6352ab..72b12ec6 100644 --- a/debugfs/debugfs.8.in +++ b/debugfs/debugfs.8.in @@ -150,7 +150,7 @@ which is a link to .IR filespec . Note this does not adjust the inode reference counts. .TP -.I ls filespec +.I ls [-l] filespec Print a listing of the files in the directory .IR filespec . .TP diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c index 0797a889..ded79cce 100644 --- a/debugfs/debugfs.c +++ b/debugfs/debugfs.c @@ -727,78 +727,6 @@ void do_modify_inode(int argc, char *argv[]) } } -/* - * list directory - */ - -struct list_dir_struct { - FILE *f; - int col; -}; - -static int list_dir_proc(struct ext2_dir_entry *dirent, - int offset, - int blocksize, - char *buf, - void *private) -{ - char name[EXT2_NAME_LEN]; - char tmp[EXT2_NAME_LEN + 16]; - - struct list_dir_struct *ls = (struct list_dir_struct *) private; - int thislen; - - thislen = (dirent->name_len < EXT2_NAME_LEN) ? dirent->name_len : - EXT2_NAME_LEN; - strncpy(name, dirent->name, thislen); - name[thislen] = '\0'; - - sprintf(tmp, "%d (%d) %s ", dirent->inode, dirent->rec_len, name); - thislen = strlen(tmp); - - if (ls->col + thislen > 80) { - fprintf(ls->f, "\n"); - ls->col = 0; - } - fprintf(ls->f, "%s", tmp); - ls->col += thislen; - - return 0; -} - -void do_list_dir(int argc, char *argv[]) -{ - ino_t inode; - int retval; - struct list_dir_struct ls; - - if (argc > 2) { - com_err(argv[0], 0, "Usage: list_dir [pathname]"); - return; - } - if (check_fs_open(argv[0])) - return; - - if (argc == 2) - inode = string_to_inode(argv[1]); - else - inode = cwd; - if (!inode) - return; - - ls.f = open_pager(); - ls.col = 0; - retval = ext2fs_dir_iterate(current_fs, inode, - DIRENT_FLAG_INCLUDE_EMPTY, - 0, list_dir_proc, &ls); - fprintf(ls.f, "\n"); - close_pager(ls.f); - if (retval) - com_err(argv[1], retval, ""); - - return; -} - void do_change_working_dir(int argc, char *argv[]) { ino_t inode; @@ -1337,6 +1265,7 @@ static void kill_file_by_inode(ino_t inode) printf("Kill file by inode %ld\n", inode); ext2fs_block_iterate(current_fs, inode, 0, NULL, release_blocks_proc, NULL); + printf("\n"); ext2fs_unmark_inode_bitmap(current_fs->inode_map, inode); ext2fs_mark_bb_dirty(current_fs); @@ -1479,7 +1408,7 @@ void main(int argc, char **argv) { int retval; int sci_idx; - const char *usage = "Usage: debugfs [-w] [device]"; + const char *usage = "Usage: debugfs [[-w] device]"; char c; int open_flags = 0; char *request = 0; diff --git a/debugfs/ls.c b/debugfs/ls.c new file mode 100644 index 00000000..98c1d607 --- /dev/null +++ b/debugfs/ls.c @@ -0,0 +1,137 @@ +/* + * ls.c --- list directories + * + * Copyright (C) 1997 Theodore Ts'o. This file may be redistributed + * under the terms of the GNU Public License. + */ + +#include +#include +#include +#include +#include +#include +#ifdef HAVE_ERRNO_H +#include +#endif +#include + +#include "debugfs.h" + +/* + * list directory + */ + +#define LONG_OPT 0x0001 + +struct list_dir_struct { + FILE *f; + int col; + int options; +}; + +static const char *monstr[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + +static void ls_l_file(struct list_dir_struct *ls, char *name, ino_t ino) +{ + struct ext2_inode inode; + errcode_t retval; + struct tm *tm_p; + time_t modtime; + char datestr[80]; + + retval = ext2fs_read_inode(current_fs, ino, &inode); + if (retval) { + fprintf(ls->f, "%5d --- error --- %s\n", name); + return; + } + modtime = inode.i_mtime; + tm_p = localtime(&modtime); + sprintf(datestr, "%2d-%s-%2d %02d:%02d", + tm_p->tm_mday, monstr[tm_p->tm_mon], tm_p->tm_year, + tm_p->tm_hour, tm_p->tm_min); + fprintf(ls->f, "%6d %6o %5d %5d %5d %s %s\n", ino, inode.i_mode, + inode.i_uid, inode.i_gid, inode.i_size, datestr, name); +} + +static void ls_file(struct list_dir_struct *ls, char *name, + ino_t ino, int rec_len) +{ + char tmp[EXT2_NAME_LEN + 16]; + int thislen; + + sprintf(tmp, "%d (%d) %s ", ino, rec_len, name); + thislen = strlen(tmp); + + if (ls->col + thislen > 80) { + fprintf(ls->f, "\n"); + ls->col = 0; + } + fprintf(ls->f, "%s", tmp); + ls->col += thislen; +} + + +static int list_dir_proc(struct ext2_dir_entry *dirent, + int offset, + int blocksize, + char *buf, + void *private) +{ + char name[EXT2_NAME_LEN]; + char tmp[EXT2_NAME_LEN + 16]; + + struct list_dir_struct *ls = (struct list_dir_struct *) private; + int thislen; + + thislen = (dirent->name_len < EXT2_NAME_LEN) ? dirent->name_len : + EXT2_NAME_LEN; + strncpy(name, dirent->name, thislen); + name[thislen] = '\0'; + + if (ls->options & LONG_OPT) + ls_l_file(ls, name, dirent->inode); + else + ls_file(ls, name, dirent->inode, dirent->rec_len); + + return 0; +} + +void do_list_dir(int argc, char *argv[]) +{ + ino_t inode; + int retval; + struct list_dir_struct ls; + int argptr = 1; + + ls.options = 0; + if (check_fs_open(argv[0])) + return; + + if ((argc > argptr) && (argv[argptr][0] == '-')) { + argptr++; + ls.options = LONG_OPT; + } + + if (argc <= argptr) + inode = cwd; + else + inode = string_to_inode(argv[argptr]); + if (!inode) + return; + + ls.f = open_pager(); + ls.col = 0; + retval = ext2fs_dir_iterate(current_fs, inode, + DIRENT_FLAG_INCLUDE_EMPTY, + 0, list_dir_proc, &ls); + fprintf(ls.f, "\n"); + close_pager(ls.f); + if (retval) + com_err(argv[1], retval, ""); + + return; +} + + diff --git a/doc/libext2fs.texinfo b/doc/libext2fs.texinfo index 9769985e..0506e5c4 100644 --- a/doc/libext2fs.texinfo +++ b/doc/libext2fs.texinfo @@ -1,7 +1,7 @@ \input texinfo @c -*-texinfo-*- @c %**start of header @setfilename libext2fs.info -@settitle The EXT2FS Library (version 1.07) +@settitle The EXT2FS Library (version 1.08) @synindex tp fn @comment %**end of header @@ -60,8 +60,8 @@ by the author. @title The EXT2FS Library @subtitle The EXT2FS Library -@subtitle Version 1.07 -@subtitle February 1997 +@subtitle Version 1.08 +@subtitle April 1997 @author by Theodore Ts'o @@ -101,7 +101,7 @@ by the Foundation. @top The EXT2FS Library -This manual documents the EXT2FS Library, version 1.07. +This manual documents the EXT2FS Library, version 1.08. @end ifinfo @@ -130,8 +130,7 @@ manipulate an ext2 filesystem. * Inode Functions:: * Directory functions:: * Bitmap Functions:: -* Badblocks list management:: -* Directory-block list management:: +* EXT2 data abstractions:: * Byte-swapping functions:: * Other functions:: @end menu @@ -505,9 +504,21 @@ EXT2_ET_MISSING_INODE_TABLE. @subsection Convenience functions for Inodes @deftypefun errcode_t ext2fs_get_blocks (ext2_filsys @var{fs}, ino_t @var{ino}, blk_t *@var{blocks}) + +Returns an array of blocks corresponding to the direct, +indirect, doubly indirect, and triply indirect blocks as stored in the +inode structure. @end deftypefun @deftypefun errcode_t ext2fs_check_directory (ext2_filsys @var{fs}, ino_t @var{ino}) +Returns 0 if @var{ino} is a directory, and @code{ENOTDIR} if it is not. +@end deftypefun + +@deftypefun int ext2_inode_has_valid_blocks (struct ext2_inode *@var{inode}) + +Returns 1 if the inode's block entries actually valid block entries, and +0 if not. Inodes which represent devices and fast symbolic links do not +contain valid block entries. @end deftypefun @c ---------------------------------------------------------------------- @@ -603,7 +614,7 @@ EXT2_ET_MISSING_INODE_TABLE. @c ---------------------------------------------------------------------- -@node Bitmap Functions, Badblocks list management, Directory functions, EXT2FS Library Functions +@node Bitmap Functions, EXT2 data abstractions, Directory functions, EXT2FS Library Functions @comment node-name, next, previous, up @section Bitmap Functions @@ -786,9 +797,24 @@ Return the first inode or block which is stored in the bitmap. @c ---------------------------------------------------------------------- -@node Badblocks list management, Directory-block list management, Bitmap Functions, EXT2FS Library Functions +@node EXT2 data abstractions, Byte-swapping functions, Bitmap Functions, EXT2FS Library Functions @comment node-name, next, previous, up -@section Badblocks list management +@section EXT2 data abstractions + +The ext2 library has a number of abstractions which are useful for ext2 +utility programs. + +@menu +* Badblocks list management:: +* Directory-block list management:: +* Inode count functions:: +@end menu + +@c ---------------------------------------------------------------------- + +@node Badblocks list management, Directory-block list management, EXT2 data abstractions, EXT2 data abstractions +@comment node-name, next, previous, up +@subsection Badblocks list management @deftypefun errcode_t ext2fs_badblocks_list_create (ext2_badblocks_list *@var{ret}, int @var{size}) @@ -824,29 +850,130 @@ Return the first inode or block which is stored in the bitmap. @c ---------------------------------------------------------------------- -@node Directory-block list management, Byte-swapping functions, Badblocks list management, EXT2FS Library Functions +@node Directory-block list management, Inode count functions, Badblocks list management, EXT2 data abstractions @comment node-name, next, previous, up -@section Directory-block list management +@subsection Directory-block list management + +The dblist abstraction stores a list of blocks belonging to +directories. This list can be useful when a program needs to interate +over all directory entries in a filesystem; @code{e2fsck} does this in +pass 2 of its operations, and @code{debugfs} needs to do this when it is +trying to turn an inode number into a pathname. @deftypefun errcode_t ext2fs_init_dblist (ext2_filsys @var{fs}, ext2_dblist *@var{ret_dblist}) + +Creates a dblist data structure and return it in @var{ret_dblist}. @end deftypefun @deftypefun void ext2fs_free_dblist (ext2_dblist @var{dblist}) + +Free a dblist data structure. @end deftypefun -@deftypefun errcode_t ext2fs_add_dir_block (ext2_dblist dblist, ino_t @var{ino}, blk_t @var{blk}, int @var{blockcnt}) +@deftypefun errcode_t ext2fs_add_dir_block (ext2_dblist @var{dblist}, ino_t @var{ino}, blk_t @var{blk}, int @var{blockcnt}) + +Add an entry to the dblist data structure. This call records the fact +that block number @var{blockcnt} of directory inode @var{ino} is stored +in block @var{blk}. @end deftypefun -@deftypefun errcode_t ext2fs_dblist_iterate (ext2_dblist dblist, int (*func)(ext2_filsys @var{fs}, struct ext2_db_entry *@var{db_info}, void *@var{private}), void *@var{private}) +@deftypefun errcode_t ext2fs_set_dir_block (ext2_dblist @var{dblist}, ino_t @var{ino}, blk_t @var{blk}, int @var{blockcnt}) + +Change an entry in the dblist data structure; this changes the location +of block number @var{blockcnt} of directory indoe @var{ino} to be block +@var{blk}. @end deftypefun -@deftypefun errcode_t ext2fs_dblist_dir_iterate -(ext2_dblist dblist, int flags, char *@var{block_buf}, int (*func)(ino_t @var{dir}, int @var{entry}, struct ext2_dir_entry *@var{dirent}, int @var{offset}, int @var{blocksize}, char *@var{buf}, void *@var{private}), void *@var{private}) +@deftypefun errcode_t ext2fs_dblist_iterate (ext2_dblist @var{dblist}, int (*func)(ext2_filsys @var{fs}, struct ext2_db_entry *@var{db_info}, void *@var{private}), void *@var{private}) + +This iterator calls @var{func} for every entry in the dblist data structure. +@end deftypefun + +@deftypefun errcode_t ext2fs_dblist_dir_iterate (ext2_dblist @var{dblist}, int flags, char *@var{block_buf}, int (*func)(ino_t @var{dir}, int @var{entry}, struct ext2_dir_entry *@var{dirent}, int @var{offset}, int @var{blocksize}, char *@var{buf}, void *@var{private}), void *@var{private}) + +This iterator takes reads in the directory block indicated in each +dblist entry, and calls @var{func} for each directory entry in each +directory block. If @var{dblist} contains all the directory blocks in a +filesystem, this function provides a convenient way to iterate over all +directory entries for that filesystem. @end deftypefun @c ---------------------------------------------------------------------- -@node Byte-swapping functions, Other functions, Directory-block list management, EXT2FS Library Functions +@node Inode count functions, , Directory-block list management, EXT2 data abstractions +@comment node-name, next, previous, up +@subsection Inode count functions + +The icount abstraction is a specialized data type used by @code{e2fsck} +to store how many times a particular inode is referenced by the +filesystem. This is used twice; once to store the actual number of times +that the inode is reference; and once to store the claimed number of times +the inode is referenced according to the inode structure. + +This abstraction is designed to be extremely efficient for storing this +sort of information, by taking advantage of the following properties of +inode counts, namely (1) inode counts are very often zero (because +the inode is currrently not in use), and (2) many files have a inode +count of 1 (because they are a file which has no additional hard links). + +@deftypefun errcode_t ext2fs_create_icount2(ext2_filsys @var{fs}, int @var{flags}, int @var{size}, ext2_icount_t @var{hint}, ext2_icount_t *@var{ret}) + +Creates an icount stucture for a filesystem @var{fs}, with initial space +for @var{size} inodes whose count is greater than 1. The @var{flags} +parameter is either 0 or @code{EXT2_ICOUNT_OPT_INCREMENT}, which +indicates that icount structure should be able to increment inode counts +quickly. The icount structure is returned in @var{ret}. The returned +icount structure initially has a count of zero for all inodes. + +The @var{hint} parameter allows the caller to optionally pass in another +icount structure which is used to initialize the array of inodes whose +count is greater than 1. It is used purely as a speed optimization so +that the icount structure can determine in advance which inodes are +likely to contain a count grater than 1. +@end deftypefun + +@deftypefun void ext2fs_free_icount(ext2_icount_t @var{icount}) + +Frees an icount structure. +@end deftypefun + +@deftypefun errcode_t ext2fs_icount_fetch(ext2_icount_t @var{icount}, ino_t @var{ino}, __u16 *@var{ret}) + +Returns in @var{ret} fetches the count for a particular inode @var{ino}. +@end deftypefun + +@deftypefun errcode_t ext2fs_icount_increment(ext2_icount_t @var{icount}, ino_t @var{ino}, __u16 *@var{ret}) + +Increments the ref count for inode @var{ino}. +@end deftypefun + +@deftypefun errcode_t ext2fs_icount_decrement(ext2_icount_t @var{icount}, ino_t @var{ino}, __u16 *@var{ret}) + +Decrements the ref count for inode @var{ino}. +@end deftypefun + +@deftypefun errcode_t ext2fs_icount_store(ext2_icount_t @var{icount}, ino_t @var{ino}, __u16 @var{count}) + +Sets the reference count for inode @var{ino} to be @var{count}. +@end deftypefun + +@deftypefun ino_t ext2fs_get_icount_size(ext2_icount_t @var{icount}) + +Returns the current number of inodes in @var{icount} which has a count +greater than 1. +@end deftypefun + +@deftypefun errcode_t ext2fs_icount_validate(ext2_icount_t @var{icount}, FILE *@var{f}) + +Validates the internal rep invariant of @var{icount}; if there are any +problems, print out debugging information to @var{f}. This function is +intended for debugging and testing use only. +@end deftypefun + + +@c ---------------------------------------------------------------------- + +@node Byte-swapping functions, Other functions, EXT2 data abstractions, EXT2FS Library Functions @comment node-name, next, previous, up @section Byte-swapping functions @@ -896,11 +1023,29 @@ Return the first inode or block which is stored in the bitmap. @deftypefun errcode_t ext2fs_check_if_mounted (const char *@var{file}, int *@var{mount_flags}) @end deftypefun +/* version.c */ -/* valid_blk.c */ -@deftypefun int ext2_inode_has_valid_blocks (struct ext2_inode *@var{inode}) +@deftypefun int ext2fs_get_library_version(const char **@var{ver_string}, const char **@var{date_string}) + +This function returns the current version of the ext2 library. The +return value contains an integer version code, which consists of the +major version number of the library multiplied by 100, plus the minor +version number of the library. Hence, if the library version is 1.08, +the returned value will be 108. + +If @var{ver_string} and/or @var{date_string} are non-NULL, they will be +set to point at a constant string containing the library version and/or +release date, respectively. @end deftypefun +@deftypefun int ext2fs_parse_version_string(const char *@var{ver_string}) + +This function takes a version string which may included in an +application and returns a version code using the same algorithm used by +@code{ext2fs_get_library_version}. It can be used by programs included +in the @code{e2fsprogs} distribution to assure that they are using an +up-to-date ext2 shared library. +@end deftypefun /* inline functions */ @deftypefun int ext2fs_group_of_blk (ext2_filsys @var{fs}, blk_t @var{blk}) diff --git a/e2fsck/ChangeLog b/e2fsck/ChangeLog index d37988d1..51db19bd 100644 --- a/e2fsck/ChangeLog +++ b/e2fsck/ChangeLog @@ -1,3 +1,38 @@ +Thu Apr 10 13:51:16 1997 Theodore Ts'o + + * pass1b.c (clone_file_block): If we clone a directory, we need to + update the dblist entry so that we check (and correct) the + right directory block. + +Sun Apr 6 09:13:12 1997 Theodore Ts'o + + * pass1.c (process_block): Don't clear blocks references to + filesystem metadata; let pass 1B handle this case. + + * problem.c, problem.h: Add new problem, PR_1B_SHARE_METADATA. + + * pass1b.c (pass1d): Deal with a block which is shared with + filesystem metadata. + + * e2fsck.h: Make block_illegal_map be a global variable + +Sat Apr 5 11:51:58 1997 Theodore Ts'o + + * e2fsck.c, pass1.c (mark_table_blocks): Support the sparse_super + feature. + (get_backup_sb): New function which attempts to obtain the + correct backup superblock (if possible). + +Fri Apr 4 10:46:26 1997 Theodore Ts'o + + * e2fsck.c (main): Check the version of the library, and warn if + the library is out of date; this happens generally due to + users who manually install e2fsprogs. + + * pass1.c (pass1_get_blocks): If the passed in inode number for + get_blocks isn't what we're expecting pass back + EXT2_ET_CALLBACK_NOT_HANDLED. + Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o * Release of E2fsprogs version 1.07 diff --git a/e2fsck/e2fsck.c b/e2fsck/e2fsck.c index 9cebae4f..c40a4426 100644 --- a/e2fsck/e2fsck.c +++ b/e2fsck/e2fsck.c @@ -216,6 +216,13 @@ static void sync_disks(NOARGS) sync(); } +static blk_t get_backup_sb(ext2_filsys fs) +{ + if (!fs || !fs->super) + return 8193; + return fs->super->s_blocks_per_group + 1; +} + #define MIN_CHECK 1 #define MAX_CHECK 2 @@ -224,21 +231,22 @@ static const char *corrupt_msg = "filesystem. If the device is valid and it really contains an ext2\n" "filesystem (and not swap or ufs or something else), then the superblock\n" "is corrupt, and you might try running e2fsck with an alternate superblock:\n" -" e2fsck -b 8193 \n\n"; +" e2fsck -b %d \n\n"; -static void check_super_value(const char *descr, unsigned long value, - int flags, unsigned long min, unsigned long max) +static void check_super_value(ext2_filsys fs, const char *descr, + unsigned long value, int flags, + unsigned long min, unsigned long max) { if (((flags & MIN_CHECK) && (value < min)) || ((flags & MAX_CHECK) && (value > max))) { printf("Corruption found in superblock. (%s = %lu).\n", descr, value); - printf(corrupt_msg); + printf(corrupt_msg, get_backup_sb(fs)); fatal_error(0); } } -static void relocate_hint(void) +static void relocate_hint(ext2_filsys fs) { static hint_issued = 0; @@ -252,9 +260,9 @@ static void relocate_hint(void) printf("Note: if there is several inode or block bitmap blocks\n" "which require relocation, or one part of the inode table\n" "which must be moved, you may wish to try running e2fsck\n" - "the '-b 8193' option first. The problem may lie only with\n" - "the primary block group descriptor, and the backup block\n" - "group descriptor may be OK.\n\n"); + "with the '-b %d' option first. The problem may lie only\n" + "with the primary block group descriptor, and the backup\n" + "block group descriptor may be OK.\n\n", get_backup_sb(fs)); hint_issued = 1; } @@ -274,24 +282,24 @@ static void check_super_block(ext2_filsys fs) /* * Verify the super block constants... */ - check_super_value("inodes_count", s->s_inodes_count, + check_super_value(fs, "inodes_count", s->s_inodes_count, MIN_CHECK, 1, 0); - check_super_value("blocks_count", s->s_blocks_count, + check_super_value(fs, "blocks_count", s->s_blocks_count, MIN_CHECK, 1, 0); - check_super_value("first_data_block", s->s_first_data_block, + check_super_value(fs, "first_data_block", s->s_first_data_block, MAX_CHECK, 0, s->s_blocks_count); - check_super_value("log_frag_size", s->s_log_frag_size, + check_super_value(fs, "log_frag_size", s->s_log_frag_size, MAX_CHECK, 0, 2); - check_super_value("log_block_size", s->s_log_block_size, + check_super_value(fs, "log_block_size", s->s_log_block_size, MIN_CHECK | MAX_CHECK, s->s_log_frag_size, 2); - check_super_value("frags_per_group", s->s_frags_per_group, + check_super_value(fs, "frags_per_group", s->s_frags_per_group, MIN_CHECK | MAX_CHECK, 1, 8 * EXT2_BLOCK_SIZE(s)); - check_super_value("blocks_per_group", s->s_blocks_per_group, + check_super_value(fs, "blocks_per_group", s->s_blocks_per_group, MIN_CHECK | MAX_CHECK, 1, 8 * EXT2_BLOCK_SIZE(s)); - check_super_value("inodes_per_group", s->s_inodes_per_group, + check_super_value(fs, "inodes_per_group", s->s_inodes_per_group, MIN_CHECK, 1, 0); - check_super_value("r_blocks_count", s->s_r_blocks_count, + check_super_value(fs, "r_blocks_count", s->s_r_blocks_count, MAX_CHECK, 0, s->s_blocks_count); retval = ext2fs_get_device_size(filesystem_name, EXT2_BLOCK_SIZE(s), @@ -326,7 +334,7 @@ static void check_super_block(ext2_filsys fs) printf("Superblock blocks_per_group = %u, should " "have been %u\n", s->s_blocks_per_group, should_be); - printf(corrupt_msg); + printf(corrupt_msg, get_backup_sb(fs)); fatal_error(0); } @@ -335,7 +343,7 @@ static void check_super_block(ext2_filsys fs) printf("Superblock first_data_block = %u, should " "have been %u\n", s->s_first_data_block, should_be); - printf(corrupt_msg); + printf(corrupt_msg, get_backup_sb(fs)); fatal_error(0); } @@ -352,7 +360,7 @@ static void check_super_block(ext2_filsys fs) last_block = fs->super->s_blocks_count; if ((fs->group_desc[i].bg_block_bitmap < first_block) || (fs->group_desc[i].bg_block_bitmap >= last_block)) { - relocate_hint(); + relocate_hint(fs); pctx.blk = fs->group_desc[i].bg_block_bitmap; if (fix_problem(fs, PR_0_BB_NOT_GROUP, &pctx)) { fs->group_desc[i].bg_block_bitmap = 0; @@ -362,7 +370,7 @@ static void check_super_block(ext2_filsys fs) } if ((fs->group_desc[i].bg_inode_bitmap < first_block) || (fs->group_desc[i].bg_inode_bitmap >= last_block)) { - relocate_hint(); + relocate_hint(fs); pctx.blk = fs->group_desc[i].bg_inode_bitmap; if (fix_problem(fs, PR_0_IB_NOT_GROUP, &pctx)) { fs->group_desc[i].bg_inode_bitmap = 0; @@ -373,7 +381,7 @@ static void check_super_block(ext2_filsys fs) if ((fs->group_desc[i].bg_inode_table < first_block) || ((fs->group_desc[i].bg_inode_table + fs->inode_blocks_per_group - 1) >= last_block)) { - relocate_hint(); + relocate_hint(fs); pctx.blk = fs->group_desc[i].bg_inode_table; if (fix_problem(fs, PR_0_ITABLE_NOT_GROUP, &pctx)) { fs->group_desc[i].bg_inode_table = 0; @@ -591,6 +599,9 @@ static void PRS(int argc, char *argv[]) } } } + +static const char *my_ver_string = E2FSPROGS_VERSION; +static const char *my_ver_date = E2FSPROGS_DATE; int main (int argc, char *argv[]) { @@ -600,6 +611,8 @@ int main (int argc, char *argv[]) ext2_filsys fs = 0; io_manager io_ptr; struct ext2fs_sb *s; + const char *lib_ver_date; + int my_ver, lib_ver; #ifdef MTRACE mtrace(); @@ -607,6 +620,13 @@ int main (int argc, char *argv[]) #ifdef MCHECK mcheck(0); #endif + my_ver = ext2fs_parse_version_string(my_ver_string); + lib_ver = ext2fs_get_library_version(0, &lib_ver_date); + if (my_ver > lib_ver) { + fprintf( stderr, "Error: ext2fs library version " + "out of date!\n"); + show_version_only++; + } init_resource_track(&global_rtrack); @@ -614,12 +634,12 @@ int main (int argc, char *argv[]) if (!preen || show_version_only) fprintf (stderr, "e2fsck %s, %s for EXT2 FS %s, %s\n", - E2FSPROGS_VERSION, E2FSPROGS_DATE, - EXT2FS_VERSION, EXT2FS_DATE); + my_ver_string, my_ver_date, EXT2FS_VERSION, + EXT2FS_DATE); if (show_version_only) { - fprintf(stderr, "\tUsing %s\n", - error_message(EXT2_ET_BASE)); + fprintf(stderr, "\tUsing %s, %s\n", + error_message(EXT2_ET_BASE), lib_ver_date); exit(0); } @@ -663,7 +683,7 @@ restart: printf("%s trying backup blocks...\n", retval ? "Couldn't find ext2 superblock," : "Group descriptors look bad..."); - superblock = 8193; + superblock = get_backup_sb(fs); if (fs) ext2fs_close(fs); goto restart; @@ -683,7 +703,7 @@ restart: else if (retval == ENXIO) printf("Possibly non-existent or swap device?\n"); else - printf(corrupt_msg); + printf(corrupt_msg, get_backup_sb(fs)); fatal_error(0); } #ifdef EXT2_CURRENT_REV @@ -695,18 +715,23 @@ restart: } #endif /* - * Check for compatibility with the feature sets. We have to - * check because we need to be more stringent than ext2fs_open + * Check for compatibility with the feature sets. We need to + * be more stringent than ext2fs_open(). */ s = (struct ext2fs_sb *) fs->super; - if (s->s_feature_compat || s->s_feature_incompat || - s->s_feature_ro_compat) { + if ((s->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) || + (s->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) { com_err(program_name, EXT2_ET_UNSUPP_FEATURE, - " (%s)", filesystem_name); + "(%s)", filesystem_name); get_newer: printf ("Get a newer version of e2fsck!\n"); fatal_error(0); } + if (s->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) { + com_err(program_name, EXT2_ET_RO_UNSUPP_FEATURE, + "(%s)", filesystem_name); + goto get_newer; + } /* * If the user specified a specific superblock, presumably the diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h index 9eb0dad5..9efefa36 100644 --- a/e2fsck/e2fsck.h +++ b/e2fsck/e2fsck.h @@ -85,6 +85,7 @@ extern ext2fs_inode_bitmap inode_bb_map; /* Inodes which are in bad blocks */ extern ext2fs_block_bitmap block_found_map; /* Blocks which are in use */ extern ext2fs_block_bitmap block_dup_map; /* Blocks which are used by more than once */ +extern ext2fs_block_bitmap block_illegal_map; /* Meta-data blocks */ extern const char *fix_msg[2]; /* Fixed or ignored! */ extern const char *clear_msg[2]; /* Cleared or ignored! */ diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c index 2b058676..2c760a9c 100644 --- a/e2fsck/pass1.c +++ b/e2fsck/pass1.c @@ -217,7 +217,7 @@ void pass1(ext2_filsys fs) "while allocating block_illegal_map"); fatal_error(0); } - retval = ext2fs_create_icount(fs, 0, 0, &inode_link_info); + retval = ext2fs_create_icount2(fs, 0, 0, 0, &inode_link_info); if (retval) { com_err("ext2fs_create_icount", retval, "while creating inode_link_info"); @@ -821,8 +821,11 @@ int process_block(ext2_filsys fs, if (blk < fs->super->s_first_data_block || blk >= fs->super->s_blocks_count) problem = PR_1_ILLEGAL_BLOCK_NUM; - else if (ext2fs_test_block_bitmap(block_illegal_map, blk)) - problem = PR_1_BLOCK_OVERLAPS_METADATA; +#if 0 + else + if (ext2fs_test_block_bitmap(block_illegal_map, blk)) + problem = PR_1_BLOCK_OVERLAPS_METADATA; +#endif if (problem) { p->num_illegal_blocks++; @@ -1184,21 +1187,23 @@ static void mark_table_blocks(ext2_filsys fs) fs->group_desc[i].bg_inode_bitmap); } } - - /* - * Mark this group's copy of the superblock - */ - ext2fs_mark_block_bitmap(block_found_map, block); - ext2fs_mark_block_bitmap(block_illegal_map, block); + + if (ext2fs_bg_has_super(fs, i)) { + /* + * Mark this group's copy of the superblock + */ + ext2fs_mark_block_bitmap(block_found_map, block); + ext2fs_mark_block_bitmap(block_illegal_map, block); - /* - * Mark this group's copy of the descriptors - */ - for (j = 0; j < fs->desc_blocks; j++) { - ext2fs_mark_block_bitmap(block_found_map, - block + j + 1); - ext2fs_mark_block_bitmap(block_illegal_map, - block + j + 1); + /* + * Mark this group's copy of the descriptors + */ + for (j = 0; j < fs->desc_blocks; j++) { + ext2fs_mark_block_bitmap(block_found_map, + block + j + 1); + ext2fs_mark_block_bitmap(block_illegal_map, + block + j + 1); + } } block += fs->super->s_blocks_per_group; } @@ -1214,15 +1219,12 @@ errcode_t pass1_get_blocks(ext2_filsys fs, ino_t ino, blk_t *blocks) { int i; - if (ino == stashed_ino) { - for (i=0; i < EXT2_N_BLOCKS; i++) - blocks[i] = stashed_inode->i_block[i]; - return 0; - } - printf("INTERNAL ERROR: pass1_get_blocks: unexpected inode #%lu\n", - ino); - printf("\t(was expecting %lu)\n", stashed_ino); - exit(FSCK_ERROR); + if (ino != stashed_ino) + return EXT2_ET_CALLBACK_NOTHANDLED; + + for (i=0; i < EXT2_N_BLOCKS; i++) + blocks[i] = stashed_inode->i_block[i]; + return 0; } errcode_t pass1_read_inode(ext2_filsys fs, ino_t ino, struct ext2_inode *inode) diff --git a/e2fsck/pass1b.c b/e2fsck/pass1b.c index 27ca98b8..50865c14 100644 --- a/e2fsck/pass1b.c +++ b/e2fsck/pass1b.c @@ -277,6 +277,7 @@ int process_pass1b_block(ext2_filsys fs, struct search_dir_struct { int count; ino_t first_inode; + ino_t max_inode; }; static int search_dirent_proc(ino_t dir, int entry, @@ -287,6 +288,10 @@ static int search_dirent_proc(ino_t dir, int entry, struct search_dir_struct *sd = private; struct dup_inode *p; + if (dirent->inode > sd->max_inode) + /* Should abort this inode, but not everything */ + return 0; + if (!dirent->inode || (entry < DIRENT_OTHER_FILE) || !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode)) return 0; @@ -332,6 +337,7 @@ void pass1c(ext2_filsys fs, char *block_buf) */ sd.count = inodes_left; sd.first_inode = EXT2_FIRST_INODE(fs->super); + sd.max_inode = fs->super->s_inodes_count; ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf, search_dirent_proc, &sd); } @@ -345,6 +351,7 @@ static void pass1d(ext2_filsys fs, char *block_buf) int i; errcode_t retval; int file_ok; + int meta_data = 0; struct problem_context pctx; printf("Pass 1D: Reconciling duplicate blocks\n"); @@ -376,6 +383,12 @@ static void pass1d(ext2_filsys fs, char *block_buf) continue; if (q->num_bad > 1) file_ok = 0; + if (ext2fs_test_block_bitmap(block_illegal_map, + q->block)) { + file_ok = 0; + meta_data = 1; + } + /* * Add all inodes used by this block to the * shared[] --- which is a unique list, so @@ -402,11 +415,14 @@ static void pass1d(ext2_filsys fs, char *block_buf) pctx.ino = p->ino; pctx.dir = p->dir; pctx.blkcount = p->num_dupblocks; - pctx.num = shared_len; + pctx.num = meta_data ? shared_len+1 : shared_len; fix_problem(fs, PR_1B_DUP_FILE, &pctx); pctx.blkcount = 0; pctx.num = 0; + if (meta_data) + fix_problem(fs, PR_1B_SHARE_METADATA, &pctx); + for (i = 0; i < shared_len; i++) { for (s = dup_ino; s; s = s->next) if (s->ino == shared[i]) @@ -506,6 +522,7 @@ static void delete_file(ext2_filsys fs, struct dup_inode *dp, char* block_buf) struct clone_struct { errcode_t errcode; + ino_t dir; char *buf; }; @@ -533,6 +550,14 @@ static int clone_file_block(ext2_filsys fs, cs->errcode = retval; return BLOCK_ABORT; } + if (cs->dir) { + retval = ext2fs_set_dir_block(fs->dblist, + cs->dir, new_block, blockcnt); + if (retval) { + cs->errcode = retval; + return BLOCK_ABORT; + } + } retval = io_channel_read_blk(fs->io, *block_nr, 1, cs->buf); if (retval) { @@ -569,8 +594,12 @@ static int clone_file(ext2_filsys fs, struct dup_inode *dp, char* block_buf) cs.errcode = 0; cs.buf = malloc(fs->blocksize); + cs.dir = 0; if (!cs.buf) return ENOMEM; + + if (ext2fs_test_inode_bitmap(inode_dir_map, dp->ino)) + cs.dir = dp->ino; retval = ext2fs_block_iterate(fs, dp->ino, 0, block_buf, clone_file_block, &cs); diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c index 0032c852..8822e8f5 100644 --- a/e2fsck/pass2.c +++ b/e2fsck/pass2.c @@ -86,9 +86,8 @@ void pass2(ext2_filsys fs) if (!preen) printf("Pass 2: Checking directory structure\n"); - size = ext2fs_get_icount_size(inode_link_info) + 10; - retval = ext2fs_create_icount(fs, EXT2_ICOUNT_OPT_INCREMENT, - size, &inode_count); + retval = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT, + 0, inode_link_info, &inode_count); if (retval) { com_err("ext2fs_create_icount", retval, "while creating inode_count"); diff --git a/e2fsck/problem.c b/e2fsck/problem.c index 14908ad5..27526331 100644 --- a/e2fsck/problem.c +++ b/e2fsck/problem.c @@ -191,6 +191,10 @@ static struct e2fsck_problem problem_table[] = { "\t%Q (@i #%i, mod time %IM)\n", PROMPT_FIX, PR_MSG_ONLY }, + /* File sharing blocks with filesystem metadata */ + { PR_1B_SHARE_METADATA, + "\t\n", + PROMPT_FIX, PR_MSG_ONLY }, /* Pass 2 errors */ diff --git a/e2fsck/problem.h b/e2fsck/problem.h index 91da479a..e41cee15 100644 --- a/e2fsck/problem.h +++ b/e2fsck/problem.h @@ -125,6 +125,9 @@ struct e2fsck_problem { /* List of files sharing duplicate blocks */ #define PR_1B_DUP_FILE_LIST 0x011002 +/* File sharing blocks with filesystem metadata */ +#define PR_1B_SHARE_METADATA 0x011003 + /* * Pass 2 errors */ diff --git a/include/linux/ext2_fs.h b/include/linux/ext2_fs.h index 649f7dec..a0454253 100644 --- a/include/linux/ext2_fs.h +++ b/include/linux/ext2_fs.h @@ -38,6 +38,19 @@ #define EXT2FS_DATE "95/08/09" #define EXT2FS_VERSION "0.5b" +/* + * Debug code + */ +#ifdef EXT2FS_DEBUG +# define ext2_debug(f, a...) { \ + printk ("EXT2-fs DEBUG (%s, %d): %s:", \ + __FILE__, __LINE__, __FUNCTION__); \ + printk (f, ## a); \ + } +#else +# define ext2_debug(f, a...) /**/ +#endif + /* * Special inodes numbers */ @@ -47,7 +60,9 @@ #define EXT2_ACL_DATA_INO 4 /* ACL inode */ #define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */ #define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */ -#define EXT2_FIRST_INO 11 /* First non reserved inode */ + +/* First non-reserved inode for old ext2 filesystems */ +#define EXT2_GOOD_OLD_FIRST_INO 11 /* * The second extended file system magic number @@ -77,10 +92,17 @@ #else # define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10) #endif -#define EXT2_INODES_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_inode)) #ifdef __KERNEL__ #define EXT2_ADDR_PER_BLOCK_BITS(s) ((s)->u.ext2_sb.s_addr_per_block_bits) -#define EXT2_INODES_PER_BLOCK_BITS(s) ((s)->u.ext2_sb.s_inodes_per_block_bits) +#define EXT2_INODE_SIZE(s) ((s)->u.ext2_sb.s_inode_size) +#define EXT2_FIRST_INO(s) ((s)->u.ext2_sb.s_first_ino) +#else +#define EXT2_INODE_SIZE(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \ + EXT2_GOOD_OLD_INODE_SIZE : \ + (s)->s_inode_size) +#define EXT2_FIRST_INO(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \ + EXT2_GOOD_OLD_FIRST_INO : \ + (s)->s_first_ino) #endif /* @@ -167,7 +189,9 @@ struct ext2_group_desc #define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */ #define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */ #define EXT2_NODUMP_FL 0x00000040 /* do not dump file */ - +#define EXT2_NOATIME_FL 0x00000080 /* do not update atime */ +#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */ + /* * ioctl commands */ @@ -314,14 +338,36 @@ struct ext2_super_block { __u16 s_magic; /* Magic signature */ __u16 s_state; /* File system state */ __u16 s_errors; /* Behaviour when detecting errors */ - __u16 s_pad; + __u16 s_minor_rev_level; /* minor revision level */ __u32 s_lastcheck; /* time of last check */ __u32 s_checkinterval; /* max. time between checks */ __u32 s_creator_os; /* OS */ __u32 s_rev_level; /* Revision level */ __u16 s_def_resuid; /* Default uid for reserved blocks */ __u16 s_def_resgid; /* Default gid for reserved blocks */ - __u32 s_reserved[235]; /* Padding to the end of the block */ + /* + * These fields are for EXT2_DYNAMIC_REV superblocks only. + * + * Note: the difference between the compatible feature set and + * the incompatible feature set is that if there is a bit set + * in the incompatible feature set that the kernel doesn't + * know about, it should refuse to mount the filesystem. + * + * e2fsck's requirements are more strict; if it doesn't know + * about a feature in either the compatible or incompatible + * feature set, it must abort and not try to meddle with + * things it doesn't understand... + */ + __u32 s_first_ino; /* First non-reserved inode */ + __u16 s_inode_size; /* size of inode structure */ + __u16 s_block_group_nr; /* block group # of this superblock */ + __u32 s_feature_compat; /* compatible feature set */ + __u32 s_feature_incompat; /* incompatible feature set */ + __u32 s_feature_ro_compat; /* readonly-compatible feature set */ + __u8 s_uuid[16]; /* 128-bit uuid for volume */ + char s_volume_name[16]; /* volume name */ + char s_last_mounted[64]; /* directory where last mounted */ + __u32 s_reserved[206]; /* Padding to the end of the block */ }; /* @@ -337,8 +383,22 @@ struct ext2_super_block { * Revision levels */ #define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */ +#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */ #define EXT2_CURRENT_REV EXT2_GOOD_OLD_REV +#define EXT2_MAX_SUPP_REV EXT2_DYNAMIC_REV + +#define EXT2_GOOD_OLD_INODE_SIZE 128 + +/* + * Feature set definitions + */ + +#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001 + +#define EXT2_FEATURE_COMPAT_SUPP 0 +#define EXT2_FEATURE_INCOMPAT_SUPP 0 +#define EXT2_FEATURE_RO_COMPAT_SUPP EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER /* * Default values for user and/or group using reserved blocks @@ -391,9 +451,9 @@ struct ext2_dir_entry { extern int ext2_permission (struct inode *, int); /* balloc.c */ -extern int ext2_new_block (struct super_block *, unsigned long, - __u32 *, __u32 *); -extern void ext2_free_blocks (struct super_block *, unsigned long, +extern int ext2_new_block (const struct inode *, unsigned long, + __u32 *, __u32 *, int *); +extern void ext2_free_blocks (const struct inode *, unsigned long, unsigned long); extern unsigned long ext2_count_free_blocks (struct super_block *); extern void ext2_check_blocks_bitmap (struct super_block *); @@ -414,7 +474,7 @@ extern int ext2_write (struct inode *, struct file *, char *, int); extern int ext2_sync_file (struct inode *, struct file *); /* ialloc.c */ -extern struct inode * ext2_new_inode (const struct inode *, int); +extern struct inode * ext2_new_inode (const struct inode *, int, int *); extern void ext2_free_inode (struct inode *); extern unsigned long ext2_count_free_inodes (struct super_block *); extern void ext2_check_inodes_bitmap (struct super_block *); @@ -448,7 +508,7 @@ extern int ext2_symlink (struct inode *, const char *, int, const char *); extern int ext2_link (struct inode *, struct inode *, const char *, int); extern int ext2_mknod (struct inode *, const char *, int, int, int); extern int ext2_rename (struct inode *, const char *, int, - struct inode *, const char *, int); + struct inode *, const char *, int, int); /* super.c */ extern void ext2_error (struct super_block *, const char *, const char *, ...) @@ -462,6 +522,7 @@ extern void ext2_put_super (struct super_block *); extern void ext2_write_super (struct super_block *); extern int ext2_remount (struct super_block *, int *, char *); extern struct super_block * ext2_read_super (struct super_block *,void *,int); +extern int init_ext2_fs(void); extern void ext2_statfs (struct super_block *, struct statfs *, int); /* truncate.c */ diff --git a/lib/e2p/ChangeLog b/lib/e2p/ChangeLog index 9b18c363..1329eb37 100644 --- a/lib/e2p/ChangeLog +++ b/lib/e2p/ChangeLog @@ -1,3 +1,8 @@ +Sat Apr 5 11:48:03 1997 Theodore Ts'o + + * ls.c (list_super): Display the filesystem revision and any + features that might be implemented. + Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o * Release of E2fsprogs version 1.07 diff --git a/lib/e2p/Makefile.in b/lib/e2p/Makefile.in index f78c98de..b51fb889 100644 --- a/lib/e2p/Makefile.in +++ b/lib/e2p/Makefile.in @@ -34,13 +34,13 @@ LIBDIR= e2p DLL_ADDRESS = 0x66980000 DLL_JUMPSIZE = 0x1000 DLL_GOTSIZE = 0x1000 -DLL_VERSION = 1.2 +DLL_VERSION = 1.3 DLL_IMAGE = libe2p DLL_STUB = libe2p DLL_MYDIR = e2p DLL_INSTALL_DIR = $(libdir) -ELF_VERSION = 2.2 +ELF_VERSION = 2.3 ELF_SO_VERSION = 2 ELF_IMAGE = libe2p ELF_MYDIR = e2p diff --git a/lib/e2p/ls.c b/lib/e2p/ls.c index a1320472..2cbe3d54 100644 --- a/lib/e2p/ls.c +++ b/lib/e2p/ls.c @@ -76,6 +76,10 @@ struct ext2fs_sb { __u32 s_reserved[206]; /* Padding to the end of the block */ }; +#ifndef EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER +#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001 +#endif + static void print_user (unsigned short uid) { struct passwd *pw; @@ -164,8 +168,6 @@ void list_super (struct ext2_super_block * s) EXT2_INODE_SIZE(s)) + EXT2_BLOCK_SIZE(s) - 1) / EXT2_BLOCK_SIZE(s)); - printf ("Filesystem magic number: 0x%04X\n", s->s_magic); - printf ("Filesystem revision #: %d\n", s->s_rev_level); if (sb->s_volume_name[0]) { memset(buf, 0, sizeof(buf)); strncpy(buf, sb->s_volume_name, sizeof(sb->s_volume_name)); @@ -183,6 +185,22 @@ void list_super (struct ext2_super_block * s) } else strcpy(buf, ""); printf("Filesystem UUID: %s\n", buf); + printf ("Filesystem magic number: 0x%04X\n", s->s_magic); + printf ("Filesystem revision #: %d", s->s_rev_level); + if (s->s_rev_level == EXT2_GOOD_OLD_REV) { + printf(" (original)\n"); +#ifdef EXT2_DYNAMIC_REV + } else if (s->s_rev_level == EXT2_DYNAMIC_REV) { + printf(" (dynamic)\n"); +#endif + } else + printf("\n"); + printf ("Filesystem features: "); + if (s->s_feature_ro_compat & EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) + printf("sparse_super"); + else + printf("(none)"); + printf("\n"); printf ("Filesystem state: "); print_fs_state (stdout, s->s_state); printf ("\n"); diff --git a/lib/ext2fs/ChangeLog b/lib/ext2fs/ChangeLog index dd6da6a3..e191b7d9 100644 --- a/lib/ext2fs/ChangeLog +++ b/lib/ext2fs/ChangeLog @@ -1,3 +1,73 @@ +Thu Apr 10 13:15:15 1997 Theodore Ts'o + + * dblist.c (ext2fs_set_dir_block): New function which sets the + block of a dblist entry, given the directory inode and + blockcnt. + +Sat Apr 5 12:42:42 1997 Theodore Ts'o + + * alloc_tables.c (ext2fs_allocate_tables): Allocate the bitmap and + inode bitmaps at staggered locations across the block + groups, to avoid concentrating the bitmaps on a small + number of disks when using striped RAID arrays. + + * initialize.c (ext2fs_initialize): By default, choose the maximum + possible number of blocks per group (based on the size of + the bitmaps in the blocksize). + +Fri Apr 4 11:28:16 1997 Theodore Ts'o + + * initialize.c (ext2fs_initialize): Add support for + EXT2_COMPAT_SPARSE_SUPER feature. + + * closefs.c (ext2fs_bg_has_super): New function to determine + whether or a particular block group should have a + superblock and block group descriptor. Used for the + EXT2_COMPAT_SPARSE_SUPER feature is turned on. + (ext2fs_flush): Check ext2fs_bg_has_super to see whether + or not the superblock should be written out for the block + group. + + * ext2fs.h (EXT2_COMPAT_SPARSE_SUPER): Define compatibility flag + for sparse duplicate superblocks. + + * version.c (ext2fs_get_library_version): New function which + returns the library version. + + * version.c (ext2fs_parse_version_string): New function which + parses a version string and returns a version number, + so application programs can compare version numbers as + integers. + +Wed Mar 26 00:43:52 1997 Theodore Ts'o + + * icount.c (ext2fs_create_icount): Change function so that it also + takes a new argument which contains a "hint" icount + structure. This "hint" icount allows the create function + to set up the sorted list in advance. This reduces + significantly the amount of data moving needed to insert + these inodes into the list later. + + * icount.c (ext2fs_icount_validate): New function which validates + that the icount structure's rep invariant. + + * icount.c (get_icount_el): Completely revamped implementation + to subsume put_icount_el(). Put_icount_el() used to + use an O(N) implementation to insert in the middle + of the icount list. It now uses a O(ln N) to search + for where the icount should be inserted, and then uses + a memcpy to move the list down (instead of a for loop). + + * icount.c (ext2fs_icount_fetch, ext2fs_icount_store, + ext2fs_icount_increment, ext2fs_icount_decrement): Check + to see if the inode is within bounds; if it isn't, return + EINVAL. + + * bitops.h (ext2fs_test_generic_bitmap): Fix error message given + when a bad inode number is passed to test_generic_bitmap + to be EXT2FS_TEST_ERROR instead of the wrong + EXT2FS_UNMARK_ERROR. + Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o * Release of E2fsprogs version 1.07 diff --git a/lib/ext2fs/Makefile.in b/lib/ext2fs/Makefile.in index 2867dce8..cea8490e 100644 --- a/lib/ext2fs/Makefile.in +++ b/lib/ext2fs/Makefile.in @@ -50,7 +50,8 @@ OBJS= ext2_err.o \ test_io.o \ unix_io.o \ unlink.o \ - valid_blk.o + valid_blk.o \ + version.o SRCS= ext2_err.c \ $(srcdir)/alloc.c \ @@ -95,7 +96,8 @@ SRCS= ext2_err.c \ $(srcdir)/test_io.c \ $(srcdir)/unix_io.c \ $(srcdir)/unlink.c \ - $(srcdir)/valid_blk.c + $(srcdir)/valid_blk.c \ + $(srcdir)/version.c HFILES= bitops.h ext2fs.h io.h @@ -105,21 +107,21 @@ LIBDIR= ext2fs DLL_ADDRESS = 0x66900000 DLL_JUMPSIZE = 0x1000 DLL_GOTSIZE = 0x1000 -DLL_VERSION = 1.1 +DLL_VERSION = 1.2 DLL_IMAGE = libe2fs DLL_STUB = libext2fs DLL_LIBS = -L../.. -lcom_err DLL_MYDIR = ext2fs DLL_INSTALL_DIR = $(libdir) -ELF_VERSION = 2.2 +ELF_VERSION = 2.3 ELF_SO_VERSION = 2 ELF_IMAGE = libext2fs ELF_MYDIR = ext2fs ELF_INSTALL_DIR = $(libdir) ELF_OTHER_LIBS = -lc -L../.. -lcom_err -BSDLIB_VERSION = 2.0 +BSDLIB_VERSION = 2.1 BSDLIB_IMAGE = libext2fs BSDLIB_MYDIR = ext2fs BSDLIB_INSTALL_DIR = $(libdir) diff --git a/lib/ext2fs/alloc_tables.c b/lib/ext2fs/alloc_tables.c index 97bceefe..4bfc91d3 100644 --- a/lib/ext2fs/alloc_tables.c +++ b/lib/ext2fs/alloc_tables.c @@ -29,37 +29,17 @@ errcode_t ext2fs_allocate_tables(ext2_filsys fs) { errcode_t retval; - blk_t group_blk, last_blk, new_blk, blk; + blk_t group_blk, start_blk, last_blk, new_blk, blk; int i, j; group_blk = fs->super->s_first_data_block; for (i = 0; i < fs->group_desc_count; i++) { last_blk = group_blk + fs->super->s_blocks_per_group; - /* - * Allocate the block bitmap + * Allocate the inode table */ - retval = ext2fs_get_free_blocks(fs, group_blk, last_blk, - 1, fs->block_map, &new_blk); - if (retval) - return retval; - ext2fs_mark_block_bitmap(fs->block_map, new_blk); - fs->group_desc[i].bg_block_bitmap = new_blk; - - /* - * ... and the inode bitmap - */ - retval = ext2fs_get_free_blocks(fs, group_blk, last_blk, - 1, fs->block_map, &new_blk); - if (retval) - return retval; - ext2fs_mark_block_bitmap(fs->block_map, new_blk); - fs->group_desc[i].bg_inode_bitmap = new_blk; - - /* - * Finally, allocate the inode table - */ - retval = ext2fs_get_free_blocks(fs, group_blk, last_blk, + start_blk = group_blk + 3 + fs->desc_blocks; + retval = ext2fs_get_free_blocks(fs, start_blk, last_blk, fs->inode_blocks_per_group, fs->block_map, &new_blk); if (retval) @@ -70,6 +50,25 @@ errcode_t ext2fs_allocate_tables(ext2_filsys fs) ext2fs_mark_block_bitmap(fs->block_map, blk); fs->group_desc[i].bg_inode_table = new_blk; + /* + * Allocate the block and inode bitmaps + */ + start_blk += fs->inode_blocks_per_group + + ((2 * i) % (last_blk - start_blk)); + retval = ext2fs_get_free_blocks(fs, start_blk, last_blk, + 1, fs->block_map, &new_blk); + if (retval) + return retval; + ext2fs_mark_block_bitmap(fs->block_map, new_blk); + fs->group_desc[i].bg_block_bitmap = new_blk; + + retval = ext2fs_get_free_blocks(fs, start_blk, last_blk, + 1, fs->block_map, &new_blk); + if (retval) + return retval; + ext2fs_mark_block_bitmap(fs->block_map, new_blk); + fs->group_desc[i].bg_inode_bitmap = new_blk; + /* * Increment the start of the block group */ diff --git a/lib/ext2fs/bitops.h b/lib/ext2fs/bitops.h index 24bd5a74..a20d3955 100644 --- a/lib/ext2fs/bitops.h +++ b/lib/ext2fs/bitops.h @@ -353,7 +353,7 @@ _INLINE_ int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap, blk_t bitno) { if ((bitno < bitmap->start) || (bitno > bitmap->end)) { - ext2fs_warn_bitmap2(bitmap, EXT2FS_UNMARK_ERROR, bitno); + ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, bitno); return 0; } return ext2fs_test_bit(bitno - bitmap->start, bitmap->bitmap); diff --git a/lib/ext2fs/closefs.c b/lib/ext2fs/closefs.c index e24b6b69..a61f8783 100644 --- a/lib/ext2fs/closefs.c +++ b/lib/ext2fs/closefs.c @@ -22,6 +22,38 @@ #include "ext2fsP.h" +static int test_root(int a, int b) +{ + if (a == 0) + return 1; + while (1) { + if (a == 1) + return 1; + if (a % b) + return 0; + a = a / b; + } +} + +int ext2fs_bg_has_super(ext2_filsys fs, int group_block) +{ +#ifdef EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER + struct ext2fs_sb *s; + + s = (struct ext2fs_sb *) fs->super; + if (!(s->s_feature_ro_compat & EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) + return 1; + + if (test_root(group_block, 3) || (test_root(group_block, 5)) || + test_root(group_block, 7)) + return 1; + + return 0; +#else + return 1; +#endif +} + errcode_t ext2fs_flush(ext2_filsys fs) { int i,j,maxgroup; @@ -92,6 +124,9 @@ errcode_t ext2fs_flush(ext2_filsys fs) maxgroup = (fs->flags & EXT2_FLAG_MASTER_SB_ONLY) ? 1 : fs->group_desc_count; for (i = 0; i < maxgroup; i++) { + if (!ext2fs_bg_has_super(fs, i)) + goto next_group; + if (i !=0 ) { retval = io_channel_write_blk(fs->io, group_block, -SUPERBLOCK_SIZE, @@ -108,6 +143,7 @@ errcode_t ext2fs_flush(ext2_filsys fs) goto errout; group_ptr += fs->blocksize; } + next_group: group_block += EXT2_BLOCKS_PER_GROUP(fs->super); } diff --git a/lib/ext2fs/dblist.c b/lib/ext2fs/dblist.c index 72d58407..76c847ff 100644 --- a/lib/ext2fs/dblist.c +++ b/lib/ext2fs/dblist.c @@ -127,6 +127,28 @@ errcode_t ext2fs_add_dir_block(ext2_dblist dblist, ino_t ino, blk_t blk, return 0; } +/* + * Change the directory block to the directory block list + */ +errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ino_t ino, blk_t blk, + int blockcnt) +{ + struct ext2_db_entry *ent; + int i; + + EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST); + + for (i=0; i < dblist->count; i++) { + if ((dblist->list[i].ino != ino) || + (dblist->list[i].blockcnt != blockcnt)) + continue; + dblist->list[i].blk = blk; + dblist->sorted = 0; + return 0; + } + return ENOENT; +} + /* * This function iterates over the directory block list */ @@ -151,7 +173,6 @@ errcode_t ext2fs_dblist_iterate(ext2_dblist dblist, if (ret & DBLIST_ABORT) return 0; } - return 0; } diff --git a/lib/ext2fs/dll/jump.funcs b/lib/ext2fs/dll/jump.funcs index 825844ca..60843721 100644 --- a/lib/ext2fs/dll/jump.funcs +++ b/lib/ext2fs/dll/jump.funcs @@ -138,3 +138,7 @@ 00000000 T _ext2fs_icount_decrement libext2fs icount 00000000 T _ext2fs_icount_store libext2fs icount 00000000 T _ext2fs_get_icount_size libext2fs icount +00000000 T _ext2fs_create_icount2 libext2fs icount +00000000 T _ext2fs_get_library_version libext2fs version +00000000 T _ext2fs_parse_version_string libext2fs version +00000000 T _ext2fs_set_dir_block libext2fs dblist diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h index ce57e13b..4e14fd61 100644 --- a/lib/ext2fs/ext2fs.h +++ b/lib/ext2fs/ext2fs.h @@ -341,7 +341,19 @@ struct ext2fs_sb { char s_last_mounted[64]; /* directory where last mounted */ __u32 s_reserved[206]; /* Padding to the end of the block */ }; - + +/* + * Feature set definitions (that might not be in ext2_fs.h + * (was EXT2_COMPAT_SPARSE_SUPER) + */ +#ifndef EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER +#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001 +#endif + +#define EXT2_LIB_FEATURE_COMPAT_SUPP 0 +#define EXT2_LIB_FEATURE_INCOMPAT_SUPP 0 +#define EXT2_LIB_FEATURE_RO_COMPAT_SUPP EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER + /* * function prototypes */ @@ -442,6 +454,7 @@ extern errcode_t ext2fs_check_desc(ext2_filsys fs); /* closefs.c */ extern errcode_t ext2fs_close(ext2_filsys fs); extern errcode_t ext2fs_flush(ext2_filsys fs); +extern int ext2fs_bg_has_super(ext2_filsys fs, int group_block); /* cmp_bitmaps.c */ extern errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1, @@ -461,6 +474,8 @@ errcode_t ext2fs_dblist_iterate(ext2_dblist dblist, struct ext2_db_entry *db_info, void *private), void *private); +errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ino_t ino, blk_t blk, + int blockcnt); /* dblist_dir.c */ extern errcode_t @@ -544,6 +559,8 @@ 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_icount2(ext2_filsys fs, int flags, int size, + ext2_icount_t hint, ext2_icount_t *ret); extern errcode_t ext2fs_create_icount(ext2_filsys fs, int flags, int size, ext2_icount_t *ret); extern errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ino_t ino, @@ -555,6 +572,7 @@ extern errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ino_t ino, extern errcode_t ext2fs_icount_store(ext2_icount_t icount, ino_t ino, __u16 count); extern ino_t ext2fs_get_icount_size(ext2_icount_t icount); +errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *); /* ismounted.c */ extern errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags); @@ -621,7 +639,12 @@ 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); +extern int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode); + +/* version.c */ +extern int ext2fs_parse_version_string(const char *ver_string); +extern int ext2fs_get_library_version(const char **ver_string, + const char **date_string); /* inline functions */ extern void ext2fs_mark_super_dirty(ext2_filsys fs); diff --git a/lib/ext2fs/icount.c b/lib/ext2fs/icount.c index b9070a93..7c686804 100644 --- a/lib/ext2fs/icount.c +++ b/lib/ext2fs/icount.c @@ -71,13 +71,20 @@ void ext2fs_free_icount(ext2_icount_t icount) free(icount); } -errcode_t ext2fs_create_icount(ext2_filsys fs, int flags, int size, - ext2_icount_t *ret) +errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags, int size, + ext2_icount_t hint, ext2_icount_t *ret) { ext2_icount_t icount; errcode_t retval; size_t bytes; + int i; + if (hint) { + EXT2_CHECK_MAGIC(hint, EXT2_ET_MAGIC_ICOUNT); + if (hint->size > size) + size = hint->size; + } + icount = malloc(sizeof(struct ext2_icount)); if (!icount) return ENOMEM; @@ -125,8 +132,18 @@ errcode_t ext2fs_create_icount(ext2_filsys fs, int flags, int size, icount->cursor = 0; icount->num_inodes = fs->super->s_inodes_count; - *ret = icount; + /* + * Populate the sorted list with those entries which were + * found in the hint icount (since those are ones which will + * likely need to be in the sorted list this time around). + */ + if (hint) { + for (i=0; i < hint->count; i++) + icount->list[i].ino = hint->list[i].ino; + icount->count = hint->count; + } + *ret = icount; return 0; errout: @@ -134,65 +151,22 @@ errout: return(retval); } -/* - * get_icount_el() --- given an inode number, try to find icount - * information in the sorted list. We use a binary search... - */ -static struct ext2_icount_el *get_icount_el(ext2_icount_t icount, ino_t ino) +errcode_t ext2fs_create_icount(ext2_filsys fs, int flags, int size, + ext2_icount_t *ret) { - int low, high, mid; - - if (!icount || !icount->list || !icount->count) - return 0; - - if (icount->multiple && - !ext2fs_test_inode_bitmap(icount->multiple, ino)) - return 0; - - low = 0; - high = icount->count-1; - if (ino == icount->list[low].ino) { - icount->cursor = low+1; - return &icount->list[low]; - } - if (ino == icount->list[high].ino) { - icount->cursor = 0; - return &icount->list[high]; - } - if (icount->cursor >= icount->count) - icount->cursor = 0; - if (ino == icount->list[icount->cursor].ino) - return &icount->list[icount->cursor++]; -#if 0 - printf("Non-cursor get_icount_el: %u\n", ino); -#endif - - while (low < high) { - mid = (low+high)/2; - if (mid == low || mid == high) - break; - if (ino == icount->list[mid].ino) { - icount->cursor = mid; - return &icount->list[mid]; - } - if (ino < icount->list[mid].ino) - high = mid; - else - low = mid; - } - return 0; + return ext2fs_create_icount2(fs, flags, size, 0, ret); } /* - * put_icount_el() --- given an inode number, create a new entry in - * the sorted list. This function is optimized for adding values - * in ascending order. + * insert_icount_el() --- Insert a new entry into the sorted list at a + * specified position. */ -static struct ext2_icount_el *put_icount_el(ext2_icount_t icount, ino_t ino) +static struct ext2_icount_el *insert_icount_el(ext2_icount_t icount, + ino_t ino, int pos) { struct ext2_icount_el *el, *new_list; ino_t new_size = 0; - int i, j; + int num; if (icount->count >= icount->size) { if (icount->count) { @@ -212,31 +186,112 @@ static struct ext2_icount_el *put_icount_el(ext2_icount_t icount, ino_t ino) icount->size = new_size; icount->list = new_list; } - - /* - * Normally, get_icount_el is called with each inode in - * sequential order; but once in a while (like when pass 3 - * needs to recreate the root directory or lost+found - * directory) it is called out of order. - */ - if (icount->count && icount->list[icount->count-1].ino >= ino) { - for (i = icount->count-1; i > 0; i--) - if (icount->list[i-1].ino < ino) - break; - el = &icount->list[i]; - if (el->ino != ino) { - for (j = icount->count++; j > i; j--) - icount->list[j] = icount->list[j-1]; - el->count = 0; - } - } else { - el = &icount->list[icount->count++]; - el->count = 0; + num = icount->count - pos; + if (num < 0) + return 0; /* should never happen */ + if (num) { + memmove(&icount->list[pos+1], &icount->list[pos], + sizeof(struct ext2_icount_el) * num); } + icount->count++; + el = &icount->list[pos]; + el->count = 0; el->ino = ino; return el; } + +/* + * get_icount_el() --- given an inode number, try to find icount + * information in the sorted list. If the create flag is set, + * and we can't find an entry, create one in the sorted list. + */ +static struct ext2_icount_el *get_icount_el(ext2_icount_t icount, + ino_t ino, int create) +{ + float range; + int low, high, mid; + ino_t lowval, highval; + + if (!icount || !icount->list) + return 0; + + if (create && ((icount->count == 0) || + (ino > icount->list[icount->count-1].ino))) { + return insert_icount_el(icount, ino, icount->count); + } + if (icount->count == 0) + return 0; + if (icount->cursor >= icount->count) + icount->cursor = 0; + if (ino == icount->list[icount->cursor].ino) + return &icount->list[icount->cursor++]; +#if 0 + printf("Non-cursor get_icount_el: %u\n", ino); +#endif + low = 0; + high = icount->count-1; + while (low <= high) { +#if 0 + mid = (low+high)/2; +#else + if (low == high) + mid = low; + else { + /* Interpolate for efficiency */ + lowval = icount->list[low].ino; + highval = icount->list[high].ino; + + if (ino < lowval) + range = 0; + else if (ino > highval) + range = 1; + else + range = ((float) (ino - lowval)) / + (highval - lowval); + mid = low + ((int) (range * (high-low))); + } +#endif + if (ino == icount->list[mid].ino) { + icount->cursor = mid+1; + return &icount->list[mid]; + } + if (ino < icount->list[mid].ino) + high = mid-1; + else + low = mid+1; + } + /* + * If we need to create a new entry, it should be right at + * low (where high will be left at low-1). + */ + if (create) + return insert_icount_el(icount, ino, low); + return 0; +} + +errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *out) +{ + errcode_t ret = 0; + int i; + const char *bad = "bad icount"; + + EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); + + if (icount->count > icount->size) { + fprintf(out, "%s: count > size\n", bad); + return EINVAL; + } + for (i=1; i < icount->count; i++) { + if (icount->list[i-1].ino >= icount->list[i].ino) { + fprintf(out, "%s: list[%d].ino=%u, list[%d].ino=%u\n", + bad, i-1, icount->list[i-1].ino, + i, icount->list[i].ino); + ret = EINVAL; + } + } + return ret; +} errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ino_t ino, __u16 *ret) { @@ -244,11 +299,19 @@ errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ino_t ino, __u16 *ret) EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); + if (!ino || (ino > icount->num_inodes)) + return EINVAL; + if (ext2fs_test_inode_bitmap(icount->single, ino)) { *ret = 1; return 0; } - el = get_icount_el(icount, ino); + if (icount->multiple && + !ext2fs_test_inode_bitmap(icount->multiple, ino)) { + *ret = 0; + return 0; + } + el = get_icount_el(icount, ino, 0); if (!el) { *ret = 0; return 0; @@ -264,14 +327,19 @@ errcode_t ext2fs_icount_increment(ext2_icount_t icount, ino_t ino, EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); + if (!ino || (ino > icount->num_inodes)) + return EINVAL; + if (ext2fs_test_inode_bitmap(icount->single, ino)) { /* * If the existing count is 1, then we know there is - * no entry in the list, so use put_icount_el(). + * no entry in the list. */ - el = put_icount_el(icount, ino); + el = get_icount_el(icount, ino, 1); if (!el) return ENOMEM; + ext2fs_unmark_inode_bitmap(icount->single, ino); + el->count = 2; } else if (icount->multiple) { /* * The count is either zero or greater than 1; if the @@ -280,13 +348,10 @@ errcode_t ext2fs_icount_increment(ext2_icount_t icount, ino_t ino, * get_icount_el(). */ if (ext2fs_test_inode_bitmap(icount->multiple, ino)) { - el = get_icount_el(icount, ino); - if (!el) { - /* should never happen */ - el = put_icount_el(icount, ino); - if (!el) - return ENOMEM; - } + el = get_icount_el(icount, ino, 1); + if (!el) + return ENOMEM; + el->count++; } else { /* * The count was zero; mark the single bitmap @@ -303,20 +368,16 @@ errcode_t ext2fs_icount_increment(ext2_icount_t icount, ino_t ino, * The count is either zero or greater than 1; try to * find an entry in the list to determine which. */ - el = get_icount_el(icount, ino); + el = get_icount_el(icount, ino, 0); if (!el) { /* No entry means the count was zero */ goto zero_count; } - el = put_icount_el(icount, ino); + el = get_icount_el(icount, ino, 1); if (!el) return ENOMEM; - } - if (ext2fs_test_inode_bitmap(icount->single, ino)) { - ext2fs_unmark_inode_bitmap(icount->single, ino); - el->count = 2; - } else el->count++; + } if (icount->multiple) ext2fs_mark_inode_bitmap(icount->multiple, ino); if (ret) @@ -329,6 +390,9 @@ errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ino_t ino, { struct ext2_icount_el *el; + if (!ino || (ino > icount->num_inodes)) + return EINVAL; + EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); if (ext2fs_test_inode_bitmap(icount->single, ino)) { @@ -336,7 +400,7 @@ errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ino_t ino, if (icount->multiple) ext2fs_unmark_inode_bitmap(icount->multiple, ino); else { - el = get_icount_el(icount, ino); + el = get_icount_el(icount, ino, 0); if (el) el->count = 0; } @@ -345,8 +409,12 @@ errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ino_t ino, return 0; } - el = get_icount_el(icount, ino); - if (!el) + if (icount->multiple && + !ext2fs_test_inode_bitmap(icount->multiple, ino)) + return EINVAL; + + el = get_icount_el(icount, ino, 0); + if (!el || el->count == 0) return EINVAL; el->count--; @@ -365,6 +433,9 @@ errcode_t ext2fs_icount_store(ext2_icount_t icount, ino_t ino, { struct ext2_icount_el *el; + if (!ino || (ino > icount->num_inodes)) + return EINVAL; + EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); if (count == 1) { @@ -382,7 +453,7 @@ errcode_t ext2fs_icount_store(ext2_icount_t icount, ino_t ino, */ ext2fs_unmark_inode_bitmap(icount->multiple, ino); } else { - el = get_icount_el(icount, ino); + el = get_icount_el(icount, ino, 0); if (el) el->count = 0; } @@ -392,7 +463,7 @@ errcode_t ext2fs_icount_store(ext2_icount_t icount, ino_t ino, /* * Get the icount element */ - el = put_icount_el(icount, ino); + el = get_icount_el(icount, ino, 1); if (!el) return ENOMEM; el->count = count; diff --git a/lib/ext2fs/initialize.c b/lib/ext2fs/initialize.c index 6db5a0cd..72f40eaa 100644 --- a/lib/ext2fs/initialize.c +++ b/lib/ext2fs/initialize.c @@ -58,6 +58,7 @@ errcode_t ext2fs_initialize(const char *name, int flags, ext2_filsys fs; errcode_t retval; struct ext2_super_block *super; + struct ext2fs_sb *s; int frags_per_block; int rem; int overhead = 0; @@ -91,9 +92,12 @@ errcode_t ext2fs_initialize(const char *name, int flags, goto cleanup; } memset(super, 0, SUPERBLOCK_SIZE); + s = (struct ext2fs_sb *) super; #define set_field(field, default) (super->field = param->field ? \ param->field : (default)) +#define set_ext2_field(field, default) (s->field = param->field ? \ + param->field : (default)) super->s_magic = EXT2_SUPER_MAGIC; super->s_state = EXT2_VALID_FS; @@ -103,7 +107,13 @@ errcode_t ext2fs_initialize(const char *name, int flags, set_field(s_first_data_block, super->s_log_block_size ? 0 : 1); set_field(s_max_mnt_count, EXT2_DFL_MAX_MNT_COUNT); set_field(s_errors, EXT2_ERRORS_DEFAULT); - + set_ext2_field(s_feature_compat, 0); + set_ext2_field(s_feature_incompat, 0); + set_ext2_field(s_feature_ro_compat, 0); + if (s->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP) + return EXT2_ET_UNSUPP_FEATURE; + if (s->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) + return EXT2_ET_RO_UNSUPP_FEATURE; #ifdef EXT2_DYNAMIC_REV set_field(s_rev_level, EXT2_GOOD_OLD_REV); @@ -122,7 +132,8 @@ errcode_t ext2fs_initialize(const char *name, int flags, fs->fragsize = EXT2_FRAG_SIZE(super); frags_per_block = fs->blocksize / fs->fragsize; - set_field(s_blocks_per_group, 8192); /* default: 8192 blocks/group */ + /* default: (fs->blocksize*8) blocks/group */ + set_field(s_blocks_per_group, fs->blocksize*8); super->s_frags_per_group = super->s_blocks_per_group * frags_per_block; super->s_blocks_count = param->s_blocks_count; @@ -187,16 +198,6 @@ retry: fs->group_desc_count; super->s_free_inodes_count = super->s_inodes_count; - /* - * Overhead is the number of bookkeeping blocks per group. It - * includes the superblock backup, the group descriptor - * backups, the inode bitmap, the block bitmap, and the inode - * table. - */ - overhead = 3 + fs->desc_blocks + fs->inode_blocks_per_group; - super->s_free_blocks_count = super->s_blocks_count - - super->s_first_data_block - (overhead*fs->group_desc_count); - /* * See if the last group is big enough to support the * necessary data structures. If not, we need to get rid of @@ -250,11 +251,8 @@ retry: * by this routine), they are accounted for nevertheless. */ group_block = super->s_first_data_block; + super->s_free_blocks_count = 0; for (i = 0; i < fs->group_desc_count; i++) { - for (j=0; j < fs->desc_blocks+1; j++) - ext2fs_mark_block_bitmap(fs->block_map, - group_block + j); - if (i == fs->group_desc_count-1) { numblocks = (fs->super->s_blocks_count - fs->super->s_first_data_block) % @@ -263,8 +261,17 @@ retry: numblocks = fs->super->s_blocks_per_group; } else numblocks = fs->super->s_blocks_per_group; - numblocks -= 3 + fs->desc_blocks + fs->inode_blocks_per_group; + + if (ext2fs_bg_has_super(fs, i)) { + for (j=0; j < fs->desc_blocks+1; j++) + ext2fs_mark_block_bitmap(fs->block_map, + group_block + j); + numblocks -= 1 + fs->desc_blocks; + } + numblocks -= 2 + fs->inode_blocks_per_group; + + super->s_free_blocks_count += numblocks; fs->group_desc[i].bg_free_blocks_count = numblocks; fs->group_desc[i].bg_free_inodes_count = fs->super->s_inodes_per_group; diff --git a/lib/ext2fs/inode.c b/lib/ext2fs/inode.c index 8fd5e7e4..7194fb0c 100644 --- a/lib/ext2fs/inode.c +++ b/lib/ext2fs/inode.c @@ -51,6 +51,7 @@ errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks, { ext2_inode_scan scan; errcode_t retval; + errcode_t (*save_get_blocks)(ext2_filsys fs, ino_t ino, blk_t *blocks); EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); @@ -59,11 +60,18 @@ errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks, * scanning functions require it. */ if (fs->badblocks == 0) { + /* + * Temporarly save fs->get_blocks and set it to zero, + * for compatibility with old e2fsck's. + */ + save_get_blocks = fs->get_blocks; + fs->get_blocks = 0; retval = ext2fs_read_bb_inode(fs, &fs->badblocks); if (retval && fs->badblocks) { badblocks_list_free(fs->badblocks); fs->badblocks = 0; } + fs->get_blocks = save_get_blocks; } scan = (ext2_inode_scan) malloc(sizeof(struct ext2_struct_inode_scan)); diff --git a/lib/ext2fs/openfs.c b/lib/ext2fs/openfs.c index b2e2393a..a1c0d5bc 100644 --- a/lib/ext2fs/openfs.c +++ b/lib/ext2fs/openfs.c @@ -126,12 +126,13 @@ errcode_t ext2fs_open(const char *name, int flags, int superblock, */ if (!(flags & EXT2_FLAG_FORCE)) { s = (struct ext2fs_sb *) fs->super; - if (s->s_feature_incompat) { + if (s->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP) { retval = EXT2_ET_UNSUPP_FEATURE; goto cleanup; } if ((flags & EXT2_FLAG_RW) && - s->s_feature_ro_compat) { + (s->s_feature_ro_compat & + ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP)) { retval = EXT2_ET_RO_UNSUPP_FEATURE; goto cleanup; } diff --git a/lib/ext2fs/version.c b/lib/ext2fs/version.c new file mode 100644 index 00000000..df7236e1 --- /dev/null +++ b/lib/ext2fs/version.c @@ -0,0 +1,53 @@ +/* + * version.c --- Return the version of the ext2 library + * + * Copyright (C) 1997 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#include +#include +#include +#include +#ifdef HAVE_ERRNO_H +#include +#endif + +#include +#include "ext2fs.h" + +#include "../../version.h" + +static const char *lib_version = E2FSPROGS_VERSION; +static const char *lib_date = E2FSPROGS_DATE; + +int ext2fs_parse_version_string(const char *ver_string) +{ + const char *cp; + int version = 0; + + for (cp = lib_version; *cp; cp++) { + if (!isdigit(*cp)) + continue; + version = (version * 10) + (*cp - '0'); + } + return version; +} + + +int ext2fs_get_library_version(const char **ver_string, + const char **date_string) +{ + if (ver_string) + *ver_string = lib_version; + if (date_string) + *date_string = lib_date; + + return ext2fs_parse_version_string(lib_version); +} diff --git a/lib/ss/test_ss.c b/lib/ss/test_ss.c index 64f0e2a1..f58e73fe 100644 --- a/lib/ss/test_ss.c +++ b/lib/ss/test_ss.c @@ -9,8 +9,8 @@ * $Locker$ * * $Log$ - * Revision 1.10 1997/04/29 16:15:48 tytso - * Checked in e2fsprogs-1.07 + * Revision 1.11 1997/04/29 17:47:28 tytso + * Checked in e2fsprogs 1.08. * * Revision 1.1 1993/06/03 12:31:25 tytso * Initial revision diff --git a/misc/ChangeLog b/misc/ChangeLog index 8886779d..b761fb47 100644 --- a/misc/ChangeLog +++ b/misc/ChangeLog @@ -1,3 +1,21 @@ +Thu Apr 10 07:08:03 1997 Theodore Ts'o + + * dumpe2fs.c (list_desc): List the offsets of the inode and block + bitmaps, and the inode table. List the block boundaries + for the groups. + +Sat Apr 5 11:55:52 1997 Theodore Ts'o + + * tune2fs.c (main): Implement the -s flag allows the user to + set and reset the sparse superblock flag. + + * mke2fs.c (PRS): By default generate DYNAMIC revision + filesystems. The -s flag controls whether or not the + sparse superblock flag is set. + (PRS): Change to allow the user to specify the true + maximum number of blocks per group to reflect the + blocksize. + Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o * Release of E2fsprogs version 1.07 diff --git a/misc/dumpe2fs.c b/misc/dumpe2fs.c index 448e4eb1..b71900e7 100644 --- a/misc/dumpe2fs.c +++ b/misc/dumpe2fs.c @@ -77,18 +77,27 @@ static void print_free (unsigned long group, char * bitmap, static void list_desc (ext2_filsys fs) { unsigned long i; + blk_t group_blk, next_blk; char * block_bitmap = fs->block_map->bitmap; char * inode_bitmap = fs->inode_map->bitmap; printf ("\n"); - for (i = 0; i < fs->group_desc_count; i++) - { - printf ("Group %lu:\n", i); - printf (" Block bitmap at %u, Inode bitmap at %u, " - "Inode table at %u\n", + group_blk = fs->super->s_first_data_block; + for (i = 0; i < fs->group_desc_count; i++) { + next_blk = group_blk + fs->super->s_blocks_per_group; + if (next_blk > fs->super->s_blocks_count) + next_blk = fs->super->s_blocks_count; + printf ("Group %lu: (Blocks %u -- %u)\n", i, + group_blk, next_blk -1 ); + printf (" Block bitmap at %u (+%d), " + "Inode bitmap at %u (+%d)\n " + "Inode table at %u (+%d)\n", fs->group_desc[i].bg_block_bitmap, + fs->group_desc[i].bg_block_bitmap - group_blk, fs->group_desc[i].bg_inode_bitmap, - fs->group_desc[i].bg_inode_table); + fs->group_desc[i].bg_inode_bitmap - group_blk, + fs->group_desc[i].bg_inode_table, + fs->group_desc[i].bg_inode_table - group_blk); printf (" %d free blocks, %d free inodes, %d directories\n", fs->group_desc[i].bg_free_blocks_count, fs->group_desc[i].bg_free_inodes_count, @@ -102,6 +111,7 @@ static void list_desc (ext2_filsys fs) print_free (i, inode_bitmap, fs->super->s_inodes_per_group, 1); inode_bitmap += fs->super->s_inodes_per_group / 8; printf ("\n"); + group_blk = next_blk; } } diff --git a/misc/mke2fs.8.in b/misc/mke2fs.8.in index 55265516..ab139a4c 100644 --- a/misc/mke2fs.8.in +++ b/misc/mke2fs.8.in @@ -40,6 +40,9 @@ mke2fs \- create a Linux second extended file system .B \-q ] [ +.B -s sparse-super-flag +] +[ .B \-v ] [ @@ -114,6 +117,11 @@ of the mke2fs executable. .I -q Quiet execution. Useful if mke2fs is run in a script. .TP +.I -s sparse-super-flag +If sparse-super-flag is 1, then turn on the sparse superblock flag. +If 0, then turn off the sparse superblock flag. (Currently, the sparse +superblock flag defaults to off.) +.TP .I -v Verbose execution. .TP diff --git a/misc/mke2fs.c b/misc/mke2fs.c index 3723af5d..475397d9 100644 --- a/misc/mke2fs.c +++ b/misc/mke2fs.c @@ -486,6 +486,8 @@ static void show_stats(ext2_filsys fs) col_left = 0; for (i = 1; i < fs->group_desc_count; i++) { group_block += s->s_blocks_per_group; + if (!ext2fs_bg_has_super(fs, i)) + continue; if (!col_left--) { printf("\n\t"); col_left = 8; @@ -539,11 +541,14 @@ static void PRS(int argc, char *argv[]) char c; int size; char * tmp; + blk_t max = 8192; int inode_ratio = 4096; int reserved_ratio = 5; errcode_t retval; + int sparse_option = -1; char *oldpath = getenv("PATH"); - + struct ext2fs_sb *param_ext2 = (struct ext2fs_sb *) ¶m; + /* Update our PATH to include /sbin */ if (oldpath) { char *newpath; @@ -560,6 +565,9 @@ static void PRS(int argc, char *argv[]) setbuf(stderr, NULL); initialize_ext2_error_table(); memset(¶m, 0, sizeof(struct ext2_super_block)); +#ifdef EXT2_DYNAMIC_REV + param.s_rev_level = EXT2_DYNAMIC_REV; +#endif fprintf (stderr, "mke2fs %s, %s for EXT2 FS %s, %s\n", E2FSPROGS_VERSION, E2FSPROGS_DATE, @@ -567,7 +575,7 @@ static void PRS(int argc, char *argv[]) if (argc && *argv) program_name = *argv; while ((c = getopt (argc, argv, - "b:cf:g:i:l:m:o:qr:tvI:SFL:M:")) != EOF) + "b:cf:g:i:l:m:o:qr:s:tvI:SFL:M:")) != EOF) switch (c) { case 'b': size = strtoul(optarg, &tmp, 0); @@ -578,6 +586,7 @@ static void PRS(int argc, char *argv[]) } param.s_log_block_size = log2(size >> EXT2_MIN_BLOCK_LOG_SIZE); + max = size * 8; break; case 'c': case 't': /* Check for bad blocks */ @@ -602,12 +611,6 @@ static void PRS(int argc, char *argv[]) "Illegal number for blocks per group"); exit(1); } - if (param.s_blocks_per_group < 256 || - param.s_blocks_per_group > 8192 || *tmp) { - com_err(program_name, 0, - "blocks per group count out of range"); - exit(1); - } if ((param.s_blocks_per_group % 8) != 0) { com_err(program_name, 0, "blocks per group must be multiple of 8"); @@ -647,6 +650,9 @@ static void PRS(int argc, char *argv[]) case 'r': param.s_rev_level = atoi(optarg); break; + case 's': + sparse_option = atoi(optarg); + break; #ifdef EXT2_DYNAMIC_REV case 'I': param.s_inode_size = atoi(optarg); @@ -705,6 +711,15 @@ static void PRS(int argc, char *argv[]) } } + if (param.s_blocks_per_group) { + if (param.s_blocks_per_group < 256 || + param.s_blocks_per_group > max || *tmp) { + com_err(program_name, 0, + "blocks per group count out of range"); + exit(1); + } + } + /* * Calculate number of inodes based on the inode ratio */ @@ -716,6 +731,20 @@ static void PRS(int argc, char *argv[]) * Calculate number of blocks to reserve */ param.s_r_blocks_count = (param.s_blocks_count * reserved_ratio) / 100; + + /* + * If we are using revision #1, use the sparse super feature + * by default + */ +#ifdef EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER + if ((sparse_option == 1) +#ifdef EXT2_DYNAMIC_REV + || (param.s_rev_level >= EXT2_DYNAMIC_REV) && (!sparse_option) +#endif + ) + param_ext2->s_feature_ro_compat |= + EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER; +#endif } int main (int argc, char *argv[]) diff --git a/misc/tune2fs.8.in b/misc/tune2fs.8.in index 9b927112..0e34085e 100644 --- a/misc/tune2fs.8.in +++ b/misc/tune2fs.8.in @@ -31,6 +31,9 @@ tune2fs \- adjust tunable filesystem parameters on second extended filesystems .I reserved-blocks-count ] [ +.B -s sparse-super-flag +] +[ .B -u .I user ] @@ -97,6 +100,10 @@ adjust the reserved blocks percentage on the given device. .I -r reserved-blocks-count adjust the reserved blocks count on the given device. .TP +.I -s sparse_super_flag +sets and resets the sparse_superblock flag. The sparse_superblock feature +saves space on really big filesystems. +.TP .I -u user set the user who can benefit from the reserved blocks. .I user diff --git a/misc/tune2fs.c b/misc/tune2fs.c index db3539e0..2cd43a63 100644 --- a/misc/tune2fs.c +++ b/misc/tune2fs.c @@ -63,6 +63,7 @@ int L_flag = 0; int m_flag = 0; int M_flag = 0; int r_flag = 0; +int s_flag = -1; int u_flag = 0; int U_flag = 0; int max_mount_count, mount_count; @@ -93,7 +94,7 @@ static volatile void usage (void) { fprintf (stderr, "Usage: %s [-c max-mounts-count] [-e errors-behavior] " "[-g group]\n" - "\t[-i interval[d|m|w]] [-l] [-m reserved-blocks-percent]\n" + "\t[-i interval[d|m|w]] [-l] [-s] [-m reserved-blocks-percent]\n" "\t[-r reserved-blocks-count] [-u user] [-C mount-count]\n" "\t[-L volume-label] [-M last-mounted-dir] [-U UUID] " "device\n", program_name); @@ -117,7 +118,7 @@ void main (int argc, char ** argv) if (argc && *argv) program_name = *argv; initialize_ext2_error_table(); - while ((c = getopt (argc, argv, "c:e:g:i:lm:r:u:C:L:M:U:")) != EOF) + while ((c = getopt (argc, argv, "c:e:g:i:lm:r:s:u:C:L:M:U:")) != EOF) switch (c) { case 'c': @@ -253,6 +254,10 @@ void main (int argc, char ** argv) r_flag = 1; open_flag = EXT2_FLAG_RW; break; + case 's': + s_flag = atoi(optarg); + open_flag = EXT2_FLAG_RW; + break; case 'u': resuid = strtoul (optarg, &tmp, 0); if (*tmp) @@ -355,6 +360,48 @@ void main (int argc, char ** argv) printf ("Setting reserved blocks count to %lu\n", reserved_blocks); } + if (s_flag == 1) { +#ifdef EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER + if (sb->s_feature_ro_compat & + EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) + fprintf(stderr, "\nThe filesystem already " + " has spare superblocks.\n"); + else { + sb->s_feature_ro_compat |= + EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER; + fs->super->s_state &= ~EXT2_VALID_FS; + ext2fs_mark_super_dirty(fs); + printf("\nSparse superblock flag set. " + "Please run e2fsck on the filesystem.\n"); + } +#else /* !EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER */ + com_err (program_name, 0, + "The -s option is not supported by this version -- " + "Recompile with a newer kernel"); +#endif /* EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER */ + } + if (s_flag == 0) { +#ifdef EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER + if (!(sb->s_feature_ro_compat & + EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) + fprintf(stderr, "\nThe filesystem already " + " does not support spare superblocks.\n"); + else { + sb->s_feature_ro_compat &= + ~EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER; + fs->super->s_state &= ~EXT2_VALID_FS; + fs->flags |= EXT2_FLAG_MASTER_SB_ONLY; + ext2fs_mark_super_dirty(fs); + printf("\nSparse superblock flag cleared. " + "Please run e2fsck on the filesystem.\n"); + } +#else /* !EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER */ + com_err (program_name, 0, + "The -s option is not supported by this version -- " + "Recompile with a newer kernel"); +#endif /* EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER */ + } + if (u_flag) #ifdef EXT2_DEF_RESUID { diff --git a/tests/ChangeLog b/tests/ChangeLog index 8850628a..4ebb21e4 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,16 @@ +Wed Mar 26 09:29:25 1997 Theodore Ts'o + + * e_icount_normal, e_icount_opt: New tests which validate the + icount abstraction. + + * test_script.in: New feature; an argument of a single character + means do all the tests in that series. + +Tue Mar 18 15:11:04 1997 Theodore Ts'o + + * test_config (LANG): Set the language to be C so that the brel + and irel tests don't fail. + Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o * Release of E2fsprogs version 1.07 diff --git a/tests/defaults/r_script b/tests/defaults/e_script similarity index 52% rename from tests/defaults/r_script rename to tests/defaults/e_script index 43e1cc2f..d1f460be 100644 --- a/tests/defaults/r_script +++ b/tests/defaults/e_script @@ -8,18 +8,28 @@ if [ -f $test_dir/setup ]; then fi if [ "$class"x = x ]; then - class=`echo $test_name | sed -e 's/r_\([^_]*\)_\(.*\)/\1/'` - instance=`echo $test_name | sed -e 's/r_\([^_]*\)_\(.*\)/\2/'` + class=`echo $test_name | sed -e 's/e_\([^_]*\)_\(.*\)/\1/'` + instance=`echo $test_name | sed -e 's/e_\([^_]*\)_\(.*\)/\2/'` fi if [ "$OUT"x = x ]; then OUT=$test_name.log fi if [ "$EXPECT"x = x ]; then - EXPECT=$SRCDIR/progs/rel_test/expect.$class + EXPECT=$SRCDIR/progs/test_data/expect.$class fi -cat $SRCDIR/progs/rel_test/$instance.setup $SRCDIR/progs/rel_test/test.$class \ - | $TEST_REL -f - > $OUT 2>&1 +if [ "$class" = irel ]; then + TEST_PROG=$TEST_REL +elif [ "$class" = brel ]; then + TEST_PROG=$TEST_REL +elif [ "$class" = icount ]; then + TEST_PROG=$TEST_ICOUNT +else + TEST_PROG=/bin/cat +fi + +cat $SRCDIR/progs/test_data/$instance.setup $SRCDIR/progs/test_data/test.$class \ + | $TEST_PROG -f - > $OUT 2>&1 cmp -s $EXPECT $OUT status=$? diff --git a/tests/r_brel_bma/name b/tests/e_brel_bma/name similarity index 100% rename from tests/r_brel_bma/name rename to tests/e_brel_bma/name diff --git a/tests/e_icount_normal/name b/tests/e_icount_normal/name new file mode 100644 index 00000000..eafa8020 --- /dev/null +++ b/tests/e_icount_normal/name @@ -0,0 +1 @@ +inode counting abstraction optimized for storing inode counts diff --git a/tests/e_icount_opt/name b/tests/e_icount_opt/name new file mode 100644 index 00000000..5b6b1a56 --- /dev/null +++ b/tests/e_icount_opt/name @@ -0,0 +1 @@ +inode counting abstraction optimized for counting diff --git a/tests/r_irel_ima/name b/tests/e_irel_ima/name similarity index 100% rename from tests/r_irel_ima/name rename to tests/e_irel_ima/name diff --git a/tests/f_dupfsblks/expect.1 b/tests/f_dupfsblks/expect.1 index 60aaaacc..1adda3b3 100644 --- a/tests/f_dupfsblks/expect.1 +++ b/tests/f_dupfsblks/expect.1 @@ -1,21 +1,28 @@ Filesystem did not have a UUID; generating one. Pass 1: Checking inodes, blocks, and sizes -Inode 12 has illegal block(s). Clear? yes +Duplicate blocks found... invoking duplicate block passes. +Pass 1B: Rescan for duplicate/bad blocks +Duplicate/bad block(s) in inode 12: 3 4 6 +Pass 1C: Scan directories for inodes with dup blocks. +Pass 1D: Reconciling duplicate blocks +(There are 1 inodes containing duplicate/bad blocks.) -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 +File /foo (inode #12, mod time Thu Apr 28 17:57:53 1994) + has 3 duplicate block(s), shared with 1 file(s): + +Clone duplicate/bad blocks? yes -Inode 12, i_blocks is 8, should be 2. Fix? yes Pass 2: Checking directory structure -Directory inode 12 has an unallocated block #1. Allocate? yes +Directory inode 12, block 1, offset 0: directory corrupted +Salvage? yes -Directory inode 12 has an unallocated block #2. Allocate? yes +Directory inode 12, block 2, offset 0: directory corrupted +Salvage? yes -Directory inode 12 has an unallocated block #3. Allocate? yes +Directory inode 12, block 3, offset 0: directory corrupted +Salvage? 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 5cb54685..61603bff 100644 --- a/tests/f_dupsuper/expect.1 +++ b/tests/f_dupsuper/expect.1 @@ -1,12 +1,18 @@ Filesystem did not have a UUID; generating one. Pass 1: Checking inodes, blocks, and sizes -Inode 12 has illegal block(s). Clear? yes +Duplicate blocks found... invoking duplicate block passes. +Pass 1B: Rescan for duplicate/bad blocks +Duplicate/bad block(s) in inode 12: 2 3 1 +Pass 1C: Scan directories for inodes with dup blocks. +Pass 1D: Reconciling duplicate blocks +(There are 1 inodes containing duplicate/bad blocks.) + +File /termcap (inode #12, mod time Sun Jan 2 08:29:13 1994) + has 3 duplicate block(s), shared with 1 file(s): + +Clone duplicate/bad blocks? 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 @@ -15,9 +21,7 @@ Pass 5: Checking group summary information Fix summary information? yes Block bitmap differences: -29 -30 -31. FIXED -Free blocks count wrong for group 0 (61, counted=64). FIXED -Free blocks count wrong (61, counted=64). FIXED test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** -test_filesys: 12/32 files (8.3% non-contiguous), 36/100 blocks +test_filesys: 12/32 files (8.3% non-contiguous), 39/100 blocks Exit status is 1 diff --git a/tests/f_dupsuper/expect.2 b/tests/f_dupsuper/expect.2 index f5cf22b2..8735c4e3 100644 --- a/tests/f_dupsuper/expect.2 +++ b/tests/f_dupsuper/expect.2 @@ -3,5 +3,5 @@ Pass 2: Checking directory structure Pass 3: Checking directory connectivity Pass 4: Checking reference counts Pass 5: Checking group summary information -test_filesys: 12/32 files (8.3% non-contiguous), 36/100 blocks +test_filesys: 12/32 files (8.3% non-contiguous), 39/100 blocks Exit status is 0 diff --git a/tests/f_illbbitmap/expect.1 b/tests/f_illbbitmap/expect.1 index 29fa4962..d22dbf2a 100644 --- a/tests/f_illbbitmap/expect.1 +++ b/tests/f_illbbitmap/expect.1 @@ -1,9 +1,9 @@ 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. +with 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. Block bitmap for group 0 is not in group. (block 4096) Relocate? yes diff --git a/tests/f_illibitmap/expect.1 b/tests/f_illibitmap/expect.1 index a296ed8b..4e4d996c 100644 --- a/tests/f_illibitmap/expect.1 +++ b/tests/f_illibitmap/expect.1 @@ -1,9 +1,9 @@ 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. +with 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 bitmap for group 0 is not in group. (block 4000) Relocate? yes diff --git a/tests/f_illitable/expect.1 b/tests/f_illitable/expect.1 index 6c6b7f59..e0af316e 100644 --- a/tests/f_illitable/expect.1 +++ b/tests/f_illitable/expect.1 @@ -1,9 +1,9 @@ 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. +with 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. diff --git a/tests/f_preen/expect.1 b/tests/f_preen/expect.1 index 297bb612..824b0ecb 100644 --- a/tests/f_preen/expect.1 +++ b/tests/f_preen/expect.1 @@ -1,8 +1,8 @@ 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. +with 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. test_filesys: Block bitmap for group 0 is not in group. (block 0) diff --git a/tests/progs/ChangeLog b/tests/progs/ChangeLog new file mode 100644 index 00000000..625919e6 --- /dev/null +++ b/tests/progs/ChangeLog @@ -0,0 +1,4 @@ +Wed Mar 26 15:38:52 1997 Theodore Ts'o + + * test_icount.c: New file which tests the icount abstraction. + diff --git a/tests/progs/Makefile.in b/tests/progs/Makefile.in index 5ed3944b..434ec21b 100644 --- a/tests/progs/Makefile.in +++ b/tests/progs/Makefile.in @@ -13,10 +13,12 @@ INSTALL = @INSTALL@ MK_CMDS= ../../lib/ss/mk_cmds -PROGS= test_rel +PROGS= test_rel test_icount TEST_REL_OBJS= test_rel.o test_rel_cmds.o +TEST_ICOUNT_OBJS= test_icount.o test_icount_cmds.o + SRCS= $(srcdir)/test_rel.c LIBS= $(LIBEXT2FS) $(LIBSS) $(LIBCOM_ERR) @@ -27,14 +29,21 @@ DEPLIBS= $(LIBEXT2FS) $(LIBSS) $(LIBCOM_ERR) all:: $(PROGS) -test_rel: $(TEST_REL_OBJS) +test_rel: $(TEST_REL_OBJS) $(DEPLIBS) $(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 +test_icount: $(TEST_ICOUNT_OBJS) $(DEPLIBS) + $(LD) $(ALL_LDFLAGS) -o test_icount $(TEST_ICOUNT_OBJS) $(LIBS) + +test_icount_cmds.c: test_icount_cmds.ct + $(MK_CMDS) $(srcdir)/test_icount_cmds.ct + clean: - $(RM) -f $(PROGS) test_rel_cmds.c \#* *.s *.o *.a *~ core + $(RM) -f $(PROGS) test_rel_cmds.c test_icount_cmds.c \ + \#* *.s *.o *.a *~ core install: diff --git a/tests/progs/rel_test/bma.setup b/tests/progs/test_data/bma.setup similarity index 100% rename from tests/progs/rel_test/bma.setup rename to tests/progs/test_data/bma.setup diff --git a/tests/progs/rel_test/expect.brel b/tests/progs/test_data/expect.brel similarity index 100% rename from tests/progs/rel_test/expect.brel rename to tests/progs/test_data/expect.brel diff --git a/tests/progs/test_data/expect.icount b/tests/progs/test_data/expect.icount new file mode 100644 index 00000000..507550fe --- /dev/null +++ b/tests/progs/test_data/expect.icount @@ -0,0 +1,191 @@ +test_icount: validate +Icount structure successfully validated +test_icount: store 0 +usage: store inode counttest_icount: fetch 0 +fetch: Invalid argument while calling ext2fs_icount_fetch +test_icount: increment 0 +increment: Invalid argument while calling ext2fs_icount_increment +test_icount: decrement 0 +decrement: Invalid argument while calling ext2fs_icount_increment +test_icount: store 20001 +usage: store inode counttest_icount: fetch 20001 +fetch: Invalid argument while calling ext2fs_icount_fetch +test_icount: increment 20001 +increment: Invalid argument while calling ext2fs_icount_increment +test_icount: decrement 20001 +decrement: Invalid argument while calling ext2fs_icount_increment +test_icount: validate +Icount structure successfully validated +test_icount: fetch 1 +Count is 0 +test_icount: store 1 1 +test_icount: fetch 1 +Count is 1 +test_icount: store 1 2 +test_icount: fetch 1 +Count is 2 +test_icount: store 1 3 +test_icount: fetch 1 +Count is 3 +test_icount: store 1 1 +test_icount: fetch 1 +Count is 1 +test_icount: store 1 0 +test_icount: fetch 1 +Count is 0 +test_icount: fetch 20000 +Count is 0 +test_icount: store 20000 0 +test_icount: fetch 20000 +Count is 0 +test_icount: store 20000 3 +test_icount: fetch 20000 +Count is 3 +test_icount: store 20000 0 +test_icount: fetch 20000 +Count is 0 +test_icount: store 20000 42 +test_icount: fetch 20000 +Count is 42 +test_icount: store 20000 1 +test_icount: fetch 20000 +Count is 1 +test_icount: store 20000 0 +test_icount: fetch 20000 +Count is 0 +test_icount: get_size +Size of icount is: 5 +test_icount: decrement 2 +decrement: Invalid argument while calling ext2fs_icount_increment +test_icount: increment 2 +Count is now 1 +test_icount: fetch 2 +Count is 1 +test_icount: increment 2 +Count is now 2 +test_icount: fetch 2 +Count is 2 +test_icount: increment 2 +Count is now 3 +test_icount: fetch 2 +Count is 3 +test_icount: increment 2 +Count is now 4 +test_icount: fetch 2 +Count is 4 +test_icount: decrement 2 +Count is now 3 +test_icount: fetch 2 +Count is 3 +test_icount: decrement 2 +Count is now 2 +test_icount: fetch 2 +Count is 2 +test_icount: decrement 2 +Count is now 1 +test_icount: fetch 2 +Count is 1 +test_icount: decrement 2 +Count is now 0 +test_icount: decrement 2 +decrement: Invalid argument while calling ext2fs_icount_increment +test_icount: store 3 1 +test_icount: increment 3 +Count is now 2 +test_icount: fetch 3 +Count is 2 +test_icount: decrement 3 +Count is now 1 +test_icount: fetch 3 +Count is 1 +test_icount: decrement 3 +Count is now 0 +test_icount: store 4 0 +test_icount: fetch 4 +Count is 0 +test_icount: increment 4 +Count is now 1 +test_icount: increment 4 +Count is now 2 +test_icount: fetch 4 +Count is 2 +test_icount: decrement 4 +Count is now 1 +test_icount: decrement 4 +Count is now 0 +test_icount: store 4 42 +test_icount: store 4 0 +test_icount: increment 4 +Count is now 1 +test_icount: increment 4 +Count is now 2 +test_icount: increment 4 +Count is now 3 +test_icount: decrement 4 +Count is now 2 +test_icount: decrement 4 +Count is now 1 +test_icount: decrement 4 +Count is now 0 +test_icount: decrement 4 +decrement: Invalid argument while calling ext2fs_icount_increment +test_icount: decrement 4 +decrement: Invalid argument while calling ext2fs_icount_increment +test_icount: store 5 4 +test_icount: decrement 5 +Count is now 3 +test_icount: decrement 5 +Count is now 2 +test_icount: decrement 5 +Count is now 1 +test_icount: decrement 5 +Count is now 0 +test_icount: decrement 5 +decrement: Invalid argument while calling ext2fs_icount_increment +test_icount: get_size +Size of icount is: 105 +test_icount: validate +Icount structure successfully validated +test_icount: store 10 10 +test_icount: store 20 20 +test_icount: store 30 30 +test_icount: store 40 40 +test_icount: store 50 50 +test_icount: store 60 60 +test_icount: store 70 70 +test_icount: store 80 80 +test_icount: store 90 90 +test_icount: store 100 100 +test_icount: store 15 15 +test_icount: store 25 25 +test_icount: store 35 35 +test_icount: store 45 45 +test_icount: store 55 55 +test_icount: store 65 65 +test_icount: store 75 75 +test_icount: store 85 85 +test_icount: store 95 95 +test_icount: dump +10: 10 +15: 15 +20: 20 +25: 25 +30: 30 +35: 35 +40: 40 +45: 45 +50: 50 +55: 55 +60: 60 +65: 65 +70: 70 +75: 75 +80: 80 +85: 85 +90: 90 +95: 95 +100: 100 +test_icount: get_size +Size of icount is: 105 +test_icount: validate +Icount structure successfully validated diff --git a/tests/progs/rel_test/expect.irel b/tests/progs/test_data/expect.irel similarity index 100% rename from tests/progs/rel_test/expect.irel rename to tests/progs/test_data/expect.irel diff --git a/tests/progs/rel_test/ima.setup b/tests/progs/test_data/ima.setup similarity index 100% rename from tests/progs/rel_test/ima.setup rename to tests/progs/test_data/ima.setup diff --git a/tests/progs/test_data/normal.setup b/tests/progs/test_data/normal.setup new file mode 100644 index 00000000..dfc6c413 --- /dev/null +++ b/tests/progs/test_data/normal.setup @@ -0,0 +1 @@ +-create diff --git a/tests/progs/test_data/opt.setup b/tests/progs/test_data/opt.setup new file mode 100644 index 00000000..79458b0a --- /dev/null +++ b/tests/progs/test_data/opt.setup @@ -0,0 +1 @@ +-create -i diff --git a/tests/progs/rel_test/test.brel b/tests/progs/test_data/test.brel similarity index 100% rename from tests/progs/rel_test/test.brel rename to tests/progs/test_data/test.brel diff --git a/tests/progs/test_data/test.icount b/tests/progs/test_data/test.icount new file mode 100644 index 00000000..ea611db3 --- /dev/null +++ b/tests/progs/test_data/test.icount @@ -0,0 +1,136 @@ +# +# This is the test script for the icount abstraction +# +# Copyright 1997 by Theodore Ts'o. This file may be redistributed +# under the terms of the GNU Public License. +# +# +# First let's test the boundary cases for illegal arguments +# +validate +store 0 +fetch 0 +increment 0 +decrement 0 +store 20001 +fetch 20001 +increment 20001 +decrement 20001 +validate +# +# OK, now let's test fetch and store. We also test the boundary cases +# for legal inodes here. +# +fetch 1 +store 1 1 +fetch 1 +store 1 2 +fetch 1 +store 1 3 +fetch 1 +store 1 1 +fetch 1 +store 1 0 +fetch 1 +fetch 20000 +store 20000 0 +fetch 20000 +store 20000 3 +fetch 20000 +store 20000 0 +fetch 20000 +store 20000 42 +fetch 20000 +store 20000 1 +fetch 20000 +store 20000 0 +fetch 20000 +get_size +# +# Time to test increment. First increment from 0 (previously unreferenced) +# +decrement 2 +increment 2 +fetch 2 +increment 2 +fetch 2 +increment 2 +fetch 2 +increment 2 +fetch 2 +decrement 2 +fetch 2 +decrement 2 +fetch 2 +decrement 2 +fetch 2 +decrement 2 +decrement 2 +# +# Store 1 then test... +# +store 3 1 +increment 3 +fetch 3 +decrement 3 +fetch 3 +decrement 3 +# +# Store 0 then test +# +store 4 0 +fetch 4 +increment 4 +increment 4 +fetch 4 +decrement 4 +decrement 4 +# +# Store something, then store 0, then test... +# +store 4 42 +store 4 0 +increment 4 +increment 4 +increment 4 +decrement 4 +decrement 4 +decrement 4 +decrement 4 +decrement 4 +# +# store something, then decrement to zero +# +store 5 4 +decrement 5 +decrement 5 +decrement 5 +decrement 5 +decrement 5 +# +# Test insert +# +get_size +validate +store 10 10 +store 20 20 +store 30 30 +store 40 40 +store 50 50 +store 60 60 +store 70 70 +store 80 80 +store 90 90 +store 100 100 +store 15 15 +store 25 25 +store 35 35 +store 45 45 +store 55 55 +store 65 65 +store 75 75 +store 85 85 +store 95 95 +dump +get_size +validate diff --git a/tests/progs/rel_test/test.irel b/tests/progs/test_data/test.irel similarity index 100% rename from tests/progs/rel_test/test.irel rename to tests/progs/test_data/test.irel diff --git a/tests/progs/test_icount.c b/tests/progs/test_icount.c new file mode 100644 index 00000000..588e90f3 --- /dev/null +++ b/tests/progs/test_icount.c @@ -0,0 +1,361 @@ +/* + * test_icount.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 +#include +#include +#include +#ifdef HAVE_GETOPT_H +#include +#endif +#include + +#include + +#include +#include +#include +#include +#include + +extern ss_request_table test_cmds; + +#include "test_icount.h" + +ext2_filsys test_fs; +ext2_icount_t test_icount; + +/* + * Helper function which assures that the icount structure is valid + */ +static int check_icount(char *request) +{ + if (test_icount) + return 0; + com_err(request, 0, "The icount structure must be allocated."); + return 1; +} + +/* + * 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; +} + +void do_create_icount(int argc, char **argv) +{ + errcode_t retval; + char *progname; + int flags = 0; + ino_t size = 5; + + progname = *argv; + argv++; argc --; + + if (argc && !strcmp("-i", *argv)) { + flags |= EXT2_ICOUNT_OPT_INCREMENT; + argv++; argc--; + } + if (argc) { + if (parse_inode(progname, "icount size", argv[0], &size)) + return; + argv++; argc--; + } +#if 0 + printf("Creating icount... flags=%d, size=%d\n", flags, (int) size); +#endif + retval = ext2fs_create_icount(test_fs, flags, (int) size, + &test_icount); + if (retval) { + com_err(progname, retval, "while creating icount"); + return; + } +} + +void do_free_icount(int argc, char **argv) +{ + if (check_icount(argv[0])) + return; + + ext2fs_free_icount(test_icount); + test_icount = 0; +} + +void do_fetch(int argc, char **argv) +{ + const char *usage = "usage: %s inode"; + errcode_t retval; + ino_t ino; + __u16 count; + + if (argc < 2) { + printf(usage, argv[0]); + return; + } + if (check_icount(argv[0])) + return; + if (parse_inode(argv[0], "inode", argv[1], &ino)) + return; + retval = ext2fs_icount_fetch(test_icount, ino, &count); + if (retval) { + com_err(argv[0], retval, "while calling ext2fs_icount_fetch"); + return; + } + printf("Count is %u\n", count); +} + +void do_increment(int argc, char **argv) +{ + const char *usage = "usage: %s inode"; + errcode_t retval; + ino_t ino; + __u16 count; + + if (argc < 2) { + printf(usage, argv[0]); + return; + } + if (check_icount(argv[0])) + return; + if (parse_inode(argv[0], "inode", argv[1], &ino)) + return; + retval = ext2fs_icount_increment(test_icount, ino, &count); + if (retval) { + com_err(argv[0], retval, + "while calling ext2fs_icount_increment"); + return; + } + printf("Count is now %u\n", count); +} + +void do_decrement(int argc, char **argv) +{ + const char *usage = "usage: %s inode"; + errcode_t retval; + ino_t ino; + __u16 count; + + if (argc < 2) { + printf(usage, argv[0]); + return; + } + if (check_icount(argv[0])) + return; + if (parse_inode(argv[0], "inode", argv[1], &ino)) + return; + retval = ext2fs_icount_decrement(test_icount, ino, &count); + if (retval) { + com_err(argv[0], retval, + "while calling ext2fs_icount_increment"); + return; + } + printf("Count is now %u\n", count); +} + +void do_store(int argc, char **argv) +{ + const char *usage = "usage: %s inode count"; + errcode_t retval; + ino_t ino; + ino_t count; + + if (argc < 3) { + printf(usage, argv[0]); + return; + } + if (check_icount(argv[0])) + return; + if (parse_inode(argv[0], "inode", argv[1], &ino)) + return; + if (parse_inode(argv[0], "count", argv[2], &count)) + return; + if (count > 65535) { + printf("Count too large.\n"); + return; + } + retval = ext2fs_icount_store(test_icount, ino, (__u16) count); + if (retval) { + com_err(argv[0], retval, + "while calling ext2fs_icount_store"); + return; + } +} + +void do_dump(int argc, char **argv) +{ + errcode_t retval; + ino_t i; + __u16 count; + + if (check_icount(argv[0])) + return; + for (i=1; i <= test_fs->super->s_inodes_count; i++) { + retval = ext2fs_icount_fetch(test_icount, i, &count); + if (retval) { + com_err(argv[0], retval, + "while fetching icount for %lu", i); + return; + } + if (count) + printf("%lu: %u\n", i, count); + } +} + +void do_validate(int argc, char **argv) +{ + errcode_t retval; + ino_t size; + + if (check_icount(argv[0])) + return; + retval = ext2fs_icount_validate(test_icount, stdout); + if (retval) { + com_err(argv[0], retval, "while validating icount structure"); + return; + } + printf("Icount structure successfully validated\n"); +} + +void do_get_size(int argc, char **argv) +{ + errcode_t retval; + ino_t size; + + if (check_icount(argv[0])) + return; + size = ext2fs_get_icount_size(test_icount); + printf("Size of icount is: %u\n", size); +} + +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_icount: %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_icount [-R request] [-f cmd_file]"; + char c; + char *request = 0; + int exit_status = 0; + char *cmd_file = 0; + struct ext2_super_block param; + + initialize_ext2_error_table(); + + /* + * Create a sample filesystem structure + */ + memset(¶m, 0, sizeof(struct ext2_super_block)); + param.s_blocks_count = 80000; + param.s_inodes_count = 20000; + retval = ext2fs_initialize("/dev/null", 0, ¶m, + unix_io_manager, &test_fs); + if (retval) { + com_err("/dev/null", retval, "while setting up test fs"); + exit(1); + } + + 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_icount", "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_icount.h b/tests/progs/test_icount.h new file mode 100644 index 00000000..9678a688 --- /dev/null +++ b/tests/progs/test_icount.h @@ -0,0 +1,7 @@ +void do_create_icount(int argc, char **argv); +void do_free_icount(int argc, char **argv); +void do_fetch(int argc, char **argv); +void do_increment(int argc, char **argv); +void do_decrement(int argc, char **argv); +void do_store(int argc, char **argv); +void do_get_size(int argc, char **argv); diff --git a/tests/progs/test_icount_cmds.ct b/tests/progs/test_icount_cmds.ct new file mode 100644 index 00000000..c3cc6f40 --- /dev/null +++ b/tests/progs/test_icount_cmds.ct @@ -0,0 +1,37 @@ +# +# Copyright (C) 1997 Theodore Ts'o. This file may be redistributed +# under the terms of the GNU Public License. +# +command_table test_cmds; + +# +# Icount table commands +# +request do_create_icount, "Create an icount structure", + create_icount, create; + +request do_free_icount, "Free an icount structure", + free_icount, free; + +request do_fetch, "Fetch an icount entry", + fetch; + +request do_increment, "Increment an icount entry", + increment, inc; + +request do_decrement, "Decrement an icount entry", + decrement, dec; + +request do_store, "Store an icount entry", + store; + +request do_get_size, "Get the size of the icount structure", + get_size; + +request do_dump, "Dump the icount structure", + dump; + +request do_validate, "Validate the icount structure", + validate, check; + +end; diff --git a/tests/progs/test_rel.c b/tests/progs/test_rel.c index d76c1f43..2dfb473b 100644 --- a/tests/progs/test_rel.c +++ b/tests/progs/test_rel.c @@ -707,8 +707,6 @@ static int source_file(const char *cmd_file, int sci_idx) return exit_status; } - - void main(int argc, char **argv) { int retval; diff --git a/tests/test_config b/tests/test_config index 6a424761..e1d2df7e 100644 --- a/tests/test_config +++ b/tests/test_config @@ -10,9 +10,12 @@ CHATTR=../misc/chattr LSATTR=../misc/lsattr DEBUGFS=../debugfs/debugfs TEST_REL=../tests/progs/test_rel +TEST_ICOUNT=../tests/progs/test_icount LD_LIBRARY_PATH=../lib:../lib/ext2fs:../lib/e2p:../lib/et:../lib/ss TMPFILE=./test.img export LD_LIBRARY_PATH TZ=GMT export TZ +LANG=C +export LANG unset PAGER diff --git a/tests/test_script.in b/tests/test_script.in index fcb4cf31..fb6a8486 100644 --- a/tests/test_script.in +++ b/tests/test_script.in @@ -9,7 +9,10 @@ else TESTS= for i do - TESTS="$TESTS $SRCDIR/$i" + case $i in + [a-zA-Z]) TESTS="$TESTS $SRCDIR/${i}_*" ;; + *) TESTS="$TESTS $SRCDIR/$i" ;; + esac done fi