mirror of https://github.com/vitalif/e2fsprogs
parent
24757fa046
commit
521e368572
|
@ -1,3 +1,8 @@
|
|||
Thu Apr 10 14:36:05 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
|
||||
|
||||
* ls.c: New file which implements the ls command. Added the -l
|
||||
option.
|
||||
|
||||
Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o <tytso@mit.edu>
|
||||
|
||||
* Release of E2fsprogs version 1.07
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
|
@ -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})
|
||||
|
|
|
@ -1,3 +1,38 @@
|
|||
Thu Apr 10 13:51:16 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
|
||||
|
||||
* 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 <tytso@rsts-11.mit.edu>
|
||||
|
||||
* 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 <tytso@rsts-11.mit.edu>
|
||||
|
||||
* 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 <tytso@rsts-11.mit.edu>
|
||||
|
||||
* 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 <tytso@mit.edu>
|
||||
|
||||
* Release of E2fsprogs version 1.07
|
||||
|
|
|
@ -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 <device>\n\n";
|
||||
" e2fsck -b %d <device>\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
|
||||
|
|
|
@ -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! */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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<filesystem metadata>\n",
|
||||
PROMPT_FIX, PR_MSG_ONLY },
|
||||
|
||||
/* Pass 2 errors */
|
||||
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
Sat Apr 5 11:48:03 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
|
||||
|
||||
* 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 <tytso@mit.edu>
|
||||
|
||||
* Release of E2fsprogs version 1.07
|
||||
|
|
|
@ -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
|
||||
|
|
22
lib/e2p/ls.c
22
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, "<none>");
|
||||
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");
|
||||
|
|
|
@ -1,3 +1,73 @@
|
|||
Thu Apr 10 13:15:15 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
|
||||
|
||||
* dblist.c (ext2fs_set_dir_block): New function which sets the
|
||||
block of a dblist entry, given the directory inode and
|
||||
blockcnt.
|
||||
|
||||
Sat Apr 5 12:42:42 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
|
||||
|
||||
* alloc_tables.c (ext2fs_allocate_tables): Allocate the bitmap and
|
||||
inode bitmaps at staggered locations across the block
|
||||
groups, to avoid concentrating the bitmaps on a small
|
||||
number of disks when using striped RAID arrays.
|
||||
|
||||
* initialize.c (ext2fs_initialize): By default, choose the maximum
|
||||
possible number of blocks per group (based on the size of
|
||||
the bitmaps in the blocksize).
|
||||
|
||||
Fri Apr 4 11:28:16 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
|
||||
|
||||
* initialize.c (ext2fs_initialize): Add support for
|
||||
EXT2_COMPAT_SPARSE_SUPER feature.
|
||||
|
||||
* closefs.c (ext2fs_bg_has_super): New function to determine
|
||||
whether or a particular block group should have a
|
||||
superblock and block group descriptor. Used for the
|
||||
EXT2_COMPAT_SPARSE_SUPER feature is turned on.
|
||||
(ext2fs_flush): Check ext2fs_bg_has_super to see whether
|
||||
or not the superblock should be written out for the block
|
||||
group.
|
||||
|
||||
* ext2fs.h (EXT2_COMPAT_SPARSE_SUPER): Define compatibility flag
|
||||
for sparse duplicate superblocks.
|
||||
|
||||
* version.c (ext2fs_get_library_version): New function which
|
||||
returns the library version.
|
||||
|
||||
* version.c (ext2fs_parse_version_string): New function which
|
||||
parses a version string and returns a version number,
|
||||
so application programs can compare version numbers as
|
||||
integers.
|
||||
|
||||
Wed Mar 26 00:43:52 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
|
||||
|
||||
* icount.c (ext2fs_create_icount): Change function so that it also
|
||||
takes a new argument which contains a "hint" icount
|
||||
structure. This "hint" icount allows the create function
|
||||
to set up the sorted list in advance. This reduces
|
||||
significantly the amount of data moving needed to insert
|
||||
these inodes into the list later.
|
||||
|
||||
* icount.c (ext2fs_icount_validate): New function which validates
|
||||
that the icount structure's rep invariant.
|
||||
|
||||
* icount.c (get_icount_el): Completely revamped implementation
|
||||
to subsume put_icount_el(). Put_icount_el() used to
|
||||
use an O(N) implementation to insert in the middle
|
||||
of the icount list. It now uses a O(ln N) to search
|
||||
for where the icount should be inserted, and then uses
|
||||
a memcpy to move the list down (instead of a for loop).
|
||||
|
||||
* icount.c (ext2fs_icount_fetch, ext2fs_icount_store,
|
||||
ext2fs_icount_increment, ext2fs_icount_decrement): Check
|
||||
to see if the inode is within bounds; if it isn't, return
|
||||
EINVAL.
|
||||
|
||||
* bitops.h (ext2fs_test_generic_bitmap): Fix error message given
|
||||
when a bad inode number is passed to test_generic_bitmap
|
||||
to be EXT2FS_TEST_ERROR instead of the wrong
|
||||
EXT2FS_UNMARK_ERROR.
|
||||
|
||||
Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o <tytso@mit.edu>
|
||||
|
||||
* Release of E2fsprogs version 1.07
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* version.c --- Return the version of the ext2 library
|
||||
*
|
||||
* Copyright (C) 1997 Theodore Ts'o.
|
||||
*
|
||||
* %Begin-Header%
|
||||
* This file may be redistributed under the terms of the GNU Public
|
||||
* License.
|
||||
* %End-Header%
|
||||
*/
|
||||
|
||||
#include <et/com_err.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#include <linux/ext2_fs.h>
|
||||
#include "ext2fs.h"
|
||||
|
||||
#include "../../version.h"
|
||||
|
||||
static const char *lib_version = E2FSPROGS_VERSION;
|
||||
static const char *lib_date = E2FSPROGS_DATE;
|
||||
|
||||
int ext2fs_parse_version_string(const char *ver_string)
|
||||
{
|
||||
const char *cp;
|
||||
int version = 0;
|
||||
|
||||
for (cp = lib_version; *cp; cp++) {
|
||||
if (!isdigit(*cp))
|
||||
continue;
|
||||
version = (version * 10) + (*cp - '0');
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
|
||||
int ext2fs_get_library_version(const char **ver_string,
|
||||
const char **date_string)
|
||||
{
|
||||
if (ver_string)
|
||||
*ver_string = lib_version;
|
||||
if (date_string)
|
||||
*date_string = lib_date;
|
||||
|
||||
return ext2fs_parse_version_string(lib_version);
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -1,3 +1,21 @@
|
|||
Thu Apr 10 07:08:03 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
|
||||
|
||||
* 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 <tytso@rsts-11.mit.edu>
|
||||
|
||||
* 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 <tytso@mit.edu>
|
||||
|
||||
* Release of E2fsprogs version 1.07
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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[])
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -1,3 +1,16 @@
|
|||
Wed Mar 26 09:29:25 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
|
||||
|
||||
* 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 <tytso@rsts-11.mit.edu>
|
||||
|
||||
* 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 <tytso@mit.edu>
|
||||
|
||||
* Release of E2fsprogs version 1.07
|
||||
|
|
|
@ -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=$?
|
|
@ -0,0 +1 @@
|
|||
inode counting abstraction optimized for storing inode counts
|
|
@ -0,0 +1 @@
|
|||
inode counting abstraction optimized for counting
|
|
@ -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):
|
||||
<filesystem metadata>
|
||||
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
|
||||
|
|
|
@ -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):
|
||||
<filesystem metadata>
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Wed Mar 26 15:38:52 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
|
||||
|
||||
* test_icount.c: New file which tests the icount abstraction.
|
||||
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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
|
|
@ -0,0 +1 @@
|
|||
-create
|
|
@ -0,0 +1 @@
|
|||
-create -i
|
|
@ -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
|
|
@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#ifdef HAVE_GETOPT_H
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <linux/ext2_fs.h>
|
||||
|
||||
#include <et/com_err.h>
|
||||
#include <ss/ss.h>
|
||||
#include <ext2fs/ext2fs.h>
|
||||
#include <ext2fs/irel.h>
|
||||
#include <ext2fs/brel.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
@ -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);
|
|
@ -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;
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue