mirror of https://github.com/vitalif/e2fsprogs
parent
f45a038dbe
commit
21c84b71e2
|
@ -1,6 +1,6 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
FILES=`find . -name ChangeLog`
|
FILES=`find . -name ChangeLog -print`
|
||||||
|
|
||||||
header=/tmp/revheader
|
header=/tmp/revheader
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
find . -type f \! -name \*~ \! -exec grep -q Begin-Header \{\} \; -print \
|
||||||
|
| grep -v ^./build
|
13
ChangeLog
13
ChangeLog
|
@ -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>
|
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
|
* Makefile.in (all): Don't run "make check" by default. User
|
||||||
|
|
|
@ -9,7 +9,7 @@ system management programs, just follow the steps:
|
||||||
|
|
||||||
1) Install this tar file using the following command:
|
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.
|
2) Run ldconfig to update the shared library pointers.
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ system management programs, just follow the steps:
|
||||||
|
|
||||||
1) Install this tar file using the following command:
|
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.
|
2) Run ldconfig to update the shared library pointers.
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ man1dir = $(usr_prefix)/man/man1
|
||||||
man8dir = $(usr_prefix)/man/man8
|
man8dir = $(usr_prefix)/man/man8
|
||||||
cat1dir = $(usr_prefix)/man/cat1
|
cat1dir = $(usr_prefix)/man/cat1
|
||||||
cat8dir = $(usr_prefix)/man/cat8
|
cat8dir = $(usr_prefix)/man/cat8
|
||||||
|
infodir = $(usr_prefix)/info
|
||||||
|
|
||||||
@SET_MAKE@
|
@SET_MAKE@
|
||||||
|
|
||||||
|
|
22
Makefile.in
22
Makefile.in
|
@ -8,18 +8,26 @@ INSTALL = @INSTALL@
|
||||||
@MCONFIG@
|
@MCONFIG@
|
||||||
|
|
||||||
LIB_SUBDIRS=lib/et lib/ss lib/ext2fs lib/e2p lib/uuid
|
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
|
SUBDIRS=$(LIB_SUBDIRS) $(PROG_SUBDIRS) tests
|
||||||
|
|
||||||
SUBS= include/linux/types.h
|
SUBS= include/linux/types.h
|
||||||
|
|
||||||
all:: $(SUBS) libs progs
|
TAR=tar
|
||||||
|
|
||||||
|
all:: $(SUBS) libs progs docs
|
||||||
|
|
||||||
progs: $(SUBS) all-progs-recursive
|
progs: $(SUBS) all-progs-recursive
|
||||||
libs: $(SUBS) all-libs-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: 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)
|
(export MANPATH=$(DESTDIR)$(mandir); $(srcdir)/install-utils/compile_manpages)
|
||||||
|
|
||||||
install-libs: install-libs-recursive
|
install-libs: install-libs-recursive
|
||||||
|
@ -64,7 +72,7 @@ mostlyclean-local:
|
||||||
$(RM) -f \#* *~ core MAKELOG
|
$(RM) -f \#* *~ core MAKELOG
|
||||||
clean-local: mostlyclean-local
|
clean-local: mostlyclean-local
|
||||||
distclean-local: clean-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
|
$(RM) -f config.status config.log config.cache MCONFIG Makefile
|
||||||
realclean-local: distclean-local
|
realclean-local: distclean-local
|
||||||
$(RM) -f configure
|
$(RM) -f configure
|
||||||
|
@ -78,7 +86,7 @@ distribution_tar_file:
|
||||||
cd ..
|
cd ..
|
||||||
cp -r $(srcdir)/README $(srcdir)/install-utils /tmp/dest
|
cp -r $(srcdir)/README $(srcdir)/install-utils /tmp/dest
|
||||||
cp $(srcdir)/INSTALL.@BINARY_TYPE@ /tmp/dest/INSTALL
|
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
|
> e2fsprogs-@E2FSPROGS_VERSION@-@BINARY_TYPE@.tar.gz
|
||||||
|
|
||||||
SRCROOT = `echo e2fsprogs-@E2FSPROGS_VERSION@ | sed -e 's/-WIP//'`
|
SRCROOT = `echo e2fsprogs-@E2FSPROGS_VERSION@ | sed -e 's/-WIP//'`
|
||||||
|
@ -87,14 +95,14 @@ $(srcdir)/.exclude-file:
|
||||||
(cd $(srcdir)/.. ; find $(SRCROOT) \( -name \*~ -o -name \*.orig \
|
(cd $(srcdir)/.. ; find $(SRCROOT) \( -name \*~ -o -name \*.orig \
|
||||||
-o -name \*.rej \) -print > $(SRCROOT)/.exclude-file)
|
-o -name \*.rej \) -print > $(SRCROOT)/.exclude-file)
|
||||||
echo "$(SRCROOT)/build" >> $(srcdir)/.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)/.exclude-file" >> $(srcdir)/.exclude-file
|
||||||
echo $(SRCROOT)/e2fsprogs-@E2FSPROGS_VERSION@.tar.gz \
|
echo $(SRCROOT)/e2fsprogs-@E2FSPROGS_VERSION@.tar.gz \
|
||||||
>> $(srcdir)/.exclude-file
|
>> $(srcdir)/.exclude-file
|
||||||
|
|
||||||
|
|
||||||
source_tar_file: $(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) | \
|
-X .exclude-file $(SRCROOT) | \
|
||||||
gzip -9 > e2fsprogs-@E2FSPROGS_VERSION@.tar.gz)
|
gzip -9 > e2fsprogs-@E2FSPROGS_VERSION@.tar.gz)
|
||||||
rm -f $(srcdir)/.exclude-file
|
rm -f $(srcdir)/.exclude-file
|
||||||
|
|
4
README
4
README
|
@ -1,5 +1,5 @@
|
||||||
This is the new version (1.05) of the second extended file system
|
This is the new version (1.07) of the second extended file system
|
||||||
management programs, otherwise known as the Monomonac Release.
|
management programs.
|
||||||
|
|
||||||
See the file INSTALL for installation instructions. This is
|
See the file INSTALL for installation instructions. This is
|
||||||
important! Note that your /etc/fstab file may need modifying before
|
important! Note that your /etc/fstab file may need modifying before
|
||||||
|
|
122
RELEASE-NOTES
122
RELEASE-NOTES
|
@ -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)
|
E2fsprogs 1.06 (October 7, 1996)
|
||||||
================================
|
================================
|
||||||
|
|
8
SHLIBS
8
SHLIBS
|
@ -25,3 +25,11 @@ Maintainer: Theodore Ts'o
|
||||||
Email: tytso@mit.edu
|
Email: tytso@mit.edu
|
||||||
Start: 0x66980000
|
Start: 0x66980000
|
||||||
End: 0x669fffff
|
End: 0x669fffff
|
||||||
|
|
||||||
|
Library:libuuid.so
|
||||||
|
Description: DCE Universally Unique ID (UUID) library
|
||||||
|
Maintainer: Theodore Ts'o
|
||||||
|
Email: tytso@mit.edu
|
||||||
|
Start: 0x67900000
|
||||||
|
End: 0x679fffff
|
||||||
|
|
||||||
|
|
|
@ -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
|
# We don't have specific support for the Intel Pentium (p6) followon yet, so just call it a Pentium
|
||||||
basic_machine=i586-intel
|
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
|
# 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/^[^-]*-//'`
|
basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||||
;;
|
;;
|
||||||
|
|
|
@ -505,4 +505,4 @@ test -d include/linux || mkdir include/linux
|
||||||
AC_OUTPUT(MCONFIG lib/substitute_sh Makefile lib/et/Makefile
|
AC_OUTPUT(MCONFIG lib/substitute_sh Makefile lib/et/Makefile
|
||||||
lib/ss/Makefile lib/ext2fs/Makefile lib/e2p/Makefile lib/uuid/Makefile
|
lib/ss/Makefile lib/ext2fs/Makefile lib/e2p/Makefile lib/uuid/Makefile
|
||||||
misc/Makefile e2fsck/Makefile debugfs/Makefile tests/Makefile
|
misc/Makefile e2fsck/Makefile debugfs/Makefile tests/Makefile
|
||||||
relocate/Makefile)
|
tests/progs/Makefile doc/Makefile)
|
||||||
|
|
|
@ -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>
|
Thu Sep 12 15:23:07 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
|
||||||
|
|
||||||
* Release of E2fsprogs version 1.05
|
* Release of E2fsprogs version 1.05
|
||||||
|
|
|
@ -73,8 +73,8 @@ distclean: clean
|
||||||
# Makefile dependencies follow. This must be the last section in
|
# Makefile dependencies follow. This must be the last section in
|
||||||
# the Makefile.in file
|
# the Makefile.in file
|
||||||
#
|
#
|
||||||
debug_cmds.o: debug_cmds.c $(top_builddir)/lib/ss/ss_err.h \
|
debug_cmds.o: debug_cmds.c $(top_srcdir)/lib/ss/ss.h \
|
||||||
$(top_srcdir)/lib/ss/ss.h $(top_srcdir)/lib/ss/copyright.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 \
|
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_srcdir)/lib/ss/ss.h $(top_srcdir)/lib/ss/copyright.h \
|
||||||
$(top_builddir)/lib/ss/ss_err.h $(srcdir)/debugfs.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/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/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
|
||||||
$(top_srcdir)/lib/ext2fs/bitops.h
|
$(top_srcdir)/lib/ext2fs/bitops.h
|
||||||
|
|
||||||
|
|
|
@ -10,9 +10,12 @@ request do_show_debugfs_params, "Show debugfs parameters",
|
||||||
request do_open_filesys, "Open a filesystem",
|
request do_open_filesys, "Open a filesystem",
|
||||||
open_filesys, open;
|
open_filesys, open;
|
||||||
|
|
||||||
request do_close_filesys, "Close a filesystem",
|
request do_close_filesys, "Close the filesystem",
|
||||||
close_filesys, close;
|
close_filesys, close;
|
||||||
|
|
||||||
|
request do_dirty_filesys, "Mark the filesystem as dirty",
|
||||||
|
dirty_filesys, dirty;
|
||||||
|
|
||||||
request do_init_filesys, "Initalize a filesystem (DESTROYS DATA)",
|
request do_init_filesys, "Initalize a filesystem (DESTROYS DATA)",
|
||||||
init_filesys;
|
init_filesys;
|
||||||
|
|
||||||
|
|
|
@ -248,6 +248,14 @@ void do_show_super_stats(int argc, char *argv[])
|
||||||
close_pager(out);
|
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 {
|
struct list_blocks_struct {
|
||||||
FILE *f;
|
FILE *f;
|
||||||
int total;
|
int total;
|
||||||
|
@ -565,7 +573,7 @@ static void modify_u8(char *com, const char *prompt,
|
||||||
const char *format, __u8 *val)
|
const char *format, __u8 *val)
|
||||||
{
|
{
|
||||||
char buf[200];
|
char buf[200];
|
||||||
u_char v;
|
unsigned long v;
|
||||||
char *tmp;
|
char *tmp;
|
||||||
|
|
||||||
sprintf(buf, format, *val);
|
sprintf(buf, format, *val);
|
||||||
|
@ -575,7 +583,7 @@ static void modify_u8(char *com, const char *prompt,
|
||||||
buf[strlen (buf) - 1] = '\0';
|
buf[strlen (buf) - 1] = '\0';
|
||||||
if (!buf[0])
|
if (!buf[0])
|
||||||
return;
|
return;
|
||||||
v = strtol(buf, &tmp, 0);
|
v = strtoul(buf, &tmp, 0);
|
||||||
if (*tmp)
|
if (*tmp)
|
||||||
com_err(com, 0, "Bad value - %s", buf);
|
com_err(com, 0, "Bad value - %s", buf);
|
||||||
else
|
else
|
||||||
|
@ -586,7 +594,7 @@ static void modify_u16(char *com, const char *prompt,
|
||||||
const char *format, __u16 *val)
|
const char *format, __u16 *val)
|
||||||
{
|
{
|
||||||
char buf[200];
|
char buf[200];
|
||||||
u_short v;
|
unsigned long v;
|
||||||
char *tmp;
|
char *tmp;
|
||||||
|
|
||||||
sprintf(buf, format, *val);
|
sprintf(buf, format, *val);
|
||||||
|
@ -596,7 +604,7 @@ static void modify_u16(char *com, const char *prompt,
|
||||||
buf[strlen (buf) - 1] = '\0';
|
buf[strlen (buf) - 1] = '\0';
|
||||||
if (!buf[0])
|
if (!buf[0])
|
||||||
return;
|
return;
|
||||||
v = strtol(buf, &tmp, 0);
|
v = strtoul(buf, &tmp, 0);
|
||||||
if (*tmp)
|
if (*tmp)
|
||||||
com_err(com, 0, "Bad value - %s", buf);
|
com_err(com, 0, "Bad value - %s", buf);
|
||||||
else
|
else
|
||||||
|
@ -607,7 +615,7 @@ static void modify_u32(char *com, const char *prompt,
|
||||||
const char *format, __u32 *val)
|
const char *format, __u32 *val)
|
||||||
{
|
{
|
||||||
char buf[200];
|
char buf[200];
|
||||||
u_long v;
|
unsigned long v;
|
||||||
char *tmp;
|
char *tmp;
|
||||||
|
|
||||||
sprintf(buf, format, *val);
|
sprintf(buf, format, *val);
|
||||||
|
@ -617,7 +625,7 @@ static void modify_u32(char *com, const char *prompt,
|
||||||
buf[strlen (buf) - 1] = '\0';
|
buf[strlen (buf) - 1] = '\0';
|
||||||
if (!buf[0])
|
if (!buf[0])
|
||||||
return;
|
return;
|
||||||
v = strtol(buf, &tmp, 0);
|
v = strtoul(buf, &tmp, 0);
|
||||||
if (*tmp)
|
if (*tmp)
|
||||||
com_err(com, 0, "Bad value - %s", buf);
|
com_err(com, 0, "Bad value - %s", buf);
|
||||||
else
|
else
|
||||||
|
|
|
@ -173,7 +173,7 @@ void do_lsdel(int argc, char **argv)
|
||||||
printf("%6lu %6d %6o %6lu %4d/%4d %s", delarray[i].ino,
|
printf("%6lu %6d %6o %6lu %4d/%4d %s", delarray[i].ino,
|
||||||
delarray[i].uid, delarray[i].mode, delarray[i].size,
|
delarray[i].uid, delarray[i].mode, delarray[i].size,
|
||||||
delarray[i].free_blocks, delarray[i].num_blocks,
|
delarray[i].free_blocks, delarray[i].num_blocks,
|
||||||
ctime(&delarray[i].dtime));
|
time_to_string(delarray[i].dtime));
|
||||||
}
|
}
|
||||||
|
|
||||||
error_out:
|
error_out:
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
File diff suppressed because it is too large
Load Diff
149
e2fsck/ChangeLog
149
e2fsck/ChangeLog
|
@ -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>
|
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
|
* e2fsck.c (main): Print out the version number of the shared
|
||||||
|
|
|
@ -12,7 +12,7 @@ LDFLAG_STATIC = @LDFLAG_STATIC@
|
||||||
|
|
||||||
@MCONFIG@
|
@MCONFIG@
|
||||||
|
|
||||||
PROGS= e2fsck extend @EXTRA_PROGS@
|
PROGS= e2fsck @EXTRA_PROGS@
|
||||||
MANPAGES= e2fsck.8
|
MANPAGES= e2fsck.8
|
||||||
|
|
||||||
LIBS= $(LIBEXT2FS) $(LIBCOM_ERR) $(LIBUUID)
|
LIBS= $(LIBEXT2FS) $(LIBCOM_ERR) $(LIBUUID)
|
||||||
|
@ -26,7 +26,7 @@ PROFILED_DEPLIBS= $(PROFILED_LIBEXT2FS) $(PROFILED_LIBCOM_ERR) $(PROFILED_LIBUUI
|
||||||
|
|
||||||
.c.o:
|
.c.o:
|
||||||
$(CC) -c $(ALL_CFLAGS) $< -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
|
# Flags for using Checker
|
||||||
|
@ -53,12 +53,14 @@ PROFILED_DEPLIBS= $(PROFILED_LIBEXT2FS) $(PROFILED_LIBCOM_ERR) $(PROFILED_LIBUUI
|
||||||
#MCHECK= -DMCHECK
|
#MCHECK= -DMCHECK
|
||||||
|
|
||||||
OBJS= e2fsck.o pass1.o pass1b.o pass2.o pass3.o pass4.o pass5.o \
|
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_OBJS= profiled/e2fsck.o profiled/pass1.o profiled/pass1b.o \
|
||||||
profiled/pass2.o profiled/pass3.o profiled/pass4.o profiled/pass5.o \
|
profiled/pass2.o profiled/pass3.o profiled/pass4.o profiled/pass5.o \
|
||||||
profiled/badblocks.o profiled/util.o profiled/dirinfo.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 \
|
SRCS= $(srcdir)/e2fsck.c \
|
||||||
$(srcdir)/pass1.c \
|
$(srcdir)/pass1.c \
|
||||||
|
@ -71,6 +73,7 @@ SRCS= $(srcdir)/e2fsck.c \
|
||||||
$(srcdir)/util.c \
|
$(srcdir)/util.c \
|
||||||
$(srcdir)/dirinfo.c \
|
$(srcdir)/dirinfo.c \
|
||||||
$(srcdir)/ehandler.c \
|
$(srcdir)/ehandler.c \
|
||||||
|
$(srcdir)/problem.c \
|
||||||
$(MTRACE_SRC)
|
$(MTRACE_SRC)
|
||||||
|
|
||||||
all:: profiled $(PROGS) e2fsck.static e2fsck.shared $(MANPAGES)
|
all:: profiled $(PROGS) e2fsck.static e2fsck.shared $(MANPAGES)
|
||||||
|
@ -87,8 +90,8 @@ e2fsck.static: $(OBJS) $(STATIC_DEPLIBS)
|
||||||
e2fsck.shared: $(OBJS) $(DEPLIBS)
|
e2fsck.shared: $(OBJS) $(DEPLIBS)
|
||||||
$(LD) $(ALL_LDFLAGS) -o e2fsck.shared $(OBJS) $(LIBS)
|
$(LD) $(ALL_LDFLAGS) -o e2fsck.shared $(OBJS) $(LIBS)
|
||||||
|
|
||||||
e2fsck.profiled: $(PROFILED_OBJS) $(DEPLIBS)
|
e2fsck.profiled: $(PROFILED_OBJS) $(PROFILED_DEPLIBS)
|
||||||
$(LD) $(ALL_LDFLAGS) -pg -o e2fsck.profiled $(PROFILED_OBJS) \
|
$(LD) $(ALL_LDFLAGS) -g -pg -o e2fsck.profiled $(PROFILED_OBJS) \
|
||||||
$(PROFILED_LIBS)
|
$(PROFILED_LIBS)
|
||||||
|
|
||||||
extend: extend.o
|
extend: extend.o
|
||||||
|
@ -122,8 +125,9 @@ install: $(PROGS) $(MANPAGES) installdirs
|
||||||
done
|
done
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
$(RM) -f $(sbindir)/e2fsck
|
for i in $(PROGS); do \
|
||||||
$(RM) -f $(sbindir)/flushb
|
$(RM) -f $(sbindir)/$$i; \
|
||||||
|
done
|
||||||
$(RM) -f $(sbindir)/fsck.ext2
|
$(RM) -f $(sbindir)/fsck.ext2
|
||||||
for i in $(MANPAGES); do \
|
for i in $(MANPAGES); do \
|
||||||
$(RM) -f $(man8dir)/$$i; \
|
$(RM) -f $(man8dir)/$$i; \
|
||||||
|
@ -143,46 +147,66 @@ distclean: clean
|
||||||
# Makefile dependencies follow. This must be the last section in
|
# Makefile dependencies follow. This must be the last section in
|
||||||
# the Makefile.in file
|
# 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/uuid/uuid.h $(srcdir)/e2fsck.h \
|
||||||
$(top_srcdir)/lib/ext2fs/ext2fs.h \
|
$(top_srcdir)/lib/ext2fs/ext2fs.h \
|
||||||
$(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
|
$(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
|
||||||
$(top_srcdir)/lib/ext2fs/bitops.h $(srcdir)/../version.h
|
$(top_srcdir)/lib/ext2fs/bitops.h $(srcdir)/problem.h \
|
||||||
pass1.o: $(srcdir)/pass1.c $(top_srcdir)/lib/et/com_err.h \
|
$(srcdir)/../version.h
|
||||||
$(srcdir)/e2fsck.h $(top_srcdir)/lib/ext2fs/ext2fs.h \
|
pass1.o: $(srcdir)/pass1.c \
|
||||||
$(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
|
$(top_srcdir)/lib/et/com_err.h \
|
||||||
$(top_srcdir)/lib/ext2fs/bitops.h
|
$(srcdir)/e2fsck.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/ext2fs.h \
|
$(top_srcdir)/lib/ext2fs/ext2fs.h \
|
||||||
$(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_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 $(srcdir)/problem.h
|
||||||
pass3.o: $(srcdir)/pass3.c $(top_srcdir)/lib/et/com_err.h $(srcdir)/e2fsck.h \
|
pass1b.o: $(srcdir)/pass1b.c \
|
||||||
$(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/bitops.h \
|
$(top_srcdir)/lib/et/com_err.h \
|
||||||
$(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_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 \
|
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/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/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
|
||||||
$(top_srcdir)/lib/ext2fs/bitops.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 \
|
pass5.o: $(srcdir)/pass5.c $(top_srcdir)/lib/et/com_err.h \
|
||||||
$(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/bitops.h \
|
$(srcdir)/e2fsck.h \
|
||||||
$(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
|
$(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/io.h \
|
||||||
badblocks.o: $(srcdir)/badblocks.c $(top_srcdir)/lib/et/com_err.h \
|
$(top_builddir)/lib/ext2fs/ext2_err.h $(top_srcdir)/lib/ext2fs/bitops.h
|
||||||
$(srcdir)/e2fsck.h $(top_srcdir)/lib/ext2fs/ext2fs.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/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
|
||||||
$(top_srcdir)/lib/ext2fs/bitops.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/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/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
|
||||||
$(top_srcdir)/lib/ext2fs/bitops.h
|
$(top_srcdir)/lib/ext2fs/bitops.h
|
||||||
dirinfo.o: $(srcdir)/dirinfo.c $(top_srcdir)/lib/et/com_err.h \
|
dirinfo.o: $(srcdir)/dirinfo.c $(top_srcdir)/lib/et/com_err.h \
|
||||||
$(srcdir)/e2fsck.h $(top_srcdir)/lib/ext2fs/ext2fs.h \
|
$(srcdir)/e2fsck.h \
|
||||||
$(top_srcdir)/lib/ext2fs/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
|
$(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/io.h \
|
||||||
$(top_srcdir)/lib/ext2fs/bitops.h
|
$(top_builddir)/lib/ext2fs/ext2_err.h $(top_srcdir)/lib/ext2fs/bitops.h
|
||||||
ehandler.o: $(srcdir)/ehandler.c $(srcdir)/e2fsck.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/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/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
|
||||||
|
|
|
@ -24,12 +24,11 @@ int get_num_dirs(ext2_filsys fs)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This subroutine is called during pass1 to stash away the block
|
* This subroutine is called during pass1 to create a directory info
|
||||||
* numbers for the directory, which we will need later. The idea is
|
* entry. During pass1, the passed-in parent is 0; it will get filled
|
||||||
* to avoid reading directory inodes twice.
|
* in during pass2.
|
||||||
*/
|
*/
|
||||||
void add_dir_info(ext2_filsys fs, ino_t ino, ino_t parent,
|
void add_dir_info(ext2_filsys fs, ino_t ino, ino_t parent)
|
||||||
struct ext2_inode *inode)
|
|
||||||
{
|
{
|
||||||
struct dir_info *dir;
|
struct dir_info *dir;
|
||||||
int i, j;
|
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
|
* the dir_info array needs to be sorted by inode number for
|
||||||
* get_dir_info()'s sake.
|
* 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--)
|
for (i = dir_info_count-1; i > 0; i--)
|
||||||
if (dir_info[i-1].ino < ino)
|
if (dir_info[i-1].ino < ino)
|
||||||
break;
|
break;
|
||||||
|
@ -87,6 +86,8 @@ struct dir_info *get_dir_info(ino_t ino)
|
||||||
|
|
||||||
low = 0;
|
low = 0;
|
||||||
high = dir_info_count-1;
|
high = dir_info_count-1;
|
||||||
|
if (!dir_info)
|
||||||
|
return 0;
|
||||||
if (ino == dir_info[low].ino)
|
if (ino == dir_info[low].ino)
|
||||||
return &dir_info[low];
|
return &dir_info[low];
|
||||||
if (ino == dir_info[high].ino)
|
if (ino == dir_info[high].ino)
|
||||||
|
@ -118,3 +119,14 @@ void free_dir_info(ext2_filsys fs)
|
||||||
dir_info_size = 0;
|
dir_info_size = 0;
|
||||||
dir_info_count = 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)++);
|
||||||
|
}
|
||||||
|
|
133
e2fsck/e2fsck.c
133
e2fsck/e2fsck.c
|
@ -1,8 +1,12 @@
|
||||||
/*
|
/*
|
||||||
* e2fsck.c - a consistency checker for the new extended file system.
|
* e2fsck.c - a consistency checker for the new extended file system.
|
||||||
*
|
*
|
||||||
* Copyright (C) 1993, 1994 Theodore Ts'o. This file may be
|
* Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
|
||||||
* redistributed under the terms of the GNU Public License.
|
*
|
||||||
|
* %Begin-Header%
|
||||||
|
* This file may be redistributed under the terms of the GNU Public
|
||||||
|
* License.
|
||||||
|
* %End-Header%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Usage: e2fsck [-dfpnsvy] device
|
/* Usage: e2fsck [-dfpnsvy] device
|
||||||
|
@ -42,6 +46,7 @@
|
||||||
#include "et/com_err.h"
|
#include "et/com_err.h"
|
||||||
#include "uuid/uuid.h"
|
#include "uuid/uuid.h"
|
||||||
#include "e2fsck.h"
|
#include "e2fsck.h"
|
||||||
|
#include "problem.h"
|
||||||
#include "../version.h"
|
#include "../version.h"
|
||||||
|
|
||||||
extern int isatty(int);
|
extern int isatty(int);
|
||||||
|
@ -60,6 +65,7 @@ int rwflag = 1;
|
||||||
int swapfs = 0;
|
int swapfs = 0;
|
||||||
int normalize_swapfs = 0;
|
int normalize_swapfs = 0;
|
||||||
int inode_buffer_blocks = 0;
|
int inode_buffer_blocks = 0;
|
||||||
|
blk_t use_superblock;
|
||||||
blk_t superblock;
|
blk_t superblock;
|
||||||
int blocksize = 0;
|
int blocksize = 0;
|
||||||
int verbose = 0;
|
int verbose = 0;
|
||||||
|
@ -236,8 +242,11 @@ static void relocate_hint(void)
|
||||||
{
|
{
|
||||||
static hint_issued = 0;
|
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;
|
return;
|
||||||
|
|
||||||
printf("Note: if there is several inode or block bitmap blocks\n"
|
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;
|
int i;
|
||||||
blk_t should_be;
|
blk_t should_be;
|
||||||
errcode_t retval;
|
errcode_t retval;
|
||||||
|
struct problem_context pctx;
|
||||||
|
|
||||||
|
clear_problem_context(&pctx);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Verify the super block constants...
|
* Verify the super block constants...
|
||||||
|
@ -334,55 +346,52 @@ static void check_super_block(ext2_filsys fs)
|
||||||
last_block = first_block + blocks_per_group;
|
last_block = first_block + blocks_per_group;
|
||||||
|
|
||||||
for (i = 0; i < fs->group_desc_count; i++) {
|
for (i = 0; i < fs->group_desc_count; i++) {
|
||||||
|
pctx.group = i;
|
||||||
|
|
||||||
if (i == fs->group_desc_count - 1)
|
if (i == fs->group_desc_count - 1)
|
||||||
last_block = fs->super->s_blocks_count;
|
last_block = fs->super->s_blocks_count;
|
||||||
if ((fs->group_desc[i].bg_block_bitmap < first_block) ||
|
if ((fs->group_desc[i].bg_block_bitmap < first_block) ||
|
||||||
(fs->group_desc[i].bg_block_bitmap >= last_block)) {
|
(fs->group_desc[i].bg_block_bitmap >= last_block)) {
|
||||||
relocate_hint();
|
relocate_hint();
|
||||||
printf("Block bitmap for group %d is not in group. "
|
pctx.blk = fs->group_desc[i].bg_block_bitmap;
|
||||||
"(block %u)\n",
|
if (fix_problem(fs, PR_0_BB_NOT_GROUP, &pctx)) {
|
||||||
i, fs->group_desc[i].bg_block_bitmap);
|
fs->group_desc[i].bg_block_bitmap = 0;
|
||||||
preenhalt(fs);
|
invalid_block_bitmap[i]++;
|
||||||
if (!ask("Relocate", 1)) {
|
invalid_bitmaps++;
|
||||||
fatal_error("Block bitmap not in group");
|
|
||||||
}
|
}
|
||||||
fs->group_desc[i].bg_block_bitmap = 0;
|
|
||||||
invalid_block_bitmap[i]++;
|
|
||||||
invalid_bitmaps++;
|
|
||||||
}
|
}
|
||||||
if ((fs->group_desc[i].bg_inode_bitmap < first_block) ||
|
if ((fs->group_desc[i].bg_inode_bitmap < first_block) ||
|
||||||
(fs->group_desc[i].bg_inode_bitmap >= last_block)) {
|
(fs->group_desc[i].bg_inode_bitmap >= last_block)) {
|
||||||
relocate_hint();
|
relocate_hint();
|
||||||
printf("Inode bitmap group %d not in group. "
|
pctx.blk = fs->group_desc[i].bg_inode_bitmap;
|
||||||
"(block %u)\n",
|
if (fix_problem(fs, PR_0_IB_NOT_GROUP, &pctx)) {
|
||||||
i, fs->group_desc[i].bg_inode_bitmap);
|
fs->group_desc[i].bg_inode_bitmap = 0;
|
||||||
preenhalt(fs);
|
invalid_inode_bitmap[i]++;
|
||||||
if (!ask("Relocate", 1)) {
|
invalid_bitmaps++;
|
||||||
fatal_error("Inode bitmap not in group");
|
|
||||||
}
|
}
|
||||||
fs->group_desc[i].bg_inode_bitmap = 0;
|
|
||||||
invalid_inode_bitmap[i]++;
|
|
||||||
invalid_bitmaps++;
|
|
||||||
}
|
}
|
||||||
if ((fs->group_desc[i].bg_inode_table < first_block) ||
|
if ((fs->group_desc[i].bg_inode_table < first_block) ||
|
||||||
((fs->group_desc[i].bg_inode_table +
|
((fs->group_desc[i].bg_inode_table +
|
||||||
fs->inode_blocks_per_group - 1) >= last_block)) {
|
fs->inode_blocks_per_group - 1) >= last_block)) {
|
||||||
relocate_hint();
|
relocate_hint();
|
||||||
printf("Inode table for group %d not in group. "
|
pctx.blk = fs->group_desc[i].bg_inode_table;
|
||||||
"(block %u)\n",
|
if (fix_problem(fs, PR_0_ITABLE_NOT_GROUP, &pctx)) {
|
||||||
i, fs->group_desc[i].bg_inode_table);
|
fs->group_desc[i].bg_inode_table = 0;
|
||||||
printf("WARNING: SEVERE DATA LOSS POSSIBLE.\n");
|
invalid_inode_table[i]++;
|
||||||
preenhalt(fs);
|
invalid_bitmaps++;
|
||||||
if (!ask("Relocate", 1)) {
|
|
||||||
fatal_error("Inode table not in group");
|
|
||||||
}
|
}
|
||||||
fs->group_desc[i].bg_inode_table = 0;
|
|
||||||
invalid_inode_table[i]++;
|
|
||||||
invalid_bitmaps++;
|
|
||||||
}
|
}
|
||||||
first_block += fs->super->s_blocks_per_group;
|
first_block += fs->super->s_blocks_per_group;
|
||||||
last_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.
|
* 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! */
|
/* What we do by default, anyway! */
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
superblock = atoi(optarg);
|
use_superblock = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
case 'B':
|
case 'B':
|
||||||
blocksize = atoi(optarg);
|
blocksize = atoi(optarg);
|
||||||
|
@ -588,7 +597,9 @@ int main (int argc, char *argv[])
|
||||||
errcode_t retval = 0;
|
errcode_t retval = 0;
|
||||||
int exit_value = FSCK_OK;
|
int exit_value = FSCK_OK;
|
||||||
int i;
|
int i;
|
||||||
ext2_filsys fs;
|
ext2_filsys fs = 0;
|
||||||
|
io_manager io_ptr;
|
||||||
|
struct ext2fs_sb *s;
|
||||||
|
|
||||||
#ifdef MTRACE
|
#ifdef MTRACE
|
||||||
mtrace();
|
mtrace();
|
||||||
|
@ -601,7 +612,7 @@ int main (int argc, char *argv[])
|
||||||
|
|
||||||
PRS(argc, argv);
|
PRS(argc, argv);
|
||||||
|
|
||||||
if (!preen)
|
if (!preen || show_version_only)
|
||||||
fprintf (stderr, "e2fsck %s, %s for EXT2 FS %s, %s\n",
|
fprintf (stderr, "e2fsck %s, %s for EXT2 FS %s, %s\n",
|
||||||
E2FSPROGS_VERSION, E2FSPROGS_DATE,
|
E2FSPROGS_VERSION, E2FSPROGS_DATE,
|
||||||
EXT2FS_VERSION, EXT2FS_DATE);
|
EXT2FS_VERSION, EXT2FS_DATE);
|
||||||
|
@ -618,27 +629,46 @@ int main (int argc, char *argv[])
|
||||||
if (!isatty (0) || !isatty (1))
|
if (!isatty (0) || !isatty (1))
|
||||||
die ("need terminal for interactive repairs");
|
die ("need terminal for interactive repairs");
|
||||||
}
|
}
|
||||||
|
superblock = use_superblock;
|
||||||
restart:
|
restart:
|
||||||
|
#if 1
|
||||||
|
io_ptr = unix_io_manager;
|
||||||
|
#else
|
||||||
|
io_ptr = test_io_manager;
|
||||||
|
test_io_backing_manager = unix_io_manager;
|
||||||
|
#endif
|
||||||
sync_disks();
|
sync_disks();
|
||||||
if (superblock && blocksize) {
|
if (superblock && blocksize) {
|
||||||
retval = ext2fs_open(filesystem_name,
|
retval = ext2fs_open(filesystem_name,
|
||||||
rwflag ? EXT2_FLAG_RW : 0,
|
rwflag ? EXT2_FLAG_RW : 0,
|
||||||
superblock, blocksize, unix_io_manager,
|
superblock, blocksize, io_ptr, &fs);
|
||||||
&fs);
|
|
||||||
} else if (superblock) {
|
} else if (superblock) {
|
||||||
for (i=0; possible_block_sizes[i]; i++) {
|
for (i=0; possible_block_sizes[i]; i++) {
|
||||||
retval = ext2fs_open(filesystem_name,
|
retval = ext2fs_open(filesystem_name,
|
||||||
rwflag ? EXT2_FLAG_RW : 0,
|
rwflag ? EXT2_FLAG_RW : 0,
|
||||||
superblock,
|
superblock,
|
||||||
possible_block_sizes[i],
|
possible_block_sizes[i],
|
||||||
unix_io_manager, &fs);
|
io_ptr, &fs);
|
||||||
if (!retval)
|
if (!retval)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
retval = ext2fs_open(filesystem_name,
|
retval = ext2fs_open(filesystem_name,
|
||||||
rwflag ? EXT2_FLAG_RW : 0,
|
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) {
|
if (retval) {
|
||||||
com_err(program_name, retval, "while trying to open %s",
|
com_err(program_name, retval, "while trying to open %s",
|
||||||
filesystem_name);
|
filesystem_name);
|
||||||
|
@ -656,16 +686,28 @@ restart:
|
||||||
printf(corrupt_msg);
|
printf(corrupt_msg);
|
||||||
fatal_error(0);
|
fatal_error(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef EXT2_CURRENT_REV
|
#ifdef EXT2_CURRENT_REV
|
||||||
if (fs->super->s_rev_level > E2FSCK_CURRENT_REV) {
|
if (fs->super->s_rev_level > E2FSCK_CURRENT_REV) {
|
||||||
com_err(program_name, EXT2_ET_REV_TOO_HIGH,
|
com_err(program_name, EXT2_ET_REV_TOO_HIGH,
|
||||||
"while trying to open %s",
|
"while trying to open %s",
|
||||||
filesystem_name);
|
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");
|
printf ("Get a newer version of e2fsck!\n");
|
||||||
fatal_error(0);
|
fatal_error(0);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
/*
|
/*
|
||||||
* If the user specified a specific superblock, presumably the
|
* If the user specified a specific superblock, presumably the
|
||||||
* master superblock has been trashed. So we mark the
|
* master superblock has been trashed. So we mark the
|
||||||
|
@ -715,6 +757,14 @@ restart:
|
||||||
*/
|
*/
|
||||||
ext2fs_mark_valid(fs);
|
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);
|
pass1(fs);
|
||||||
free(invalid_inode_bitmap);
|
free(invalid_inode_bitmap);
|
||||||
free(invalid_block_bitmap);
|
free(invalid_block_bitmap);
|
||||||
|
@ -723,6 +773,7 @@ restart:
|
||||||
ext2fs_close(fs);
|
ext2fs_close(fs);
|
||||||
printf("Restarting e2fsck from the beginning...\n");
|
printf("Restarting e2fsck from the beginning...\n");
|
||||||
restart_e2fsck = 0;
|
restart_e2fsck = 0;
|
||||||
|
superblock = use_superblock;
|
||||||
goto restart;
|
goto restart;
|
||||||
}
|
}
|
||||||
pass2(fs);
|
pass2(fs);
|
||||||
|
|
|
@ -47,13 +47,13 @@
|
||||||
/*
|
/*
|
||||||
* Inode count arrays
|
* Inode count arrays
|
||||||
*/
|
*/
|
||||||
extern unsigned short * inode_count;
|
extern ext2_icount_t inode_count;
|
||||||
extern unsigned short * inode_link_info;
|
extern ext2_icount_t inode_link_info;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The directory information structure; stores directory information
|
* The directory information structure; stores directory information
|
||||||
* collected in earlier passes, to avoid disk i/o in fetching the
|
* collected in earlier passes, to avoid disk i/o in fetching the
|
||||||
* directoryt information.
|
* directory information.
|
||||||
*/
|
*/
|
||||||
struct dir_info {
|
struct dir_info {
|
||||||
ino_t ino; /* Inode number */
|
ino_t ino; /* Inode number */
|
||||||
|
@ -61,16 +61,6 @@ struct dir_info {
|
||||||
ino_t parent; /* Parent according to treewalk */
|
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
|
* This structure is used for keeping track of how much resources have
|
||||||
* been used for a particular pass of e2fsck.
|
* 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_used_map; /* Inodes which are in use */
|
||||||
extern ext2fs_inode_bitmap inode_bad_map; /* Inodes which are bad somehow */
|
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_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_found_map; /* Blocks which are in use */
|
||||||
extern ext2fs_block_bitmap block_dup_map; /* Blocks which are used by more than once */
|
extern ext2fs_block_bitmap block_dup_map; /* Blocks which are used by more than once */
|
||||||
|
@ -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);
|
extern void test_disk(ext2_filsys fs);
|
||||||
|
|
||||||
/* dirinfo.c */
|
/* dirinfo.c */
|
||||||
extern void add_dir_info(ext2_filsys fs, ino_t ino, ino_t parent,
|
extern void add_dir_info(ext2_filsys fs, ino_t ino, ino_t parent);
|
||||||
struct ext2_inode *inode);
|
|
||||||
extern struct dir_info *get_dir_info(ino_t ino);
|
extern struct dir_info *get_dir_info(ino_t ino);
|
||||||
extern void free_dir_info(ext2_filsys fs);
|
extern void free_dir_info(ext2_filsys fs);
|
||||||
extern int get_num_dirs(ext2_filsys fs);
|
extern int get_num_dirs(ext2_filsys fs);
|
||||||
|
extern struct dir_info *dir_info_iter(int *control);
|
||||||
|
|
||||||
/* ehandler.c */
|
/* ehandler.c */
|
||||||
extern const char *ehandler_operation(const char *op);
|
extern const char *ehandler_operation(const char *op);
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
471
e2fsck/pass1.c
471
e2fsck/pass1.c
|
@ -1,8 +1,12 @@
|
||||||
/*
|
/*
|
||||||
* pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
|
* pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
|
||||||
*
|
*
|
||||||
* Copyright (C) 1993, 1994 Theodore Ts'o. This file may be
|
* Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
|
||||||
* redistributed under the terms of the GNU Public License.
|
*
|
||||||
|
* %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,
|
* Pass 1 of e2fsck iterates over all the inodes in the filesystems,
|
||||||
* and applies the following tests to each inode:
|
* 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 in use. (inode_used_map)
|
||||||
* - A bitmap of which inodes are directories. (inode_dir_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 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. (block_found_map)
|
||||||
* - A bitmap of which blocks are in use by two inodes (block_dup_map)
|
* - A bitmap of which blocks are in use by two inodes (block_dup_map)
|
||||||
* - The data blocks of the directory inodes. (dir_map)
|
* - The data blocks of the directory inodes. (dir_map)
|
||||||
|
@ -37,6 +42,7 @@
|
||||||
|
|
||||||
#include <et/com_err.h>
|
#include <et/com_err.h>
|
||||||
#include "e2fsck.h"
|
#include "e2fsck.h"
|
||||||
|
#include "problem.h"
|
||||||
|
|
||||||
#ifdef NO_INLINE_FUNCS
|
#ifdef NO_INLINE_FUNCS
|
||||||
#define _INLINE_
|
#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_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_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_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_found_map = 0;
|
||||||
ext2fs_block_bitmap block_dup_map = 0;
|
ext2fs_block_bitmap block_dup_map = 0;
|
||||||
ext2fs_block_bitmap block_illegal_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,
|
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,
|
static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
|
||||||
int blockcnt, void *private);
|
int blockcnt, blk_t ref_blk,
|
||||||
static void check_blocks(ext2_filsys fs, ino_t ino, struct ext2_inode *inode,
|
int ref_offset, void *private);
|
||||||
|
static void check_blocks(ext2_filsys fs, struct problem_context *pctx,
|
||||||
char *block_buf);
|
char *block_buf);
|
||||||
static void mark_table_blocks(ext2_filsys fs);
|
static void mark_table_blocks(ext2_filsys fs);
|
||||||
static void alloc_bad_map(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 handle_fs_bad_blocks(ext2_filsys fs);
|
||||||
static void process_inodes(ext2_filsys fs, char *block_buf);
|
static void process_inodes(ext2_filsys fs, char *block_buf);
|
||||||
static int process_inode_cmp(const void *a, const void *b);
|
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,
|
static errcode_t scan_callback(ext2_filsys fs, ext2_inode_scan scan,
|
||||||
dgrp_t group, void * private);
|
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 {
|
struct process_block_struct {
|
||||||
ino_t ino;
|
ino_t ino;
|
||||||
|
@ -93,9 +102,9 @@ struct process_block_struct {
|
||||||
int num_blocks;
|
int num_blocks;
|
||||||
int last_block;
|
int last_block;
|
||||||
int num_illegal_blocks;
|
int num_illegal_blocks;
|
||||||
int fix;
|
|
||||||
blk_t previous_block;
|
blk_t previous_block;
|
||||||
struct ext2_inode *inode;
|
struct ext2_inode *inode;
|
||||||
|
struct problem_context *pctx;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct process_inode_block {
|
struct process_inode_block {
|
||||||
|
@ -116,13 +125,6 @@ static struct process_inode_block *inodes_to_process;
|
||||||
static int process_inode_count;
|
static int process_inode_count;
|
||||||
int process_inode_size = 256;
|
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
|
* Free all memory allocated by pass1 in preparation for restarting
|
||||||
* things.
|
* 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_used_map); inode_used_map = 0;
|
||||||
ext2fs_free_inode_bitmap(inode_dir_map); inode_dir_map = 0;
|
ext2fs_free_inode_bitmap(inode_dir_map); inode_dir_map = 0;
|
||||||
ext2fs_free_block_bitmap(block_found_map); block_found_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(inodes_to_process);inodes_to_process = 0;
|
||||||
free(dir_blocks); dir_blocks = 0;
|
ext2fs_free_dblist(fs->dblist); fs->dblist = 0;
|
||||||
dir_block_size = 0;
|
free_dir_info(fs);
|
||||||
if (block_dup_map) {
|
if (block_dup_map) {
|
||||||
ext2fs_free_block_bitmap(block_dup_map); block_dup_map = 0;
|
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 */
|
/* Clear statistic counters */
|
||||||
fs_directory_count = 0;
|
fs_directory_count = 0;
|
||||||
|
@ -167,6 +175,7 @@ void pass1(ext2_filsys fs)
|
||||||
errcode_t retval;
|
errcode_t retval;
|
||||||
struct resource_track rtrack;
|
struct resource_track rtrack;
|
||||||
unsigned char frag, fsize;
|
unsigned char frag, fsize;
|
||||||
|
struct problem_context pctx;
|
||||||
|
|
||||||
init_resource_track(&rtrack);
|
init_resource_track(&rtrack);
|
||||||
|
|
||||||
|
@ -208,19 +217,23 @@ void pass1(ext2_filsys fs)
|
||||||
"while allocating block_illegal_map");
|
"while allocating block_illegal_map");
|
||||||
fatal_error(0);
|
fatal_error(0);
|
||||||
}
|
}
|
||||||
inode_link_info = allocate_memory((fs->super->s_inodes_count + 1) *
|
retval = ext2fs_create_icount(fs, 0, 0, &inode_link_info);
|
||||||
sizeof(unsigned short),
|
if (retval) {
|
||||||
"inode link count array");
|
com_err("ext2fs_create_icount", retval,
|
||||||
|
"while creating inode_link_info");
|
||||||
|
fatal_error(0);
|
||||||
|
}
|
||||||
inodes_to_process = allocate_memory(process_inode_size *
|
inodes_to_process = allocate_memory(process_inode_size *
|
||||||
sizeof(struct process_inode_block),
|
sizeof(struct process_inode_block),
|
||||||
"array of inodes to process");
|
"array of inodes to process");
|
||||||
process_inode_count = 0;
|
process_inode_count = 0;
|
||||||
|
|
||||||
dir_block_size = get_num_dirs(fs) * 4;
|
retval = ext2fs_init_dblist(fs, 0);
|
||||||
dir_block_count = 0;
|
if (retval) {
|
||||||
dir_blocks = allocate_memory(sizeof(struct dir_block_struct) *
|
com_err(program_name, retval,
|
||||||
dir_block_size,
|
"while allocating directory block information");
|
||||||
"directory block information");
|
fatal_error(0);
|
||||||
|
}
|
||||||
|
|
||||||
mark_table_blocks(fs);
|
mark_table_blocks(fs);
|
||||||
block_buf = allocate_memory(fs->blocksize * 3, "block interate buffer");
|
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");
|
com_err(program_name, retval, "while opening inode scan");
|
||||||
fatal_error(0);
|
fatal_error(0);
|
||||||
}
|
}
|
||||||
|
ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
|
||||||
retval = ext2fs_get_next_inode(scan, &ino, &inode);
|
retval = ext2fs_get_next_inode(scan, &ino, &inode);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
com_err(program_name, retval, "while starting inode scan");
|
com_err(program_name, retval, "while starting inode scan");
|
||||||
|
@ -241,25 +255,36 @@ void pass1(ext2_filsys fs)
|
||||||
}
|
}
|
||||||
stashed_inode = &inode;
|
stashed_inode = &inode;
|
||||||
ext2fs_set_inode_callback(scan, scan_callback, block_buf);
|
ext2fs_set_inode_callback(scan, scan_callback, block_buf);
|
||||||
|
clear_problem_context(&pctx);
|
||||||
while (ino) {
|
while (ino) {
|
||||||
stashed_ino = 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) {
|
if (ino == EXT2_BAD_INO) {
|
||||||
struct process_block_struct pb;
|
struct process_block_struct pb;
|
||||||
|
|
||||||
pb.ino = EXT2_BAD_INO;
|
pb.ino = EXT2_BAD_INO;
|
||||||
pb.num_blocks = pb.last_block = 0;
|
pb.num_blocks = pb.last_block = 0;
|
||||||
pb.num_illegal_blocks = 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.fragmented = 0;
|
||||||
pb.fix = -1;
|
|
||||||
pb.inode = &inode;
|
pb.inode = &inode;
|
||||||
retval = ext2fs_block_iterate(fs, ino, 0, block_buf,
|
pb.pctx = &pctx;
|
||||||
process_bad_block, &pb);
|
retval = ext2fs_block_iterate2(fs, ino, 0, block_buf,
|
||||||
|
process_bad_block, &pb);
|
||||||
if (retval)
|
if (retval)
|
||||||
com_err(program_name, retval, "while calling e2fsc_block_interate in pass 1");
|
com_err(program_name, retval, "while calling e2fsc_block_interate in pass 1");
|
||||||
|
|
||||||
ext2fs_mark_inode_bitmap(inode_used_map, ino);
|
ext2fs_mark_inode_bitmap(inode_used_map, ino);
|
||||||
|
clear_problem_context(&pctx);
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
if (ino == EXT2_ROOT_INO) {
|
if (ino == EXT2_ROOT_INO) {
|
||||||
|
@ -269,16 +294,14 @@ void pass1(ext2_filsys fs)
|
||||||
* regnerated in pass #3.
|
* regnerated in pass #3.
|
||||||
*/
|
*/
|
||||||
if (!LINUX_S_ISDIR(inode.i_mode)) {
|
if (!LINUX_S_ISDIR(inode.i_mode)) {
|
||||||
printf("Root inode is not a directory. ");
|
if (fix_problem(fs, PR_1_ROOT_NO_DIR, &pctx)) {
|
||||||
preenhalt(fs);
|
|
||||||
if (ask("Clear", 1)) {
|
|
||||||
inode.i_dtime = time(0);
|
inode.i_dtime = time(0);
|
||||||
inode.i_links_count = 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,
|
e2fsck_write_inode(fs, ino, &inode,
|
||||||
"pass1");
|
"pass1");
|
||||||
} else
|
}
|
||||||
ext2fs_unmark_valid(fs);
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* If dtime is set, offer to clear it. mke2fs
|
* If dtime is set, offer to clear it. mke2fs
|
||||||
|
@ -290,34 +313,30 @@ void pass1(ext2_filsys fs)
|
||||||
* as a special case.
|
* as a special case.
|
||||||
*/
|
*/
|
||||||
if (inode.i_dtime && inode.i_links_count) {
|
if (inode.i_dtime && inode.i_links_count) {
|
||||||
if (ask("Root inode has dtime set "
|
if (fix_problem(fs, PR_1_ROOT_DTIME, &pctx)) {
|
||||||
"(probably due to old mke2fs). Fix",
|
|
||||||
1)) {
|
|
||||||
inode.i_dtime = 0;
|
inode.i_dtime = 0;
|
||||||
e2fsck_write_inode(fs, ino, &inode,
|
e2fsck_write_inode(fs, ino, &inode,
|
||||||
"pass1");
|
"pass1");
|
||||||
} else
|
}
|
||||||
ext2fs_unmark_valid(fs);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ino == EXT2_BOOT_LOADER_INO) {
|
if (ino == EXT2_BOOT_LOADER_INO) {
|
||||||
ext2fs_mark_inode_bitmap(inode_used_map, ino);
|
ext2fs_mark_inode_bitmap(inode_used_map, ino);
|
||||||
check_blocks(fs, ino, &inode, block_buf);
|
check_blocks(fs, &pctx, block_buf);
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
if ((ino != EXT2_ROOT_INO) &&
|
if ((ino != EXT2_ROOT_INO) &&
|
||||||
(ino < EXT2_FIRST_INODE(fs->super))) {
|
(ino < EXT2_FIRST_INODE(fs->super))) {
|
||||||
ext2fs_mark_inode_bitmap(inode_used_map, ino);
|
ext2fs_mark_inode_bitmap(inode_used_map, ino);
|
||||||
if (inode.i_mode != 0) {
|
if (inode.i_mode != 0) {
|
||||||
printf("Reserved inode %lu has bad mode. ", ino);
|
if (fix_problem(fs,
|
||||||
if (ask("Clear", 1)) {
|
PR_1_RESERVED_BAD_MODE, &pctx)) {
|
||||||
inode.i_mode = 0;
|
inode.i_mode = 0;
|
||||||
e2fsck_write_inode(fs, ino, &inode,
|
e2fsck_write_inode(fs, ino, &inode,
|
||||||
"pass1");
|
"pass1");
|
||||||
} else
|
}
|
||||||
ext2fs_unmark_valid(fs);
|
|
||||||
}
|
}
|
||||||
check_blocks(fs, ino, &inode, block_buf);
|
check_blocks(fs, &pctx, block_buf);
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -326,14 +345,12 @@ void pass1(ext2_filsys fs)
|
||||||
*/
|
*/
|
||||||
if (!inode.i_links_count) {
|
if (!inode.i_links_count) {
|
||||||
if (!inode.i_dtime && inode.i_mode) {
|
if (!inode.i_dtime && inode.i_mode) {
|
||||||
printf("Deleted inode %lu has zero dtime.\n",
|
if (fix_problem(fs,
|
||||||
ino);
|
PR_1_ZERO_DTIME, &pctx)) {
|
||||||
if (ask("Set dtime", 1)) {
|
|
||||||
inode.i_dtime = time(0);
|
inode.i_dtime = time(0);
|
||||||
e2fsck_write_inode(fs, ino, &inode,
|
e2fsck_write_inode(fs, ino, &inode,
|
||||||
"pass1");
|
"pass1");
|
||||||
} else
|
}
|
||||||
ext2fs_unmark_valid(fs);
|
|
||||||
}
|
}
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
|
@ -348,13 +365,10 @@ void pass1(ext2_filsys fs)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
if (inode.i_dtime) {
|
if (inode.i_dtime) {
|
||||||
printf("Inode %lu is in use, but has dtime set\n",
|
if (fix_problem(fs, PR_1_SET_DTIME, &pctx)) {
|
||||||
ino);
|
|
||||||
if (ask("Clear dtime", 1)) {
|
|
||||||
inode.i_dtime = 0;
|
inode.i_dtime = 0;
|
||||||
e2fsck_write_inode(fs, ino, &inode, "pass1");
|
e2fsck_write_inode(fs, ino, &inode, "pass1");
|
||||||
} else
|
}
|
||||||
ext2fs_unmark_valid(fs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ext2fs_mark_inode_bitmap(inode_used_map, ino);
|
ext2fs_mark_inode_bitmap(inode_used_map, ino);
|
||||||
|
@ -384,7 +398,7 @@ void pass1(ext2_filsys fs)
|
||||||
|
|
||||||
if (LINUX_S_ISDIR(inode.i_mode)) {
|
if (LINUX_S_ISDIR(inode.i_mode)) {
|
||||||
ext2fs_mark_inode_bitmap(inode_dir_map, ino);
|
ext2fs_mark_inode_bitmap(inode_dir_map, ino);
|
||||||
add_dir_info(fs, ino, 0, &inode);
|
add_dir_info(fs, ino, 0);
|
||||||
fs_directory_count++;
|
fs_directory_count++;
|
||||||
} else if (LINUX_S_ISREG (inode.i_mode))
|
} else if (LINUX_S_ISREG (inode.i_mode))
|
||||||
fs_regular_count++;
|
fs_regular_count++;
|
||||||
|
@ -394,8 +408,10 @@ void pass1(ext2_filsys fs)
|
||||||
fs_blockdev_count++;
|
fs_blockdev_count++;
|
||||||
else if (LINUX_S_ISLNK (inode.i_mode)) {
|
else if (LINUX_S_ISLNK (inode.i_mode)) {
|
||||||
fs_symlinks_count++;
|
fs_symlinks_count++;
|
||||||
if (!inode.i_blocks)
|
if (!inode.i_blocks) {
|
||||||
fs_fast_symlinks_count++;
|
fs_fast_symlinks_count++;
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (LINUX_S_ISFIFO (inode.i_mode))
|
else if (LINUX_S_ISFIFO (inode.i_mode))
|
||||||
fs_fifo_count++;
|
fs_fifo_count++;
|
||||||
|
@ -419,12 +435,19 @@ void pass1(ext2_filsys fs)
|
||||||
inodes_to_process[process_inode_count].inode = inode;
|
inodes_to_process[process_inode_count].inode = inode;
|
||||||
process_inode_count++;
|
process_inode_count++;
|
||||||
} else
|
} else
|
||||||
check_blocks(fs, ino, &inode, block_buf);
|
check_blocks(fs, &pctx, block_buf);
|
||||||
|
|
||||||
if (process_inode_count >= process_inode_size)
|
if (process_inode_count >= process_inode_size)
|
||||||
process_inodes(fs, block_buf);
|
process_inodes(fs, block_buf);
|
||||||
next:
|
next:
|
||||||
retval = ext2fs_get_next_inode(scan, &ino, &inode);
|
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) {
|
if (retval) {
|
||||||
com_err(program_name, retval,
|
com_err(program_name, retval,
|
||||||
"while doing inode scan");
|
"while doing inode scan");
|
||||||
|
@ -435,9 +458,6 @@ void pass1(ext2_filsys fs)
|
||||||
ext2fs_close_inode_scan(scan);
|
ext2fs_close_inode_scan(scan);
|
||||||
ehandler_operation(0);
|
ehandler_operation(0);
|
||||||
|
|
||||||
qsort(dir_blocks, dir_block_count, sizeof(struct dir_block_struct),
|
|
||||||
dir_block_cmp);
|
|
||||||
|
|
||||||
if (invalid_bitmaps)
|
if (invalid_bitmaps)
|
||||||
handle_fs_bad_blocks(fs);
|
handle_fs_bad_blocks(fs);
|
||||||
|
|
||||||
|
@ -463,7 +483,7 @@ endit:
|
||||||
free(block_buf);
|
free(block_buf);
|
||||||
ext2fs_free_block_bitmap(block_illegal_map);
|
ext2fs_free_block_bitmap(block_illegal_map);
|
||||||
block_illegal_map = 0;
|
block_illegal_map = 0;
|
||||||
|
|
||||||
if (tflag > 1) {
|
if (tflag > 1) {
|
||||||
printf("Pass 1: ");
|
printf("Pass 1: ");
|
||||||
print_resource_track(&rtrack);
|
print_resource_track(&rtrack);
|
||||||
|
@ -488,30 +508,33 @@ static void process_inodes(ext2_filsys fs, char *block_buf)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct ext2_inode *old_stashed_inode;
|
struct ext2_inode *old_stashed_inode;
|
||||||
ino_t ino;
|
ino_t old_stashed_ino;
|
||||||
const char *old_operation;
|
const char *old_operation;
|
||||||
char buf[80];
|
char buf[80];
|
||||||
|
struct problem_context pctx;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
printf("begin process_inodes: ");
|
printf("begin process_inodes: ");
|
||||||
#endif
|
#endif
|
||||||
old_operation = ehandler_operation(0);
|
old_operation = ehandler_operation(0);
|
||||||
old_stashed_inode = stashed_inode;
|
old_stashed_inode = stashed_inode;
|
||||||
|
old_stashed_ino = stashed_ino;
|
||||||
qsort(inodes_to_process, process_inode_count,
|
qsort(inodes_to_process, process_inode_count,
|
||||||
sizeof(struct process_inode_block), process_inode_cmp);
|
sizeof(struct process_inode_block), process_inode_cmp);
|
||||||
|
clear_problem_context(&pctx);
|
||||||
for (i=0; i < process_inode_count; i++) {
|
for (i=0; i < process_inode_count; i++) {
|
||||||
stashed_inode = &inodes_to_process[i].inode;
|
pctx.inode = stashed_inode = &inodes_to_process[i].inode;
|
||||||
ino = inodes_to_process[i].ino;
|
pctx.ino = stashed_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);
|
|
||||||
|
|
||||||
|
#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_inode = old_stashed_inode;
|
||||||
|
stashed_ino = old_stashed_ino;
|
||||||
process_inode_count = 0;
|
process_inode_count = 0;
|
||||||
#if 0
|
#if 0
|
||||||
printf("end process inodes\n");
|
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]);
|
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
|
* 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
|
* Marks a block as in use, setting the dup_map if it's been set
|
||||||
* already. Called by process_block and process_bad_block.
|
* 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
|
* This subroutine is called on each inode to account for all of the
|
||||||
* blocks used by that inode.
|
* 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)
|
char *block_buf)
|
||||||
{
|
{
|
||||||
struct process_block_struct pb;
|
struct process_block_struct pb;
|
||||||
errcode_t retval;
|
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;
|
return;
|
||||||
|
|
||||||
pb.ino = ino;
|
pb.ino = ino;
|
||||||
pb.num_blocks = pb.last_block = 0;
|
pb.num_blocks = pb.last_block = 0;
|
||||||
pb.num_illegal_blocks = 0;
|
pb.num_illegal_blocks = 0;
|
||||||
pb.suppress = pb.clear = 0;
|
pb.suppress = 0; pb.clear = 0;
|
||||||
pb.fragmented = 0;
|
pb.fragmented = 0;
|
||||||
pb.previous_block = 0;
|
pb.previous_block = 0;
|
||||||
pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
|
pb.is_dir = LINUX_S_ISDIR(pctx->inode->i_mode);
|
||||||
pb.fix = -1;
|
|
||||||
pb.inode = inode;
|
pb.inode = inode;
|
||||||
retval = ext2fs_block_iterate(fs, ino,
|
pb.pctx = pctx;
|
||||||
pb.is_dir ? BLOCK_FLAG_HOLE : 0,
|
retval = ext2fs_block_iterate2(fs, ino,
|
||||||
block_buf, process_block, &pb);
|
pb.is_dir ? BLOCK_FLAG_HOLE : 0,
|
||||||
|
block_buf, process_block, &pb);
|
||||||
|
reset_problem_latch(PR_LATCH_BLOCK);
|
||||||
if (retval)
|
if (retval)
|
||||||
com_err(program_name, retval,
|
com_err(program_name, retval,
|
||||||
"while calling ext2fs_block_iterate in check_blocks");
|
"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);
|
fatal_error(0);
|
||||||
}
|
}
|
||||||
inode->i_links_count = 0;
|
inode->i_links_count = 0;
|
||||||
inode_link_info[ino] = 0;
|
ext2fs_icount_store(inode_link_info, ino, 0);
|
||||||
inode->i_dtime = time(0);
|
inode->i_dtime = time(0);
|
||||||
e2fsck_write_inode(fs, ino, inode, "check_blocks");
|
e2fsck_write_inode(fs, ino, inode, "check_blocks");
|
||||||
ext2fs_unmark_inode_bitmap(inode_dir_map, ino);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pb.fix > 0)
|
|
||||||
e2fsck_read_inode(fs, ino, inode, "check_blocks");
|
|
||||||
|
|
||||||
pb.num_blocks *= (fs->blocksize / 512);
|
pb.num_blocks *= (fs->blocksize / 512);
|
||||||
#if 0
|
#if 0
|
||||||
printf("inode %u, i_size = %lu, last_block = %lu, i_blocks=%lu, num_blocks = %lu\n",
|
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);
|
pb.num_blocks);
|
||||||
#endif
|
#endif
|
||||||
if (!pb.num_blocks && pb.is_dir) {
|
if (!pb.num_blocks && pb.is_dir) {
|
||||||
printf("Inode %lu is a zero length directory. ", ino);
|
if (fix_problem(fs, PR_1_ZERO_LENGTH_DIR, pctx)) {
|
||||||
if (ask("Clear", 1)) {
|
|
||||||
inode->i_links_count = 0;
|
inode->i_links_count = 0;
|
||||||
inode_link_info[ino] = 0;
|
ext2fs_icount_store(inode_link_info, ino, 0);
|
||||||
inode->i_dtime = time(0);
|
inode->i_dtime = time(0);
|
||||||
e2fsck_write_inode(fs, ino, inode, "check_blocks");
|
e2fsck_write_inode(fs, ino, inode, "check_blocks");
|
||||||
ext2fs_unmark_inode_bitmap(inode_dir_map, ino);
|
ext2fs_unmark_inode_bitmap(inode_dir_map, ino);
|
||||||
ext2fs_unmark_inode_bitmap(inode_used_map, ino);
|
ext2fs_unmark_inode_bitmap(inode_used_map, ino);
|
||||||
fs_directory_count--;
|
fs_directory_count--;
|
||||||
pb.is_dir = 0;
|
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)) {
|
(inode->i_size < pb.last_block * fs->blocksize)) {
|
||||||
printf ("%s %lu, incorrect size, %u (counted = %u). ",
|
pctx->num = (pb.last_block+1) * fs->blocksize;
|
||||||
pb.is_dir ? "Directory" : "Inode", ino, inode->i_size,
|
if (fix_problem(fs, PR_1_BAD_I_SIZE, pctx)) {
|
||||||
(pb.last_block+1) * fs->blocksize);
|
inode->i_size = pctx->num;
|
||||||
if (ask ("Set size to counted", 1)) {
|
|
||||||
inode->i_size = (pb.last_block+1) * fs->blocksize;
|
|
||||||
e2fsck_write_inode(fs, ino, inode, "check_blocks");
|
e2fsck_write_inode(fs, ino, inode, "check_blocks");
|
||||||
} else
|
}
|
||||||
ext2fs_unmark_valid(fs);
|
pctx->num = 0;
|
||||||
}
|
}
|
||||||
if (pb.num_blocks != inode->i_blocks) {
|
if (pb.num_blocks != inode->i_blocks) {
|
||||||
printf ("Inode %lu, i_blocks wrong %u (counted=%u). ",
|
pctx->num = pb.num_blocks;
|
||||||
ino, inode->i_blocks, pb.num_blocks);
|
if (fix_problem(fs, PR_1_BAD_I_BLOCKS, pctx)) {
|
||||||
if (ask ("Set i_blocks to counted", 1)) {
|
|
||||||
inode->i_blocks = pb.num_blocks;
|
inode->i_blocks = pb.num_blocks;
|
||||||
e2fsck_write_inode(fs, ino, inode, "check_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
|
* Helper function called by process block when an illegal block is
|
||||||
* found. It returns a description about why the block is illegal
|
* 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);
|
return(problem);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is a helper function for check_blocks().
|
* 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,
|
int process_block(ext2_filsys fs,
|
||||||
blk_t *block_nr,
|
blk_t *block_nr,
|
||||||
int blockcnt,
|
int blockcnt,
|
||||||
|
blk_t ref_block,
|
||||||
|
int ref_offset,
|
||||||
void *private)
|
void *private)
|
||||||
{
|
{
|
||||||
struct process_block_struct *p;
|
struct process_block_struct *p;
|
||||||
char *problem;
|
struct problem_context *pctx;
|
||||||
blk_t blk = *block_nr;
|
blk_t blk = *block_nr;
|
||||||
int ret_code = 0;
|
int ret_code = 0;
|
||||||
|
int problem = 0;
|
||||||
|
errcode_t retval;
|
||||||
|
|
||||||
p = (struct process_block_struct *) private;
|
p = (struct process_block_struct *) private;
|
||||||
|
pctx = p->pctx;
|
||||||
|
|
||||||
if (blk == 0) {
|
if (blk == 0) {
|
||||||
if (p->is_dir == 0) {
|
if (p->is_dir == 0) {
|
||||||
|
@ -767,8 +793,10 @@ int process_block(ext2_filsys fs,
|
||||||
if (blockcnt < 0)
|
if (blockcnt < 0)
|
||||||
return 0;
|
return 0;
|
||||||
if (blockcnt * fs->blocksize < p->inode->i_size) {
|
if (blockcnt * fs->blocksize < p->inode->i_size) {
|
||||||
printf("Hole found in directory inode %lu! "
|
#if 0
|
||||||
"(blkcnt=%d)\n", p->ino, blockcnt);
|
printf("Missing block (#%d) in directory inode %lu!\n",
|
||||||
|
blockcnt, p->ino);
|
||||||
|
#endif
|
||||||
goto mark_dir;
|
goto mark_dir;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -790,43 +818,34 @@ int process_block(ext2_filsys fs,
|
||||||
}
|
}
|
||||||
p->previous_block = blk;
|
p->previous_block = blk;
|
||||||
|
|
||||||
|
|
||||||
if (blk < fs->super->s_first_data_block ||
|
if (blk < fs->super->s_first_data_block ||
|
||||||
blk >= fs->super->s_blocks_count ||
|
blk >= fs->super->s_blocks_count)
|
||||||
ext2fs_test_block_bitmap(block_illegal_map, blk)) {
|
problem = PR_1_ILLEGAL_BLOCK_NUM;
|
||||||
problem = describe_illegal_block(fs, blk);
|
else if (ext2fs_test_block_bitmap(block_illegal_map, blk))
|
||||||
if (preen) {
|
problem = PR_1_BLOCK_OVERLAPS_METADATA;
|
||||||
printf("Block %u of inode %lu %s\n", blk, p->ino,
|
|
||||||
problem);
|
if (problem) {
|
||||||
preenhalt(fs);
|
|
||||||
}
|
|
||||||
if (p->fix == -1) {
|
|
||||||
printf("Remove illegal block(s) in inode %lu", p->ino);
|
|
||||||
p->fix = ask("", 1);
|
|
||||||
}
|
|
||||||
p->num_illegal_blocks++;
|
p->num_illegal_blocks++;
|
||||||
if (!p->suppress && (p->num_illegal_blocks % 20) == 0) {
|
if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
|
||||||
printf("Too many illegal blocks in inode %lu.\n",
|
if (fix_problem(fs, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
|
||||||
p->ino);
|
|
||||||
if (ask("Clear inode", 1)) {
|
|
||||||
p->clear = 1;
|
p->clear = 1;
|
||||||
return BLOCK_ABORT;
|
return BLOCK_ABORT;
|
||||||
}
|
}
|
||||||
if (ask("Supress messages", 0)) {
|
if (ask("Suppress messages", 0)) {
|
||||||
p->suppress = 1;
|
p->suppress = 1;
|
||||||
|
suppress_latch_group(PR_LATCH_BLOCK, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!p->suppress)
|
pctx->blk = blk;
|
||||||
printf("Block #%d (%u) %s. %s\n", blockcnt, blk,
|
pctx->blkcount = blockcnt;
|
||||||
problem, clear_msg[p->fix]);
|
if (fix_problem(fs, problem, pctx)) {
|
||||||
if (p->fix) {
|
|
||||||
blk = *block_nr = 0;
|
blk = *block_nr = 0;
|
||||||
ret_code = BLOCK_CHANGED;
|
ret_code = BLOCK_CHANGED;
|
||||||
goto mark_dir;
|
goto mark_dir;
|
||||||
} else {
|
} else
|
||||||
ext2fs_unmark_valid(fs);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
pctx->blk = 0;
|
||||||
|
pctx->blkcount = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
mark_block_used(fs, blk);
|
mark_block_used(fs, blk);
|
||||||
|
@ -835,20 +854,13 @@ int process_block(ext2_filsys fs,
|
||||||
p->last_block = blockcnt;
|
p->last_block = blockcnt;
|
||||||
mark_dir:
|
mark_dir:
|
||||||
if (p->is_dir && (blockcnt >= 0)) {
|
if (p->is_dir && (blockcnt >= 0)) {
|
||||||
if (dir_block_count >= dir_block_size) {
|
retval = ext2fs_add_dir_block(fs->dblist, p->ino,
|
||||||
dir_block_size += 100;
|
blk, blockcnt);
|
||||||
dir_blocks = realloc(dir_blocks,
|
if (retval) {
|
||||||
dir_block_size *
|
com_err(program_name, retval,
|
||||||
sizeof(struct dir_block_struct));
|
"while adding to directory block list");
|
||||||
if (dir_blocks == 0)
|
fatal_error(0);
|
||||||
fatal_error("Not enough memory to "
|
|
||||||
"realloc dir_blocks");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
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,
|
int process_bad_block(ext2_filsys fs,
|
||||||
blk_t *block_nr,
|
blk_t *block_nr,
|
||||||
int blockcnt,
|
int blockcnt,
|
||||||
|
blk_t ref_block,
|
||||||
|
int ref_offset,
|
||||||
void *private)
|
void *private)
|
||||||
{
|
{
|
||||||
struct process_block_struct *p;
|
struct process_block_struct *p;
|
||||||
blk_t blk = *block_nr;
|
blk_t blk = *block_nr;
|
||||||
int first_block;
|
int first_block;
|
||||||
int i;
|
int i;
|
||||||
|
struct problem_context *pctx;
|
||||||
|
|
||||||
if (!blk)
|
if (!blk)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
p = (struct process_block_struct *) private;
|
p = (struct process_block_struct *) private;
|
||||||
|
pctx = p->pctx;
|
||||||
|
|
||||||
|
pctx->blk = blk;
|
||||||
|
pctx->blkcount = blockcnt;
|
||||||
|
|
||||||
|
|
||||||
if ((blk < fs->super->s_first_data_block) ||
|
if ((blk < fs->super->s_first_data_block) ||
|
||||||
(blk >= fs->super->s_blocks_count)) {
|
(blk >= fs->super->s_blocks_count)) {
|
||||||
if (preen) {
|
if (fix_problem(fs, PR_1_BB_ILLEGAL_BLOCK_NUM, pctx)) {
|
||||||
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) {
|
|
||||||
*block_nr = 0;
|
*block_nr = 0;
|
||||||
return BLOCK_CHANGED;
|
return BLOCK_CHANGED;
|
||||||
} else {
|
} else
|
||||||
ext2fs_unmark_valid(fs);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blockcnt < 0) {
|
if (blockcnt < 0) {
|
||||||
|
@ -943,6 +954,7 @@ int process_bad_block(ext2_filsys fs,
|
||||||
first_block = fs->super->s_first_data_block;
|
first_block = fs->super->s_first_data_block;
|
||||||
|
|
||||||
for (i = 0; i < fs->group_desc_count; i++ ) {
|
for (i = 0; i < fs->group_desc_count; i++ ) {
|
||||||
|
pctx->group = i;
|
||||||
if (blk == first_block) {
|
if (blk == first_block) {
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
printf("The primary superblock (%u) is "
|
printf("The primary superblock (%u) is "
|
||||||
|
@ -973,39 +985,29 @@ int process_bad_block(ext2_filsys fs,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (blk == fs->group_desc[i].bg_block_bitmap) {
|
if (blk == fs->group_desc[i].bg_block_bitmap) {
|
||||||
printf("Group %d's block bitmap (%u) is bad. ",
|
if (fix_problem(fs, PR_1_BB_BAD_BLOCK, pctx)) {
|
||||||
i, blk);
|
|
||||||
if (ask("Relocate", 1)) {
|
|
||||||
invalid_block_bitmap[i]++;
|
invalid_block_bitmap[i]++;
|
||||||
invalid_bitmaps++;
|
invalid_bitmaps++;
|
||||||
} else
|
}
|
||||||
ext2fs_unmark_valid(fs);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (blk == fs->group_desc[i].bg_inode_bitmap) {
|
if (blk == fs->group_desc[i].bg_inode_bitmap) {
|
||||||
printf("Group %d's inode bitmap (%u) is bad. ",
|
if (fix_problem(fs, PR_1_IB_BAD_BLOCK, pctx)) {
|
||||||
i, blk);
|
|
||||||
if (ask("Relocate", 1)) {
|
|
||||||
invalid_inode_bitmap[i]++;
|
invalid_inode_bitmap[i]++;
|
||||||
invalid_bitmaps++;
|
invalid_bitmaps++;
|
||||||
} else
|
}
|
||||||
ext2fs_unmark_valid(fs);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if ((blk >= fs->group_desc[i].bg_inode_table) &&
|
if ((blk >= fs->group_desc[i].bg_inode_table) &&
|
||||||
(blk < (fs->group_desc[i].bg_inode_table +
|
(blk < (fs->group_desc[i].bg_inode_table +
|
||||||
fs->inode_blocks_per_group))) {
|
fs->inode_blocks_per_group))) {
|
||||||
printf("WARNING: Severe data loss possible!!!!\n");
|
/*
|
||||||
printf("Bad block %u in group %d's inode table. ",
|
* If there are bad blocks in the inode table,
|
||||||
blk, i);
|
* the inode scan code will try to do
|
||||||
if (ask("Relocate", 1)) {
|
* something reasonable automatically.
|
||||||
invalid_inode_table[i]++;
|
*/
|
||||||
invalid_bitmaps++;
|
|
||||||
} else
|
|
||||||
ext2fs_unmark_valid(fs);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
first_block += fs->super->s_blocks_per_group;
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* If we've gotten to this point, then the only
|
* 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;
|
blk_t block, b;
|
||||||
int i,j;
|
int i,j;
|
||||||
|
struct problem_context pctx;
|
||||||
|
|
||||||
|
clear_problem_context(&pctx);
|
||||||
|
|
||||||
block = fs->super->s_first_data_block;
|
block = fs->super->s_first_data_block;
|
||||||
for (i = 0; i < fs->group_desc_count; i++) {
|
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
|
* Mark block used for the block bitmap
|
||||||
*/
|
*/
|
||||||
if (fs->group_desc[i].bg_block_bitmap) {
|
if (fs->group_desc[i].bg_block_bitmap) {
|
||||||
if (ext2fs_test_block_bitmap(block_found_map,
|
if (ext2fs_test_block_bitmap(block_found_map,
|
||||||
fs->group_desc[i].bg_block_bitmap)) {
|
fs->group_desc[i].bg_block_bitmap)) {
|
||||||
printf("Group %i's block bitmap at %u "
|
pctx.blk = fs->group_desc[i].bg_block_bitmap;
|
||||||
"conflicts with some other fs block.\n",
|
if (fix_problem(fs, PR_1_BB_CONFLICT, &pctx)) {
|
||||||
i, fs->group_desc[i].bg_block_bitmap);
|
|
||||||
preenhalt(fs);
|
|
||||||
if (ask("Relocate", 1)) {
|
|
||||||
invalid_block_bitmap[i]++;
|
invalid_block_bitmap[i]++;
|
||||||
invalid_bitmaps++;
|
invalid_bitmaps++;
|
||||||
} else {
|
|
||||||
ext2fs_unmark_valid(fs);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ext2fs_mark_block_bitmap(block_found_map,
|
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 (fs->group_desc[i].bg_inode_bitmap) {
|
||||||
if (ext2fs_test_block_bitmap(block_found_map,
|
if (ext2fs_test_block_bitmap(block_found_map,
|
||||||
fs->group_desc[i].bg_inode_bitmap)) {
|
fs->group_desc[i].bg_inode_bitmap)) {
|
||||||
printf("Group %i's inode bitmap at %u "
|
pctx.blk = fs->group_desc[i].bg_inode_bitmap;
|
||||||
"conflicts with some other fs block.\n",
|
if (fix_problem(fs, PR_1_IB_CONFLICT, &pctx)) {
|
||||||
i, fs->group_desc[i].bg_inode_bitmap);
|
|
||||||
preenhalt(fs);
|
|
||||||
if (ask("Relocate", 1)) {
|
|
||||||
invalid_inode_bitmap[i]++;
|
invalid_inode_bitmap[i]++;
|
||||||
invalid_bitmaps++;
|
invalid_bitmaps++;
|
||||||
} else {
|
}
|
||||||
ext2fs_unmark_valid(fs);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
ext2fs_mark_block_bitmap(block_found_map,
|
ext2fs_mark_block_bitmap(block_found_map,
|
||||||
fs->group_desc[i].bg_inode_bitmap);
|
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
|
* Mark this group's copy of the superblock
|
||||||
*/
|
*/
|
||||||
|
|
185
e2fsck/pass1b.c
185
e2fsck/pass1b.c
|
@ -18,8 +18,12 @@
|
||||||
* (so that the file gets a fresh copy of the duplicated blocks) or
|
* (so that the file gets a fresh copy of the duplicated blocks) or
|
||||||
* simply to delete the file.
|
* simply to delete the file.
|
||||||
*
|
*
|
||||||
* Copyright (C) 1993, 1994 Theodore Ts'o. This file may be
|
* Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
|
||||||
* redistributed under the terms of the GNU Public License.
|
*
|
||||||
|
* %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 <et/com_err.h>
|
||||||
#include "e2fsck.h"
|
#include "e2fsck.h"
|
||||||
|
|
||||||
|
#include "problem.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is structure is allocated for each time that a block is
|
* 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
|
* claimed by more than one file. So if a particular block is claimed
|
||||||
|
@ -75,16 +81,12 @@ struct dup_block {
|
||||||
* of multiply-claimed blocks.
|
* of multiply-claimed blocks.
|
||||||
*/
|
*/
|
||||||
struct dup_inode {
|
struct dup_inode {
|
||||||
ino_t ino;
|
ino_t ino, dir;
|
||||||
time_t mtime;
|
int num_dupblocks;
|
||||||
char *pathname;
|
struct ext2_inode inode;
|
||||||
int num_dupblocks;
|
|
||||||
int flags;
|
|
||||||
struct dup_inode *next;
|
struct dup_inode *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DUP_INODE_DONT_FREE_PATHNAME 0x1
|
|
||||||
|
|
||||||
static int process_pass1b_block(ext2_filsys fs, blk_t *blocknr,
|
static int process_pass1b_block(ext2_filsys fs, blk_t *blocknr,
|
||||||
int blockcnt, void *private);
|
int blockcnt, void *private);
|
||||||
static void delete_file(ext2_filsys fs, struct dup_inode *dp,
|
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
|
* Time to free all of the accumulated data structures that we
|
||||||
* don't need anymore.
|
* 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;
|
ext2fs_free_block_bitmap(block_dup_map); block_dup_map = 0;
|
||||||
for (p = dup_blk; p; p = next_p) {
|
for (p = dup_blk; p; p = next_p) {
|
||||||
next_p = p->next_block;
|
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) {
|
for (r = dup_ino; r; r = next_r) {
|
||||||
next_r = r->next;
|
next_r = r->next;
|
||||||
if (r->pathname && !(r->flags & DUP_INODE_DONT_FREE_PATHNAME))
|
|
||||||
free(r->pathname);
|
|
||||||
free(r);
|
free(r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,7 +176,7 @@ void pass1b(ext2_filsys fs, char *block_buf)
|
||||||
stashed_ino = ino;
|
stashed_ino = ino;
|
||||||
if ((ino != EXT2_BAD_INO) &&
|
if ((ino != EXT2_BAD_INO) &&
|
||||||
(!ext2fs_test_inode_bitmap(inode_used_map, ino) ||
|
(!ext2fs_test_inode_bitmap(inode_used_map, ino) ||
|
||||||
!inode_has_valid_blocks(&inode)))
|
!ext2fs_inode_has_valid_blocks(&inode)))
|
||||||
goto next;
|
goto next;
|
||||||
|
|
||||||
pb.ino = ino;
|
pb.ino = ino;
|
||||||
|
@ -189,10 +189,9 @@ void pass1b(ext2_filsys fs, char *block_buf)
|
||||||
dp = allocate_memory(sizeof(struct dup_inode),
|
dp = allocate_memory(sizeof(struct dup_inode),
|
||||||
"duplicate inode record");
|
"duplicate inode record");
|
||||||
dp->ino = ino;
|
dp->ino = ino;
|
||||||
dp->mtime = inode.i_mtime;
|
dp->dir = 0;
|
||||||
|
dp->inode = inode;
|
||||||
dp->num_dupblocks = pb.dup_blocks;
|
dp->num_dupblocks = pb.dup_blocks;
|
||||||
dp->pathname = 0;
|
|
||||||
dp->flags = 0;
|
|
||||||
dp->next = dup_ino;
|
dp->next = dup_ino;
|
||||||
dup_ino = dp;
|
dup_ino = dp;
|
||||||
if (ino != EXT2_BAD_INO)
|
if (ino != EXT2_BAD_INO)
|
||||||
|
@ -270,113 +269,71 @@ int process_pass1b_block(ext2_filsys fs,
|
||||||
return 0;
|
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
|
* Pass 1c: Scan directories for inodes with duplicate blocks. This
|
||||||
* is used so that we can print pathnames when prompting the user for
|
* is used so that we can print pathnames when prompting the user for
|
||||||
* what to do.
|
* what to do.
|
||||||
*/
|
*/
|
||||||
struct process_dir_struct {
|
struct search_dir_struct {
|
||||||
ext2_filsys fs;
|
|
||||||
ino_t dir_ino;
|
|
||||||
int count;
|
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)
|
void pass1c(ext2_filsys fs, char *block_buf)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
struct dup_inode *p;
|
struct dup_inode *p;
|
||||||
errcode_t retval;
|
|
||||||
char buf[80];
|
|
||||||
int inodes_left = dup_inode_count;
|
int inodes_left = dup_inode_count;
|
||||||
int offset, entry;
|
struct search_dir_struct sd;
|
||||||
struct ext2_dir_entry *dirent;
|
|
||||||
|
|
||||||
printf("Pass 1C: Scan directories for inodes with dup blocks.\n");
|
printf("Pass 1C: Scan directories for inodes with dup blocks.\n");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First check to see if any of the inodes with dup blocks is
|
* First check to see if any of the inodes with dup blocks is
|
||||||
* the bad block inode or the root inode; handle them as
|
* a special inode. (Note that the bad block inode isn't
|
||||||
* special cases.
|
* counted.)
|
||||||
*/
|
*/
|
||||||
for (p = dup_ino; p; p = p->next) {
|
for (p = dup_ino; p; p = p->next) {
|
||||||
if (p->ino < num_special_inodes) {
|
if ((p->ino < EXT2_FIRST_INODE(fs->super)) &&
|
||||||
p->pathname = special_inode_name[p->ino];
|
(p->ino != EXT2_BAD_INO))
|
||||||
p->flags |= DUP_INODE_DONT_FREE_PATHNAME;
|
|
||||||
inodes_left--;
|
inodes_left--;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Search through all directories to translate inodes to names
|
* Search through all directories to translate inodes to names
|
||||||
* (by searching for the containing directory for that inode.)
|
* (by searching for the containing directory for that inode.)
|
||||||
*/
|
*/
|
||||||
for (i=0; inodes_left && i < dir_block_count; i++) {
|
sd.count = inodes_left;
|
||||||
retval = ext2fs_read_dir_block(fs, dir_blocks[i].blk,
|
sd.first_inode = EXT2_FIRST_INODE(fs->super);
|
||||||
block_buf);
|
ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
|
||||||
entry = offset = 0;
|
search_dirent_proc, &sd);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pass1d(ext2_filsys fs, char *block_buf)
|
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 shared_len;
|
||||||
int i;
|
int i;
|
||||||
errcode_t retval;
|
errcode_t retval;
|
||||||
char *time_str;
|
|
||||||
int file_ok;
|
int file_ok;
|
||||||
|
struct problem_context pctx;
|
||||||
|
|
||||||
printf("Pass 1D: Reconciling duplicate blocks\n");
|
printf("Pass 1D: Reconciling duplicate blocks\n");
|
||||||
read_bitmaps(fs);
|
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",
|
* Report the inode that we are working on
|
||||||
p->pathname, p->ino, time_str);
|
*/
|
||||||
printf(" has %d duplicate blocks, shared with %d file%s:\n",
|
clear_problem_context(&pctx);
|
||||||
p->num_dupblocks, shared_len,
|
pctx.inode = &p->inode;
|
||||||
(shared_len>1) ? "s" : "");
|
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 (i = 0; i < shared_len; i++) {
|
||||||
for (s = dup_ino; s; s = s->next)
|
for (s = dup_ino; s; s = s->next)
|
||||||
if (s->ino == shared[i])
|
if (s->ino == shared[i])
|
||||||
break;
|
break;
|
||||||
if (!s)
|
if (!s)
|
||||||
continue;
|
continue;
|
||||||
time_str = ctime(&s->mtime);
|
/*
|
||||||
time_str[24] = 0;
|
* Report the inode that we are sharing with
|
||||||
printf("\t%s (inode #%lu, mod time %s)\n",
|
*/
|
||||||
s->pathname, s->ino, time_str);
|
pctx.inode = &s->inode;
|
||||||
|
pctx.ino = s->ino;
|
||||||
|
pctx.dir = s->dir;
|
||||||
|
fix_problem(fs, PR_1B_DUP_FILE_LIST, &pctx);
|
||||||
}
|
}
|
||||||
if (file_ok) {
|
if (file_ok) {
|
||||||
printf("Duplicated blocks already reassigned or cloned.\n\n");
|
printf("Duplicated blocks already reassigned or cloned.\n\n");
|
||||||
|
|
458
e2fsck/pass2.c
458
e2fsck/pass2.c
|
@ -1,8 +1,12 @@
|
||||||
/*
|
/*
|
||||||
* pass2.c --- check directory structure
|
* pass2.c --- check directory structure
|
||||||
*
|
*
|
||||||
* Copyright (C) 1993, 1994 Theodore Ts'o. This file may be
|
* Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o
|
||||||
* redistributed under the terms of the GNU Public License.
|
*
|
||||||
|
* %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
|
* Pass 2 of e2fsck iterates through all active directory inodes, and
|
||||||
* applies to following tests to each directory entry in the directory
|
* applies to following tests to each directory entry in the directory
|
||||||
|
@ -39,32 +43,41 @@
|
||||||
#include "et/com_err.h"
|
#include "et/com_err.h"
|
||||||
|
|
||||||
#include "e2fsck.h"
|
#include "e2fsck.h"
|
||||||
|
#include "problem.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Keeps track of how many times an inode is referenced.
|
* 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,
|
static void deallocate_inode(ext2_filsys fs, ino_t ino,
|
||||||
char* block_buf);
|
char* block_buf);
|
||||||
static int process_bad_inode(ext2_filsys fs, ino_t dir, ino_t ino);
|
static int process_bad_inode(ext2_filsys fs, ino_t dir, ino_t ino);
|
||||||
static int check_dir_block(ext2_filsys fs,
|
static int check_dir_block(ext2_filsys fs,
|
||||||
struct dir_block_struct *dir_blocks_info,
|
struct ext2_db_entry *dir_blocks_info,
|
||||||
char *buf);
|
void *private);
|
||||||
static int allocate_dir_block(ext2_filsys fs,
|
static int allocate_dir_block(ext2_filsys fs,
|
||||||
struct dir_block_struct *dir_blocks_info,
|
struct ext2_db_entry *dir_blocks_info,
|
||||||
char *buf);
|
char *buf, struct problem_context *pctx);
|
||||||
static int update_dir_block(ext2_filsys fs,
|
static int update_dir_block(ext2_filsys fs,
|
||||||
blk_t *block_nr,
|
blk_t *block_nr,
|
||||||
int blockcnt,
|
int blockcnt,
|
||||||
void *private);
|
void *private);
|
||||||
|
|
||||||
|
struct check_dir_struct {
|
||||||
|
char *buf;
|
||||||
|
struct problem_context pctx;
|
||||||
|
};
|
||||||
|
|
||||||
void pass2(ext2_filsys fs)
|
void pass2(ext2_filsys fs)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
char *buf;
|
char *buf;
|
||||||
struct resource_track rtrack;
|
struct resource_track rtrack;
|
||||||
|
struct dir_info *dir;
|
||||||
|
errcode_t retval;
|
||||||
|
ino_t size;
|
||||||
|
struct check_dir_struct cd;
|
||||||
|
|
||||||
init_resource_track(&rtrack);
|
init_resource_track(&rtrack);
|
||||||
|
|
||||||
#ifdef MTRACE
|
#ifdef MTRACE
|
||||||
|
@ -73,17 +86,33 @@ void pass2(ext2_filsys fs)
|
||||||
|
|
||||||
if (!preen)
|
if (!preen)
|
||||||
printf("Pass 2: Checking directory structure\n");
|
printf("Pass 2: Checking directory structure\n");
|
||||||
inode_count = allocate_memory((fs->super->s_inodes_count + 1) *
|
size = ext2fs_get_icount_size(inode_link_info) + 10;
|
||||||
sizeof(unsigned short),
|
retval = ext2fs_create_icount(fs, EXT2_ICOUNT_OPT_INCREMENT,
|
||||||
"buffer for inode count");
|
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");
|
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(buf);
|
||||||
free(dir_blocks);
|
ext2fs_free_dblist(fs->dblist);
|
||||||
|
|
||||||
if (inode_bad_map) {
|
if (inode_bad_map) {
|
||||||
ext2fs_free_inode_bitmap(inode_bad_map);
|
ext2fs_free_inode_bitmap(inode_bad_map);
|
||||||
inode_bad_map = 0;
|
inode_bad_map = 0;
|
||||||
|
@ -100,54 +129,39 @@ void pass2(ext2_filsys fs)
|
||||||
*/
|
*/
|
||||||
static int check_dot(ext2_filsys fs,
|
static int check_dot(ext2_filsys fs,
|
||||||
struct ext2_dir_entry *dirent,
|
struct ext2_dir_entry *dirent,
|
||||||
ino_t ino)
|
ino_t ino, struct problem_context *pctx)
|
||||||
{
|
{
|
||||||
struct ext2_dir_entry *nextdir;
|
struct ext2_dir_entry *nextdir;
|
||||||
int status = 0;
|
int status = 0;
|
||||||
int created = 0;
|
int created = 0;
|
||||||
int new_len;
|
int new_len;
|
||||||
const char *question = 0;
|
int problem = 0;
|
||||||
|
|
||||||
if (!dirent->inode) {
|
if (!dirent->inode)
|
||||||
printf("Missing '.' in directory inode %lu.\n", ino);
|
problem = PR_2_MISSING_DOT;
|
||||||
question = "Fix";
|
else if ((dirent->name_len != 1) ||
|
||||||
} else if ((dirent->name_len != 1) ||
|
(dirent->name[0] != '.'))
|
||||||
strncmp(dirent->name, ".", dirent->name_len)) {
|
problem = PR_2_1ST_NOT_DOT;
|
||||||
char *name = malloc(dirent->name_len + 1);
|
else if (dirent->name[1] != '\0')
|
||||||
if (!name)
|
problem = PR_2_DOT_NULL_TERM;
|
||||||
fatal_error("Couldn't allocate . name");
|
|
||||||
strncpy(name, dirent->name, dirent->name_len);
|
if (problem) {
|
||||||
name[dirent->name_len] = '\0';
|
if (fix_problem(fs, problem, pctx)) {
|
||||||
printf("First entry in directory inode %lu contains '%s' "
|
if (dirent->rec_len < 12)
|
||||||
"(inode=%u)\n", ino, name, dirent->inode);
|
dirent->rec_len = 12;
|
||||||
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)) {
|
|
||||||
dirent->inode = ino;
|
dirent->inode = ino;
|
||||||
dirent->name_len = 1;
|
dirent->name_len = 1;
|
||||||
dirent->name[0] = '.';
|
dirent->name[0] = '.';
|
||||||
|
dirent->name[1] = '\0';
|
||||||
status = 1;
|
status = 1;
|
||||||
created = 1;
|
created = 1;
|
||||||
} else {
|
|
||||||
ext2fs_unmark_valid(fs);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dirent->inode != ino) {
|
if (dirent->inode != ino) {
|
||||||
printf("Bad inode number for '.' in directory inode %lu.\n",
|
if (fix_problem(fs, PR_2_BAD_INODE_DOT, pctx)) {
|
||||||
ino);
|
|
||||||
preenhalt(fs);
|
|
||||||
if (ask("Fix", 1)) {
|
|
||||||
dirent->inode = ino;
|
dirent->inode = ino;
|
||||||
status = 1;
|
status = 1;
|
||||||
} else
|
}
|
||||||
ext2fs_unmark_valid(fs);
|
|
||||||
}
|
}
|
||||||
if (dirent->rec_len > 12) {
|
if (dirent->rec_len > 12) {
|
||||||
new_len = 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,
|
static int check_dotdot(ext2_filsys fs,
|
||||||
struct ext2_dir_entry *dirent,
|
struct ext2_dir_entry *dirent,
|
||||||
struct dir_info *dir)
|
struct dir_info *dir, struct problem_context *pctx)
|
||||||
{
|
{
|
||||||
ino_t ino = dir->ino;
|
int problem = 0;
|
||||||
const char *question = 0;
|
|
||||||
|
|
||||||
if (!dirent->inode) {
|
if (!dirent->inode)
|
||||||
printf("Missing '..' in directory inode %lu.\n", ino);
|
problem = PR_2_MISSING_DOT_DOT;
|
||||||
question = "Fix";
|
else if ((dirent->name_len != 2) ||
|
||||||
} else if ((dirent->name_len != 2) ||
|
(dirent->name[0] != '.') ||
|
||||||
strncmp(dirent->name, "..", dirent->name_len)) {
|
(dirent->name[1] != '.'))
|
||||||
char *name = malloc(dirent->name_len + 1);
|
problem = PR_2_2ND_NOT_DOT_DOT;
|
||||||
if (!name)
|
else if (dirent->name[2] != '\0')
|
||||||
fatal_error("Couldn't allocate bad .. name");
|
problem = PR_2_DOT_DOT_NULL_TERM;
|
||||||
strncpy(name, dirent->name, dirent->name_len);
|
|
||||||
name[dirent->name_len] = '\0';
|
if (problem) {
|
||||||
printf("Second entry in directory inode %lu contains '%s' "
|
if (fix_problem(fs, problem, pctx)) {
|
||||||
"(inode=%u)\n", ino, name, dirent->inode);
|
if (dirent->rec_len < 12)
|
||||||
printf("instead of '..'.\n");
|
dirent->rec_len = 12;
|
||||||
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)) {
|
|
||||||
/*
|
/*
|
||||||
* Note: we don't have the parent inode just
|
* Note: we don't have the parent inode just
|
||||||
* yet, so we will fill it in with the root
|
* 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_len = 2;
|
||||||
dirent->name[0] = '.';
|
dirent->name[0] = '.';
|
||||||
dirent->name[1] = '.';
|
dirent->name[1] = '.';
|
||||||
|
dirent->name[2] = '\0';
|
||||||
return 1;
|
return 1;
|
||||||
} else
|
}
|
||||||
ext2fs_unmark_valid(fs);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
dir->dotdot = dirent->inode;
|
dir->dotdot = dirent->inode;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char unknown_pathname[] = "???";
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check to make sure a directory entry doesn't contain any illegal
|
* Check to make sure a directory entry doesn't contain any illegal
|
||||||
* characters.
|
* characters.
|
||||||
*/
|
*/
|
||||||
static int check_name(ext2_filsys fs,
|
static int check_name(ext2_filsys fs,
|
||||||
struct ext2_dir_entry *dirent,
|
struct ext2_dir_entry *dirent,
|
||||||
ino_t dir_ino,
|
ino_t dir_ino, struct problem_context *pctx)
|
||||||
char *name)
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int fixup = -1;
|
int fixup = -1;
|
||||||
char *pathname;
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
errcode_t retval;
|
|
||||||
|
|
||||||
for ( i = 0; i < dirent->name_len; i++) {
|
for ( i = 0; i < dirent->name_len; i++) {
|
||||||
if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
|
if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
|
||||||
if (fixup < 0) {
|
if (fixup < 0) {
|
||||||
retval = ext2fs_get_pathname(fs, dir_ino,
|
fixup = fix_problem(fs, PR_2_BAD_NAME, pctx);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
if (fixup) {
|
if (fixup) {
|
||||||
dirent->name[i] = '.';
|
dirent->name[i] = '.';
|
||||||
ret = 1;
|
ret = 1;
|
||||||
} else
|
}
|
||||||
ext2fs_unmark_valid(fs);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int check_dir_block(ext2_filsys fs,
|
static int check_dir_block(ext2_filsys fs,
|
||||||
struct dir_block_struct *db,
|
struct ext2_db_entry *db,
|
||||||
char *buf)
|
void *private)
|
||||||
{
|
{
|
||||||
struct dir_info *subdir, *dir;
|
struct dir_info *subdir, *dir;
|
||||||
struct ext2_dir_entry *dirent;
|
struct ext2_dir_entry *dirent;
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
int dir_modified = 0;
|
int dir_modified = 0;
|
||||||
errcode_t retval;
|
errcode_t retval;
|
||||||
char *path1, *path2;
|
int dot_state;
|
||||||
int dot_state, name_len;
|
|
||||||
blk_t block_nr = db->blk;
|
blk_t block_nr = db->blk;
|
||||||
ino_t ino = db->ino;
|
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
|
* Make sure the inode is still in use (could have been
|
||||||
* deleted in the duplicate/bad blocks pass.
|
* 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)))
|
if (!(ext2fs_test_inode_bitmap(inode_used_map, ino)))
|
||||||
return 0;
|
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 (db->blk == 0) {
|
||||||
if (allocate_dir_block(fs, db, buf))
|
if (allocate_dir_block(fs, db, buf, &cd->pctx))
|
||||||
return 0;
|
return 0;
|
||||||
block_nr = db->blk;
|
block_nr = db->blk;
|
||||||
}
|
}
|
||||||
|
@ -310,40 +305,30 @@ static int check_dir_block(ext2_filsys fs,
|
||||||
do {
|
do {
|
||||||
dot_state++;
|
dot_state++;
|
||||||
dirent = (struct ext2_dir_entry *) (buf + offset);
|
dirent = (struct ext2_dir_entry *) (buf + offset);
|
||||||
|
cd->pctx.dirent = dirent;
|
||||||
|
cd->pctx.num = offset;
|
||||||
if (((offset + dirent->rec_len) > fs->blocksize) ||
|
if (((offset + dirent->rec_len) > fs->blocksize) ||
|
||||||
(dirent->rec_len < 8) ||
|
(dirent->rec_len < 8) ||
|
||||||
|
((dirent->rec_len % 4) != 0) ||
|
||||||
((dirent->name_len+8) > dirent->rec_len)) {
|
((dirent->name_len+8) > dirent->rec_len)) {
|
||||||
printf("Directory inode %lu, block %d, offset %d: directory corrupted\n",
|
if (fix_problem(fs, PR_2_DIR_CORRUPTED, &cd->pctx)) {
|
||||||
ino, db->blockcnt, offset);
|
|
||||||
preenhalt(fs);
|
|
||||||
if (ask("Salvage", 1)) {
|
|
||||||
dirent->rec_len = fs->blocksize - offset;
|
dirent->rec_len = fs->blocksize - offset;
|
||||||
dirent->name_len = 0;
|
dirent->name_len = 0;
|
||||||
dirent->inode = 0;
|
dirent->inode = 0;
|
||||||
dir_modified++;
|
dir_modified++;
|
||||||
} else {
|
} else
|
||||||
ext2fs_unmark_valid(fs);
|
|
||||||
return DIRENT_ABORT;
|
return DIRENT_ABORT;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
name_len = dirent->name_len;
|
|
||||||
if (dirent->name_len > EXT2_NAME_LEN) {
|
if (dirent->name_len > EXT2_NAME_LEN) {
|
||||||
printf("Directory inode %lu, block %d, offset %d: filename too long\n",
|
if (fix_problem(fs, PR_2_FILENAME_LONG, &cd->pctx)) {
|
||||||
ino, db->blockcnt, offset);
|
|
||||||
preenhalt(fs);
|
|
||||||
if (ask("Truncate filename", 1)) {
|
|
||||||
dirent->name_len = EXT2_NAME_LEN;
|
dirent->name_len = EXT2_NAME_LEN;
|
||||||
dir_modified++;
|
dir_modified++;
|
||||||
}
|
}
|
||||||
name_len = EXT2_NAME_LEN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy(name, dirent->name, name_len);
|
|
||||||
name[name_len] = '\0';
|
|
||||||
|
|
||||||
if (dot_state == 1) {
|
if (dot_state == 1) {
|
||||||
if (check_dot(fs, dirent, ino))
|
if (check_dot(fs, dirent, ino, &cd->pctx))
|
||||||
dir_modified++;
|
dir_modified++;
|
||||||
} else if (dot_state == 2) {
|
} else if (dot_state == 2) {
|
||||||
dir = get_dir_info(ino);
|
dir = get_dir_info(ino);
|
||||||
|
@ -352,30 +337,19 @@ static int check_dir_block(ext2_filsys fs,
|
||||||
ino);
|
ino);
|
||||||
fatal_error(0);
|
fatal_error(0);
|
||||||
}
|
}
|
||||||
if (check_dotdot(fs, dirent, dir))
|
if (check_dotdot(fs, dirent, dir, &cd->pctx))
|
||||||
dir_modified++;
|
dir_modified++;
|
||||||
} else if (dirent->inode == ino) {
|
} else if (dirent->inode == ino) {
|
||||||
retval = ext2fs_get_pathname(fs, ino, 0, &path1);
|
if (fix_problem(fs, PR_2_LINK_DOT, &cd->pctx)) {
|
||||||
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)) {
|
|
||||||
dirent->inode = 0;
|
dirent->inode = 0;
|
||||||
dir_modified++;
|
dir_modified++;
|
||||||
|
goto next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!dirent->inode)
|
if (!dirent->inode)
|
||||||
goto next;
|
goto next;
|
||||||
|
|
||||||
#if 0
|
if (check_name(fs, dirent, ino, &cd->pctx))
|
||||||
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))
|
|
||||||
dir_modified++;
|
dir_modified++;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -384,40 +358,36 @@ static int check_dir_block(ext2_filsys fs,
|
||||||
if (((dirent->inode != EXT2_ROOT_INO) &&
|
if (((dirent->inode != EXT2_ROOT_INO) &&
|
||||||
(dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
|
(dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
|
||||||
(dirent->inode > fs->super->s_inodes_count)) {
|
(dirent->inode > fs->super->s_inodes_count)) {
|
||||||
retval = ext2fs_get_pathname(fs, ino, 0, &path1);
|
if (fix_problem(fs, PR_2_BAD_INO, &cd->pctx)) {
|
||||||
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)) {
|
|
||||||
dirent->inode = 0;
|
dirent->inode = 0;
|
||||||
dir_modified++;
|
dir_modified++;
|
||||||
goto next;
|
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,
|
if (!(ext2fs_test_inode_bitmap(inode_used_map,
|
||||||
dirent->inode))) {
|
dirent->inode))) {
|
||||||
retval = ext2fs_get_pathname(fs, ino, 0, &path1);
|
if (fix_problem(fs, PR_2_UNUSED_INODE, &cd->pctx)) {
|
||||||
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)) {
|
|
||||||
dirent->inode = 0;
|
dirent->inode = 0;
|
||||||
dir_modified++;
|
dir_modified++;
|
||||||
goto next;
|
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
|
* If this is a directory, then mark its parent in its
|
||||||
* dir_info structure. If the parent field is already
|
* dir_info structure. If the parent field is already
|
||||||
|
@ -453,34 +437,20 @@ static int check_dir_block(ext2_filsys fs,
|
||||||
fatal_error(0);
|
fatal_error(0);
|
||||||
}
|
}
|
||||||
if (subdir->parent) {
|
if (subdir->parent) {
|
||||||
retval = ext2fs_get_pathname(fs, ino,
|
cd->pctx.ino2 = subdir->parent;
|
||||||
0, &path1);
|
if (fix_problem(fs, PR_2_LINK_DIR,
|
||||||
if (retval)
|
&cd->pctx)) {
|
||||||
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)) {
|
|
||||||
dirent->inode = 0;
|
dirent->inode = 0;
|
||||||
dir_modified++;
|
dir_modified++;
|
||||||
goto next;
|
goto next;
|
||||||
} else
|
}
|
||||||
ext2fs_unmark_valid(fs);
|
cd->pctx.ino2 = 0;
|
||||||
}
|
} else
|
||||||
subdir->parent = ino;
|
subdir->parent = ino;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inode_count[dirent->inode]++ > 0)
|
ext2fs_icount_increment(inode_count, dirent->inode, &links);
|
||||||
|
if (links > 1)
|
||||||
fs_links_count++;
|
fs_links_count++;
|
||||||
fs_total_count++;
|
fs_total_count++;
|
||||||
next:
|
next:
|
||||||
|
@ -530,7 +500,7 @@ static void deallocate_inode(ext2_filsys fs, ino_t ino,
|
||||||
errcode_t retval;
|
errcode_t retval;
|
||||||
struct ext2_inode inode;
|
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");
|
e2fsck_read_inode(fs, ino, &inode, "deallocate_inode");
|
||||||
inode.i_links_count = 0;
|
inode.i_links_count = 0;
|
||||||
inode.i_dtime = time(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_unmark_inode_bitmap(fs->inode_map, ino);
|
||||||
ext2fs_mark_ib_dirty(fs);
|
ext2fs_mark_ib_dirty(fs);
|
||||||
|
|
||||||
if (!inode_has_valid_blocks(&inode))
|
if (!ext2fs_inode_has_valid_blocks(&inode))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ext2fs_mark_bb_dirty(fs);
|
ext2fs_mark_bb_dirty(fs);
|
||||||
|
@ -559,83 +529,34 @@ static void deallocate_inode(ext2_filsys fs, ino_t ino,
|
||||||
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)
|
static int process_bad_inode(ext2_filsys fs, ino_t dir, ino_t ino)
|
||||||
{
|
{
|
||||||
struct ext2_inode inode;
|
struct ext2_inode inode;
|
||||||
errcode_t retval;
|
|
||||||
int inode_modified = 0;
|
int inode_modified = 0;
|
||||||
char *pathname;
|
|
||||||
unsigned char *frag, *fsize;
|
unsigned char *frag, *fsize;
|
||||||
|
struct problem_context pctx;
|
||||||
|
|
||||||
e2fsck_read_inode(fs, ino, &inode, "process_bad_inode");
|
e2fsck_read_inode(fs, ino, &inode, "process_bad_inode");
|
||||||
retval = ext2fs_get_pathname(fs, dir, ino, &pathname);
|
|
||||||
if (retval) {
|
clear_problem_context(&pctx);
|
||||||
com_err("process_bad_inode", retval,
|
pctx.ino = ino;
|
||||||
"while getting pathname for inode %d",
|
pctx.dir = dir;
|
||||||
ino);
|
pctx.inode = &inode;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
|
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_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
|
||||||
!LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
|
!LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
|
||||||
!(LINUX_S_ISSOCK(inode.i_mode))) {
|
!(LINUX_S_ISSOCK(inode.i_mode))) {
|
||||||
printf("Inode %lu (%s) has a bad mode (0%o).\n",
|
if (fix_problem(fs, PR_2_BAD_MODE, &pctx)) {
|
||||||
ino, pathname, inode.i_mode);
|
|
||||||
preenhalt(fs);
|
|
||||||
if (ask("Clear", 1)) {
|
|
||||||
deallocate_inode(fs, ino, 0);
|
deallocate_inode(fs, ino, 0);
|
||||||
free(pathname);
|
|
||||||
return 1;
|
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) {
|
switch (fs->super->s_creator_os) {
|
||||||
case EXT2_OS_LINUX:
|
case EXT2_OS_LINUX:
|
||||||
|
@ -653,18 +574,33 @@ static int process_bad_inode(ext2_filsys fs, ino_t dir, ino_t ino)
|
||||||
default:
|
default:
|
||||||
frag = fsize = 0;
|
frag = fsize = 0;
|
||||||
}
|
}
|
||||||
if (frag)
|
if (frag && *frag) {
|
||||||
check_for_zero_u8(fs, ino, pathname, "i_frag", frag,
|
pctx.num = *frag;
|
||||||
&inode_modified);
|
if (fix_problem(fs, PR_2_FRAG_ZERO, &pctx)) {
|
||||||
if (fsize)
|
*frag = 0;
|
||||||
check_for_zero_u8(fs, ino, pathname, "i_fsize", fsize,
|
inode_modified++;
|
||||||
&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,
|
if (inode.i_file_acl &&
|
||||||
&inode_modified);
|
fix_problem(fs, PR_2_FILE_ACL_ZERO, &pctx)) {
|
||||||
check_for_zero_u32(fs, ino, pathname, "i_dir_acl", &inode.i_dir_acl,
|
inode.i_file_acl = 0;
|
||||||
&inode_modified);
|
inode_modified++;
|
||||||
free(pathname);
|
}
|
||||||
|
if (inode.i_dir_acl &&
|
||||||
|
fix_problem(fs, PR_2_DIR_ACL_ZERO, &pctx)) {
|
||||||
|
inode.i_dir_acl = 0;
|
||||||
|
inode_modified++;
|
||||||
|
}
|
||||||
if (inode_modified)
|
if (inode_modified)
|
||||||
e2fsck_write_inode(fs, ino, &inode, "process_bad_inode");
|
e2fsck_write_inode(fs, ino, &inode, "process_bad_inode");
|
||||||
return 0;
|
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.
|
* that was zeroed out and now needs to be replaced.
|
||||||
*/
|
*/
|
||||||
static int allocate_dir_block(ext2_filsys fs,
|
static int allocate_dir_block(ext2_filsys fs,
|
||||||
struct dir_block_struct *db,
|
struct ext2_db_entry *db,
|
||||||
char *buf)
|
char *buf, struct problem_context *pctx)
|
||||||
{
|
{
|
||||||
blk_t blk;
|
blk_t blk;
|
||||||
char *block;
|
char *block;
|
||||||
struct ext2_inode inode;
|
struct ext2_inode inode;
|
||||||
errcode_t retval;
|
errcode_t retval;
|
||||||
|
|
||||||
printf("Directory inode %lu has a hole at block #%d\n",
|
if (fix_problem(fs, PR_2_DIRECTORY_HOLE, pctx) == 0)
|
||||||
db->ino, db->blockcnt);
|
|
||||||
if (ask("Allocate block", 1) == 0)
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -765,7 +699,7 @@ static int update_dir_block(ext2_filsys fs,
|
||||||
int blockcnt,
|
int blockcnt,
|
||||||
void *private)
|
void *private)
|
||||||
{
|
{
|
||||||
struct dir_block_struct *db = private;
|
struct ext2_db_entry *db = private;
|
||||||
|
|
||||||
if (db->blockcnt == blockcnt) {
|
if (db->blockcnt == blockcnt) {
|
||||||
*block_nr = db->blk;
|
*block_nr = db->blk;
|
||||||
|
|
142
e2fsck/pass3.c
142
e2fsck/pass3.c
|
@ -1,8 +1,12 @@
|
||||||
/*
|
/*
|
||||||
* pass3.c -- pass #3 of e2fsck: Check for directory connectivity
|
* pass3.c -- pass #3 of e2fsck: Check for directory connectivity
|
||||||
*
|
*
|
||||||
* Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
|
* Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
|
||||||
* under the terms of the GNU Public License.
|
*
|
||||||
|
* %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
|
* Pass #3 assures that all directories are connected to the
|
||||||
* filesystem tree, using the following algorithm:
|
* filesystem tree, using the following algorithm:
|
||||||
|
@ -36,9 +40,11 @@
|
||||||
#include "et/com_err.h"
|
#include "et/com_err.h"
|
||||||
|
|
||||||
#include "e2fsck.h"
|
#include "e2fsck.h"
|
||||||
|
#include "problem.h"
|
||||||
|
|
||||||
static void check_root(ext2_filsys fs, ino_t root_ino);
|
static void check_root(ext2_filsys fs);
|
||||||
static void check_directory(ext2_filsys fs, ino_t dir);
|
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 ino_t get_lost_and_found(ext2_filsys fs);
|
||||||
static void fix_dotdot(ext2_filsys fs, struct dir_info *dir, ino_t parent);
|
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);
|
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;
|
int i;
|
||||||
errcode_t retval;
|
errcode_t retval;
|
||||||
struct resource_track rtrack;
|
struct resource_track rtrack;
|
||||||
|
struct problem_context pctx;
|
||||||
|
struct dir_info *dir;
|
||||||
|
|
||||||
init_resource_track(&rtrack);
|
init_resource_track(&rtrack);
|
||||||
|
|
||||||
|
@ -88,14 +96,16 @@ void pass3(ext2_filsys fs)
|
||||||
print_resource_track(&global_rtrack);
|
print_resource_track(&global_rtrack);
|
||||||
}
|
}
|
||||||
|
|
||||||
check_root(fs, EXT2_ROOT_INO);
|
check_root(fs);
|
||||||
ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
|
ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
|
||||||
|
|
||||||
for (i=1; i <= fs->super->s_inodes_count; i++) {
|
clear_problem_context(&pctx);
|
||||||
if (ext2fs_test_inode_bitmap(inode_dir_map, i))
|
for (i=0; (dir = dir_info_iter(&i)) != 0;) {
|
||||||
check_directory(fs, i);
|
if (ext2fs_test_inode_bitmap(inode_dir_map, dir->ino))
|
||||||
|
check_directory(fs, dir, &pctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
free_dir_info(fs);
|
free_dir_info(fs);
|
||||||
ext2fs_free_inode_bitmap(inode_loop_detect);
|
ext2fs_free_inode_bitmap(inode_loop_detect);
|
||||||
ext2fs_free_inode_bitmap(inode_done_map);
|
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
|
* 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.
|
* 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;
|
blk_t blk;
|
||||||
errcode_t retval;
|
errcode_t retval;
|
||||||
struct ext2_inode inode;
|
struct ext2_inode inode;
|
||||||
char * block;
|
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
|
* If the root inode is a directory, die here. The
|
||||||
* user must have answered 'no' in pass1 when we
|
* user must have answered 'no' in pass1 when we
|
||||||
* offered to clear it.
|
* 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");
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Root inode not allocated. ");
|
if (!fix_problem(fs, PR_3_NO_ROOT_INODE, 0))
|
||||||
preenhalt(fs);
|
|
||||||
if (!ask("Reallocate", 1)) {
|
|
||||||
ext2fs_unmark_valid(fs);
|
|
||||||
fatal_error("Cannot proceed without a root inode.");
|
fatal_error("Cannot proceed without a root inode.");
|
||||||
}
|
|
||||||
|
|
||||||
read_bitmaps(fs);
|
read_bitmaps(fs);
|
||||||
|
|
||||||
|
@ -201,9 +198,9 @@ void check_root(ext2_filsys fs, ino_t root_ino)
|
||||||
/*
|
/*
|
||||||
* Miscellaneous bookkeeping...
|
* Miscellaneous bookkeeping...
|
||||||
*/
|
*/
|
||||||
add_dir_info(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, &inode);
|
add_dir_info(fs, EXT2_ROOT_INO, EXT2_ROOT_INO);
|
||||||
inode_count[EXT2_ROOT_INO] = 2;
|
ext2fs_icount_store(inode_count, EXT2_ROOT_INO, 2);
|
||||||
inode_link_info[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_used_map, EXT2_ROOT_INO);
|
||||||
ext2fs_mark_inode_bitmap(inode_dir_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
|
* a loop, we treat that as a disconnected directory and offer to
|
||||||
* reparent it to lost+found.
|
* 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 = 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
ext2fs_clear_inode_bitmap(inode_loop_detect);
|
ext2fs_clear_inode_bitmap(inode_loop_detect);
|
||||||
p = dir;
|
|
||||||
while (p) {
|
while (p) {
|
||||||
/*
|
/*
|
||||||
* If we find a parent which we've already checked,
|
* 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
|
* If we've reached here, we've hit a detached directory
|
||||||
* inode; offer to reconnect it to lost+found.
|
* inode; offer to reconnect it to lost+found.
|
||||||
*/
|
*/
|
||||||
retval = ext2fs_get_pathname(fs, p->ino, 0, &path1);
|
pctx->ino = p->ino;
|
||||||
if (retval)
|
if (fix_problem(fs, PR_3_UNCONNECTED_DIR, pctx)) {
|
||||||
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)) {
|
|
||||||
if (reconnect_file(fs, p->ino))
|
if (reconnect_file(fs, p->ino))
|
||||||
ext2fs_unmark_valid(fs);
|
ext2fs_unmark_valid(fs);
|
||||||
else {
|
else {
|
||||||
p->parent = lost_and_found;
|
p->parent = lost_and_found;
|
||||||
fix_dotdot(fs, p, 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;
|
* 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:
|
check_dot_dot:
|
||||||
if (dir->parent != dir->dotdot) {
|
if (dir->parent != dir->dotdot) {
|
||||||
retval = ext2fs_get_pathname(fs, dir->parent, ino,
|
pctx->ino = dir->ino;
|
||||||
&path1);
|
pctx->ino2 = dir->dotdot;
|
||||||
if (retval)
|
pctx->dir = dir->parent;
|
||||||
path1 = unknown;
|
if (fix_problem(fs, PR_3_BAD_DOT_DOT, pctx))
|
||||||
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))
|
|
||||||
fix_dotdot(fs, dir, dir->parent);
|
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;
|
errcode_t retval;
|
||||||
struct ext2_inode inode;
|
struct ext2_inode inode;
|
||||||
char * block;
|
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)
|
if (!retval)
|
||||||
return ino;
|
return ino;
|
||||||
if (retval != ENOENT)
|
if (retval != ENOENT)
|
||||||
printf("Error while trying to find /lost+found: %s",
|
printf("Error while trying to find /lost+found: %s",
|
||||||
error_message(retval));
|
error_message(retval));
|
||||||
else
|
if (!fix_problem(fs, PR_3_NO_LF_DIR, 0))
|
||||||
printf("/lost+found not found. ");
|
|
||||||
preenhalt(fs);
|
|
||||||
if (!ask("Create", 1)) {
|
|
||||||
ext2fs_unmark_valid(fs);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read the inode and block bitmaps in; we'll be messing with
|
* 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.
|
* 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);
|
adjust_inode_count(fs, EXT2_ROOT_INO, +1);
|
||||||
inode_count[ino] = 2;
|
ext2fs_icount_store(inode_count, ino, 2);
|
||||||
inode_link_info[ino] = 2;
|
ext2fs_icount_store(inode_link_info, ino, 2);
|
||||||
#if 0
|
#if 0
|
||||||
printf("/lost+found created; inode #%lu\n", ino);
|
printf("/lost+found created; inode #%lu\n", ino);
|
||||||
#endif
|
#endif
|
||||||
|
@ -468,7 +422,7 @@ int reconnect_file(ext2_filsys fs, ino_t inode)
|
||||||
sprintf(name, "#%lu", inode);
|
sprintf(name, "#%lu", inode);
|
||||||
retval = ext2fs_link(fs, lost_and_found, name, inode, 0);
|
retval = ext2fs_link(fs, lost_and_found, name, inode, 0);
|
||||||
if (retval == EXT2_ET_DIR_NO_SPACE) {
|
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;
|
return 1;
|
||||||
retval = expand_directory(fs, lost_and_found);
|
retval = expand_directory(fs, lost_and_found);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
|
@ -510,8 +464,14 @@ static errcode_t adjust_inode_count(ext2_filsys fs, ino_t ino, int adj)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
inode.i_links_count += adj;
|
inode.i_links_count += adj;
|
||||||
inode_count[ino] += adj;
|
if (adj == 1) {
|
||||||
inode_link_info[ino] += adj;
|
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);
|
retval = ext2fs_write_inode(fs, ino, &inode);
|
||||||
if (retval)
|
if (retval)
|
||||||
|
|
|
@ -1,12 +1,19 @@
|
||||||
/*
|
/*
|
||||||
* pass4.c -- pass #4 of e2fsck: Check reference counts
|
* pass4.c -- pass #4 of e2fsck: Check reference counts
|
||||||
*
|
*
|
||||||
* Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
|
* Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
|
||||||
* under the terms of the GNU Public License.
|
*
|
||||||
*
|
* %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 "e2fsck.h"
|
||||||
|
#include "problem.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This routine is called when an inode is not connected to the
|
* 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
|
* This subroutine returns 1 then the caller shouldn't bother with the
|
||||||
* rest of the pass 4 tests.
|
* 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 ext2_inode inode;
|
||||||
|
struct problem_context pctx;
|
||||||
|
|
||||||
e2fsck_read_inode(fs, i, &inode, "pass4: disconnect_inode");
|
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) ||
|
if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
|
||||||
LINUX_S_ISDIR(inode.i_mode))) {
|
LINUX_S_ISDIR(inode.i_mode))) {
|
||||||
/*
|
/*
|
||||||
* This is a zero-length file; prompt to delete it...
|
* This is a zero-length file; prompt to delete it...
|
||||||
*/
|
*/
|
||||||
printf("Unattached zero-length inode %lu\n", i);
|
if (fix_problem(fs, PR_4_ZERO_LEN_INODE, &pctx)) {
|
||||||
if (ask("Clear", 1)) {
|
ext2fs_icount_store(inode_link_info, i, 0);
|
||||||
inode_link_info[i] = 0;
|
|
||||||
inode.i_links_count = 0;
|
inode.i_links_count = 0;
|
||||||
inode.i_dtime = time(0);
|
inode.i_dtime = time(0);
|
||||||
e2fsck_write_inode(fs, i, &inode,
|
e2fsck_write_inode(fs, i, &inode,
|
||||||
|
@ -47,9 +58,7 @@ int disconnect_inode(ext2_filsys fs, ino_t i)
|
||||||
/*
|
/*
|
||||||
* Prompt to reconnect.
|
* Prompt to reconnect.
|
||||||
*/
|
*/
|
||||||
printf("Unattached inode %lu\n", i);
|
if (fix_problem(fs, PR_4_UNATTACHED_INODE, &pctx)) {
|
||||||
preenhalt(fs);
|
|
||||||
if (ask("Connect to /lost+found", 1)) {
|
|
||||||
if (reconnect_file(fs, i))
|
if (reconnect_file(fs, i))
|
||||||
ext2fs_unmark_valid(fs);
|
ext2fs_unmark_valid(fs);
|
||||||
} else {
|
} else {
|
||||||
|
@ -70,6 +79,8 @@ void pass4(ext2_filsys fs)
|
||||||
ino_t i;
|
ino_t i;
|
||||||
struct ext2_inode inode;
|
struct ext2_inode inode;
|
||||||
struct resource_track rtrack;
|
struct resource_track rtrack;
|
||||||
|
struct problem_context pctx;
|
||||||
|
__u16 link_count, link_counted;
|
||||||
|
|
||||||
init_resource_track(&rtrack);
|
init_resource_track(&rtrack);
|
||||||
|
|
||||||
|
@ -79,39 +90,47 @@ void pass4(ext2_filsys fs)
|
||||||
|
|
||||||
if (!preen)
|
if (!preen)
|
||||||
printf("Pass 4: Checking reference counts\n");
|
printf("Pass 4: Checking reference counts\n");
|
||||||
|
clear_problem_context(&pctx);
|
||||||
for (i=1; i <= fs->super->s_inodes_count; i++) {
|
for (i=1; i <= fs->super->s_inodes_count; i++) {
|
||||||
if (i == EXT2_BAD_INO ||
|
if (i == EXT2_BAD_INO ||
|
||||||
(i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
|
(i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
|
||||||
continue;
|
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;
|
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))
|
if (disconnect_inode(fs, i))
|
||||||
continue;
|
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");
|
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("WARNING: PROGRAMMING BUG IN E2FSCK!\n");
|
||||||
printf("\tOR SOME BONEHEAD (YOU) IS CHECKING "
|
printf("\tOR SOME BONEHEAD (YOU) IS CHECKING "
|
||||||
"A MOUNTED (LIVE) FILESYSTEM.\n");
|
"A MOUNTED (LIVE) FILESYSTEM.\n");
|
||||||
printf("inode_link_info[%ld] is %u, "
|
printf("inode_link_info[%ld] is %u, "
|
||||||
"inode.i_links_count is %d. "
|
"inode.i_links_count is %d. "
|
||||||
"They should be the same!\n",
|
"They should be the same!\n",
|
||||||
i, inode_link_info[i],
|
i, link_count,
|
||||||
inode.i_links_count);
|
inode.i_links_count);
|
||||||
}
|
}
|
||||||
printf("Inode %lu has ref count %d, expecting %d.\n",
|
pctx.num = link_counted;
|
||||||
i, inode.i_links_count, inode_count[i]);
|
if (fix_problem(fs, PR_4_BAD_REF_COUNT, &pctx)) {
|
||||||
if (ask("Set i_nlinks to count", 1)) {
|
inode.i_links_count = link_counted;
|
||||||
inode.i_links_count = inode_count[i];
|
|
||||||
e2fsck_write_inode(fs, i, &inode, "pass4");
|
e2fsck_write_inode(fs, i, &inode, "pass4");
|
||||||
} else
|
}
|
||||||
ext2fs_unmark_valid(fs);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(inode_link_info); inode_link_info = 0;
|
ext2fs_free_icount(inode_link_info); inode_link_info = 0;
|
||||||
free(inode_count); inode_count = 0;
|
ext2fs_free_icount(inode_count); inode_count = 0;
|
||||||
|
ext2fs_free_inode_bitmap(inode_bb_map);
|
||||||
if (tflag > 1) {
|
if (tflag > 1) {
|
||||||
printf("Pass 4: ");
|
printf("Pass 4: ");
|
||||||
print_resource_track(&rtrack);
|
print_resource_track(&rtrack);
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
/*
|
/*
|
||||||
* pass5.c --- check block and inode bitmaps against on-disk bitmaps
|
* pass5.c --- check block and inode bitmaps against on-disk bitmaps
|
||||||
*
|
*
|
||||||
* Copyright (C) 1993, 1994 Theodore Ts'o. This file may be
|
* Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
|
||||||
* redistributed under the terms of the GNU Public License.
|
*
|
||||||
|
* %Begin-Header%
|
||||||
|
* This file may be redistributed under the terms of the GNU Public
|
||||||
|
* License.
|
||||||
|
* %End-Header%
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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);
|
||||||
|
|
|
@ -1,5 +1,13 @@
|
||||||
/*
|
/*
|
||||||
* swapfs.c --- byte-swap an ext2 filesystem
|
* 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
|
#ifdef HAVE_ERRNO_H
|
||||||
|
@ -125,21 +133,29 @@ static void swap_inodes(ext2_filsys fs)
|
||||||
fatal_error(0);
|
fatal_error(0);
|
||||||
}
|
}
|
||||||
inode = (struct ext2_inode *) buf;
|
inode = (struct ext2_inode *) buf;
|
||||||
for (i=0; i < fs->super->s_inodes_per_group; i++, ino++) {
|
for (i=0; i < fs->super->s_inodes_per_group;
|
||||||
if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
|
i++, ino++, inode++) {
|
||||||
ext2fs_swap_inode(fs, inode, inode, 0);
|
|
||||||
stashed_ino = ino;
|
stashed_ino = ino;
|
||||||
stashed_inode = inode;
|
stashed_inode = inode;
|
||||||
|
|
||||||
if (inode->i_block[EXT2_IND_BLOCK] ||
|
if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
|
||||||
inode->i_block[EXT2_DIND_BLOCK] ||
|
ext2fs_swap_inode(fs, inode, inode, 0);
|
||||||
inode->i_block[EXT2_TIND_BLOCK] ||
|
|
||||||
LINUX_S_ISDIR(inode->i_mode))
|
/*
|
||||||
|
* 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);
|
swap_inode_blocks(fs, ino, block_buf, inode);
|
||||||
|
|
||||||
if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
|
if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
|
||||||
ext2fs_swap_inode(fs, inode, inode, 1);
|
ext2fs_swap_inode(fs, inode, inode, 1);
|
||||||
inode++;
|
|
||||||
}
|
}
|
||||||
retval = io_channel_write_blk(fs->io,
|
retval = io_channel_write_blk(fs->io,
|
||||||
fs->group_desc[group].bg_inode_table,
|
fs->group_desc[group].bg_inode_table,
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
/*
|
/*
|
||||||
* util.c --- miscellaneous utilities
|
* util.c --- miscellaneous utilities
|
||||||
*
|
*
|
||||||
* Copyright (C) 1993, 1994 Theodore Ts'o. This file may be
|
* Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
|
||||||
* redistributed under the terms of the GNU Public License.
|
*
|
||||||
|
* %Begin-Header%
|
||||||
|
* This file may be redistributed under the terms of the GNU Public
|
||||||
|
* License.
|
||||||
|
* %End-Header%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -17,7 +21,6 @@
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
|
|
||||||
const char * fix_msg[2] = { "IGNORED", "FIXED" };
|
const char * fix_msg[2] = { "IGNORED", "FIXED" };
|
||||||
const char * clear_msg[2] = { "IGNORED", "CLEARED" };
|
|
||||||
|
|
||||||
void fatal_error (const char *msg)
|
void fatal_error (const char *msg)
|
||||||
{
|
{
|
||||||
|
@ -189,8 +192,14 @@ void init_resource_track(struct resource_track *track)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static __inline__ float timeval_subtract(struct timeval *tv1,
|
#ifdef __GNUC__
|
||||||
struct timeval *tv2)
|
#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) +
|
return ((tv1->tv_sec - tv2->tv_sec) +
|
||||||
((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
|
((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
|
#ifdef MTRACE
|
||||||
void mtrace_print(char *mesg)
|
void mtrace_print(char *mesg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
|
@ -1,43 +1,47 @@
|
||||||
Description: Tools for the second extended (ext2) filesystem
|
Summary: Tools for the second extended (ext2) filesystem
|
||||||
Name: e2fsprogs
|
Name: e2fsprogs
|
||||||
Version: 1.06
|
Version: 1.07
|
||||||
Release: 0
|
Release: 0
|
||||||
Copyright: GPL
|
Copyright: GPL
|
||||||
Group: Utilities/System
|
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
|
%package devel
|
||||||
Description: e2fs static libs and headers
|
Summary: e2fs static libs and headers
|
||||||
Group: Development/Libraries
|
Group: Development/Libraries
|
||||||
|
|
||||||
|
%description devel
|
||||||
|
Libraries and header files needed to develop ext2 filesystem-specific
|
||||||
|
programs.
|
||||||
|
|
||||||
%prep
|
%prep
|
||||||
%setup
|
%setup
|
||||||
|
|
||||||
%build
|
%build
|
||||||
|
CFLAGS="$RPM_OPT_FLAGS" ./configure --enable-elf-shlibs
|
||||||
|
|
||||||
%ifarch i386
|
make libs progs docs
|
||||||
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
|
|
||||||
|
|
||||||
%install
|
%install
|
||||||
rm -rf /usr/include/ss /usr/include/et /usr/include/ext2fs
|
|
||||||
export PATH=/sbin:$PATH
|
export PATH=/sbin:$PATH
|
||||||
make install
|
make install DESTDIR="$RPM_BUILD_ROOT"
|
||||||
make install-libs
|
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
|
%post
|
||||||
/sbin/ldconfig
|
/sbin/ldconfig
|
||||||
%endif
|
|
||||||
|
%postun
|
||||||
|
/sbin/ldconfig
|
||||||
|
|
||||||
%files
|
%files
|
||||||
/sbin/e2fsck
|
/sbin/e2fsck
|
||||||
|
@ -53,13 +57,11 @@ mv /usr/sbin/debugfs /sbin/debugfs
|
||||||
/usr/sbin/mklost+found
|
/usr/sbin/mklost+found
|
||||||
/sbin/mkfs.ext2
|
/sbin/mkfs.ext2
|
||||||
|
|
||||||
%ifarch i386
|
|
||||||
/lib/libe2p.so.2.2
|
/lib/libe2p.so.2.2
|
||||||
/lib/libext2fs.so.2.1
|
/lib/libext2fs.so.2.2
|
||||||
/lib/libss.so.2.0
|
/lib/libss.so.2.0
|
||||||
/lib/libcom_err.so.2.0
|
/lib/libcom_err.so.2.0
|
||||||
/lib/libuuid.so.1.0
|
/lib/libuuid.so.1.1
|
||||||
%endif
|
|
||||||
|
|
||||||
/usr/bin/chattr
|
/usr/bin/chattr
|
||||||
/usr/bin/lsattr
|
/usr/bin/lsattr
|
||||||
|
@ -73,28 +75,19 @@ mv /usr/sbin/debugfs /sbin/debugfs
|
||||||
/usr/man/man1/lsattr.1
|
/usr/man/man1/lsattr.1
|
||||||
|
|
||||||
%files devel
|
%files devel
|
||||||
|
/usr/info/libext2fs.info*
|
||||||
/usr/lib/libe2p.a
|
/usr/lib/libe2p.a
|
||||||
/usr/lib/libext2fs.a
|
/usr/lib/libext2fs.a
|
||||||
/usr/lib/libss.a
|
/usr/lib/libss.a
|
||||||
/usr/lib/libcom_err.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.a
|
||||||
/usr/lib/libuuid_p.a
|
|
||||||
/usr/include/ss
|
/usr/include/ss
|
||||||
/usr/include/ext2fs
|
/usr/include/ext2fs
|
||||||
/usr/include/et
|
/usr/include/et
|
||||||
/usr/include/uuid
|
/usr/include/uuid
|
||||||
|
|
||||||
%ifarch i386
|
|
||||||
/usr/lib/libe2p.so
|
/usr/lib/libe2p.so
|
||||||
/usr/lib/libext2fs.so
|
/usr/lib/libext2fs.so
|
||||||
/usr/lib/libss.so
|
/usr/lib/libss.so
|
||||||
/usr/lib/libcom_err.so
|
/usr/lib/libcom_err.so
|
||||||
/usr/lib/libuuid.so
|
/usr/lib/libuuid.so
|
||||||
|
|
||||||
%post
|
|
||||||
rm -f /lib/libe2p.so /lib/libext2fs.so /lib/libss.so /lib/libcom_err.so
|
|
||||||
%endif
|
|
|
@ -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>
|
Thu Sep 12 15:23:07 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
|
||||||
|
|
||||||
* Release of E2fsprogs version 1.05
|
* Release of E2fsprogs version 1.05
|
||||||
|
|
|
@ -38,19 +38,6 @@
|
||||||
#define EXT2FS_DATE "95/08/09"
|
#define EXT2FS_DATE "95/08/09"
|
||||||
#define EXT2FS_VERSION "0.5b"
|
#define EXT2FS_VERSION "0.5b"
|
||||||
|
|
||||||
/*
|
|
||||||
* Debug code
|
|
||||||
*/
|
|
||||||
#ifdef EXT2FS_DEBUG
|
|
||||||
# define ext2_debug(f, a...) { \
|
|
||||||
printk ("EXT2-fs DEBUG (%s, %d): %s:", \
|
|
||||||
__FILE__, __LINE__, __FUNCTION__); \
|
|
||||||
printk (f, ## a); \
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
# define ext2_debug(f, a...) /**/
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Special inodes numbers
|
* Special inodes numbers
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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>
|
Thu Sep 12 15:23:07 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
|
||||||
|
|
||||||
* Release of E2fsprogs version 1.05
|
* Release of E2fsprogs version 1.05
|
||||||
|
|
|
@ -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>
|
Thu Sep 12 15:23:07 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
|
||||||
|
|
||||||
* Release of E2fsprogs version 1.05
|
* Release of E2fsprogs version 1.05
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
# ELF_IMAGE = libce
|
# ELF_IMAGE = libce
|
||||||
# ELF_MYDIR = et
|
# ELF_MYDIR = et
|
||||||
# ELF_INSTALL_DIR = $(SHLIBDIR)
|
# ELF_INSTALL_DIR = $(SHLIBDIR)
|
||||||
#
|
# ELF_OTHER_LIBS = -lc
|
||||||
|
|
||||||
all:: elfshared image
|
all:: elfshared image
|
||||||
|
|
||||||
|
@ -24,7 +24,8 @@ ELF_SONAME = $(ELF_IMAGE).so.$(ELF_SO_VERSION)
|
||||||
image: $(ELF_LIB)
|
image: $(ELF_LIB)
|
||||||
|
|
||||||
$(ELF_LIB): $(OBJS)
|
$(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) .
|
$(MV) elfshared/$(ELF_LIB) .
|
||||||
$(RM) -f ../$(ELF_LIB) ../$(ELF_IMAGE).so ../$(ELF_SONAME)
|
$(RM) -f ../$(ELF_LIB) ../$(ELF_IMAGE).so ../$(ELF_SONAME)
|
||||||
$(LN) $(ELF_LIB) ../$(ELF_LIB)
|
$(LN) $(ELF_LIB) ../$(ELF_LIB)
|
||||||
|
|
|
@ -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>
|
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.
|
* pf.c: Add support for the 'A' (no atime) flag.
|
||||||
|
|
|
@ -45,6 +45,7 @@ ELF_SO_VERSION = 2
|
||||||
ELF_IMAGE = libe2p
|
ELF_IMAGE = libe2p
|
||||||
ELF_MYDIR = e2p
|
ELF_MYDIR = e2p
|
||||||
ELF_INSTALL_DIR = $(libdir)
|
ELF_INSTALL_DIR = $(libdir)
|
||||||
|
ELF_OTHER_LIBS = -lc
|
||||||
|
|
||||||
BSDLIB_VERSION = 2.1
|
BSDLIB_VERSION = 2.1
|
||||||
BSDLIB_IMAGE = libe2p
|
BSDLIB_IMAGE = libe2p
|
||||||
|
@ -60,7 +61,7 @@ BSDLIB_INSTALL_DIR = $(libdir)
|
||||||
|
|
||||||
.c.o:
|
.c.o:
|
||||||
$(CC) $(ALL_CFLAGS) -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 $<
|
@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@ (export JUMP_DIR=`pwd`/jump; $(CC) -B$(JUMP_PREFIX) $(ALL_CFLAGS) \
|
||||||
@DLL_CMT@ -o jump/$*.o -c $<)
|
@DLL_CMT@ -o jump/$*.o -c $<)
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
00000000 T _fgetflags libe2p jump/fgetflags
|
00000000 T _fgetflags libe2p fgetflags
|
||||||
00000000 T _fsetflags libe2p jump/fsetflags
|
00000000 T _fsetflags libe2p fsetflags
|
||||||
00000000 T _fgetversion libe2p jump/fgetversion
|
00000000 T _fgetversion libe2p fgetversion
|
||||||
00000000 T _fsetversion libe2p jump/fsetversion
|
00000000 T _fsetversion libe2p fsetversion
|
||||||
00000000 T _getflags libe2p jump/getflags
|
00000000 T _getflags libe2p getflags
|
||||||
00000000 T _getversion libe2p jump/getversion
|
00000000 T _getversion libe2p getversion
|
||||||
00000000 T _iterate_on_dir libe2p jump/iod
|
00000000 T _iterate_on_dir libe2p iod
|
||||||
00000000 T _list_super libe2p jump/ls
|
00000000 T _list_super libe2p ls
|
||||||
00000000 T _print_fs_errors libe2p jump/pe
|
00000000 T _print_fs_errors libe2p pe
|
||||||
00000000 T _print_flags libe2p jump/pf
|
00000000 T _print_flags libe2p pf
|
||||||
00000000 T _print_fs_state libe2p jump/ps
|
00000000 T _print_fs_state libe2p ps
|
||||||
00000000 T _setflags libe2p jump/setflags
|
00000000 T _setflags libe2p setflags
|
||||||
00000000 T _setversion libe2p jump/setversion
|
00000000 T _setversion libe2p setversion
|
||||||
|
00000000 T _e2p_is_null_uuid libe2p uuid
|
||||||
|
00000000 T _e2p_uuid_to_str libe2p uuid
|
||||||
|
|
76
lib/e2p/ls.c
76
lib/e2p/ls.c
|
@ -5,6 +5,8 @@
|
||||||
* Laboratoire MASI, Institut Blaise Pascal
|
* Laboratoire MASI, Institut Blaise Pascal
|
||||||
* Universite Pierre et Marie Curie (Paris VI)
|
* 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
|
* This file can be redistributed under the terms of the GNU Library General
|
||||||
* Public License
|
* Public License
|
||||||
*/
|
*/
|
||||||
|
@ -104,13 +106,16 @@ static void print_group (unsigned short gid)
|
||||||
#define HOUR_INT (60 * 60)
|
#define HOUR_INT (60 * 60)
|
||||||
#define MINUTE_INT (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];
|
static char buf[256], tmp[80];
|
||||||
int hr, min, num;
|
int hr, min, num;
|
||||||
|
|
||||||
buf[0] = 0;
|
buf[0] = 0;
|
||||||
|
|
||||||
|
if (secs == 0)
|
||||||
|
return "<none>";
|
||||||
|
|
||||||
if (secs >= MONTH_INT) {
|
if (secs >= MONTH_INT) {
|
||||||
num = secs / MONTH_INT;
|
num = secs / MONTH_INT;
|
||||||
secs -= num*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;
|
struct ext2fs_sb *sb = (struct ext2fs_sb *) s;
|
||||||
char buf[80];
|
char buf[80];
|
||||||
const char *os;
|
const char *os;
|
||||||
|
time_t tm;
|
||||||
|
|
||||||
inode_blocks_per_group = (((s->s_inodes_per_group *
|
inode_blocks_per_group = (((s->s_inodes_per_group *
|
||||||
EXT2_INODE_SIZE(s)) +
|
EXT2_INODE_SIZE(s)) +
|
||||||
|
@ -163,17 +169,20 @@ void list_super (struct ext2_super_block * s)
|
||||||
if (sb->s_volume_name[0]) {
|
if (sb->s_volume_name[0]) {
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
strncpy(buf, sb->s_volume_name, sizeof(sb->s_volume_name));
|
strncpy(buf, sb->s_volume_name, sizeof(sb->s_volume_name));
|
||||||
printf("Filesystem volume name: %s\n", buf);
|
} else
|
||||||
}
|
strcpy(buf, "<none>");
|
||||||
|
printf("Filesystem volume name: %s\n", buf);
|
||||||
if (sb->s_last_mounted[0]) {
|
if (sb->s_last_mounted[0]) {
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
strncpy(buf, sb->s_last_mounted, sizeof(sb->s_last_mounted));
|
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)) {
|
if (!e2p_is_null_uuid(sb->s_uuid)) {
|
||||||
e2p_uuid_to_str(sb->s_uuid, buf);
|
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: ");
|
printf ("Filesystem state: ");
|
||||||
print_fs_state (stdout, s->s_state);
|
print_fs_state (stdout, s->s_state);
|
||||||
printf ("\n");
|
printf ("\n");
|
||||||
|
@ -186,38 +195,41 @@ void list_super (struct ext2_super_block * s)
|
||||||
case EXT2_OS_MASIX: os = "Masix"; break;
|
case EXT2_OS_MASIX: os = "Masix"; break;
|
||||||
default: os = "unknown"; break;
|
default: os = "unknown"; break;
|
||||||
}
|
}
|
||||||
printf ("Filesystem OS type: %s\n", os);
|
printf("Filesystem OS type: %s\n", os);
|
||||||
printf ("Inode count: %u\n", s->s_inodes_count);
|
printf("Inode count: %u\n", s->s_inodes_count);
|
||||||
printf ("Block count: %u\n", s->s_blocks_count);
|
printf("Block count: %u\n", s->s_blocks_count);
|
||||||
printf ("Reserved block count: %u\n", s->s_r_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 blocks: %u\n", s->s_free_blocks_count);
|
||||||
printf ("Free inodes: %u\n", s->s_free_inodes_count);
|
printf("Free inodes: %u\n", s->s_free_inodes_count);
|
||||||
printf ("First block: %u\n", s->s_first_data_block);
|
printf("First block: %u\n", s->s_first_data_block);
|
||||||
printf ("Block size: %u\n", EXT2_BLOCK_SIZE(s));
|
printf("Block size: %u\n", EXT2_BLOCK_SIZE(s));
|
||||||
printf ("Fragment size: %u\n", EXT2_FRAG_SIZE(s));
|
printf("Fragment size: %u\n", EXT2_FRAG_SIZE(s));
|
||||||
printf ("Blocks per group: %u\n", s->s_blocks_per_group);
|
printf("Blocks per group: %u\n", s->s_blocks_per_group);
|
||||||
printf ("Fragments per group: %u\n", s->s_frags_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("Inodes per group: %u\n", s->s_inodes_per_group);
|
||||||
printf ("Inode blocks per group: %u\n", inode_blocks_per_group);
|
printf("Inode blocks per group: %u\n", inode_blocks_per_group);
|
||||||
printf ("Last mount time: %s", ctime ((time_t *) &s->s_mtime));
|
tm = s->s_mtime;
|
||||||
printf ("Last write time: %s", ctime ((time_t *) &s->s_wtime));
|
printf("Last mount time: %s", ctime(&tm));
|
||||||
printf ("Mount count: %u\n", s->s_mnt_count);
|
tm = s->s_wtime;
|
||||||
printf ("Maximum mount count: %d\n", s->s_max_mnt_count);
|
printf("Last write time: %s", ctime(&tm));
|
||||||
printf ("Last checked: %s", ctime ((time_t *) &s->s_lastcheck));
|
printf("Mount count: %u\n", s->s_mnt_count);
|
||||||
printf ("Check interval: %u (%s)\n", s->s_checkinterval,
|
printf("Maximum mount count: %d\n", s->s_max_mnt_count);
|
||||||
interval_string(s->s_checkinterval));
|
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)
|
if (s->s_checkinterval)
|
||||||
{
|
{
|
||||||
time_t next;
|
time_t next;
|
||||||
|
|
||||||
next = s->s_lastcheck + s->s_checkinterval;
|
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
|
#ifdef EXT2_DEF_RESUID
|
||||||
printf ("Reserved blocks uid: ");
|
printf("Reserved blocks uid: ");
|
||||||
print_user (s->s_def_resuid);
|
print_user(s->s_def_resuid);
|
||||||
printf ("Reserved blocks gid: ");
|
printf("Reserved blocks gid: ");
|
||||||
print_group (s->s_def_resgid);
|
print_group(s->s_def_resgid);
|
||||||
#endif
|
#endif
|
||||||
#ifdef EXT2_DYNAMIC_REV
|
#ifdef EXT2_DYNAMIC_REV
|
||||||
if (s->s_rev_level >= EXT2_DYNAMIC_REV) {
|
if (s->s_rev_level >= EXT2_DYNAMIC_REV) {
|
||||||
|
|
|
@ -3,8 +3,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
#include "e2p.h"
|
||||||
|
|
||||||
struct uuid {
|
struct uuid {
|
||||||
__u32 time_low;
|
__u32 time_low;
|
||||||
__u16 time_mid;
|
__u16 time_mid;
|
||||||
|
|
|
@ -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>
|
Thu Sep 12 15:23:07 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
|
||||||
|
|
||||||
* Release of E2fsprogs version 1.05
|
* Release of E2fsprogs version 1.05
|
||||||
|
|
|
@ -36,6 +36,7 @@ ELF_SO_VERSION = 2
|
||||||
ELF_IMAGE = libcom_err
|
ELF_IMAGE = libcom_err
|
||||||
ELF_MYDIR = et
|
ELF_MYDIR = et
|
||||||
ELF_INSTALL_DIR = $(libdir)
|
ELF_INSTALL_DIR = $(libdir)
|
||||||
|
ELF_OTHER_LIBS = -lc
|
||||||
|
|
||||||
BSDLIB_VERSION = 1.0
|
BSDLIB_VERSION = 1.0
|
||||||
BSDLIB_IMAGE = libcom_err
|
BSDLIB_IMAGE = libcom_err
|
||||||
|
@ -47,7 +48,7 @@ BSDLIB_INSTALL_DIR = $(libdir)
|
||||||
#
|
#
|
||||||
.c.o:
|
.c.o:
|
||||||
$(CC) $(ALL_CFLAGS) -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 $<
|
@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@ (export JUMP_DIR=`pwd`/jump; $(CC) -B$(JUMP_PREFIX) $(ALL_CFLAGS) \
|
||||||
@DLL_CMT@ -o jump/$*.o -c $<)
|
@DLL_CMT@ -o jump/$*.o -c $<)
|
||||||
|
|
|
@ -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>
|
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,
|
* ext2fs.h, block.c, closefs.c, dirblock.c, inode.c, native.c,
|
||||||
|
|
|
@ -9,25 +9,34 @@ INSTALL = @INSTALL@
|
||||||
|
|
||||||
OBJS= ext2_err.o \
|
OBJS= ext2_err.o \
|
||||||
alloc.o \
|
alloc.o \
|
||||||
|
alloc_tables.o \
|
||||||
badblocks.o \
|
badblocks.o \
|
||||||
|
bb_compat.o \
|
||||||
bb_inode.o \
|
bb_inode.o \
|
||||||
bitmaps.o \
|
bitmaps.o \
|
||||||
bitops.o \
|
bitops.o \
|
||||||
block.o \
|
block.o \
|
||||||
|
brel_ma.o \
|
||||||
check_desc.o \
|
check_desc.o \
|
||||||
closefs.o \
|
closefs.o \
|
||||||
cmp_bitmaps.o \
|
cmp_bitmaps.o \
|
||||||
|
dblist.o \
|
||||||
|
dblist_dir.o \
|
||||||
dirblock.o \
|
dirblock.o \
|
||||||
|
dir_iterate.o \
|
||||||
expanddir.o \
|
expanddir.o \
|
||||||
freefs.o \
|
freefs.o \
|
||||||
get_pathname.o \
|
get_pathname.o \
|
||||||
getsize.o \
|
getsize.o \
|
||||||
|
icount.o \
|
||||||
initialize.o \
|
initialize.o \
|
||||||
inline.o \
|
inline.o \
|
||||||
inode.o \
|
inode.o \
|
||||||
|
irel_ma.o \
|
||||||
ismounted.o \
|
ismounted.o \
|
||||||
link.o \
|
link.o \
|
||||||
llseek.o \
|
llseek.o \
|
||||||
|
lookup.o \
|
||||||
mkdir.o \
|
mkdir.o \
|
||||||
namei.o \
|
namei.o \
|
||||||
native.o \
|
native.o \
|
||||||
|
@ -35,31 +44,44 @@ OBJS= ext2_err.o \
|
||||||
openfs.o \
|
openfs.o \
|
||||||
read_bb.o \
|
read_bb.o \
|
||||||
read_bb_file.o \
|
read_bb_file.o \
|
||||||
|
rs_bitmap.o \
|
||||||
rw_bitmaps.o \
|
rw_bitmaps.o \
|
||||||
swapfs.o \
|
swapfs.o \
|
||||||
unix_io.o
|
test_io.o \
|
||||||
|
unix_io.o \
|
||||||
|
unlink.o \
|
||||||
|
valid_blk.o
|
||||||
|
|
||||||
SRCS= ext2_err.c \
|
SRCS= ext2_err.c \
|
||||||
$(srcdir)/alloc.c \
|
$(srcdir)/alloc.c \
|
||||||
|
$(srcdir)/alloc_tables.c \
|
||||||
$(srcdir)/badblocks.c \
|
$(srcdir)/badblocks.c \
|
||||||
|
$(srcdir)/bb_compat.c \
|
||||||
$(srcdir)/bb_inode.c \
|
$(srcdir)/bb_inode.c \
|
||||||
$(srcdir)/bitmaps.c \
|
$(srcdir)/bitmaps.c \
|
||||||
$(srcdir)/bitops.c \
|
$(srcdir)/bitops.c \
|
||||||
$(srcdir)/block.c \
|
$(srcdir)/block.c \
|
||||||
|
$(srcdir)/brel_ma.c \
|
||||||
$(srcdir)/check_desc.c \
|
$(srcdir)/check_desc.c \
|
||||||
$(srcdir)/closefs.c \
|
$(srcdir)/closefs.c \
|
||||||
$(srcdir)/cmp_bitmaps.c \
|
$(srcdir)/cmp_bitmaps.c \
|
||||||
|
$(srcdir)/dblist.c \
|
||||||
|
$(srcdir)/dblist_dir.c \
|
||||||
$(srcdir)/dirblock.c \
|
$(srcdir)/dirblock.c \
|
||||||
|
$(srcdir)/dir_iterate.c \
|
||||||
$(srcdir)/expanddir.c \
|
$(srcdir)/expanddir.c \
|
||||||
$(srcdir)/freefs.c \
|
$(srcdir)/freefs.c \
|
||||||
$(srcdir)/get_pathname.c \
|
$(srcdir)/get_pathname.c \
|
||||||
$(srcdir)/getsize.c \
|
$(srcdir)/getsize.c \
|
||||||
|
$(srcdir)/icount.c \
|
||||||
$(srcdir)/initialize.c \
|
$(srcdir)/initialize.c \
|
||||||
$(srcdir)/inline.c \
|
$(srcdir)/inline.c \
|
||||||
$(srcdir)/inode.c \
|
$(srcdir)/inode.c \
|
||||||
|
$(srcdir)/irel_ma.c \
|
||||||
$(srcdir)/ismounted.c \
|
$(srcdir)/ismounted.c \
|
||||||
$(srcdir)/link.c \
|
$(srcdir)/link.c \
|
||||||
$(srcdir)/llseek.c \
|
$(srcdir)/llseek.c \
|
||||||
|
$(srcdir)/lookup.c \
|
||||||
$(srcdir)/mkdir.c \
|
$(srcdir)/mkdir.c \
|
||||||
$(srcdir)/namei.c \
|
$(srcdir)/namei.c \
|
||||||
$(srcdir)/native.c \
|
$(srcdir)/native.c \
|
||||||
|
@ -67,9 +89,13 @@ SRCS= ext2_err.c \
|
||||||
$(srcdir)/openfs.c \
|
$(srcdir)/openfs.c \
|
||||||
$(srcdir)/read_bb.c \
|
$(srcdir)/read_bb.c \
|
||||||
$(srcdir)/read_bb_file.c \
|
$(srcdir)/read_bb_file.c \
|
||||||
|
$(srcdir)/rs_bitmap.c \
|
||||||
$(srcdir)/rw_bitmaps.c \
|
$(srcdir)/rw_bitmaps.c \
|
||||||
$(srcdir)/swapfs.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
|
HFILES= bitops.h ext2fs.h io.h
|
||||||
|
|
||||||
|
@ -86,11 +112,12 @@ DLL_LIBS = -L../.. -lcom_err
|
||||||
DLL_MYDIR = ext2fs
|
DLL_MYDIR = ext2fs
|
||||||
DLL_INSTALL_DIR = $(libdir)
|
DLL_INSTALL_DIR = $(libdir)
|
||||||
|
|
||||||
ELF_VERSION = 2.1
|
ELF_VERSION = 2.2
|
||||||
ELF_SO_VERSION = 2
|
ELF_SO_VERSION = 2
|
||||||
ELF_IMAGE = libext2fs
|
ELF_IMAGE = libext2fs
|
||||||
ELF_MYDIR = ext2fs
|
ELF_MYDIR = ext2fs
|
||||||
ELF_INSTALL_DIR = $(libdir)
|
ELF_INSTALL_DIR = $(libdir)
|
||||||
|
ELF_OTHER_LIBS = -lc -L../.. -lcom_err
|
||||||
|
|
||||||
BSDLIB_VERSION = 2.0
|
BSDLIB_VERSION = 2.0
|
||||||
BSDLIB_IMAGE = libext2fs
|
BSDLIB_IMAGE = libext2fs
|
||||||
|
@ -106,7 +133,7 @@ BSDLIB_INSTALL_DIR = $(libdir)
|
||||||
|
|
||||||
.c.o:
|
.c.o:
|
||||||
$(CC) $(ALL_CFLAGS) -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 $<
|
@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@ (export JUMP_DIR=`pwd`/jump; $(CC) -B$(JUMP_PREFIX) $(ALL_CFLAGS) \
|
||||||
@DLL_CMT@ -o jump/$*.o -c $<)
|
@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
|
ext2_err.c ext2_err.h: ext2_err.et
|
||||||
$(COMPILE_ET) 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::
|
installdirs::
|
||||||
$(top_srcdir)/mkinstalldirs $(DESTDIR)$(ulibdir) \
|
$(top_srcdir)/mkinstalldirs $(DESTDIR)$(ulibdir) \
|
||||||
$(DESTDIR)$(includedir)/ext2fs
|
$(DESTDIR)$(includedir)/ext2fs
|
||||||
|
@ -157,90 +195,205 @@ distclean:: clean
|
||||||
# the Makefile.in file
|
# the Makefile.in file
|
||||||
#
|
#
|
||||||
ext2_err.o: ext2_err.c
|
ext2_err.o: ext2_err.c
|
||||||
alloc.o: $(srcdir)/alloc.c $(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
|
alloc.o: $(srcdir)/alloc.c \
|
||||||
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
|
$(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
|
||||||
badblocks.o: $(srcdir)/badblocks.c $(srcdir)/ext2fs.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 \
|
$(top_srcdir)/lib/et/com_err.h \
|
||||||
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h $(srcdir)/bitops.h
|
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
|
||||||
bb_inode.o: $(srcdir)/bb_inode.c $(srcdir)/ext2fs.h \
|
$(srcdir)/bitops.h
|
||||||
$(top_srcdir)/lib/et/com_err.h $(srcdir)/bitops.h \
|
badblocks.o: $(srcdir)/badblocks.c \
|
||||||
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
|
$(srcdir)/ext2fsP.h \
|
||||||
bitmaps.o: $(srcdir)/bitmaps.c $(srcdir)/ext2fs.h \
|
$(srcdir)/ext2fs.h $(top_srcdir)/lib/et/com_err.h \
|
||||||
$(top_srcdir)/lib/et/com_err.h $(srcdir)/bitops.h \
|
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
|
||||||
$(srcdir)/io.h $(top_builddir)/lib/ext2fs/ext2_err.h
|
$(srcdir)/bitops.h
|
||||||
bitops.o: $(srcdir)/bitops.c $(srcdir)/ext2fs.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 \
|
$(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
|
$(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
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
/*
|
/*
|
||||||
* alloc.c --- allocate new inodes, blocks for ext2fs
|
* alloc.c --- allocate new inodes, blocks for ext2fs
|
||||||
*
|
*
|
||||||
* Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
|
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
|
||||||
* under the terms of the GNU Public License.
|
*
|
||||||
|
* %Begin-Header%
|
||||||
|
* This file may be redistributed under the terms of the GNU Public
|
||||||
|
* License.
|
||||||
|
* %End-Header%
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -84,26 +89,12 @@ errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
if (i > fs->super->s_blocks_count)
|
if (i >= fs->super->s_blocks_count)
|
||||||
i = fs->super->s_first_data_block;
|
i = fs->super->s_first_data_block;
|
||||||
} while (i != goal);
|
} while (i != goal);
|
||||||
return ENOSPC;
|
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,
|
errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start, blk_t finish,
|
||||||
int num, ext2fs_block_bitmap map, blk_t *ret)
|
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)
|
if (!num)
|
||||||
num = 1;
|
num = 1;
|
||||||
do {
|
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;
|
*ret = b;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
b++;
|
b++;
|
||||||
if (b > fs->super->s_blocks_count)
|
|
||||||
b = fs->super->s_first_data_block;
|
|
||||||
} while (b != finish);
|
} while (b != finish);
|
||||||
return ENOSPC;
|
return ENOSPC;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
/*
|
/*
|
||||||
* badblocks.c --- routines to manipulate the bad block structure
|
* badblocks.c --- routines to manipulate the bad block structure
|
||||||
*
|
*
|
||||||
* Copyright (C) 1994 Theodore Ts'o. This file may be redistributed
|
* Copyright (C) 1994, 1995, 1996 Theodore Ts'o.
|
||||||
* under the terms of the GNU Public License.
|
*
|
||||||
|
* %Begin-Header%
|
||||||
|
* This file may be redistributed under the terms of the GNU Public
|
||||||
|
* License.
|
||||||
|
* %End-Header%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -19,19 +23,19 @@
|
||||||
|
|
||||||
#include <linux/ext2_fs.h>
|
#include <linux/ext2_fs.h>
|
||||||
|
|
||||||
#include "ext2fs.h"
|
#include "ext2fsP.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This procedure create an empty badblocks list.
|
* 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)
|
if (!bb)
|
||||||
return ENOMEM;
|
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->magic = EXT2_ET_MAGIC_BADBLOCKS_LIST;
|
||||||
bb->size = size ? size : 10;
|
bb->size = size ? size : 10;
|
||||||
bb->list = malloc(bb->size * sizeof(blk_t));
|
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.
|
* 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.
|
* 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);
|
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) {
|
if (bb->num >= bb->size) {
|
||||||
bb->size += 10;
|
bb->size += 10;
|
||||||
bb->list = realloc(bb->list, bb->size * sizeof(blk_t));
|
new_list = realloc(bb->list, bb->size * sizeof(blk_t));
|
||||||
if (!bb->list) {
|
if (!new_list)
|
||||||
bb->size = 0;
|
|
||||||
bb->num = 0;
|
|
||||||
return ENOMEM;
|
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;
|
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
|
* This procedure tests to see if a particular block is on a badblocks
|
||||||
* list.
|
* 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++)
|
low = 0;
|
||||||
if (bb->list[i] == blk)
|
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;
|
return 1;
|
||||||
|
if (blk < bb->list[mid])
|
||||||
|
high = mid;
|
||||||
|
else
|
||||||
|
low = mid;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
errcode_t badblocks_list_iterate_begin(badblocks_list bb,
|
errcode_t ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb,
|
||||||
badblocks_iterate *ret)
|
ext2_badblocks_iterate *ret)
|
||||||
{
|
{
|
||||||
badblocks_iterate iter;
|
ext2_badblocks_iterate iter;
|
||||||
|
|
||||||
EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST);
|
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)
|
if (!iter)
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
|
|
||||||
|
@ -119,9 +138,9 @@ errcode_t badblocks_list_iterate_begin(badblocks_list bb,
|
||||||
return 0;
|
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)
|
if (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -139,7 +158,7 @@ int badblocks_list_iterate(badblocks_iterate iter, blk_t *blk)
|
||||||
return 0;
|
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))
|
if (!iter || (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE))
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -5,8 +5,12 @@
|
||||||
* this routine returns an error, the bad block inode may be in an
|
* this routine returns an error, the bad block inode may be in an
|
||||||
* inconsistent state.
|
* inconsistent state.
|
||||||
*
|
*
|
||||||
* Copyright (C) 1994 Theodore Ts'o. This file may be redistributed
|
* Copyright (C) 1994, 1995 Theodore Ts'o.
|
||||||
* under the terms of the GNU Public License.
|
*
|
||||||
|
* %Begin-Header%
|
||||||
|
* This file may be redistributed under the terms of the GNU Public
|
||||||
|
* License.
|
||||||
|
* %End-Header%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -26,7 +30,7 @@
|
||||||
#include "ext2fs.h"
|
#include "ext2fs.h"
|
||||||
|
|
||||||
struct set_badblock_record {
|
struct set_badblock_record {
|
||||||
badblocks_iterate bb_iter;
|
ext2_badblocks_iterate bb_iter;
|
||||||
int bad_block_count;
|
int bad_block_count;
|
||||||
blk_t *ind_blocks;
|
blk_t *ind_blocks;
|
||||||
int max_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,
|
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,
|
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
|
* Given a bad blocks bitmap, update the bad blocks inode to reflect
|
||||||
* the map.
|
* 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;
|
errcode_t retval;
|
||||||
struct set_badblock_record rec;
|
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)
|
* First clear the old bad blocks (while saving the indirect blocks)
|
||||||
*/
|
*/
|
||||||
retval = ext2fs_block_iterate(fs, EXT2_BAD_INO,
|
retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO,
|
||||||
BLOCK_FLAG_DEPTH_TRAVERSE, 0,
|
BLOCK_FLAG_DEPTH_TRAVERSE, 0,
|
||||||
clear_bad_block_proc, &rec);
|
clear_bad_block_proc, &rec);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
if (rec.err) {
|
if (rec.err) {
|
||||||
|
@ -93,22 +98,24 @@ errcode_t ext2fs_update_bb_inode(ext2_filsys fs, badblocks_list bb_list)
|
||||||
* block inode (!).
|
* block inode (!).
|
||||||
*/
|
*/
|
||||||
if (bb_list) {
|
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)
|
if (retval)
|
||||||
goto cleanup;
|
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);
|
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);
|
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)
|
if (retval)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
retval = ext2fs_block_iterate(fs, EXT2_BAD_INO,
|
retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO,
|
||||||
BLOCK_FLAG_APPEND, 0,
|
BLOCK_FLAG_APPEND, 0,
|
||||||
set_bad_block_proc, &rec);
|
set_bad_block_proc, &rec);
|
||||||
badblocks_list_iterate_end(rec.bb_iter);
|
ext2fs_badblocks_list_iterate_end(rec.bb_iter);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
if (rec.err) {
|
if (rec.err) {
|
||||||
|
@ -148,7 +155,7 @@ cleanup:
|
||||||
* indirect blocks.
|
* indirect blocks.
|
||||||
*/
|
*/
|
||||||
static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr, int blockcnt,
|
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 *)
|
struct set_badblock_record *rec = (struct set_badblock_record *)
|
||||||
private;
|
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.
|
* 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,
|
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 *)
|
struct set_badblock_record *rec = (struct set_badblock_record *)
|
||||||
private;
|
private;
|
||||||
|
@ -213,7 +221,7 @@ static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr,
|
||||||
/*
|
/*
|
||||||
* Get the next bad block.
|
* 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;
|
return BLOCK_ABORT;
|
||||||
rec->bad_block_count++;
|
rec->bad_block_count++;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -2,8 +2,12 @@
|
||||||
* bitmaps.c --- routines to read, write, and manipulate the inode and
|
* bitmaps.c --- routines to read, write, and manipulate the inode and
|
||||||
* block bitmaps.
|
* block bitmaps.
|
||||||
*
|
*
|
||||||
* Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
|
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
|
||||||
* under the terms of the GNU Public License.
|
*
|
||||||
|
* %Begin-Header%
|
||||||
|
* This file may be redistributed under the terms of the GNU Public
|
||||||
|
* License.
|
||||||
|
* %End-Header%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -166,4 +170,3 @@ void ext2fs_clear_block_bitmap(ext2fs_block_bitmap bitmap)
|
||||||
memset(bitmap->bitmap, 0,
|
memset(bitmap->bitmap, 0,
|
||||||
((bitmap->real_end - bitmap->start) / 8) + 1);
|
((bitmap->real_end - bitmap->start) / 8) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,12 @@
|
||||||
* bitops.c --- Bitmap frobbing code. See bitops.h for the inlined
|
* bitops.c --- Bitmap frobbing code. See bitops.h for the inlined
|
||||||
* routines.
|
* routines.
|
||||||
*
|
*
|
||||||
* Copyright (C) 1993, 1994 Theodore Ts'o. This file may be
|
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
|
||||||
* redistributed under the terms of the GNU Public License.
|
*
|
||||||
*
|
* %Begin-Header%
|
||||||
* Taken from <asm/bitops.h>, Copyright 1992, Linus Torvalds.
|
* This file may be redistributed under the terms of the GNU Public
|
||||||
|
* License.
|
||||||
|
* %End-Header%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
|
@ -2,10 +2,15 @@
|
||||||
* bitops.h --- Bitmap frobbing code. The byte swapping routines are
|
* bitops.h --- Bitmap frobbing code. The byte swapping routines are
|
||||||
* also included here.
|
* also included here.
|
||||||
*
|
*
|
||||||
* Copyright (C) 1993, 1994, 1995 Theodore Ts'o. This file may be
|
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
|
||||||
* redistributed under the terms of the GNU Public License.
|
*
|
||||||
|
* %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,
|
extern int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
|
||||||
ino_t inode);
|
ino_t inode);
|
||||||
extern blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap);
|
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_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...
|
* The inline routines themselves...
|
||||||
|
@ -305,7 +323,14 @@ _INLINE_ __u32 ext2fs_swab32(__u32 val)
|
||||||
#endif /* !_EXT2_HAVE_ASM_SWAB */
|
#endif /* !_EXT2_HAVE_ASM_SWAB */
|
||||||
|
|
||||||
_INLINE_ void ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
|
_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)) {
|
if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
|
||||||
ext2fs_warn_bitmap2(bitmap, EXT2FS_MARK_ERROR, bitno);
|
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,
|
_INLINE_ void ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
|
||||||
blk_t bitno)
|
blk_t bitno)
|
||||||
{
|
{
|
||||||
if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
|
if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
|
||||||
ext2fs_warn_bitmap2(bitmap, EXT2FS_UNMARK_ERROR, bitno);
|
ext2fs_warn_bitmap2(bitmap, EXT2FS_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,
|
_INLINE_ int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
|
||||||
blk_t bitno)
|
blk_t bitno)
|
||||||
{
|
{
|
||||||
if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
|
if ((bitno < bitmap->start) || (bitno > bitmap->end)) {
|
||||||
ext2fs_warn_bitmap2(bitmap, EXT2FS_UNMARK_ERROR, bitno);
|
ext2fs_warn_bitmap2(bitmap, EXT2FS_UNMARK_ERROR, bitno);
|
||||||
|
@ -455,7 +480,7 @@ _INLINE_ blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap)
|
||||||
return bitmap->start;
|
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;
|
return bitmap->start;
|
||||||
}
|
}
|
||||||
|
@ -465,11 +490,107 @@ _INLINE_ blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap)
|
||||||
return bitmap->end;
|
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;
|
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_
|
#undef _INLINE_
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
/*
|
/*
|
||||||
* block.c --- iterate over all blocks in an inode
|
* block.c --- iterate over all blocks in an inode
|
||||||
*
|
*
|
||||||
* Copyright (C) 1993 Theodore Ts'o. This file may be redistributed
|
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
|
||||||
* under the terms of the GNU Public License.
|
*
|
||||||
|
* %Begin-Header%
|
||||||
|
* This file may be redistributed under the terms of the GNU Public
|
||||||
|
* License.
|
||||||
|
* %End-Header%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -22,6 +26,8 @@ struct block_context {
|
||||||
int (*func)(ext2_filsys fs,
|
int (*func)(ext2_filsys fs,
|
||||||
blk_t *blocknr,
|
blk_t *blocknr,
|
||||||
int bcount,
|
int bcount,
|
||||||
|
blk_t ref_blk,
|
||||||
|
int ref_offset,
|
||||||
void *private);
|
void *private);
|
||||||
int bcount;
|
int bcount;
|
||||||
int bsize;
|
int bsize;
|
||||||
|
@ -33,16 +39,18 @@ struct block_context {
|
||||||
void *private;
|
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 ret = 0, changed = 0;
|
||||||
int i, flags, limit;
|
int i, flags, limit, offset;
|
||||||
blk_t *block_nr;
|
blk_t *block_nr;
|
||||||
|
|
||||||
if (!(ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
|
if (!(ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
|
||||||
!(ctx->flags & BLOCK_FLAG_DATA_ONLY))
|
!(ctx->flags & BLOCK_FLAG_DATA_ONLY))
|
||||||
ret = (*ctx->func)(ctx->fs, ind_block,
|
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))
|
if (!*ind_block || (ret & BLOCK_ABORT))
|
||||||
return ret;
|
return ret;
|
||||||
if (*ind_block >= ctx->fs->super->s_blocks_count ||
|
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 = ext2fs_swab32(*block_nr);
|
||||||
}
|
}
|
||||||
block_nr = (blk_t *) ctx->ind_buf;
|
block_nr = (blk_t *) ctx->ind_buf;
|
||||||
|
offset = 0;
|
||||||
if (ctx->flags & BLOCK_FLAG_APPEND) {
|
if (ctx->flags & BLOCK_FLAG_APPEND) {
|
||||||
for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) {
|
for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) {
|
||||||
flags = (*ctx->func)(ctx->fs, block_nr, ctx->bcount,
|
flags = (*ctx->func)(ctx->fs, block_nr, ctx->bcount,
|
||||||
|
*ind_block, offset,
|
||||||
ctx->private);
|
ctx->private);
|
||||||
changed |= flags;
|
changed |= flags;
|
||||||
if (flags & BLOCK_ABORT) {
|
if (flags & BLOCK_ABORT) {
|
||||||
ret |= BLOCK_ABORT;
|
ret |= BLOCK_ABORT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
offset += sizeof(blk_t);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) {
|
for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) {
|
||||||
if (*block_nr == 0)
|
if (*block_nr == 0)
|
||||||
continue;
|
continue;
|
||||||
flags = (*ctx->func)(ctx->fs, block_nr, ctx->bcount,
|
flags = (*ctx->func)(ctx->fs, block_nr, ctx->bcount,
|
||||||
|
*ind_block, offset,
|
||||||
ctx->private);
|
ctx->private);
|
||||||
changed |= flags;
|
changed |= flags;
|
||||||
if (flags & BLOCK_ABORT) {
|
if (flags & BLOCK_ABORT) {
|
||||||
ret |= BLOCK_ABORT;
|
ret |= BLOCK_ABORT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
offset += sizeof(blk_t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (changed & BLOCK_CHANGED) {
|
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) &&
|
!(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
|
||||||
!(ret & BLOCK_ABORT))
|
!(ret & BLOCK_ABORT))
|
||||||
ret |= (*ctx->func)(ctx->fs, ind_block,
|
ret |= (*ctx->func)(ctx->fs, ind_block,
|
||||||
BLOCK_COUNT_IND, ctx->private);
|
BLOCK_COUNT_IND, ref_block,
|
||||||
|
ref_offset, ctx->private);
|
||||||
return ret;
|
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 ret = 0, changed = 0;
|
||||||
int i, flags, limit;
|
int i, flags, limit, offset;
|
||||||
blk_t *block_nr;
|
blk_t *block_nr;
|
||||||
|
|
||||||
if (!(ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
|
if (!(ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
|
||||||
!(ctx->flags & BLOCK_FLAG_DATA_ONLY))
|
!(ctx->flags & BLOCK_FLAG_DATA_ONLY))
|
||||||
ret = (*ctx->func)(ctx->fs, dind_block,
|
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))
|
if (!*dind_block || (ret & BLOCK_ABORT))
|
||||||
return ret;
|
return ret;
|
||||||
if (*dind_block >= ctx->fs->super->s_blocks_count ||
|
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 = ext2fs_swab32(*block_nr);
|
||||||
}
|
}
|
||||||
block_nr = (blk_t *) ctx->dind_buf;
|
block_nr = (blk_t *) ctx->dind_buf;
|
||||||
|
offset = 0;
|
||||||
if (ctx->flags & BLOCK_FLAG_APPEND) {
|
if (ctx->flags & BLOCK_FLAG_APPEND) {
|
||||||
for (i = 0; i < limit; i++, block_nr++) {
|
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;
|
changed |= flags;
|
||||||
if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
|
if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
|
||||||
ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
|
ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
offset += sizeof(blk_t);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < limit; i++, block_nr++) {
|
for (i = 0; i < limit; i++, block_nr++) {
|
||||||
if (*block_nr == 0)
|
if (*block_nr == 0)
|
||||||
continue;
|
continue;
|
||||||
flags = block_iterate_ind(block_nr, ctx);
|
flags = block_iterate_ind(block_nr,
|
||||||
|
*dind_block, offset,
|
||||||
|
ctx);
|
||||||
changed |= flags;
|
changed |= flags;
|
||||||
if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
|
if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
|
||||||
ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
|
ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
offset += sizeof(blk_t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (changed & BLOCK_CHANGED) {
|
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) &&
|
!(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
|
||||||
!(ret & BLOCK_ABORT))
|
!(ret & BLOCK_ABORT))
|
||||||
ret |= (*ctx->func)(ctx->fs, dind_block,
|
ret |= (*ctx->func)(ctx->fs, dind_block,
|
||||||
BLOCK_COUNT_DIND, ctx->private);
|
BLOCK_COUNT_DIND, ref_block,
|
||||||
|
ref_offset, ctx->private);
|
||||||
return ret;
|
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 ret = 0, changed = 0;
|
||||||
int i, flags, limit;
|
int i, flags, limit, offset;
|
||||||
blk_t *block_nr;
|
blk_t *block_nr;
|
||||||
|
|
||||||
if (!(ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
|
if (!(ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) &&
|
||||||
!(ctx->flags & BLOCK_FLAG_DATA_ONLY))
|
!(ctx->flags & BLOCK_FLAG_DATA_ONLY))
|
||||||
ret = (*ctx->func)(ctx->fs, tind_block,
|
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))
|
if (!*tind_block || (ret & BLOCK_ABORT))
|
||||||
return ret;
|
return ret;
|
||||||
if (*tind_block >= ctx->fs->super->s_blocks_count ||
|
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 = ext2fs_swab32(*block_nr);
|
||||||
}
|
}
|
||||||
block_nr = (blk_t *) ctx->tind_buf;
|
block_nr = (blk_t *) ctx->tind_buf;
|
||||||
|
offset = 0;
|
||||||
if (ctx->flags & BLOCK_FLAG_APPEND) {
|
if (ctx->flags & BLOCK_FLAG_APPEND) {
|
||||||
for (i = 0; i < limit; i++, block_nr++) {
|
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;
|
changed |= flags;
|
||||||
if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
|
if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
|
||||||
ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
|
ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
offset += sizeof(blk_t);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < limit; i++, block_nr++) {
|
for (i = 0; i < limit; i++, block_nr++) {
|
||||||
if (*block_nr == 0)
|
if (*block_nr == 0)
|
||||||
continue;
|
continue;
|
||||||
flags = block_iterate_dind(block_nr, ctx);
|
flags = block_iterate_dind(block_nr,
|
||||||
|
*tind_block,
|
||||||
|
offset, ctx);
|
||||||
changed |= flags;
|
changed |= flags;
|
||||||
if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
|
if (flags & (BLOCK_ABORT | BLOCK_ERROR)) {
|
||||||
ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
|
ret |= flags & (BLOCK_ABORT | BLOCK_ERROR);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
offset += sizeof(blk_t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (changed & BLOCK_CHANGED) {
|
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) &&
|
!(ctx->flags & BLOCK_FLAG_DATA_ONLY) &&
|
||||||
!(ret & BLOCK_ABORT))
|
!(ret & BLOCK_ABORT))
|
||||||
ret |= (*ctx->func)(ctx->fs, tind_block,
|
ret |= (*ctx->func)(ctx->fs, tind_block,
|
||||||
BLOCK_COUNT_TIND, ctx->private);
|
BLOCK_COUNT_TIND, ref_block,
|
||||||
|
ref_offset, ctx->private);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
errcode_t ext2fs_block_iterate(ext2_filsys fs,
|
errcode_t ext2fs_block_iterate2(ext2_filsys fs,
|
||||||
ino_t ino,
|
ino_t ino,
|
||||||
int flags,
|
int flags,
|
||||||
char *block_buf,
|
char *block_buf,
|
||||||
int (*func)(ext2_filsys fs,
|
int (*func)(ext2_filsys fs,
|
||||||
blk_t *blocknr,
|
blk_t *blocknr,
|
||||||
int blockcnt,
|
int blockcnt,
|
||||||
void *private),
|
blk_t ref_blk,
|
||||||
void *private)
|
int ref_offset,
|
||||||
|
void *private),
|
||||||
|
void *private)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int got_inode = 0;
|
int got_inode = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct block_context ctx;
|
|
||||||
blk_t blocks[EXT2_N_BLOCKS]; /* directory data blocks */
|
blk_t blocks[EXT2_N_BLOCKS]; /* directory data blocks */
|
||||||
struct ext2_inode inode;
|
struct ext2_inode inode;
|
||||||
errcode_t retval;
|
errcode_t retval;
|
||||||
|
struct block_context ctx;
|
||||||
|
|
||||||
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
|
EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
|
||||||
|
|
||||||
ret = ext2fs_get_blocks(fs, ino, blocks);
|
ret = ext2fs_get_blocks(fs, ino, blocks);
|
||||||
|
@ -282,8 +318,8 @@ errcode_t ext2fs_block_iterate(ext2_filsys fs,
|
||||||
ctx.fs = fs;
|
ctx.fs = fs;
|
||||||
ctx.func = func;
|
ctx.func = func;
|
||||||
ctx.private = private;
|
ctx.private = private;
|
||||||
ctx.bcount = 0;
|
|
||||||
ctx.flags = flags;
|
ctx.flags = flags;
|
||||||
|
ctx.bcount = 0;
|
||||||
if (block_buf) {
|
if (block_buf) {
|
||||||
ctx.ind_buf = block_buf;
|
ctx.ind_buf = block_buf;
|
||||||
} else {
|
} else {
|
||||||
|
@ -304,8 +340,10 @@ errcode_t ext2fs_block_iterate(ext2_filsys fs,
|
||||||
goto abort;
|
goto abort;
|
||||||
got_inode = 1;
|
got_inode = 1;
|
||||||
if (inode.osd1.hurd1.h_i_translator) {
|
if (inode.osd1.hurd1.h_i_translator) {
|
||||||
ret |= (*func)(fs, &inode.osd1.hurd1.h_i_translator,
|
ret |= (*ctx.func)(fs,
|
||||||
BLOCK_COUNT_TRANSLATOR, private);
|
&inode.osd1.hurd1.h_i_translator,
|
||||||
|
BLOCK_COUNT_TRANSLATOR,
|
||||||
|
0, 0, private);
|
||||||
if (ret & BLOCK_ABORT)
|
if (ret & BLOCK_ABORT)
|
||||||
goto 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++) {
|
for (i = 0; i < EXT2_NDIR_BLOCKS ; i++, ctx.bcount++) {
|
||||||
if (blocks[i] || (flags & BLOCK_FLAG_APPEND)) {
|
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)
|
if (ret & BLOCK_ABORT)
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (*(blocks + EXT2_IND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
|
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)
|
if (ret & BLOCK_ABORT)
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
if (*(blocks + EXT2_DIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
|
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)
|
if (ret & BLOCK_ABORT)
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
if (*(blocks + EXT2_TIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) {
|
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)
|
if (ret & BLOCK_ABORT)
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
|
@ -356,3 +398,40 @@ abort:
|
||||||
|
|
||||||
return (ret & BLOCK_ERROR) ? ctx.errcode : 0;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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)))
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -1,8 +1,12 @@
|
||||||
/*
|
/*
|
||||||
* check_desc.c --- Check the group descriptors of an ext2 filesystem
|
* check_desc.c --- Check the group descriptors of an ext2 filesystem
|
||||||
*
|
*
|
||||||
* Copyright (C) 1993, 1994 Theodore Ts'o. This file may be redistributed
|
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
|
||||||
* under the terms of the GNU Public License.
|
*
|
||||||
|
* %Begin-Header%
|
||||||
|
* This file may be redistributed under the terms of the GNU Public
|
||||||
|
* License.
|
||||||
|
* %End-Header%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
/*
|
/*
|
||||||
* closefs.c --- close an ext2 filesystem
|
* closefs.c --- close an ext2 filesystem
|
||||||
*
|
*
|
||||||
* Copyright (C) 1993, 1994 Theodore Ts'o. This file may be redistributed
|
* Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o.
|
||||||
* under the terms of the GNU Public License.
|
*
|
||||||
|
* %Begin-Header%
|
||||||
|
* This file may be redistributed under the terms of the GNU Public
|
||||||
|
* License.
|
||||||
|
* %End-Header%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -16,7 +20,7 @@
|
||||||
|
|
||||||
#include <linux/ext2_fs.h>
|
#include <linux/ext2_fs.h>
|
||||||
|
|
||||||
#include "ext2fs.h"
|
#include "ext2fsP.h"
|
||||||
|
|
||||||
errcode_t ext2fs_flush(ext2_filsys fs)
|
errcode_t ext2fs_flush(ext2_filsys fs)
|
||||||
{
|
{
|
||||||
|
@ -118,7 +122,6 @@ errcode_t ext2fs_flush(ext2_filsys fs)
|
||||||
if (retval)
|
if (retval)
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
errout:
|
errout:
|
||||||
fs->super->s_state = fs_state;
|
fs->super->s_state = fs_state;
|
||||||
|
@ -142,6 +145,42 @@ errcode_t ext2fs_close(ext2_filsys fs)
|
||||||
if (retval)
|
if (retval)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
if (fs->write_bitmaps) {
|
||||||
|
retval = fs->write_bitmaps(fs);
|
||||||
|
if (retval)
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
ext2fs_free(fs);
|
ext2fs_free(fs);
|
||||||
return 0;
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
/*
|
/*
|
||||||
* cmp_bitmaps.c --- routines to compare inode and block bitmaps.
|
* cmp_bitmaps.c --- routines to compare inode and block bitmaps.
|
||||||
*
|
*
|
||||||
* Copyright (C) 1995 Theodore Ts'o. This file may be redistributed
|
* Copyright (C) 1995 Theodore Ts'o.
|
||||||
* under the terms of the GNU Public License.
|
*
|
||||||
|
* %Begin-Header%
|
||||||
|
* This file may be redistributed under the terms of the GNU Public
|
||||||
|
* License.
|
||||||
|
* %End-Header%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -1,13 +1,18 @@
|
||||||
/*
|
/*
|
||||||
* dirblock.c --- directory block routines.
|
* dirblock.c --- directory block routines.
|
||||||
*
|
*
|
||||||
* Copyright (C) 1995 Theodore Ts'o. This file may be redistributed
|
* Copyright (C) 1995, 1996 Theodore Ts'o.
|
||||||
* under the terms of the GNU Public License.
|
*
|
||||||
|
* %Begin-Header%
|
||||||
|
* This file may be redistributed under the terms of the GNU Public
|
||||||
|
* License.
|
||||||
|
* %End-Header%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#ifdef HAVE_ERRNO_H
|
#ifdef HAVE_ERRNO_H
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
Loading…
Reference in New Issue