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>
|
Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o <tytso@mit.edu>
|
||||||
|
|
||||||
* Release of E2fsprogs version 1.07
|
* Release of E2fsprogs version 1.07
|
||||||
|
|
|
@ -16,9 +16,9 @@ MANPAGES= debugfs.8
|
||||||
|
|
||||||
MK_CMDS= ../lib/ss/mk_cmds
|
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)/ncheck.c $(srcdir)/icheck.c $(srcdir)/lsdel.c \
|
||||||
$(srcdir)/dump.c
|
$(srcdir)/dump.c
|
||||||
|
|
||||||
|
|
|
@ -150,7 +150,7 @@ which is a link to
|
||||||
.IR filespec .
|
.IR filespec .
|
||||||
Note this does not adjust the inode reference counts.
|
Note this does not adjust the inode reference counts.
|
||||||
.TP
|
.TP
|
||||||
.I ls filespec
|
.I ls [-l] filespec
|
||||||
Print a listing of the files in the directory
|
Print a listing of the files in the directory
|
||||||
.IR filespec .
|
.IR filespec .
|
||||||
.TP
|
.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[])
|
void do_change_working_dir(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
ino_t inode;
|
ino_t inode;
|
||||||
|
@ -1337,6 +1265,7 @@ static void kill_file_by_inode(ino_t inode)
|
||||||
printf("Kill file by inode %ld\n", inode);
|
printf("Kill file by inode %ld\n", inode);
|
||||||
ext2fs_block_iterate(current_fs, inode, 0, NULL,
|
ext2fs_block_iterate(current_fs, inode, 0, NULL,
|
||||||
release_blocks_proc, NULL);
|
release_blocks_proc, NULL);
|
||||||
|
printf("\n");
|
||||||
ext2fs_unmark_inode_bitmap(current_fs->inode_map, inode);
|
ext2fs_unmark_inode_bitmap(current_fs->inode_map, inode);
|
||||||
|
|
||||||
ext2fs_mark_bb_dirty(current_fs);
|
ext2fs_mark_bb_dirty(current_fs);
|
||||||
|
@ -1479,7 +1408,7 @@ void main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
int sci_idx;
|
int sci_idx;
|
||||||
const char *usage = "Usage: debugfs [-w] [device]";
|
const char *usage = "Usage: debugfs [[-w] device]";
|
||||||
char c;
|
char c;
|
||||||
int open_flags = 0;
|
int open_flags = 0;
|
||||||
char *request = 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-*-
|
\input texinfo @c -*-texinfo-*-
|
||||||
@c %**start of header
|
@c %**start of header
|
||||||
@setfilename libext2fs.info
|
@setfilename libext2fs.info
|
||||||
@settitle The EXT2FS Library (version 1.07)
|
@settitle The EXT2FS Library (version 1.08)
|
||||||
@synindex tp fn
|
@synindex tp fn
|
||||||
@comment %**end of header
|
@comment %**end of header
|
||||||
|
|
||||||
|
@ -60,8 +60,8 @@ by the author.
|
||||||
|
|
||||||
@title The EXT2FS Library
|
@title The EXT2FS Library
|
||||||
@subtitle The EXT2FS Library
|
@subtitle The EXT2FS Library
|
||||||
@subtitle Version 1.07
|
@subtitle Version 1.08
|
||||||
@subtitle February 1997
|
@subtitle April 1997
|
||||||
|
|
||||||
@author by Theodore Ts'o
|
@author by Theodore Ts'o
|
||||||
|
|
||||||
|
@ -101,7 +101,7 @@ by the Foundation.
|
||||||
|
|
||||||
@top The EXT2FS Library
|
@top The EXT2FS Library
|
||||||
|
|
||||||
This manual documents the EXT2FS Library, version 1.07.
|
This manual documents the EXT2FS Library, version 1.08.
|
||||||
|
|
||||||
@end ifinfo
|
@end ifinfo
|
||||||
|
|
||||||
|
@ -130,8 +130,7 @@ manipulate an ext2 filesystem.
|
||||||
* Inode Functions::
|
* Inode Functions::
|
||||||
* Directory functions::
|
* Directory functions::
|
||||||
* Bitmap Functions::
|
* Bitmap Functions::
|
||||||
* Badblocks list management::
|
* EXT2 data abstractions::
|
||||||
* Directory-block list management::
|
|
||||||
* Byte-swapping functions::
|
* Byte-swapping functions::
|
||||||
* Other functions::
|
* Other functions::
|
||||||
@end menu
|
@end menu
|
||||||
|
@ -505,9 +504,21 @@ EXT2_ET_MISSING_INODE_TABLE.
|
||||||
@subsection Convenience functions for Inodes
|
@subsection Convenience functions for Inodes
|
||||||
|
|
||||||
@deftypefun errcode_t ext2fs_get_blocks (ext2_filsys @var{fs}, ino_t @var{ino}, blk_t *@var{blocks})
|
@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
|
@end deftypefun
|
||||||
|
|
||||||
@deftypefun errcode_t ext2fs_check_directory (ext2_filsys @var{fs}, ino_t @var{ino})
|
@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
|
@end deftypefun
|
||||||
|
|
||||||
@c ----------------------------------------------------------------------
|
@c ----------------------------------------------------------------------
|
||||||
|
@ -603,7 +614,7 @@ EXT2_ET_MISSING_INODE_TABLE.
|
||||||
|
|
||||||
@c ----------------------------------------------------------------------
|
@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
|
@comment node-name, next, previous, up
|
||||||
@section Bitmap Functions
|
@section Bitmap Functions
|
||||||
|
|
||||||
|
@ -786,9 +797,24 @@ Return the first inode or block which is stored in the bitmap.
|
||||||
|
|
||||||
@c ----------------------------------------------------------------------
|
@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
|
@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})
|
@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 ----------------------------------------------------------------------
|
@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
|
@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})
|
@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
|
@end deftypefun
|
||||||
|
|
||||||
@deftypefun void ext2fs_free_dblist (ext2_dblist @var{dblist})
|
@deftypefun void ext2fs_free_dblist (ext2_dblist @var{dblist})
|
||||||
|
|
||||||
|
Free a dblist data structure.
|
||||||
@end deftypefun
|
@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
|
@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
|
@end deftypefun
|
||||||
|
|
||||||
@deftypefun errcode_t ext2fs_dblist_dir_iterate
|
@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})
|
||||||
(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})
|
|
||||||
|
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
|
@end deftypefun
|
||||||
|
|
||||||
@c ----------------------------------------------------------------------
|
@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
|
@comment node-name, next, previous, up
|
||||||
@section Byte-swapping functions
|
@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})
|
@deftypefun errcode_t ext2fs_check_if_mounted (const char *@var{file}, int *@var{mount_flags})
|
||||||
@end deftypefun
|
@end deftypefun
|
||||||
|
|
||||||
|
/* version.c */
|
||||||
|
|
||||||
/* valid_blk.c */
|
@deftypefun int ext2fs_get_library_version(const char **@var{ver_string}, const char **@var{date_string})
|
||||||
@deftypefun int ext2_inode_has_valid_blocks (struct ext2_inode *@var{inode})
|
|
||||||
|
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
|
@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 */
|
/* inline functions */
|
||||||
@deftypefun int ext2fs_group_of_blk (ext2_filsys @var{fs}, blk_t @var{blk})
|
@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>
|
Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o <tytso@mit.edu>
|
||||||
|
|
||||||
* Release of E2fsprogs version 1.07
|
* Release of E2fsprogs version 1.07
|
||||||
|
|
|
@ -216,6 +216,13 @@ static void sync_disks(NOARGS)
|
||||||
sync();
|
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 MIN_CHECK 1
|
||||||
#define MAX_CHECK 2
|
#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. 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"
|
"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"
|
"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,
|
static void check_super_value(ext2_filsys fs, const char *descr,
|
||||||
int flags, unsigned long min, unsigned long max)
|
unsigned long value, int flags,
|
||||||
|
unsigned long min, unsigned long max)
|
||||||
{
|
{
|
||||||
if (((flags & MIN_CHECK) && (value < min)) ||
|
if (((flags & MIN_CHECK) && (value < min)) ||
|
||||||
((flags & MAX_CHECK) && (value > max))) {
|
((flags & MAX_CHECK) && (value > max))) {
|
||||||
printf("Corruption found in superblock. (%s = %lu).\n",
|
printf("Corruption found in superblock. (%s = %lu).\n",
|
||||||
descr, value);
|
descr, value);
|
||||||
printf(corrupt_msg);
|
printf(corrupt_msg, get_backup_sb(fs));
|
||||||
fatal_error(0);
|
fatal_error(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void relocate_hint(void)
|
static void relocate_hint(ext2_filsys fs)
|
||||||
{
|
{
|
||||||
static hint_issued = 0;
|
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"
|
printf("Note: if there is several inode or block bitmap blocks\n"
|
||||||
"which require relocation, or one part of the inode table\n"
|
"which require relocation, or one part of the inode table\n"
|
||||||
"which must be moved, you may wish to try running e2fsck\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"
|
"with the '-b %d' option first. The problem may lie only\n"
|
||||||
"the primary block group descriptor, and the backup block\n"
|
"with the primary block group descriptor, and the backup\n"
|
||||||
"group descriptor may be OK.\n\n");
|
"block group descriptor may be OK.\n\n", get_backup_sb(fs));
|
||||||
hint_issued = 1;
|
hint_issued = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,24 +282,24 @@ static void check_super_block(ext2_filsys fs)
|
||||||
/*
|
/*
|
||||||
* Verify the super block constants...
|
* 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);
|
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);
|
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);
|
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);
|
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,
|
MIN_CHECK | MAX_CHECK, s->s_log_frag_size,
|
||||||
2);
|
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));
|
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));
|
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);
|
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);
|
MAX_CHECK, 0, s->s_blocks_count);
|
||||||
|
|
||||||
retval = ext2fs_get_device_size(filesystem_name, EXT2_BLOCK_SIZE(s),
|
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 "
|
printf("Superblock blocks_per_group = %u, should "
|
||||||
"have been %u\n", s->s_blocks_per_group,
|
"have been %u\n", s->s_blocks_per_group,
|
||||||
should_be);
|
should_be);
|
||||||
printf(corrupt_msg);
|
printf(corrupt_msg, get_backup_sb(fs));
|
||||||
fatal_error(0);
|
fatal_error(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,7 +343,7 @@ static void check_super_block(ext2_filsys fs)
|
||||||
printf("Superblock first_data_block = %u, should "
|
printf("Superblock first_data_block = %u, should "
|
||||||
"have been %u\n", s->s_first_data_block,
|
"have been %u\n", s->s_first_data_block,
|
||||||
should_be);
|
should_be);
|
||||||
printf(corrupt_msg);
|
printf(corrupt_msg, get_backup_sb(fs));
|
||||||
fatal_error(0);
|
fatal_error(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,7 +360,7 @@ static void check_super_block(ext2_filsys fs)
|
||||||
last_block = fs->super->s_blocks_count;
|
last_block = fs->super->s_blocks_count;
|
||||||
if ((fs->group_desc[i].bg_block_bitmap < first_block) ||
|
if ((fs->group_desc[i].bg_block_bitmap < first_block) ||
|
||||||
(fs->group_desc[i].bg_block_bitmap >= last_block)) {
|
(fs->group_desc[i].bg_block_bitmap >= last_block)) {
|
||||||
relocate_hint();
|
relocate_hint(fs);
|
||||||
pctx.blk = fs->group_desc[i].bg_block_bitmap;
|
pctx.blk = fs->group_desc[i].bg_block_bitmap;
|
||||||
if (fix_problem(fs, PR_0_BB_NOT_GROUP, &pctx)) {
|
if (fix_problem(fs, PR_0_BB_NOT_GROUP, &pctx)) {
|
||||||
fs->group_desc[i].bg_block_bitmap = 0;
|
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) ||
|
if ((fs->group_desc[i].bg_inode_bitmap < first_block) ||
|
||||||
(fs->group_desc[i].bg_inode_bitmap >= last_block)) {
|
(fs->group_desc[i].bg_inode_bitmap >= last_block)) {
|
||||||
relocate_hint();
|
relocate_hint(fs);
|
||||||
pctx.blk = fs->group_desc[i].bg_inode_bitmap;
|
pctx.blk = fs->group_desc[i].bg_inode_bitmap;
|
||||||
if (fix_problem(fs, PR_0_IB_NOT_GROUP, &pctx)) {
|
if (fix_problem(fs, PR_0_IB_NOT_GROUP, &pctx)) {
|
||||||
fs->group_desc[i].bg_inode_bitmap = 0;
|
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) ||
|
if ((fs->group_desc[i].bg_inode_table < first_block) ||
|
||||||
((fs->group_desc[i].bg_inode_table +
|
((fs->group_desc[i].bg_inode_table +
|
||||||
fs->inode_blocks_per_group - 1) >= last_block)) {
|
fs->inode_blocks_per_group - 1) >= last_block)) {
|
||||||
relocate_hint();
|
relocate_hint(fs);
|
||||||
pctx.blk = fs->group_desc[i].bg_inode_table;
|
pctx.blk = fs->group_desc[i].bg_inode_table;
|
||||||
if (fix_problem(fs, PR_0_ITABLE_NOT_GROUP, &pctx)) {
|
if (fix_problem(fs, PR_0_ITABLE_NOT_GROUP, &pctx)) {
|
||||||
fs->group_desc[i].bg_inode_table = 0;
|
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[])
|
int main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
@ -600,6 +611,8 @@ int main (int argc, char *argv[])
|
||||||
ext2_filsys fs = 0;
|
ext2_filsys fs = 0;
|
||||||
io_manager io_ptr;
|
io_manager io_ptr;
|
||||||
struct ext2fs_sb *s;
|
struct ext2fs_sb *s;
|
||||||
|
const char *lib_ver_date;
|
||||||
|
int my_ver, lib_ver;
|
||||||
|
|
||||||
#ifdef MTRACE
|
#ifdef MTRACE
|
||||||
mtrace();
|
mtrace();
|
||||||
|
@ -607,6 +620,13 @@ int main (int argc, char *argv[])
|
||||||
#ifdef MCHECK
|
#ifdef MCHECK
|
||||||
mcheck(0);
|
mcheck(0);
|
||||||
#endif
|
#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);
|
init_resource_track(&global_rtrack);
|
||||||
|
|
||||||
|
@ -614,12 +634,12 @@ int main (int argc, char *argv[])
|
||||||
|
|
||||||
if (!preen || show_version_only)
|
if (!preen || show_version_only)
|
||||||
fprintf (stderr, "e2fsck %s, %s for EXT2 FS %s, %s\n",
|
fprintf (stderr, "e2fsck %s, %s for EXT2 FS %s, %s\n",
|
||||||
E2FSPROGS_VERSION, E2FSPROGS_DATE,
|
my_ver_string, my_ver_date, EXT2FS_VERSION,
|
||||||
EXT2FS_VERSION, EXT2FS_DATE);
|
EXT2FS_DATE);
|
||||||
|
|
||||||
if (show_version_only) {
|
if (show_version_only) {
|
||||||
fprintf(stderr, "\tUsing %s\n",
|
fprintf(stderr, "\tUsing %s, %s\n",
|
||||||
error_message(EXT2_ET_BASE));
|
error_message(EXT2_ET_BASE), lib_ver_date);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -663,7 +683,7 @@ restart:
|
||||||
printf("%s trying backup blocks...\n",
|
printf("%s trying backup blocks...\n",
|
||||||
retval ? "Couldn't find ext2 superblock," :
|
retval ? "Couldn't find ext2 superblock," :
|
||||||
"Group descriptors look bad...");
|
"Group descriptors look bad...");
|
||||||
superblock = 8193;
|
superblock = get_backup_sb(fs);
|
||||||
if (fs)
|
if (fs)
|
||||||
ext2fs_close(fs);
|
ext2fs_close(fs);
|
||||||
goto restart;
|
goto restart;
|
||||||
|
@ -683,7 +703,7 @@ restart:
|
||||||
else if (retval == ENXIO)
|
else if (retval == ENXIO)
|
||||||
printf("Possibly non-existent or swap device?\n");
|
printf("Possibly non-existent or swap device?\n");
|
||||||
else
|
else
|
||||||
printf(corrupt_msg);
|
printf(corrupt_msg, get_backup_sb(fs));
|
||||||
fatal_error(0);
|
fatal_error(0);
|
||||||
}
|
}
|
||||||
#ifdef EXT2_CURRENT_REV
|
#ifdef EXT2_CURRENT_REV
|
||||||
|
@ -695,18 +715,23 @@ restart:
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/*
|
/*
|
||||||
* Check for compatibility with the feature sets. We have to
|
* Check for compatibility with the feature sets. We need to
|
||||||
* check because we need to be more stringent than ext2fs_open
|
* be more stringent than ext2fs_open().
|
||||||
*/
|
*/
|
||||||
s = (struct ext2fs_sb *) fs->super;
|
s = (struct ext2fs_sb *) fs->super;
|
||||||
if (s->s_feature_compat || s->s_feature_incompat ||
|
if ((s->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
|
||||||
s->s_feature_ro_compat) {
|
(s->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
|
||||||
com_err(program_name, EXT2_ET_UNSUPP_FEATURE,
|
com_err(program_name, EXT2_ET_UNSUPP_FEATURE,
|
||||||
" (%s)", filesystem_name);
|
"(%s)", filesystem_name);
|
||||||
get_newer:
|
get_newer:
|
||||||
printf ("Get a newer version of e2fsck!\n");
|
printf ("Get a newer version of e2fsck!\n");
|
||||||
fatal_error(0);
|
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
|
* 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_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_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 *fix_msg[2]; /* Fixed or ignored! */
|
||||||
extern const char *clear_msg[2]; /* Cleared 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");
|
"while allocating block_illegal_map");
|
||||||
fatal_error(0);
|
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) {
|
if (retval) {
|
||||||
com_err("ext2fs_create_icount", retval,
|
com_err("ext2fs_create_icount", retval,
|
||||||
"while creating inode_link_info");
|
"while creating inode_link_info");
|
||||||
|
@ -821,8 +821,11 @@ int process_block(ext2_filsys fs,
|
||||||
if (blk < fs->super->s_first_data_block ||
|
if (blk < fs->super->s_first_data_block ||
|
||||||
blk >= fs->super->s_blocks_count)
|
blk >= fs->super->s_blocks_count)
|
||||||
problem = PR_1_ILLEGAL_BLOCK_NUM;
|
problem = PR_1_ILLEGAL_BLOCK_NUM;
|
||||||
else if (ext2fs_test_block_bitmap(block_illegal_map, blk))
|
#if 0
|
||||||
problem = PR_1_BLOCK_OVERLAPS_METADATA;
|
else
|
||||||
|
if (ext2fs_test_block_bitmap(block_illegal_map, blk))
|
||||||
|
problem = PR_1_BLOCK_OVERLAPS_METADATA;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (problem) {
|
if (problem) {
|
||||||
p->num_illegal_blocks++;
|
p->num_illegal_blocks++;
|
||||||
|
@ -1184,21 +1187,23 @@ static void mark_table_blocks(ext2_filsys fs)
|
||||||
fs->group_desc[i].bg_inode_bitmap);
|
fs->group_desc[i].bg_inode_bitmap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (ext2fs_bg_has_super(fs, i)) {
|
||||||
* Mark this group's copy of the superblock
|
/*
|
||||||
*/
|
* Mark this group's copy of the superblock
|
||||||
ext2fs_mark_block_bitmap(block_found_map, block);
|
*/
|
||||||
ext2fs_mark_block_bitmap(block_illegal_map, block);
|
ext2fs_mark_block_bitmap(block_found_map, block);
|
||||||
|
ext2fs_mark_block_bitmap(block_illegal_map, block);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mark this group's copy of the descriptors
|
* Mark this group's copy of the descriptors
|
||||||
*/
|
*/
|
||||||
for (j = 0; j < fs->desc_blocks; j++) {
|
for (j = 0; j < fs->desc_blocks; j++) {
|
||||||
ext2fs_mark_block_bitmap(block_found_map,
|
ext2fs_mark_block_bitmap(block_found_map,
|
||||||
block + j + 1);
|
block + j + 1);
|
||||||
ext2fs_mark_block_bitmap(block_illegal_map,
|
ext2fs_mark_block_bitmap(block_illegal_map,
|
||||||
block + j + 1);
|
block + j + 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
block += fs->super->s_blocks_per_group;
|
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;
|
int i;
|
||||||
|
|
||||||
if (ino == stashed_ino) {
|
if (ino != stashed_ino)
|
||||||
for (i=0; i < EXT2_N_BLOCKS; i++)
|
return EXT2_ET_CALLBACK_NOTHANDLED;
|
||||||
blocks[i] = stashed_inode->i_block[i];
|
|
||||||
return 0;
|
for (i=0; i < EXT2_N_BLOCKS; i++)
|
||||||
}
|
blocks[i] = stashed_inode->i_block[i];
|
||||||
printf("INTERNAL ERROR: pass1_get_blocks: unexpected inode #%lu\n",
|
return 0;
|
||||||
ino);
|
|
||||||
printf("\t(was expecting %lu)\n", stashed_ino);
|
|
||||||
exit(FSCK_ERROR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
errcode_t pass1_read_inode(ext2_filsys fs, ino_t ino, struct ext2_inode *inode)
|
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 {
|
struct search_dir_struct {
|
||||||
int count;
|
int count;
|
||||||
ino_t first_inode;
|
ino_t first_inode;
|
||||||
|
ino_t max_inode;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int search_dirent_proc(ino_t dir, int entry,
|
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 search_dir_struct *sd = private;
|
||||||
struct dup_inode *p;
|
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) ||
|
if (!dirent->inode || (entry < DIRENT_OTHER_FILE) ||
|
||||||
!ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
|
!ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -332,6 +337,7 @@ void pass1c(ext2_filsys fs, char *block_buf)
|
||||||
*/
|
*/
|
||||||
sd.count = inodes_left;
|
sd.count = inodes_left;
|
||||||
sd.first_inode = EXT2_FIRST_INODE(fs->super);
|
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,
|
ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
|
||||||
search_dirent_proc, &sd);
|
search_dirent_proc, &sd);
|
||||||
}
|
}
|
||||||
|
@ -345,6 +351,7 @@ static void pass1d(ext2_filsys fs, char *block_buf)
|
||||||
int i;
|
int i;
|
||||||
errcode_t retval;
|
errcode_t retval;
|
||||||
int file_ok;
|
int file_ok;
|
||||||
|
int meta_data = 0;
|
||||||
struct problem_context pctx;
|
struct problem_context pctx;
|
||||||
|
|
||||||
printf("Pass 1D: Reconciling duplicate blocks\n");
|
printf("Pass 1D: Reconciling duplicate blocks\n");
|
||||||
|
@ -376,6 +383,12 @@ static void pass1d(ext2_filsys fs, char *block_buf)
|
||||||
continue;
|
continue;
|
||||||
if (q->num_bad > 1)
|
if (q->num_bad > 1)
|
||||||
file_ok = 0;
|
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
|
* Add all inodes used by this block to the
|
||||||
* shared[] --- which is a unique list, so
|
* 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.ino = p->ino;
|
||||||
pctx.dir = p->dir;
|
pctx.dir = p->dir;
|
||||||
pctx.blkcount = p->num_dupblocks;
|
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);
|
fix_problem(fs, PR_1B_DUP_FILE, &pctx);
|
||||||
pctx.blkcount = 0;
|
pctx.blkcount = 0;
|
||||||
pctx.num = 0;
|
pctx.num = 0;
|
||||||
|
|
||||||
|
if (meta_data)
|
||||||
|
fix_problem(fs, PR_1B_SHARE_METADATA, &pctx);
|
||||||
|
|
||||||
for (i = 0; i < shared_len; i++) {
|
for (i = 0; i < shared_len; i++) {
|
||||||
for (s = dup_ino; s; s = s->next)
|
for (s = dup_ino; s; s = s->next)
|
||||||
if (s->ino == shared[i])
|
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 {
|
struct clone_struct {
|
||||||
errcode_t errcode;
|
errcode_t errcode;
|
||||||
|
ino_t dir;
|
||||||
char *buf;
|
char *buf;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -533,6 +550,14 @@ static int clone_file_block(ext2_filsys fs,
|
||||||
cs->errcode = retval;
|
cs->errcode = retval;
|
||||||
return BLOCK_ABORT;
|
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,
|
retval = io_channel_read_blk(fs->io, *block_nr, 1,
|
||||||
cs->buf);
|
cs->buf);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
|
@ -569,8 +594,12 @@ static int clone_file(ext2_filsys fs, struct dup_inode *dp, char* block_buf)
|
||||||
|
|
||||||
cs.errcode = 0;
|
cs.errcode = 0;
|
||||||
cs.buf = malloc(fs->blocksize);
|
cs.buf = malloc(fs->blocksize);
|
||||||
|
cs.dir = 0;
|
||||||
if (!cs.buf)
|
if (!cs.buf)
|
||||||
return ENOMEM;
|
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,
|
retval = ext2fs_block_iterate(fs, dp->ino, 0, block_buf,
|
||||||
clone_file_block, &cs);
|
clone_file_block, &cs);
|
||||||
|
|
|
@ -86,9 +86,8 @@ void pass2(ext2_filsys fs)
|
||||||
|
|
||||||
if (!preen)
|
if (!preen)
|
||||||
printf("Pass 2: Checking directory structure\n");
|
printf("Pass 2: Checking directory structure\n");
|
||||||
size = ext2fs_get_icount_size(inode_link_info) + 10;
|
retval = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
|
||||||
retval = ext2fs_create_icount(fs, EXT2_ICOUNT_OPT_INCREMENT,
|
0, inode_link_info, &inode_count);
|
||||||
size, &inode_count);
|
|
||||||
if (retval) {
|
if (retval) {
|
||||||
com_err("ext2fs_create_icount", retval,
|
com_err("ext2fs_create_icount", retval,
|
||||||
"while creating inode_count");
|
"while creating inode_count");
|
||||||
|
|
|
@ -191,6 +191,10 @@ static struct e2fsck_problem problem_table[] = {
|
||||||
"\t%Q (@i #%i, mod time %IM)\n",
|
"\t%Q (@i #%i, mod time %IM)\n",
|
||||||
PROMPT_FIX, PR_MSG_ONLY },
|
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 */
|
/* Pass 2 errors */
|
||||||
|
|
||||||
|
|
|
@ -125,6 +125,9 @@ struct e2fsck_problem {
|
||||||
/* List of files sharing duplicate blocks */
|
/* List of files sharing duplicate blocks */
|
||||||
#define PR_1B_DUP_FILE_LIST 0x011002
|
#define PR_1B_DUP_FILE_LIST 0x011002
|
||||||
|
|
||||||
|
/* File sharing blocks with filesystem metadata */
|
||||||
|
#define PR_1B_SHARE_METADATA 0x011003
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pass 2 errors
|
* Pass 2 errors
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -38,6 +38,19 @@
|
||||||
#define EXT2FS_DATE "95/08/09"
|
#define EXT2FS_DATE "95/08/09"
|
||||||
#define EXT2FS_VERSION "0.5b"
|
#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
|
* Special inodes numbers
|
||||||
*/
|
*/
|
||||||
|
@ -47,7 +60,9 @@
|
||||||
#define EXT2_ACL_DATA_INO 4 /* ACL inode */
|
#define EXT2_ACL_DATA_INO 4 /* ACL inode */
|
||||||
#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
|
#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
|
||||||
#define EXT2_UNDEL_DIR_INO 6 /* Undelete directory 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
|
* The second extended file system magic number
|
||||||
|
@ -77,10 +92,17 @@
|
||||||
#else
|
#else
|
||||||
# define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10)
|
# define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10)
|
||||||
#endif
|
#endif
|
||||||
#define EXT2_INODES_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_inode))
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
#define EXT2_ADDR_PER_BLOCK_BITS(s) ((s)->u.ext2_sb.s_addr_per_block_bits)
|
#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
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -167,7 +189,9 @@ struct ext2_group_desc
|
||||||
#define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */
|
#define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */
|
||||||
#define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */
|
#define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */
|
||||||
#define EXT2_NODUMP_FL 0x00000040 /* do not dump file */
|
#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
|
* ioctl commands
|
||||||
*/
|
*/
|
||||||
|
@ -314,14 +338,36 @@ struct ext2_super_block {
|
||||||
__u16 s_magic; /* Magic signature */
|
__u16 s_magic; /* Magic signature */
|
||||||
__u16 s_state; /* File system state */
|
__u16 s_state; /* File system state */
|
||||||
__u16 s_errors; /* Behaviour when detecting errors */
|
__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_lastcheck; /* time of last check */
|
||||||
__u32 s_checkinterval; /* max. time between checks */
|
__u32 s_checkinterval; /* max. time between checks */
|
||||||
__u32 s_creator_os; /* OS */
|
__u32 s_creator_os; /* OS */
|
||||||
__u32 s_rev_level; /* Revision level */
|
__u32 s_rev_level; /* Revision level */
|
||||||
__u16 s_def_resuid; /* Default uid for reserved blocks */
|
__u16 s_def_resuid; /* Default uid for reserved blocks */
|
||||||
__u16 s_def_resgid; /* Default gid 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
|
* Revision levels
|
||||||
*/
|
*/
|
||||||
#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */
|
#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_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
|
* 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);
|
extern int ext2_permission (struct inode *, int);
|
||||||
|
|
||||||
/* balloc.c */
|
/* balloc.c */
|
||||||
extern int ext2_new_block (struct super_block *, unsigned long,
|
extern int ext2_new_block (const struct inode *, unsigned long,
|
||||||
__u32 *, __u32 *);
|
__u32 *, __u32 *, int *);
|
||||||
extern void ext2_free_blocks (struct super_block *, unsigned long,
|
extern void ext2_free_blocks (const struct inode *, unsigned long,
|
||||||
unsigned long);
|
unsigned long);
|
||||||
extern unsigned long ext2_count_free_blocks (struct super_block *);
|
extern unsigned long ext2_count_free_blocks (struct super_block *);
|
||||||
extern void ext2_check_blocks_bitmap (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 *);
|
extern int ext2_sync_file (struct inode *, struct file *);
|
||||||
|
|
||||||
/* ialloc.c */
|
/* 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 void ext2_free_inode (struct inode *);
|
||||||
extern unsigned long ext2_count_free_inodes (struct super_block *);
|
extern unsigned long ext2_count_free_inodes (struct super_block *);
|
||||||
extern void ext2_check_inodes_bitmap (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_link (struct inode *, struct inode *, const char *, int);
|
||||||
extern int ext2_mknod (struct inode *, const char *, int, int, int);
|
extern int ext2_mknod (struct inode *, const char *, int, int, int);
|
||||||
extern int ext2_rename (struct inode *, const char *, int,
|
extern int ext2_rename (struct inode *, const char *, int,
|
||||||
struct inode *, const char *, int);
|
struct inode *, const char *, int, int);
|
||||||
|
|
||||||
/* super.c */
|
/* super.c */
|
||||||
extern void ext2_error (struct super_block *, const char *, const char *, ...)
|
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 void ext2_write_super (struct super_block *);
|
||||||
extern int ext2_remount (struct super_block *, int *, char *);
|
extern int ext2_remount (struct super_block *, int *, char *);
|
||||||
extern struct super_block * ext2_read_super (struct super_block *,void *,int);
|
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);
|
extern void ext2_statfs (struct super_block *, struct statfs *, int);
|
||||||
|
|
||||||
/* truncate.c */
|
/* 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>
|
Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o <tytso@mit.edu>
|
||||||
|
|
||||||
* Release of E2fsprogs version 1.07
|
* Release of E2fsprogs version 1.07
|
||||||
|
|
|
@ -34,13 +34,13 @@ LIBDIR= e2p
|
||||||
DLL_ADDRESS = 0x66980000
|
DLL_ADDRESS = 0x66980000
|
||||||
DLL_JUMPSIZE = 0x1000
|
DLL_JUMPSIZE = 0x1000
|
||||||
DLL_GOTSIZE = 0x1000
|
DLL_GOTSIZE = 0x1000
|
||||||
DLL_VERSION = 1.2
|
DLL_VERSION = 1.3
|
||||||
DLL_IMAGE = libe2p
|
DLL_IMAGE = libe2p
|
||||||
DLL_STUB = libe2p
|
DLL_STUB = libe2p
|
||||||
DLL_MYDIR = e2p
|
DLL_MYDIR = e2p
|
||||||
DLL_INSTALL_DIR = $(libdir)
|
DLL_INSTALL_DIR = $(libdir)
|
||||||
|
|
||||||
ELF_VERSION = 2.2
|
ELF_VERSION = 2.3
|
||||||
ELF_SO_VERSION = 2
|
ELF_SO_VERSION = 2
|
||||||
ELF_IMAGE = libe2p
|
ELF_IMAGE = libe2p
|
||||||
ELF_MYDIR = e2p
|
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 */
|
__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)
|
static void print_user (unsigned short uid)
|
||||||
{
|
{
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
|
@ -164,8 +168,6 @@ void list_super (struct ext2_super_block * s)
|
||||||
EXT2_INODE_SIZE(s)) +
|
EXT2_INODE_SIZE(s)) +
|
||||||
EXT2_BLOCK_SIZE(s) - 1) /
|
EXT2_BLOCK_SIZE(s) - 1) /
|
||||||
EXT2_BLOCK_SIZE(s));
|
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]) {
|
if (sb->s_volume_name[0]) {
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
strncpy(buf, sb->s_volume_name, sizeof(sb->s_volume_name));
|
strncpy(buf, sb->s_volume_name, sizeof(sb->s_volume_name));
|
||||||
|
@ -183,6 +185,22 @@ void list_super (struct ext2_super_block * s)
|
||||||
} else
|
} else
|
||||||
strcpy(buf, "<none>");
|
strcpy(buf, "<none>");
|
||||||
printf("Filesystem UUID: %s\n", buf);
|
printf("Filesystem UUID: %s\n", buf);
|
||||||
|
printf ("Filesystem magic number: 0x%04X\n", s->s_magic);
|
||||||
|
printf ("Filesystem revision #: %d", s->s_rev_level);
|
||||||
|
if (s->s_rev_level == EXT2_GOOD_OLD_REV) {
|
||||||
|
printf(" (original)\n");
|
||||||
|
#ifdef EXT2_DYNAMIC_REV
|
||||||
|
} else if (s->s_rev_level == EXT2_DYNAMIC_REV) {
|
||||||
|
printf(" (dynamic)\n");
|
||||||
|
#endif
|
||||||
|
} else
|
||||||
|
printf("\n");
|
||||||
|
printf ("Filesystem features: ");
|
||||||
|
if (s->s_feature_ro_compat & EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)
|
||||||
|
printf("sparse_super");
|
||||||
|
else
|
||||||
|
printf("(none)");
|
||||||
|
printf("\n");
|
||||||
printf ("Filesystem state: ");
|
printf ("Filesystem state: ");
|
||||||
print_fs_state (stdout, s->s_state);
|
print_fs_state (stdout, s->s_state);
|
||||||
printf ("\n");
|
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>
|
Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o <tytso@mit.edu>
|
||||||
|
|
||||||
* Release of E2fsprogs version 1.07
|
* Release of E2fsprogs version 1.07
|
||||||
|
|
|
@ -50,7 +50,8 @@ OBJS= ext2_err.o \
|
||||||
test_io.o \
|
test_io.o \
|
||||||
unix_io.o \
|
unix_io.o \
|
||||||
unlink.o \
|
unlink.o \
|
||||||
valid_blk.o
|
valid_blk.o \
|
||||||
|
version.o
|
||||||
|
|
||||||
SRCS= ext2_err.c \
|
SRCS= ext2_err.c \
|
||||||
$(srcdir)/alloc.c \
|
$(srcdir)/alloc.c \
|
||||||
|
@ -95,7 +96,8 @@ SRCS= ext2_err.c \
|
||||||
$(srcdir)/test_io.c \
|
$(srcdir)/test_io.c \
|
||||||
$(srcdir)/unix_io.c \
|
$(srcdir)/unix_io.c \
|
||||||
$(srcdir)/unlink.c \
|
$(srcdir)/unlink.c \
|
||||||
$(srcdir)/valid_blk.c
|
$(srcdir)/valid_blk.c \
|
||||||
|
$(srcdir)/version.c
|
||||||
|
|
||||||
HFILES= bitops.h ext2fs.h io.h
|
HFILES= bitops.h ext2fs.h io.h
|
||||||
|
|
||||||
|
@ -105,21 +107,21 @@ LIBDIR= ext2fs
|
||||||
DLL_ADDRESS = 0x66900000
|
DLL_ADDRESS = 0x66900000
|
||||||
DLL_JUMPSIZE = 0x1000
|
DLL_JUMPSIZE = 0x1000
|
||||||
DLL_GOTSIZE = 0x1000
|
DLL_GOTSIZE = 0x1000
|
||||||
DLL_VERSION = 1.1
|
DLL_VERSION = 1.2
|
||||||
DLL_IMAGE = libe2fs
|
DLL_IMAGE = libe2fs
|
||||||
DLL_STUB = libext2fs
|
DLL_STUB = libext2fs
|
||||||
DLL_LIBS = -L../.. -lcom_err
|
DLL_LIBS = -L../.. -lcom_err
|
||||||
DLL_MYDIR = ext2fs
|
DLL_MYDIR = ext2fs
|
||||||
DLL_INSTALL_DIR = $(libdir)
|
DLL_INSTALL_DIR = $(libdir)
|
||||||
|
|
||||||
ELF_VERSION = 2.2
|
ELF_VERSION = 2.3
|
||||||
ELF_SO_VERSION = 2
|
ELF_SO_VERSION = 2
|
||||||
ELF_IMAGE = libext2fs
|
ELF_IMAGE = libext2fs
|
||||||
ELF_MYDIR = ext2fs
|
ELF_MYDIR = ext2fs
|
||||||
ELF_INSTALL_DIR = $(libdir)
|
ELF_INSTALL_DIR = $(libdir)
|
||||||
ELF_OTHER_LIBS = -lc -L../.. -lcom_err
|
ELF_OTHER_LIBS = -lc -L../.. -lcom_err
|
||||||
|
|
||||||
BSDLIB_VERSION = 2.0
|
BSDLIB_VERSION = 2.1
|
||||||
BSDLIB_IMAGE = libext2fs
|
BSDLIB_IMAGE = libext2fs
|
||||||
BSDLIB_MYDIR = ext2fs
|
BSDLIB_MYDIR = ext2fs
|
||||||
BSDLIB_INSTALL_DIR = $(libdir)
|
BSDLIB_INSTALL_DIR = $(libdir)
|
||||||
|
|
|
@ -29,37 +29,17 @@
|
||||||
errcode_t ext2fs_allocate_tables(ext2_filsys fs)
|
errcode_t ext2fs_allocate_tables(ext2_filsys fs)
|
||||||
{
|
{
|
||||||
errcode_t retval;
|
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;
|
int i, j;
|
||||||
|
|
||||||
group_blk = fs->super->s_first_data_block;
|
group_blk = fs->super->s_first_data_block;
|
||||||
for (i = 0; i < fs->group_desc_count; i++) {
|
for (i = 0; i < fs->group_desc_count; i++) {
|
||||||
last_blk = group_blk + fs->super->s_blocks_per_group;
|
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,
|
start_blk = group_blk + 3 + fs->desc_blocks;
|
||||||
1, fs->block_map, &new_blk);
|
retval = ext2fs_get_free_blocks(fs, start_blk, last_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,
|
|
||||||
fs->inode_blocks_per_group,
|
fs->inode_blocks_per_group,
|
||||||
fs->block_map, &new_blk);
|
fs->block_map, &new_blk);
|
||||||
if (retval)
|
if (retval)
|
||||||
|
@ -70,6 +50,25 @@ errcode_t ext2fs_allocate_tables(ext2_filsys fs)
|
||||||
ext2fs_mark_block_bitmap(fs->block_map, blk);
|
ext2fs_mark_block_bitmap(fs->block_map, blk);
|
||||||
fs->group_desc[i].bg_inode_table = new_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
|
* Increment the start of the block group
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -353,7 +353,7 @@ _INLINE_ int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
|
||||||
blk_t bitno)
|
blk_t bitno)
|
||||||
{
|
{
|
||||||
if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
|
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 0;
|
||||||
}
|
}
|
||||||
return ext2fs_test_bit(bitno - bitmap->start, bitmap->bitmap);
|
return ext2fs_test_bit(bitno - bitmap->start, bitmap->bitmap);
|
||||||
|
|
|
@ -22,6 +22,38 @@
|
||||||
|
|
||||||
#include "ext2fsP.h"
|
#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)
|
errcode_t ext2fs_flush(ext2_filsys fs)
|
||||||
{
|
{
|
||||||
int i,j,maxgroup;
|
int i,j,maxgroup;
|
||||||
|
@ -92,6 +124,9 @@ errcode_t ext2fs_flush(ext2_filsys fs)
|
||||||
maxgroup = (fs->flags & EXT2_FLAG_MASTER_SB_ONLY) ? 1 :
|
maxgroup = (fs->flags & EXT2_FLAG_MASTER_SB_ONLY) ? 1 :
|
||||||
fs->group_desc_count;
|
fs->group_desc_count;
|
||||||
for (i = 0; i < maxgroup; i++) {
|
for (i = 0; i < maxgroup; i++) {
|
||||||
|
if (!ext2fs_bg_has_super(fs, i))
|
||||||
|
goto next_group;
|
||||||
|
|
||||||
if (i !=0 ) {
|
if (i !=0 ) {
|
||||||
retval = io_channel_write_blk(fs->io, group_block,
|
retval = io_channel_write_blk(fs->io, group_block,
|
||||||
-SUPERBLOCK_SIZE,
|
-SUPERBLOCK_SIZE,
|
||||||
|
@ -108,6 +143,7 @@ errcode_t ext2fs_flush(ext2_filsys fs)
|
||||||
goto errout;
|
goto errout;
|
||||||
group_ptr += fs->blocksize;
|
group_ptr += fs->blocksize;
|
||||||
}
|
}
|
||||||
|
next_group:
|
||||||
group_block += EXT2_BLOCKS_PER_GROUP(fs->super);
|
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;
|
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
|
* This function iterates over the directory block list
|
||||||
*/
|
*/
|
||||||
|
@ -151,7 +173,6 @@ errcode_t ext2fs_dblist_iterate(ext2_dblist dblist,
|
||||||
if (ret & DBLIST_ABORT)
|
if (ret & DBLIST_ABORT)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -138,3 +138,7 @@
|
||||||
00000000 T _ext2fs_icount_decrement libext2fs icount
|
00000000 T _ext2fs_icount_decrement libext2fs icount
|
||||||
00000000 T _ext2fs_icount_store libext2fs icount
|
00000000 T _ext2fs_icount_store libext2fs icount
|
||||||
00000000 T _ext2fs_get_icount_size 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 */
|
char s_last_mounted[64]; /* directory where last mounted */
|
||||||
__u32 s_reserved[206]; /* Padding to the end of the block */
|
__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
|
* function prototypes
|
||||||
*/
|
*/
|
||||||
|
@ -442,6 +454,7 @@ extern errcode_t ext2fs_check_desc(ext2_filsys fs);
|
||||||
/* closefs.c */
|
/* closefs.c */
|
||||||
extern errcode_t ext2fs_close(ext2_filsys fs);
|
extern errcode_t ext2fs_close(ext2_filsys fs);
|
||||||
extern errcode_t ext2fs_flush(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 */
|
/* cmp_bitmaps.c */
|
||||||
extern errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1,
|
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,
|
struct ext2_db_entry *db_info,
|
||||||
void *private),
|
void *private),
|
||||||
void *private);
|
void *private);
|
||||||
|
errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ino_t ino, blk_t blk,
|
||||||
|
int blockcnt);
|
||||||
|
|
||||||
/* dblist_dir.c */
|
/* dblist_dir.c */
|
||||||
extern errcode_t
|
extern errcode_t
|
||||||
|
@ -544,6 +559,8 @@ extern errcode_t ext2fs_check_directory(ext2_filsys fs, ino_t ino);
|
||||||
|
|
||||||
/* icount.c */
|
/* icount.c */
|
||||||
extern void ext2fs_free_icount(ext2_icount_t icount);
|
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,
|
extern errcode_t ext2fs_create_icount(ext2_filsys fs, int flags, int size,
|
||||||
ext2_icount_t *ret);
|
ext2_icount_t *ret);
|
||||||
extern errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ino_t ino,
|
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,
|
extern errcode_t ext2fs_icount_store(ext2_icount_t icount, ino_t ino,
|
||||||
__u16 count);
|
__u16 count);
|
||||||
extern ino_t ext2fs_get_icount_size(ext2_icount_t icount);
|
extern ino_t ext2fs_get_icount_size(ext2_icount_t icount);
|
||||||
|
errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *);
|
||||||
|
|
||||||
/* ismounted.c */
|
/* ismounted.c */
|
||||||
extern errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags);
|
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);
|
struct ext2_inode *f, int hostorder);
|
||||||
|
|
||||||
/* valid_blk.c */
|
/* 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 */
|
/* inline functions */
|
||||||
extern void ext2fs_mark_super_dirty(ext2_filsys fs);
|
extern void ext2fs_mark_super_dirty(ext2_filsys fs);
|
||||||
|
|
|
@ -71,13 +71,20 @@ void ext2fs_free_icount(ext2_icount_t icount)
|
||||||
free(icount);
|
free(icount);
|
||||||
}
|
}
|
||||||
|
|
||||||
errcode_t ext2fs_create_icount(ext2_filsys fs, int flags, int size,
|
errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags, int size,
|
||||||
ext2_icount_t *ret)
|
ext2_icount_t hint, ext2_icount_t *ret)
|
||||||
{
|
{
|
||||||
ext2_icount_t icount;
|
ext2_icount_t icount;
|
||||||
errcode_t retval;
|
errcode_t retval;
|
||||||
size_t bytes;
|
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));
|
icount = malloc(sizeof(struct ext2_icount));
|
||||||
if (!icount)
|
if (!icount)
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
|
@ -125,8 +132,18 @@ errcode_t ext2fs_create_icount(ext2_filsys fs, int flags, int size,
|
||||||
icount->cursor = 0;
|
icount->cursor = 0;
|
||||||
icount->num_inodes = fs->super->s_inodes_count;
|
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;
|
return 0;
|
||||||
|
|
||||||
errout:
|
errout:
|
||||||
|
@ -134,65 +151,22 @@ errout:
|
||||||
return(retval);
|
return(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
errcode_t ext2fs_create_icount(ext2_filsys fs, int flags, int size,
|
||||||
* get_icount_el() --- given an inode number, try to find icount
|
ext2_icount_t *ret)
|
||||||
* information in the sorted list. We use a binary search...
|
|
||||||
*/
|
|
||||||
static struct ext2_icount_el *get_icount_el(ext2_icount_t icount, ino_t ino)
|
|
||||||
{
|
{
|
||||||
int low, high, mid;
|
return ext2fs_create_icount2(fs, flags, size, 0, ret);
|
||||||
|
|
||||||
if (!icount || !icount->list || !icount->count)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (icount->multiple &&
|
|
||||||
!ext2fs_test_inode_bitmap(icount->multiple, ino))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
low = 0;
|
|
||||||
high = icount->count-1;
|
|
||||||
if (ino == icount->list[low].ino) {
|
|
||||||
icount->cursor = low+1;
|
|
||||||
return &icount->list[low];
|
|
||||||
}
|
|
||||||
if (ino == icount->list[high].ino) {
|
|
||||||
icount->cursor = 0;
|
|
||||||
return &icount->list[high];
|
|
||||||
}
|
|
||||||
if (icount->cursor >= icount->count)
|
|
||||||
icount->cursor = 0;
|
|
||||||
if (ino == icount->list[icount->cursor].ino)
|
|
||||||
return &icount->list[icount->cursor++];
|
|
||||||
#if 0
|
|
||||||
printf("Non-cursor get_icount_el: %u\n", ino);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
while (low < high) {
|
|
||||||
mid = (low+high)/2;
|
|
||||||
if (mid == low || mid == high)
|
|
||||||
break;
|
|
||||||
if (ino == icount->list[mid].ino) {
|
|
||||||
icount->cursor = mid;
|
|
||||||
return &icount->list[mid];
|
|
||||||
}
|
|
||||||
if (ino < icount->list[mid].ino)
|
|
||||||
high = mid;
|
|
||||||
else
|
|
||||||
low = mid;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* put_icount_el() --- given an inode number, create a new entry in
|
* insert_icount_el() --- Insert a new entry into the sorted list at a
|
||||||
* the sorted list. This function is optimized for adding values
|
* specified position.
|
||||||
* in ascending order.
|
|
||||||
*/
|
*/
|
||||||
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;
|
struct ext2_icount_el *el, *new_list;
|
||||||
ino_t new_size = 0;
|
ino_t new_size = 0;
|
||||||
int i, j;
|
int num;
|
||||||
|
|
||||||
if (icount->count >= icount->size) {
|
if (icount->count >= icount->size) {
|
||||||
if (icount->count) {
|
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->size = new_size;
|
||||||
icount->list = new_list;
|
icount->list = new_list;
|
||||||
}
|
}
|
||||||
|
num = icount->count - pos;
|
||||||
/*
|
if (num < 0)
|
||||||
* Normally, get_icount_el is called with each inode in
|
return 0; /* should never happen */
|
||||||
* sequential order; but once in a while (like when pass 3
|
if (num) {
|
||||||
* needs to recreate the root directory or lost+found
|
memmove(&icount->list[pos+1], &icount->list[pos],
|
||||||
* directory) it is called out of order.
|
sizeof(struct ext2_icount_el) * num);
|
||||||
*/
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
icount->count++;
|
||||||
|
el = &icount->list[pos];
|
||||||
|
el->count = 0;
|
||||||
el->ino = ino;
|
el->ino = ino;
|
||||||
return el;
|
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)
|
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);
|
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 (ext2fs_test_inode_bitmap(icount->single, ino)) {
|
||||||
*ret = 1;
|
*ret = 1;
|
||||||
return 0;
|
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) {
|
if (!el) {
|
||||||
*ret = 0;
|
*ret = 0;
|
||||||
return 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);
|
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 (ext2fs_test_inode_bitmap(icount->single, ino)) {
|
||||||
/*
|
/*
|
||||||
* If the existing count is 1, then we know there is
|
* 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)
|
if (!el)
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
|
ext2fs_unmark_inode_bitmap(icount->single, ino);
|
||||||
|
el->count = 2;
|
||||||
} else if (icount->multiple) {
|
} else if (icount->multiple) {
|
||||||
/*
|
/*
|
||||||
* The count is either zero or greater than 1; if the
|
* 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().
|
* get_icount_el().
|
||||||
*/
|
*/
|
||||||
if (ext2fs_test_inode_bitmap(icount->multiple, ino)) {
|
if (ext2fs_test_inode_bitmap(icount->multiple, ino)) {
|
||||||
el = get_icount_el(icount, ino);
|
el = get_icount_el(icount, ino, 1);
|
||||||
if (!el) {
|
if (!el)
|
||||||
/* should never happen */
|
return ENOMEM;
|
||||||
el = put_icount_el(icount, ino);
|
el->count++;
|
||||||
if (!el)
|
|
||||||
return ENOMEM;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* The count was zero; mark the single bitmap
|
* 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
|
* The count is either zero or greater than 1; try to
|
||||||
* find an entry in the list to determine which.
|
* find an entry in the list to determine which.
|
||||||
*/
|
*/
|
||||||
el = get_icount_el(icount, ino);
|
el = get_icount_el(icount, ino, 0);
|
||||||
if (!el) {
|
if (!el) {
|
||||||
/* No entry means the count was zero */
|
/* No entry means the count was zero */
|
||||||
goto zero_count;
|
goto zero_count;
|
||||||
}
|
}
|
||||||
el = put_icount_el(icount, ino);
|
el = get_icount_el(icount, ino, 1);
|
||||||
if (!el)
|
if (!el)
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
}
|
|
||||||
if (ext2fs_test_inode_bitmap(icount->single, ino)) {
|
|
||||||
ext2fs_unmark_inode_bitmap(icount->single, ino);
|
|
||||||
el->count = 2;
|
|
||||||
} else
|
|
||||||
el->count++;
|
el->count++;
|
||||||
|
}
|
||||||
if (icount->multiple)
|
if (icount->multiple)
|
||||||
ext2fs_mark_inode_bitmap(icount->multiple, ino);
|
ext2fs_mark_inode_bitmap(icount->multiple, ino);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -329,6 +390,9 @@ errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ino_t ino,
|
||||||
{
|
{
|
||||||
struct ext2_icount_el *el;
|
struct ext2_icount_el *el;
|
||||||
|
|
||||||
|
if (!ino || (ino > icount->num_inodes))
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
|
EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
|
||||||
|
|
||||||
if (ext2fs_test_inode_bitmap(icount->single, ino)) {
|
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)
|
if (icount->multiple)
|
||||||
ext2fs_unmark_inode_bitmap(icount->multiple, ino);
|
ext2fs_unmark_inode_bitmap(icount->multiple, ino);
|
||||||
else {
|
else {
|
||||||
el = get_icount_el(icount, ino);
|
el = get_icount_el(icount, ino, 0);
|
||||||
if (el)
|
if (el)
|
||||||
el->count = 0;
|
el->count = 0;
|
||||||
}
|
}
|
||||||
|
@ -345,8 +409,12 @@ errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ino_t ino,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
el = get_icount_el(icount, ino);
|
if (icount->multiple &&
|
||||||
if (!el)
|
!ext2fs_test_inode_bitmap(icount->multiple, ino))
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
el = get_icount_el(icount, ino, 0);
|
||||||
|
if (!el || el->count == 0)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
el->count--;
|
el->count--;
|
||||||
|
@ -365,6 +433,9 @@ errcode_t ext2fs_icount_store(ext2_icount_t icount, ino_t ino,
|
||||||
{
|
{
|
||||||
struct ext2_icount_el *el;
|
struct ext2_icount_el *el;
|
||||||
|
|
||||||
|
if (!ino || (ino > icount->num_inodes))
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
|
EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT);
|
||||||
|
|
||||||
if (count == 1) {
|
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);
|
ext2fs_unmark_inode_bitmap(icount->multiple, ino);
|
||||||
} else {
|
} else {
|
||||||
el = get_icount_el(icount, ino);
|
el = get_icount_el(icount, ino, 0);
|
||||||
if (el)
|
if (el)
|
||||||
el->count = 0;
|
el->count = 0;
|
||||||
}
|
}
|
||||||
|
@ -392,7 +463,7 @@ errcode_t ext2fs_icount_store(ext2_icount_t icount, ino_t ino,
|
||||||
/*
|
/*
|
||||||
* Get the icount element
|
* Get the icount element
|
||||||
*/
|
*/
|
||||||
el = put_icount_el(icount, ino);
|
el = get_icount_el(icount, ino, 1);
|
||||||
if (!el)
|
if (!el)
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
el->count = count;
|
el->count = count;
|
||||||
|
|
|
@ -58,6 +58,7 @@ errcode_t ext2fs_initialize(const char *name, int flags,
|
||||||
ext2_filsys fs;
|
ext2_filsys fs;
|
||||||
errcode_t retval;
|
errcode_t retval;
|
||||||
struct ext2_super_block *super;
|
struct ext2_super_block *super;
|
||||||
|
struct ext2fs_sb *s;
|
||||||
int frags_per_block;
|
int frags_per_block;
|
||||||
int rem;
|
int rem;
|
||||||
int overhead = 0;
|
int overhead = 0;
|
||||||
|
@ -91,9 +92,12 @@ errcode_t ext2fs_initialize(const char *name, int flags,
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
memset(super, 0, SUPERBLOCK_SIZE);
|
memset(super, 0, SUPERBLOCK_SIZE);
|
||||||
|
s = (struct ext2fs_sb *) super;
|
||||||
|
|
||||||
#define set_field(field, default) (super->field = param->field ? \
|
#define set_field(field, default) (super->field = param->field ? \
|
||||||
param->field : (default))
|
param->field : (default))
|
||||||
|
#define set_ext2_field(field, default) (s->field = param->field ? \
|
||||||
|
param->field : (default))
|
||||||
|
|
||||||
super->s_magic = EXT2_SUPER_MAGIC;
|
super->s_magic = EXT2_SUPER_MAGIC;
|
||||||
super->s_state = EXT2_VALID_FS;
|
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_first_data_block, super->s_log_block_size ? 0 : 1);
|
||||||
set_field(s_max_mnt_count, EXT2_DFL_MAX_MNT_COUNT);
|
set_field(s_max_mnt_count, EXT2_DFL_MAX_MNT_COUNT);
|
||||||
set_field(s_errors, EXT2_ERRORS_DEFAULT);
|
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
|
#ifdef EXT2_DYNAMIC_REV
|
||||||
set_field(s_rev_level, EXT2_GOOD_OLD_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);
|
fs->fragsize = EXT2_FRAG_SIZE(super);
|
||||||
frags_per_block = fs->blocksize / fs->fragsize;
|
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_frags_per_group = super->s_blocks_per_group * frags_per_block;
|
||||||
|
|
||||||
super->s_blocks_count = param->s_blocks_count;
|
super->s_blocks_count = param->s_blocks_count;
|
||||||
|
@ -187,16 +198,6 @@ retry:
|
||||||
fs->group_desc_count;
|
fs->group_desc_count;
|
||||||
super->s_free_inodes_count = super->s_inodes_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
|
* See if the last group is big enough to support the
|
||||||
* necessary data structures. If not, we need to get rid of
|
* necessary data structures. If not, we need to get rid of
|
||||||
|
@ -250,11 +251,8 @@ retry:
|
||||||
* by this routine), they are accounted for nevertheless.
|
* by this routine), they are accounted for nevertheless.
|
||||||
*/
|
*/
|
||||||
group_block = super->s_first_data_block;
|
group_block = super->s_first_data_block;
|
||||||
|
super->s_free_blocks_count = 0;
|
||||||
for (i = 0; i < fs->group_desc_count; i++) {
|
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) {
|
if (i == fs->group_desc_count-1) {
|
||||||
numblocks = (fs->super->s_blocks_count -
|
numblocks = (fs->super->s_blocks_count -
|
||||||
fs->super->s_first_data_block) %
|
fs->super->s_first_data_block) %
|
||||||
|
@ -263,8 +261,17 @@ retry:
|
||||||
numblocks = fs->super->s_blocks_per_group;
|
numblocks = fs->super->s_blocks_per_group;
|
||||||
} else
|
} else
|
||||||
numblocks = fs->super->s_blocks_per_group;
|
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_blocks_count = numblocks;
|
||||||
fs->group_desc[i].bg_free_inodes_count =
|
fs->group_desc[i].bg_free_inodes_count =
|
||||||
fs->super->s_inodes_per_group;
|
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;
|
ext2_inode_scan scan;
|
||||||
errcode_t retval;
|
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);
|
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.
|
* scanning functions require it.
|
||||||
*/
|
*/
|
||||||
if (fs->badblocks == 0) {
|
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);
|
retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
|
||||||
if (retval && fs->badblocks) {
|
if (retval && fs->badblocks) {
|
||||||
badblocks_list_free(fs->badblocks);
|
badblocks_list_free(fs->badblocks);
|
||||||
fs->badblocks = 0;
|
fs->badblocks = 0;
|
||||||
}
|
}
|
||||||
|
fs->get_blocks = save_get_blocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
scan = (ext2_inode_scan) malloc(sizeof(struct ext2_struct_inode_scan));
|
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)) {
|
if (!(flags & EXT2_FLAG_FORCE)) {
|
||||||
s = (struct ext2fs_sb *) fs->super;
|
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;
|
retval = EXT2_ET_UNSUPP_FEATURE;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
if ((flags & EXT2_FLAG_RW) &&
|
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;
|
retval = EXT2_ET_RO_UNSUPP_FEATURE;
|
||||||
goto cleanup;
|
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$
|
* $Locker$
|
||||||
*
|
*
|
||||||
* $Log$
|
* $Log$
|
||||||
* Revision 1.10 1997/04/29 16:15:48 tytso
|
* Revision 1.11 1997/04/29 17:47:28 tytso
|
||||||
* Checked in e2fsprogs-1.07
|
* Checked in e2fsprogs 1.08.
|
||||||
*
|
*
|
||||||
* Revision 1.1 1993/06/03 12:31:25 tytso
|
* Revision 1.1 1993/06/03 12:31:25 tytso
|
||||||
* Initial revision
|
* 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>
|
Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o <tytso@mit.edu>
|
||||||
|
|
||||||
* Release of E2fsprogs version 1.07
|
* 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)
|
static void list_desc (ext2_filsys fs)
|
||||||
{
|
{
|
||||||
unsigned long i;
|
unsigned long i;
|
||||||
|
blk_t group_blk, next_blk;
|
||||||
char * block_bitmap = fs->block_map->bitmap;
|
char * block_bitmap = fs->block_map->bitmap;
|
||||||
char * inode_bitmap = fs->inode_map->bitmap;
|
char * inode_bitmap = fs->inode_map->bitmap;
|
||||||
|
|
||||||
printf ("\n");
|
printf ("\n");
|
||||||
for (i = 0; i < fs->group_desc_count; i++)
|
group_blk = fs->super->s_first_data_block;
|
||||||
{
|
for (i = 0; i < fs->group_desc_count; i++) {
|
||||||
printf ("Group %lu:\n", i);
|
next_blk = group_blk + fs->super->s_blocks_per_group;
|
||||||
printf (" Block bitmap at %u, Inode bitmap at %u, "
|
if (next_blk > fs->super->s_blocks_count)
|
||||||
"Inode table at %u\n",
|
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,
|
||||||
|
fs->group_desc[i].bg_block_bitmap - group_blk,
|
||||||
fs->group_desc[i].bg_inode_bitmap,
|
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",
|
printf (" %d free blocks, %d free inodes, %d directories\n",
|
||||||
fs->group_desc[i].bg_free_blocks_count,
|
fs->group_desc[i].bg_free_blocks_count,
|
||||||
fs->group_desc[i].bg_free_inodes_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);
|
print_free (i, inode_bitmap, fs->super->s_inodes_per_group, 1);
|
||||||
inode_bitmap += fs->super->s_inodes_per_group / 8;
|
inode_bitmap += fs->super->s_inodes_per_group / 8;
|
||||||
printf ("\n");
|
printf ("\n");
|
||||||
|
group_blk = next_blk;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,9 @@ mke2fs \- create a Linux second extended file system
|
||||||
.B \-q
|
.B \-q
|
||||||
]
|
]
|
||||||
[
|
[
|
||||||
|
.B -s sparse-super-flag
|
||||||
|
]
|
||||||
|
[
|
||||||
.B \-v
|
.B \-v
|
||||||
]
|
]
|
||||||
[
|
[
|
||||||
|
@ -114,6 +117,11 @@ of the mke2fs executable.
|
||||||
.I -q
|
.I -q
|
||||||
Quiet execution. Useful if mke2fs is run in a script.
|
Quiet execution. Useful if mke2fs is run in a script.
|
||||||
.TP
|
.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
|
.I -v
|
||||||
Verbose execution.
|
Verbose execution.
|
||||||
.TP
|
.TP
|
||||||
|
|
|
@ -486,6 +486,8 @@ static void show_stats(ext2_filsys fs)
|
||||||
col_left = 0;
|
col_left = 0;
|
||||||
for (i = 1; i < fs->group_desc_count; i++) {
|
for (i = 1; i < fs->group_desc_count; i++) {
|
||||||
group_block += s->s_blocks_per_group;
|
group_block += s->s_blocks_per_group;
|
||||||
|
if (!ext2fs_bg_has_super(fs, i))
|
||||||
|
continue;
|
||||||
if (!col_left--) {
|
if (!col_left--) {
|
||||||
printf("\n\t");
|
printf("\n\t");
|
||||||
col_left = 8;
|
col_left = 8;
|
||||||
|
@ -539,11 +541,14 @@ static void PRS(int argc, char *argv[])
|
||||||
char c;
|
char c;
|
||||||
int size;
|
int size;
|
||||||
char * tmp;
|
char * tmp;
|
||||||
|
blk_t max = 8192;
|
||||||
int inode_ratio = 4096;
|
int inode_ratio = 4096;
|
||||||
int reserved_ratio = 5;
|
int reserved_ratio = 5;
|
||||||
errcode_t retval;
|
errcode_t retval;
|
||||||
|
int sparse_option = -1;
|
||||||
char *oldpath = getenv("PATH");
|
char *oldpath = getenv("PATH");
|
||||||
|
struct ext2fs_sb *param_ext2 = (struct ext2fs_sb *) ¶m;
|
||||||
|
|
||||||
/* Update our PATH to include /sbin */
|
/* Update our PATH to include /sbin */
|
||||||
if (oldpath) {
|
if (oldpath) {
|
||||||
char *newpath;
|
char *newpath;
|
||||||
|
@ -560,6 +565,9 @@ static void PRS(int argc, char *argv[])
|
||||||
setbuf(stderr, NULL);
|
setbuf(stderr, NULL);
|
||||||
initialize_ext2_error_table();
|
initialize_ext2_error_table();
|
||||||
memset(¶m, 0, sizeof(struct ext2_super_block));
|
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",
|
fprintf (stderr, "mke2fs %s, %s for EXT2 FS %s, %s\n",
|
||||||
E2FSPROGS_VERSION, E2FSPROGS_DATE,
|
E2FSPROGS_VERSION, E2FSPROGS_DATE,
|
||||||
|
@ -567,7 +575,7 @@ static void PRS(int argc, char *argv[])
|
||||||
if (argc && *argv)
|
if (argc && *argv)
|
||||||
program_name = *argv;
|
program_name = *argv;
|
||||||
while ((c = getopt (argc, 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) {
|
switch (c) {
|
||||||
case 'b':
|
case 'b':
|
||||||
size = strtoul(optarg, &tmp, 0);
|
size = strtoul(optarg, &tmp, 0);
|
||||||
|
@ -578,6 +586,7 @@ static void PRS(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
param.s_log_block_size =
|
param.s_log_block_size =
|
||||||
log2(size >> EXT2_MIN_BLOCK_LOG_SIZE);
|
log2(size >> EXT2_MIN_BLOCK_LOG_SIZE);
|
||||||
|
max = size * 8;
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
case 't': /* Check for bad blocks */
|
case 't': /* Check for bad blocks */
|
||||||
|
@ -602,12 +611,6 @@ static void PRS(int argc, char *argv[])
|
||||||
"Illegal number for blocks per group");
|
"Illegal number for blocks per group");
|
||||||
exit(1);
|
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) {
|
if ((param.s_blocks_per_group % 8) != 0) {
|
||||||
com_err(program_name, 0,
|
com_err(program_name, 0,
|
||||||
"blocks per group must be multiple of 8");
|
"blocks per group must be multiple of 8");
|
||||||
|
@ -647,6 +650,9 @@ static void PRS(int argc, char *argv[])
|
||||||
case 'r':
|
case 'r':
|
||||||
param.s_rev_level = atoi(optarg);
|
param.s_rev_level = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
|
case 's':
|
||||||
|
sparse_option = atoi(optarg);
|
||||||
|
break;
|
||||||
#ifdef EXT2_DYNAMIC_REV
|
#ifdef EXT2_DYNAMIC_REV
|
||||||
case 'I':
|
case 'I':
|
||||||
param.s_inode_size = atoi(optarg);
|
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
|
* 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
|
* Calculate number of blocks to reserve
|
||||||
*/
|
*/
|
||||||
param.s_r_blocks_count = (param.s_blocks_count * reserved_ratio) / 100;
|
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[])
|
int main (int argc, char *argv[])
|
||||||
|
|
|
@ -31,6 +31,9 @@ tune2fs \- adjust tunable filesystem parameters on second extended filesystems
|
||||||
.I reserved-blocks-count
|
.I reserved-blocks-count
|
||||||
]
|
]
|
||||||
[
|
[
|
||||||
|
.B -s sparse-super-flag
|
||||||
|
]
|
||||||
|
[
|
||||||
.B -u
|
.B -u
|
||||||
.I user
|
.I user
|
||||||
]
|
]
|
||||||
|
@ -97,6 +100,10 @@ adjust the reserved blocks percentage on the given device.
|
||||||
.I -r reserved-blocks-count
|
.I -r reserved-blocks-count
|
||||||
adjust the reserved blocks count on the given device.
|
adjust the reserved blocks count on the given device.
|
||||||
.TP
|
.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
|
.I -u user
|
||||||
set the user who can benefit from the reserved blocks.
|
set the user who can benefit from the reserved blocks.
|
||||||
.I user
|
.I user
|
||||||
|
|
|
@ -63,6 +63,7 @@ int L_flag = 0;
|
||||||
int m_flag = 0;
|
int m_flag = 0;
|
||||||
int M_flag = 0;
|
int M_flag = 0;
|
||||||
int r_flag = 0;
|
int r_flag = 0;
|
||||||
|
int s_flag = -1;
|
||||||
int u_flag = 0;
|
int u_flag = 0;
|
||||||
int U_flag = 0;
|
int U_flag = 0;
|
||||||
int max_mount_count, mount_count;
|
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] "
|
fprintf (stderr, "Usage: %s [-c max-mounts-count] [-e errors-behavior] "
|
||||||
"[-g group]\n"
|
"[-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[-r reserved-blocks-count] [-u user] [-C mount-count]\n"
|
||||||
"\t[-L volume-label] [-M last-mounted-dir] [-U UUID] "
|
"\t[-L volume-label] [-M last-mounted-dir] [-U UUID] "
|
||||||
"device\n", program_name);
|
"device\n", program_name);
|
||||||
|
@ -117,7 +118,7 @@ void main (int argc, char ** argv)
|
||||||
if (argc && *argv)
|
if (argc && *argv)
|
||||||
program_name = *argv;
|
program_name = *argv;
|
||||||
initialize_ext2_error_table();
|
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)
|
switch (c)
|
||||||
{
|
{
|
||||||
case 'c':
|
case 'c':
|
||||||
|
@ -253,6 +254,10 @@ void main (int argc, char ** argv)
|
||||||
r_flag = 1;
|
r_flag = 1;
|
||||||
open_flag = EXT2_FLAG_RW;
|
open_flag = EXT2_FLAG_RW;
|
||||||
break;
|
break;
|
||||||
|
case 's':
|
||||||
|
s_flag = atoi(optarg);
|
||||||
|
open_flag = EXT2_FLAG_RW;
|
||||||
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
resuid = strtoul (optarg, &tmp, 0);
|
resuid = strtoul (optarg, &tmp, 0);
|
||||||
if (*tmp)
|
if (*tmp)
|
||||||
|
@ -355,6 +360,48 @@ void main (int argc, char ** argv)
|
||||||
printf ("Setting reserved blocks count to %lu\n",
|
printf ("Setting reserved blocks count to %lu\n",
|
||||||
reserved_blocks);
|
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)
|
if (u_flag)
|
||||||
#ifdef EXT2_DEF_RESUID
|
#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>
|
Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o <tytso@mit.edu>
|
||||||
|
|
||||||
* Release of E2fsprogs version 1.07
|
* Release of E2fsprogs version 1.07
|
||||||
|
|
|
@ -8,18 +8,28 @@ if [ -f $test_dir/setup ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$class"x = x ]; then
|
if [ "$class"x = x ]; then
|
||||||
class=`echo $test_name | sed -e 's/r_\([^_]*\)_\(.*\)/\1/'`
|
class=`echo $test_name | sed -e 's/e_\([^_]*\)_\(.*\)/\1/'`
|
||||||
instance=`echo $test_name | sed -e 's/r_\([^_]*\)_\(.*\)/\2/'`
|
instance=`echo $test_name | sed -e 's/e_\([^_]*\)_\(.*\)/\2/'`
|
||||||
fi
|
fi
|
||||||
if [ "$OUT"x = x ]; then
|
if [ "$OUT"x = x ]; then
|
||||||
OUT=$test_name.log
|
OUT=$test_name.log
|
||||||
fi
|
fi
|
||||||
if [ "$EXPECT"x = x ]; then
|
if [ "$EXPECT"x = x ]; then
|
||||||
EXPECT=$SRCDIR/progs/rel_test/expect.$class
|
EXPECT=$SRCDIR/progs/test_data/expect.$class
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cat $SRCDIR/progs/rel_test/$instance.setup $SRCDIR/progs/rel_test/test.$class \
|
if [ "$class" = irel ]; then
|
||||||
| $TEST_REL -f - > $OUT 2>&1
|
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
|
cmp -s $EXPECT $OUT
|
||||||
status=$?
|
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.
|
Filesystem did not have a UUID; generating one.
|
||||||
|
|
||||||
Pass 1: Checking inodes, blocks, and sizes
|
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.
|
File /foo (inode #12, mod time Thu Apr 28 17:57:53 1994)
|
||||||
Block #2 (4) overlaps filesystem metadata in inode 12. CLEARED.
|
has 3 duplicate block(s), shared with 1 file(s):
|
||||||
Block #3 (6) overlaps filesystem metadata in inode 12. CLEARED.
|
<filesystem metadata>
|
||||||
Inode 12, i_size is 4096, should be 1024. Fix? yes
|
Clone duplicate/bad blocks? yes
|
||||||
|
|
||||||
Inode 12, i_blocks is 8, should be 2. Fix? yes
|
|
||||||
|
|
||||||
Pass 2: Checking directory structure
|
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 3: Checking directory connectivity
|
||||||
Pass 4: Checking reference counts
|
Pass 4: Checking reference counts
|
||||||
|
|
|
@ -1,12 +1,18 @@
|
||||||
Filesystem did not have a UUID; generating one.
|
Filesystem did not have a UUID; generating one.
|
||||||
|
|
||||||
Pass 1: Checking inodes, blocks, and sizes
|
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 2: Checking directory structure
|
||||||
Pass 3: Checking directory connectivity
|
Pass 3: Checking directory connectivity
|
||||||
|
@ -15,9 +21,7 @@ Pass 5: Checking group summary information
|
||||||
Fix summary information? yes
|
Fix summary information? yes
|
||||||
|
|
||||||
Block bitmap differences: -29 -30 -31. FIXED
|
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: ***** 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
|
Exit status is 1
|
||||||
|
|
|
@ -3,5 +3,5 @@ Pass 2: Checking directory structure
|
||||||
Pass 3: Checking directory connectivity
|
Pass 3: Checking directory connectivity
|
||||||
Pass 4: Checking reference counts
|
Pass 4: Checking reference counts
|
||||||
Pass 5: Checking group summary information
|
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
|
Exit status is 0
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
Note: if there is several inode or block bitmap blocks
|
Note: if there is several inode or block bitmap blocks
|
||||||
which require relocation, or one part of the inode table
|
which require relocation, or one part of the inode table
|
||||||
which must be moved, you may wish to try running e2fsck
|
which must be moved, you may wish to try running e2fsck
|
||||||
the '-b 8193' option first. The problem may lie only with
|
with the '-b 8193' option first. The problem may lie only
|
||||||
the primary block group descriptor, and the backup block
|
with the primary block group descriptor, and the backup
|
||||||
group descriptor may be OK.
|
block group descriptor may be OK.
|
||||||
|
|
||||||
Block bitmap for group 0 is not in group. (block 4096)
|
Block bitmap for group 0 is not in group. (block 4096)
|
||||||
Relocate? yes
|
Relocate? yes
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
Note: if there is several inode or block bitmap blocks
|
Note: if there is several inode or block bitmap blocks
|
||||||
which require relocation, or one part of the inode table
|
which require relocation, or one part of the inode table
|
||||||
which must be moved, you may wish to try running e2fsck
|
which must be moved, you may wish to try running e2fsck
|
||||||
the '-b 8193' option first. The problem may lie only with
|
with the '-b 8193' option first. The problem may lie only
|
||||||
the primary block group descriptor, and the backup block
|
with the primary block group descriptor, and the backup
|
||||||
group descriptor may be OK.
|
block group descriptor may be OK.
|
||||||
|
|
||||||
Inode bitmap for group 0 is not in group. (block 4000)
|
Inode bitmap for group 0 is not in group. (block 4000)
|
||||||
Relocate? yes
|
Relocate? yes
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
Note: if there is several inode or block bitmap blocks
|
Note: if there is several inode or block bitmap blocks
|
||||||
which require relocation, or one part of the inode table
|
which require relocation, or one part of the inode table
|
||||||
which must be moved, you may wish to try running e2fsck
|
which must be moved, you may wish to try running e2fsck
|
||||||
the '-b 8193' option first. The problem may lie only with
|
with the '-b 8193' option first. The problem may lie only
|
||||||
the primary block group descriptor, and the backup block
|
with the primary block group descriptor, and the backup
|
||||||
group descriptor may be OK.
|
block group descriptor may be OK.
|
||||||
|
|
||||||
Inode table for group 0 is not in group. (block 40000)
|
Inode table for group 0 is not in group. (block 40000)
|
||||||
WARNING: SEVERE DATA LOSS POSSIBLE.
|
WARNING: SEVERE DATA LOSS POSSIBLE.
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
which require relocation, or one part of the inode table
|
which require relocation, or one part of the inode table
|
||||||
which must be moved, you may wish to try running e2fsck
|
which must be moved, you may wish to try running e2fsck
|
||||||
the '-b 8193' option first. The problem may lie only with
|
with the '-b 8193' option first. The problem may lie only
|
||||||
the primary block group descriptor, and the backup block
|
with the primary block group descriptor, and the backup
|
||||||
group descriptor may be OK.
|
block group descriptor may be OK.
|
||||||
|
|
||||||
test_filesys: Block bitmap for group 0 is not in group. (block 0)
|
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
|
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_REL_OBJS= test_rel.o test_rel_cmds.o
|
||||||
|
|
||||||
|
TEST_ICOUNT_OBJS= test_icount.o test_icount_cmds.o
|
||||||
|
|
||||||
SRCS= $(srcdir)/test_rel.c
|
SRCS= $(srcdir)/test_rel.c
|
||||||
|
|
||||||
LIBS= $(LIBEXT2FS) $(LIBSS) $(LIBCOM_ERR)
|
LIBS= $(LIBEXT2FS) $(LIBSS) $(LIBCOM_ERR)
|
||||||
|
@ -27,14 +29,21 @@ DEPLIBS= $(LIBEXT2FS) $(LIBSS) $(LIBCOM_ERR)
|
||||||
|
|
||||||
all:: $(PROGS)
|
all:: $(PROGS)
|
||||||
|
|
||||||
test_rel: $(TEST_REL_OBJS)
|
test_rel: $(TEST_REL_OBJS) $(DEPLIBS)
|
||||||
$(LD) $(ALL_LDFLAGS) -o test_rel $(TEST_REL_OBJS) $(LIBS)
|
$(LD) $(ALL_LDFLAGS) -o test_rel $(TEST_REL_OBJS) $(LIBS)
|
||||||
|
|
||||||
test_rel_cmds.c: test_rel_cmds.ct
|
test_rel_cmds.c: test_rel_cmds.ct
|
||||||
$(MK_CMDS) $(srcdir)/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:
|
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:
|
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;
|
return exit_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void main(int argc, char **argv)
|
void main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
|
|
@ -10,9 +10,12 @@ CHATTR=../misc/chattr
|
||||||
LSATTR=../misc/lsattr
|
LSATTR=../misc/lsattr
|
||||||
DEBUGFS=../debugfs/debugfs
|
DEBUGFS=../debugfs/debugfs
|
||||||
TEST_REL=../tests/progs/test_rel
|
TEST_REL=../tests/progs/test_rel
|
||||||
|
TEST_ICOUNT=../tests/progs/test_icount
|
||||||
LD_LIBRARY_PATH=../lib:../lib/ext2fs:../lib/e2p:../lib/et:../lib/ss
|
LD_LIBRARY_PATH=../lib:../lib/ext2fs:../lib/e2p:../lib/et:../lib/ss
|
||||||
TMPFILE=./test.img
|
TMPFILE=./test.img
|
||||||
export LD_LIBRARY_PATH
|
export LD_LIBRARY_PATH
|
||||||
TZ=GMT
|
TZ=GMT
|
||||||
export TZ
|
export TZ
|
||||||
|
LANG=C
|
||||||
|
export LANG
|
||||||
unset PAGER
|
unset PAGER
|
||||||
|
|
|
@ -9,7 +9,10 @@ else
|
||||||
TESTS=
|
TESTS=
|
||||||
for i
|
for i
|
||||||
do
|
do
|
||||||
TESTS="$TESTS $SRCDIR/$i"
|
case $i in
|
||||||
|
[a-zA-Z]) TESTS="$TESTS $SRCDIR/${i}_*" ;;
|
||||||
|
*) TESTS="$TESTS $SRCDIR/$i" ;;
|
||||||
|
esac
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue