Many files:

Checked in e2fsprogs-1.07
bitmap-optimize
Theodore Ts'o 1997-04-29 16:15:03 +00:00
parent f45a038dbe
commit 21c84b71e2
72 changed files with 10280 additions and 1403 deletions

View File

@ -1,6 +1,6 @@
#!/bin/sh
FILES=`find . -name ChangeLog`
FILES=`find . -name ChangeLog -print`
header=/tmp/revheader

4
.missing-copyright Normal file
View File

@ -0,0 +1,4 @@
#!/bin/sh
find . -type f \! -name \*~ \! -exec grep -q Begin-Header \{\} \; -print \
| grep -v ^./build

View File

@ -1,3 +1,16 @@
Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o <tytso@mit.edu>
* Release of E2fsprogs version 1.07
Wed Jan 15 11:37:36 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* config.sub (basic_machine): Added i686-* as another name for the
Pentium Pro.
Tue Oct 8 02:02:03 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* Release of E2fsprogs version 1.06
Mon Oct 7 08:22:31 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* Makefile.in (all): Don't run "make check" by default. User

View File

@ -9,7 +9,7 @@ system management programs, just follow the steps:
1) Install this tar file using the following command:
gunzip < e2fsprogs-1.04-dllbin.tar.gz | (cd /; tar xvf - )
gunzip < e2fsprogs-1.04-dllbin.tar.gz | (cd /; tar Sxvpf - )
2) Run ldconfig to update the shared library pointers.

View File

@ -9,7 +9,7 @@ system management programs, just follow the steps:
1) Install this tar file using the following command:
gunzip < e2fsprogs-1.04-elfbin.tar.gz | (cd /; tar xvf - )
gunzip < e2fsprogs-1.04-elfbin.tar.gz | (cd /; tar Sxvpf - )
2) Run ldconfig to update the shared library pointers.

View File

@ -17,6 +17,7 @@ man1dir = $(usr_prefix)/man/man1
man8dir = $(usr_prefix)/man/man8
cat1dir = $(usr_prefix)/man/cat1
cat8dir = $(usr_prefix)/man/cat8
infodir = $(usr_prefix)/info
@SET_MAKE@

View File

@ -8,18 +8,26 @@ INSTALL = @INSTALL@
@MCONFIG@
LIB_SUBDIRS=lib/et lib/ss lib/ext2fs lib/e2p lib/uuid
PROG_SUBDIRS=e2fsck debugfs misc
PROG_SUBDIRS=e2fsck debugfs misc tests/progs
SUBDIRS=$(LIB_SUBDIRS) $(PROG_SUBDIRS) tests
SUBS= include/linux/types.h
all:: $(SUBS) libs progs
TAR=tar
all:: $(SUBS) libs progs docs
progs: $(SUBS) all-progs-recursive
libs: $(SUBS) all-libs-recursive
docs:
(cd doc; make libext2fs.info)
install-doc-libs:
(cd doc; make install-doc-libs)
install: all-libs-recursive install-progs-recursive \
install-shlibs-libs-recursive
install-shlibs-libs-recursive install-doc-libs
(export MANPATH=$(DESTDIR)$(mandir); $(srcdir)/install-utils/compile_manpages)
install-libs: install-libs-recursive
@ -64,7 +72,7 @@ mostlyclean-local:
$(RM) -f \#* *~ core MAKELOG
clean-local: mostlyclean-local
distclean-local: clean-local
$(RM) -f include/linux/types.h
$(RM) -f include/linux/types.h $(SUBSTITUTE)
$(RM) -f config.status config.log config.cache MCONFIG Makefile
realclean-local: distclean-local
$(RM) -f configure
@ -78,7 +86,7 @@ distribution_tar_file:
cd ..
cp -r $(srcdir)/README $(srcdir)/install-utils /tmp/dest
cp $(srcdir)/INSTALL.@BINARY_TYPE@ /tmp/dest/INSTALL
(cd /tmp/dest; tar cf - . ) | gzip -9 \
(cd /tmp/dest; $(TAR) cf - . ) | gzip -9 \
> e2fsprogs-@E2FSPROGS_VERSION@-@BINARY_TYPE@.tar.gz
SRCROOT = `echo e2fsprogs-@E2FSPROGS_VERSION@ | sed -e 's/-WIP//'`
@ -87,14 +95,14 @@ $(srcdir)/.exclude-file:
(cd $(srcdir)/.. ; find $(SRCROOT) \( -name \*~ -o -name \*.orig \
-o -name \*.rej \) -print > $(SRCROOT)/.exclude-file)
echo "$(SRCROOT)/build" >> $(srcdir)/.exclude-file
echo "$(SRCROOT)/todo" >> $(srcdir)/.exclude-file
echo "$(SRCROOT)/rpm.log" >> $(srcdir)/.exclude-file
echo "$(SRCROOT)/.exclude-file" >> $(srcdir)/.exclude-file
echo $(SRCROOT)/e2fsprogs-@E2FSPROGS_VERSION@.tar.gz \
>> $(srcdir)/.exclude-file
source_tar_file: $(srcdir)/.exclude-file
(cd $(srcdir) ; tar -C .. -c -v -f - \
(cd $(srcdir) ; $(TAR) -C .. -c -v -f - \
-X .exclude-file $(SRCROOT) | \
gzip -9 > e2fsprogs-@E2FSPROGS_VERSION@.tar.gz)
rm -f $(srcdir)/.exclude-file

4
README
View File

@ -1,5 +1,5 @@
This is the new version (1.05) of the second extended file system
management programs, otherwise known as the Monomonac Release.
This is the new version (1.07) of the second extended file system
management programs.
See the file INSTALL for installation instructions. This is
important! Note that your /etc/fstab file may need modifying before

View File

@ -1,3 +1,125 @@
E2fsprogs 1.07 (March 9, 1997)
==============================
E2fsck is now uses much less memory when checking really large
filesystems (or rather, filesystems with a large number of inodes).
Previously a filesystem with 1 million inodes required 4 megabytes of
memory to store inode count statistics; that storage requirement has
now been reduced to roughly half a megabyte.
E2fsck can now properly deal with bad blocks appearing inside the
inode table. Instead of trying to relocate the inode table (which
often failed because there wasn't enough space), the inodes in the bad
block are marked as in use.
E2fsck will automatically try to use the backup superblocks if the
primary superblocks have a bad magic number or have missing meta-data
blocks (or meta-data blocks which are out of range).
E2fsck's pass 3 has been made more efficient; most noticeable on
filesystems with a very large number of directories.
Completely revamped e2fsck's system of printing problem reports. It
is now table driven, to make them more easily customizeable and
extendable. Error messages which can be printed out during preen mode
are now one line long.
Fixed e2fsck's filesystem swapping code so that it won't try to swap
fast symbolic links or deleted files.
Fixed e2fsck core dumping when fixing a filesystem which has no
directories (not even a root directory).
Added a check to e2fsck to make sure that the length of every
directory entry is a multiple of 4 (since the kernel complains if it
isn't).
Added a check to e2fsck to make sure that a directory entry isn't a
link to the root directory, since that isn't allowed.
Added a check to e2fsk to now make sure the '.' and '..' directory
entries are null terminated, since the 2.0 kernel requires it.
Added check to write_bitmaps() to make sure the superblock doesn't get
trashed if the inode or block bitmap is marked as being block zero.
Added checking of the new feature set fields in the superblock, to
avoid dealing with new filesystem features that this package wasn't
set up to handle.
Fixed a fencepost error in ext2fs_new_block() which would occasionally
try to allocate a block beyond the end of a filesystem.
When the UUID library picks a random IEEE 802 address (because it
can't find one from a network card), it sets the multicast bit, to
avoid conflicting with a legitimate IEEE 802 address.
Mke2fs now sets the root directory's owner to be the real uid of the
user running mke2fs. If the real uid is non-zero, it also sets
the group ownership of the root directory to be the real group-id of
the user running mke2fs.
Mke2fs now has more intelligent error checking when it is given a
non-existent device.
When badblocks is given the -vv option, it now updates the block that
it is currently testing on every block.
Fixed a bug in fsck where it wouldn't modify the PATH envirnoment
currently correctly if PATH wasn't already set.
Shared libraries now built with dependencies. This allows the shared
library files to be used with dlopen(); it also makes the transition
to libc 6 easier, since ld.so can tell which libc a particular shared
library expects to use.
Programmer's notes:
-------------------
Added new abstraction (defined in dblist.c) for maintaining a list of
blocks which belongs to directories. This is used in e2fsck and other
programs which need to iterate over all directories.
Added new functions which test to see if a contiguous range of blocks
(or inodes) are available. (ext2fs_*_bitmap_range).
Added new function (ext2_inode_has_valid_blocks) which returns true if
an inode has valid blocks. (moved from e2fsck code).
Added new function (ext2fs_allocate_tables) which allocates the
meta-data blocks as part of initializing a filesystem. (moved from
mke2fs code).
Added a new I/O manager for testing purposes. It will either allow a
program to intercept I/O requests, or print debugging messages to
trace the activity of a program using the I/O manager.
The badblocks_list functions now store the bad blocks in a sorted
order, and use a binary search to speed up badblocks_list_test.
The inode scan function ext2fs_get_next_inode() may now return a soft
error returns: MISSING_INODE_TABLE and BAD_BLOCK_IN_INODE_TABLE in
those cases where part of an inode table is missing or there is a bad
block in the inode table.
Added a new function (ext2fs_block_iterate2) which adds new arguments to
the callback function to return a pointer (block and offset) to the
reference of the block.
Added new function (ext2fs_inode_scan_goto_blockgroup) which allows an
application to jump to a particular block group while doing an inode
scan.
The badblocks list functions were renamed from badblocks_* to
ext2fs_badblocks_*. Backwards compatibility functions are available
for now, but programs should be modified to use the new interface.
Some of the library functions were reorganized into separate files to
reduce the size of some programs which statically link against the
ext2 library.
Put in some miscellaneous fixes for the Alpha platform.
E2fsprogs 1.06 (October 7, 1996)
================================

8
SHLIBS
View File

@ -25,3 +25,11 @@ Maintainer: Theodore Ts'o
Email: tytso@mit.edu
Start: 0x66980000
End: 0x669fffff
Library:libuuid.so
Description: DCE Universally Unique ID (UUID) library
Maintainer: Theodore Ts'o
Email: tytso@mit.edu
Start: 0x67900000
End: 0x679fffff

2
config.sub vendored
View File

@ -422,7 +422,7 @@ case $basic_machine in
# We don't have specific support for the Intel Pentium (p6) followon yet, so just call it a Pentium
basic_machine=i586-intel
;;
pentium-* | p5-* | p6-*)
pentium-* | p5-* | p6-* | i686-* )
# We don't have specific support for the Intel Pentium (p6) followon yet, so just call it a Pentium
basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
;;

720
configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -505,4 +505,4 @@ test -d include/linux || mkdir include/linux
AC_OUTPUT(MCONFIG lib/substitute_sh Makefile lib/et/Makefile
lib/ss/Makefile lib/ext2fs/Makefile lib/e2p/Makefile lib/uuid/Makefile
misc/Makefile e2fsck/Makefile debugfs/Makefile tests/Makefile
relocate/Makefile)
tests/progs/Makefile doc/Makefile)

View File

@ -1,3 +1,15 @@
Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o <tytso@mit.edu>
* Release of E2fsprogs version 1.07
Wed Jan 1 23:53:26 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* lsdel.c (do_lsdel): Use time_to_string() instead of ctime().
Tue Oct 8 02:02:03 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* Release of E2fsprogs version 1.06
Thu Sep 12 15:23:07 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* Release of E2fsprogs version 1.05

View File

@ -73,8 +73,8 @@ distclean: clean
# Makefile dependencies follow. This must be the last section in
# the Makefile.in file
#
debug_cmds.o: debug_cmds.c $(top_builddir)/lib/ss/ss_err.h \
$(top_srcdir)/lib/ss/ss.h $(top_srcdir)/lib/ss/copyright.h
debug_cmds.o: debug_cmds.c $(top_srcdir)/lib/ss/ss.h \
$(top_srcdir)/lib/ss/copyright.h $(top_builddir)/lib/ss/ss_err.h
debugfs.o: $(srcdir)/debugfs.c $(top_srcdir)/lib/et/com_err.h \
$(top_srcdir)/lib/ss/ss.h $(top_srcdir)/lib/ss/copyright.h \
$(top_builddir)/lib/ss/ss_err.h $(srcdir)/debugfs.h \
@ -101,3 +101,4 @@ dump.o: $(srcdir)/dump.c $(srcdir)/debugfs.h \
$(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
$(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(top_srcdir)/lib/ext2fs/bitops.h

View File

@ -10,9 +10,12 @@ request do_show_debugfs_params, "Show debugfs parameters",
request do_open_filesys, "Open a filesystem",
open_filesys, open;
request do_close_filesys, "Close a filesystem",
request do_close_filesys, "Close the filesystem",
close_filesys, close;
request do_dirty_filesys, "Mark the filesystem as dirty",
dirty_filesys, dirty;
request do_init_filesys, "Initalize a filesystem (DESTROYS DATA)",
init_filesys;

View File

@ -248,6 +248,14 @@ void do_show_super_stats(int argc, char *argv[])
close_pager(out);
}
void do_dirty_filesys(int argc, char *argv[])
{
if (check_fs_open(argv[0]))
return;
ext2fs_mark_super_dirty(current_fs);
}
struct list_blocks_struct {
FILE *f;
int total;
@ -565,7 +573,7 @@ static void modify_u8(char *com, const char *prompt,
const char *format, __u8 *val)
{
char buf[200];
u_char v;
unsigned long v;
char *tmp;
sprintf(buf, format, *val);
@ -575,7 +583,7 @@ static void modify_u8(char *com, const char *prompt,
buf[strlen (buf) - 1] = '\0';
if (!buf[0])
return;
v = strtol(buf, &tmp, 0);
v = strtoul(buf, &tmp, 0);
if (*tmp)
com_err(com, 0, "Bad value - %s", buf);
else
@ -586,7 +594,7 @@ static void modify_u16(char *com, const char *prompt,
const char *format, __u16 *val)
{
char buf[200];
u_short v;
unsigned long v;
char *tmp;
sprintf(buf, format, *val);
@ -596,7 +604,7 @@ static void modify_u16(char *com, const char *prompt,
buf[strlen (buf) - 1] = '\0';
if (!buf[0])
return;
v = strtol(buf, &tmp, 0);
v = strtoul(buf, &tmp, 0);
if (*tmp)
com_err(com, 0, "Bad value - %s", buf);
else
@ -607,7 +615,7 @@ static void modify_u32(char *com, const char *prompt,
const char *format, __u32 *val)
{
char buf[200];
u_long v;
unsigned long v;
char *tmp;
sprintf(buf, format, *val);
@ -617,7 +625,7 @@ static void modify_u32(char *com, const char *prompt,
buf[strlen (buf) - 1] = '\0';
if (!buf[0])
return;
v = strtol(buf, &tmp, 0);
v = strtoul(buf, &tmp, 0);
if (*tmp)
com_err(com, 0, "Bad value - %s", buf);
else

View File

@ -173,7 +173,7 @@ void do_lsdel(int argc, char **argv)
printf("%6lu %6d %6o %6lu %4d/%4d %s", delarray[i].ino,
delarray[i].uid, delarray[i].mode, delarray[i].size,
delarray[i].free_blocks, delarray[i].num_blocks,
ctime(&delarray[i].dtime));
time_to_string(delarray[i].dtime));
}
error_out:

59
doc/Makefile.in Normal file
View File

@ -0,0 +1,59 @@
#
# Makefile for the doc directory
#
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
top_builddir = ..
my_dir = doc
INSTALL = @INSTALL@
@MCONFIG@
DVI=texi2dvi
DVIPS=dvips -o "$@"
INFO=makeinfo
HTML=texi2html
RM=/bin/rm -rf
all:: libext2fs.info libext2fs.dvi
install-doc-libs:
$(RM) $(DESTDIR)$(infodir)/libext2fs.info*.gz
$(top_srcdir)/mkinstalldirs $(DESTDIR)$(infodir)
for i in libext2fs.info* ; do \
$(INSTALL_DATA) $$i $(DESTDIR)$(infodir)/$$i ; \
done
gzip -9 $(DESTDIR)$(infodir)/libext2fs.info*
libext2fs.info: $(srcdir)/libext2fs.texinfo
$(INFO) $(srcdir)/libext2fs.texinfo
libext2fs.dvi: $(srcdir)/libext2fs.texinfo
$(DVI) $(srcdir)/libext2fs.texinfo
.PHONY: clean
clean:: clean-all
.PHONY: clean-all
clean-all:: clean-tex clean-backup clean-final clean-tarfiles
.PHONY: clean-final
clean-final::
$(RM) *.ps *.info *.info-? *.html
.PHONY: clean-tex
clean-tex::
$(RM) *.aux *.cp *.dvi *.fn *.ky *.log *.pg *.toc *.tp *.vr *.fns
.PHONY: clean-backup
clean-backup::
$(RM) *~ #*
.PHONY: clean-tarfiles
clean-tarfiles::
$(RM) *.tar *.tar.gz *.tgz

929
doc/libext2fs.texinfo Normal file
View File

@ -0,0 +1,929 @@
\input texinfo @c -*-texinfo-*-
@c %**start of header
@setfilename libext2fs.info
@settitle The EXT2FS Library (version 1.07)
@synindex tp fn
@comment %**end of header
@ifinfo
@format
START-INFO-DIR-ENTRY
* libext2fs: (libext2fs.info). The EXT2FS library.
END-INFO-DIR-ENTRY
@end format
@end ifinfo
@c smallbook
@iftex
@finalout
@end iftex
@c Note: the edition number is listed in *three* places; please update
@c all three. Also, update the month and year where appropriate.
@c ==> Update edition number for settitle and subtitle, and in the
@c ==> following paragraph; update date, too.
@ifinfo
This file documents the ext2fs library, a library for manipulating the
ext2 filesystem.
Copyright (C) 1997 Theodore Ts'o
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
are preserved on all copies.
@ignore
Permission is granted to process this file through TeX and print the
results, provided the printed document carries copying permission
notice identical to this one except for the removal of this paragraph
(this paragraph not being relevant to the printed manual).
@end ignore
Permission is granted to copy and distribute modified versions of this
manual under the conditions for verbatim copying, provided that the entire
resulting derived work is distributed under the terms of a permission
notice identical to this one.
Permission is granted to copy and distribute translations of this manual
into another language, under the above conditions for modified versions,
except that this permission notice may be stated in a translation approved
by the author.
@end ifinfo
@setchapternewpage on
@titlepage
@c use the new format for titles
@title The EXT2FS Library
@subtitle The EXT2FS Library
@subtitle Version 1.07
@subtitle February 1997
@author by Theodore Ts'o
@c Include the Distribution inside the titlepage so
@c that headings are turned off.
@tex
\global\parindent=0pt
\global\parskip=8pt
\global\baselineskip=13pt
@end tex
@page
@vskip 0pt plus 1filll
Copyright @copyright{} 1997 Theodore Ts'o
@sp 2
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
are preserved on all copies.
Permission is granted to copy and distribute modified versions of this
manual under the conditions for verbatim copying, provided that the entire
resulting derived work is distributed under the terms of a permission
notice identical to this one.
Permission is granted to copy and distribute translations of this manual
into another language, under the above conditions for modified versions,
except that this permission notice may be stated in a translation approved
by the Foundation.
@end titlepage
@headings double
@ifinfo
@node Top, Introduction to the EXT2FS Library, (dir), (dir)
@top The EXT2FS Library
This manual documents the EXT2FS Library, version 1.07.
@end ifinfo
@menu
* Introduction to the EXT2FS Library::
* EXT2FS Library Functions::
* Concept Index::
* Function Index::
@end menu
@c ----------------------------------------------------------------------
@node Introduction to the EXT2FS Library, EXT2FS Library Functions, Top, Top
@comment node-name, next, previous, up
@chapter Introduction to the EXT2FS Library
The EXT2FS library is designed to allow user-level programs to
manipulate an ext2 filesystem.
@node EXT2FS Library Functions, Concept Index, Introduction to the EXT2FS Library, Top
@comment node-name, next, previous, up
@chapter EXT2FS Library Functions
@menu
* Filesystem-level functions::
* Inode Functions::
* Directory functions::
* Bitmap Functions::
* Badblocks list management::
* Directory-block list management::
* Byte-swapping functions::
* Other functions::
@end menu
@c ----------------------------------------------------------------------
@node Filesystem-level functions, Inode Functions, EXT2FS Library Functions, EXT2FS Library Functions
@comment node-name, next, previous, up
@section Filesystem-level functions
The following functions operate on a filesystem handle. Most EXT2FS
Library functions require a filesystem handle as their first argument.
There are two functions which create a filesystem handle,
@code{ext2fs_open} and @code{ext2fs_initialize}.
The filesystem can also be closed using @code{ext2fs_close}, and any
changes to the superblock and group descripts can be written out to disk
using @code{ext2fs_flush}.
@menu
* Opening an ext2 filesystem::
* Closing and flushing out changes::
* Initializing a filesystem::
* Filesystem flag functions::
@end menu
@c ----------------------------------------------------------------------
@node Opening an ext2 filesystem, Closing and flushing out changes, Filesystem-level functions, Filesystem-level functions
@comment node-name, next, previous, up
@subsection Opening an ext2 filesystem
Most libext2fs functions take a filesystem handle of type
@code{ext2_filsys}. A filesystem handle is created either by opening
an existing function using @code{ext2fs_open}, or by initializing a new
filesystem using @code{ext2fs_initialize}.
@deftypefun errcode_t ext2fs_open (const char *@var{name}, int @var{flags}, int @var{superblock}, int @var{block_size}, io_manager @var{manager}, ext2_filsys *@var{ret_fs})
Opens a filesystem named @var{name}, using the the io_manager
@var{manager} to define the input/output routines needed to read and
write the filesystem. In the case of the @code{unix_io} io_manager,
@var{name} is interpreted as the Unix filename of the filesystem image.
This is often a device file, such as @file{/dev/hda1}.
The @var{superblock} parameter specifies the block number of the
superblock which should be used when opening the filesystem.
If @var{superblock} is zero, @code{ext2fs_open} will use the primary
superblock located at offset 1024 bytes from the start of the filesystem
image.
The @var{block_size} parameter specifies the block size used by the
filesystem. Normally this is determined automatically from the
filesystem uperblock. If @var{block_size} is non-zero, it must match
the block size found in the superblock, or the error
@code{EXT2_ET_UNEXPECTED_BLOCK_SIZE} will be returned. The
@var{block_size} parameter is also used to help fund the superblock when
@var{superblock} is non-zero.
The @var{flags} argument contains a bitmask of flags which control how
the filesystem open should be handled.
@table @code
@item EXT2_FLAG_RW
Open the filesystem for reading and writing. Without this flag, the
filesystem is opened for reading only.
@item EXT2_FLAG_FORCE
Open the filesystem regardless of the feature sets listed in the
superblock.
@end table
@end deftypefun
@c ----------------------------------------------------------------------
@node Closing and flushing out changes, Initializing a filesystem, Opening an ext2 filesystem, Filesystem-level functions
@comment node-name, next, previous, up
@subsection Closing and flushing out changes
@deftypefun errcode_t ext2fs_flush (ext2_filsys @var{fs})
Write any changes to the high-level filesystem data structures in the
@var{fs} filesystem. The following data structures will be written out:
@itemize @bullet
@item The filesystem superblock
@item The filesystem group descriptors
@item The filesystem bitmaps, if read in via @code{ext2fs_read_bitmaps}.
@end itemize
@end deftypefun
@deftypefun void ext2fs_free (ext2_filsys @var{fs})
Close the io_manager abstraction for @var{fs} and release all memory
associated with the filesystem handle.
@end deftypefun
@deftypefun errcode_t ext2fs_close (ext2_filsys @var{fs})
Flush out any changes to the high-level filesystem data structures using
@code{ext2fs_flush} if the filesystem is marked dirty; then close and
free the filesystem using @code{ext2fs_free}.
@end deftypefun
@c ----------------------------------------------------------------------
@node Initializing a filesystem, Filesystem flag functions, Closing and flushing out changes, Filesystem-level functions
@comment node-name, next, previous, up
@subsection Initializing a filesystem
An ext2 filesystem is initializing by the @code{mke2fs} program. The
two functions described here, @code{ext2fs_initialize} and
@code{ext2fs_allocate_tables} do much of the initial work for setting up
a filesystem. However, they don't do the whole job. @code{mke2fs}
calls @code{ext2fs_initialize} to set up the filesystem superblock, and
calls @code{ext2fs_allocate_tables} to allocate space for the inode
table, and the inode and block bitmaps. In addition, @code{mke2fs} must
also initialize the inode tables by clearing them with zeros, create the
root and lost+found directories, and reserve the reserved inodes.
@deftypefun errcode_t ext2fs_initialize (const char *@var{name}, int @var{flags}, struct ext2_super_block *@var{param}, io_manager @var{manager}, ext2_filsys *@var{ret_fs})
This function is used by the @code{mke2fs} program to initialize a
filesystem. The @code{ext2fs_initialize} function creates a filesystem
handle which is returned in @var{ret_fs} that has been properly setup
for a filesystem to be located in @var{name}, using the io_manager
@var{manager}. The prototype superblock in @var{param} is used to
supply parameters such as the number of blocks in the filesystem, the
block size, etc.
The @code{ext2fs_initialize} function does not actually do any I/O; that
will be done when the application program calls @code{ext2fs_close} or
@code{ext2fs_flush}. Also, this function only initializes the
superblock and group descriptor structures. It does not create the
inode table or the root directory. This must be done by the calling
application, such as @code{mke2fs}.
The following values may be set in the @var{param} prototype superblock;
if a value of 0 is found in a field, @code{ext2fs_initialize} will use a
default value. The calling application should zero out the prototype
entire superblock, and then fill in any appropriate values.
@table @code
@item s_blocks_count
The number of blocks in the filesystem. This parameter is mandatory and
must be set by the calling application.
@item s_inodes_count
The number of inodes in the filesystem. The
default value is determined by calculating the size of the filesystem,
and creating one inode for every 4096 bytes.
@item s_r_blocks_count
The number of blocks which should be reserved for the superuser. The
default value is zero blocks.
@item s_log_block_size
The blocksize of the filesystem. Valid values are 0 (1024 bytes), 1
(2048 bytes), or 2 (4096 bytes). The default blocksize is 1024 bytes.
@item s_log_frag_size
The size of fragments. The ext2 filesystem does not support fragments
(and may never support fragments). Currently this field must be the
same as @code{s_log_block_size}.
@item s_first_data_block
The first data block for the filesystem. For filesystem with a
blocksize of 1024 bytes, this value must be at least 1, since the
superblock is located in block number 1. For filesystems with larger
blocksizes, the superblock is still located at an offset of 1024 bytes,
so the superblock is located in block number 0. By default, this value
is set to 1 for filesystems with a block size of 1024 bytes, or 0 for
filesystems with larger blocksizes.
@item s_max_mnt_count
This field defines the number of times that the filesystem can be
mounted before it should be checked using @code{e2fsck}. When
@code{e2fsck} is run without the @samp{-f} option, @code{e2fsck} will
skip the filesystem check if the number of times that the filesystem has
been mounted is less than @code{s_max_mnt_count} and if the interval
between the last time a filesystem check was performed and the current
time is less than @code{s_checkinterval} (see below). The default value
of @code{s_max_mnt_count} is 20.
@item s_checkinterval
This field defines the minimal interval between filesystem checks. See
the previous entry for a discussion of how this field is used by
@code{e2fsck}. The default value of this field is 180 days (six
months).
@item s_errors
This field defines the behavior which should be used by the kernel of
errors are detected in the filesystem. Possible values include:
@table @samp
@item EXT2_ERRORS_CONTINUE
Continue execution when errors are detected.
@item EXT2_ERRORS_RO
Remount the filesystem read-only.
@item EXT2_ERRORS_PANIC
Panic.
@end table
The default behavior is @samp{EXT2_ERRORS_CONTINUE}.
@end table
@end deftypefun
@deftypefun errcode_t ext2fs_allocate_tables (ext2_filsys @var{fs})
Allocate space for the inode table and the block and inode bitmaps. The
inode tables and block and inode bitmaps aren't actually initialized;
this function just allocates the space for them.
@end deftypefun
@c ----------------------------------------------------------------------
@node Filesystem flag functions, , Initializing a filesystem, Filesystem-level functions
@comment node-name, next, previous, up
@subsection Filesystem flag functions
The filesystem handle has a number of flags which can be manipulated
using the following function. Some of these flags affect how the
libext2fs filesystem behaves; others are provided solely for the
application's convenience.
@deftypefun void ext2fs_mark_changed (ext2_filsys @var{fs})
@deftypefunx int ext2fs_test_changed (ext2_filsys @var{fs})
This flag indicates whether or not the filesystem has been changed.
It is not used by the ext2fs library.
@end deftypefun
@deftypefun void ext2fs_mark_super_dirty (ext2_filsys @var{fs})
Mark the filesystem @var{fs} as being dirty; this will cause
the superblock information to be flushed out when @code{ext2fs_close} is
called. @code{ext2fs_mark_super_dirty} will also set the filesystem
changed flag. The dirty flag is automatically cleared by
@code{ext2fs_flush} when the superblock is written to disk.
@end deftypefun
@deftypefun void ext2fs_mark_valid (ext2_filsys @var{fs})
@deftypefunx void ext2fs_unmark_valid (ext2_filsys @var{fs})
@deftypefunx int ext2fs_test_valid (ext2_filsys @var{fs})
This flag indicates whether or not the filesystem is free of errors.
It is not used by libext2fs, and is solely for the application's
convenience.
@end deftypefun
@deftypefun void ext2fs_mark_ib_dirty (ext2_filsys @var{fs})
@deftypefunx void ext2fs_mark_bb_dirty (ext2_filsys @var{fs})
@deftypefunx int ext2fs_test_ib_dirty (ext2_filsys @var{fs})
@deftypefunx int ext2fs_test_bb_dirty (ext2_filsys @var{fs})
These flags indicate whether or not the inode or block bitmaps have been
modified. If the flag is set, it will cause the appropriate bitmap
to be written when the filesystem is closed or flushed.
@end deftypefun
@c ----------------------------------------------------------------------
@node Inode Functions, Directory functions, Filesystem-level functions, EXT2FS Library Functions
@comment node-name, next, previous, up
@section Inode Functions
@menu
* Reading and writing inodes::
* Iterating over inodes in a filesystem::
* Iterating over blocks in an inode::
* Inode Convenience Functions::
@end menu
@c ----------------------------------------------------------------------
@node Reading and writing inodes, Iterating over inodes in a filesystem, Inode Functions, Inode Functions
@comment node-name, next, previous, up
@subsection Reading and writing inodes
@deftypefun errcode_t ext2fs_read_inode (ext2_filsys @var{fs}, ino_t @var{ino}, struct ext2_inode *@var{inode})
Read the inode number @var{ino} into @var{inode}.
@end deftypefun
@deftypefun errcode_t ext2fs_write_inode(ext2_filsys @var{fs}, ino_t @var{ino}, struct ext2_inode *@var{inode})
Write @var{inode} to inode @var{ino}.
@end deftypefun
@c ----------------------------------------------------------------------
@node Iterating over inodes in a filesystem, Iterating over blocks in an inode, Reading and writing inodes, Inode Functions
@comment node-name, next, previous, up
@subsection Iterating over inodes in a filesystem
The inode_scan abstraction is useful for iterating over all the inodes
in a filesystem.
@deftypefun errcode_t ext2fs_open_inode_scan (ext2_filsys @var{fs}, int @var{buffer_blocks}, ext2_inode_scan *@var{scan})
Initialize the iteration variable @var{scan}. This variable is used by
@code{ext2fs_get_next_inode}. The @var{buffer_blocks} parameter
controls how many blocks of the inode table are read in at a time. A
large number of blocks requires more memory, but reduces the overhead in
seeking and reading from the disk. If @var{buffer_blocks} is zero, a
suitable default value will be used.
@end deftypefun
@deftypefun void ext2fs_close_inode_scan (ext2_inode_scan @var{scan})
Release the memory associated with @var{scan} and invalidate it.
@end deftypefun
@deftypefun errcode_t ext2fs_get_next_inode (ext2_inode_scan @var{scan}, ino_t *@var{ino}, struct ext2_inode *@var{inode})
This function returns the next inode from the filesystem; the inode
number of the inode is stored in @var{ino}, and the inode is stored in
@var{inode}.
If the inode is located in a block that has been marked as bad,
@code{ext2fs_get_next_inode} will return the error
@code{EXT2_ET_BAD_BLOCK_IN_INODE_TABLE}.
@end deftypefun
@deftypefun errcode_t ext2fs_inode_scan_goto_blockgroup (ext2_inode_scan @var{scan}, int @var{group})
Start the inode scan at a particular ext2 blockgroup, @var{group}.
This function may be safely called at any time while @var{scan} is valid.
@end deftypefun
@deftypefun void ext2fs_set_inode_callback (ext2_inode_scan @var{scan}, errcode_t (*done_group)(ext2_filsys @var{fs}, ext2_inode_scan @var{scan}, dgrp_t @var{group}, void * @var{private}), void *@var{done_group_data})
Register a callback function which will be called by
@code{ext2_get_next_inode} when all of the inodes in a block group have
been processed.
@end deftypefun
@deftypefun int ext2fs_inode_scan_flags (ext2_inode_scan @var{scan}, int @var{set_flags}, int @var{clear_flags})
Set the scan_flags @var{set_flags} and clear the scan_flags @var{clear_flags}.
The following flags can be set using this interface:
@table @samp
@item EXT2_SF_SKIP_MISSING_ITABLE
When a block group is missing an inode table, skip it. If this flag is
not set @code{ext2fs_get_next_inode} will return the error
EXT2_ET_MISSING_INODE_TABLE.
@end table
@end deftypefun
@c ----------------------------------------------------------------------
@node Iterating over blocks in an inode, Inode Convenience Functions, Iterating over inodes in a filesystem, Inode Functions
@comment node-name, next, previous, up
@subsection Iterating over blocks in an inode
@deftypefun errcode_t ext2fs_block_iterate (ext2_filsys @var{fs}, ino_t @var{ino}, int @var{flags}, char *block_buf, int (*func)(ext2_filsys @var{fs}, blk_t *@var{blocknr}, int @var{blockcnt}, void *@var{private}), void *@var{private})
@end deftypefun
@deftypefun errcode_t ext2fs_block_iterate2 (ext2_filsys @var{fs}, ino_t @var{ino}, int @var{flags}, char *@var{block}_buf, int (*func)(ext2_filsys @var{fs}, blk_t *@var{blocknr}, int @var{blockcnt}, blk_t @var{ref_blk}, int @var{ref_offset}, void *@var{private}), void *@var{private})
@end deftypefun
@c ----------------------------------------------------------------------
@node Inode Convenience Functions, , Iterating over blocks in an inode, Inode Functions
@comment node-name, next, previous, up
@subsection Convenience functions for Inodes
@deftypefun errcode_t ext2fs_get_blocks (ext2_filsys @var{fs}, ino_t @var{ino}, blk_t *@var{blocks})
@end deftypefun
@deftypefun errcode_t ext2fs_check_directory (ext2_filsys @var{fs}, ino_t @var{ino})
@end deftypefun
@c ----------------------------------------------------------------------
@node Directory functions, Bitmap Functions, Inode Functions, EXT2FS Library Functions
@comment node-name, next, previous, up
@section Directory functions
@menu
* Directory block functions::
* Iterating over a directory::
* Creating and expanding directories::
* Creating and removing directory entries::
* Looking up filenames::
* Translating inode numbers to filenames::
@end menu
@c ----------------------------------------------------------------------
@node Directory block functions, Iterating over a directory, Directory functions, Directory functions
@comment node-name, next, previous, up
@subsection Directory block functions
@deftypefun errcode_t ext2fs_read_dir_block (ext2_filsys @var{fs}, blk_t @var{block}, void *@var{buf})
@end deftypefun
@deftypefun errcode_t ext2fs_write_dir_block (ext2_filsys @var{fs}, blk_t @var{block}, void *@var{buf})
@end deftypefun
@deftypefun errcode_t ext2fs_new_dir_block (ext2_filsys @var{fs}, ino_t @var{dir}_ino, ino_t @var{parent_ino}, char **@var{block})
@end deftypefun
@c ----------------------------------------------------------------------
@node Iterating over a directory, Creating and expanding directories, Directory block functions, Directory functions
@comment node-name, next, previous, up
@subsection Iterating over a directory
@deftypefun errcode_t ext2fs_dir_iterate (ext2_filsys @var{fs}, ino_t @var{dir}, int @var{flags}, char *@var{block_buf}, int (*@var{func})(struct ext2_dir_entry *@var{dirent}, int @var{offset}, int @var{blocksize}, char *@var{buf}, void *@var{private}), void *@var{private})
@end deftypefun
@c ----------------------------------------------------------------------
@node Creating and expanding directories, Creating and removing directory entries, Iterating over a directory, Directory functions
@comment node-name, next, previous, up
@subsection Creating and expanding directories
@deftypefun errcode_t ext2fs_mkdir (ext2_filsys @var{fs}, ino_t @var{parent}, ino_t @var{inum}, const char *@var{name})
@end deftypefun
@deftypefun errcode_t ext2fs_expand_dir (ext2_filsys @var{fs}, ino_t @var{dir})
@end deftypefun
@c ----------------------------------------------------------------------
@node Creating and removing directory entries, Looking up filenames, Creating and expanding directories, Directory functions
@comment node-name, next, previous, up
@subsection Creating and removing directory entries
@deftypefun errcode_t ext2fs_link (ext2_filsys @var{fs}, ino_t @var{dir}, const char *@var{name}, ino_t @var{ino}, int flags)
@end deftypefun
@deftypefun errcode_t ext2fs_unlink (ext2_filsys @var{fs}, ino_t @var{dir}, const char *@var{name}, ino_t @var{ino}, int @var{flags})
@end deftypefun
@c ----------------------------------------------------------------------
@node Looking up filenames, Translating inode numbers to filenames, Creating and removing directory entries, Directory functions
@comment node-name, next, previous, up
@subsection Looking up filenames
@deftypefun errcode_t ext2fs_lookup (ext2_filsys @var{fs}, ino_t @var{dir}, const char *@var{name}, int @var{namelen}, char *@var{buf}, ino_t *@var{inode})
@end deftypefun
@deftypefun errcode_t ext2fs_namei (ext2_filsys @var{fs}, ino_t @var{root}, ino_t @var{cwd}, const char *@var{name}, ino_t *@var{inode})
@end deftypefun
@deftypefun errcode_t ext2fs_namei_follow (ext2_filsys @var{fs}, ino_t @var{root}, ino_t @var{cwd}, const char *@var{name}, ino_t *@var{inode})
@end deftypefun
@deftypefun errcode_t ext2fs_follow_link (ext2_filsys @var{fs}, ino_t @var{root}, ino_t @var{cwd}, ino_t @var{inode}, ino_t *@var{res}_inode)
@end deftypefun
@c ----------------------------------------------------------------------
@node Translating inode numbers to filenames, , Looking up filenames, Directory functions
@comment node-name, next, previous, up
@subsection Translating inode numbers to filenames
@deftypefun errcode_t ext2fs_get_pathname (ext2_filsys @var{fs}, ino_t @var{dir}, ino_t @var{ino}, char **@var{name})
@end deftypefun
@c ----------------------------------------------------------------------
@node Bitmap Functions, Badblocks list management, Directory functions, EXT2FS Library Functions
@comment node-name, next, previous, up
@section Bitmap Functions
@menu
* Reading and Writing Bitmaps::
* Allocating Bitmaps::
* Free bitmaps::
* Bitmap Operations::
* Comparing bitmaps::
* Modifying Bitmaps::
* Resizing Bitmaps::
* Clearing Bitmaps::
@end menu
@c ----------------------------------------------------------------------
@node Reading and Writing Bitmaps, Allocating Bitmaps, Bitmap Functions, Bitmap Functions
@comment node-name, next, previous, up
@subsection Reading and Writing Bitmaps
@deftypefun errcode_t ext2fs_write_inode_bitmap (ext2_filsys @var{fs})
@end deftypefun
@deftypefun errcode_t ext2fs_write_block_bitmap (ext2_filsys @var{fs})
@end deftypefun
@deftypefun errcode_t ext2fs_read_inode_bitmap (ext2_filsys @var{fs})
@end deftypefun
@deftypefun errcode_t ext2fs_read_block_bitmap (ext2_filsys @var{fs})
@end deftypefun
@deftypefun errcode_t ext2fs_read_bitmaps (ext2_filsys @var{fs})
@end deftypefun
@deftypefun errcode_t ext2fs_write_bitmaps (ext2_filsys @var{fs})
@end deftypefun
@c ----------------------------------------------------------------------
@node Allocating Bitmaps, Free bitmaps, Reading and Writing Bitmaps, Bitmap Functions
@comment node-name, next, previous, up
@subsection Allocating Bitmaps
@deftypefun errcode_t ext2fs_allocate_generic_bitmap (__u32 @var{start}, __u32 @var{end}, _u32 @var{real_end}, const char *@var{descr}, ext2fs_generic_bitmap *@var{ret})
@end deftypefun
@deftypefun errcode_t ext2fs_allocate_block_bitmap (ext2_filsys @var{fs}, const char *@var{descr}, ext2fs_block_bitmap *@var{ret})
@end deftypefun
@deftypefun errcode_t ext2fs_allocate_inode_bitmap (ext2_filsys @var{fs}, const char *@var{descr}, ext2fs_inode_bitmap *@var{ret})
@end deftypefun
@c ----------------------------------------------------------------------
@node Free bitmaps, Bitmap Operations, Allocating Bitmaps, Bitmap Functions
@comment node-name, next, previous, up
@subsection Freeing bitmaps
@deftypefun void ext2fs_free_generic_bitmap (ext2fs_inode_bitmap @var{bitmap})
@end deftypefun
@deftypefun void ext2fs_free_block_bitmap (ext2fs_block_bitmap @var{bitmap})
@end deftypefun
@deftypefun void ext2fs_free_inode_bitmap (ext2fs_inode_bitmap @var{bitmap})
@end deftypefun
@c ----------------------------------------------------------------------
@node Bitmap Operations, Comparing bitmaps, Free bitmaps, Bitmap Functions
@comment node-name, next, previous, up
@subsection Bitmap Operations
@deftypefun void ext2fs_mark_block_bitmap (ext2fs_block_bitmap @var{bitmap}, blk_t @var{block})
@deftypefunx void ext2fs_unmark_block_bitmap (ext2fs_block_bitmap @var{bitmap}, blk_t @var{block})
@deftypefunx int ext2fs_test_block_bitmap (ext2fs_block_bitmap @var{bitmap}, blk_t @var{block})
These functions set, clear, and test bits in a block bitmap @var{bitmap}.
@end deftypefun
@deftypefun void ext2fs_mark_inode_bitmap (ext2fs_inode_bitmap @var{bitmap}, ino_t @var{inode})
@deftypefunx void ext2fs_unmark_inode_bitmap (ext2fs_inode_bitmap @var{bitmap}, ino_t @var{inode})
@deftypefunx int ext2fs_test_inode_bitmap (ext2fs_inode_bitmap @var{bitmap}, ino_t @var{inode})
These functions set, clear, and test bits in an inode bitmap @var{bitmap}.
@end deftypefun
@deftypefun void ext2fs_fast_mark_block_bitmap (ext2fs_block_bitmap @var{bitmap}, blk_t @var{block})
@deftypefunx void ext2fs_fast_unmark_block_bitmap (ext2fs_block_bitmap @var{bitmap}, blk_t @var{block})
@deftypefunx int ext2fs_fast_test_block_bitmap (ext2fs_block_bitmap @var{bitmap}, blk_t @var{block})
@deftypefunx void ext2fs_fast_mark_inode_bitmap (ext2fs_inode_bitmap @var{bitmap}, ino_t @var{inode})
@deftypefunx void ext2fs_fast_unmark_inode_bitmap (ext2fs_inode_bitmap @var{bitmap}, ino_t @var{inode})
@deftypefunx int ext2fs_fast_test_inode_bitmap (ext2fs_inode_bitmap @var{bitmap}, ino_t @var{inode})
These ``fast'' functions are like their normal counterparts; however,
they are implemented as inline functions and do not perform bounds
checks on the inode number or block number; they are assumed to be
correct. They should only be used in speed-critical applications, where
the inode or block number has already been validated by other means.
@end deftypefun
@deftypefun blk_t ext2fs_get_block_bitmap_start (ext2fs_block_bitmap @var{bitmap})
@deftypefunx ino_t ext2fs_get_inode_bitmap_start (ext2fs_inode_bitmap @var{bitmap})
Return the first inode or block which is stored in the bitmap.
@end deftypefun
@deftypefun blk_t ext2fs_get_block_bitmap_end (ext2fs_block_bitmap @var{bitmap})
@deftypefunx ino_t ext2fs_get_inode_bitmap_end (ext2fs_inode_bitmap @var{bitmap})
Return the first inode or block which is stored in the bitmap.
@end deftypefun
@c ----------------------------------------------------------------------
@node Comparing bitmaps, Modifying Bitmaps, Bitmap Operations, Bitmap Functions
@comment node-name, next, previous, up
@subsection Comparing bitmaps
@deftypefun errcode_t ext2fs_compare_block_bitmap (ext2fs_block_bitmap @var{bm1}, ext2fs_block_bitmap @var{bm2})
@end deftypefun
@deftypefun errcode_t ext2fs_compare_inode_bitmap (ext2fs_inode_bitmap @var{bm1}, ext2fs_inode_bitmap @var{bm2})
@end deftypefun
@c ----------------------------------------------------------------------
@node Modifying Bitmaps, Resizing Bitmaps, Comparing bitmaps, Bitmap Functions
@comment node-name, next, previous, up
@subsection Modifying Bitmaps
@deftypefun errcode_t ext2fs_fudge_inode_bitmap_end (ext2fs_inode_bitmap @var{bitmap}, ino_t @var{end}, ino_t *@var{oend})
@end deftypefun
@deftypefun errcode_t ext2fs_fudge_block_bitmap_end (ext2fs_block_bitmap @var{bitmap}, blk_t @var{end}, blk_t *@var{oend})
@end deftypefun
@c ----------------------------------------------------------------------
@node Resizing Bitmaps, Clearing Bitmaps, Modifying Bitmaps, Bitmap Functions
@comment node-name, next, previous, up
@subsection Resizing Bitmaps
@deftypefun errcode_t ext2fs_resize_generic_bitmap (__u32 @var{new_end}, __u32 @var{new_real_end}, ext2fs_generic_bitmap @var{bmap})
@end deftypefun
@deftypefun errcode_t ext2fs_resize_inode_bitmap (__u32 @var{new_end}, __u32 @var{new_real_end}, ext2fs_inode_bitmap @var{bmap})
@end deftypefun
@deftypefun errcode_t ext2fs_resize_block_bitmap (__u32 @var{new_end}, __u32 @var{new_real_end}, ext2fs_block_bitmap @var{bmap})
@end deftypefun
@c ----------------------------------------------------------------------
@node Clearing Bitmaps, , Resizing Bitmaps, Bitmap Functions
@comment node-name, next, previous, up
@subsection Clearing Bitmaps
@deftypefun void ext2fs_clear_inode_bitmap (ext2fs_inode_bitmap @var{bitmap})
@end deftypefun
@deftypefun void ext2fs_clear_block_bitmap (ext2fs_block_bitmap @var{bitmap})
@end deftypefun
@c ----------------------------------------------------------------------
@node Badblocks list management, Directory-block list management, Bitmap Functions, EXT2FS Library Functions
@comment node-name, next, previous, up
@section Badblocks list management
@deftypefun errcode_t ext2fs_badblocks_list_create (ext2_badblocks_list *@var{ret}, int @var{size})
@end deftypefun
@deftypefun void ext2fs_badblocks_list_free (ext2_badblocks_list @var{bb})
@end deftypefun
@deftypefun errcode_t ext2fs_badblocks_list_add (ext2_badblocks_list @var{bb}, blk_t @var{blk})
@end deftypefun
@deftypefun int ext2fs_badblocks_list_test (ext2_badblocks_list @var{bb}, blk_t @var{blk})
@end deftypefun
@deftypefun errcode_t ext2fs_badblocks_list_iterate_begin (ext2_badblocks_list @var{bb}, ext2_badblocks_iterate *@var{ret})
@end deftypefun
@deftypefun int ext2fs_badblocks_list_iterate (ext2_badblocks_iterate iter, blk_t *@var{blk})
@end deftypefun
@deftypefun void ext2fs_badblocks_list_iterate_end (ext2_badblocks_iterate @var{iter})
@end deftypefun
@deftypefun errcode_t ext2fs_update_bb_inode (ext2_filsys @var{fs}, ext2_badblocks_list @var{bb_list})
@end deftypefun
@deftypefun errcode_t ext2fs_read_bb_inode (ext2_filsys @var{fs}, ext2_badblocks_list *@var{bb_list})
@end deftypefun
@deftypefun errcode_t ext2fs_read_bb_FILE (ext2_filsys @var{fs}, FILE *f, ext2_badblocks_list *@var{bb_list}, void (*invalid)(ext2_filsys @var{fs}, blk_t @var{blk}))
@end deftypefun
@c ----------------------------------------------------------------------
@node Directory-block list management, Byte-swapping functions, Badblocks list management, EXT2FS Library Functions
@comment node-name, next, previous, up
@section Directory-block list management
@deftypefun errcode_t ext2fs_init_dblist (ext2_filsys @var{fs}, ext2_dblist *@var{ret_dblist})
@end deftypefun
@deftypefun void ext2fs_free_dblist (ext2_dblist @var{dblist})
@end deftypefun
@deftypefun errcode_t ext2fs_add_dir_block (ext2_dblist dblist, ino_t @var{ino}, blk_t @var{blk}, int @var{blockcnt})
@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})
@end deftypefun
@deftypefun errcode_t ext2fs_dblist_dir_iterate
(ext2_dblist dblist, int flags, char *@var{block_buf}, int (*func)(ino_t @var{dir}, int @var{entry}, struct ext2_dir_entry *@var{dirent}, int @var{offset}, int @var{blocksize}, char *@var{buf}, void *@var{private}), void *@var{private})
@end deftypefun
@c ----------------------------------------------------------------------
@node Byte-swapping functions, Other functions, Directory-block list management, EXT2FS Library Functions
@comment node-name, next, previous, up
@section Byte-swapping functions
@deftypefun void ext2fs_swap_super (struct ext2_super_block * @var{super})
@end deftypefun
@deftypefun void ext2fs_swap_group_desc (struct ext2_group_desc *@var{gdp})
@end deftypefun
@deftypefun void ext2fs_swap_inode (ext2_filsys @var{fs}, struct ext2_inode *@var{to}, struct ext2_inode *@var{from}, int @var{hostorder})
@end deftypefun
@deftypefun int ext2fs_native_flag (void)
@end deftypefun
@c ----------------------------------------------------------------------
@node Other functions, , Byte-swapping functions, EXT2FS Library Functions
@comment node-name, next, previous, up
@section Other functions
/* alloc.c */
@deftypefun errcode_t ext2fs_new_inode (ext2_filsys @var{fs}, ino_t @var{dir}, int @var{mode}, ext2fs_inode_bitmap @var{map}, ino_t *@var{ret})
@end deftypefun
@deftypefun errcode_t ext2fs_new_block (ext2_filsys @var{fs}, blk_t @var{goal}, ext2fs_block_bitmap @var{map}, blk_t *@var{ret})
@end deftypefun
@deftypefun errcode_t ext2fs_get_free_blocks (ext2_filsys @var{fs}, blk_t @var{start}, blk_t @var{finish}, int @var{num}, ext2fs_block_bitmap @var{map}, blk_t *@var{ret})
@end deftypefun
/* check_desc.c */
@deftypefun errcode_t ext2fs_check_desc (ext2_filsys @var{fs})
@end deftypefun
@deftypefun errcode_t ext2_get_num_dirs (ext2_filsys @var{fs}, ino_t *@var{ret_num_dirs})
@end deftypefun
/* getsize.c */
@deftypefun errcode_t ext2fs_get_device_size (const char *@var{file}, int @var{blocksize}, blk_t *@var{retblocks})
@end deftypefun
/* ismounted.c */
@deftypefun errcode_t ext2fs_check_if_mounted (const char *@var{file}, int *@var{mount_flags})
@end deftypefun
/* valid_blk.c */
@deftypefun int ext2_inode_has_valid_blocks (struct ext2_inode *@var{inode})
@end deftypefun
/* inline functions */
@deftypefun int ext2fs_group_of_blk (ext2_filsys @var{fs}, blk_t @var{blk})
@end deftypefun
@deftypefun int ext2fs_group_of_ino (ext2_filsys @var{fs}, ino_t @var{ino})
@end deftypefun
@c ----------------------------------------------------------------------
@node Concept Index, Function Index, EXT2FS Library Functions, Top
@comment node-name, next, previous, up
@unnumbered Concept Index
@printindex cp
@c ----------------------------------------------------------------------
@node Function Index, , Concept Index, Top
@comment node-name, next, previous, up
@unnumbered Function and Type Index
@printindex fn
@contents
@bye

4761
doc/texinfo.tex Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,152 @@
Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o <tytso@mit.edu>
* Release of E2fsprogs version 1.07
Tue Mar 11 10:31:47 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* icount.c: New file which implements an inode count abstraction.
This significantly reduces amount of memory needed to
check really large filesystems.
* pass1.c, pass2.c, pass3.c, pass4.c: Modified to use the icount
abstraction.
Fri Mar 7 08:28:55 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* dirinfo.c (dir_info_iter): New function which allows iteration
over the directories in the dir_info map.
* pass3.c (pass3, check_directory): Speed up pass 3 by iterating
over all directories in the dir_info structure, instead of
iterating all inodes looking for directories, and then
looking up the directories using get_dir_info().
Sat Feb 1 11:33:43 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* pass1.c (pass1, process_block):
* pass2.c (pass2): Use the ext2_dblist abstraction instead of
manual code to manage the directory block list information.
* pass1.c (check_blocks), pass1b.c (pass1b), pass2.c
(deallocate_inode): Call the ext2 library routine
ext2_inode_has_valid_blocks() instead of
inode_has_valid_blocks().
* swapfs.c (swap_inodes): Add check so that we don't try to call
swap_inode_blocks unless the inode has valid blocks.
(Otherwise a long fast symlink might cause
swap_inode_blocks to erroneously get called.)
Wed Jan 22 14:42:53 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* problem.c, problem.h: Added entries for PR_2_DOT_NULL_TERM and
PR_2_DOT_DOT_NULL_TERM.
* pass2.c (check_dot, check_dot_dot): Make sure the new . and
.. entries are null-terminated, since the 2.0 kernel
requires this (for no good reason).
Mon Jan 20 20:05:11 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* pass1.c (pass1): Set the EXT2_SF_SKIP_MISSING_ITABLE flag so
that we can recover from missing inode tables.
* dirinfo.c (get_dir_info): If there are no directories in the
dir_info abstraction, don't core dump (because dir_info is
NULL).
* e2fsck.c (main): Don't try using the backup superblocks if there
aren't any.
(check_super_block): If there are illegal inode table or
bitmaps, set the filesystem as being in error.
Wed Jan 15 11:32:01 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* pass2.c (check_dir_block): Added check to make sure that rec_len
is a a multiple of 4 (so that the directory entries are
4-byte aligned).
Sat Dec 28 12:16:32 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* Makefile.in (uninstall): Uninstall all programs in the PROGS
line.
(PROGS): Don't build and install the extend program by
default.
Sat Dec 7 16:41:02 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* pass1.c (process_inodes): Make sure the stashed_ino variable is
saved and restored as well.
(pass1): For fast sym links, skip the check_blocks
processing step altogether.
Mon Dec 2 09:28:24 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* problem.c, message.c: New files, to completely refurbish how
filesystem problems are reported to the user. The
diagnostic messages are now encoded out in an easily
customizable, extensible format. The messages printed out
in preen mode are all on one line, and contain the device
name.
Fri Nov 29 20:26:08 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* swapfs.c (swap_inodes): When swapping a filesystem, ignore
deleted files.
* pass1.c (pass1): Ignore missing inode table errors during the
scan, and just skip past those inodes.
* pass3.c (check_root): Remove root_ino argument, and assume that
the root inode must be EXT2_ROOT_INO. Move responsibility
of setting the parent of the root inode in the directory
inode structure to pass2().
* pass2.c (check_dir_block): Don't allow links to the root
directory.
* dirinfo.c (add_dir_info): Remove last argument to add_dir_info,
since the inode is no longer used.
Tue Oct 15 00:06:49 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* e2fsck.c (main): If the superblock magic number is wrong, or the
block group fails a sanity check, then automatically
restart trying to use the backup superblocks.
* pass1.c (mark_table_blocks): Make the inode tables ahead of
everything else; in the case where a bitmap block overlays
the inode table, the inode table should take precedence.
* pass2.c (maybe_clear_entry): Make the deleted/unused error
message fit on one line, since the error can happen during
a preen pass. (We eventually need to revamp the whole
e2fsck error reporting and prompting system, but that's a
job for another day.)
Mon Oct 14 22:29:49 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* e2fsck.c (main): Read in the list badblocks into fs->badblocks
for the benefit of the inode scan functions.
* pass1.c (pass1): If ext2fs_get_next_inode() returns an error
indicating that an inode is in a bad block, mark that
inode as being used, as well as in the inode "bb" map.
* pass2.c (maybe_clear_entry): New function which generalizes the
error cases when a directory entry needs to be cleared.
(check_dir_block): If an inode is in the "bb" map, offer
to clear the directory entry, since the inode is in a bad
block.
* pass4.c (pass4): If an inode is marked as used, but is is marked
in the "bb" map, don't process it as a disconnected inode.
Tue Oct 8 02:02:03 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* Release of E2fsprogs version 1.06
Mon Oct 7 00:45:30 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* e2fsck.c (main): Print out the version number of the shared

View File

@ -12,7 +12,7 @@ LDFLAG_STATIC = @LDFLAG_STATIC@
@MCONFIG@
PROGS= e2fsck extend @EXTRA_PROGS@
PROGS= e2fsck @EXTRA_PROGS@
MANPAGES= e2fsck.8
LIBS= $(LIBEXT2FS) $(LIBCOM_ERR) $(LIBUUID)
@ -26,7 +26,7 @@ PROFILED_DEPLIBS= $(PROFILED_LIBEXT2FS) $(PROFILED_LIBCOM_ERR) $(PROFILED_LIBUUI
.c.o:
$(CC) -c $(ALL_CFLAGS) $< -o $@
@PROFILE_CMT@ $(CC) $(ALL_CFLAGS) -pg -o profiled/$*.o -c $<
@PROFILE_CMT@ $(CC) $(ALL_CFLAGS) -g -pg -o profiled/$*.o -c $<
#
# Flags for using Checker
@ -53,12 +53,14 @@ PROFILED_DEPLIBS= $(PROFILED_LIBEXT2FS) $(PROFILED_LIBCOM_ERR) $(PROFILED_LIBUUI
#MCHECK= -DMCHECK
OBJS= e2fsck.o pass1.o pass1b.o pass2.o pass3.o pass4.o pass5.o \
swapfs.o badblocks.o util.o dirinfo.o ehandler.o $(MTRACE_OBJ)
swapfs.o badblocks.o util.o dirinfo.o ehandler.o problem.o message.o \
$(MTRACE_OBJ)
PROFILED_OBJS= profiled/e2fsck.o profiled/pass1.o profiled/pass1b.o \
profiled/pass2.o profiled/pass3.o profiled/pass4.o profiled/pass5.o \
profiled/badblocks.o profiled/util.o profiled/dirinfo.o \
profiled/ehandler.o profiled/swapfs.o
profiled/ehandler.o profiled/message.o profiled/problem.o \
profiled/swapfs.o
SRCS= $(srcdir)/e2fsck.c \
$(srcdir)/pass1.c \
@ -71,6 +73,7 @@ SRCS= $(srcdir)/e2fsck.c \
$(srcdir)/util.c \
$(srcdir)/dirinfo.c \
$(srcdir)/ehandler.c \
$(srcdir)/problem.c \
$(MTRACE_SRC)
all:: profiled $(PROGS) e2fsck.static e2fsck.shared $(MANPAGES)
@ -87,8 +90,8 @@ e2fsck.static: $(OBJS) $(STATIC_DEPLIBS)
e2fsck.shared: $(OBJS) $(DEPLIBS)
$(LD) $(ALL_LDFLAGS) -o e2fsck.shared $(OBJS) $(LIBS)
e2fsck.profiled: $(PROFILED_OBJS) $(DEPLIBS)
$(LD) $(ALL_LDFLAGS) -pg -o e2fsck.profiled $(PROFILED_OBJS) \
e2fsck.profiled: $(PROFILED_OBJS) $(PROFILED_DEPLIBS)
$(LD) $(ALL_LDFLAGS) -g -pg -o e2fsck.profiled $(PROFILED_OBJS) \
$(PROFILED_LIBS)
extend: extend.o
@ -122,8 +125,9 @@ install: $(PROGS) $(MANPAGES) installdirs
done
uninstall:
$(RM) -f $(sbindir)/e2fsck
$(RM) -f $(sbindir)/flushb
for i in $(PROGS); do \
$(RM) -f $(sbindir)/$$i; \
done
$(RM) -f $(sbindir)/fsck.ext2
for i in $(MANPAGES); do \
$(RM) -f $(man8dir)/$$i; \
@ -143,46 +147,66 @@ distclean: clean
# Makefile dependencies follow. This must be the last section in
# the Makefile.in file
#
e2fsck.o: $(srcdir)/e2fsck.c $(top_srcdir)/lib/et/com_err.h \
e2fsck.o: $(srcdir)/e2fsck.c \
$(top_srcdir)/lib/et/com_err.h \
$(top_srcdir)/lib/uuid/uuid.h $(srcdir)/e2fsck.h \
$(top_srcdir)/lib/ext2fs/ext2fs.h \
$(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(top_srcdir)/lib/ext2fs/bitops.h $(srcdir)/../version.h
pass1.o: $(srcdir)/pass1.c $(top_srcdir)/lib/et/com_err.h \
$(srcdir)/e2fsck.h $(top_srcdir)/lib/ext2fs/ext2fs.h \
$(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(top_srcdir)/lib/ext2fs/bitops.h
pass1b.o: $(srcdir)/pass1b.c $(top_srcdir)/lib/et/com_err.h \
$(srcdir)/e2fsck.h $(top_srcdir)/lib/ext2fs/ext2fs.h \
$(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(top_srcdir)/lib/ext2fs/bitops.h
pass2.o: $(srcdir)/pass2.c $(top_srcdir)/lib/et/com_err.h $(srcdir)/e2fsck.h \
$(top_srcdir)/lib/ext2fs/bitops.h $(srcdir)/problem.h \
$(srcdir)/../version.h
pass1.o: $(srcdir)/pass1.c \
$(top_srcdir)/lib/et/com_err.h \
$(srcdir)/e2fsck.h \
$(top_srcdir)/lib/ext2fs/ext2fs.h \
$(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(top_srcdir)/lib/ext2fs/bitops.h
pass3.o: $(srcdir)/pass3.c $(top_srcdir)/lib/et/com_err.h $(srcdir)/e2fsck.h \
$(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/bitops.h \
$(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
$(top_srcdir)/lib/ext2fs/bitops.h $(srcdir)/problem.h
pass1b.o: $(srcdir)/pass1b.c \
$(top_srcdir)/lib/et/com_err.h \
$(srcdir)/e2fsck.h \
$(top_srcdir)/lib/ext2fs/ext2fs.h \
$(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(top_srcdir)/lib/ext2fs/bitops.h $(srcdir)/problem.h
pass2.o: $(srcdir)/pass2.c $(top_srcdir)/lib/et/com_err.h \
$(srcdir)/e2fsck.h \
$(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/io.h \
$(top_builddir)/lib/ext2fs/ext2_err.h $(top_srcdir)/lib/ext2fs/bitops.h \
$(srcdir)/problem.h
pass3.o: $(srcdir)/pass3.c \
$(top_srcdir)/lib/et/com_err.h \
$(srcdir)/e2fsck.h \
$(top_srcdir)/lib/ext2fs/ext2fs.h \
$(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(top_srcdir)/lib/ext2fs/bitops.h $(srcdir)/problem.h
pass4.o: $(srcdir)/pass4.c $(srcdir)/e2fsck.h \
$(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
$(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(top_srcdir)/lib/ext2fs/bitops.h
pass5.o: $(srcdir)/pass5.c $(top_srcdir)/lib/et/com_err.h $(srcdir)/e2fsck.h \
$(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/bitops.h \
$(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
badblocks.o: $(srcdir)/badblocks.c $(top_srcdir)/lib/et/com_err.h \
$(srcdir)/e2fsck.h $(top_srcdir)/lib/ext2fs/ext2fs.h \
$(top_srcdir)/lib/ext2fs/bitops.h $(srcdir)/problem.h
pass5.o: $(srcdir)/pass5.c $(top_srcdir)/lib/et/com_err.h \
$(srcdir)/e2fsck.h \
$(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/io.h \
$(top_builddir)/lib/ext2fs/ext2_err.h $(top_srcdir)/lib/ext2fs/bitops.h
badblocks.o: $(srcdir)/badblocks.c \
$(top_srcdir)/lib/et/com_err.h \
$(srcdir)/e2fsck.h \
$(top_srcdir)/lib/ext2fs/ext2fs.h \
$(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(top_srcdir)/lib/ext2fs/bitops.h
util.o: $(srcdir)/util.c $(srcdir)/e2fsck.h \
util.o: $(srcdir)/util.c \
$(srcdir)/e2fsck.h \
$(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
$(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(top_srcdir)/lib/ext2fs/bitops.h
dirinfo.o: $(srcdir)/dirinfo.c $(top_srcdir)/lib/et/com_err.h \
$(srcdir)/e2fsck.h $(top_srcdir)/lib/ext2fs/ext2fs.h \
$(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(top_srcdir)/lib/ext2fs/bitops.h
ehandler.o: $(srcdir)/ehandler.c $(srcdir)/e2fsck.h \
$(srcdir)/e2fsck.h \
$(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/io.h \
$(top_builddir)/lib/ext2fs/ext2_err.h $(top_srcdir)/lib/ext2fs/bitops.h
ehandler.o: $(srcdir)/ehandler.c \
$(srcdir)/e2fsck.h \
$(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
$(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(top_srcdir)/lib/ext2fs/bitops.h
$(top_srcdir)/lib/ext2fs/bitops.h
problem.o: $(srcdir)/problem.c \
$(srcdir)/e2fsck.h \
$(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
$(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(top_srcdir)/lib/ext2fs/bitops.h $(srcdir)/problem.h

View File

@ -24,12 +24,11 @@ int get_num_dirs(ext2_filsys fs)
}
/*
* This subroutine is called during pass1 to stash away the block
* numbers for the directory, which we will need later. The idea is
* to avoid reading directory inodes twice.
* This subroutine is called during pass1 to create a directory info
* entry. During pass1, the passed-in parent is 0; it will get filled
* in during pass2.
*/
void add_dir_info(ext2_filsys fs, ino_t ino, ino_t parent,
struct ext2_inode *inode)
void add_dir_info(ext2_filsys fs, ino_t ino, ino_t parent)
{
struct dir_info *dir;
int i, j;
@ -61,7 +60,7 @@ void add_dir_info(ext2_filsys fs, ino_t ino, ino_t parent,
* the dir_info array needs to be sorted by inode number for
* get_dir_info()'s sake.
*/
if (dir_info_count && dir_info[dir_info_count-1].ino > ino) {
if (dir_info_count && dir_info[dir_info_count-1].ino >= ino) {
for (i = dir_info_count-1; i > 0; i--)
if (dir_info[i-1].ino < ino)
break;
@ -87,6 +86,8 @@ struct dir_info *get_dir_info(ino_t ino)
low = 0;
high = dir_info_count-1;
if (!dir_info)
return 0;
if (ino == dir_info[low].ino)
return &dir_info[low];
if (ino == dir_info[high].ino)
@ -118,3 +119,14 @@ void free_dir_info(ext2_filsys fs)
dir_info_size = 0;
dir_info_count = 0;
}
/*
* A simple interator function
*/
struct dir_info *dir_info_iter(int *control)
{
if (*control >= dir_info_count)
return 0;
return(dir_info + (*control)++);
}

View File

@ -1,8 +1,12 @@
/*
* e2fsck.c - a consistency checker for the new extended file system.
*
* Copyright (C) 1993, 1994 Theodore Ts'o. This file may be
* redistributed under the terms of the GNU Public License.
* Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
/* Usage: e2fsck [-dfpnsvy] device
@ -42,6 +46,7 @@
#include "et/com_err.h"
#include "uuid/uuid.h"
#include "e2fsck.h"
#include "problem.h"
#include "../version.h"
extern int isatty(int);
@ -60,6 +65,7 @@ int rwflag = 1;
int swapfs = 0;
int normalize_swapfs = 0;
int inode_buffer_blocks = 0;
blk_t use_superblock;
blk_t superblock;
int blocksize = 0;
int verbose = 0;
@ -236,8 +242,11 @@ static void relocate_hint(void)
{
static hint_issued = 0;
/* Only issue the hint once */
if (hint_issued)
/*
* Only issue the hint once, and only if we're using the
* primary superblocks.
*/
if (hint_issued || superblock)
return;
printf("Note: if there is several inode or block bitmap blocks\n"
@ -258,6 +267,9 @@ static void check_super_block(ext2_filsys fs)
int i;
blk_t should_be;
errcode_t retval;
struct problem_context pctx;
clear_problem_context(&pctx);
/*
* Verify the super block constants...
@ -334,55 +346,52 @@ static void check_super_block(ext2_filsys fs)
last_block = first_block + blocks_per_group;
for (i = 0; i < fs->group_desc_count; i++) {
pctx.group = i;
if (i == fs->group_desc_count - 1)
last_block = fs->super->s_blocks_count;
if ((fs->group_desc[i].bg_block_bitmap < first_block) ||
(fs->group_desc[i].bg_block_bitmap >= last_block)) {
relocate_hint();
printf("Block bitmap for group %d is not in group. "
"(block %u)\n",
i, fs->group_desc[i].bg_block_bitmap);
preenhalt(fs);
if (!ask("Relocate", 1)) {
fatal_error("Block bitmap not in group");
pctx.blk = fs->group_desc[i].bg_block_bitmap;
if (fix_problem(fs, PR_0_BB_NOT_GROUP, &pctx)) {
fs->group_desc[i].bg_block_bitmap = 0;
invalid_block_bitmap[i]++;
invalid_bitmaps++;
}
fs->group_desc[i].bg_block_bitmap = 0;
invalid_block_bitmap[i]++;
invalid_bitmaps++;
}
if ((fs->group_desc[i].bg_inode_bitmap < first_block) ||
(fs->group_desc[i].bg_inode_bitmap >= last_block)) {
relocate_hint();
printf("Inode bitmap group %d not in group. "
"(block %u)\n",
i, fs->group_desc[i].bg_inode_bitmap);
preenhalt(fs);
if (!ask("Relocate", 1)) {
fatal_error("Inode bitmap not in group");
pctx.blk = fs->group_desc[i].bg_inode_bitmap;
if (fix_problem(fs, PR_0_IB_NOT_GROUP, &pctx)) {
fs->group_desc[i].bg_inode_bitmap = 0;
invalid_inode_bitmap[i]++;
invalid_bitmaps++;
}
fs->group_desc[i].bg_inode_bitmap = 0;
invalid_inode_bitmap[i]++;
invalid_bitmaps++;
}
if ((fs->group_desc[i].bg_inode_table < first_block) ||
((fs->group_desc[i].bg_inode_table +
fs->inode_blocks_per_group - 1) >= last_block)) {
relocate_hint();
printf("Inode table for group %d not in group. "
"(block %u)\n",
i, fs->group_desc[i].bg_inode_table);
printf("WARNING: SEVERE DATA LOSS POSSIBLE.\n");
preenhalt(fs);
if (!ask("Relocate", 1)) {
fatal_error("Inode table not in group");
pctx.blk = fs->group_desc[i].bg_inode_table;
if (fix_problem(fs, PR_0_ITABLE_NOT_GROUP, &pctx)) {
fs->group_desc[i].bg_inode_table = 0;
invalid_inode_table[i]++;
invalid_bitmaps++;
}
fs->group_desc[i].bg_inode_table = 0;
invalid_inode_table[i]++;
invalid_bitmaps++;
}
first_block += fs->super->s_blocks_per_group;
last_block += fs->super->s_blocks_per_group;
}
/*
* If we have invalid bitmaps, set the error state of the
* filesystem.
*/
if (invalid_bitmaps && rwflag) {
fs->super->s_state &= ~EXT2_VALID_FS;
ext2fs_mark_super_dirty(fs);
}
/*
* If the UUID field isn't assigned, assign it.
@ -492,7 +501,7 @@ static void PRS(int argc, char *argv[])
/* What we do by default, anyway! */
break;
case 'b':
superblock = atoi(optarg);
use_superblock = atoi(optarg);
break;
case 'B':
blocksize = atoi(optarg);
@ -588,7 +597,9 @@ int main (int argc, char *argv[])
errcode_t retval = 0;
int exit_value = FSCK_OK;
int i;
ext2_filsys fs;
ext2_filsys fs = 0;
io_manager io_ptr;
struct ext2fs_sb *s;
#ifdef MTRACE
mtrace();
@ -601,7 +612,7 @@ int main (int argc, char *argv[])
PRS(argc, argv);
if (!preen)
if (!preen || show_version_only)
fprintf (stderr, "e2fsck %s, %s for EXT2 FS %s, %s\n",
E2FSPROGS_VERSION, E2FSPROGS_DATE,
EXT2FS_VERSION, EXT2FS_DATE);
@ -618,27 +629,46 @@ int main (int argc, char *argv[])
if (!isatty (0) || !isatty (1))
die ("need terminal for interactive repairs");
}
superblock = use_superblock;
restart:
#if 1
io_ptr = unix_io_manager;
#else
io_ptr = test_io_manager;
test_io_backing_manager = unix_io_manager;
#endif
sync_disks();
if (superblock && blocksize) {
retval = ext2fs_open(filesystem_name,
rwflag ? EXT2_FLAG_RW : 0,
superblock, blocksize, unix_io_manager,
&fs);
superblock, blocksize, io_ptr, &fs);
} else if (superblock) {
for (i=0; possible_block_sizes[i]; i++) {
retval = ext2fs_open(filesystem_name,
rwflag ? EXT2_FLAG_RW : 0,
superblock,
possible_block_sizes[i],
unix_io_manager, &fs);
io_ptr, &fs);
if (!retval)
break;
}
} else
retval = ext2fs_open(filesystem_name,
rwflag ? EXT2_FLAG_RW : 0,
0, 0, unix_io_manager, &fs);
0, 0, io_ptr, &fs);
if (!superblock && !preen &&
((retval == EXT2_ET_BAD_MAGIC) ||
((retval == 0) && ext2fs_check_desc(fs)))) {
if (!fs || (fs->group_desc_count > 1)) {
printf("%s trying backup blocks...\n",
retval ? "Couldn't find ext2 superblock," :
"Group descriptors look bad...");
superblock = 8193;
if (fs)
ext2fs_close(fs);
goto restart;
}
}
if (retval) {
com_err(program_name, retval, "while trying to open %s",
filesystem_name);
@ -656,16 +686,28 @@ restart:
printf(corrupt_msg);
fatal_error(0);
}
#ifdef EXT2_CURRENT_REV
if (fs->super->s_rev_level > E2FSCK_CURRENT_REV) {
com_err(program_name, EXT2_ET_REV_TOO_HIGH,
"while trying to open %s",
filesystem_name);
goto get_newer;
}
#endif
/*
* Check for compatibility with the feature sets. We have to
* check because we need to be more stringent than ext2fs_open
*/
s = (struct ext2fs_sb *) fs->super;
if (s->s_feature_compat || s->s_feature_incompat ||
s->s_feature_ro_compat) {
com_err(program_name, EXT2_ET_UNSUPP_FEATURE,
" (%s)", filesystem_name);
get_newer:
printf ("Get a newer version of e2fsck!\n");
fatal_error(0);
}
#endif
/*
* If the user specified a specific superblock, presumably the
* master superblock has been trashed. So we mark the
@ -715,6 +757,14 @@ restart:
*/
ext2fs_mark_valid(fs);
retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
if (retval) {
com_err(program_name, retval,
"while reading bad blocks inode");
preenhalt(fs);
printf("This doesn't bode well, but we'll try to go on...\n");
}
pass1(fs);
free(invalid_inode_bitmap);
free(invalid_block_bitmap);
@ -723,6 +773,7 @@ restart:
ext2fs_close(fs);
printf("Restarting e2fsck from the beginning...\n");
restart_e2fsck = 0;
superblock = use_superblock;
goto restart;
}
pass2(fs);

View File

@ -47,13 +47,13 @@
/*
* Inode count arrays
*/
extern unsigned short * inode_count;
extern unsigned short * inode_link_info;
extern ext2_icount_t inode_count;
extern ext2_icount_t inode_link_info;
/*
* The directory information structure; stores directory information
* collected in earlier passes, to avoid disk i/o in fetching the
* directoryt information.
* directory information.
*/
struct dir_info {
ino_t ino; /* Inode number */
@ -61,16 +61,6 @@ struct dir_info {
ino_t parent; /* Parent according to treewalk */
};
struct dir_block_struct {
ino_t ino;
blk_t blk;
int blockcnt;
};
struct dir_block_struct *dir_blocks;
int dir_block_count;
int dir_block_size;
/*
* This structure is used for keeping track of how much resources have
* been used for a particular pass of e2fsck.
@ -91,6 +81,7 @@ extern const char * device_name;
extern ext2fs_inode_bitmap inode_used_map; /* Inodes which are in use */
extern ext2fs_inode_bitmap inode_bad_map; /* Inodes which are bad somehow */
extern ext2fs_inode_bitmap inode_dir_map; /* Inodes which are directories */
extern ext2fs_inode_bitmap inode_bb_map; /* Inodes which are in bad blocks */
extern ext2fs_block_bitmap block_found_map; /* Blocks which are in use */
extern ext2fs_block_bitmap block_dup_map; /* Blocks which are used by more than once */
@ -175,11 +166,11 @@ extern void read_bad_blocks_file(ext2_filsys fs, const char *bad_blocks_file,
extern void test_disk(ext2_filsys fs);
/* dirinfo.c */
extern void add_dir_info(ext2_filsys fs, ino_t ino, ino_t parent,
struct ext2_inode *inode);
extern void add_dir_info(ext2_filsys fs, ino_t ino, ino_t parent);
extern struct dir_info *get_dir_info(ino_t ino);
extern void free_dir_info(ext2_filsys fs);
extern int get_num_dirs(ext2_filsys fs);
extern struct dir_info *dir_info_iter(int *control);
/* ehandler.c */
extern const char *ehandler_operation(const char *op);

329
e2fsck/message.c Normal file
View File

@ -0,0 +1,329 @@
/*
* message.c --- print e2fsck messages (with compression)
*
* Copyright 1996, 1997 by Theodore Ts'o
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*
* print_e2fsck_message() prints a message to the user, using
* compression techniques and expansions of abbreviations.
*
* The following % expansions are supported:
*
* %b <blk> block number
* %B <blkcount> integer
* %di <dirent>->ino inode number
* %dn <dirent>->name string
* %D <dir> inode number
* %g <group> integer
* %i <ino> inode number
* %Is <inode> -> i_size
* %Ib <inode> -> i_blocks
* %Il <inode> -> i_links_count
* %Im <inode> -> i_mode
* %IM <inode> -> i_mtime
* %IF <inode> -> i_faddr
* %If <inode> -> i_file_acl
* %Id <inode> -> i_dir_acl
* %j <ino2> inode number
* %N <num>
* %p ext2fs_get_pathname of directory <ino>
* %P ext2fs_get_pathname of <dirent>->ino with <ino2> as
* the containing directory. (If dirent is NULL
* then return the pathname of directory <ino2>)
* %q ext2fs_get_pathname of directory <dir>
* %Q ext2fs_get_pathname of directory <ino> with <dir> as
* the containing directory.
*
* The following '@' expansions are supported:
*
* @b block
* @B bitmap
* @C conflicts with some other fs block
* @i inode
* @D deleted
* @d directory
* @e entry
* @E Entry '%Dn' in %p (%i)
* @F for @i %i (%Q) is
* @g group
* @l lost+found
* @L is a link
* @u unattached
* @r root inode
* @z zero-length
*/
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <termios.h>
#include "e2fsck.h"
#include "problem.h"
#ifdef __GNUC__
#define _INLINE_ __inline__
#else
#define _INLINE_
#endif
/*
* This structure defines the abbreviations used by the text strings
* below. The first character in the string is the index letter. An
* abbreviation of the form '@<i>' is expanded by looking up the index
* letter <i> in the table below.
*/
static const char *abbrevs[] = {
"bblock",
"Bbitmap",
"Cconflicts with some other fs @b",
"iinode",
"Ddeleted",
"ddirectory",
"eentry",
"E@e '%Dn' in %p (%i)",
"Ffor @i %i (%Q) is",
"ggroup",
"llost+found",
"Lis a link",
"uunattached",
"rroot @i",
"sshould be",
"zzero-length",
"@@",
0
};
/*
* Give more user friendly names to the "special" inodes.
*/
#define num_special_inodes 7
static const char *special_inode_name[] =
{
"<The NULL inode>", /* 0 */
"<The bad blocks inode>", /* 1 */
"/", /* 2 */
"<The ACL index inode>", /* 3 */
"<The ACL data inode>", /* 4 */
"<The boot loader inode>", /* 5 */
"<The undelete directory inode>" /* 6 */
};
/*
* This function prints a pathname, using the ext2fs_get_pathname
* function
*/
static void print_pathname(ext2_filsys fs, ino_t dir, ino_t ino)
{
errcode_t retval;
char *path;
if (!dir && (ino < num_special_inodes)) {
fputs(special_inode_name[ino], stdout);
return;
}
retval = ext2fs_get_pathname(fs, dir, ino, &path);
if (retval)
fputs("???", stdout);
else {
fputs(path, stdout);
free(path);
}
}
/*
* This function handles the '@' expansion. We allow recursive
* expansion; an @ expression can contain further '@' and '%'
* expressions.
*/
static _INLINE_ void expand_at_expression(ext2_filsys fs, char ch,
struct problem_context *ctx,
int *first)
{
const char **cpp, *str;
/* Search for the abbreviation */
for (cpp = abbrevs; *cpp; cpp++) {
if (ch == *cpp[0])
break;
}
if (*cpp) {
str = (*cpp) + 1;
if (*first && islower(*str)) {
*first = 0;
fputc(toupper(*str++), stdout);
}
print_e2fsck_message(fs, str, ctx, *first);
} else
printf("@%c", ch);
}
/*
* This function expands '%kX' expressions
*/
static _INLINE_ void expand_inode_expression(char ch,
struct problem_context *ctx)
{
struct ext2_inode *inode;
char * time_str;
time_t t;
if (!ctx || !ctx->inode)
goto no_inode;
inode = ctx->inode;
switch (ch) {
case 's':
printf("%u", inode->i_size);
break;
case 'b':
printf("%u", inode->i_blocks);
break;
case 'l':
printf("%d", inode->i_links_count);
break;
case 'm':
printf("0%o", inode->i_mode);
break;
case 'M':
t = inode->i_mtime;
time_str = ctime(&t);
printf("%.24s", time_str);
break;
case 'F':
printf("%u", inode->i_faddr);
break;
case 'f':
printf("%u", inode->i_file_acl);
break;
case 'd':
printf("%u", inode->i_dir_acl);
break;
default:
no_inode:
printf("%%I%c", ch);
break;
}
}
/*
* This function expands '%dX' expressions
*/
static _INLINE_ void expand_dirent_expression(char ch,
struct problem_context *ctx)
{
struct ext2_dir_entry *dirent;
int len;
if (!ctx || !ctx->dirent)
goto no_dirent;
dirent = ctx->dirent;
switch (ch) {
case 'i':
printf("%u", dirent->inode);
break;
case 'n':
len = dirent->name_len;
if (len > EXT2_NAME_LEN)
len = EXT2_NAME_LEN;
if (len > dirent->rec_len)
len = dirent->rec_len;
printf("%.*s", dirent->name_len, dirent->name);
break;
default:
no_dirent:
printf("%%D%c", ch);
break;
}
}
static _INLINE_ void expand_percent_expression(ext2_filsys fs, char ch,
struct problem_context *ctx)
{
if (!ctx)
goto no_context;
switch (ch) {
case '%':
fputc('%', stdout);
break;
case 'b':
printf("%u", ctx->blk);
break;
case 'B':
printf("%d", ctx->blkcount);
break;
case 'd':
printf("%lu", ctx->dir);
break;
case 'g':
printf("%d", ctx->group);
break;
case 'i':
printf("%lu", ctx->ino);
break;
case 'j':
printf("%lu", ctx->ino2);
break;
case 'N':
printf("%u", ctx->num);
break;
case 'p':
print_pathname(fs, ctx->ino, 0);
break;
case 'P':
print_pathname(fs, ctx->ino2,
ctx->dirent ? ctx->dirent->inode : 0);
break;
case 'q':
print_pathname(fs, ctx->dir, 0);
break;
case 'Q':
print_pathname(fs, ctx->dir, ctx->ino);
break;
default:
no_context:
printf("%%%c", ch);
break;
}
}
void print_e2fsck_message(ext2_filsys fs, const char *msg,
struct problem_context *ctx, int first)
{
const char * cp;
int i;
for (cp = msg; *cp; cp++) {
if (cp[0] == '@') {
cp++;
expand_at_expression(fs, *cp, ctx, &first);
} else if (cp[0] == '%' && cp[1] == 'I') {
cp += 2;
expand_inode_expression(*cp, ctx);
} else if (cp[0] == '%' && cp[1] == 'D') {
cp += 2;
expand_dirent_expression(*cp, ctx);
} else if ((cp[0] == '%')) {
cp++;
expand_percent_expression(fs, *cp, ctx);
} else {
for (i=0; cp[i]; i++)
if ((cp[i] == '@') || cp[i] == '%')
break;
printf("%.*s", i, cp);
cp += i-1;
}
first = 0;
}
}

View File

@ -1,8 +1,12 @@
/*
* pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
*
* Copyright (C) 1993, 1994 Theodore Ts'o. This file may be
* redistributed under the terms of the GNU Public License.
* Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*
* Pass 1 of e2fsck iterates over all the inodes in the filesystems,
* and applies the following tests to each inode:
@ -16,6 +20,7 @@
* - A bitmap of which inodes are in use. (inode_used_map)
* - A bitmap of which inodes are directories. (inode_dir_map)
* - A bitmap of which inodes have bad fields. (inode_bad_map)
* - A bitmap of which inodes are in bad blocks. (inode_bb_map)
* - A bitmap of which blocks are in use. (block_found_map)
* - A bitmap of which blocks are in use by two inodes (block_dup_map)
* - The data blocks of the directory inodes. (dir_map)
@ -37,6 +42,7 @@
#include <et/com_err.h>
#include "e2fsck.h"
#include "problem.h"
#ifdef NO_INLINE_FUNCS
#define _INLINE_
@ -64,28 +70,31 @@ int fs_fragmented = 0;
ext2fs_inode_bitmap inode_used_map = 0; /* Inodes which are in use */
ext2fs_inode_bitmap inode_bad_map = 0; /* Inodes which are bad in some way */
ext2fs_inode_bitmap inode_dir_map = 0; /* Inodes which are directories */
ext2fs_inode_bitmap inode_bb_map = 0; /* Inodes which are in bad blocks */
ext2fs_block_bitmap block_found_map = 0;
ext2fs_block_bitmap block_dup_map = 0;
ext2fs_block_bitmap block_illegal_map = 0;
unsigned short * inode_link_info = NULL;
ext2_icount_t inode_link_info = 0;
static int process_block(ext2_filsys fs, blk_t *blocknr,
int blockcnt, void *private);
int blockcnt, blk_t ref_blk,
int ref_offset, void *private);
static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
int blockcnt, void *private);
static void check_blocks(ext2_filsys fs, ino_t ino, struct ext2_inode *inode,
int blockcnt, blk_t ref_blk,
int ref_offset, void *private);
static void check_blocks(ext2_filsys fs, struct problem_context *pctx,
char *block_buf);
static void mark_table_blocks(ext2_filsys fs);
static void alloc_bad_map(ext2_filsys fs);
static void alloc_bb_map(ext2_filsys fs);
static void handle_fs_bad_blocks(ext2_filsys fs);
static void process_inodes(ext2_filsys fs, char *block_buf);
static int process_inode_cmp(const void *a, const void *b);
static int dir_block_cmp(const void *a, const void *b);
static errcode_t scan_callback(ext2_filsys fs, ext2_inode_scan scan,
dgrp_t group, void * private);
static char *describe_illegal_block(ext2_filsys fs, blk_t block);
/* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
struct process_block_struct {
ino_t ino;
@ -93,9 +102,9 @@ struct process_block_struct {
int num_blocks;
int last_block;
int num_illegal_blocks;
int fix;
blk_t previous_block;
struct ext2_inode *inode;
struct problem_context *pctx;
};
struct process_inode_block {
@ -116,13 +125,6 @@ static struct process_inode_block *inodes_to_process;
static int process_inode_count;
int process_inode_size = 256;
/*
* For the directory blocks list.
*/
struct dir_block_struct *dir_blocks = 0;
int dir_block_count = 0;
int dir_block_size = 0;
/*
* Free all memory allocated by pass1 in preparation for restarting
* things.
@ -132,13 +134,19 @@ static void unwind_pass1(ext2_filsys fs)
ext2fs_free_inode_bitmap(inode_used_map); inode_used_map = 0;
ext2fs_free_inode_bitmap(inode_dir_map); inode_dir_map = 0;
ext2fs_free_block_bitmap(block_found_map); block_found_map = 0;
free(inode_link_info); inode_link_info = 0;
ext2fs_free_icount(inode_link_info); inode_link_info = 0;
free(inodes_to_process);inodes_to_process = 0;
free(dir_blocks); dir_blocks = 0;
dir_block_size = 0;
ext2fs_free_dblist(fs->dblist); fs->dblist = 0;
free_dir_info(fs);
if (block_dup_map) {
ext2fs_free_block_bitmap(block_dup_map); block_dup_map = 0;
}
if (inode_bb_map) {
ext2fs_free_inode_bitmap(inode_bb_map); inode_bb_map = 0;
}
if (inode_bad_map) {
ext2fs_free_inode_bitmap(inode_bad_map); inode_bad_map = 0;
}
/* Clear statistic counters */
fs_directory_count = 0;
@ -167,6 +175,7 @@ void pass1(ext2_filsys fs)
errcode_t retval;
struct resource_track rtrack;
unsigned char frag, fsize;
struct problem_context pctx;
init_resource_track(&rtrack);
@ -208,19 +217,23 @@ void pass1(ext2_filsys fs)
"while allocating block_illegal_map");
fatal_error(0);
}
inode_link_info = allocate_memory((fs->super->s_inodes_count + 1) *
sizeof(unsigned short),
"inode link count array");
retval = ext2fs_create_icount(fs, 0, 0, &inode_link_info);
if (retval) {
com_err("ext2fs_create_icount", retval,
"while creating inode_link_info");
fatal_error(0);
}
inodes_to_process = allocate_memory(process_inode_size *
sizeof(struct process_inode_block),
"array of inodes to process");
process_inode_count = 0;
dir_block_size = get_num_dirs(fs) * 4;
dir_block_count = 0;
dir_blocks = allocate_memory(sizeof(struct dir_block_struct) *
dir_block_size,
"directory block information");
retval = ext2fs_init_dblist(fs, 0);
if (retval) {
com_err(program_name, retval,
"while allocating directory block information");
fatal_error(0);
}
mark_table_blocks(fs);
block_buf = allocate_memory(fs->blocksize * 3, "block interate buffer");
@ -234,6 +247,7 @@ void pass1(ext2_filsys fs)
com_err(program_name, retval, "while opening inode scan");
fatal_error(0);
}
ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
retval = ext2fs_get_next_inode(scan, &ino, &inode);
if (retval) {
com_err(program_name, retval, "while starting inode scan");
@ -241,25 +255,36 @@ void pass1(ext2_filsys fs)
}
stashed_inode = &inode;
ext2fs_set_inode_callback(scan, scan_callback, block_buf);
clear_problem_context(&pctx);
while (ino) {
stashed_ino = ino;
inode_link_info[ino] = inode.i_links_count;
if (inode.i_links_count)
retval = ext2fs_icount_store(inode_link_info, ino,
inode.i_links_count);
if (retval) {
com_err("ext2fs_icount_fetch", retval,
"while adding inode %u", ino);
fatal_error(0);
}
pctx.ino = ino;
pctx.inode = &inode;
if (ino == EXT2_BAD_INO) {
struct process_block_struct pb;
pb.ino = EXT2_BAD_INO;
pb.num_blocks = pb.last_block = 0;
pb.num_illegal_blocks = 0;
pb.suppress = pb.clear = pb.is_dir = 0;
pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
pb.fragmented = 0;
pb.fix = -1;
pb.inode = &inode;
retval = ext2fs_block_iterate(fs, ino, 0, block_buf,
process_bad_block, &pb);
pb.pctx = &pctx;
retval = ext2fs_block_iterate2(fs, ino, 0, block_buf,
process_bad_block, &pb);
if (retval)
com_err(program_name, retval, "while calling e2fsc_block_interate in pass 1");
ext2fs_mark_inode_bitmap(inode_used_map, ino);
clear_problem_context(&pctx);
goto next;
}
if (ino == EXT2_ROOT_INO) {
@ -269,16 +294,14 @@ void pass1(ext2_filsys fs)
* regnerated in pass #3.
*/
if (!LINUX_S_ISDIR(inode.i_mode)) {
printf("Root inode is not a directory. ");
preenhalt(fs);
if (ask("Clear", 1)) {
if (fix_problem(fs, PR_1_ROOT_NO_DIR, &pctx)) {
inode.i_dtime = time(0);
inode.i_links_count = 0;
inode_link_info[ino] = 0;
ext2fs_icount_store(inode_link_info,
ino, 0);
e2fsck_write_inode(fs, ino, &inode,
"pass1");
} else
ext2fs_unmark_valid(fs);
}
}
/*
* If dtime is set, offer to clear it. mke2fs
@ -290,34 +313,30 @@ void pass1(ext2_filsys fs)
* as a special case.
*/
if (inode.i_dtime && inode.i_links_count) {
if (ask("Root inode has dtime set "
"(probably due to old mke2fs). Fix",
1)) {
if (fix_problem(fs, PR_1_ROOT_DTIME, &pctx)) {
inode.i_dtime = 0;
e2fsck_write_inode(fs, ino, &inode,
"pass1");
} else
ext2fs_unmark_valid(fs);
}
}
}
if (ino == EXT2_BOOT_LOADER_INO) {
ext2fs_mark_inode_bitmap(inode_used_map, ino);
check_blocks(fs, ino, &inode, block_buf);
check_blocks(fs, &pctx, block_buf);
goto next;
}
if ((ino != EXT2_ROOT_INO) &&
(ino < EXT2_FIRST_INODE(fs->super))) {
ext2fs_mark_inode_bitmap(inode_used_map, ino);
if (inode.i_mode != 0) {
printf("Reserved inode %lu has bad mode. ", ino);
if (ask("Clear", 1)) {
if (fix_problem(fs,
PR_1_RESERVED_BAD_MODE, &pctx)) {
inode.i_mode = 0;
e2fsck_write_inode(fs, ino, &inode,
"pass1");
} else
ext2fs_unmark_valid(fs);
}
}
check_blocks(fs, ino, &inode, block_buf);
check_blocks(fs, &pctx, block_buf);
goto next;
}
/*
@ -326,14 +345,12 @@ void pass1(ext2_filsys fs)
*/
if (!inode.i_links_count) {
if (!inode.i_dtime && inode.i_mode) {
printf("Deleted inode %lu has zero dtime.\n",
ino);
if (ask("Set dtime", 1)) {
if (fix_problem(fs,
PR_1_ZERO_DTIME, &pctx)) {
inode.i_dtime = time(0);
e2fsck_write_inode(fs, ino, &inode,
"pass1");
} else
ext2fs_unmark_valid(fs);
}
}
goto next;
}
@ -348,13 +365,10 @@ void pass1(ext2_filsys fs)
*
*/
if (inode.i_dtime) {
printf("Inode %lu is in use, but has dtime set\n",
ino);
if (ask("Clear dtime", 1)) {
if (fix_problem(fs, PR_1_SET_DTIME, &pctx)) {
inode.i_dtime = 0;
e2fsck_write_inode(fs, ino, &inode, "pass1");
} else
ext2fs_unmark_valid(fs);
}
}
ext2fs_mark_inode_bitmap(inode_used_map, ino);
@ -384,7 +398,7 @@ void pass1(ext2_filsys fs)
if (LINUX_S_ISDIR(inode.i_mode)) {
ext2fs_mark_inode_bitmap(inode_dir_map, ino);
add_dir_info(fs, ino, 0, &inode);
add_dir_info(fs, ino, 0);
fs_directory_count++;
} else if (LINUX_S_ISREG (inode.i_mode))
fs_regular_count++;
@ -394,8 +408,10 @@ void pass1(ext2_filsys fs)
fs_blockdev_count++;
else if (LINUX_S_ISLNK (inode.i_mode)) {
fs_symlinks_count++;
if (!inode.i_blocks)
if (!inode.i_blocks) {
fs_fast_symlinks_count++;
goto next;
}
}
else if (LINUX_S_ISFIFO (inode.i_mode))
fs_fifo_count++;
@ -419,12 +435,19 @@ void pass1(ext2_filsys fs)
inodes_to_process[process_inode_count].inode = inode;
process_inode_count++;
} else
check_blocks(fs, ino, &inode, block_buf);
check_blocks(fs, &pctx, block_buf);
if (process_inode_count >= process_inode_size)
process_inodes(fs, block_buf);
next:
retval = ext2fs_get_next_inode(scan, &ino, &inode);
if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
if (!inode_bb_map)
alloc_bb_map(fs);
ext2fs_mark_inode_bitmap(inode_bb_map, ino);
ext2fs_mark_inode_bitmap(inode_used_map, ino);
goto next;
}
if (retval) {
com_err(program_name, retval,
"while doing inode scan");
@ -435,9 +458,6 @@ void pass1(ext2_filsys fs)
ext2fs_close_inode_scan(scan);
ehandler_operation(0);
qsort(dir_blocks, dir_block_count, sizeof(struct dir_block_struct),
dir_block_cmp);
if (invalid_bitmaps)
handle_fs_bad_blocks(fs);
@ -463,7 +483,7 @@ endit:
free(block_buf);
ext2fs_free_block_bitmap(block_illegal_map);
block_illegal_map = 0;
if (tflag > 1) {
printf("Pass 1: ");
print_resource_track(&rtrack);
@ -488,30 +508,33 @@ static void process_inodes(ext2_filsys fs, char *block_buf)
{
int i;
struct ext2_inode *old_stashed_inode;
ino_t ino;
ino_t old_stashed_ino;
const char *old_operation;
char buf[80];
struct problem_context pctx;
#if 0
printf("begin process_inodes: ");
#endif
old_operation = ehandler_operation(0);
old_stashed_inode = stashed_inode;
old_stashed_ino = stashed_ino;
qsort(inodes_to_process, process_inode_count,
sizeof(struct process_inode_block), process_inode_cmp);
clear_problem_context(&pctx);
for (i=0; i < process_inode_count; i++) {
stashed_inode = &inodes_to_process[i].inode;
ino = inodes_to_process[i].ino;
stashed_ino = ino;
#if 0
printf("%u ", ino);
#endif
sprintf(buf, "reading indirect blocks of inode %lu", ino);
ehandler_operation(buf);
check_blocks(fs, ino, stashed_inode, block_buf);
pctx.inode = stashed_inode = &inodes_to_process[i].inode;
pctx.ino = stashed_ino = inodes_to_process[i].ino;
#if 0
printf("%u ", pctx.ino);
#endif
sprintf(buf, "reading indirect blocks of inode %lu", pctx.ino);
ehandler_operation(buf);
check_blocks(fs, &pctx, block_buf);
}
stashed_inode = old_stashed_inode;
stashed_ino = old_stashed_ino;
process_inode_count = 0;
#if 0
printf("end process inodes\n");
@ -530,22 +553,6 @@ static int process_inode_cmp(const void *a, const void *b)
ib_b->inode.i_block[EXT2_IND_BLOCK]);
}
static int dir_block_cmp(const void *a, const void *b)
{
const struct dir_block_struct *db_a =
(const struct dir_block_struct *) a;
const struct dir_block_struct *db_b =
(const struct dir_block_struct *) b;
if (db_a->blk != db_b->blk)
return (db_a->blk - db_b->blk);
if (db_a->ino != db_b->ino)
return (db_a->ino - db_b->ino);
return (db_a->blockcnt - db_b->blockcnt);
}
/*
* This procedure will allocate the inode bad map table
*/
@ -562,6 +569,22 @@ static void alloc_bad_map(ext2_filsys fs)
}
}
/*
* This procedure will allocate the inode "bb" (badblock) map table
*/
static void alloc_bb_map(ext2_filsys fs)
{
errcode_t retval;
retval = ext2fs_allocate_inode_bitmap(fs, "inode in bad block map",
&inode_bb_map);
if (retval) {
com_err("ext2fs_allocate_inode_bitmap", retval,
"while allocating inode in bad block map");
fatal_error(0);
}
}
/*
* Marks a block as in use, setting the dup_map if it's been set
* already. Called by process_block and process_bad_block.
@ -593,27 +616,30 @@ static _INLINE_ void mark_block_used(ext2_filsys fs, blk_t block)
* This subroutine is called on each inode to account for all of the
* blocks used by that inode.
*/
static void check_blocks(ext2_filsys fs, ino_t ino, struct ext2_inode *inode,
static void check_blocks(ext2_filsys fs, struct problem_context *pctx,
char *block_buf)
{
struct process_block_struct pb;
errcode_t retval;
ino_t ino = pctx->ino;
struct ext2_inode *inode = pctx->inode;
if (!inode_has_valid_blocks(inode))
if (!ext2fs_inode_has_valid_blocks(pctx->inode))
return;
pb.ino = ino;
pb.num_blocks = pb.last_block = 0;
pb.num_illegal_blocks = 0;
pb.suppress = pb.clear = 0;
pb.suppress = 0; pb.clear = 0;
pb.fragmented = 0;
pb.previous_block = 0;
pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
pb.fix = -1;
pb.is_dir = LINUX_S_ISDIR(pctx->inode->i_mode);
pb.inode = inode;
retval = ext2fs_block_iterate(fs, ino,
pb.is_dir ? BLOCK_FLAG_HOLE : 0,
block_buf, process_block, &pb);
pb.pctx = pctx;
retval = ext2fs_block_iterate2(fs, ino,
pb.is_dir ? BLOCK_FLAG_HOLE : 0,
block_buf, process_block, &pb);
reset_problem_latch(PR_LATCH_BLOCK);
if (retval)
com_err(program_name, retval,
"while calling ext2fs_block_iterate in check_blocks");
@ -629,7 +655,7 @@ static void check_blocks(ext2_filsys fs, ino_t ino, struct ext2_inode *inode,
fatal_error(0);
}
inode->i_links_count = 0;
inode_link_info[ino] = 0;
ext2fs_icount_store(inode_link_info, ino, 0);
inode->i_dtime = time(0);
e2fsck_write_inode(fs, ino, inode, "check_blocks");
ext2fs_unmark_inode_bitmap(inode_dir_map, ino);
@ -643,9 +669,6 @@ static void check_blocks(ext2_filsys fs, ino_t ino, struct ext2_inode *inode,
return;
}
if (pb.fix > 0)
e2fsck_read_inode(fs, ino, inode, "check_blocks");
pb.num_blocks *= (fs->blocksize / 512);
#if 0
printf("inode %u, i_size = %lu, last_block = %lu, i_blocks=%lu, num_blocks = %lu\n",
@ -653,41 +676,38 @@ static void check_blocks(ext2_filsys fs, ino_t ino, struct ext2_inode *inode,
pb.num_blocks);
#endif
if (!pb.num_blocks && pb.is_dir) {
printf("Inode %lu is a zero length directory. ", ino);
if (ask("Clear", 1)) {
if (fix_problem(fs, PR_1_ZERO_LENGTH_DIR, pctx)) {
inode->i_links_count = 0;
inode_link_info[ino] = 0;
ext2fs_icount_store(inode_link_info, ino, 0);
inode->i_dtime = time(0);
e2fsck_write_inode(fs, ino, inode, "check_blocks");
ext2fs_unmark_inode_bitmap(inode_dir_map, ino);
ext2fs_unmark_inode_bitmap(inode_used_map, ino);
fs_directory_count--;
pb.is_dir = 0;
} else
ext2fs_unmark_valid(fs);
}
}
if ((pb.is_dir && (inode->i_size != (pb.last_block + 1) * fs->blocksize)) ||
if ((pb.is_dir && (inode->i_size !=
(pb.last_block + 1) * fs->blocksize)) ||
(inode->i_size < pb.last_block * fs->blocksize)) {
printf ("%s %lu, incorrect size, %u (counted = %u). ",
pb.is_dir ? "Directory" : "Inode", ino, inode->i_size,
(pb.last_block+1) * fs->blocksize);
if (ask ("Set size to counted", 1)) {
inode->i_size = (pb.last_block+1) * fs->blocksize;
pctx->num = (pb.last_block+1) * fs->blocksize;
if (fix_problem(fs, PR_1_BAD_I_SIZE, pctx)) {
inode->i_size = pctx->num;
e2fsck_write_inode(fs, ino, inode, "check_blocks");
} else
ext2fs_unmark_valid(fs);
}
pctx->num = 0;
}
if (pb.num_blocks != inode->i_blocks) {
printf ("Inode %lu, i_blocks wrong %u (counted=%u). ",
ino, inode->i_blocks, pb.num_blocks);
if (ask ("Set i_blocks to counted", 1)) {
pctx->num = pb.num_blocks;
if (fix_problem(fs, PR_1_BAD_I_BLOCKS, pctx)) {
inode->i_blocks = pb.num_blocks;
e2fsck_write_inode(fs, ino, inode, "check_blocks");
} else
ext2fs_unmark_valid(fs);
}
pctx->num = 0;
}
}
#if 0
/*
* Helper function called by process block when an illegal block is
* found. It returns a description about why the block is illegal
@ -737,6 +757,7 @@ static char *describe_illegal_block(ext2_filsys fs, blk_t block)
}
return(problem);
}
#endif
/*
* This is a helper function for check_blocks().
@ -744,14 +765,19 @@ static char *describe_illegal_block(ext2_filsys fs, blk_t block)
int process_block(ext2_filsys fs,
blk_t *block_nr,
int blockcnt,
blk_t ref_block,
int ref_offset,
void *private)
{
struct process_block_struct *p;
char *problem;
struct problem_context *pctx;
blk_t blk = *block_nr;
int ret_code = 0;
int problem = 0;
errcode_t retval;
p = (struct process_block_struct *) private;
pctx = p->pctx;
if (blk == 0) {
if (p->is_dir == 0) {
@ -767,8 +793,10 @@ int process_block(ext2_filsys fs,
if (blockcnt < 0)
return 0;
if (blockcnt * fs->blocksize < p->inode->i_size) {
printf("Hole found in directory inode %lu! "
"(blkcnt=%d)\n", p->ino, blockcnt);
#if 0
printf("Missing block (#%d) in directory inode %lu!\n",
blockcnt, p->ino);
#endif
goto mark_dir;
}
return 0;
@ -790,43 +818,34 @@ int process_block(ext2_filsys fs,
}
p->previous_block = blk;
if (blk < fs->super->s_first_data_block ||
blk >= fs->super->s_blocks_count ||
ext2fs_test_block_bitmap(block_illegal_map, blk)) {
problem = describe_illegal_block(fs, blk);
if (preen) {
printf("Block %u of inode %lu %s\n", blk, p->ino,
problem);
preenhalt(fs);
}
if (p->fix == -1) {
printf("Remove illegal block(s) in inode %lu", p->ino);
p->fix = ask("", 1);
}
blk >= fs->super->s_blocks_count)
problem = PR_1_ILLEGAL_BLOCK_NUM;
else if (ext2fs_test_block_bitmap(block_illegal_map, blk))
problem = PR_1_BLOCK_OVERLAPS_METADATA;
if (problem) {
p->num_illegal_blocks++;
if (!p->suppress && (p->num_illegal_blocks % 20) == 0) {
printf("Too many illegal blocks in inode %lu.\n",
p->ino);
if (ask("Clear inode", 1)) {
if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
if (fix_problem(fs, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
p->clear = 1;
return BLOCK_ABORT;
}
if (ask("Supress messages", 0)) {
if (ask("Suppress messages", 0)) {
p->suppress = 1;
suppress_latch_group(PR_LATCH_BLOCK, 1);
}
}
if (!p->suppress)
printf("Block #%d (%u) %s. %s\n", blockcnt, blk,
problem, clear_msg[p->fix]);
if (p->fix) {
pctx->blk = blk;
pctx->blkcount = blockcnt;
if (fix_problem(fs, problem, pctx)) {
blk = *block_nr = 0;
ret_code = BLOCK_CHANGED;
goto mark_dir;
} else {
ext2fs_unmark_valid(fs);
} else
return 0;
}
pctx->blk = 0;
pctx->blkcount = -1;
}
mark_block_used(fs, blk);
@ -835,20 +854,13 @@ int process_block(ext2_filsys fs,
p->last_block = blockcnt;
mark_dir:
if (p->is_dir && (blockcnt >= 0)) {
if (dir_block_count >= dir_block_size) {
dir_block_size += 100;
dir_blocks = realloc(dir_blocks,
dir_block_size *
sizeof(struct dir_block_struct));
if (dir_blocks == 0)
fatal_error("Not enough memory to "
"realloc dir_blocks");
retval = ext2fs_add_dir_block(fs->dblist, p->ino,
blk, blockcnt);
if (retval) {
com_err(program_name, retval,
"while adding to directory block list");
fatal_error(0);
}
dir_blocks[dir_block_count].blk = blk;
dir_blocks[dir_block_count].ino = p->ino;
dir_blocks[dir_block_count].blockcnt = blockcnt;
dir_block_count++;
}
return ret_code;
}
@ -886,34 +898,33 @@ static int bad_primary_block(ext2_filsys fs, blk_t *block_nr)
int process_bad_block(ext2_filsys fs,
blk_t *block_nr,
int blockcnt,
blk_t ref_block,
int ref_offset,
void *private)
{
struct process_block_struct *p;
blk_t blk = *block_nr;
int first_block;
int i;
struct problem_context *pctx;
if (!blk)
return 0;
p = (struct process_block_struct *) private;
pctx = p->pctx;
pctx->blk = blk;
pctx->blkcount = blockcnt;
if ((blk < fs->super->s_first_data_block) ||
(blk >= fs->super->s_blocks_count)) {
if (preen) {
printf("Illegal block %u in bad block inode\n", blk);
preenhalt(fs);
}
if (p->fix == -1)
p->fix = ask("Remove illegal block(s) in bad block inode", 1);
printf("Illegal block %u in bad block inode. %s\n", blk,
clear_msg[p->fix]);
if (p->fix) {
if (fix_problem(fs, PR_1_BB_ILLEGAL_BLOCK_NUM, pctx)) {
*block_nr = 0;
return BLOCK_CHANGED;
} else {
ext2fs_unmark_valid(fs);
} else
return 0;
}
}
if (blockcnt < 0) {
@ -943,6 +954,7 @@ int process_bad_block(ext2_filsys fs,
first_block = fs->super->s_first_data_block;
for (i = 0; i < fs->group_desc_count; i++ ) {
pctx->group = i;
if (blk == first_block) {
if (i == 0) {
printf("The primary superblock (%u) is "
@ -973,39 +985,29 @@ int process_bad_block(ext2_filsys fs,
return 0;
}
if (blk == fs->group_desc[i].bg_block_bitmap) {
printf("Group %d's block bitmap (%u) is bad. ",
i, blk);
if (ask("Relocate", 1)) {
if (fix_problem(fs, PR_1_BB_BAD_BLOCK, pctx)) {
invalid_block_bitmap[i]++;
invalid_bitmaps++;
} else
ext2fs_unmark_valid(fs);
}
return 0;
}
if (blk == fs->group_desc[i].bg_inode_bitmap) {
printf("Group %d's inode bitmap (%u) is bad. ",
i, blk);
if (ask("Relocate", 1)) {
if (fix_problem(fs, PR_1_IB_BAD_BLOCK, pctx)) {
invalid_inode_bitmap[i]++;
invalid_bitmaps++;
} else
ext2fs_unmark_valid(fs);
}
return 0;
}
if ((blk >= fs->group_desc[i].bg_inode_table) &&
(blk < (fs->group_desc[i].bg_inode_table +
fs->inode_blocks_per_group))) {
printf("WARNING: Severe data loss possible!!!!\n");
printf("Bad block %u in group %d's inode table. ",
blk, i);
if (ask("Relocate", 1)) {
invalid_inode_table[i]++;
invalid_bitmaps++;
} else
ext2fs_unmark_valid(fs);
/*
* If there are bad blocks in the inode table,
* the inode scan code will try to do
* something reasonable automatically.
*/
return 0;
}
first_block += fs->super->s_blocks_per_group;
}
/*
* If we've gotten to this point, then the only
@ -1114,24 +1116,47 @@ static void mark_table_blocks(ext2_filsys fs)
{
blk_t block, b;
int i,j;
struct problem_context pctx;
clear_problem_context(&pctx);
block = fs->super->s_first_data_block;
for (i = 0; i < fs->group_desc_count; i++) {
pctx.group = i;
/*
* Mark the blocks used for the inode table
*/
if (fs->group_desc[i].bg_inode_table) {
for (j = 0, b = fs->group_desc[i].bg_inode_table;
j < fs->inode_blocks_per_group;
j++, b++) {
if (ext2fs_test_block_bitmap(block_found_map,
b)) {
pctx.blk = b;
if (fix_problem(fs,
PR_1_ITABLE_CONFLICT, &pctx)) {
invalid_inode_table[i]++;
invalid_bitmaps++;
}
} else {
ext2fs_mark_block_bitmap(block_found_map,
b);
ext2fs_mark_block_bitmap(block_illegal_map,
b);
}
}
}
/*
* Mark block used for the block bitmap
*/
if (fs->group_desc[i].bg_block_bitmap) {
if (ext2fs_test_block_bitmap(block_found_map,
fs->group_desc[i].bg_block_bitmap)) {
printf("Group %i's block bitmap at %u "
"conflicts with some other fs block.\n",
i, fs->group_desc[i].bg_block_bitmap);
preenhalt(fs);
if (ask("Relocate", 1)) {
pctx.blk = fs->group_desc[i].bg_block_bitmap;
if (fix_problem(fs, PR_1_BB_CONFLICT, &pctx)) {
invalid_block_bitmap[i]++;
invalid_bitmaps++;
} else {
ext2fs_unmark_valid(fs);
}
} else {
ext2fs_mark_block_bitmap(block_found_map,
@ -1147,16 +1172,11 @@ static void mark_table_blocks(ext2_filsys fs)
if (fs->group_desc[i].bg_inode_bitmap) {
if (ext2fs_test_block_bitmap(block_found_map,
fs->group_desc[i].bg_inode_bitmap)) {
printf("Group %i's inode bitmap at %u "
"conflicts with some other fs block.\n",
i, fs->group_desc[i].bg_inode_bitmap);
preenhalt(fs);
if (ask("Relocate", 1)) {
pctx.blk = fs->group_desc[i].bg_inode_bitmap;
if (fix_problem(fs, PR_1_IB_CONFLICT, &pctx)) {
invalid_inode_bitmap[i]++;
invalid_bitmaps++;
} else {
ext2fs_unmark_valid(fs);
}
}
} else {
ext2fs_mark_block_bitmap(block_found_map,
fs->group_desc[i].bg_inode_bitmap);
@ -1165,35 +1185,6 @@ static void mark_table_blocks(ext2_filsys fs)
}
}
/*
* Mark the blocks used for the inode table
*/
if (fs->group_desc[i].bg_inode_table) {
for (j = 0, b = fs->group_desc[i].bg_inode_table;
j < fs->inode_blocks_per_group;
j++, b++) {
if (ext2fs_test_block_bitmap(block_found_map,
b)) {
printf("Group %i's inode table at %u "
"conflicts with some other "
"fs block.\n",
i, b);
preenhalt(fs);
if (ask("Relocate", 1)) {
invalid_inode_table[i]++;
invalid_bitmaps++;
} else {
ext2fs_unmark_valid(fs);
}
} else {
ext2fs_mark_block_bitmap(block_found_map,
b);
ext2fs_mark_block_bitmap(block_illegal_map,
b);
}
}
}
/*
* Mark this group's copy of the superblock
*/

View File

@ -18,8 +18,12 @@
* (so that the file gets a fresh copy of the duplicated blocks) or
* simply to delete the file.
*
* Copyright (C) 1993, 1994 Theodore Ts'o. This file may be
* redistributed under the terms of the GNU Public License.
* Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*
*/
@ -31,6 +35,8 @@
#include <et/com_err.h>
#include "e2fsck.h"
#include "problem.h"
/*
* This is structure is allocated for each time that a block is
* claimed by more than one file. So if a particular block is claimed
@ -75,16 +81,12 @@ struct dup_block {
* of multiply-claimed blocks.
*/
struct dup_inode {
ino_t ino;
time_t mtime;
char *pathname;
int num_dupblocks;
int flags;
ino_t ino, dir;
int num_dupblocks;
struct ext2_inode inode;
struct dup_inode *next;
};
#define DUP_INODE_DONT_FREE_PATHNAME 0x1
static int process_pass1b_block(ext2_filsys fs, blk_t *blocknr,
int blockcnt, void *private);
static void delete_file(ext2_filsys fs, struct dup_inode *dp,
@ -125,7 +127,7 @@ void pass1_dupblocks(ext2_filsys fs, char *block_buf)
* Time to free all of the accumulated data structures that we
* don't need anymore.
*/
ext2fs_free_inode_bitmap(inode_dup_map); inode_dup_map = 0;
ext2fs_free_inode_bitmap(inode_dup_map); inode_dup_map = 0;
ext2fs_free_block_bitmap(block_dup_map); block_dup_map = 0;
for (p = dup_blk; p; p = next_p) {
next_p = p->next_block;
@ -136,8 +138,6 @@ void pass1_dupblocks(ext2_filsys fs, char *block_buf)
}
for (r = dup_ino; r; r = next_r) {
next_r = r->next;
if (r->pathname && !(r->flags & DUP_INODE_DONT_FREE_PATHNAME))
free(r->pathname);
free(r);
}
}
@ -176,7 +176,7 @@ void pass1b(ext2_filsys fs, char *block_buf)
stashed_ino = ino;
if ((ino != EXT2_BAD_INO) &&
(!ext2fs_test_inode_bitmap(inode_used_map, ino) ||
!inode_has_valid_blocks(&inode)))
!ext2fs_inode_has_valid_blocks(&inode)))
goto next;
pb.ino = ino;
@ -189,10 +189,9 @@ void pass1b(ext2_filsys fs, char *block_buf)
dp = allocate_memory(sizeof(struct dup_inode),
"duplicate inode record");
dp->ino = ino;
dp->mtime = inode.i_mtime;
dp->dir = 0;
dp->inode = inode;
dp->num_dupblocks = pb.dup_blocks;
dp->pathname = 0;
dp->flags = 0;
dp->next = dup_ino;
dup_ino = dp;
if (ino != EXT2_BAD_INO)
@ -270,113 +269,71 @@ int process_pass1b_block(ext2_filsys fs,
return 0;
}
/*
* Used by pass1c to name the "special" inodes. They are declared as
* writeable strings to prevent const problems.
*/
#define num_special_inodes 7
char special_inode_name[num_special_inodes][40] =
{
"<The NULL inode>", /* 0 */
"<The bad blocks inode>", /* 1 */
"/", /* 2 */
"<The ACL index inode>", /* 3 */
"<The ACL data inode>", /* 4 */
"<The boot loader inode>", /* 5 */
"<The undelete directory inode>" /* 6 */
};
/*
* Pass 1c: Scan directories for inodes with duplicate blocks. This
* is used so that we can print pathnames when prompting the user for
* what to do.
*/
struct process_dir_struct {
ext2_filsys fs;
ino_t dir_ino;
struct search_dir_struct {
int count;
ino_t first_inode;
};
static int search_dirent_proc(ino_t dir, int entry,
struct ext2_dir_entry *dirent,
int offset, int blocksize,
char *buf, void *private)
{
struct search_dir_struct *sd = private;
struct dup_inode *p;
if (!dirent->inode || (entry < DIRENT_OTHER_FILE) ||
!ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
return 0;
for (p = dup_ino; p; p = p->next) {
if ((p->ino >= sd->first_inode) &&
(p->ino == dirent->inode))
break;
}
if (!p || p->dir)
return 0;
p->dir = dir;
sd->count--;
return(sd->count ? 0 : DIRENT_ABORT);
}
void pass1c(ext2_filsys fs, char *block_buf)
{
int i;
struct dup_inode *p;
errcode_t retval;
char buf[80];
int inodes_left = dup_inode_count;
int offset, entry;
struct ext2_dir_entry *dirent;
struct search_dir_struct sd;
printf("Pass 1C: Scan directories for inodes with dup blocks.\n");
/*
* First check to see if any of the inodes with dup blocks is
* the bad block inode or the root inode; handle them as
* special cases.
* a special inode. (Note that the bad block inode isn't
* counted.)
*/
for (p = dup_ino; p; p = p->next) {
if (p->ino < num_special_inodes) {
p->pathname = special_inode_name[p->ino];
p->flags |= DUP_INODE_DONT_FREE_PATHNAME;
if ((p->ino < EXT2_FIRST_INODE(fs->super)) &&
(p->ino != EXT2_BAD_INO))
inodes_left--;
}
}
/*
* Search through all directories to translate inodes to names
* (by searching for the containing directory for that inode.)
*/
for (i=0; inodes_left && i < dir_block_count; i++) {
retval = ext2fs_read_dir_block(fs, dir_blocks[i].blk,
block_buf);
entry = offset = 0;
while (offset < fs->blocksize) {
entry++;
dirent = (struct ext2_dir_entry *)
(block_buf + offset);
if (!dirent->inode ||
((dir_blocks[i].blockcnt == 0) && (entry <= 2)))
goto next;
if (!ext2fs_test_inode_bitmap(inode_dup_map,
dirent->inode))
goto next;
for (p = dup_ino; p; p = p->next) {
if (p->ino == dirent->inode)
break;
}
if (!p || p->pathname)
goto next;
(void) ext2fs_get_pathname(fs, dir_blocks[i].ino,
p->ino, &p->pathname);
inodes_left--;
next:
if (dirent->rec_len < 8)
break;
offset += dirent->rec_len;
}
}
/*
* If we can't get a name, then put in a generic one.
*/
for (p = dup_ino; p; p = p->next) {
if (!p->pathname) {
sprintf(buf, "<Unknown inode #%lu>", p->ino);
p->pathname = malloc(strlen(buf)+1);
if (!p->pathname) {
fprintf(stderr, "pass1c: couldn't malloc "
"generic pathname\n");
fatal_error(0);
}
strcpy(p->pathname, buf);
}
}
sd.count = inodes_left;
sd.first_inode = EXT2_FIRST_INODE(fs->super);
ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
search_dirent_proc, &sd);
}
static void pass1d(ext2_filsys fs, char *block_buf)
@ -387,8 +344,8 @@ static void pass1d(ext2_filsys fs, char *block_buf)
int shared_len;
int i;
errcode_t retval;
char *time_str;
int file_ok;
struct problem_context pctx;
printf("Pass 1D: Reconciling duplicate blocks\n");
read_bitmaps(fs);
@ -436,23 +393,33 @@ static void pass1d(ext2_filsys fs, char *block_buf)
}
}
}
time_str = ctime(&p->mtime);
time_str[24] = 0;
printf("File %s (inode #%lu, mod time %s) \n",
p->pathname, p->ino, time_str);
printf(" has %d duplicate blocks, shared with %d file%s:\n",
p->num_dupblocks, shared_len,
(shared_len>1) ? "s" : "");
/*
* Report the inode that we are working on
*/
clear_problem_context(&pctx);
pctx.inode = &p->inode;
pctx.ino = p->ino;
pctx.dir = p->dir;
pctx.blkcount = p->num_dupblocks;
pctx.num = shared_len;
fix_problem(fs, PR_1B_DUP_FILE, &pctx);
pctx.blkcount = 0;
pctx.num = 0;
for (i = 0; i < shared_len; i++) {
for (s = dup_ino; s; s = s->next)
if (s->ino == shared[i])
break;
if (!s)
continue;
time_str = ctime(&s->mtime);
time_str[24] = 0;
printf("\t%s (inode #%lu, mod time %s)\n",
s->pathname, s->ino, time_str);
/*
* Report the inode that we are sharing with
*/
pctx.inode = &s->inode;
pctx.ino = s->ino;
pctx.dir = s->dir;
fix_problem(fs, PR_1B_DUP_FILE_LIST, &pctx);
}
if (file_ok) {
printf("Duplicated blocks already reassigned or cloned.\n\n");

View File

@ -1,8 +1,12 @@
/*
* pass2.c --- check directory structure
*
* Copyright (C) 1993, 1994 Theodore Ts'o. This file may be
* redistributed under the terms of the GNU Public License.
* Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*
* Pass 2 of e2fsck iterates through all active directory inodes, and
* applies to following tests to each directory entry in the directory
@ -39,32 +43,41 @@
#include "et/com_err.h"
#include "e2fsck.h"
#include "problem.h"
/*
* Keeps track of how many times an inode is referenced.
*/
unsigned short * inode_count;
ext2_icount_t inode_count = 0;
static void deallocate_inode(ext2_filsys fs, ino_t ino,
char* block_buf);
static int process_bad_inode(ext2_filsys fs, ino_t dir, ino_t ino);
static int check_dir_block(ext2_filsys fs,
struct dir_block_struct *dir_blocks_info,
char *buf);
struct ext2_db_entry *dir_blocks_info,
void *private);
static int allocate_dir_block(ext2_filsys fs,
struct dir_block_struct *dir_blocks_info,
char *buf);
struct ext2_db_entry *dir_blocks_info,
char *buf, struct problem_context *pctx);
static int update_dir_block(ext2_filsys fs,
blk_t *block_nr,
int blockcnt,
void *private);
struct check_dir_struct {
char *buf;
struct problem_context pctx;
};
void pass2(ext2_filsys fs)
{
int i;
char *buf;
struct resource_track rtrack;
struct dir_info *dir;
errcode_t retval;
ino_t size;
struct check_dir_struct cd;
init_resource_track(&rtrack);
#ifdef MTRACE
@ -73,17 +86,33 @@ void pass2(ext2_filsys fs)
if (!preen)
printf("Pass 2: Checking directory structure\n");
inode_count = allocate_memory((fs->super->s_inodes_count + 1) *
sizeof(unsigned short),
"buffer for inode count");
size = ext2fs_get_icount_size(inode_link_info) + 10;
retval = ext2fs_create_icount(fs, EXT2_ICOUNT_OPT_INCREMENT,
size, &inode_count);
if (retval) {
com_err("ext2fs_create_icount", retval,
"while creating inode_count");
fatal_error(0);
}
buf = allocate_memory(fs->blocksize, "directory scan buffer");
for (i=0; i < dir_block_count; i++)
check_dir_block(fs, &dir_blocks[i], buf);
/*
* Set up the parent pointer for the root directory, if
* present. (If the root directory is not present, we will
* create it in pass 3.)
*/
dir = get_dir_info(EXT2_ROOT_INO);
if (dir)
dir->parent = EXT2_ROOT_INO;
cd.buf = buf;
clear_problem_context(&cd.pctx);
retval = ext2fs_dblist_iterate(fs->dblist, check_dir_block, &cd);
free(buf);
free(dir_blocks);
ext2fs_free_dblist(fs->dblist);
if (inode_bad_map) {
ext2fs_free_inode_bitmap(inode_bad_map);
inode_bad_map = 0;
@ -100,54 +129,39 @@ void pass2(ext2_filsys fs)
*/
static int check_dot(ext2_filsys fs,
struct ext2_dir_entry *dirent,
ino_t ino)
ino_t ino, struct problem_context *pctx)
{
struct ext2_dir_entry *nextdir;
int status = 0;
int created = 0;
int new_len;
const char *question = 0;
int problem = 0;
if (!dirent->inode) {
printf("Missing '.' in directory inode %lu.\n", ino);
question = "Fix";
} else if ((dirent->name_len != 1) ||
strncmp(dirent->name, ".", dirent->name_len)) {
char *name = malloc(dirent->name_len + 1);
if (!name)
fatal_error("Couldn't allocate . name");
strncpy(name, dirent->name, dirent->name_len);
name[dirent->name_len] = '\0';
printf("First entry in directory inode %lu contains '%s' "
"(inode=%u)\n", ino, name, dirent->inode);
printf("instead of '.'.\n");
free(name);
question = "Change to be '.'";
}
if (question) {
if (dirent->rec_len < 12)
fatal_error("Cannot fix, insufficient space to add '.'");
preenhalt(fs);
if (ask(question, 1)) {
if (!dirent->inode)
problem = PR_2_MISSING_DOT;
else if ((dirent->name_len != 1) ||
(dirent->name[0] != '.'))
problem = PR_2_1ST_NOT_DOT;
else if (dirent->name[1] != '\0')
problem = PR_2_DOT_NULL_TERM;
if (problem) {
if (fix_problem(fs, problem, pctx)) {
if (dirent->rec_len < 12)
dirent->rec_len = 12;
dirent->inode = ino;
dirent->name_len = 1;
dirent->name[0] = '.';
dirent->name[1] = '\0';
status = 1;
created = 1;
} else {
ext2fs_unmark_valid(fs);
return 0;
}
}
if (dirent->inode != ino) {
printf("Bad inode number for '.' in directory inode %lu.\n",
ino);
preenhalt(fs);
if (ask("Fix", 1)) {
if (fix_problem(fs, PR_2_BAD_INODE_DOT, pctx)) {
dirent->inode = ino;
status = 1;
} else
ext2fs_unmark_valid(fs);
}
}
if (dirent->rec_len > 12) {
new_len = dirent->rec_len - 12;
@ -175,32 +189,23 @@ static int check_dot(ext2_filsys fs,
*/
static int check_dotdot(ext2_filsys fs,
struct ext2_dir_entry *dirent,
struct dir_info *dir)
struct dir_info *dir, struct problem_context *pctx)
{
ino_t ino = dir->ino;
const char *question = 0;
int problem = 0;
if (!dirent->inode) {
printf("Missing '..' in directory inode %lu.\n", ino);
question = "Fix";
} else if ((dirent->name_len != 2) ||
strncmp(dirent->name, "..", dirent->name_len)) {
char *name = malloc(dirent->name_len + 1);
if (!name)
fatal_error("Couldn't allocate bad .. name");
strncpy(name, dirent->name, dirent->name_len);
name[dirent->name_len] = '\0';
printf("Second entry in directory inode %lu contains '%s' "
"(inode=%u)\n", ino, name, dirent->inode);
printf("instead of '..'.\n");
free(name);
question = "Change to be '..'";
}
if (question) {
if (dirent->rec_len < 12)
fatal_error("Cannot fix, insufficient space to add '..'");
preenhalt(fs);
if (ask(question, 1)) {
if (!dirent->inode)
problem = PR_2_MISSING_DOT_DOT;
else if ((dirent->name_len != 2) ||
(dirent->name[0] != '.') ||
(dirent->name[1] != '.'))
problem = PR_2_2ND_NOT_DOT_DOT;
else if (dirent->name[2] != '\0')
problem = PR_2_DOT_DOT_NULL_TERM;
if (problem) {
if (fix_problem(fs, problem, pctx)) {
if (dirent->rec_len < 12)
dirent->rec_len = 12;
/*
* Note: we don't have the parent inode just
* yet, so we will fill it in with the root
@ -210,74 +215,57 @@ static int check_dotdot(ext2_filsys fs,
dirent->name_len = 2;
dirent->name[0] = '.';
dirent->name[1] = '.';
dirent->name[2] = '\0';
return 1;
} else
ext2fs_unmark_valid(fs);
}
return 0;
}
dir->dotdot = dirent->inode;
return 0;
}
static char unknown_pathname[] = "???";
/*
* Check to make sure a directory entry doesn't contain any illegal
* characters.
*/
static int check_name(ext2_filsys fs,
struct ext2_dir_entry *dirent,
ino_t dir_ino,
char *name)
ino_t dir_ino, struct problem_context *pctx)
{
int i;
int fixup = -1;
char *pathname;
int ret = 0;
errcode_t retval;
for ( i = 0; i < dirent->name_len; i++) {
if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
if (fixup < 0) {
retval = ext2fs_get_pathname(fs, dir_ino,
0, &pathname);
if (retval) {
com_err(program_name, retval, "while getting pathname in check_name");
pathname = unknown_pathname;
}
printf ("Bad file name '%s' (contains '/' or "
" null) in directory '%s' (%lu)\n",
name, pathname, dir_ino);
if (pathname != unknown_pathname)
free(pathname);
preenhalt(fs);
fixup = ask("Replace '/' or null by '.'", 1);
fixup = fix_problem(fs, PR_2_BAD_NAME, pctx);
}
if (fixup) {
dirent->name[i] = '.';
ret = 1;
} else
ext2fs_unmark_valid(fs);
}
}
}
return ret;
}
static int check_dir_block(ext2_filsys fs,
struct dir_block_struct *db,
char *buf)
struct ext2_db_entry *db,
void *private)
{
struct dir_info *subdir, *dir;
struct ext2_dir_entry *dirent;
int offset = 0;
int dir_modified = 0;
errcode_t retval;
char *path1, *path2;
int dot_state, name_len;
int dot_state;
blk_t block_nr = db->blk;
ino_t ino = db->ino;
char name[EXT2_NAME_LEN+1];
__u16 links;
struct check_dir_struct *cd = private;
char *buf = cd->buf;
/*
* Make sure the inode is still in use (could have been
* deleted in the duplicate/bad blocks pass.
@ -285,8 +273,15 @@ static int check_dir_block(ext2_filsys fs,
if (!(ext2fs_test_inode_bitmap(inode_used_map, ino)))
return 0;
cd->pctx.ino = ino;
cd->pctx.blk = block_nr;
cd->pctx.blkcount = db->blockcnt;
cd->pctx.ino2 = 0;
cd->pctx.dirent = 0;
cd->pctx.num = 0;
if (db->blk == 0) {
if (allocate_dir_block(fs, db, buf))
if (allocate_dir_block(fs, db, buf, &cd->pctx))
return 0;
block_nr = db->blk;
}
@ -310,40 +305,30 @@ static int check_dir_block(ext2_filsys fs,
do {
dot_state++;
dirent = (struct ext2_dir_entry *) (buf + offset);
cd->pctx.dirent = dirent;
cd->pctx.num = offset;
if (((offset + dirent->rec_len) > fs->blocksize) ||
(dirent->rec_len < 8) ||
((dirent->rec_len % 4) != 0) ||
((dirent->name_len+8) > dirent->rec_len)) {
printf("Directory inode %lu, block %d, offset %d: directory corrupted\n",
ino, db->blockcnt, offset);
preenhalt(fs);
if (ask("Salvage", 1)) {
if (fix_problem(fs, PR_2_DIR_CORRUPTED, &cd->pctx)) {
dirent->rec_len = fs->blocksize - offset;
dirent->name_len = 0;
dirent->inode = 0;
dir_modified++;
} else {
ext2fs_unmark_valid(fs);
} else
return DIRENT_ABORT;
}
}
name_len = dirent->name_len;
if (dirent->name_len > EXT2_NAME_LEN) {
printf("Directory inode %lu, block %d, offset %d: filename too long\n",
ino, db->blockcnt, offset);
preenhalt(fs);
if (ask("Truncate filename", 1)) {
if (fix_problem(fs, PR_2_FILENAME_LONG, &cd->pctx)) {
dirent->name_len = EXT2_NAME_LEN;
dir_modified++;
}
name_len = EXT2_NAME_LEN;
}
strncpy(name, dirent->name, name_len);
name[name_len] = '\0';
if (dot_state == 1) {
if (check_dot(fs, dirent, ino))
if (check_dot(fs, dirent, ino, &cd->pctx))
dir_modified++;
} else if (dot_state == 2) {
dir = get_dir_info(ino);
@ -352,30 +337,19 @@ static int check_dir_block(ext2_filsys fs,
ino);
fatal_error(0);
}
if (check_dotdot(fs, dirent, dir))
if (check_dotdot(fs, dirent, dir, &cd->pctx))
dir_modified++;
} else if (dirent->inode == ino) {
retval = ext2fs_get_pathname(fs, ino, 0, &path1);
if (retval)
path1 = unknown_pathname;
printf("Entry '%s' in %s (%lu) is a link to '.' ",
name, path1, ino);
if (path1 != unknown_pathname)
free(path1);
preenhalt(fs);
if (ask("Clear", 1)) {
if (fix_problem(fs, PR_2_LINK_DOT, &cd->pctx)) {
dirent->inode = 0;
dir_modified++;
goto next;
}
}
if (!dirent->inode)
goto next;
#if 0
printf("Entry '%s', name_len %d, rec_len %d, inode %lu... ",
name, dirent->name_len, dirent->rec_len, dirent->inode);
#endif
if (check_name(fs, dirent, ino, name))
if (check_name(fs, dirent, ino, &cd->pctx))
dir_modified++;
/*
@ -384,40 +358,36 @@ static int check_dir_block(ext2_filsys fs,
if (((dirent->inode != EXT2_ROOT_INO) &&
(dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
(dirent->inode > fs->super->s_inodes_count)) {
retval = ext2fs_get_pathname(fs, ino, 0, &path1);
if (retval)
path1 = unknown_pathname;
printf("Entry '%s' in %s (%lu) has bad inode #: %u.\n",
name, path1, ino, dirent->inode);
if (path1 != unknown_pathname)
free(path1);
preenhalt(fs);
if (ask("Clear", 1)) {
if (fix_problem(fs, PR_2_BAD_INO, &cd->pctx)) {
dirent->inode = 0;
dir_modified++;
goto next;
} else
ext2fs_unmark_valid(fs);
}
}
/*
* If the inode is unusued, offer to clear it.
* If the inode is unused, offer to clear it.
*/
if (!(ext2fs_test_inode_bitmap(inode_used_map,
dirent->inode))) {
retval = ext2fs_get_pathname(fs, ino, 0, &path1);
if (retval)
path1 = unknown_pathname;
printf("Entry '%s' in %s (%lu) has deleted/unused inode %u.\n",
name, path1, ino, dirent->inode);
if (path1 != unknown_pathname)
free(path1);
if (ask("Clear", 1)) {
if (fix_problem(fs, PR_2_UNUSED_INODE, &cd->pctx)) {
dirent->inode = 0;
dir_modified++;
goto next;
} else
ext2fs_unmark_valid(fs);
}
}
/*
* If the inode is in a bad block, offer to clear it.
*/
if (inode_bb_map &&
(ext2fs_test_inode_bitmap(inode_bb_map,
dirent->inode))) {
if (fix_problem(fs, PR_2_BB_INODE, &cd->pctx)) {
dirent->inode = 0;
dir_modified++;
goto next;
}
}
/*
@ -436,6 +406,20 @@ static int check_dir_block(ext2_filsys fs,
}
}
/*
* Don't allow links to the root directory. We check
* this specially to make sure we catch this error
* case even if the root directory hasn't been created
* yet.
*/
if ((dot_state > 2) && (dirent->inode == EXT2_ROOT_INO)) {
if (fix_problem(fs, PR_2_LINK_ROOT, &cd->pctx)) {
dirent->inode = 0;
dir_modified++;
goto next;
}
}
/*
* If this is a directory, then mark its parent in its
* dir_info structure. If the parent field is already
@ -453,34 +437,20 @@ static int check_dir_block(ext2_filsys fs,
fatal_error(0);
}
if (subdir->parent) {
retval = ext2fs_get_pathname(fs, ino,
0, &path1);
if (retval)
path1 = unknown_pathname;
retval = ext2fs_get_pathname(fs,
subdir->parent,
dirent->inode,
&path2);
if (retval)
path2 = unknown_pathname;
printf("Entry '%s' in %s (%lu) is a link to directory %s (%u).\n",
name, path1, ino, path2,
dirent->inode);
if (path1 != unknown_pathname)
free(path1);
if (path2 != unknown_pathname)
free(path2);
if (ask("Clear", 1)) {
cd->pctx.ino2 = subdir->parent;
if (fix_problem(fs, PR_2_LINK_DIR,
&cd->pctx)) {
dirent->inode = 0;
dir_modified++;
goto next;
} else
ext2fs_unmark_valid(fs);
}
subdir->parent = ino;
}
cd->pctx.ino2 = 0;
} else
subdir->parent = ino;
}
if (inode_count[dirent->inode]++ > 0)
ext2fs_icount_increment(inode_count, dirent->inode, &links);
if (links > 1)
fs_links_count++;
fs_total_count++;
next:
@ -530,7 +500,7 @@ static void deallocate_inode(ext2_filsys fs, ino_t ino,
errcode_t retval;
struct ext2_inode inode;
inode_link_info[ino] = 0;
ext2fs_icount_store(inode_link_info, ino, 0);
e2fsck_read_inode(fs, ino, &inode, "deallocate_inode");
inode.i_links_count = 0;
inode.i_dtime = time(0);
@ -547,7 +517,7 @@ static void deallocate_inode(ext2_filsys fs, ino_t ino,
ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
ext2fs_mark_ib_dirty(fs);
if (!inode_has_valid_blocks(&inode))
if (!ext2fs_inode_has_valid_blocks(&inode))
return;
ext2fs_mark_bb_dirty(fs);
@ -559,83 +529,34 @@ static void deallocate_inode(ext2_filsys fs, ino_t ino,
ino);
}
/*
* These two subroutines are used by process_bad_inode; it is used to
* make sure that certain reserved fields are really zero. If not,
* prompt the user if he/she wants us to zeroize them.
*/
static void check_for_zero_u32(ext2_filsys fs, ino_t ino, char *pathname,
const char *name, __u32 *val,
int *modified)
{
char prompt[80];
if (*val) {
printf("%s for inode %lu (%s) is %u, should be zero.\n",
name, ino, pathname, *val);
preenhalt(fs);
sprintf(prompt, "Clear %s", name);
if (ask(prompt, 1)) {
*val = 0;
*modified = 1;
} else
ext2fs_unmark_valid(fs);
}
}
static void check_for_zero_u8(ext2_filsys fs, ino_t ino, char *pathname,
const char *name, __u8 *val,
int *modified)
{
char prompt[80];
if (*val) {
printf("%s for inode %lu (%s) is %d, should be zero.\n",
name, ino, pathname, *val);
preenhalt(fs);
sprintf(prompt, "Clear %s", name);
if (ask(prompt, 1)) {
*val = 0;
*modified = 1;
} else
ext2fs_unmark_valid(fs);
}
}
static int process_bad_inode(ext2_filsys fs, ino_t dir, ino_t ino)
{
struct ext2_inode inode;
errcode_t retval;
int inode_modified = 0;
char *pathname;
unsigned char *frag, *fsize;
struct problem_context pctx;
e2fsck_read_inode(fs, ino, &inode, "process_bad_inode");
retval = ext2fs_get_pathname(fs, dir, ino, &pathname);
if (retval) {
com_err("process_bad_inode", retval,
"while getting pathname for inode %d",
ino);
return 0;
}
clear_problem_context(&pctx);
pctx.ino = ino;
pctx.dir = dir;
pctx.inode = &inode;
if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
!LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
!LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
!(LINUX_S_ISSOCK(inode.i_mode))) {
printf("Inode %lu (%s) has a bad mode (0%o).\n",
ino, pathname, inode.i_mode);
preenhalt(fs);
if (ask("Clear", 1)) {
if (fix_problem(fs, PR_2_BAD_MODE, &pctx)) {
deallocate_inode(fs, ino, 0);
free(pathname);
return 1;
} else
ext2fs_unmark_valid(fs);
}
}
if (inode.i_faddr &&
fix_problem(fs, PR_2_FADDR_ZERO, &pctx)) {
inode.i_faddr = 0;
inode_modified++;
}
check_for_zero_u32(fs, ino, pathname, "i_faddr", &inode.i_faddr,
&inode_modified);
switch (fs->super->s_creator_os) {
case EXT2_OS_LINUX:
@ -653,18 +574,33 @@ static int process_bad_inode(ext2_filsys fs, ino_t dir, ino_t ino)
default:
frag = fsize = 0;
}
if (frag)
check_for_zero_u8(fs, ino, pathname, "i_frag", frag,
&inode_modified);
if (fsize)
check_for_zero_u8(fs, ino, pathname, "i_fsize", fsize,
&inode_modified);
if (frag && *frag) {
pctx.num = *frag;
if (fix_problem(fs, PR_2_FRAG_ZERO, &pctx)) {
*frag = 0;
inode_modified++;
}
pctx.num = 0;
}
if (fsize && *fsize) {
pctx.num = *fsize;
if (fix_problem(fs, PR_2_FSIZE_ZERO, &pctx)) {
*fsize = 0;
inode_modified++;
}
pctx.num = 0;
}
check_for_zero_u32(fs, ino, pathname, "i_file_acl", &inode.i_file_acl,
&inode_modified);
check_for_zero_u32(fs, ino, pathname, "i_dir_acl", &inode.i_dir_acl,
&inode_modified);
free(pathname);
if (inode.i_file_acl &&
fix_problem(fs, PR_2_FILE_ACL_ZERO, &pctx)) {
inode.i_file_acl = 0;
inode_modified++;
}
if (inode.i_dir_acl &&
fix_problem(fs, PR_2_DIR_ACL_ZERO, &pctx)) {
inode.i_dir_acl = 0;
inode_modified++;
}
if (inode_modified)
e2fsck_write_inode(fs, ino, &inode, "process_bad_inode");
return 0;
@ -678,17 +614,15 @@ static int process_bad_inode(ext2_filsys fs, ino_t dir, ino_t ino)
* that was zeroed out and now needs to be replaced.
*/
static int allocate_dir_block(ext2_filsys fs,
struct dir_block_struct *db,
char *buf)
struct ext2_db_entry *db,
char *buf, struct problem_context *pctx)
{
blk_t blk;
char *block;
struct ext2_inode inode;
errcode_t retval;
printf("Directory inode %lu has a hole at block #%d\n",
db->ino, db->blockcnt);
if (ask("Allocate block", 1) == 0)
if (fix_problem(fs, PR_2_DIRECTORY_HOLE, pctx) == 0)
return 1;
/*
@ -765,7 +699,7 @@ static int update_dir_block(ext2_filsys fs,
int blockcnt,
void *private)
{
struct dir_block_struct *db = private;
struct ext2_db_entry *db = private;
if (db->blockcnt == blockcnt) {
*block_nr = db->blk;

View File

@ -1,8 +1,12 @@
/*
* pass3.c -- pass #3 of e2fsck: Check for directory connectivity
*
* Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
* Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*
* Pass #3 assures that all directories are connected to the
* filesystem tree, using the following algorithm:
@ -36,9 +40,11 @@
#include "et/com_err.h"
#include "e2fsck.h"
#include "problem.h"
static void check_root(ext2_filsys fs, ino_t root_ino);
static void check_directory(ext2_filsys fs, ino_t dir);
static void check_root(ext2_filsys fs);
static void check_directory(ext2_filsys fs, struct dir_info *dir,
struct problem_context *pctx);
static ino_t get_lost_and_found(ext2_filsys fs);
static void fix_dotdot(ext2_filsys fs, struct dir_info *dir, ino_t parent);
static errcode_t adjust_inode_count(ext2_filsys fs, ino_t ino, int adj);
@ -55,6 +61,8 @@ void pass3(ext2_filsys fs)
int i;
errcode_t retval;
struct resource_track rtrack;
struct problem_context pctx;
struct dir_info *dir;
init_resource_track(&rtrack);
@ -88,14 +96,16 @@ void pass3(ext2_filsys fs)
print_resource_track(&global_rtrack);
}
check_root(fs, EXT2_ROOT_INO);
check_root(fs);
ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
for (i=1; i <= fs->super->s_inodes_count; i++) {
if (ext2fs_test_inode_bitmap(inode_dir_map, i))
check_directory(fs, i);
clear_problem_context(&pctx);
for (i=0; (dir = dir_info_iter(&i)) != 0;) {
if (ext2fs_test_inode_bitmap(inode_dir_map, dir->ino))
check_directory(fs, dir, &pctx);
}
free_dir_info(fs);
ext2fs_free_inode_bitmap(inode_loop_detect);
ext2fs_free_inode_bitmap(inode_done_map);
@ -109,39 +119,26 @@ void pass3(ext2_filsys fs)
* This makes sure the root inode is present; if not, we ask if the
* user wants us to create it. Not creating it is a fatal error.
*/
void check_root(ext2_filsys fs, ino_t root_ino)
static void check_root(ext2_filsys fs)
{
blk_t blk;
errcode_t retval;
struct ext2_inode inode;
char * block;
struct dir_info *dir;
if (ext2fs_test_inode_bitmap(inode_used_map, root_ino)) {
if (ext2fs_test_inode_bitmap(inode_used_map, EXT2_ROOT_INO)) {
/*
* If the root inode is a directory, die here. The
* user must have answered 'no' in pass1 when we
* offered to clear it.
*/
if (!(ext2fs_test_inode_bitmap(inode_dir_map, root_ino)))
if (!(ext2fs_test_inode_bitmap(inode_dir_map, EXT2_ROOT_INO)))
fatal_error("Root inode not directory");
/*
* Set up the parent pointer for the root; this isn't
* done anywhere else, so we do it here.
*/
dir = get_dir_info(root_ino);
dir->parent = root_ino;
return;
}
printf("Root inode not allocated. ");
preenhalt(fs);
if (!ask("Reallocate", 1)) {
ext2fs_unmark_valid(fs);
if (!fix_problem(fs, PR_3_NO_ROOT_INODE, 0))
fatal_error("Cannot proceed without a root inode.");
}
read_bitmaps(fs);
@ -201,9 +198,9 @@ void check_root(ext2_filsys fs, ino_t root_ino)
/*
* Miscellaneous bookkeeping...
*/
add_dir_info(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, &inode);
inode_count[EXT2_ROOT_INO] = 2;
inode_link_info[EXT2_ROOT_INO] = 2;
add_dir_info(fs, EXT2_ROOT_INO, EXT2_ROOT_INO);
ext2fs_icount_store(inode_count, EXT2_ROOT_INO, 2);
ext2fs_icount_store(inode_link_info, EXT2_ROOT_INO, 2);
ext2fs_mark_inode_bitmap(inode_used_map, EXT2_ROOT_INO);
ext2fs_mark_inode_bitmap(inode_dir_map, EXT2_ROOT_INO);
@ -219,23 +216,12 @@ void check_root(ext2_filsys fs, ino_t root_ino)
* a loop, we treat that as a disconnected directory and offer to
* reparent it to lost+found.
*/
static void check_directory(ext2_filsys fs, ino_t ino)
static void check_directory(ext2_filsys fs, struct dir_info *dir,
struct problem_context *pctx)
{
struct dir_info *dir;
struct dir_info *p;
errcode_t retval;
char *path1, *path2, *path3;
static char unknown[] = "???";
dir = get_dir_info(ino);
if (!dir) {
printf("Internal error: couldn't find dir_info for %lu\n",
ino);
fatal_error(0);
}
struct dir_info *p = dir;
ext2fs_clear_inode_bitmap(inode_loop_detect);
p = dir;
while (p) {
/*
* If we find a parent which we've already checked,
@ -271,24 +257,15 @@ static void check_directory(ext2_filsys fs, ino_t ino)
* If we've reached here, we've hit a detached directory
* inode; offer to reconnect it to lost+found.
*/
retval = ext2fs_get_pathname(fs, p->ino, 0, &path1);
if (retval)
path1 = unknown;
printf("Unconnected directory inode %lu (%s)\n", p->ino, path1);
if (path1 != unknown)
free(path1);
preenhalt(fs);
if (ask("Connect to /lost+found", 1)) {
pctx->ino = p->ino;
if (fix_problem(fs, PR_3_UNCONNECTED_DIR, pctx)) {
if (reconnect_file(fs, p->ino))
ext2fs_unmark_valid(fs);
else {
p->parent = lost_and_found;
fix_dotdot(fs, p, lost_and_found);
}
} else
ext2fs_unmark_valid(fs);
}
/*
* Make sure that .. and the parent directory are the same;
@ -296,30 +273,11 @@ static void check_directory(ext2_filsys fs, ino_t ino)
*/
check_dot_dot:
if (dir->parent != dir->dotdot) {
retval = ext2fs_get_pathname(fs, dir->parent, ino,
&path1);
if (retval)
path1 = unknown;
retval = ext2fs_get_pathname(fs, dir->dotdot, 0, &path2);
if (retval)
path2 = unknown;
retval = ext2fs_get_pathname(fs, dir->parent, 0, &path3);
if (retval)
path3 = unknown;
printf("'..' in %s (%lu) is %s (%lu), should be %s (%lu).\n",
path1, ino, path2, dir->dotdot,
path3, dir->parent);
if (path1 != unknown)
free(path1);
if (path2 != unknown)
free(path2);
if (path3 != unknown)
free(path3);
if (ask("Fix", 1))
pctx->ino = dir->ino;
pctx->ino2 = dir->dotdot;
pctx->dir = dir->parent;
if (fix_problem(fs, PR_3_BAD_DOT_DOT, pctx))
fix_dotdot(fs, dir, dir->parent);
else
ext2fs_unmark_valid(fs);
}
}
@ -334,21 +292,17 @@ ino_t get_lost_and_found(ext2_filsys fs)
errcode_t retval;
struct ext2_inode inode;
char * block;
const char * name = "lost+found";
const char name[] = "lost+found";
retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name, strlen(name), 0, &ino);
retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
sizeof(name)-1, 0, &ino);
if (!retval)
return ino;
if (retval != ENOENT)
printf("Error while trying to find /lost+found: %s",
error_message(retval));
else
printf("/lost+found not found. ");
preenhalt(fs);
if (!ask("Create", 1)) {
ext2fs_unmark_valid(fs);
if (!fix_problem(fs, PR_3_NO_LF_DIR, 0))
return 0;
}
/*
* Read the inode and block bitmaps in; we'll be messing with
@ -434,10 +388,10 @@ ino_t get_lost_and_found(ext2_filsys fs)
/*
* Miscellaneous bookkeeping that needs to be kept straight.
*/
add_dir_info(fs, ino, EXT2_ROOT_INO, &inode);
add_dir_info(fs, ino, EXT2_ROOT_INO);
adjust_inode_count(fs, EXT2_ROOT_INO, +1);
inode_count[ino] = 2;
inode_link_info[ino] = 2;
ext2fs_icount_store(inode_count, ino, 2);
ext2fs_icount_store(inode_link_info, ino, 2);
#if 0
printf("/lost+found created; inode #%lu\n", ino);
#endif
@ -468,7 +422,7 @@ int reconnect_file(ext2_filsys fs, ino_t inode)
sprintf(name, "#%lu", inode);
retval = ext2fs_link(fs, lost_and_found, name, inode, 0);
if (retval == EXT2_ET_DIR_NO_SPACE) {
if (!ask("No room in /lost+found; expand /lost+found", 1))
if (!fix_problem(fs, PR_3_EXPAND_LF_DIR, 0))
return 1;
retval = expand_directory(fs, lost_and_found);
if (retval) {
@ -510,8 +464,14 @@ static errcode_t adjust_inode_count(ext2_filsys fs, ino_t ino, int adj)
#endif
inode.i_links_count += adj;
inode_count[ino] += adj;
inode_link_info[ino] += adj;
if (adj == 1) {
ext2fs_icount_increment(inode_count, ino, 0);
ext2fs_icount_increment(inode_link_info, ino, 0);
} else {
ext2fs_icount_decrement(inode_count, ino, 0);
ext2fs_icount_decrement(inode_link_info, ino, 0);
}
retval = ext2fs_write_inode(fs, ino, &inode);
if (retval)

View File

@ -1,12 +1,19 @@
/*
* pass4.c -- pass #4 of e2fsck: Check reference counts
*
* Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
*
* Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*
* Pass 4 frees the following data structures:
* - A bitmap of which inodes are in bad blocks. (inode_bb_map)
*/
#include "e2fsck.h"
#include "problem.h"
/*
* This routine is called when an inode is not connected to the
@ -15,19 +22,23 @@
* This subroutine returns 1 then the caller shouldn't bother with the
* rest of the pass 4 tests.
*/
int disconnect_inode(ext2_filsys fs, ino_t i)
static int disconnect_inode(ext2_filsys fs, ino_t i)
{
struct ext2_inode inode;
struct problem_context pctx;
e2fsck_read_inode(fs, i, &inode, "pass4: disconnect_inode");
clear_problem_context(&pctx);
pctx.ino = i;
pctx.inode = &inode;
if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
LINUX_S_ISDIR(inode.i_mode))) {
/*
* This is a zero-length file; prompt to delete it...
*/
printf("Unattached zero-length inode %lu\n", i);
if (ask("Clear", 1)) {
inode_link_info[i] = 0;
if (fix_problem(fs, PR_4_ZERO_LEN_INODE, &pctx)) {
ext2fs_icount_store(inode_link_info, i, 0);
inode.i_links_count = 0;
inode.i_dtime = time(0);
e2fsck_write_inode(fs, i, &inode,
@ -47,9 +58,7 @@ int disconnect_inode(ext2_filsys fs, ino_t i)
/*
* Prompt to reconnect.
*/
printf("Unattached inode %lu\n", i);
preenhalt(fs);
if (ask("Connect to /lost+found", 1)) {
if (fix_problem(fs, PR_4_UNATTACHED_INODE, &pctx)) {
if (reconnect_file(fs, i))
ext2fs_unmark_valid(fs);
} else {
@ -70,6 +79,8 @@ void pass4(ext2_filsys fs)
ino_t i;
struct ext2_inode inode;
struct resource_track rtrack;
struct problem_context pctx;
__u16 link_count, link_counted;
init_resource_track(&rtrack);
@ -79,39 +90,47 @@ void pass4(ext2_filsys fs)
if (!preen)
printf("Pass 4: Checking reference counts\n");
clear_problem_context(&pctx);
for (i=1; i <= fs->super->s_inodes_count; i++) {
if (i == EXT2_BAD_INO ||
(i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
continue;
if (!(ext2fs_test_inode_bitmap(inode_used_map, i)))
if (!(ext2fs_test_inode_bitmap(inode_used_map, i)) ||
(inode_bb_map &&
ext2fs_test_inode_bitmap(inode_bb_map, i)))
continue;
if (inode_count[i] == 0) {
ext2fs_icount_fetch(inode_link_info, i, &link_count);
ext2fs_icount_fetch(inode_count, i, &link_counted);
if (link_counted == 0) {
if (disconnect_inode(fs, i))
continue;
ext2fs_icount_fetch(inode_link_info, i, &link_count);
ext2fs_icount_fetch(inode_count, i, &link_counted);
}
if (inode_count[i] != inode_link_info[i]) {
if (link_counted != link_count) {
e2fsck_read_inode(fs, i, &inode, "pass4");
if (inode_link_info[i] != inode.i_links_count) {
pctx.ino = i;
pctx.inode = &inode;
if (link_count != inode.i_links_count) {
printf("WARNING: PROGRAMMING BUG IN E2FSCK!\n");
printf("\tOR SOME BONEHEAD (YOU) IS CHECKING "
"A MOUNTED (LIVE) FILESYSTEM.\n");
printf("inode_link_info[%ld] is %u, "
"inode.i_links_count is %d. "
"They should be the same!\n",
i, inode_link_info[i],
i, link_count,
inode.i_links_count);
}
printf("Inode %lu has ref count %d, expecting %d.\n",
i, inode.i_links_count, inode_count[i]);
if (ask("Set i_nlinks to count", 1)) {
inode.i_links_count = inode_count[i];
pctx.num = link_counted;
if (fix_problem(fs, PR_4_BAD_REF_COUNT, &pctx)) {
inode.i_links_count = link_counted;
e2fsck_write_inode(fs, i, &inode, "pass4");
} else
ext2fs_unmark_valid(fs);
}
}
}
free(inode_link_info); inode_link_info = 0;
free(inode_count); inode_count = 0;
ext2fs_free_icount(inode_link_info); inode_link_info = 0;
ext2fs_free_icount(inode_count); inode_count = 0;
ext2fs_free_inode_bitmap(inode_bb_map);
if (tflag > 1) {
printf("Pass 4: ");
print_resource_track(&rtrack);

View File

@ -1,8 +1,12 @@
/*
* pass5.c --- check block and inode bitmaps against on-disk bitmaps
*
* Copyright (C) 1993, 1994 Theodore Ts'o. This file may be
* redistributed under the terms of the GNU Public License.
* Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*
*/

462
e2fsck/problem.c Normal file
View File

@ -0,0 +1,462 @@
/*
* problem.c --- report filesystem problems to the user
*
* Copyright 1996, 1997 by Theodore Ts'o
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <termios.h>
#include "e2fsck.h"
#include "problem.h"
#define PROMPT_FIX 0
#define PROMPT_CLEAR 1
#define PROMPT_RELOCATE 2
#define PROMPT_ALLOCATE 3
#define PROMPT_EXPAND 4
#define PROMPT_CONNECT 5
#define PROMPT_CREATE 6
#define PROMPT_SALVAGE 7
#define PROMPT_TRUNCATE 8
#define PROMPT_CLEAR_INODE 9
/*
* These are the prompts which are used to ask the user if they want
* to fix a problem.
*/
static const char *prompt[] = {
"Fix", /* 0 */
"Clear", /* 1 */
"Relocate", /* 2 */
"Allocate", /* 3 */
"Expand", /* 4 */
"Connect to /lost+found", /* 5 */
"Create", /* 6 */
"Salvage", /* 7 */
"Truncate", /* 8 */
"Clear inode" /* 9 */
};
/*
* These messages are printed when we are preen mode and we will be
* automatically fixing the problem.
*/
static const char *preen_msg[] = {
"FIXED", /* 0 */
"CLEARED", /* 1 */
"RELOCATED", /* 2 */
"ALLOCATED", /* 3 */
"EXPANDED", /* 4 */
"RECONNECTED", /* 5 */
"CREATED", /* 6 */
"SALVAGED", /* 7 */
"TRUNCATED", /* 8 */
"INODE CLEARED" /* 9 */
};
static struct e2fsck_problem problem_table[] = {
/* Pre-Pass 1 errors */
/* Block bitmap not in group */
{ PR_0_BB_NOT_GROUP, "@b @B for @g %g is not in @g. (@b %b)\n",
PROMPT_RELOCATE, 0 },
/* Inode bitmap not in group */
{ PR_0_IB_NOT_GROUP, "@i @B for @g %g is not in @g. (@b %b)\n",
PROMPT_RELOCATE, 0 },
/* Inode table not in group */
{ PR_0_ITABLE_NOT_GROUP,
"@i table for @g %g is not in @g. (@b %b)\n"
"WARNING: SEVERE DATA LOSS POSSIBLE.\n",
PROMPT_RELOCATE, 0 },
/* Pass 1 errors */
/* Root directory is not an inode */
{ PR_1_ROOT_NO_DIR, "@r is not a @d. ",
PROMPT_CLEAR, 0 },
/* Root directory has dtime set */
{ PR_1_ROOT_DTIME,
"@r has dtime set (probably due to old mke2fs). ",
PROMPT_FIX, PR_PREEN_OK },
/* Reserved inode has bad mode */
{ PR_1_RESERVED_BAD_MODE,
"Reserved @i %i has bad mode. ",
PROMPT_CLEAR, PR_PREEN_OK },
/* Deleted inode has zero dtime */
{ PR_1_ZERO_DTIME,
"@D @i %i has zero dtime. ",
PROMPT_FIX, PR_PREEN_OK },
/* Inode in use, but dtime set */
{ PR_1_SET_DTIME,
"@i %i is in use, but has dtime set. ",
PROMPT_FIX, PR_PREEN_OK },
/* Zero-length directory */
{ PR_1_ZERO_LENGTH_DIR,
"@i %i is a @z @d. ",
PROMPT_CLEAR, PR_PREEN_OK },
/* Block bitmap conflicts with some other fs block */
{ PR_1_BB_CONFLICT,
"@g %N's @b @B at %b @C.\n",
PROMPT_RELOCATE, 0 },
/* Inode bitmap conflicts with some other fs block */
{ PR_1_IB_CONFLICT,
"@g %N's @i @B at %b @C.\n",
PROMPT_RELOCATE, 0 },
/* Inode table conflicts with some other fs block */
{ PR_1_ITABLE_CONFLICT,
"@g %g's @i table at %b @C.\n",
PROMPT_RELOCATE, 0 },
/* Block bitmap is on a bad block */
{ PR_1_BB_BAD_BLOCK,
"@g %g's @b @B (%b) is bad. ",
PROMPT_RELOCATE, 0 },
/* Inode bitmap is on a bad block */
{ PR_1_IB_BAD_BLOCK,
"@g %g's @i @B (%b) is bad. ",
PROMPT_RELOCATE, 0 },
/* Inode has incorrect i_size */
{ PR_1_BAD_I_SIZE,
"@i %i, i_size is %Is, @s %N. ",
PROMPT_FIX, PR_PREEN_OK },
/* Inode has incorrect i_blocks */
{ PR_1_BAD_I_BLOCKS,
"@i %i, i_blocks is %Ib, @s %N. ",
PROMPT_FIX, PR_PREEN_OK },
/* Illegal block number in inode */
{ PR_1_ILLEGAL_BLOCK_NUM,
"Illegal @b #%B (%b) in @i %i. ",
PROMPT_CLEAR, PR_LATCH_BLOCK },
/* Block number overlaps fs metadata */
{ PR_1_BLOCK_OVERLAPS_METADATA,
"@b #%B (%b) overlaps filesystem metadata in @i %i. ",
PROMPT_CLEAR, PR_LATCH_BLOCK },
/* Inode has illegal blocks (latch question) */
{ PR_1_INODE_BLOCK_LATCH,
"@i %i has illegal @b(s). ",
PROMPT_CLEAR, 0 },
/* Too many bad blocks in inode */
{ PR_1_TOO_MANY_BAD_BLOCKS,
"Too many illegal @bs in @i %i.\n",
PROMPT_CLEAR_INODE, PR_NO_OK },
/* Illegal block number in bad block inode */
{ PR_1_BB_ILLEGAL_BLOCK_NUM,
"Illegal @b #%B (%b) in bad @b @i. ",
PROMPT_CLEAR, PR_LATCH_BBLOCK },
/* Bad block inode has illegal blocks (latch question) */
{ PR_1_INODE_BBLOCK_LATCH,
"Bad @b @i has illegal @b(s). ",
PROMPT_CLEAR, 0 },
/* Pass 1b errors */
/* File has duplicate blocks */
{ PR_1B_DUP_FILE,
"File %Q (@i #%i, mod time %IM) \n"
" has %B duplicate @b(s), shared with %N file(s):\n",
PROMPT_FIX, PR_MSG_ONLY },
/* List of files sharing duplicate blocks */
{ PR_1B_DUP_FILE_LIST,
"\t%Q (@i #%i, mod time %IM)\n",
PROMPT_FIX, PR_MSG_ONLY },
/* Pass 2 errors */
/* Bad inode number for '.' */
{ PR_2_BAD_INODE_DOT,
"Bad @i number for '.' in @d @i %i.\n",
PROMPT_FIX, 0 },
/* Directory entry has bad inode number */
{ PR_2_BAD_INO,
"@E has bad @i #: %Di.\n",
PROMPT_CLEAR, 0 },
/* Directory entry has deleted or unused inode */
{ PR_2_UNUSED_INODE,
"@E has @D/unused @i %Di. ",
PROMPT_CLEAR, PR_PREEN_OK },
/* Directry entry is link to '.' */
{ PR_2_LINK_DOT,
"@E @L to '.' ",
PROMPT_CLEAR, 0 },
/* Directory entry points to inode now located in a bad block */
{ PR_2_BB_INODE,
"@E points to @i (%Di) located in a bad @b.\n",
PROMPT_CLEAR, 0 },
/* Directory entry contains a link to a directory */
{ PR_2_LINK_DIR,
"@E @L to @d %P (%Di).\n",
PROMPT_CLEAR, 0 },
/* Directory entry contains a link to the root directry */
{ PR_2_LINK_ROOT,
"@E @L to the @r.\n",
PROMPT_CLEAR, 0 },
/* Directory entry has illegal characters in its name */
{ PR_2_BAD_NAME,
"@E has illegal characters in its name.\n",
PROMPT_FIX, 0 },
/* Missing '.' in directory inode */
{ PR_2_MISSING_DOT,
"Missing '.' in @d @i %i.\n",
PROMPT_FIX, 0 },
/* Missing '..' in directory inode */
{ PR_2_MISSING_DOT_DOT,
"Missing '..' in @d @i %i.\n",
PROMPT_FIX, 0 },
/* First entry in directory inode doesn't contain '.' */
{ PR_2_1ST_NOT_DOT,
"First @e '%Dn' (inode=%Di) in @d @i %i (%p) @s '.'\n",
PROMPT_FIX, 0 },
/* Second entry in directory inode doesn't contain '..' */
{ PR_2_2ND_NOT_DOT_DOT,
"Second @e '%Dn' (inode=%Di) in @d @i %i @s '..'\n",
PROMPT_FIX, 0 },
/* i_faddr should be zero */
{ PR_2_FADDR_ZERO,
"i_faddr @F %IF, @s zero.\n",
PROMPT_CLEAR, 0 },
/* i_file_acl should be zero */
{ PR_2_FILE_ACL_ZERO,
"i_file_acl @F %If, @s zero.\n",
PROMPT_CLEAR, 0 },
/* i_dir_acl should be zero */
{ PR_2_DIR_ACL_ZERO,
"i_dir_acl @F %Id, @s zero.\n",
PROMPT_CLEAR, 0 },
/* i_frag should be zero */
{ PR_2_FRAG_ZERO,
"i_frag @F %N, @s zero.\n",
PROMPT_CLEAR, 0 },
/* i_fsize should be zero */
{ PR_2_FSIZE_ZERO,
"i_fsize @F %N, @s zero.\n",
PROMPT_CLEAR, 0 },
/* inode has bad mode */
{ PR_2_BAD_MODE,
"@i %i (%Q) has a bad mode (%Im).\n",
PROMPT_CLEAR, 0 },
/* directory corrupted */
{ PR_2_DIR_CORRUPTED,
"@d @i %i, @b %B, offset %N: @d corrupted\n",
PROMPT_SALVAGE, 0 },
/* filename too long */
{ PR_2_FILENAME_LONG,
"@d @i %i, @b %B, offset %N: filename too long\n",
PROMPT_TRUNCATE, 0 },
/* Directory inode has a missing block (hole) */
{ PR_2_DIRECTORY_HOLE,
"@d @i %i has an unallocated @b #%B. ",
PROMPT_ALLOCATE, 0 },
/* '.' is not NULL terminated */
{ PR_2_DOT_NULL_TERM,
"'.' directory entry in @d @i %i is not NULL terminated\n",
PROMPT_FIX, 0 },
/* '..' is not NULL terminated */
{ PR_2_DOT_DOT_NULL_TERM,
"'..' directory entry in @d @i %i is not NULL terminated\n",
PROMPT_FIX, 0 },
/* Pass 3 errors */
/* Root inode not allocated */
{ PR_3_NO_ROOT_INODE,
"@r not allocated. ",
PROMPT_ALLOCATE, 0 },
/* No room in lost+found */
{ PR_3_EXPAND_LF_DIR,
"No room in @l @d. ",
PROMPT_EXPAND, 0 },
/* Unconnected directory inode */
{ PR_3_UNCONNECTED_DIR,
"Unconnected @d @i %i (%p)\n",
PROMPT_CONNECT, 0 },
/* /lost+found not found */
{ PR_3_NO_LF_DIR,
"/@l not found. ",
PROMPT_CREATE, 0 },
/* .. entry is incorrect */
{ PR_3_BAD_DOT_DOT,
"'..' in %Q (%i) is %P (%j), @s %q (%d).\n",
PROMPT_FIX, 0 },
/* Pass 4 errors */
/* Unattached zero-length inode */
{ PR_4_ZERO_LEN_INODE,
"@u @z @i %i. ",
PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
/* Unattached inode */
{ PR_4_UNATTACHED_INODE,
"@u @i %i\n",
PROMPT_CONNECT, 0 },
/* Inode ref count wrong */
{ PR_4_BAD_REF_COUNT,
"@i %i ref count is %Il, @s %N. ",
PROMPT_FIX, PR_PREEN_OK },
{ 0 }
};
/*
* This is the latch flags register. It allows several problems to be
* "latched" together. This means that the user has to answer but one
* question for the set of problems, and all of the associated
* problems will be either fixed or not fixed.
*/
char pr_latch[7]; /* Latch flags register */
char pr_suppress[7]; /* Latch groups which are suppressed */
int latch_question[7] = {
PR_1_INODE_BLOCK_LATCH,
PR_1_INODE_BBLOCK_LATCH
};
static struct e2fsck_problem *find_problem(int code)
{
int i;
for (i=0; problem_table[i].e2p_code; i++) {
if (problem_table[i].e2p_code == code)
return &problem_table[i];
}
return 0;
}
void reset_problem_latch(int mask)
{
pr_latch[PR_LATCH(mask)] = 0;
pr_suppress[PR_LATCH(mask)] = 0;
}
void suppress_latch_group(int mask, int value)
{
pr_suppress[PR_LATCH(mask)] = value;
}
void clear_problem_context(struct problem_context *ctx)
{
memset(ctx, 0, sizeof(struct problem_context));
ctx->blkcount = -1;
ctx->group = -1;
}
int fix_problem(ext2_filsys fs, int code, struct problem_context *ctx)
{
struct e2fsck_problem *ptr;
int def_yn, answer;
int latch;
int print_answer = 0;
int suppress = 0;
ptr = find_problem(code);
if (!ptr) {
printf("Unhandled error code (%d)!\n", code);
return 0;
}
def_yn = (ptr->flags & PR_NO_DEFAULT) ? 0 : 1;
/*
* Do special latch processing. This is where we ask the
* latch question, if it exists
*/
if (ptr->flags & PR_LATCH_MASK) {
latch = PR_LATCH(ptr->flags);
if (latch_question[latch] && !pr_latch[latch])
pr_latch[latch] = fix_problem(fs,
latch_question[latch],
ctx) + 1;
if (pr_suppress[latch])
suppress++;
}
if (!suppress) {
if (preen)
printf("%s: ", device_name);
print_e2fsck_message(fs, ptr->e2p_description, ctx, 1);
}
if (!(ptr->flags & PR_PREEN_OK))
preenhalt(fs);
if (ptr->flags & PR_MSG_ONLY)
return 1;
if (preen) {
answer = def_yn;
print_answer = 1;
} else if (ptr->flags & PR_LATCH_MASK) {
latch = PR_LATCH(ptr->flags);
if (!pr_latch[latch])
pr_latch[latch] =
ask(prompt[(int) ptr->prompt], def_yn) + 1;
else
print_answer = 1;
answer = pr_latch[latch] - 1;
} else
answer = ask(prompt[(int) ptr->prompt], def_yn);
if (!answer && !(ptr->flags & PR_NO_OK))
ext2fs_unmark_valid(fs);
if (print_answer)
printf("%s.\n",
answer ? preen_msg[(int) ptr->prompt] : "IGNORED");
return answer;
}

249
e2fsck/problem.h Normal file
View File

@ -0,0 +1,249 @@
/*
* problem.h --- e2fsck problem error codes
*
* Copyright 1996 by Theodore Ts'o
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
struct problem_context {
ino_t ino, ino2, dir;
struct ext2_inode *inode;
struct ext2_dir_entry *dirent;
blk_t blk;
int blkcount, group;
__u32 num;
};
struct e2fsck_problem {
int e2p_code;
const char * e2p_description;
char prompt;
short flags;
};
#define PR_PREEN_OK 0x0001 /* Don't need to do preenhalt */
#define PR_NO_OK 0x0002 /* If user answers no, don't make fs invalid */
#define PR_NO_DEFAULT 0x0004 /* Default to no */
#define PR_MSG_ONLY 0x0008 /* Print message only */
/*
* We define a set of "latch groups"; these are problems which are
* handled as a set. The user answers once for a particular latch
* group.
*/
#define PR_LATCH_MASK 0x0070 /* Latch mask */
#define PR_LATCH_BLOCK 0x0010 /* Latch for illegal blocks (pass 1) */
#define PR_LATCH_BBLOCK 0x0020 /* Latch for bad block inode blocks (pass 1) */
#define PR_LATCH(x) ((((x) & PR_LATCH_MASK) >> 4) - 1)
/*
* Pre-Pass 1 errors
*/
/* Block bitmap not in group */
#define PR_0_BB_NOT_GROUP 0x000001
/* Inode bitmap not in group */
#define PR_0_IB_NOT_GROUP 0x000002
/* Inode table not in group */
#define PR_0_ITABLE_NOT_GROUP 0x000003
/*
* Pass 1 errors
*/
/* Root directory is not an inode */
#define PR_1_ROOT_NO_DIR 0x010001
/* Root directory has dtime set */
#define PR_1_ROOT_DTIME 0x010002
/* Reserved inode has bad mode */
#define PR_1_RESERVED_BAD_MODE 0x010003
/* Deleted inode has zero dtime */
#define PR_1_ZERO_DTIME 0x010004
/* Inode in use, but dtime set */
#define PR_1_SET_DTIME 0x010005
/* Zero-length directory */
#define PR_1_ZERO_LENGTH_DIR 0x010006
/* Block bitmap conflicts with some other fs block */
#define PR_1_BB_CONFLICT 0x010007
/* Inode bitmap conflicts with some other fs block */
#define PR_1_IB_CONFLICT 0x010008
/* Inode table conflicts with some other fs block */
#define PR_1_ITABLE_CONFLICT 0x010009
/* Block bitmap is on a bad block */
#define PR_1_BB_BAD_BLOCK 0x01000A
/* Inode bitmap is on a bad block */
#define PR_1_IB_BAD_BLOCK 0x01000B
/* Inode has incorrect i_size */
#define PR_1_BAD_I_SIZE 0x01000C
/* Inode has incorrect i_blocks */
#define PR_1_BAD_I_BLOCKS 0x01000D
/* Illegal block number in inode */
#define PR_1_ILLEGAL_BLOCK_NUM 0x01000E
/* Block number overlaps fs metadata */
#define PR_1_BLOCK_OVERLAPS_METADATA 0x01000F
/* Inode has illegal blocks (latch question) */
#define PR_1_INODE_BLOCK_LATCH 0x010010
/* Too many bad blocks in inode */
#define PR_1_TOO_MANY_BAD_BLOCKS 0x010011
/* Illegal block number in bad block inode */
#define PR_1_BB_ILLEGAL_BLOCK_NUM 0x010012
/* Bad block inode has illegal blocks (latch question) */
#define PR_1_INODE_BBLOCK_LATCH 0x010013
/*
* Pass 1b errors
*/
/* File has duplicate blocks */
#define PR_1B_DUP_FILE 0x011001
/* List of files sharing duplicate blocks */
#define PR_1B_DUP_FILE_LIST 0x011002
/*
* Pass 2 errors
*/
/* Bad inode number for '.' */
#define PR_2_BAD_INODE_DOT 0x020001
/* Directory entry has bad inode number */
#define PR_2_BAD_INO 0x020002
/* Directory entry has deleted or unused inode */
#define PR_2_UNUSED_INODE 0x020003
/* Directry entry is link to '.' */
#define PR_2_LINK_DOT 0x020004
/* Directory entry points to inode now located in a bad block */
#define PR_2_BB_INODE 0x020005
/* Directory entry contains a link to a directory */
#define PR_2_LINK_DIR 0x020006
/* Directory entry contains a link to the root directry */
#define PR_2_LINK_ROOT 0x020007
/* Directory entry has illegal characters in its name */
#define PR_2_BAD_NAME 0x020008
/* Missing '.' in directory inode */
#define PR_2_MISSING_DOT 0x020009
/* Missing '..' in directory inode */
#define PR_2_MISSING_DOT_DOT 0x02000A
/* First entry in directory inode doesn't contain '.' */
#define PR_2_1ST_NOT_DOT 0x02000B
/* Second entry in directory inode doesn't contain '..' */
#define PR_2_2ND_NOT_DOT_DOT 0x02000C
/* i_faddr should be zero */
#define PR_2_FADDR_ZERO 0x02000D
/* i_file_acl should be zero */
#define PR_2_FILE_ACL_ZERO 0x02000E
/* i_dir_acl should be zero */
#define PR_2_DIR_ACL_ZERO 0x02000F
/* i_frag should be zero */
#define PR_2_FRAG_ZERO 0x020010
/* i_fsize should be zero */
#define PR_2_FSIZE_ZERO 0x020011
/* inode has bad mode */
#define PR_2_BAD_MODE 0x020012
/* directory corrupted */
#define PR_2_DIR_CORRUPTED 0x020013
/* filename too long */
#define PR_2_FILENAME_LONG 0x020014
/* Directory inode has a missing block (hole) */
#define PR_2_DIRECTORY_HOLE 0x020015
/* '.' is not NULL terminated */
#define PR_2_DOT_NULL_TERM 0x020016
/* '..' is not NULL terminated */
#define PR_2_DOT_DOT_NULL_TERM 0x020017
/*
* Pass 3 errors
*/
/* Root inode not allocated */
#define PR_3_NO_ROOT_INODE 0x030001
/* No room in lost+found */
#define PR_3_EXPAND_LF_DIR 0x030002
/* Unconnected directory inode */
#define PR_3_UNCONNECTED_DIR 0x030003
/* /lost+found not found */
#define PR_3_NO_LF_DIR 0x030004
/* .. entry is incorrect */
#define PR_3_BAD_DOT_DOT 0x030005
/*
* Pass 4 errors
*/
/* Unattached zero-length inode */
#define PR_4_ZERO_LEN_INODE 0x040001
/* Unattached inode */
#define PR_4_UNATTACHED_INODE 0x040002
/* Inode ref count wrong */
#define PR_4_BAD_REF_COUNT 0x040003
/*
* Pass 5 errors
*/
/*
* Function declarations
*/
int fix_problem(ext2_filsys fs, int code, struct problem_context *ctx);
void reset_problem_latch(int mask);
void suppress_latch_group(int mask, int value);
void clear_problem_context(struct problem_context *ctx);
/* message.c */
void print_e2fsck_message(ext2_filsys fs, const char *msg,
struct problem_context *ctx, int first);

View File

@ -1,5 +1,13 @@
/*
* swapfs.c --- byte-swap an ext2 filesystem
*
* Copyright 1996, 1997 by Theodore Ts'o
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*
*/
#ifdef HAVE_ERRNO_H
@ -125,21 +133,29 @@ static void swap_inodes(ext2_filsys fs)
fatal_error(0);
}
inode = (struct ext2_inode *) buf;
for (i=0; i < fs->super->s_inodes_per_group; i++, ino++) {
if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
ext2fs_swap_inode(fs, inode, inode, 0);
for (i=0; i < fs->super->s_inodes_per_group;
i++, ino++, inode++) {
stashed_ino = ino;
stashed_inode = inode;
if (inode->i_block[EXT2_IND_BLOCK] ||
inode->i_block[EXT2_DIND_BLOCK] ||
inode->i_block[EXT2_TIND_BLOCK] ||
LINUX_S_ISDIR(inode->i_mode))
if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
ext2fs_swap_inode(fs, inode, inode, 0);
/*
* Skip deleted files.
*/
if (inode->i_links_count == 0)
continue;
if (LINUX_S_ISDIR(inode->i_mode) ||
((inode->i_block[EXT2_IND_BLOCK] ||
inode->i_block[EXT2_DIND_BLOCK] ||
inode->i_block[EXT2_TIND_BLOCK]) &&
ext2fs_inode_has_valid_blocks(inode)))
swap_inode_blocks(fs, ino, block_buf, inode);
if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
ext2fs_swap_inode(fs, inode, inode, 1);
inode++;
}
retval = io_channel_write_blk(fs->io,
fs->group_desc[group].bg_inode_table,

View File

@ -1,8 +1,12 @@
/*
* util.c --- miscellaneous utilities
*
* Copyright (C) 1993, 1994 Theodore Ts'o. This file may be
* redistributed under the terms of the GNU Public License.
* Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <stdlib.h>
@ -17,7 +21,6 @@
#include <sys/resource.h>
const char * fix_msg[2] = { "IGNORED", "FIXED" };
const char * clear_msg[2] = { "IGNORED", "CLEARED" };
void fatal_error (const char *msg)
{
@ -189,8 +192,14 @@ void init_resource_track(struct resource_track *track)
#endif
}
static __inline__ float timeval_subtract(struct timeval *tv1,
struct timeval *tv2)
#ifdef __GNUC__
#define _INLINE_ __inline__
#else
#define _INLINE_
#endif
static _INLINE_ float timeval_subtract(struct timeval *tv1,
struct timeval *tv2)
{
return ((tv1->tv_sec - tv2->tv_sec) +
((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
@ -245,31 +254,6 @@ extern void e2fsck_write_inode(ext2_filsys fs, unsigned long ino,
}
}
/*
* This function returns 1 if the inode's block entries actually
* contain block entries.
*/
int inode_has_valid_blocks(struct ext2_inode *inode)
{
/*
* Only directories, regular files, and some symbolic links
* have valid block entries.
*/
if (!LINUX_S_ISDIR(inode->i_mode) && !LINUX_S_ISREG(inode->i_mode) &&
!LINUX_S_ISLNK(inode->i_mode))
return 0;
/*
* If the symbolic link is a "fast symlink", then the symlink
* target is stored in the block entries.
*/
if (LINUX_S_ISLNK (inode->i_mode) && inode->i_blocks == 0 &&
inode->i_size < EXT2_N_BLOCKS * sizeof (unsigned long))
return 0;
return 1;
}
#ifdef MTRACE
void mtrace_print(char *mesg)
{

20
e2fsprogs-1.07.lsm Normal file
View File

@ -0,0 +1,20 @@
Begin3
Title: EXT2 Filesystem utilities
Version: 1.07
Entered-date: 14Mar97
Description: The filesystem utilities for the EXT2 filesystem, including
e2fsck, mke2fs, dumpe2fs, fsck, and others.
Keywords: utilities, fsck, filesystem, Ext2fs
Author: tytso@mit.edu (Theodore Tso)
Maintained-by: tytso@mit.edu (Theodore Tso)
Primary-site: tsx-11.mit.edu /pub/linux/packages/ext2fs
620kB e2fsprogs-1.07.tar.gz
222kB e2fsprogs-1.07-elfbin.tar.gz
199kB e2fsprogs-1.07-0.i386.rpm
68kB e2fsprogs-devel-1.07-0.i386.rpm
622kB e2fsprogs-1.07-0.src.rpm
1kB e2fsprogs-1.07.lsm
Alternate-site:
Platforms: linux 1.2.x/1.3.x/2.0.x/2.1.x
Copying-policy: GPL
End

View File

@ -1,43 +1,47 @@
Description: Tools for the second extended (ext2) filesystem
Summary: Tools for the second extended (ext2) filesystem
Name: e2fsprogs
Version: 1.06
Version: 1.07
Release: 0
Copyright: GPL
Group: Utilities/System
Source: tsx-11.mit.edu:/pub/linux/packages/ext2fs/e2fsprogs-1.06.tar.gz
Source: tsx-11.mit.edu:/pub/linux/packages/ext2fs/e2fsprogs-1.07.tar.gz
BuildRoot: /tmp/e2fsprogs-root
%description
This package includes a number of utilities for creating, checking,
and repairing ext2 filesystems.
%package devel
Description: e2fs static libs and headers
Summary: e2fs static libs and headers
Group: Development/Libraries
%description devel
Libraries and header files needed to develop ext2 filesystem-specific
programs.
%prep
%setup
%build
CFLAGS="$RPM_OPT_FLAGS" ./configure --enable-elf-shlibs
%ifarch i386
CFLAGS="$RPM_OPT_FLAGS" ./configure --enable-profile --enable-elf-shlibs
%endif
%ifarch axp
CFLAGS="$RPM_OPT_FLAGS" ./configure --enable-profile
%endif
#make
make libs progs
make libs progs docs
%install
rm -rf /usr/include/ss /usr/include/et /usr/include/ext2fs
export PATH=/sbin:$PATH
make install
make install-libs
make install DESTDIR="$RPM_BUILD_ROOT"
make install-libs DESTDIR="$RPM_BUILD_ROOT"
mv /usr/sbin/debugfs /sbin/debugfs
mv $RPM_BUILD_ROOT/usr/sbin/debugfs $RPM_BUILD_ROOT/sbin/debugfs
%clean
rm -rf $RPM_BUILD_ROOT
%ifarch i386
%post
/sbin/ldconfig
%endif
%postun
/sbin/ldconfig
%files
/sbin/e2fsck
@ -53,13 +57,11 @@ mv /usr/sbin/debugfs /sbin/debugfs
/usr/sbin/mklost+found
/sbin/mkfs.ext2
%ifarch i386
/lib/libe2p.so.2.2
/lib/libext2fs.so.2.1
/lib/libext2fs.so.2.2
/lib/libss.so.2.0
/lib/libcom_err.so.2.0
/lib/libuuid.so.1.0
%endif
/lib/libuuid.so.1.1
/usr/bin/chattr
/usr/bin/lsattr
@ -73,28 +75,19 @@ mv /usr/sbin/debugfs /sbin/debugfs
/usr/man/man1/lsattr.1
%files devel
/usr/info/libext2fs.info*
/usr/lib/libe2p.a
/usr/lib/libext2fs.a
/usr/lib/libss.a
/usr/lib/libcom_err.a
/usr/lib/libe2p_p.a
/usr/lib/libext2fs_p.a
/usr/lib/libss_p.a
/usr/lib/libcom_err_p.a
/usr/lib/libuuid.a
/usr/lib/libuuid_p.a
/usr/include/ss
/usr/include/ext2fs
/usr/include/et
/usr/include/uuid
%ifarch i386
/usr/lib/libe2p.so
/usr/lib/libext2fs.so
/usr/lib/libss.so
/usr/lib/libcom_err.so
/usr/lib/libuuid.so
%post
rm -f /lib/libe2p.so /lib/libext2fs.so /lib/libss.so /lib/libcom_err.so
%endif

View File

@ -1,3 +1,11 @@
Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o <tytso@mit.edu>
* Release of E2fsprogs version 1.07
Tue Oct 8 02:02:03 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* Release of E2fsprogs version 1.06
Thu Sep 12 15:23:07 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* Release of E2fsprogs version 1.05

View File

@ -38,19 +38,6 @@
#define EXT2FS_DATE "95/08/09"
#define EXT2FS_VERSION "0.5b"
/*
* Debug code
*/
#ifdef EXT2FS_DEBUG
# define ext2_debug(f, a...) { \
printk ("EXT2-fs DEBUG (%s, %d): %s:", \
__FILE__, __LINE__, __FUNCTION__); \
printk (f, ## a); \
}
#else
# define ext2_debug(f, a...) /**/
#endif
/*
* Special inodes numbers
*/

View File

@ -1,3 +1,11 @@
Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o <tytso@mit.edu>
* Release of E2fsprogs version 1.07
Tue Oct 8 02:02:03 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* Release of E2fsprogs version 1.06
Thu Sep 12 15:23:07 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* Release of E2fsprogs version 1.05

View File

@ -1,3 +1,16 @@
Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o <tytso@mit.edu>
* Release of E2fsprogs version 1.07
Sat Mar 8 13:23:43 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* Makefile.elf-lib (image): Allow Makefile.in files to specify
a list of libraries which the shared library depends upon.
Tue Oct 8 02:02:03 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* Release of E2fsprogs version 1.06
Thu Sep 12 15:23:07 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* Release of E2fsprogs version 1.05

View File

@ -9,7 +9,7 @@
# ELF_IMAGE = libce
# ELF_MYDIR = et
# ELF_INSTALL_DIR = $(SHLIBDIR)
#
# ELF_OTHER_LIBS = -lc
all:: elfshared image
@ -24,7 +24,8 @@ ELF_SONAME = $(ELF_IMAGE).so.$(ELF_SO_VERSION)
image: $(ELF_LIB)
$(ELF_LIB): $(OBJS)
(cd elfshared; $(CC) --shared -o $(ELF_LIB) -Wl,-soname,$(ELF_SONAME) $(OBJS))
(cd elfshared; $(CC) --shared -o $(ELF_LIB) -Wl,-soname,$(ELF_SONAME) \
$(OBJS) $(ELF_OTHER_LIBS))
$(MV) elfshared/$(ELF_LIB) .
$(RM) -f ../$(ELF_LIB) ../$(ELF_IMAGE).so ../$(ELF_SONAME)
$(LN) $(ELF_LIB) ../$(ELF_LIB)

View File

@ -1,3 +1,21 @@
Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o <tytso@mit.edu>
* Release of E2fsprogs version 1.07
Thu Jan 2 00:06:29 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* uuid.c: Include string.h, since we use memcpy().
Wed Jan 1 23:47:22 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* ls.c (list_super): Copy times from the superblock to a time_t
variable. (The alpha has different sizes for time_t and
the time in the superblock.)
Tue Oct 8 02:02:03 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* Release of E2fsprogs version 1.06
Sun Sep 22 16:20:12 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* pf.c: Add support for the 'A' (no atime) flag.

View File

@ -45,6 +45,7 @@ ELF_SO_VERSION = 2
ELF_IMAGE = libe2p
ELF_MYDIR = e2p
ELF_INSTALL_DIR = $(libdir)
ELF_OTHER_LIBS = -lc
BSDLIB_VERSION = 2.1
BSDLIB_IMAGE = libe2p
@ -60,7 +61,7 @@ BSDLIB_INSTALL_DIR = $(libdir)
.c.o:
$(CC) $(ALL_CFLAGS) -c $< -o $@
@PROFILE_CMT@ $(CC) $(ALL_CFLAGS) -pg -o profiled/$*.o -c $<
@PROFILE_CMT@ $(CC) $(ALL_CFLAGS) -g -pg -o profiled/$*.o -c $<
@CHECKER_CMT@ $(CC) $(ALL_CFLAGS) -checker -g -o checker/$*.o -c $<
@DLL_CMT@ (export JUMP_DIR=`pwd`/jump; $(CC) -B$(JUMP_PREFIX) $(ALL_CFLAGS) \
@DLL_CMT@ -o jump/$*.o -c $<)

View File

@ -1,13 +1,15 @@
00000000 T _fgetflags libe2p jump/fgetflags
00000000 T _fsetflags libe2p jump/fsetflags
00000000 T _fgetversion libe2p jump/fgetversion
00000000 T _fsetversion libe2p jump/fsetversion
00000000 T _getflags libe2p jump/getflags
00000000 T _getversion libe2p jump/getversion
00000000 T _iterate_on_dir libe2p jump/iod
00000000 T _list_super libe2p jump/ls
00000000 T _print_fs_errors libe2p jump/pe
00000000 T _print_flags libe2p jump/pf
00000000 T _print_fs_state libe2p jump/ps
00000000 T _setflags libe2p jump/setflags
00000000 T _setversion libe2p jump/setversion
00000000 T _fgetflags libe2p fgetflags
00000000 T _fsetflags libe2p fsetflags
00000000 T _fgetversion libe2p fgetversion
00000000 T _fsetversion libe2p fsetversion
00000000 T _getflags libe2p getflags
00000000 T _getversion libe2p getversion
00000000 T _iterate_on_dir libe2p iod
00000000 T _list_super libe2p ls
00000000 T _print_fs_errors libe2p pe
00000000 T _print_flags libe2p pf
00000000 T _print_fs_state libe2p ps
00000000 T _setflags libe2p setflags
00000000 T _setversion libe2p setversion
00000000 T _e2p_is_null_uuid libe2p uuid
00000000 T _e2p_uuid_to_str libe2p uuid

View File

@ -5,6 +5,8 @@
* Laboratoire MASI, Institut Blaise Pascal
* Universite Pierre et Marie Curie (Paris VI)
*
* Copyright (C) 1995, 1996, 1997 Theodore Ts'o <tytso@mit.edu>
*
* This file can be redistributed under the terms of the GNU Library General
* Public License
*/
@ -104,13 +106,16 @@ static void print_group (unsigned short gid)
#define HOUR_INT (60 * 60)
#define MINUTE_INT (60)
static char *interval_string(unsigned int secs)
static const char *interval_string(unsigned int secs)
{
static char buf[256], tmp[80];
int hr, min, num;
buf[0] = 0;
if (secs == 0)
return "<none>";
if (secs >= MONTH_INT) {
num = secs / MONTH_INT;
secs -= num*MONTH_INT;
@ -153,6 +158,7 @@ void list_super (struct ext2_super_block * s)
struct ext2fs_sb *sb = (struct ext2fs_sb *) s;
char buf[80];
const char *os;
time_t tm;
inode_blocks_per_group = (((s->s_inodes_per_group *
EXT2_INODE_SIZE(s)) +
@ -163,17 +169,20 @@ void list_super (struct ext2_super_block * s)
if (sb->s_volume_name[0]) {
memset(buf, 0, sizeof(buf));
strncpy(buf, sb->s_volume_name, sizeof(sb->s_volume_name));
printf("Filesystem volume name: %s\n", buf);
}
} else
strcpy(buf, "<none>");
printf("Filesystem volume name: %s\n", buf);
if (sb->s_last_mounted[0]) {
memset(buf, 0, sizeof(buf));
strncpy(buf, sb->s_last_mounted, sizeof(sb->s_last_mounted));
printf("Last mounted on: %s\n", buf);
}
} else
strcpy(buf, "<not available>");
printf("Last mounted on: %s\n", buf);
if (!e2p_is_null_uuid(sb->s_uuid)) {
e2p_uuid_to_str(sb->s_uuid, buf);
printf("Filesystem UUID: %s\n", buf);
}
} else
strcpy(buf, "<none>");
printf("Filesystem UUID: %s\n", buf);
printf ("Filesystem state: ");
print_fs_state (stdout, s->s_state);
printf ("\n");
@ -186,38 +195,41 @@ void list_super (struct ext2_super_block * s)
case EXT2_OS_MASIX: os = "Masix"; break;
default: os = "unknown"; break;
}
printf ("Filesystem OS type: %s\n", os);
printf ("Inode count: %u\n", s->s_inodes_count);
printf ("Block count: %u\n", s->s_blocks_count);
printf ("Reserved block count: %u\n", s->s_r_blocks_count);
printf ("Free blocks: %u\n", s->s_free_blocks_count);
printf ("Free inodes: %u\n", s->s_free_inodes_count);
printf ("First block: %u\n", s->s_first_data_block);
printf ("Block size: %u\n", EXT2_BLOCK_SIZE(s));
printf ("Fragment size: %u\n", EXT2_FRAG_SIZE(s));
printf ("Blocks per group: %u\n", s->s_blocks_per_group);
printf ("Fragments per group: %u\n", s->s_frags_per_group);
printf ("Inodes per group: %u\n", s->s_inodes_per_group);
printf ("Inode blocks per group: %u\n", inode_blocks_per_group);
printf ("Last mount time: %s", ctime ((time_t *) &s->s_mtime));
printf ("Last write time: %s", ctime ((time_t *) &s->s_wtime));
printf ("Mount count: %u\n", s->s_mnt_count);
printf ("Maximum mount count: %d\n", s->s_max_mnt_count);
printf ("Last checked: %s", ctime ((time_t *) &s->s_lastcheck));
printf ("Check interval: %u (%s)\n", s->s_checkinterval,
interval_string(s->s_checkinterval));
printf("Filesystem OS type: %s\n", os);
printf("Inode count: %u\n", s->s_inodes_count);
printf("Block count: %u\n", s->s_blocks_count);
printf("Reserved block count: %u\n", s->s_r_blocks_count);
printf("Free blocks: %u\n", s->s_free_blocks_count);
printf("Free inodes: %u\n", s->s_free_inodes_count);
printf("First block: %u\n", s->s_first_data_block);
printf("Block size: %u\n", EXT2_BLOCK_SIZE(s));
printf("Fragment size: %u\n", EXT2_FRAG_SIZE(s));
printf("Blocks per group: %u\n", s->s_blocks_per_group);
printf("Fragments per group: %u\n", s->s_frags_per_group);
printf("Inodes per group: %u\n", s->s_inodes_per_group);
printf("Inode blocks per group: %u\n", inode_blocks_per_group);
tm = s->s_mtime;
printf("Last mount time: %s", ctime(&tm));
tm = s->s_wtime;
printf("Last write time: %s", ctime(&tm));
printf("Mount count: %u\n", s->s_mnt_count);
printf("Maximum mount count: %d\n", s->s_max_mnt_count);
tm = s->s_lastcheck;
printf("Last checked: %s", ctime(&tm));
printf("Check interval: %u (%s)\n", s->s_checkinterval,
interval_string(s->s_checkinterval));
if (s->s_checkinterval)
{
time_t next;
next = s->s_lastcheck + s->s_checkinterval;
printf ("Next check after: %s", ctime (&next));
printf("Next check after: %s", ctime(&next));
}
#ifdef EXT2_DEF_RESUID
printf ("Reserved blocks uid: ");
print_user (s->s_def_resuid);
printf ("Reserved blocks gid: ");
print_group (s->s_def_resgid);
printf("Reserved blocks uid: ");
print_user(s->s_def_resuid);
printf("Reserved blocks gid: ");
print_group(s->s_def_resgid);
#endif
#ifdef EXT2_DYNAMIC_REV
if (s->s_rev_level >= EXT2_DYNAMIC_REV) {

View File

@ -3,8 +3,11 @@
*/
#include <stdio.h>
#include <string.h>
#include <linux/types.h>
#include "e2p.h"
struct uuid {
__u32 time_low;
__u16 time_mid;

View File

@ -1,3 +1,11 @@
Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o <tytso@mit.edu>
* Release of E2fsprogs version 1.07
Tue Oct 8 02:02:03 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* Release of E2fsprogs version 1.06
Thu Sep 12 15:23:07 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* Release of E2fsprogs version 1.05

View File

@ -36,6 +36,7 @@ ELF_SO_VERSION = 2
ELF_IMAGE = libcom_err
ELF_MYDIR = et
ELF_INSTALL_DIR = $(libdir)
ELF_OTHER_LIBS = -lc
BSDLIB_VERSION = 1.0
BSDLIB_IMAGE = libcom_err
@ -47,7 +48,7 @@ BSDLIB_INSTALL_DIR = $(libdir)
#
.c.o:
$(CC) $(ALL_CFLAGS) -c $< -o $@
@PROFILE_CMT@ $(CC) $(ALL_CFLAGS) -pg -o profiled/$*.o -c $<
@PROFILE_CMT@ $(CC) $(ALL_CFLAGS) -g -pg -o profiled/$*.o -c $<
@CHECKER_CMT@ $(CC) $(ALL_CFLAGS) -checker -g -o checker/$*.o -c $<
@DLL_CMT@ (export JUMP_DIR=`pwd`/jump; $(CC) -B$(JUMP_PREFIX) $(ALL_CFLAGS) \
@DLL_CMT@ -o jump/$*.o -c $<)

View File

@ -1,3 +1,154 @@
Wed Mar 12 13:32:05 1997 Theodore Y. Ts'o <tytso@mit.edu>
* Release of E2fsprogs version 1.07
Sun Mar 2 16:46:18 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* Makefile.in (ELF_VERSION): Change version to be 2.2
Tue Feb 11 14:54:02 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* alloc.c (ext2fs_get_free_blocks): Change routine to use
ext2fs_fast_test_block_bitmap_range().
* bitops.h (ext2fs_fast_test_block_bitmap_range,
ext2fs_test_block_bitmap_range: New inline functions which
test to see whether a contiguous range of blocks is
available.
Thu Feb 6 10:00:13 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* badblocks.c (ext2fs_badblocks_list_create): Rename sybmols to use
use ext2fs_badblocks_* instead of badblocks_*
* bb_compat.c: New file which translates between old badblocks_*()
names to ext2fs_badblocks_*()
* unlink.c (ext2fs_unlink): New file, moved ext2fs_unlink() from
link.c (since e2fsck doesn't use ext2fs_unlink()).
* rs_bitmap.c (ext2fs_resize_generic_bitmap): New file, contains
bitmap resizing routine moved from bitmaps.c, since e2fsck
doesn't need to use this function.
* lookup.c (ext2fs_lookup): Moved ext2fs_lookup to its own file,
since e2fsck only needs ext2fs_lookup.
Mon Feb 3 10:11:40 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* inode.c (ext2fs_open_inode_scan): Set fs->badblocks if it is not
already set; this is needed so that programs like dump
which use the inode scan functions will deal with
filesystems that have bad blocks in the inode table.
Sun Feb 2 00:17:36 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* ext2fs.h (struct_badblocks_list, struct_badblocks_iterate):
Moved to ext2fsP.h, since it doesn't need to be part of
the public interface.
* dir_iterate.c: Move ext2_dir_iterate out of namei.c.
Sat Feb 1 10:14:55 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* dblist.c (ext2fs_get_num_dirs): New file, which implements a
directory block list abstraction. (Code moved from
e2fsck).
* ext2fs.h, inode.c: Moved definition of ext2_struct_inode_scan to
to inode.c (since no one else should be peeking inside it!)
* valid_blk.c (ext2_inode_has_valid_blocks): New function.
* openfs.c (ext2fs_open): Check the feature set in the ext2
superblock, and refuse to open filesystems if they contain
incompatible features. (Can be overriden with the
EXT2_FLAG_FORCE
Sun Jan 12 11:31:46 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* block.c (ext2fs_block_iterate2): Added new function
ext2fs_block_iterate2 which changes the function
signature of the callback function to include the
referencing block and offset.
* inode.c (ext2fs_inode_scan_goto_blockgroup): Added new function
ext2fs_inode_scan_goto_blockgroup which allows an
application to jump to a particular block group while
doing an inode scan.
Wed Jan 1 23:50:12 1997 Theodore Ts'o <tytso@rsts-11.mit.edu>
* dirblock.c: Include string.h, since we use memcpy().
Tue Dec 3 12:27:29 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* getsize.c (ext2fs_get_device_size): The ioctl BLKGETSIZE returns
a long not an int; this doesn't matter on i386 machines,
but it does on Alpha's.
Fri Nov 29 20:57:37 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* inode.c (ext2fs_write_inode, ext2fs_read_inode): If the inode
table pointer is NULL, then return an error indicating
that the inode table is missing.
(get_next_blockgroup, get_next_blocks,
ext2fs_get_next_inode): Don't treat a missing inode table
as permanent error. Return MISSING_INODE_TABLE, but as an
advisory error code, much like BAD_BLOCK_IN_INODE_TABLE.
* rw_bitmaps.c (ext2fs_write_block_bitmap,
ext2fs_write_inode_bitmap): If the inode or block bitmap
block is zero, then don't write out the inode or block
bitmap. The idea here is to avoid stomping on the
superblock.
(read_bitmaps): If the inode or block bitmap block is
zero, then fill in that portion of the inode or block
bitmap with all zeros.
* inode.c (ext2fs_get_next_inode): Fix bug in handling of bad
blocks in inode table when the inode table size is
non-standard (and can therefore span blocks).
Tue Oct 29 20:13:14 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* alloc.c (ext2fs_new_block): Fix fencepost error in
ext2fs_new_block; make sure we don't try to allocate the
first block beyond the end of the filesystem.
Mon Oct 14 11:00:48 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* inode.c (check_for_inode_bad_blocks): New function called by
get_next_blocks() to avoid reading in bad blocks marked in
fs->badblocks. Inodes located in bad blocks are returned
by ext2fs_get_next_inode() returns the error code
EXT2_ET_BAD_BLOCK_IN_INODE_TABLE.
* alloc_tables.c (ext2fs_allocate_tables): New function which
performs the part of mke2fs's job of allocating the
filesystem tables.
* test_io.c (test_close): IO manager which is used for testing
purposes.
Sun Oct 13 04:31:57 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* inode.c (ext2fs_get_next_inode): Separate out the function of
setting up for a new block group to get_next_blockgroup().
Separate out the function of reading in blocks of the
inode table to get_next_blocks().
* ext2fs.h: Add the badblocks list to the ext2_filsys entry
* badblocks.c (badblocks_list_add, badblocks_list_test): Add
blocks to the badblock list in sorted order. This allows
badblocks_list_test to be coded using a binary search for
speed.
Tue Oct 8 02:02:03 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* Release of E2fsprogs version 1.06
Mon Oct 7 00:44:17 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* ext2fs.h, block.c, closefs.c, dirblock.c, inode.c, native.c,

View File

@ -9,25 +9,34 @@ INSTALL = @INSTALL@
OBJS= ext2_err.o \
alloc.o \
alloc_tables.o \
badblocks.o \
bb_compat.o \
bb_inode.o \
bitmaps.o \
bitops.o \
block.o \
brel_ma.o \
check_desc.o \
closefs.o \
cmp_bitmaps.o \
dblist.o \
dblist_dir.o \
dirblock.o \
dir_iterate.o \
expanddir.o \
freefs.o \
get_pathname.o \
getsize.o \
icount.o \
initialize.o \
inline.o \
inode.o \
irel_ma.o \
ismounted.o \
link.o \
llseek.o \
lookup.o \
mkdir.o \
namei.o \
native.o \
@ -35,31 +44,44 @@ OBJS= ext2_err.o \
openfs.o \
read_bb.o \
read_bb_file.o \
rs_bitmap.o \
rw_bitmaps.o \
swapfs.o \
unix_io.o
test_io.o \
unix_io.o \
unlink.o \
valid_blk.o
SRCS= ext2_err.c \
$(srcdir)/alloc.c \
$(srcdir)/alloc_tables.c \
$(srcdir)/badblocks.c \
$(srcdir)/bb_compat.c \
$(srcdir)/bb_inode.c \
$(srcdir)/bitmaps.c \
$(srcdir)/bitops.c \
$(srcdir)/block.c \
$(srcdir)/brel_ma.c \
$(srcdir)/check_desc.c \
$(srcdir)/closefs.c \
$(srcdir)/cmp_bitmaps.c \
$(srcdir)/dblist.c \
$(srcdir)/dblist_dir.c \
$(srcdir)/dirblock.c \
$(srcdir)/dir_iterate.c \
$(srcdir)/expanddir.c \
$(srcdir)/freefs.c \
$(srcdir)/get_pathname.c \
$(srcdir)/getsize.c \
$(srcdir)/icount.c \
$(srcdir)/initialize.c \
$(srcdir)/inline.c \
$(srcdir)/inode.c \
$(srcdir)/irel_ma.c \
$(srcdir)/ismounted.c \
$(srcdir)/link.c \
$(srcdir)/llseek.c \
$(srcdir)/lookup.c \
$(srcdir)/mkdir.c \
$(srcdir)/namei.c \
$(srcdir)/native.c \
@ -67,9 +89,13 @@ SRCS= ext2_err.c \
$(srcdir)/openfs.c \
$(srcdir)/read_bb.c \
$(srcdir)/read_bb_file.c \
$(srcdir)/rs_bitmap.c \
$(srcdir)/rw_bitmaps.c \
$(srcdir)/swapfs.c \
$(srcdir)/unix_io.c
$(srcdir)/test_io.c \
$(srcdir)/unix_io.c \
$(srcdir)/unlink.c \
$(srcdir)/valid_blk.c
HFILES= bitops.h ext2fs.h io.h
@ -86,11 +112,12 @@ DLL_LIBS = -L../.. -lcom_err
DLL_MYDIR = ext2fs
DLL_INSTALL_DIR = $(libdir)
ELF_VERSION = 2.1
ELF_VERSION = 2.2
ELF_SO_VERSION = 2
ELF_IMAGE = libext2fs
ELF_MYDIR = ext2fs
ELF_INSTALL_DIR = $(libdir)
ELF_OTHER_LIBS = -lc -L../.. -lcom_err
BSDLIB_VERSION = 2.0
BSDLIB_IMAGE = libext2fs
@ -106,7 +133,7 @@ BSDLIB_INSTALL_DIR = $(libdir)
.c.o:
$(CC) $(ALL_CFLAGS) -c $< -o $@
@PROFILE_CMT@ $(CC) $(ALL_CFLAGS) -pg -o profiled/$*.o -c $<
@PROFILE_CMT@ $(CC) $(ALL_CFLAGS) -g -pg -o profiled/$*.o -c $<
@CHECKER_CMT@ $(CC) $(ALL_CFLAGS) -checker -g -o checker/$*.o -c $<
@DLL_CMT@ (export JUMP_DIR=`pwd`/jump; $(CC) -B$(JUMP_PREFIX) $(ALL_CFLAGS) \
@DLL_CMT@ -o jump/$*.o -c $<)
@ -124,6 +151,17 @@ ext2_err.et: $(SUBSTITUTE) $(srcdir)/ext2_err.et.in
ext2_err.c ext2_err.h: ext2_err.et
$(COMPILE_ET) ext2_err.et
tst_badblocks: tst_badblocks.o badblocks.o
$(CC) -o tst_badblocks tst_badblocks.o badblocks.o $(LIBCOM_ERR)
tst_iscan: tst_iscan.o inode.o $(STATIC_LIBEXT2FS)
$(CC) -o tst_iscan tst_iscan.o inode.o $(STATIC_LIBEXT2FS) \
$(LIBCOM_ERR)
check:: tst_badblocks tst_iscan
./tst_badblocks
./tst_iscan
installdirs::
$(top_srcdir)/mkinstalldirs $(DESTDIR)$(ulibdir) \
$(DESTDIR)$(includedir)/ext2fs
@ -157,90 +195,205 @@ distclean:: clean
# the Makefile.in file
#
ext2_err.o: ext2_err.c
alloc.o: $(srcdir)/alloc.c $(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
badblocks.o: $(srcdir)/badblocks.c $(srcdir)/ext2fs.h \
alloc.o: $(srcdir)/alloc.c \
$(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
alloc_tables.o: $(srcdir)/alloc_tables.c \
$(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
bb_inode.o: $(srcdir)/bb_inode.c $(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/bitops.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
bitmaps.o: $(srcdir)/bitmaps.c $(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/bitops.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
bitops.o: $(srcdir)/bitops.c $(srcdir)/ext2fs.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
badblocks.o: $(srcdir)/badblocks.c \
$(srcdir)/ext2fsP.h \
$(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
bb_compat.o: $(srcdir)/bb_compat.c \
$(srcdir)/ext2fsP.h \
$(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
bb_inode.o: $(srcdir)/bb_inode.c \
$(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
bitmaps.o: $(srcdir)/bitmaps.c \
$(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
bitops.o: $(srcdir)/bitops.c \
$(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
block.o: $(srcdir)/block.c \
$(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
brel_ma.o: $(srcdir)/brel_ma.c \
$(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h $(srcdir)/brel.h
check_desc.o: $(srcdir)/check_desc.c \
$(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
closefs.o: $(srcdir)/closefs.c \
$(srcdir)/ext2fsP.h \
$(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
cmp_bitmaps.o: $(srcdir)/cmp_bitmaps.c \
$(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
dblist.o: $(srcdir)/dblist.c \
$(srcdir)/ext2fsP.h \
$(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
dblist_dir.o: $(srcdir)/dblist_dir.c \
$(srcdir)/ext2fsP.h \
$(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
dirblock.o: $(srcdir)/dirblock.c \
$(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
dir_iterate.o: $(srcdir)/dir_iterate.c \
$(srcdir)/ext2fsP.h \
$(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
expanddir.o: $(srcdir)/expanddir.c \
$(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
freefs.o: $(srcdir)/freefs.c \
$(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
get_pathname.o: $(srcdir)/get_pathname.c \
$(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
getsize.o: $(srcdir)/getsize.c \
$(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
icount.o: $(srcdir)/icount.c $(top_srcdir)/lib/et/com_err.h \
$(srcdir)/ext2fs.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
initialize.o: $(srcdir)/initialize.c \
$(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
inline.o: $(srcdir)/inline.c \
$(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
inode.o: $(srcdir)/inode.c \
$(srcdir)/ext2fsP.h \
$(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
irel_ma.o: $(srcdir)/irel_ma.c \
$(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h $(srcdir)/irel.h
ismounted.o: $(srcdir)/ismounted.c \
$(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
link.o: $(srcdir)/link.c \
$(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
llseek.o: $(srcdir)/llseek.c \
$(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h
lookup.o: $(srcdir)/lookup.c \
$(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
mkdir.o: $(srcdir)/mkdir.c \
$(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
namei.o: $(srcdir)/namei.c \
$(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
native.o: $(srcdir)/native.c \
$(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
newdir.o: $(srcdir)/newdir.c \
$(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
openfs.o: $(srcdir)/openfs.c \
$(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
read_bb.o: $(srcdir)/read_bb.c \
$(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
read_bb_file.o: $(srcdir)/read_bb_file.c \
$(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
rs_bitmap.o: $(srcdir)/rs_bitmap.c \
$(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
rw_bitmaps.o: $(srcdir)/rw_bitmaps.c \
$(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
swapfs.o: $(srcdir)/swapfs.c \
$(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
test_io.o: $(srcdir)/test_io.c \
$(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
block.o: $(srcdir)/block.c $(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/bitops.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
check_desc.o: $(srcdir)/check_desc.c $(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/bitops.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
closefs.o: $(srcdir)/closefs.c $(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/bitops.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
cmp_bitmaps.o: $(srcdir)/cmp_bitmaps.c $(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/bitops.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
dirblock.o: $(srcdir)/dirblock.c $(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/bitops.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
expanddir.o: $(srcdir)/expanddir.c $(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/bitops.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
freefs.o: $(srcdir)/freefs.c $(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/bitops.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
get_pathname.o: $(srcdir)/get_pathname.c $(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/bitops.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
getsize.o: $(srcdir)/getsize.c $(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/bitops.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
initialize.o: $(srcdir)/initialize.c $(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/bitops.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
inline.o: $(srcdir)/inline.c $(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/bitops.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
inode.o: $(srcdir)/inode.c $(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/bitops.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
ismounted.o: $(srcdir)/ismounted.c $(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/bitops.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
link.o: $(srcdir)/link.c $(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/bitops.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
llseek.o: $(srcdir)/llseek.c $(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h
mkdir.o: $(srcdir)/mkdir.c $(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/bitops.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
namei.o: $(srcdir)/namei.c $(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/bitops.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
native.o: $(srcdir)/native.c $(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/bitops.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
newdir.o: $(srcdir)/newdir.c $(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/bitops.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
openfs.o: $(srcdir)/openfs.c $(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/bitops.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
read_bb.o: $(srcdir)/read_bb.c $(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/bitops.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
read_bb_file.o: $(srcdir)/read_bb_file.c $(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/bitops.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
rw_bitmaps.o: $(srcdir)/rw_bitmaps.c $(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/bitops.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
swapfs.o: $(srcdir)/swapfs.c $(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h $(srcdir)/bitops.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
unix_io.o: $(srcdir)/unix_io.c $(top_srcdir)/lib/et/com_err.h \
$(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/io.h
unix_io.o: $(srcdir)/unix_io.c \
$(top_srcdir)/lib/et/com_err.h \
$(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/io.h
unlink.o: $(srcdir)/unlink.c \
$(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h
valid_blk.o: $(srcdir)/valid_blk.c \
$(srcdir)/ext2fs.h \
$(top_srcdir)/lib/et/com_err.h \
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/bitops.h

View File

@ -1,8 +1,13 @@
/*
* alloc.c --- allocate new inodes, blocks for ext2fs
*
* Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*
*/
#include <stdio.h>
@ -84,26 +89,12 @@ errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal,
return 0;
}
i++;
if (i > fs->super->s_blocks_count)
if (i >= fs->super->s_blocks_count)
i = fs->super->s_first_data_block;
} while (i != goal);
return ENOSPC;
}
static int check_blocks_free(ext2_filsys fs, ext2fs_block_bitmap map,
blk_t blk, int num)
{
int i;
for (i=0; i < num; i++) {
if ((blk+i) > fs->super->s_blocks_count)
return 0;
if (ext2fs_test_block_bitmap(map, blk+i))
return 0;
}
return 1;
}
errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start, blk_t finish,
int num, ext2fs_block_bitmap map, blk_t *ret)
{
@ -122,13 +113,13 @@ errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start, blk_t finish,
if (!num)
num = 1;
do {
if (check_blocks_free(fs, map, b, num)) {
if (b+num-1 > fs->super->s_blocks_count)
b = fs->super->s_first_data_block;
if (ext2fs_fast_test_block_bitmap_range(map, b, num)) {
*ret = b;
return 0;
}
b++;
if (b > fs->super->s_blocks_count)
b = fs->super->s_first_data_block;
} while (b != finish);
return ENOSPC;
}

80
lib/ext2fs/alloc_tables.c Normal file
View File

@ -0,0 +1,80 @@
/*
* alloc_tables.c --- Allocate tables for a newly initialized
* filesystem. Used by mke2fs when initializing a filesystem
*
* Copyright (C) 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/types.h>
#if HAVE_ERRNO_H
#include <errno.h>
#endif
#include <linux/ext2_fs.h>
#include "ext2fs.h"
errcode_t ext2fs_allocate_tables(ext2_filsys fs)
{
errcode_t retval;
blk_t group_blk, last_blk, new_blk, blk;
int i, j;
group_blk = fs->super->s_first_data_block;
for (i = 0; i < fs->group_desc_count; i++) {
last_blk = group_blk + fs->super->s_blocks_per_group;
/*
* Allocate the block bitmap
*/
retval = ext2fs_get_free_blocks(fs, group_blk, last_blk,
1, fs->block_map, &new_blk);
if (retval)
return retval;
ext2fs_mark_block_bitmap(fs->block_map, new_blk);
fs->group_desc[i].bg_block_bitmap = new_blk;
/*
* ... and the inode bitmap
*/
retval = ext2fs_get_free_blocks(fs, group_blk, last_blk,
1, fs->block_map, &new_blk);
if (retval)
return retval;
ext2fs_mark_block_bitmap(fs->block_map, new_blk);
fs->group_desc[i].bg_inode_bitmap = new_blk;
/*
* Finally, allocate the inode table
*/
retval = ext2fs_get_free_blocks(fs, group_blk, last_blk,
fs->inode_blocks_per_group,
fs->block_map, &new_blk);
if (retval)
return retval;
for (j=0, blk = new_blk;
j < fs->inode_blocks_per_group;
j++, blk++)
ext2fs_mark_block_bitmap(fs->block_map, blk);
fs->group_desc[i].bg_inode_table = new_blk;
/*
* Increment the start of the block group
*/
group_blk += fs->super->s_blocks_per_group;
}
return 0;
}

View File

@ -1,8 +1,12 @@
/*
* badblocks.c --- routines to manipulate the bad block structure
*
* Copyright (C) 1994 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
* Copyright (C) 1994, 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <stdio.h>
@ -19,19 +23,19 @@
#include <linux/ext2_fs.h>
#include "ext2fs.h"
#include "ext2fsP.h"
/*
* This procedure create an empty badblocks list.
*/
errcode_t badblocks_list_create(badblocks_list *ret, int size)
errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret, int size)
{
badblocks_list bb;
ext2_badblocks_list bb;
bb = malloc(sizeof(struct struct_badblocks_list));
bb = malloc(sizeof(struct ext2_struct_badblocks_list));
if (!bb)
return ENOMEM;
memset(bb, 0, sizeof(struct struct_badblocks_list));
memset(bb, 0, sizeof(struct ext2_struct_badblocks_list));
bb->magic = EXT2_ET_MAGIC_BADBLOCKS_LIST;
bb->size = size ? size : 10;
bb->list = malloc(bb->size * sizeof(blk_t));
@ -45,42 +49,42 @@ errcode_t badblocks_list_create(badblocks_list *ret, int size)
/*
* This procedure frees a badblocks list.
*
* (note: moved to closefs.c)
*/
void badblocks_list_free(badblocks_list bb)
{
if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
return;
if (bb->list)
free(bb->list);
bb->list = 0;
free(bb);
}
/*
* This procedure adds a block to a badblocks list.
*/
errcode_t badblocks_list_add(badblocks_list bb, blk_t blk)
errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb, blk_t blk)
{
int i;
int i, j;
blk_t *new_list;
EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
for (i=0; i < bb->num; i++)
if (bb->list[i] == blk)
return 0;
if (bb->num >= bb->size) {
bb->size += 10;
bb->list = realloc(bb->list, bb->size * sizeof(blk_t));
if (!bb->list) {
bb->size = 0;
bb->num = 0;
new_list = realloc(bb->list, bb->size * sizeof(blk_t));
if (!new_list)
return ENOMEM;
}
bb->list = new_list;
}
bb->list[bb->num++] = blk;
j = bb->num;
for (i=0; i < bb->num; i++) {
if (bb->list[i] == blk)
return 0;
if (bb->list[i] > blk) {
j = i;
break;
}
}
for (i=bb->num; i > j; i--)
bb->list[i] = bb->list[i-1];
bb->list[j] = blk;
bb->num++;
return 0;
}
@ -88,27 +92,42 @@ errcode_t badblocks_list_add(badblocks_list bb, blk_t blk)
* This procedure tests to see if a particular block is on a badblocks
* list.
*/
int badblocks_list_test(badblocks_list bb, blk_t blk)
int ext2fs_badblocks_list_test(ext2_badblocks_list bb, blk_t blk)
{
int i;
int low, high, mid;
EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
return 0;
for (i=0; i < bb->num; i++)
if (bb->list[i] == blk)
low = 0;
high = bb->num-1;
if (blk == bb->list[low])
return 1;
if (blk == bb->list[high])
return 1;
while (low < high) {
mid = (low+high)/2;
if (mid == low || mid == high)
break;
if (blk == bb->list[mid])
return 1;
if (blk < bb->list[mid])
high = mid;
else
low = mid;
}
return 0;
}
errcode_t badblocks_list_iterate_begin(badblocks_list bb,
badblocks_iterate *ret)
errcode_t ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb,
ext2_badblocks_iterate *ret)
{
badblocks_iterate iter;
ext2_badblocks_iterate iter;
EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
iter = malloc(sizeof(struct struct_badblocks_iterate));
iter = malloc(sizeof(struct ext2_struct_badblocks_iterate));
if (!iter)
return ENOMEM;
@ -119,9 +138,9 @@ errcode_t badblocks_list_iterate_begin(badblocks_list bb,
return 0;
}
int badblocks_list_iterate(badblocks_iterate iter, blk_t *blk)
int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter, blk_t *blk)
{
badblocks_list bb;
ext2_badblocks_list bb;
if (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE)
return 0;
@ -139,7 +158,7 @@ int badblocks_list_iterate(badblocks_iterate iter, blk_t *blk)
return 0;
}
void badblocks_list_iterate_end(badblocks_iterate iter)
void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter)
{
if (!iter || (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE))
return;

62
lib/ext2fs/bb_compat.c Normal file
View File

@ -0,0 +1,62 @@
/*
* bb_compat.c --- compatibility badblocks routines
*
* 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 <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/types.h>
#if HAVE_ERRNO_H
#include <errno.h>
#endif
#include <linux/ext2_fs.h>
#include "ext2fsP.h"
errcode_t badblocks_list_create(badblocks_list *ret, int size)
{
return ext2fs_badblocks_list_create(ret, size);
}
void badblocks_list_free(badblocks_list bb)
{
ext2fs_badblocks_list_free(bb);
}
errcode_t badblocks_list_add(badblocks_list bb, blk_t blk)
{
return ext2fs_badblocks_list_add(bb, blk);
}
int badblocks_list_test(badblocks_list bb, blk_t blk)
{
return ext2fs_badblocks_list_test(bb, blk);
}
errcode_t badblocks_list_iterate_begin(badblocks_list bb,
badblocks_iterate *ret)
{
return ext2fs_badblocks_list_iterate_begin(bb, ret);
}
int badblocks_list_iterate(badblocks_iterate iter, blk_t *blk)
{
return ext2fs_badblocks_list_iterate(iter, blk);
}
void badblocks_list_iterate_end(badblocks_iterate iter)
{
ext2fs_badblocks_list_iterate_end(iter);
}

View File

@ -5,8 +5,12 @@
* this routine returns an error, the bad block inode may be in an
* inconsistent state.
*
* Copyright (C) 1994 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
* Copyright (C) 1994, 1995 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <stdio.h>
@ -26,7 +30,7 @@
#include "ext2fs.h"
struct set_badblock_record {
badblocks_iterate bb_iter;
ext2_badblocks_iterate bb_iter;
int bad_block_count;
blk_t *ind_blocks;
int max_ind_blocks;
@ -37,15 +41,16 @@ struct set_badblock_record {
};
static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr, int blockcnt,
void *private);
blk_t ref_block, int ref_offset, void *private);
static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr, int blockcnt,
void *private);
blk_t ref_block, int ref_offset,
void *private);
/*
* Given a bad blocks bitmap, update the bad blocks inode to reflect
* the map.
*/
errcode_t ext2fs_update_bb_inode(ext2_filsys fs, badblocks_list bb_list)
errcode_t ext2fs_update_bb_inode(ext2_filsys fs, ext2_badblocks_list bb_list)
{
errcode_t retval;
struct set_badblock_record rec;
@ -75,9 +80,9 @@ errcode_t ext2fs_update_bb_inode(ext2_filsys fs, badblocks_list bb_list)
/*
* First clear the old bad blocks (while saving the indirect blocks)
*/
retval = ext2fs_block_iterate(fs, EXT2_BAD_INO,
BLOCK_FLAG_DEPTH_TRAVERSE, 0,
clear_bad_block_proc, &rec);
retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO,
BLOCK_FLAG_DEPTH_TRAVERSE, 0,
clear_bad_block_proc, &rec);
if (retval)
goto cleanup;
if (rec.err) {
@ -93,22 +98,24 @@ errcode_t ext2fs_update_bb_inode(ext2_filsys fs, badblocks_list bb_list)
* block inode (!).
*/
if (bb_list) {
retval = badblocks_list_iterate_begin(bb_list, &rec.bb_iter);
retval = ext2fs_badblocks_list_iterate_begin(bb_list,
&rec.bb_iter);
if (retval)
goto cleanup;
while (badblocks_list_iterate(rec.bb_iter, &blk)) {
while (ext2fs_badblocks_list_iterate(rec.bb_iter, &blk)) {
ext2fs_mark_block_bitmap(fs->block_map, blk);
}
badblocks_list_iterate_end(rec.bb_iter);
ext2fs_badblocks_list_iterate_end(rec.bb_iter);
ext2fs_mark_bb_dirty(fs);
retval = badblocks_list_iterate_begin(bb_list, &rec.bb_iter);
retval = ext2fs_badblocks_list_iterate_begin(bb_list,
&rec.bb_iter);
if (retval)
goto cleanup;
retval = ext2fs_block_iterate(fs, EXT2_BAD_INO,
BLOCK_FLAG_APPEND, 0,
set_bad_block_proc, &rec);
badblocks_list_iterate_end(rec.bb_iter);
retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO,
BLOCK_FLAG_APPEND, 0,
set_bad_block_proc, &rec);
ext2fs_badblocks_list_iterate_end(rec.bb_iter);
if (retval)
goto cleanup;
if (rec.err) {
@ -148,7 +155,7 @@ cleanup:
* indirect blocks.
*/
static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr, int blockcnt,
void *private)
blk_t ref_block, int ref_offset, void *private)
{
struct set_badblock_record *rec = (struct set_badblock_record *)
private;
@ -201,7 +208,8 @@ static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr, int blockcnt,
* Set the block list in the bad block inode, using the supplied bitmap.
*/
static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
int blockcnt, void *private)
int blockcnt, blk_t ref_block,
int ref_offset, void *private)
{
struct set_badblock_record *rec = (struct set_badblock_record *)
private;
@ -213,7 +221,7 @@ static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
/*
* Get the next bad block.
*/
if (!badblocks_list_iterate(rec->bb_iter, &blk))
if (!ext2fs_badblocks_list_iterate(rec->bb_iter, &blk))
return BLOCK_ABORT;
rec->bad_block_count++;
} else {

View File

@ -2,8 +2,12 @@
* bitmaps.c --- routines to read, write, and manipulate the inode and
* block bitmaps.
*
* Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <stdio.h>
@ -166,4 +170,3 @@ void ext2fs_clear_block_bitmap(ext2fs_block_bitmap bitmap)
memset(bitmap->bitmap, 0,
((bitmap->real_end - bitmap->start) / 8) + 1);
}

View File

@ -2,10 +2,12 @@
* bitops.c --- Bitmap frobbing code. See bitops.h for the inlined
* routines.
*
* Copyright (C) 1993, 1994 Theodore Ts'o. This file may be
* redistributed under the terms of the GNU Public License.
*
* Taken from <asm/bitops.h>, Copyright 1992, Linus Torvalds.
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <stdio.h>

View File

@ -2,10 +2,15 @@
* bitops.h --- Bitmap frobbing code. The byte swapping routines are
* also included here.
*
* Copyright (C) 1993, 1994, 1995 Theodore Ts'o. This file may be
* redistributed under the terms of the GNU Public License.
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*
* Taken from <asm/bitops.h>, Copyright 1992, Linus Torvalds.
* i386 bitops operations taken from <asm/bitops.h>, Copyright 1992,
* Linus Torvalds.
*/
@ -54,9 +59,22 @@ extern void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
extern int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
ino_t inode);
extern blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap);
extern blk_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap);
extern ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap);
extern blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap);
extern blk_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap);
extern ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap);
extern void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num);
extern void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num);
extern int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num);
extern void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num);
extern void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num);
extern int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num);
/*
* The inline routines themselves...
@ -305,7 +323,14 @@ _INLINE_ __u32 ext2fs_swab32(__u32 val)
#endif /* !_EXT2_HAVE_ASM_SWAB */
_INLINE_ void ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
__u32 bitno)
__u32 bitno);
_INLINE_ void ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
blk_t bitno);
_INLINE_ int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
blk_t bitno);
_INLINE_ void ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
__u32 bitno)
{
if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
ext2fs_warn_bitmap2(bitmap, EXT2FS_MARK_ERROR, bitno);
@ -315,7 +340,7 @@ _INLINE_ void ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
}
_INLINE_ void ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
blk_t bitno)
blk_t bitno)
{
if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
ext2fs_warn_bitmap2(bitmap, EXT2FS_UNMARK_ERROR, bitno);
@ -325,7 +350,7 @@ _INLINE_ void ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
}
_INLINE_ int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
blk_t bitno)
blk_t bitno)
{
if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
ext2fs_warn_bitmap2(bitmap, EXT2FS_UNMARK_ERROR, bitno);
@ -455,7 +480,7 @@ _INLINE_ blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap)
return bitmap->start;
}
_INLINE_ blk_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap)
_INLINE_ ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap)
{
return bitmap->start;
}
@ -465,11 +490,107 @@ _INLINE_ blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap)
return bitmap->end;
}
_INLINE_ blk_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap)
_INLINE_ ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap)
{
return bitmap->end;
}
_INLINE_ int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num)
{
int i;
if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
block, bitmap->description);
return 0;
}
for (i=0; i < num; i++) {
if (ext2fs_fast_test_block_bitmap(bitmap, block+i))
return 0;
}
return 1;
}
_INLINE_ int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num)
{
int i;
#ifdef EXT2FS_DEBUG_FAST_OPS
if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
block, bitmap->description);
return 0;
}
#endif
for (i=0; i < num; i++) {
if (ext2fs_fast_test_block_bitmap(bitmap, block+i))
return 0;
}
return 1;
}
_INLINE_ void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num)
{
int i;
if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
bitmap->description);
return;
}
for (i=0; i < num; i++)
ext2fs_set_bit(block + i - bitmap->start, bitmap->bitmap);
}
_INLINE_ void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num)
{
int i;
#ifdef EXT2FS_DEBUG_FAST_OPS
if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
bitmap->description);
return;
}
#endif
for (i=0; i < num; i++)
ext2fs_set_bit(block + i - bitmap->start, bitmap->bitmap);
}
_INLINE_ void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num)
{
int i;
if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
bitmap->description);
return;
}
for (i=0; i < num; i++)
ext2fs_clear_bit(block + i - bitmap->start, bitmap->bitmap);
}
_INLINE_ void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
blk_t block, int num)
{
int i;
#ifdef EXT2FS_DEBUG_FAST_OPS
if ((block < bitmap->start) || (block+num-1 > bitmap->end)) {
ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
bitmap->description);
return;
}
#endif
for (i=0; i < num; i++)
ext2fs_clear_bit(block + i - bitmap->start, bitmap->bitmap);
}
#undef _INLINE_
#endif

View File

@ -1,8 +1,12 @@
/*
* block.c --- iterate over all blocks in an inode
*
* Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <stdio.h>
@ -22,6 +26,8 @@ struct block_context {
int (*func)(ext2_filsys fs,
blk_t *blocknr,
int bcount,
blk_t ref_blk,
int ref_offset,
void *private);
int bcount;
int bsize;
@ -33,16 +39,18 @@ struct block_context {
void *private;
};
static int block_iterate_ind(blk_t *ind_block, struct block_context *ctx)
static int block_iterate_ind(blk_t *ind_block, blk_t ref_block,
int ref_offset, struct block_context *ctx)
{
int ret = 0, changed = 0;
int i, flags, limit;
int i, flags, limit, offset;
blk_t *block_nr;
if (!(ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
!(ctx->flags & BLOCK_FLAG_DATA_ONLY))
ret = (*ctx->func)(ctx->fs, ind_block,
BLOCK_COUNT_IND, ctx->private);
BLOCK_COUNT_IND, ref_block,
ref_offset, ctx->private);
if (!*ind_block || (ret & BLOCK_ABORT))
return ret;
if (*ind_block >= ctx->fs->super->s_blocks_count ||
@ -65,27 +73,32 @@ static int block_iterate_ind(blk_t *ind_block, struct block_context *ctx)
*block_nr = ext2fs_swab32(*block_nr);
}
block_nr = (blk_t *) ctx->ind_buf;
offset = 0;
if (ctx->flags & BLOCK_FLAG_APPEND) {
for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) {
flags = (*ctx->func)(ctx->fs, block_nr, ctx->bcount,
*ind_block, offset,
ctx->private);
changed |= flags;
if (flags & BLOCK_ABORT) {
ret |= BLOCK_ABORT;
break;
}
offset += sizeof(blk_t);
}
} else {
for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) {
if (*block_nr == 0)
continue;
flags = (*ctx->func)(ctx->fs, block_nr, ctx->bcount,
*ind_block, offset,
ctx->private);
changed |= flags;
if (flags & BLOCK_ABORT) {
ret |= BLOCK_ABORT;
break;
}
offset += sizeof(blk_t);
}
}
if (changed & BLOCK_CHANGED) {
@ -104,20 +117,23 @@ static int block_iterate_ind(blk_t *ind_block, struct block_context *ctx)
!(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
!(ret & BLOCK_ABORT))
ret |= (*ctx->func)(ctx->fs, ind_block,
BLOCK_COUNT_IND, ctx->private);
BLOCK_COUNT_IND, ref_block,
ref_offset, ctx->private);
return ret;
}
static int block_iterate_dind(blk_t *dind_block, struct block_context *ctx)
static int block_iterate_dind(blk_t *dind_block, blk_t ref_block,
int ref_offset, struct block_context *ctx)
{
int ret = 0, changed = 0;
int i, flags, limit;
int i, flags, limit, offset;
blk_t *block_nr;
if (!(ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
!(ctx->flags & BLOCK_FLAG_DATA_ONLY))
ret = (*ctx->func)(ctx->fs, dind_block,
BLOCK_COUNT_DIND, ctx->private);
BLOCK_COUNT_DIND, ref_block,
ref_offset, ctx->private);
if (!*dind_block || (ret & BLOCK_ABORT))
return ret;
if (*dind_block >= ctx->fs->super->s_blocks_count ||
@ -140,25 +156,32 @@ static int block_iterate_dind(blk_t *dind_block, struct block_context *ctx)
*block_nr = ext2fs_swab32(*block_nr);
}
block_nr = (blk_t *) ctx->dind_buf;
offset = 0;
if (ctx->flags & BLOCK_FLAG_APPEND) {
for (i = 0; i < limit; i++, block_nr++) {
flags = block_iterate_ind(block_nr, ctx);
flags = block_iterate_ind(block_nr,
*dind_block, offset,
ctx);
changed |= flags;
if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
break;
}
offset += sizeof(blk_t);
}
} else {
for (i = 0; i < limit; i++, block_nr++) {
if (*block_nr == 0)
continue;
flags = block_iterate_ind(block_nr, ctx);
flags = block_iterate_ind(block_nr,
*dind_block, offset,
ctx);
changed |= flags;
if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
break;
}
offset += sizeof(blk_t);
}
}
if (changed & BLOCK_CHANGED) {
@ -177,20 +200,23 @@ static int block_iterate_dind(blk_t *dind_block, struct block_context *ctx)
!(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
!(ret & BLOCK_ABORT))
ret |= (*ctx->func)(ctx->fs, dind_block,
BLOCK_COUNT_DIND, ctx->private);
BLOCK_COUNT_DIND, ref_block,
ref_offset, ctx->private);
return ret;
}
static int block_iterate_tind(blk_t *tind_block, struct block_context *ctx)
static int block_iterate_tind(blk_t *tind_block, blk_t ref_block,
int ref_offset, struct block_context *ctx)
{
int ret = 0, changed = 0;
int i, flags, limit;
int i, flags, limit, offset;
blk_t *block_nr;
if (!(ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
!(ctx->flags & BLOCK_FLAG_DATA_ONLY))
ret = (*ctx->func)(ctx->fs, tind_block,
BLOCK_COUNT_TIND, ctx->private);
BLOCK_COUNT_TIND, ref_block,
ref_offset, ctx->private);
if (!*tind_block || (ret & BLOCK_ABORT))
return ret;
if (*tind_block >= ctx->fs->super->s_blocks_count ||
@ -213,25 +239,32 @@ static int block_iterate_tind(blk_t *tind_block, struct block_context *ctx)
*block_nr = ext2fs_swab32(*block_nr);
}
block_nr = (blk_t *) ctx->tind_buf;
offset = 0;
if (ctx->flags & BLOCK_FLAG_APPEND) {
for (i = 0; i < limit; i++, block_nr++) {
flags = block_iterate_dind(block_nr, ctx);
flags = block_iterate_dind(block_nr,
*tind_block,
offset, ctx);
changed |= flags;
if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
break;
}
offset += sizeof(blk_t);
}
} else {
for (i = 0; i < limit; i++, block_nr++) {
if (*block_nr == 0)
continue;
flags = block_iterate_dind(block_nr, ctx);
flags = block_iterate_dind(block_nr,
*tind_block,
offset, ctx);
changed |= flags;
if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
break;
}
offset += sizeof(blk_t);
}
}
if (changed & BLOCK_CHANGED) {
@ -250,29 +283,32 @@ static int block_iterate_tind(blk_t *tind_block, struct block_context *ctx)
!(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
!(ret & BLOCK_ABORT))
ret |= (*ctx->func)(ctx->fs, tind_block,
BLOCK_COUNT_TIND, ctx->private);
BLOCK_COUNT_TIND, ref_block,
ref_offset, ctx->private);
return ret;
}
errcode_t ext2fs_block_iterate(ext2_filsys fs,
ino_t ino,
int flags,
char *block_buf,
int (*func)(ext2_filsys fs,
blk_t *blocknr,
int blockcnt,
void *private),
void *private)
errcode_t ext2fs_block_iterate2(ext2_filsys fs,
ino_t ino,
int flags,
char *block_buf,
int (*func)(ext2_filsys fs,
blk_t *blocknr,
int blockcnt,
blk_t ref_blk,
int ref_offset,
void *private),
void *private)
{
int i;
int got_inode = 0;
int ret = 0;
struct block_context ctx;
blk_t blocks[EXT2_N_BLOCKS]; /* directory data blocks */
struct ext2_inode inode;
errcode_t retval;
struct block_context ctx;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
ret = ext2fs_get_blocks(fs, ino, blocks);
@ -282,8 +318,8 @@ errcode_t ext2fs_block_iterate(ext2_filsys fs,
ctx.fs = fs;
ctx.func = func;
ctx.private = private;
ctx.bcount = 0;
ctx.flags = flags;
ctx.bcount = 0;
if (block_buf) {
ctx.ind_buf = block_buf;
} else {
@ -304,8 +340,10 @@ errcode_t ext2fs_block_iterate(ext2_filsys fs,
goto abort;
got_inode = 1;
if (inode.osd1.hurd1.h_i_translator) {
ret |= (*func)(fs, &inode.osd1.hurd1.h_i_translator,
BLOCK_COUNT_TRANSLATOR, private);
ret |= (*ctx.func)(fs,
&inode.osd1.hurd1.h_i_translator,
BLOCK_COUNT_TRANSLATOR,
0, 0, private);
if (ret & BLOCK_ABORT)
goto abort;
}
@ -316,23 +354,27 @@ errcode_t ext2fs_block_iterate(ext2_filsys fs,
*/
for (i = 0; i < EXT2_NDIR_BLOCKS ; i++, ctx.bcount++) {
if (blocks[i] || (flags & BLOCK_FLAG_APPEND)) {
ret |= (*func)(fs, &blocks[i], ctx.bcount, private);
ret |= (*ctx.func)(fs, &blocks[i],
ctx.bcount, 0, 0, private);
if (ret & BLOCK_ABORT)
goto abort;
}
}
if (*(blocks + EXT2_IND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
ret |= block_iterate_ind(blocks + EXT2_IND_BLOCK, &ctx);
ret |= block_iterate_ind(blocks + EXT2_IND_BLOCK,
0, 0, &ctx);
if (ret & BLOCK_ABORT)
goto abort;
}
if (*(blocks + EXT2_DIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
ret |= block_iterate_dind(blocks + EXT2_DIND_BLOCK, &ctx);
ret |= block_iterate_dind(blocks + EXT2_DIND_BLOCK,
0, 0, &ctx);
if (ret & BLOCK_ABORT)
goto abort;
}
if (*(blocks + EXT2_TIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
ret |= block_iterate_tind(blocks + EXT2_TIND_BLOCK, &ctx);
ret |= block_iterate_tind(blocks + EXT2_TIND_BLOCK,
0, 0, &ctx);
if (ret & BLOCK_ABORT)
goto abort;
}
@ -356,3 +398,40 @@ abort:
return (ret & BLOCK_ERROR) ? ctx.errcode : 0;
}
struct xlate {
int (*func)(ext2_filsys fs,
blk_t *blocknr,
int bcount,
void *private);
void *real_private;
};
static int xlate_func(ext2_filsys fs, blk_t *blocknr, int blockcnt,
blk_t ref_block, int ref_offset, void *private)
{
struct xlate *xl = private;
return (*xl->func)(fs, blocknr, blockcnt, xl->real_private);
}
errcode_t ext2fs_block_iterate(ext2_filsys fs,
ino_t ino,
int flags,
char *block_buf,
int (*func)(ext2_filsys fs,
blk_t *blocknr,
int blockcnt,
void *private),
void *private)
{
struct xlate xl;
xl.real_private = private;
xl.func = func;
return ext2fs_block_iterate2(fs, ino, flags, block_buf,
xlate_func, &xl);
}

84
lib/ext2fs/brel.h Normal file
View File

@ -0,0 +1,84 @@
/*
* brel.h
*
* Copyright (C) 1996, 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
struct ext2_block_relocate_entry {
blk_t new;
__s16 offset;
__u16 flags;
union {
blk_t block_ref;
ino_t inode_ref;
} owner;
};
#define RELOCATE_INODE_REF 0x0001
typedef struct ext2_block_relocation_table *ext2_brel;
struct ext2_block_relocation_table {
__u32 magic;
char *name;
blk_t current;
void *private;
/*
* Add a block relocation entry.
*/
errcode_t (*put)(ext2_brel brel, blk_t old,
struct ext2_block_relocate_entry *ent);
/*
* Get a block relocation entry.
*/
errcode_t (*get)(ext2_brel brel, blk_t old,
struct ext2_block_relocate_entry *ent);
/*
* Initialize for iterating over the block relocation entries.
*/
errcode_t (*start_iter)(ext2_brel brel);
/*
* The iterator function for the inode relocation entries.
* Returns an inode number of 0 when out of entries.
*/
errcode_t (*next)(ext2_brel brel, blk_t *old,
struct ext2_block_relocate_entry *ent);
/*
* Move the inode relocation table from one block number to
* another.
*/
errcode_t (*move)(ext2_brel brel, blk_t old, blk_t new);
/*
* Remove a block relocation entry.
*/
errcode_t (*delete)(ext2_brel brel, blk_t old);
/*
* Free the block relocation table.
*/
errcode_t (*free)(ext2_brel brel);
};
errcode_t ext2fs_brel_memarray_create(char *name, blk_t max_block,
ext2_brel *brel);
#define ext2fs_brel_put(brel, old, ent) ((brel)->put((brel), old, ent))
#define ext2fs_brel_get(brel, old, ent) ((brel)->get((brel), old, ent))
#define ext2fs_brel_start_iter(brel) ((brel)->start_iter((brel)))
#define ext2fs_brel_next(brel, old, ent) ((brel)->next((brel), old, ent))
#define ext2fs_brel_move(brel, old, new) ((brel)->move((brel), old, new))
#define ext2fs_brel_delete(brel, old) ((brel)->delete((brel), old))
#define ext2fs_brel_free(brel) ((brel)->free((brel)))

191
lib/ext2fs/brel_ma.c Normal file
View File

@ -0,0 +1,191 @@
/*
* brel_ma.c
*
* Copyright (C) 1996, 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <linux/ext2_fs.h>
#include "ext2fs.h"
#include "brel.h"
static errcode_t bma_put(ext2_brel brel, blk_t old,
struct ext2_block_relocate_entry *ent);
static errcode_t bma_get(ext2_brel brel, blk_t old,
struct ext2_block_relocate_entry *ent);
static errcode_t bma_start_iter(ext2_brel brel);
static errcode_t bma_next(ext2_brel brel, blk_t *old,
struct ext2_block_relocate_entry *ent);
static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new);
static errcode_t bma_delete(ext2_brel brel, blk_t old);
static errcode_t bma_free(ext2_brel brel);
struct brel_ma {
__u32 magic;
blk_t max_block;
struct ext2_block_relocate_entry *entries;
};
errcode_t ext2fs_brel_memarray_create(char *name, blk_t max_block,
ext2_brel *new_brel)
{
ext2_brel brel = 0;
errcode_t retval;
struct brel_ma *ma = 0;
size_t size;
*new_brel = 0;
/*
* Allocate memory structures
*/
retval = ENOMEM;
brel = malloc(sizeof(struct ext2_block_relocation_table));
if (!brel)
goto errout;
memset(brel, 0, sizeof(struct ext2_block_relocation_table));
brel->name = malloc(strlen(name)+1);
if (!brel->name)
goto errout;
strcpy(brel->name, name);
ma = malloc(sizeof(struct brel_ma));
if (!ma)
goto errout;
memset(ma, 0, sizeof(struct brel_ma));
brel->private = ma;
size = sizeof(struct ext2_block_relocate_entry) * (max_block+1);
ma->entries = malloc(size);
if (!ma->entries)
goto errout;
memset(ma->entries, 0, size);
ma->max_block = max_block;
/*
* Fill in the brel data structure
*/
brel->put = bma_put;
brel->get = bma_get;
brel->start_iter = bma_start_iter;
brel->next = bma_next;
brel->move = bma_move;
brel->delete = bma_delete;
brel->free = bma_free;
*new_brel = brel;
return 0;
errout:
bma_free(brel);
return retval;
}
static errcode_t bma_put(ext2_brel brel, blk_t old,
struct ext2_block_relocate_entry *ent)
{
struct brel_ma *ma;
ma = brel->private;
if (old > ma->max_block)
return EINVAL;
ma->entries[old] = *ent;
return 0;
}
static errcode_t bma_get(ext2_brel brel, blk_t old,
struct ext2_block_relocate_entry *ent)
{
struct brel_ma *ma;
ma = brel->private;
if (old > ma->max_block)
return EINVAL;
if (ma->entries[old].new == 0)
return ENOENT;
*ent = ma->entries[old];
return 0;
}
static errcode_t bma_start_iter(ext2_brel brel)
{
brel->current = 0;
return 0;
}
static errcode_t bma_next(ext2_brel brel, blk_t *old,
struct ext2_block_relocate_entry *ent)
{
struct brel_ma *ma;
ma = brel->private;
while (++brel->current < ma->max_block) {
if (ma->entries[brel->current].new == 0)
continue;
*old = brel->current;
*ent = ma->entries[brel->current];
return 0;
}
*old = 0;
return 0;
}
static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new)
{
struct brel_ma *ma;
ma = brel->private;
if ((old > ma->max_block) || (new > ma->max_block))
return EINVAL;
if (ma->entries[old].new == 0)
return ENOENT;
ma->entries[new] = ma->entries[old];
ma->entries[old].new = 0;
return 0;
}
static errcode_t bma_delete(ext2_brel brel, blk_t old)
{
struct brel_ma *ma;
ma = brel->private;
if (old > ma->max_block)
return EINVAL;
if (ma->entries[old].new == 0)
return ENOENT;
ma->entries[old].new = 0;
return 0;
}
static errcode_t bma_free(ext2_brel brel)
{
struct brel_ma *ma;
if (!brel)
return 0;
ma = brel->private;
if (ma) {
if (ma->entries)
free (ma->entries);
free(ma);
}
if (brel->name)
free(brel->name);
free (brel);
return 0;
}

View File

@ -1,8 +1,12 @@
/*
* check_desc.c --- Check the group descriptors of an ext2 filesystem
*
* Copyright (C) 1993, 1994 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <stdio.h>

View File

@ -1,8 +1,12 @@
/*
* closefs.c --- close an ext2 filesystem
*
* Copyright (C) 1993, 1994 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <stdio.h>
@ -16,7 +20,7 @@
#include <linux/ext2_fs.h>
#include "ext2fs.h"
#include "ext2fsP.h"
errcode_t ext2fs_flush(ext2_filsys fs)
{
@ -118,7 +122,6 @@ errcode_t ext2fs_flush(ext2_filsys fs)
if (retval)
goto errout;
}
retval = 0;
errout:
fs->super->s_state = fs_state;
@ -142,6 +145,42 @@ errcode_t ext2fs_close(ext2_filsys fs)
if (retval)
return retval;
}
if (fs->write_bitmaps) {
retval = fs->write_bitmaps(fs);
if (retval)
return retval;
}
ext2fs_free(fs);
return 0;
}
/*
* This procedure frees a badblocks list.
*/
void ext2fs_badblocks_list_free(ext2_badblocks_list bb)
{
if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST)
return;
if (bb->list)
free(bb->list);
bb->list = 0;
free(bb);
}
/*
* Close a directory block list
*/
void ext2fs_free_dblist(ext2_dblist dblist)
{
if (!dblist || (dblist->magic != EXT2_ET_MAGIC_DBLIST))
return;
if (dblist->list)
free(dblist->list);
dblist->list = 0;
if (dblist->fs && dblist->fs->dblist == dblist)
dblist->fs->dblist = 0;
dblist->magic = 0;
free(dblist);
}

View File

@ -1,8 +1,12 @@
/*
* cmp_bitmaps.c --- routines to compare inode and block bitmaps.
*
* Copyright (C) 1995 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
* Copyright (C) 1995 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <stdio.h>

175
lib/ext2fs/dblist.c Normal file
View File

@ -0,0 +1,175 @@
/*
* dblist.c -- directory block list functions
*
* Copyright 1997 by Theodore Ts'o
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#include <linux/ext2_fs.h>
#include "ext2fsP.h"
static int dir_block_cmp(const void *a, const void *b);
/*
* Returns the number of directories in the filesystem as reported by
* the group descriptors. Of course, the group descriptors could be
* wrong!
*/
errcode_t ext2fs_get_num_dirs(ext2_filsys fs, ino_t *ret_num_dirs)
{
int i;
ino_t num_dirs;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
num_dirs = 0;
for (i = 0; i < fs->group_desc_count; i++)
num_dirs += fs->group_desc[i].bg_used_dirs_count;
*ret_num_dirs = num_dirs;
return 0;
}
/*
* Initialize a directory block list
*/
errcode_t ext2fs_init_dblist(ext2_filsys fs, ext2_dblist *ret_dblist)
{
ext2_dblist dblist;
errcode_t retval;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
if ((ret_dblist == 0) && fs->dblist &&
(fs->dblist->magic == EXT2_ET_MAGIC_DBLIST))
return 0;
dblist = malloc(sizeof(struct ext2_struct_dblist));
if (!dblist)
return ENOMEM;
memset(dblist, 0, sizeof(struct ext2_struct_dblist));
dblist->magic = EXT2_ET_MAGIC_DBLIST;
dblist->fs = fs;
retval = ext2fs_get_num_dirs(fs, &dblist->size);
if (retval)
goto cleanup;
dblist->count = 0;
dblist->sorted = 1;
dblist->list = malloc(sizeof(struct ext2_db_entry) * dblist->size);
if (dblist->list == NULL) {
retval = ENOMEM;
goto cleanup;
}
if (ret_dblist)
*ret_dblist = dblist;
else
fs->dblist = dblist;
return 0;
cleanup:
if (dblist)
free(dblist);
return retval;
}
/*
* Close a directory block list
*
* (moved to closefs.c)
*/
/*
* Add a directory block to the directory block list
*/
errcode_t ext2fs_add_dir_block(ext2_dblist dblist, ino_t ino, blk_t blk,
int blockcnt)
{
struct ext2_db_entry *nlist, *new;
EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
if (dblist->count >= dblist->size) {
dblist->size += 100;
nlist = realloc(dblist->list,
dblist->size * sizeof(struct ext2_db_entry));
if (nlist == 0) {
dblist->size -= 100;
return ENOMEM;
}
dblist->list = nlist;
}
new = dblist->list + dblist->count++;
new->blk = blk;
new->ino = ino;
new->blockcnt = blockcnt;
dblist->sorted = 0;
return 0;
}
/*
* This function iterates over the directory block list
*/
errcode_t ext2fs_dblist_iterate(ext2_dblist dblist,
int (*func)(ext2_filsys fs,
struct ext2_db_entry *db_info,
void *private),
void *private)
{
ino_t i;
int ret;
EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
if (!dblist->sorted) {
qsort(dblist->list, dblist->count,
sizeof(struct ext2_db_entry), dir_block_cmp);
dblist->sorted = 1;
}
for (i=0; i < dblist->count; i++) {
ret = (*func)(dblist->fs, &dblist->list[i], private);
if (ret & DBLIST_ABORT)
return 0;
}
return 0;
}
static int dir_block_cmp(const void *a, const void *b)
{
const struct ext2_db_entry *db_a =
(const struct ext2_db_entry *) a;
const struct ext2_db_entry *db_b =
(const struct ext2_db_entry *) b;
if (db_a->blk != db_b->blk)
return (db_a->blk - db_b->blk);
if (db_a->ino != db_b->ino)
return (db_a->ino - db_b->ino);
return (db_a->blockcnt - db_b->blockcnt);
}

79
lib/ext2fs/dblist_dir.c Normal file
View File

@ -0,0 +1,79 @@
/*
* dblist_dir.c --- iterate by directory entry
*
* Copyright 1997 by Theodore Ts'o
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#include <linux/ext2_fs.h>
#include "ext2fsP.h"
static int db_dir_proc(ext2_filsys fs, struct ext2_db_entry *db_info,
void *private);
extern errcode_t
ext2fs_dblist_dir_iterate(ext2_dblist dblist,
int flags,
char *block_buf,
int (*func)(ino_t dir,
int entry,
struct ext2_dir_entry *dirent,
int offset,
int blocksize,
char *buf,
void *private),
void *private)
{
errcode_t retval;
struct dir_context ctx;
EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST);
ctx.dir = 0;
ctx.flags = flags;
if (block_buf)
ctx.buf = block_buf;
else {
ctx.buf = malloc(dblist->fs->blocksize);
if (!ctx.buf)
return ENOMEM;
}
ctx.func = 0;
ctx.func2 = func;
ctx.private = private;
ctx.errcode = 0;
retval = ext2fs_dblist_iterate(dblist, db_dir_proc, &ctx);
if (!block_buf)
free(ctx.buf);
if (retval)
return retval;
return ctx.errcode;
}
static int db_dir_proc(ext2_filsys fs, struct ext2_db_entry *db_info,
void *private)
{
struct dir_context *ctx = private;
ctx->dir = db_info->ino;
return ext2fs_process_dir_block(fs, &db_info->blk,
db_info->blockcnt, private);
}

134
lib/ext2fs/dir_iterate.c Normal file
View File

@ -0,0 +1,134 @@
/*
* dir_iterate.c --- ext2fs directory iteration operations
*
* Copyright (C) 1993, 1994, 1994, 1995, 1996, 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#if HAVE_ERRNO_H
#include <errno.h>
#endif
#include <linux/ext2_fs.h>
#include "ext2fsP.h"
errcode_t ext2fs_dir_iterate(ext2_filsys fs,
ino_t dir,
int flags,
char *block_buf,
int (*func)(struct ext2_dir_entry *dirent,
int offset,
int blocksize,
char *buf,
void *private),
void *private)
{
struct dir_context ctx;
errcode_t retval;
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
retval = ext2fs_check_directory(fs, dir);
if (retval)
return retval;
ctx.dir = dir;
ctx.flags = flags;
if (block_buf)
ctx.buf = block_buf;
else {
ctx.buf = malloc(fs->blocksize);
if (!ctx.buf)
return ENOMEM;
}
ctx.func = func;
ctx.func2 = 0;
ctx.private = private;
ctx.errcode = 0;
retval = ext2fs_block_iterate(fs, dir, 0, 0,
ext2fs_process_dir_block, &ctx);
if (!block_buf)
free(ctx.buf);
if (retval)
return retval;
return ctx.errcode;
}
/*
* Helper function which is private to this module. Used by
* ext2fs_dir_iterate() and ext2fs_dblist_dir_iterate()
*/
extern int ext2fs_process_dir_block(ext2_filsys fs,
blk_t *blocknr,
int blockcnt,
void *private)
{
struct dir_context *ctx = (struct dir_context *) private;
int offset = 0;
int ret = 0;
int changed = 0;
int do_abort = 0;
int entry;
struct ext2_dir_entry *dirent;
if (blockcnt < 0)
return 0;
ctx->errcode = ext2fs_read_dir_block(fs, *blocknr, ctx->buf);
if (ctx->errcode)
return BLOCK_ABORT;
entry = blockcnt ? DIRENT_OTHER_FILE : DIRENT_DOT_FILE;
while (offset < fs->blocksize) {
dirent = (struct ext2_dir_entry *) (ctx->buf + offset);
if (!dirent->inode &&
!(ctx->flags & DIRENT_FLAG_INCLUDE_EMPTY))
goto next;
if (ctx->func)
ret = (ctx->func)(dirent, offset, fs->blocksize,
ctx->buf, ctx->private);
else if (ctx->func2) {
ret = (ctx->func2)(ctx->dir, entry, dirent, offset,
fs->blocksize, ctx->buf,
ctx->private);
if (entry < DIRENT_OTHER_FILE)
entry++;
}
if (ret & DIRENT_CHANGED)
changed++;
if (ret & DIRENT_ABORT) {
do_abort++;
break;
}
next:
if (((offset + dirent->rec_len) > fs->blocksize) ||
(dirent->rec_len < 8) ||
((dirent->name_len+8) > dirent->rec_len)) {
ctx->errcode = EXT2_ET_DIR_CORRUPTED;
return BLOCK_ABORT;
}
offset += dirent->rec_len;
}
if (changed) {
ctx->errcode = ext2fs_write_dir_block(fs, *blocknr, ctx->buf);
if (ctx->errcode)
return BLOCK_ABORT;
}
if (do_abort)
return BLOCK_ABORT;
return 0;
}

View File

@ -1,13 +1,18 @@
/*
* dirblock.c --- directory block routines.
*
* Copyright (C) 1995 Theodore Ts'o. This file may be redistributed
* under the terms of the GNU Public License.
* Copyright (C) 1995, 1996 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifdef HAVE_ERRNO_H
#include <errno.h>

View File

@ -6,6 +6,5 @@
* under the GNU Public License.
*/
#define E2FSPROGS_VERSION "1.06"
#define E2FSPROGS_DATE "7-Oct-96"
#define E2FSPROGS_VERSION "1.07"
#define E2FSPROGS_DATE "14-Mar-97"