mirror of https://github.com/vitalif/e2fsprogs
Compare commits
19 Commits
debian-1.4
...
master
Author | SHA1 | Date |
---|---|---|
Vitaliy Filippov | 6e4fa6e281 | |
Vitaliy Filippov | b331d80fba | |
Vitaliy Filippov | f99c7a2e12 | |
Vitaliy Filippov | b9b963d427 | |
Vitaliy Filippov | f58c260dc4 | |
Vitaliy Filippov | 152890aa45 | |
Vitaliy Filippov | 63039f4bac | |
Vitaliy Filippov | 7e0136332c | |
Vitaliy Filippov | b3782b2e5b | |
Vitaliy Filippov | 460c0af190 | |
Vitaliy Filippov | 2051d63a83 | |
Theodore Ts'o | e703ba4b42 | |
Theodore Ts'o | d6cad379eb | |
Theodore Ts'o | 4e52870eeb | |
Theodore Ts'o | 047d5d774f | |
Theodore Ts'o | a7b27f11a1 | |
Theodore Ts'o | 8d7a63921f | |
Theodore Ts'o | f3bc1561c8 | |
Theodore Ts'o | 254195627f |
|
@ -5,6 +5,7 @@ build.static
|
||||||
FILES
|
FILES
|
||||||
^core
|
^core
|
||||||
*~
|
*~
|
||||||
|
patches
|
||||||
Makefile
|
Makefile
|
||||||
*.bak
|
*.bak
|
||||||
*.diff
|
*.diff
|
||||||
|
@ -160,6 +161,8 @@ misc/e2initrd_helper
|
||||||
misc/e2label.8
|
misc/e2label.8
|
||||||
misc/e2undo
|
misc/e2undo
|
||||||
misc/e2undo.8
|
misc/e2undo.8
|
||||||
|
misc/e2patch
|
||||||
|
misc/e2patch.8
|
||||||
misc/e4defrag
|
misc/e4defrag
|
||||||
misc/e4defrag.8
|
misc/e4defrag.8
|
||||||
misc/ext4.5
|
misc/ext4.5
|
||||||
|
|
|
@ -68,8 +68,8 @@ pkgconfigdir = $(libdir)/pkgconfig
|
||||||
@ifGNUmake@ endif
|
@ifGNUmake@ endif
|
||||||
@ifGNUmake@ endif
|
@ifGNUmake@ endif
|
||||||
|
|
||||||
@ifNotGNUmake@ CHECK_CMD=@true
|
@ifNotGNUmake@ CHECK_CMD=true
|
||||||
@ifNotGNUmake@ CPPHECK_CMD=@true
|
@ifNotGNUmake@ CPPCHECK_CMD=true
|
||||||
|
|
||||||
CC = @CC@
|
CC = @CC@
|
||||||
BUILD_CC = @BUILD_CC@
|
BUILD_CC = @BUILD_CC@
|
||||||
|
|
2
README
2
README
|
@ -1,4 +1,4 @@
|
||||||
This is the new version (1.43.2) of the second extended file
|
This is the new version (1.43.3) of the second extended file
|
||||||
system management programs.
|
system management programs.
|
||||||
|
|
||||||
From time to time, I release new versions of e2fsprogs, to fix
|
From time to time, I release new versions of e2fsprogs, to fix
|
||||||
|
|
|
@ -1,3 +1,31 @@
|
||||||
|
E2fsprogs 1.43.3 (September 4, 2016)
|
||||||
|
====================================
|
||||||
|
|
||||||
|
Fix e2fsck's handling of timestamps on 32-bit systems.
|
||||||
|
|
||||||
|
E2fsck will now check, and if necessary repair the extra isize fields
|
||||||
|
in the inode and superblock.
|
||||||
|
|
||||||
|
Fix crashes on architectures such as sparc64 that are sensitive to
|
||||||
|
unaligned pointer derferences in the journal recovery code when
|
||||||
|
journal checksums are enabled.
|
||||||
|
|
||||||
|
Programming notes
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Support reproducible builds by not capturing the build directory into
|
||||||
|
the mk_cmds and compile_et scripts. Also fix debian build rules to
|
||||||
|
ensure build reproducibility.
|
||||||
|
|
||||||
|
Fix debian build rules to ensure build reproducibility and to avoid
|
||||||
|
hiding the linker flags for e2fsck.static so the build hardening log
|
||||||
|
scanner can properly audit the build.
|
||||||
|
|
||||||
|
Fix compatibility with FreeBSD's pmake and teach the configure script
|
||||||
|
to force the creation of pmake-compatible Makefiles if the
|
||||||
|
FORCE_NATIVE_MAKE environment variable is set to a non-empty value.
|
||||||
|
|
||||||
|
|
||||||
E2fsprogs 1.43.2 (September 1, 2016)
|
E2fsprogs 1.43.2 (September 1, 2016)
|
||||||
====================================
|
====================================
|
||||||
|
|
||||||
|
|
|
@ -108,7 +108,12 @@ AC_DEFUN(
|
||||||
[CHECK_GNU_MAKE], [ AC_CACHE_CHECK( for GNU make,_cv_gnu_make_command,
|
[CHECK_GNU_MAKE], [ AC_CACHE_CHECK( for GNU make,_cv_gnu_make_command,
|
||||||
_cv_gnu_make_command='' ;
|
_cv_gnu_make_command='' ;
|
||||||
dnl Search all the common names for GNU make
|
dnl Search all the common names for GNU make
|
||||||
for a in "$MAKE" make gmake gnumake ; do
|
if test -n "$FORCE_NATIVE_MAKE" ; then
|
||||||
|
MAKES="make"
|
||||||
|
else
|
||||||
|
MAKES="make gmake gnumake"
|
||||||
|
fi
|
||||||
|
for a in "$MAKE" $MAKES ; do
|
||||||
if test -z "$a" ; then continue ; fi ;
|
if test -z "$a" ; then continue ; fi ;
|
||||||
if ( sh -c "$a --version" 2> /dev/null | grep GNU 2>&1 > /dev/null ) ; then
|
if ( sh -c "$a --version" 2> /dev/null | grep GNU 2>&1 > /dev/null ) ; then
|
||||||
_cv_gnu_make_command=$a ;
|
_cv_gnu_make_command=$a ;
|
||||||
|
|
|
@ -11515,7 +11515,12 @@ if ${_cv_gnu_make_command+:} false; then :
|
||||||
$as_echo_n "(cached) " >&6
|
$as_echo_n "(cached) " >&6
|
||||||
else
|
else
|
||||||
_cv_gnu_make_command='' ;
|
_cv_gnu_make_command='' ;
|
||||||
for a in "$MAKE" make gmake gnumake ; do
|
if test -n "$FORCE_NATIVE_MAKE" ; then
|
||||||
|
MAKES="make"
|
||||||
|
else
|
||||||
|
MAKES="make gmake gnumake"
|
||||||
|
fi
|
||||||
|
for a in "$MAKE" $MAKES ; do
|
||||||
if test -z "$a" ; then continue ; fi ;
|
if test -z "$a" ; then continue ; fi ;
|
||||||
if ( sh -c "$a --version" 2> /dev/null | grep GNU 2>&1 > /dev/null ) ; then
|
if ( sh -c "$a --version" 2> /dev/null | grep GNU 2>&1 > /dev/null ) ; then
|
||||||
_cv_gnu_make_command=$a ;
|
_cv_gnu_make_command=$a ;
|
||||||
|
|
|
@ -1,3 +1,13 @@
|
||||||
|
e2fsprogs (1.43.3-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Fix e2fsck's handling of timestamps on 32-bit system (Closes: #836559)
|
||||||
|
* E2fsck will sanity check and repair the extra isize fields in inodes
|
||||||
|
and the superblock.
|
||||||
|
* Fix sparc64 crashes when dereferencing unaligned integers in journal
|
||||||
|
blocks when metdata checksums are enabled.
|
||||||
|
|
||||||
|
-- Theodore Y. Ts'o <tytso@mit.edu> Sun, 04 Sep 2016 20:41:21 -0400
|
||||||
|
|
||||||
e2fsprogs (1.43.2-2) unstable; urgency=medium
|
e2fsprogs (1.43.2-2) unstable; urgency=medium
|
||||||
|
|
||||||
* Fix build reproducibility problems
|
* Fix build reproducibility problems
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
Description: Enable metadata_csum by default
|
|
||||||
For debian testing let's be more aggressive about testing the
|
|
||||||
metadata_csum feature.
|
|
||||||
From: Theodore Y. Ts'o <tytso@mit.edu>
|
|
||||||
|
|
||||||
--- e2fsprogs-1.43.orig/misc/mke2fs.conf.in
|
|
||||||
+++ e2fsprogs-1.43/misc/mke2fs.conf.in
|
|
||||||
@@ -11,11 +11,11 @@
|
|
||||||
features = has_journal
|
|
||||||
}
|
|
||||||
ext4 = {
|
|
||||||
- features = has_journal,extent,huge_file,flex_bg,64bit,dir_nlink,extra_isize
|
|
||||||
+ features = has_journal,extent,huge_file,flex_bg,metadata_csum,64bit,dir_nlink,extra_isize
|
|
||||||
inode_size = 256
|
|
||||||
}
|
|
||||||
ext4dev = {
|
|
||||||
- features = has_journal,extent,huge_file,flex_bg,inline_data,64bit,dir_nlink,extra_isize
|
|
||||||
+ features = has_journal,extent,huge_file,flex_bg,metadata_csum,inline_data,64bit,dir_nlink,extra_isize
|
|
||||||
inode_size = 256
|
|
||||||
options = test_fs=1
|
|
||||||
}
|
|
|
@ -1,262 +0,0 @@
|
||||||
Description: Fix build reproducibility for mk_cmds and compile_et
|
|
||||||
The mk_cmds and compile_et scripts include the build directory, which
|
|
||||||
breaks the build reproducibility goal of Debian.
|
|
||||||
From: Theodore Ts'o <tytso@mit.edu>
|
|
||||||
|
|
||||||
diff --git a/configure b/configure
|
|
||||||
index 03e24d1..0ac5dcb 100755
|
|
||||||
--- a/configure
|
|
||||||
+++ b/configure
|
|
||||||
@@ -633,8 +633,6 @@ BUILD_CFLAGS
|
|
||||||
MKINSTALLDIRS
|
|
||||||
INCLUDES
|
|
||||||
DO_TEST_SUITE
|
|
||||||
-ET_DIR
|
|
||||||
-SS_DIR
|
|
||||||
LDFLAGS_STATIC
|
|
||||||
root_sysconfdir
|
|
||||||
root_libdir
|
|
||||||
@@ -13805,10 +13803,6 @@ $as_echo "#define _INTL_REDIRECT_MACROS 1" >>confdefs.h
|
|
||||||
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
-SS_DIR=`cd ${srcdir}/lib/ss; pwd`
|
|
||||||
-ET_DIR=`cd ${srcdir}/lib/et; pwd`
|
|
||||||
-
|
|
||||||
-
|
|
||||||
if test "$cross_compiling" = yes ; then
|
|
||||||
DO_TEST_SUITE=
|
|
||||||
else
|
|
||||||
diff --git a/configure.ac b/configure.ac
|
|
||||||
index a387dfd..1c73301 100644
|
|
||||||
--- a/configure.ac
|
|
||||||
+++ b/configure.ac
|
|
||||||
@@ -1400,13 +1400,6 @@ darwin*)
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
dnl
|
|
||||||
-dnl Make the ss and et directories work correctly.
|
|
||||||
-dnl
|
|
||||||
-SS_DIR=`cd ${srcdir}/lib/ss; pwd`
|
|
||||||
-ET_DIR=`cd ${srcdir}/lib/et; pwd`
|
|
||||||
-AC_SUBST(SS_DIR)
|
|
||||||
-AC_SUBST(ET_DIR)
|
|
||||||
-dnl
|
|
||||||
dnl Only try to run the test suite if we're not cross compiling.
|
|
||||||
dnl
|
|
||||||
if test "$cross_compiling" = yes ; then
|
|
||||||
diff --git a/debugfs/Makefile.in b/debugfs/Makefile.in
|
|
||||||
index c22b8c0..a3fe13e 100644
|
|
||||||
--- a/debugfs/Makefile.in
|
|
||||||
+++ b/debugfs/Makefile.in
|
|
||||||
@@ -14,7 +14,7 @@ INSTALL = @INSTALL@
|
|
||||||
PROGS= debugfs
|
|
||||||
MANPAGES= debugfs.8
|
|
||||||
|
|
||||||
-MK_CMDS= _SS_DIR_OVERRIDE=../lib/ss ../lib/ss/mk_cmds
|
|
||||||
+MK_CMDS= _SS_DIR_OVERRIDE=$(srcdir)/../lib/ss ../lib/ss/mk_cmds
|
|
||||||
|
|
||||||
DEBUG_OBJS= debug_cmds.o debugfs.o util.o ncheck.o icheck.o ls.o \
|
|
||||||
lsdel.o dump.o set_fields.o logdump.o htree.o unused.o e2freefrag.o \
|
|
||||||
diff --git a/e2fsck/Makefile.in b/e2fsck/Makefile.in
|
|
||||||
index 06d9f55..6f626f4 100644
|
|
||||||
--- a/e2fsck/Makefile.in
|
|
||||||
+++ b/e2fsck/Makefile.in
|
|
||||||
@@ -34,7 +34,7 @@ PROFILED_DEPLIBS= $(DEPPROFILED_LIBSUPPORT) $(PROFILED_LIBEXT2FS) \
|
|
||||||
$(DEPPROFILED_LIBCOM_ERR) $(DEPPROFILED_LIBBLKID) \
|
|
||||||
$(DEPPROFILED_LIBUUID) $(DEPPROFILED_LIBE2P)
|
|
||||||
|
|
||||||
-COMPILE_ET=$(top_builddir)/lib/et/compile_et --build-tree
|
|
||||||
+COMPILE_ET= _ET_DIR_OVERRIDE=$(srcdir)/../lib/et/et ../lib/et/compile_et
|
|
||||||
|
|
||||||
.c.o:
|
|
||||||
$(E) " CC $<"
|
|
||||||
diff --git a/lib/et/Makefile.in b/lib/et/Makefile.in
|
|
||||||
index cb75ab8..476f189 100644
|
|
||||||
--- a/lib/et/Makefile.in
|
|
||||||
+++ b/lib/et/Makefile.in
|
|
||||||
@@ -140,7 +140,7 @@ uninstall::
|
|
||||||
check:: compile_et
|
|
||||||
for i in $(srcdir)/test_cases/*.et ; do \
|
|
||||||
t=`basename $$i | sed -e 's/.et//'`; \
|
|
||||||
- ./compile_et --build-tree $$i ; \
|
|
||||||
+ _ET_DIR_OVERRIDE=$(srcdir) ./compile_et $$i ; \
|
|
||||||
diff -c $(srcdir)/test_cases/$$t.c $$t.c > $$t.failed; \
|
|
||||||
if [ $$? -ne 0 ]; then echo Test case $$t failed; exit 1 ; fi ; \
|
|
||||||
diff -c $(srcdir)/test_cases/$$t.h $$t.h >> $$t.failed; \
|
|
||||||
diff --git a/lib/et/compile_et.sh.in b/lib/et/compile_et.sh.in
|
|
||||||
index c2861f4..4c4ba17 100644
|
|
||||||
--- a/lib/et/compile_et.sh.in
|
|
||||||
+++ b/lib/et/compile_et.sh.in
|
|
||||||
@@ -4,8 +4,7 @@
|
|
||||||
|
|
||||||
datarootdir=@datarootdir@
|
|
||||||
AWK=@AWK@
|
|
||||||
-DIR="${DIR-@datadir@/et}"
|
|
||||||
-ET_DIR="${ET_DIR-@ET_DIR@}"
|
|
||||||
+DIR=@datadir@/et
|
|
||||||
|
|
||||||
if test "$1" = "--build-tree" ; then
|
|
||||||
shift;
|
|
||||||
@@ -29,13 +28,13 @@ do
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
+if test -n "$_ET_DIR_OVERRIDE" ; then
|
|
||||||
+ DIR="$_ET_DIR_OVERRIDE";
|
|
||||||
+fi
|
|
||||||
+
|
|
||||||
if test ! -f "$DIR/et_h.awk" || test ! -f "$DIR/et_c.awk" ; then
|
|
||||||
- DIR="$ET_DIR"
|
|
||||||
-# echo "Falling back to $DIR..."
|
|
||||||
- if test ! -f "$DIR/et_h.awk" || test ! -f "$DIR/et_c.awk" ; then
|
|
||||||
- echo "compile_et: Couldn't find compile_et's template files."
|
|
||||||
- exit 1
|
|
||||||
- fi
|
|
||||||
+ echo "compile_et: Couldn't find compile_et's template files."
|
|
||||||
+ exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
ROOT=`echo $1 | sed -e s/.et$//`
|
|
||||||
diff --git a/lib/ext2fs/Makefile.in b/lib/ext2fs/Makefile.in
|
|
||||||
index 461920c..6a3656d 100644
|
|
||||||
--- a/lib/ext2fs/Makefile.in
|
|
||||||
+++ b/lib/ext2fs/Makefile.in
|
|
||||||
@@ -13,7 +13,8 @@ DEBUGFS_CFLAGS = -I$(srcdir)/../../e2fsck $(ALL_CFLAGS) -DDEBUGFS
|
|
||||||
|
|
||||||
@DEBUGFS_CMT@DEBUGFS_LIB_OBJS = bb_compat.o inode_io.o write_bb_file.o
|
|
||||||
|
|
||||||
-MK_CMDS= _SS_DIR_OVERRIDE=../ss ../ss/mk_cmds
|
|
||||||
+MK_CMDS= _SS_DIR_OVERRIDE=$(srcdir)/../ss ../ss/mk_cmds
|
|
||||||
+COMPILE_ET= _ET_DIR_OVERRIDE=$(srcdir)/../et ../et/compile_et
|
|
||||||
|
|
||||||
@RESIZER_CMT@RESIZE_LIB_OBJS = dupfs.o
|
|
||||||
@TEST_IO_CMT@TEST_IO_LIB_OBJS = test_io.o
|
|
||||||
@@ -254,8 +255,6 @@ all:: ext2fs.pc
|
|
||||||
@ELF_CMT@ $(Q) $(CC) $(ALL_CFLAGS_SHLIB) -fPIC -shared -o elfshared/$*.o -c $<
|
|
||||||
@BSDLIB_CMT@ $(Q) $(CC) $(ALL_CFLAGS_SHLIB) $(BSDLIB_PIC_FLAG) -o pic/$*.o -c $<
|
|
||||||
|
|
||||||
-COMPILE_ET=../et/compile_et --build-tree
|
|
||||||
-
|
|
||||||
DISTFILES= Makefile *.c *.h image
|
|
||||||
|
|
||||||
ext2_err.et: $(DEP_SUBSTITUTE) $(srcdir)/ext2_err.et.in
|
|
||||||
diff --git a/lib/ss/Makefile.in b/lib/ss/Makefile.in
|
|
||||||
index 255b58b..f4953f0 100644
|
|
||||||
--- a/lib/ss/Makefile.in
|
|
||||||
+++ b/lib/ss/Makefile.in
|
|
||||||
@@ -28,8 +28,8 @@ BSDLIB_MYDIR = ss
|
|
||||||
BSDLIB_INSTALL_DIR = $(root_libdir)
|
|
||||||
|
|
||||||
TAGS=etags
|
|
||||||
-COMPILE_ET=../et/compile_et --build-tree
|
|
||||||
-MK_CMDS=_SS_DIR_OVERRIDE=. ./mk_cmds
|
|
||||||
+MK_CMDS= _SS_DIR_OVERRIDE=$(srcdir) ./mk_cmds
|
|
||||||
+COMPILE_ET= _ET_DIR_OVERRIDE=$(srcdir)/../et ../et/compile_et
|
|
||||||
|
|
||||||
.c.o:
|
|
||||||
$(E) " CC $<"
|
|
||||||
diff --git a/lib/ss/mk_cmds.sh.in b/lib/ss/mk_cmds.sh.in
|
|
||||||
index a8976a4..0abc19d 100644
|
|
||||||
--- a/lib/ss/mk_cmds.sh.in
|
|
||||||
+++ b/lib/ss/mk_cmds.sh.in
|
|
||||||
@@ -3,8 +3,7 @@
|
|
||||||
#
|
|
||||||
|
|
||||||
datarootdir=@datarootdir@
|
|
||||||
-DIR="${DIR-@datadir@/ss}"
|
|
||||||
-SS_DIR="@SS_DIR@"
|
|
||||||
+DIR=@datadir@/ss
|
|
||||||
AWK=@AWK@
|
|
||||||
SED=@SED@
|
|
||||||
|
|
||||||
@@ -30,12 +29,8 @@ if test -n "$_SS_DIR_OVERRIDE" ; then
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test ! -f $DIR/ct_c.sed || test ! -f $DIR/ct_c.awk ; then
|
|
||||||
- DIR="$SS_DIR"
|
|
||||||
-# echo "Falling back to $DIR..."
|
|
||||||
- if test ! -f "$DIR/ct_c.sed" || test ! -f "$DIR/ct_c.awk" ; then
|
|
||||||
- echo "mk_cmds: Couldn't find mk_cmds's template files."
|
|
||||||
- exit 1
|
|
||||||
- fi
|
|
||||||
+ echo "mk_cmds: Couldn't find mk_cmds's template files."
|
|
||||||
+ exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
FILE="$1"
|
|
||||||
diff --git a/lib/support/Makefile.in b/lib/support/Makefile.in
|
|
||||||
index 5beaaac..112ba24 100644
|
|
||||||
--- a/lib/support/Makefile.in
|
|
||||||
+++ b/lib/support/Makefile.in
|
|
||||||
@@ -41,7 +41,7 @@ LIBDIR= support
|
|
||||||
@MAKEFILE_LIBRARY@
|
|
||||||
@MAKEFILE_PROFILE@
|
|
||||||
|
|
||||||
-COMPILE_ET=$(top_builddir)/lib/et/compile_et --build-tree
|
|
||||||
+COMPILE_ET= _ET_DIR_OVERRIDE=$(srcdir)/../et ../et/compile_et
|
|
||||||
|
|
||||||
.c.o:
|
|
||||||
$(E) " CC $<"
|
|
||||||
diff --git a/misc/Makefile.in b/misc/Makefile.in
|
|
||||||
index e487692..d6436c2 100644
|
|
||||||
--- a/misc/Makefile.in
|
|
||||||
+++ b/misc/Makefile.in
|
|
||||||
@@ -115,7 +115,7 @@ STATIC_DEPLIBS= $(DEPLIBSUPPORT) $(STATIC_LIBEXT2FS) $(DEPSTATIC_LIBCOM_ERR)
|
|
||||||
LIBS_E2P= $(LIBE2P) $(LIBCOM_ERR)
|
|
||||||
DEPLIBS_E2P= $(LIBE2P) $(DEPLIBCOM_ERR)
|
|
||||||
|
|
||||||
-COMPILE_ET=$(top_builddir)/lib/et/compile_et --build-tree
|
|
||||||
+COMPILE_ET= _ET_DIR_OVERRIDE=$(srcdir)/../lib/et/et ../lib/et/compile_et
|
|
||||||
|
|
||||||
# This nastyness is needed because of jfs_user.h hackery; when we finally
|
|
||||||
# clean up this mess, we should be able to drop it
|
|
||||||
diff --git a/tests/progs/Makefile.in b/tests/progs/Makefile.in
|
|
||||||
index 22d9417..f6a31b9 100644
|
|
||||||
--- a/tests/progs/Makefile.in
|
|
||||||
+++ b/tests/progs/Makefile.in
|
|
||||||
@@ -11,7 +11,7 @@ INSTALL = @INSTALL@
|
|
||||||
|
|
||||||
@MCONFIG@
|
|
||||||
|
|
||||||
-MK_CMDS= _SS_DIR_OVERRIDE=../../lib/ss ../../lib/ss/mk_cmds
|
|
||||||
+MK_CMDS= _SS_DIR_OVERRIDE=$(srcdir)/../../lib/ss ../../lib/ss/mk_cmds
|
|
||||||
|
|
||||||
PROGS= test_icount crcsum
|
|
||||||
|
|
||||||
diff --git a/util/gen-android-files b/util/gen-android-files
|
|
||||||
index 994337b..ebd8778 100755
|
|
||||||
--- a/util/gen-android-files
|
|
||||||
+++ b/util/gen-android-files
|
|
||||||
@@ -14,8 +14,8 @@ ANDROID_GENERATED_FILES="lib/ext2fs/ext2_err.c lib/ext2fs/ext2_err.h \
|
|
||||||
SS_DIR=$(pwd)/lib/ss
|
|
||||||
MK_CMDS=/tmp/mk_cmds$$.sh
|
|
||||||
|
|
||||||
-sed -e "s;@SS_DIR@;$SS_DIR;" < $SS_DIR/mk_cmds.sh.in \
|
|
||||||
- | sed -e "s/@AWK@/awk/" | sed -e "s/@SED@/sed/" > $MK_CMDS
|
|
||||||
+sed -e "s/@AWK@/awk/" < $SS_DIR/mk_cmds.sh.in \
|
|
||||||
+ | sed -e "s/@SED@/sed/" > $MK_CMDS
|
|
||||||
|
|
||||||
sed -e "s/@E2FSPROGS_VERSION@/$(git describe)/" < lib/ext2fs/ext2_err.et.in > lib/ext2fs/ext2_err.et
|
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ done
|
|
||||||
for i in lib/ss/std_rqs debugfs/debug_cmds debugfs/ro_debug_cmds \
|
|
||||||
debugfs/extent_cmds
|
|
||||||
do
|
|
||||||
- /bin/sh $MK_CMDS $i.ct
|
|
||||||
+ _SS_DIR_OVERRIDE=lib/ss /bin/sh $MK_CMDS $i.ct
|
|
||||||
mv -f $(basename $i).c $i.c
|
|
||||||
done
|
|
||||||
|
|
||||||
diff --git a/util/subst.conf.in b/util/subst.conf.in
|
|
||||||
index ada11e7..fbc044d 100644
|
|
||||||
--- a/util/subst.conf.in
|
|
||||||
+++ b/util/subst.conf.in
|
|
||||||
@@ -1,7 +1,5 @@
|
|
||||||
AWK @AWK@
|
|
||||||
SED @SED@
|
|
||||||
-ET_DIR @ET_DIR@
|
|
||||||
-SS_DIR @SS_DIR@
|
|
||||||
E2FSPROGS_MONTH @E2FSPROGS_MONTH@
|
|
||||||
E2FSPROGS_YEAR @E2FSPROGS_YEAR@
|
|
||||||
E2FSPROGS_VERSION @E2FSPROGS_VERSION@
|
|
|
@ -1,2 +0,0 @@
|
||||||
enable-metadata_csum-by-default
|
|
||||||
fix-build-reproducibility-in-mk_cmds-and-compile_et
|
|
|
@ -1,7 +1,7 @@
|
||||||
\input texinfo @c -*-texinfo-*-
|
\input texinfo @c -*-texinfo-*-
|
||||||
@c %**start of header
|
@c %**start of header
|
||||||
@setfilename libext2fs.info
|
@setfilename libext2fs.info
|
||||||
@settitle The EXT2FS Library (version 1.43.2)
|
@settitle The EXT2FS Library (version 1.43.3)
|
||||||
@synindex tp fn
|
@synindex tp fn
|
||||||
@comment %**end of header
|
@comment %**end of header
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ by the author.
|
||||||
|
|
||||||
@title The EXT2FS Library
|
@title The EXT2FS Library
|
||||||
@subtitle The EXT2FS Library
|
@subtitle The EXT2FS Library
|
||||||
@subtitle Version 1.43.2
|
@subtitle Version 1.43.3
|
||||||
@subtitle September 2016
|
@subtitle September 2016
|
||||||
|
|
||||||
@author by Theodore Ts'o
|
@author by Theodore Ts'o
|
||||||
|
@ -101,7 +101,7 @@ by the Foundation.
|
||||||
|
|
||||||
@top The EXT2FS Library
|
@top The EXT2FS Library
|
||||||
|
|
||||||
This manual documents the EXT2FS Library, version 1.43.2.
|
This manual documents the EXT2FS Library, version 1.43.3.
|
||||||
|
|
||||||
@menu
|
@menu
|
||||||
* Introduction to the EXT2FS Library::
|
* Introduction to the EXT2FS Library::
|
||||||
|
|
|
@ -345,6 +345,12 @@ or
|
||||||
.B \-p
|
.B \-p
|
||||||
options.
|
options.
|
||||||
.TP
|
.TP
|
||||||
|
.BI \-T " patch_file"
|
||||||
|
Do not apply changes to the real filesystem; write updates into a sparse file
|
||||||
|
named 'patch_file' to safely apply them later with e2patch(8) utility.
|
||||||
|
You'll also be able to create a backup before applying patch and safely
|
||||||
|
restore it in case of power outage or system crash.
|
||||||
|
.TP
|
||||||
.BI \-z " undo_file"
|
.BI \-z " undo_file"
|
||||||
Before overwriting a file system block, write the old contents of the block to
|
Before overwriting a file system block, write the old contents of the block to
|
||||||
an undo file. This undo file can be used with e2undo(8) to restore the old
|
an undo file. This undo file can be used with e2undo(8) to restore the old
|
||||||
|
|
|
@ -391,6 +391,9 @@ struct e2fsck_struct {
|
||||||
*/
|
*/
|
||||||
ext2fs_inode_bitmap inodes_to_rebuild;
|
ext2fs_inode_bitmap inodes_to_rebuild;
|
||||||
|
|
||||||
|
/* Patch file */
|
||||||
|
char *patch_file;
|
||||||
|
|
||||||
/* Undo file */
|
/* Undo file */
|
||||||
char *undo_file;
|
char *undo_file;
|
||||||
};
|
};
|
||||||
|
|
|
@ -488,10 +488,14 @@ static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
|
||||||
* implementations should never allow i_extra_isize to be 0
|
* implementations should never allow i_extra_isize to be 0
|
||||||
*/
|
*/
|
||||||
if (inode->i_extra_isize &&
|
if (inode->i_extra_isize &&
|
||||||
(inode->i_extra_isize < min || inode->i_extra_isize > max)) {
|
(inode->i_extra_isize < min || inode->i_extra_isize > max ||
|
||||||
|
inode->i_extra_isize & 3)) {
|
||||||
if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
|
if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
|
||||||
return;
|
return;
|
||||||
inode->i_extra_isize = min;
|
if (inode->i_extra_isize < min || inode->i_extra_isize > max)
|
||||||
|
inode->i_extra_isize = sb->s_want_extra_isize;
|
||||||
|
else
|
||||||
|
inode->i_extra_isize = (inode->i_extra_isize + 3) & ~3;
|
||||||
e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
|
e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
|
||||||
EXT2_INODE_SIZE(sb), "pass1");
|
EXT2_INODE_SIZE(sb), "pass1");
|
||||||
return;
|
return;
|
||||||
|
@ -512,9 +516,9 @@ static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
|
||||||
* If the inode's extended atime (ctime, crtime, mtime) is stored in
|
* If the inode's extended atime (ctime, crtime, mtime) is stored in
|
||||||
* the old, invalid format, repair it.
|
* the old, invalid format, repair it.
|
||||||
*/
|
*/
|
||||||
if ((sizeof(time_t) <= 4) ||
|
if (((sizeof(time_t) <= 4) ||
|
||||||
(((sizeof(time_t) > 4) &&
|
(((sizeof(time_t) > 4) &&
|
||||||
ctx->now < EXT4_EXTRA_NEGATIVE_DATE_CUTOFF)) &&
|
ctx->now < EXT4_EXTRA_NEGATIVE_DATE_CUTOFF))) &&
|
||||||
(CHECK_INODE_EXTRA_NEGATIVE_EPOCH(inode, atime) ||
|
(CHECK_INODE_EXTRA_NEGATIVE_EPOCH(inode, atime) ||
|
||||||
CHECK_INODE_EXTRA_NEGATIVE_EPOCH(inode, ctime) ||
|
CHECK_INODE_EXTRA_NEGATIVE_EPOCH(inode, ctime) ||
|
||||||
CHECK_INODE_EXTRA_NEGATIVE_EPOCH(inode, crtime) ||
|
CHECK_INODE_EXTRA_NEGATIVE_EPOCH(inode, crtime) ||
|
||||||
|
|
|
@ -477,6 +477,16 @@ static struct e2fsck_problem problem_table[] = {
|
||||||
N_("Error initializing quota context in support library: %m\n"),
|
N_("Error initializing quota context in support library: %m\n"),
|
||||||
PROMPT_NULL, PR_FATAL },
|
PROMPT_NULL, PR_FATAL },
|
||||||
|
|
||||||
|
/* Bad s_min_extra_isize in superblock */
|
||||||
|
{ PR_0_BAD_MIN_EXTRA_ISIZE,
|
||||||
|
N_("Bad required extra isize in @S (%N). "),
|
||||||
|
PROMPT_FIX, 0 },
|
||||||
|
|
||||||
|
/* Bad s_min_extra_isize in superblock */
|
||||||
|
{ PR_0_BAD_WANT_EXTRA_ISIZE,
|
||||||
|
N_("Bad desired extra isize in @S (%N). "),
|
||||||
|
PROMPT_FIX, 0 },
|
||||||
|
|
||||||
/* Pass 1 errors */
|
/* Pass 1 errors */
|
||||||
|
|
||||||
/* Pass 1: Checking inodes, blocks, and sizes */
|
/* Pass 1: Checking inodes, blocks, and sizes */
|
||||||
|
|
|
@ -274,6 +274,12 @@ struct problem_context {
|
||||||
/* Error initializing quota context */
|
/* Error initializing quota context */
|
||||||
#define PR_0_QUOTA_INIT_CTX 0x00004C
|
#define PR_0_QUOTA_INIT_CTX 0x00004C
|
||||||
|
|
||||||
|
/* Bad s_min_extra_isize in superblock */
|
||||||
|
#define PR_0_BAD_MIN_EXTRA_ISIZE 0x00004D
|
||||||
|
|
||||||
|
/* Bad s_want_extra_isize in superblock */
|
||||||
|
#define PR_0_BAD_WANT_EXTRA_ISIZE 0x00004E
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pass 1 errors
|
* Pass 1 errors
|
||||||
|
|
|
@ -338,12 +338,24 @@ int journal_skip_recovery(journal_t *journal)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline __u32 get_be32(__be32 *p)
|
||||||
|
{
|
||||||
|
unsigned char *cp = (unsigned char *) p;
|
||||||
|
__u32 ret;
|
||||||
|
|
||||||
|
ret = *cp++;
|
||||||
|
ret = (ret << 8) + *cp++;
|
||||||
|
ret = (ret << 8) + *cp++;
|
||||||
|
ret = (ret << 8) + *cp++;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static inline unsigned long long read_tag_block(journal_t *journal,
|
static inline unsigned long long read_tag_block(journal_t *journal,
|
||||||
journal_block_tag_t *tag)
|
journal_block_tag_t *tag)
|
||||||
{
|
{
|
||||||
unsigned long long block = ext2fs_be32_to_cpu(tag->t_blocknr);
|
unsigned long long block = get_be32(&tag->t_blocknr);
|
||||||
if (jfs_has_feature_64bit(journal))
|
if (jfs_has_feature_64bit(journal))
|
||||||
block |= (u64)ext2fs_be32_to_cpu(tag->t_blocknr_high) << 32;
|
block |= (u64)get_be32(&tag->t_blocknr_high) << 32;
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -578,6 +578,34 @@ void check_super_block(e2fsck_t ctx)
|
||||||
ext2fs_mark_super_dirty(fs);
|
ext2fs_mark_super_dirty(fs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (EXT2_INODE_SIZE(sb) > EXT2_GOOD_OLD_INODE_SIZE) {
|
||||||
|
unsigned min =
|
||||||
|
sizeof(((struct ext2_inode_large *) 0)->i_extra_isize) +
|
||||||
|
sizeof(((struct ext2_inode_large *) 0)->i_checksum_hi);
|
||||||
|
unsigned max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE;
|
||||||
|
pctx.num = sb->s_min_extra_isize;
|
||||||
|
if (sb->s_min_extra_isize &&
|
||||||
|
(sb->s_min_extra_isize < min ||
|
||||||
|
sb->s_min_extra_isize > max ||
|
||||||
|
sb->s_min_extra_isize & 3) &&
|
||||||
|
fix_problem(ctx, PR_0_BAD_MIN_EXTRA_ISIZE, &pctx)) {
|
||||||
|
sb->s_min_extra_isize =
|
||||||
|
(sizeof(struct ext2_inode_large) -
|
||||||
|
EXT2_GOOD_OLD_INODE_SIZE);
|
||||||
|
ext2fs_mark_super_dirty(fs);
|
||||||
|
}
|
||||||
|
pctx.num = sb->s_want_extra_isize;
|
||||||
|
if (sb->s_want_extra_isize &&
|
||||||
|
(sb->s_want_extra_isize < min ||
|
||||||
|
sb->s_want_extra_isize > max ||
|
||||||
|
sb->s_want_extra_isize & 3) &&
|
||||||
|
fix_problem(ctx, PR_0_BAD_WANT_EXTRA_ISIZE, &pctx)) {
|
||||||
|
sb->s_want_extra_isize =
|
||||||
|
(sizeof(struct ext2_inode_large) -
|
||||||
|
EXT2_GOOD_OLD_INODE_SIZE);
|
||||||
|
ext2fs_mark_super_dirty(fs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Are metadata_csum and uninit_bg both set? */
|
/* Are metadata_csum and uninit_bg both set? */
|
||||||
if (ext2fs_has_feature_metadata_csum(fs->super) &&
|
if (ext2fs_has_feature_metadata_csum(fs->super) &&
|
||||||
|
|
|
@ -76,7 +76,7 @@ static void usage(e2fsck_t ctx)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
_("Usage: %s [-panyrcdfktvDFV] [-b superblock] [-B blocksize]\n"
|
_("Usage: %s [-panyrcdfktvDFV] [-b superblock] [-B blocksize]\n"
|
||||||
"\t\t[-l|-L bad_blocks_file] [-C fd] [-j external_journal]\n"
|
"\t\t[-l|-L bad_blocks_file] [-C fd] [-j external_journal]\n"
|
||||||
"\t\t[-E extended-options] [-z undo_file] device\n"),
|
"\t\t[-E extended-options] [-T patch_file] [-z undo_file] device\n"),
|
||||||
ctx->program_name);
|
ctx->program_name);
|
||||||
|
|
||||||
fprintf(stderr, "%s", _("\nEmergency help:\n"
|
fprintf(stderr, "%s", _("\nEmergency help:\n"
|
||||||
|
@ -92,6 +92,7 @@ static void usage(e2fsck_t ctx)
|
||||||
" -j external_journal Set location of the external journal\n"
|
" -j external_journal Set location of the external journal\n"
|
||||||
" -l bad_blocks_file Add to badblocks list\n"
|
" -l bad_blocks_file Add to badblocks list\n"
|
||||||
" -L bad_blocks_file Set badblocks list\n"
|
" -L bad_blocks_file Set badblocks list\n"
|
||||||
|
" -T patch_file Create a patch file instead of applying changes to real FS\n"
|
||||||
" -z undo_file Create an undo file\n"
|
" -z undo_file Create an undo file\n"
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -804,7 +805,7 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
|
||||||
|
|
||||||
phys_mem_kb = get_memory_size() / 1024;
|
phys_mem_kb = get_memory_size() / 1024;
|
||||||
ctx->readahead_kb = ~0ULL;
|
ctx->readahead_kb = ~0ULL;
|
||||||
while ((c = getopt(argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDkz:")) != EOF)
|
while ((c = getopt(argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDkT:z:")) != EOF)
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'C':
|
case 'C':
|
||||||
ctx->progress = e2fsck_update_progress;
|
ctx->progress = e2fsck_update_progress;
|
||||||
|
@ -936,6 +937,9 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
|
||||||
case 'k':
|
case 'k':
|
||||||
keep_bad_blocks++;
|
keep_bad_blocks++;
|
||||||
break;
|
break;
|
||||||
|
case 'T':
|
||||||
|
ctx->patch_file = optarg;
|
||||||
|
break;
|
||||||
case 'z':
|
case 'z':
|
||||||
ctx->undo_file = optarg;
|
ctx->undo_file = optarg;
|
||||||
break;
|
break;
|
||||||
|
@ -1233,6 +1237,19 @@ check_error:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int e2fsck_setup_patch(e2fsck_t ctx, io_manager *io_ptr)
|
||||||
|
{
|
||||||
|
set_patch_io_backing_manager(*io_ptr);
|
||||||
|
set_patch_io_patch_file(ctx->patch_file);
|
||||||
|
*io_ptr = patch_io_manager;
|
||||||
|
printf(_("To make backup before applying changes run:\n"
|
||||||
|
" e2patch backup %s %s %s.backup\n"
|
||||||
|
"Then, to apply the operation to the real filesystem run:\n"
|
||||||
|
" e2patch apply %s %s\n"),
|
||||||
|
ctx->device_name, ctx->patch_file, ctx->patch_file, ctx->device_name, ctx->patch_file);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int e2fsck_setup_tdb(e2fsck_t ctx, io_manager *io_ptr)
|
static int e2fsck_setup_tdb(e2fsck_t ctx, io_manager *io_ptr)
|
||||||
{
|
{
|
||||||
errcode_t retval = ENOMEM;
|
errcode_t retval = ENOMEM;
|
||||||
|
@ -1430,7 +1447,11 @@ restart:
|
||||||
flags &= ~EXT2_FLAG_EXCLUSIVE;
|
flags &= ~EXT2_FLAG_EXCLUSIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->undo_file) {
|
if (ctx->patch_file) {
|
||||||
|
retval = e2fsck_setup_patch(ctx, &io_ptr);
|
||||||
|
if (retval)
|
||||||
|
exit(FSCK_ERROR);
|
||||||
|
} else if (ctx->undo_file) {
|
||||||
retval = e2fsck_setup_tdb(ctx, &io_ptr);
|
retval = e2fsck_setup_tdb(ctx, &io_ptr);
|
||||||
if (retval)
|
if (retval)
|
||||||
exit(FSCK_ERROR);
|
exit(FSCK_ERROR);
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
Begin3
|
Begin3
|
||||||
Title: EXT2 Filesystem utilities
|
Title: EXT2 Filesystem utilities
|
||||||
Version: 1.43.2
|
Version: 1.43.3
|
||||||
Entered-date: 2016-09-01
|
Entered-date: 2016-09-04
|
||||||
Description: The filesystem utilities for the EXT2, EXT3, and EXT4
|
Description: The filesystem utilities for the EXT2, EXT3, and EXT4
|
||||||
filesystems, including e2fsck, mke2fs, dumpe2fs, and others.
|
filesystems, including e2fsck, mke2fs, dumpe2fs, and others.
|
||||||
Keywords: utilities, filesystem, Ext2fs, ext3, ext4
|
Keywords: utilities, filesystem, Ext2fs, ext3, ext4
|
||||||
Author: tytso@mit.edu (Theodore Tso)
|
Author: tytso@mit.edu (Theodore Tso)
|
||||||
Maintained-by: tytso@mit.edu (Theodore Tso)
|
Maintained-by: tytso@mit.edu (Theodore Tso)
|
||||||
Primary-site: ftp.kernel.org /pub/linux/kernel/people/tytso/e2fsprogs
|
Primary-site: ftp.kernel.org /pub/linux/kernel/people/tytso/e2fsprogs
|
||||||
7224kB e2fsprogs-1.43.2.tar.gz
|
7224kB e2fsprogs-1.43.3.tar.gz
|
||||||
644kB e2fsprogs-libs-1.43.2.tar.gz
|
644kB e2fsprogs-libs-1.43.3.tar.gz
|
||||||
1kB e2fsprogs-1.43.2.lsm
|
1kB e2fsprogs-1.43.3.lsm
|
||||||
Alternate-site: download.sourceforge.net /pub/sourceforge/e2fsprogs
|
Alternate-site: download.sourceforge.net /pub/sourceforge/e2fsprogs
|
||||||
Platforms: linux 1.2.x/1.3.x/2.0.x/2.1.x/2.2.x/2.3.x/2.4.x/2.5.x/2.6.x/3.x/4.x
|
Platforms: linux 1.2.x/1.3.x/2.0.x/2.1.x/2.2.x/2.3.x/2.4.x/2.5.x/2.6.x/3.x/4.x
|
||||||
Copying-policy: GPL-2/LGPL-2
|
Copying-policy: GPL-2/LGPL-2
|
||||||
|
|
|
@ -117,6 +117,7 @@ exit 0
|
||||||
%{_root_sbindir}/e2image
|
%{_root_sbindir}/e2image
|
||||||
%{_root_sbindir}/e2label
|
%{_root_sbindir}/e2label
|
||||||
%{_root_sbindir}/e2undo
|
%{_root_sbindir}/e2undo
|
||||||
|
%{_root_sbindir}/e2patch
|
||||||
%{_root_sbindir}/findfs
|
%{_root_sbindir}/findfs
|
||||||
%{_root_sbindir}/fsck
|
%{_root_sbindir}/fsck
|
||||||
%{_root_sbindir}/fsck.ext2
|
%{_root_sbindir}/fsck.ext2
|
||||||
|
@ -168,6 +169,7 @@ exit 0
|
||||||
%{_mandir}/man8/e2image.8*
|
%{_mandir}/man8/e2image.8*
|
||||||
%{_mandir}/man8/e2label.8*
|
%{_mandir}/man8/e2label.8*
|
||||||
%{_mandir}/man8/e2undo.8*
|
%{_mandir}/man8/e2undo.8*
|
||||||
|
%{_mandir}/man8/e2patch.8*
|
||||||
%{_mandir}/man8/fsck.8*
|
%{_mandir}/man8/fsck.8*
|
||||||
%{_mandir}/man8/logsave.8*
|
%{_mandir}/man8/logsave.8*
|
||||||
%{_mandir}/man8/mke2fs.8*
|
%{_mandir}/man8/mke2fs.8*
|
||||||
|
|
|
@ -75,6 +75,8 @@ libext2fs_src_files := \
|
||||||
swapfs.c \
|
swapfs.c \
|
||||||
symlink.c \
|
symlink.c \
|
||||||
undo_io.c \
|
undo_io.c \
|
||||||
|
patch.c \
|
||||||
|
patch_io.c \
|
||||||
unix_io.c \
|
unix_io.c \
|
||||||
unlink.c \
|
unlink.c \
|
||||||
valid_blk.c \
|
valid_blk.c \
|
||||||
|
|
|
@ -124,6 +124,8 @@ OBJS= $(DEBUGFS_LIB_OBJS) $(RESIZE_LIB_OBJS) $(E2IMAGE_LIB_OBJS) \
|
||||||
symlink.o \
|
symlink.o \
|
||||||
$(TDB_OBJ) \
|
$(TDB_OBJ) \
|
||||||
undo_io.o \
|
undo_io.o \
|
||||||
|
patch.o \
|
||||||
|
patch_io.o \
|
||||||
unix_io.o \
|
unix_io.o \
|
||||||
unlink.o \
|
unlink.o \
|
||||||
valid_blk.o \
|
valid_blk.o \
|
||||||
|
@ -211,6 +213,8 @@ SRCS= ext2_err.c \
|
||||||
$(srcdir)/tst_getsize.c \
|
$(srcdir)/tst_getsize.c \
|
||||||
$(srcdir)/tst_iscan.c \
|
$(srcdir)/tst_iscan.c \
|
||||||
$(srcdir)/undo_io.c \
|
$(srcdir)/undo_io.c \
|
||||||
|
$(srcdir)/patch.c \
|
||||||
|
$(srcdir)/patch_io.c \
|
||||||
$(srcdir)/unix_io.c \
|
$(srcdir)/unix_io.c \
|
||||||
$(srcdir)/unlink.c \
|
$(srcdir)/unlink.c \
|
||||||
$(srcdir)/valid_blk.c \
|
$(srcdir)/valid_blk.c \
|
||||||
|
@ -1099,6 +1103,18 @@ undo_io.o: $(srcdir)/undo_io.c $(top_builddir)/lib/config.h \
|
||||||
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
|
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
|
||||||
$(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
|
$(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
|
||||||
$(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h $(srcdir)/ext2fsP.h
|
$(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h $(srcdir)/ext2fsP.h
|
||||||
|
patch.o: $(srcdir)/patch.c $(top_builddir)/lib/config.h \
|
||||||
|
$(top_builddir)/lib/dirpaths.h $(srcdir)/ext2_fs.h \
|
||||||
|
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
|
||||||
|
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
|
||||||
|
$(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
|
||||||
|
$(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h $(srcdir)/ext2fsP.h
|
||||||
|
patch_io.o: $(srcdir)/patch_io.c $(top_builddir)/lib/config.h \
|
||||||
|
$(top_builddir)/lib/dirpaths.h $(srcdir)/ext2_fs.h \
|
||||||
|
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
|
||||||
|
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
|
||||||
|
$(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
|
||||||
|
$(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h $(srcdir)/ext2fsP.h
|
||||||
unix_io.o: $(srcdir)/unix_io.c $(top_builddir)/lib/config.h \
|
unix_io.o: $(srcdir)/unix_io.c $(top_builddir)/lib/config.h \
|
||||||
$(top_builddir)/lib/dirpaths.h $(srcdir)/ext2_fs.h \
|
$(top_builddir)/lib/dirpaths.h $(srcdir)/ext2_fs.h \
|
||||||
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
|
$(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \
|
||||||
|
|
|
@ -185,8 +185,9 @@ struct ext2_group_desc *ext2fs_group_desc(ext2_filsys fs,
|
||||||
struct opaque_ext2_group_desc *gdp,
|
struct opaque_ext2_group_desc *gdp,
|
||||||
dgrp_t group)
|
dgrp_t group)
|
||||||
{
|
{
|
||||||
return (struct ext2_group_desc *)((char *)gdp +
|
int desc_size = EXT2_DESC_SIZE(fs->super) & ~7;
|
||||||
group * EXT2_DESC_SIZE(fs->super));
|
|
||||||
|
return (struct ext2_group_desc *)((char *)gdp + group * desc_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do the same but as an ext4 group desc for internal use here */
|
/* Do the same but as an ext4 group desc for internal use here */
|
||||||
|
|
|
@ -539,4 +539,7 @@ ec EXT2_ET_BAD_CRC,
|
||||||
ec EXT2_ET_CORRUPT_JOURNAL_SB,
|
ec EXT2_ET_CORRUPT_JOURNAL_SB,
|
||||||
"The journal superblock is corrupt"
|
"The journal superblock is corrupt"
|
||||||
|
|
||||||
|
ec EXT2_ET_INODE_CORRUPTED,
|
||||||
|
"Inode is corrupted"
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -145,6 +145,11 @@ extern io_manager undo_io_manager;
|
||||||
extern errcode_t set_undo_io_backing_manager(io_manager manager);
|
extern errcode_t set_undo_io_backing_manager(io_manager manager);
|
||||||
extern errcode_t set_undo_io_backup_file(char *file_name);
|
extern errcode_t set_undo_io_backup_file(char *file_name);
|
||||||
|
|
||||||
|
/* patch_io.c */
|
||||||
|
extern io_manager patch_io_manager;
|
||||||
|
extern errcode_t set_patch_io_backing_manager(io_manager manager);
|
||||||
|
extern errcode_t set_patch_io_patch_file(char *file_name);
|
||||||
|
|
||||||
/* test_io.c */
|
/* test_io.c */
|
||||||
extern io_manager test_io_manager, test_io_backing_manager;
|
extern io_manager test_io_manager, test_io_backing_manager;
|
||||||
extern void (*test_io_cb_read_blk)
|
extern void (*test_io_cb_read_blk)
|
||||||
|
|
|
@ -554,6 +554,10 @@ errcode_t ext2fs_xattrs_write(struct ext2_xattr_handle *handle)
|
||||||
memset(p + EXT2_GOOD_OLD_INODE_SIZE, 0, extra);
|
memset(p + EXT2_GOOD_OLD_INODE_SIZE, 0, extra);
|
||||||
inode->i_extra_isize = extra;
|
inode->i_extra_isize = extra;
|
||||||
}
|
}
|
||||||
|
if (inode->i_extra_isize & 3) {
|
||||||
|
err = EXT2_ET_INODE_CORRUPTED;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Force the inlinedata attr to the front and the empty entries
|
* Force the inlinedata attr to the front and the empty entries
|
||||||
|
@ -806,6 +810,10 @@ errcode_t ext2fs_xattrs_read(struct ext2_xattr_handle *handle)
|
||||||
inode->i_extra_isize +
|
inode->i_extra_isize +
|
||||||
sizeof(__u32))
|
sizeof(__u32))
|
||||||
goto read_ea_block;
|
goto read_ea_block;
|
||||||
|
if (inode->i_extra_isize & 3) {
|
||||||
|
err = EXT2_ET_INODE_CORRUPTED;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/* Look for EA in the inode */
|
/* Look for EA in the inode */
|
||||||
memcpy(&ea_inode_magic, ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
|
memcpy(&ea_inode_magic, ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
|
||||||
|
|
|
@ -0,0 +1,228 @@
|
||||||
|
/**
|
||||||
|
* patch.c --- Common "patch" file functions
|
||||||
|
*
|
||||||
|
* Copyright (c) Vitaliy Filippov <vitalif@mail.ru> 2014
|
||||||
|
* License: GNU GPLv2 or later
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define _LARGEFILE_SOURCE
|
||||||
|
#define _LARGEFILE64_SOURCE
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include "patch.h"
|
||||||
|
|
||||||
|
errcode_t ext2fs_patch_retry_read(int fd, ssize_t size, void *buf)
|
||||||
|
{
|
||||||
|
ssize_t r, done = 0;
|
||||||
|
while (done < size)
|
||||||
|
{
|
||||||
|
r = read(fd, buf+done, size-done);
|
||||||
|
if (!r || (r < 0 && errno != EAGAIN))
|
||||||
|
break;
|
||||||
|
done += r;
|
||||||
|
}
|
||||||
|
if (done < size)
|
||||||
|
return errno;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
errcode_t ext2fs_patch_retry_write(int fd, ssize_t size, const void *buf)
|
||||||
|
{
|
||||||
|
ssize_t r, done = 0;
|
||||||
|
while (done < size)
|
||||||
|
{
|
||||||
|
r = write(fd, buf+done, size-done);
|
||||||
|
if (r <= 0 && errno != EAGAIN)
|
||||||
|
break;
|
||||||
|
done += r;
|
||||||
|
}
|
||||||
|
if (done < size)
|
||||||
|
return errno;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
errcode_t ext2fs_patch_retry_read_at(int fd, unsigned long long offset, ssize_t size, void *buf)
|
||||||
|
{
|
||||||
|
if ((unsigned long long)ext2fs_llseek(fd, offset, SEEK_SET) != offset)
|
||||||
|
return errno ? errno : EXT2_ET_LLSEEK_FAILED;
|
||||||
|
return ext2fs_patch_retry_read(fd, size, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
errcode_t ext2fs_patch_retry_write_at(int fd, unsigned long long offset, ssize_t size, const void *buf)
|
||||||
|
{
|
||||||
|
if ((unsigned long long)ext2fs_llseek(fd, offset, SEEK_SET) != offset)
|
||||||
|
return errno ? errno : EXT2_ET_LLSEEK_FAILED;
|
||||||
|
return ext2fs_patch_retry_write(fd, size, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
errcode_t ext2fs_patch_read_bmap(struct ext2fs_patch_file *data)
|
||||||
|
{
|
||||||
|
errcode_t retval = 0;
|
||||||
|
int bufsize = 65536;
|
||||||
|
blk64_t i, r;
|
||||||
|
void *buf = malloc(bufsize);
|
||||||
|
if (!buf)
|
||||||
|
return ENOMEM;
|
||||||
|
ext2fs_llseek(data->patch_fd, data->block_size, SEEK_SET);
|
||||||
|
for (i = 0; i < data->size/8; )
|
||||||
|
{
|
||||||
|
r = bufsize;
|
||||||
|
if (data->size/8 - i < r)
|
||||||
|
r = data->size/8 - i;
|
||||||
|
retval = ext2fs_patch_retry_read(data->patch_fd, r, buf);
|
||||||
|
if (retval)
|
||||||
|
goto out;
|
||||||
|
ext2fs_set_generic_bmap_range(data->bmap, i*8, r*8, buf);
|
||||||
|
i += r;
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
free(buf);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
errcode_t ext2fs_patch_write_bmap(struct ext2fs_patch_file *data)
|
||||||
|
{
|
||||||
|
errcode_t retval = 0;
|
||||||
|
int bufsize = 65536;
|
||||||
|
blk64_t i, r;
|
||||||
|
struct patchbd_super s;
|
||||||
|
void *buf = malloc(bufsize);
|
||||||
|
if (!buf)
|
||||||
|
return ENOMEM;
|
||||||
|
ext2fs_llseek(data->patch_fd, data->block_size, SEEK_SET);
|
||||||
|
for (i = 0; i < data->size/8; )
|
||||||
|
{
|
||||||
|
r = bufsize;
|
||||||
|
if (data->size/8 - i < r)
|
||||||
|
r = data->size/8 - i;
|
||||||
|
ext2fs_get_generic_bmap_range(data->bmap, i*8, r*8, buf);
|
||||||
|
retval = ext2fs_patch_retry_write(data->patch_fd, r, buf);
|
||||||
|
if (retval)
|
||||||
|
goto out;
|
||||||
|
i += r;
|
||||||
|
}
|
||||||
|
ext2fs_llseek(data->patch_fd, 0, SEEK_SET);
|
||||||
|
s.magic = PATCHBD_MAGIC;
|
||||||
|
s.patch_block = data->block_size;
|
||||||
|
s.patch_size = data->size;
|
||||||
|
write(data->patch_fd, &s, sizeof(struct patchbd_super));
|
||||||
|
out:
|
||||||
|
free(buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
errcode_t ext2fs_patch_open(struct ext2fs_patch_file *data, char *patch_file, int flags)
|
||||||
|
{
|
||||||
|
errcode_t retval = 0;
|
||||||
|
ext2_loff_t size;
|
||||||
|
struct patchbd_super s;
|
||||||
|
data->block_size = 0;
|
||||||
|
data->size = 0;
|
||||||
|
data->offset = 0;
|
||||||
|
data->bmap = NULL;
|
||||||
|
data->patch_file = strdup(patch_file);
|
||||||
|
data->patch_fd = open(data->patch_file, flags|O_RDWR, 0666);
|
||||||
|
if (data->patch_fd < 0)
|
||||||
|
return errno;
|
||||||
|
size = ext2fs_llseek(data->patch_fd, 0, SEEK_END);
|
||||||
|
if (size < 0)
|
||||||
|
return errno;
|
||||||
|
if (size > 0)
|
||||||
|
{
|
||||||
|
size = ext2fs_llseek(data->patch_fd, 0, SEEK_SET);
|
||||||
|
read(data->patch_fd, &s, sizeof(struct patchbd_super));
|
||||||
|
if (s.magic != PATCHBD_MAGIC)
|
||||||
|
return 0;
|
||||||
|
data->block_size = s.patch_block;
|
||||||
|
// if (data->block_size != 4096)
|
||||||
|
// return EINVAL;
|
||||||
|
data->size = s.patch_size;
|
||||||
|
retval = ext2fs_patch_init_bmap(data, NULL);
|
||||||
|
if (retval)
|
||||||
|
return retval;
|
||||||
|
retval = ext2fs_patch_read_bmap(data);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
errcode_t ext2fs_patch_close(struct ext2fs_patch_file *data)
|
||||||
|
{
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
if (data->bmap)
|
||||||
|
{
|
||||||
|
if (data->patch_fd >= 0)
|
||||||
|
ext2fs_patch_write_bmap(data);
|
||||||
|
ext2fs_free_generic_bmap(data->bmap);
|
||||||
|
data->bmap = NULL;
|
||||||
|
}
|
||||||
|
if (data->patch_fd >= 0)
|
||||||
|
{
|
||||||
|
close(data->patch_fd);
|
||||||
|
data->patch_fd = -1;
|
||||||
|
}
|
||||||
|
if (data->patch_file)
|
||||||
|
{
|
||||||
|
free(data->patch_file);
|
||||||
|
data->patch_file = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
errcode_t ext2fs_patch_init_bmap(struct ext2fs_patch_file *data, io_channel channel)
|
||||||
|
{
|
||||||
|
errcode_t retval = 0;
|
||||||
|
if (!data->bmap)
|
||||||
|
{
|
||||||
|
if (channel)
|
||||||
|
{
|
||||||
|
// channel is optional parameter, if passed, means 'take size from channel'
|
||||||
|
data->block_size = channel->block_size;
|
||||||
|
// if (data->block_size != 4096)
|
||||||
|
// return EINVAL;
|
||||||
|
retval = ext2fs_get_device_size2(channel->name, data->block_size, &data->size);
|
||||||
|
if (retval)
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
else if (!data->block_size || !data->size)
|
||||||
|
return EINVAL;
|
||||||
|
retval = ext2fs_make_generic_bitmap(EXT2_ET_MAGIC_BLOCK_BITMAP, NULL,
|
||||||
|
0, data->size, data->size, "overwritten blocks", 0, &data->bmap);
|
||||||
|
data->offset = data->block_size + ((((data->size+7)>>3)+(data->block_size-1))&~(data->block_size-1));
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
errcode_t ext2fs_patch_write_blk64(struct ext2fs_patch_file *data, unsigned long long block, int count, const void *buf)
|
||||||
|
{
|
||||||
|
ssize_t size;
|
||||||
|
if (!data->bmap)
|
||||||
|
return EINVAL;
|
||||||
|
if (count < 0)
|
||||||
|
{
|
||||||
|
if ((unsigned)-count > data->block_size)
|
||||||
|
return EINVAL;
|
||||||
|
size = -count;
|
||||||
|
count = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
size = count*data->block_size;
|
||||||
|
ext2fs_mark_block_bitmap_range2(data->bmap, block, count);
|
||||||
|
return ext2fs_patch_retry_write_at(data->patch_fd, data->offset + block*data->block_size, size, buf);
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
/**
|
||||||
|
* patch.h --- Common "patch" file functions
|
||||||
|
*
|
||||||
|
* Patch file format:
|
||||||
|
* 1) sparse data blocks - same size as the patched filesystem, but only changed blocks are written
|
||||||
|
* 2) updated block bitmap - fs_size/block_size/8 bytes
|
||||||
|
* 3) 4 byte FS block size
|
||||||
|
* 4) 8 byte FS size in blocks
|
||||||
|
*
|
||||||
|
* Copyright (c) Vitaliy Filippov <vitalif@mail.ru> 2014
|
||||||
|
* License: GNU GPLv2 or later
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef E2_PATCH_H
|
||||||
|
#define E2_PATCH_H
|
||||||
|
|
||||||
|
#include "ext2_fs.h"
|
||||||
|
#include "ext2fs.h"
|
||||||
|
|
||||||
|
#define PATCHBD_MAGIC 0x44623950 // P9bD
|
||||||
|
|
||||||
|
struct ext2fs_patch_file
|
||||||
|
{
|
||||||
|
char *patch_file;
|
||||||
|
int patch_fd;
|
||||||
|
__u32 block_size;
|
||||||
|
blk64_t size;
|
||||||
|
ext2_loff_t offset;
|
||||||
|
ext2fs_generic_bitmap bmap;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct patchbd_super
|
||||||
|
{
|
||||||
|
__u32 magic;
|
||||||
|
__u32 patch_block;
|
||||||
|
__u64 patch_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
errcode_t ext2fs_patch_retry_read(int fd, ssize_t size, void *buf);
|
||||||
|
errcode_t ext2fs_patch_retry_write(int fd, ssize_t size, const void *buf);
|
||||||
|
errcode_t ext2fs_patch_retry_read_at(int fd, unsigned long long offset, ssize_t size, void *buf);
|
||||||
|
errcode_t ext2fs_patch_retry_write_at(int fd, unsigned long long offset, ssize_t size, const void *buf);
|
||||||
|
errcode_t ext2fs_patch_read_bmap(struct ext2fs_patch_file *data);
|
||||||
|
errcode_t ext2fs_patch_write_bmap(struct ext2fs_patch_file *data);
|
||||||
|
errcode_t ext2fs_patch_open(struct ext2fs_patch_file *data, char *patch_file, int flags);
|
||||||
|
errcode_t ext2fs_patch_close(struct ext2fs_patch_file *data);
|
||||||
|
errcode_t ext2fs_patch_init_bmap(struct ext2fs_patch_file *data, io_channel channel);
|
||||||
|
errcode_t ext2fs_patch_write_blk64(struct ext2fs_patch_file *data, unsigned long long block, int count, const void *buf);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,375 @@
|
||||||
|
/*
|
||||||
|
* patch_io.c --- This is the "patch" io manager that writes the new data into
|
||||||
|
* a separate sparse file to apply it later.
|
||||||
|
*
|
||||||
|
* Copyright (c) Vitaliy Filippov <vitalif@mail.ru> 2014
|
||||||
|
* License: GNU GPLv2 or later
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define _LARGEFILE_SOURCE
|
||||||
|
#define _LARGEFILE64_SOURCE
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include "ext2_fs.h"
|
||||||
|
#include "ext2fs.h"
|
||||||
|
|
||||||
|
#include "patch.h"
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define ATTR(x) __attribute__(x)
|
||||||
|
#else
|
||||||
|
#define ATTR(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define EXT2_CHECK_MAGIC(struct, code) if ((struct)->magic != (code)) return (code)
|
||||||
|
|
||||||
|
struct patch_private_data
|
||||||
|
{
|
||||||
|
int magic;
|
||||||
|
struct ext2fs_patch_file patch;
|
||||||
|
/* The backing io channel */
|
||||||
|
io_channel real;
|
||||||
|
/* to support offset in unix I/O manager */
|
||||||
|
ext2_loff_t offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
static errcode_t patch_open(const char *name, int flags, io_channel *channel);
|
||||||
|
static errcode_t patch_close(io_channel channel);
|
||||||
|
static errcode_t patch_set_blksize(io_channel channel, int blksize);
|
||||||
|
static errcode_t patch_read_blk64(io_channel channel, unsigned long long block, int count, void *data);
|
||||||
|
static errcode_t patch_write_blk64(io_channel channel, unsigned long long block, int count, const void *data);
|
||||||
|
static errcode_t patch_read_blk(io_channel channel, unsigned long block, int count, void *data);
|
||||||
|
static errcode_t patch_write_blk(io_channel channel, unsigned long block, int count, const void *data);
|
||||||
|
static errcode_t patch_flush(io_channel channel);
|
||||||
|
static errcode_t patch_write_byte(io_channel channel, unsigned long offset, int size, const void *data);
|
||||||
|
static errcode_t patch_set_option(io_channel channel, const char *option, const char *arg);
|
||||||
|
static errcode_t patch_get_stats(io_channel channel, io_stats *stats);
|
||||||
|
|
||||||
|
static struct struct_io_manager struct_patch_manager = {
|
||||||
|
EXT2_ET_MAGIC_IO_MANAGER,
|
||||||
|
"Patch I/O Manager",
|
||||||
|
patch_open,
|
||||||
|
patch_close,
|
||||||
|
patch_set_blksize,
|
||||||
|
patch_read_blk,
|
||||||
|
patch_write_blk,
|
||||||
|
patch_flush,
|
||||||
|
patch_write_byte,
|
||||||
|
patch_set_option,
|
||||||
|
patch_get_stats,
|
||||||
|
patch_read_blk64,
|
||||||
|
patch_write_blk64,
|
||||||
|
};
|
||||||
|
|
||||||
|
io_manager patch_io_manager = &struct_patch_manager;
|
||||||
|
static char *patch_file;
|
||||||
|
static io_manager patch_io_backing_manager;
|
||||||
|
|
||||||
|
errcode_t set_patch_io_backing_manager(io_manager manager)
|
||||||
|
{
|
||||||
|
patch_io_backing_manager = manager;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
errcode_t set_patch_io_patch_file(char *file)
|
||||||
|
{
|
||||||
|
patch_file = file;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static errcode_t patch_open(const char *name, int flags, io_channel *channel)
|
||||||
|
{
|
||||||
|
io_channel io = NULL;
|
||||||
|
struct patch_private_data *data = NULL;
|
||||||
|
errcode_t retval;
|
||||||
|
|
||||||
|
if (name == 0)
|
||||||
|
return EXT2_ET_BAD_DEVICE_NAME;
|
||||||
|
retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io);
|
||||||
|
if (retval)
|
||||||
|
goto cleanup;
|
||||||
|
memset(io, 0, sizeof(struct struct_io_channel));
|
||||||
|
io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
|
||||||
|
retval = ext2fs_get_mem(sizeof(struct patch_private_data), &data);
|
||||||
|
if (retval)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
io->manager = patch_io_manager;
|
||||||
|
retval = ext2fs_get_mem(strlen(name)+1, &io->name);
|
||||||
|
if (retval)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
strcpy(io->name, name);
|
||||||
|
io->private_data = data;
|
||||||
|
io->block_size = 1024;
|
||||||
|
io->read_error = 0;
|
||||||
|
io->write_error = 0;
|
||||||
|
io->refcount = 1;
|
||||||
|
|
||||||
|
memset(data, 0, sizeof(struct patch_private_data));
|
||||||
|
data->magic = EXT2_ET_MAGIC_UNIX_IO_CHANNEL;
|
||||||
|
|
||||||
|
if (patch_io_backing_manager)
|
||||||
|
{
|
||||||
|
retval = patch_io_backing_manager->open(name, flags & ~IO_FLAG_RW, &data->real);
|
||||||
|
if (retval)
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (patch_file)
|
||||||
|
{
|
||||||
|
retval = ext2fs_patch_open(&data->patch, patch_file, O_CREAT);
|
||||||
|
if (retval)
|
||||||
|
goto cleanup;
|
||||||
|
if (data->patch.block_size)
|
||||||
|
{
|
||||||
|
retval = io_channel_set_blksize(data->real, data->patch.block_size);
|
||||||
|
if (retval)
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*channel = io;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
ext2fs_patch_close(&data->patch);
|
||||||
|
if (data->real)
|
||||||
|
io_channel_close(data->real);
|
||||||
|
ext2fs_free_mem(&data);
|
||||||
|
}
|
||||||
|
if (io)
|
||||||
|
{
|
||||||
|
if (io->name)
|
||||||
|
ext2fs_free_mem(&io->name);
|
||||||
|
ext2fs_free_mem(&io);
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static errcode_t patch_close(io_channel channel)
|
||||||
|
{
|
||||||
|
struct patch_private_data *data;
|
||||||
|
errcode_t retval = 0;
|
||||||
|
|
||||||
|
EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
|
||||||
|
data = (struct patch_private_data *) channel->private_data;
|
||||||
|
EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
|
||||||
|
|
||||||
|
if (--channel->refcount > 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ext2fs_patch_close(&data->patch);
|
||||||
|
if (data->real)
|
||||||
|
retval = io_channel_close(data->real);
|
||||||
|
ext2fs_free_mem(&channel->private_data);
|
||||||
|
if (channel->name)
|
||||||
|
ext2fs_free_mem(&channel->name);
|
||||||
|
ext2fs_free_mem(&channel);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static errcode_t patch_set_blksize(io_channel channel, int blksize)
|
||||||
|
{
|
||||||
|
struct patch_private_data *data;
|
||||||
|
errcode_t retval = 0;
|
||||||
|
|
||||||
|
EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
|
||||||
|
data = (struct patch_private_data *) channel->private_data;
|
||||||
|
EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
|
||||||
|
|
||||||
|
channel->block_size = (unsigned)blksize;
|
||||||
|
if (data->patch.block_size && data->patch.block_size != (unsigned)blksize)
|
||||||
|
return EINVAL;
|
||||||
|
if (data->real)
|
||||||
|
retval = io_channel_set_blksize(data->real, blksize);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static errcode_t patch_read_blk64(io_channel channel, unsigned long long block, int count, void *buf)
|
||||||
|
{
|
||||||
|
errcode_t retval = 0;
|
||||||
|
struct patch_private_data *data;
|
||||||
|
int b, n;
|
||||||
|
|
||||||
|
EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
|
||||||
|
data = (struct patch_private_data *) channel->private_data;
|
||||||
|
EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
|
||||||
|
|
||||||
|
if (count < 0)
|
||||||
|
{
|
||||||
|
if (-count <= channel->block_size)
|
||||||
|
{
|
||||||
|
if (data->patch.bmap && ext2fs_test_generic_bitmap(data->patch.bmap, block))
|
||||||
|
retval = ext2fs_patch_retry_read_at(data->patch.patch_fd, data->patch.offset + block*channel->block_size, -count, buf);
|
||||||
|
else
|
||||||
|
retval = io_channel_read_blk64(data->real, block, count, buf);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
for (b = 0; b < count; )
|
||||||
|
{
|
||||||
|
for (n = 0; (b+n < count) && data->patch.bmap && ext2fs_test_generic_bitmap(data->patch.bmap, block+b+n); n++) {}
|
||||||
|
if (n > 0)
|
||||||
|
{
|
||||||
|
retval = ext2fs_patch_retry_read_at(data->patch.patch_fd, data->patch.offset + (block+b)*channel->block_size, n*channel->block_size, buf+b*channel->block_size);
|
||||||
|
if (retval)
|
||||||
|
break;
|
||||||
|
b += n;
|
||||||
|
}
|
||||||
|
for (n = 0; (b+n < count) && (!data->patch.bmap || !ext2fs_test_generic_bitmap(data->patch.bmap, block+b+n)); n++) {}
|
||||||
|
if (n > 0)
|
||||||
|
{
|
||||||
|
retval = io_channel_read_blk64(data->real, block+b, n, buf+b*channel->block_size);
|
||||||
|
if (retval)
|
||||||
|
break;
|
||||||
|
b += n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static errcode_t patch_read_blk(io_channel channel, unsigned long block, int count, void *buf)
|
||||||
|
{
|
||||||
|
return patch_read_blk64(channel, block, count, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static errcode_t patch_write_blk64(io_channel channel, unsigned long long block, int count, const void *buf)
|
||||||
|
{
|
||||||
|
struct patch_private_data *data;
|
||||||
|
errcode_t retval = 0;
|
||||||
|
|
||||||
|
EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
|
||||||
|
data = (struct patch_private_data *) channel->private_data;
|
||||||
|
EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
|
||||||
|
|
||||||
|
retval = ext2fs_patch_init_bmap(&data->patch, channel);
|
||||||
|
if (retval)
|
||||||
|
return retval;
|
||||||
|
// libext2fs changes block size to 1024 in order to write the superblock, so we must support it...
|
||||||
|
if ((__u32)channel->block_size < data->patch.block_size)
|
||||||
|
{
|
||||||
|
void *buf2 = NULL;
|
||||||
|
unsigned long long block_real = block / (data->patch.block_size / channel->block_size);
|
||||||
|
int count_real = ( (block % (data->patch.block_size / channel->block_size))
|
||||||
|
+ (count > 0 ? count*channel->block_size : -count)
|
||||||
|
+ data->patch.block_size - 1 ) / data->patch.block_size;
|
||||||
|
retval = ext2fs_get_mem(count_real * data->patch.block_size, &buf2);
|
||||||
|
if (retval)
|
||||||
|
goto out;
|
||||||
|
retval = patch_read_blk64(channel, block_real, count_real, buf2);
|
||||||
|
if (retval)
|
||||||
|
goto out;
|
||||||
|
memcpy(buf2 + (block % (data->patch.block_size / channel->block_size)) * channel->block_size,
|
||||||
|
buf, (count > 0 ? count*channel->block_size : -count));
|
||||||
|
retval = ext2fs_patch_write_blk64(&data->patch, block_real, count_real, buf2);
|
||||||
|
out:
|
||||||
|
if (buf2)
|
||||||
|
ext2fs_free_mem(&buf2);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
else if ((__u32)channel->block_size > data->patch.block_size)
|
||||||
|
{
|
||||||
|
return EXT2_ET_UNIMPLEMENTED;
|
||||||
|
}
|
||||||
|
return ext2fs_patch_write_blk64(&data->patch, block, count, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static errcode_t patch_write_blk(io_channel channel, unsigned long block, int count, const void *buf)
|
||||||
|
{
|
||||||
|
return patch_write_blk64(channel, block, count, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static errcode_t patch_write_byte(io_channel channel, unsigned long offset, int size, const void *buf)
|
||||||
|
{
|
||||||
|
return EXT2_ET_UNIMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Flush data buffers to disk.
|
||||||
|
*/
|
||||||
|
static errcode_t patch_flush(io_channel channel)
|
||||||
|
{
|
||||||
|
errcode_t retval = 0;
|
||||||
|
struct patch_private_data *data;
|
||||||
|
|
||||||
|
EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
|
||||||
|
data = (struct patch_private_data *) channel->private_data;
|
||||||
|
EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
|
||||||
|
|
||||||
|
if (data->real)
|
||||||
|
retval = io_channel_flush(data->real);
|
||||||
|
if (data->patch.patch_fd)
|
||||||
|
fsync(data->patch.patch_fd);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static errcode_t patch_set_option(io_channel channel, const char *option, const char *arg)
|
||||||
|
{
|
||||||
|
errcode_t retval = 0;
|
||||||
|
struct patch_private_data *data;
|
||||||
|
unsigned long tmp;
|
||||||
|
char *end;
|
||||||
|
|
||||||
|
EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
|
||||||
|
data = (struct patch_private_data *) channel->private_data;
|
||||||
|
EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Need to support offset option to work with
|
||||||
|
* Unix I/O manager
|
||||||
|
*/
|
||||||
|
if (data->real && data->real->manager->set_option)
|
||||||
|
retval = data->real->manager->set_option(data->real, option, arg);
|
||||||
|
if (!retval && !strcmp(option, "offset"))
|
||||||
|
{
|
||||||
|
if (!arg)
|
||||||
|
return EXT2_ET_INVALID_ARGUMENT;
|
||||||
|
|
||||||
|
tmp = strtoul(arg, &end, 0);
|
||||||
|
if (*end)
|
||||||
|
return EXT2_ET_INVALID_ARGUMENT;
|
||||||
|
data->offset = tmp;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static errcode_t patch_get_stats(io_channel channel, io_stats *stats)
|
||||||
|
{
|
||||||
|
errcode_t retval = 0;
|
||||||
|
struct patch_private_data *data;
|
||||||
|
|
||||||
|
EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
|
||||||
|
data = (struct patch_private_data *) channel->private_data;
|
||||||
|
EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL);
|
||||||
|
|
||||||
|
if (data->real)
|
||||||
|
retval = (data->real->manager->get_stats)(data->real, stats);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
|
@ -307,6 +307,8 @@ void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t,
|
||||||
/* this is error case: i_extra_size is too large */
|
/* this is error case: i_extra_size is too large */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (extra_isize & 3)
|
||||||
|
return; /* Illegal inode extra_isize */
|
||||||
|
|
||||||
inode_size = EXT2_GOOD_OLD_INODE_SIZE + extra_isize;
|
inode_size = EXT2_GOOD_OLD_INODE_SIZE + extra_isize;
|
||||||
if (inode_includes(inode_size, i_checksum_hi))
|
if (inode_includes(inode_size, i_checksum_hi))
|
||||||
|
|
|
@ -300,6 +300,7 @@ static errcode_t raw_write_blk(io_channel channel,
|
||||||
goto short_write;
|
goto short_write;
|
||||||
size -= actual;
|
size -= actual;
|
||||||
buf += actual;
|
buf += actual;
|
||||||
|
location += actual;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
|
@ -33,12 +33,12 @@ INSTALL = @INSTALL@
|
||||||
@FUSE_CMT@FUSE_PROG= fuse2fs
|
@FUSE_CMT@FUSE_PROG= fuse2fs
|
||||||
|
|
||||||
SPROGS= mke2fs badblocks tune2fs dumpe2fs $(BLKID_PROG) logsave \
|
SPROGS= mke2fs badblocks tune2fs dumpe2fs $(BLKID_PROG) logsave \
|
||||||
$(E2IMAGE_PROG) @FSCK_PROG@ e2undo
|
$(E2IMAGE_PROG) @FSCK_PROG@ e2undo e2patch
|
||||||
USPROGS= mklost+found filefrag e2freefrag $(UUIDD_PROG) \
|
USPROGS= mklost+found filefrag e2freefrag $(UUIDD_PROG) \
|
||||||
$(E4DEFRAG_PROG) $(E4CRYPT_PROG) $(FUSE_PROG)
|
$(E4DEFRAG_PROG) $(E4CRYPT_PROG) $(FUSE_PROG)
|
||||||
SMANPAGES= tune2fs.8 mklost+found.8 mke2fs.8 dumpe2fs.8 badblocks.8 \
|
SMANPAGES= tune2fs.8 mklost+found.8 mke2fs.8 dumpe2fs.8 badblocks.8 \
|
||||||
e2label.8 $(FINDFS_MAN) $(BLKID_MAN) $(E2IMAGE_MAN) \
|
e2label.8 $(FINDFS_MAN) $(BLKID_MAN) $(E2IMAGE_MAN) \
|
||||||
logsave.8 filefrag.8 e2freefrag.8 e2undo.8 \
|
logsave.8 filefrag.8 e2freefrag.8 e2undo.8 e2patch.8 \
|
||||||
$(UUIDD_MAN) $(E4DEFRAG_MAN) $(E4CRYPT_MAN) @FSCK_MAN@
|
$(UUIDD_MAN) $(E4DEFRAG_MAN) $(E4CRYPT_MAN) @FSCK_MAN@
|
||||||
FMANPAGES= mke2fs.conf.5 ext4.5
|
FMANPAGES= mke2fs.conf.5 ext4.5
|
||||||
|
|
||||||
|
@ -63,6 +63,7 @@ FSCK_OBJS= fsck.o base_device.o ismounted.o
|
||||||
BLKID_OBJS= blkid.o
|
BLKID_OBJS= blkid.o
|
||||||
FILEFRAG_OBJS= filefrag.o
|
FILEFRAG_OBJS= filefrag.o
|
||||||
E2UNDO_OBJS= e2undo.o
|
E2UNDO_OBJS= e2undo.o
|
||||||
|
E2PATCH_OBJS= e2patch.o
|
||||||
E4DEFRAG_OBJS= e4defrag.o
|
E4DEFRAG_OBJS= e4defrag.o
|
||||||
E4CRYPT_OBJS= e4crypt.o
|
E4CRYPT_OBJS= e4crypt.o
|
||||||
E2FREEFRAG_OBJS= e2freefrag.o
|
E2FREEFRAG_OBJS= e2freefrag.o
|
||||||
|
@ -88,6 +89,7 @@ PROFILED_BLKID_OBJS= profiled/blkid.o
|
||||||
PROFILED_FILEFRAG_OBJS= profiled/filefrag.o
|
PROFILED_FILEFRAG_OBJS= profiled/filefrag.o
|
||||||
PROFILED_E2FREEFRAG_OBJS= profiled/e2freefrag.o
|
PROFILED_E2FREEFRAG_OBJS= profiled/e2freefrag.o
|
||||||
PROFILED_E2UNDO_OBJS= profiled/e2undo.o
|
PROFILED_E2UNDO_OBJS= profiled/e2undo.o
|
||||||
|
PROFILED_E2PATCH_OBJS= profiled/e2patch.o
|
||||||
PROFILED_E4DEFRAG_OBJS= profiled/e4defrag.o
|
PROFILED_E4DEFRAG_OBJS= profiled/e4defrag.o
|
||||||
PROFILED_E4CRYPT_OBJS= profiled/e4crypt.o
|
PROFILED_E4CRYPT_OBJS= profiled/e4crypt.o
|
||||||
PROFILED_FUSE2FS_OJBS= profiled/fuse2fs.o profiled/journal.o \
|
PROFILED_FUSE2FS_OJBS= profiled/fuse2fs.o profiled/journal.o \
|
||||||
|
@ -98,7 +100,7 @@ SRCS= $(srcdir)/tune2fs.c $(srcdir)/mklost+found.c $(srcdir)/mke2fs.c $(srcdir)/
|
||||||
$(srcdir)/badblocks.c $(srcdir)/fsck.c $(srcdir)/util.c \
|
$(srcdir)/badblocks.c $(srcdir)/fsck.c $(srcdir)/util.c \
|
||||||
$(srcdir)/uuidgen.c $(srcdir)/blkid.c $(srcdir)/logsave.c \
|
$(srcdir)/uuidgen.c $(srcdir)/blkid.c $(srcdir)/logsave.c \
|
||||||
$(srcdir)/filefrag.c $(srcdir)/base_device.c \
|
$(srcdir)/filefrag.c $(srcdir)/base_device.c \
|
||||||
$(srcdir)/ismounted.c $(srcdir)/e2undo.c \
|
$(srcdir)/ismounted.c $(srcdir)/e2undo.c $(srcdir)/e2patch.c \
|
||||||
$(srcdir)/e2freefrag.c $(srcdir)/create_inode.c \
|
$(srcdir)/e2freefrag.c $(srcdir)/create_inode.c \
|
||||||
$(srcdir)/fuse2fs.c \
|
$(srcdir)/fuse2fs.c \
|
||||||
$(srcdir)/../debugfs/journal.c $(srcdir)/../e2fsck/revoke.c \
|
$(srcdir)/../debugfs/journal.c $(srcdir)/../e2fsck/revoke.c \
|
||||||
|
@ -133,7 +135,7 @@ all:: profiled $(SPROGS) $(UPROGS) $(USPROGS) $(SMANPAGES) $(UMANPAGES) \
|
||||||
$(FMANPAGES) $(LPROGS) $(E4DEFRAG_PROG) $(E4CRYPT_PROGS) e2fuzz
|
$(FMANPAGES) $(LPROGS) $(E4DEFRAG_PROG) $(E4CRYPT_PROGS) e2fuzz
|
||||||
|
|
||||||
@PROFILE_CMT@all:: tune2fs.profiled blkid.profiled e2image.profiled \
|
@PROFILE_CMT@all:: tune2fs.profiled blkid.profiled e2image.profiled \
|
||||||
e2undo.profiled mke2fs.profiled dumpe2fs.profiled fsck.profiled \
|
e2undo.profiled e2patch.profiled mke2fs.profiled dumpe2fs.profiled fsck.profiled \
|
||||||
logsave.profiled filefrag.profiled uuidgen.profiled $(UUIDD_PROFILED) \
|
logsave.profiled filefrag.profiled uuidgen.profiled $(UUIDD_PROFILED) \
|
||||||
e2image.profiled e4defrag.profiled e4crypt.profiled \
|
e2image.profiled e4defrag.profiled e4crypt.profiled \
|
||||||
e2freefrag.profiled
|
e2freefrag.profiled
|
||||||
|
@ -226,6 +228,16 @@ e2undo.profiled: $(E2UNDO_OBJS) $(PROFILED_DEPLIBS)
|
||||||
$(Q) $(CC) $(ALL_LDFLAGS) -g -pg -o e2undo.profiled \
|
$(Q) $(CC) $(ALL_LDFLAGS) -g -pg -o e2undo.profiled \
|
||||||
$(PROFILED_E2UNDO_OBJS) $(PROFILED_LIBS) $(LIBINTL) $(SYSLIBS)
|
$(PROFILED_E2UNDO_OBJS) $(PROFILED_LIBS) $(LIBINTL) $(SYSLIBS)
|
||||||
|
|
||||||
|
e2patch: $(E2PATCH_OBJS) $(DEPLIBS)
|
||||||
|
$(E) " LD $@"
|
||||||
|
$(Q) $(CC) $(ALL_LDFLAGS) -o e2patch $(E2PATCH_OBJS) $(LIBS) \
|
||||||
|
$(LIBINTL) $(SYSLIBS)
|
||||||
|
|
||||||
|
e2patch.profiled: $(E2PATCH_OBJS) $(PROFILED_DEPLIBS)
|
||||||
|
$(E) " LD $@"
|
||||||
|
$(Q) $(CC) $(ALL_LDFLAGS) -g -pg -o e2patch.profiled \
|
||||||
|
$(PROFILED_E2PATCH_OBJS) $(PROFILED_LIBS) $(LIBINTL) $(SYSLIBS)
|
||||||
|
|
||||||
e4defrag: $(E4DEFRAG_OBJS) $(DEPLIBS)
|
e4defrag: $(E4DEFRAG_OBJS) $(DEPLIBS)
|
||||||
$(E) " LD $@"
|
$(E) " LD $@"
|
||||||
$(Q) $(CC) $(ALL_LDFLAGS) -o e4defrag $(E4DEFRAG_OBJS) $(LIBS) \
|
$(Q) $(CC) $(ALL_LDFLAGS) -o e4defrag $(E4DEFRAG_OBJS) $(LIBS) \
|
||||||
|
@ -439,6 +451,10 @@ e2undo.8: $(DEP_SUBSTITUTE) $(srcdir)/e2undo.8.in
|
||||||
$(E) " SUBST $@"
|
$(E) " SUBST $@"
|
||||||
$(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/e2undo.8.in e2undo.8
|
$(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/e2undo.8.in e2undo.8
|
||||||
|
|
||||||
|
e2patch.8: $(DEP_SUBSTITUTE) $(srcdir)/e2patch.8.in
|
||||||
|
$(E) " SUBST $@"
|
||||||
|
$(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/e2patch.8.in e2patch.8
|
||||||
|
|
||||||
findfs.8: $(DEP_SUBSTITUTE) $(srcdir)/findfs.8.in
|
findfs.8: $(DEP_SUBSTITUTE) $(srcdir)/findfs.8.in
|
||||||
$(E) " SUBST $@"
|
$(E) " SUBST $@"
|
||||||
$(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/findfs.8.in findfs.8
|
$(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/findfs.8.in findfs.8
|
||||||
|
@ -669,7 +685,7 @@ clean::
|
||||||
e2initrd_helper partinfo prof_err.[ch] default_profile.c \
|
e2initrd_helper partinfo prof_err.[ch] default_profile.c \
|
||||||
uuidd e2image tune2fs.static tst_ismounted fsck.profiled \
|
uuidd e2image tune2fs.static tst_ismounted fsck.profiled \
|
||||||
blkid.profiled tune2fs.profiled e2image.profiled \
|
blkid.profiled tune2fs.profiled e2image.profiled \
|
||||||
e2undo.profiled mke2fs.profiled dumpe2fs.profiled \
|
e2undo.profiled e2patch.profiled mke2fs.profiled dumpe2fs.profiled \
|
||||||
logsave.profiled filefrag.profiled uuidgen.profiled \
|
logsave.profiled filefrag.profiled uuidgen.profiled \
|
||||||
uuidd.profiled e2image.profiled e2fuzz mke2fs.conf \
|
uuidd.profiled e2image.profiled e2fuzz mke2fs.conf \
|
||||||
profiled/*.o \#* *.s *.o *.a *~ core gmon.out
|
profiled/*.o \#* *.s *.o *.a *~ core gmon.out
|
||||||
|
@ -792,6 +808,12 @@ e2undo.o: $(srcdir)/e2undo.c $(top_builddir)/lib/config.h \
|
||||||
$(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
|
$(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
|
||||||
$(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \
|
$(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \
|
||||||
$(top_srcdir)/lib/support/nls-enable.h
|
$(top_srcdir)/lib/support/nls-enable.h
|
||||||
|
e2patch.o: $(srcdir)/e2patch.c $(top_builddir)/lib/config.h \
|
||||||
|
$(top_builddir)/lib/dirpaths.h $(top_srcdir)/lib/ext2fs/ext2fs.h \
|
||||||
|
$(top_builddir)/lib/ext2fs/ext2_types.h $(top_srcdir)/lib/ext2fs/ext2_fs.h \
|
||||||
|
$(top_srcdir)/lib/ext2fs/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
|
||||||
|
$(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
|
||||||
|
$(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h
|
||||||
e2freefrag.o: $(srcdir)/e2freefrag.c $(top_builddir)/lib/config.h \
|
e2freefrag.o: $(srcdir)/e2freefrag.c $(top_builddir)/lib/config.h \
|
||||||
$(top_builddir)/lib/dirpaths.h $(top_srcdir)/lib/ext2fs/ext2_fs.h \
|
$(top_builddir)/lib/dirpaths.h $(top_srcdir)/lib/ext2fs/ext2_fs.h \
|
||||||
$(top_builddir)/lib/ext2fs/ext2_types.h $(top_srcdir)/lib/ext2fs/ext2fs.h \
|
$(top_builddir)/lib/ext2fs/ext2_types.h $(top_srcdir)/lib/ext2fs/ext2fs.h \
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
.TH E2PATCH 8 "@E2FSPROGS_MONTH@ @E2FSPROGS_YEAR@" "E2fsprogs version @E2FSPROGS_VERSION@"
|
||||||
|
.SH NAME
|
||||||
|
e2patch \- patch tool for safely applying libext2fs patch files to block devices
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B e2patch backup \fI<device>\fR \fI<patch_file>\fR \fI<backup_file>\fR
|
||||||
|
.br
|
||||||
|
.B e2patch apply \fI<device>\fR \fI<patch_file>\fR
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B e2patch
|
||||||
|
applies and restores "patches" produced by e2fsprogs with patch file option
|
||||||
|
(\fBresize2fs -T <patch_file>\fR) to block devices.
|
||||||
|
.PP
|
||||||
|
"Patch files" are sparse files containing overwritten device blocks and
|
||||||
|
a block bitmap.
|
||||||
|
.PP
|
||||||
|
"Patch files" are faster, safer and simpler to use than "undo files"
|
||||||
|
(\fBe2undo\fR and \fBresize2fs -z <undo_file>\fR), even though their original
|
||||||
|
design goal is similar.
|
||||||
|
.SH COMMANDS
|
||||||
|
.TP
|
||||||
|
.B e2patch backup \fI<device>\fR \fI<patch_file>\fR \fI<backup_file>\fR
|
||||||
|
Creates a backup in <backup_file> for restoring after bad patch <patch_file>.
|
||||||
|
Backup can then also be applied with \fBe2patch apply\fR
|
||||||
|
.TP
|
||||||
|
.B e2patch apply \fI<device>\fR \fI<patch_file>\fR
|
||||||
|
Apply <patch_file> to <device>.
|
||||||
|
.SH AUTHOR
|
||||||
|
Written by Vitaliy Filippov <vitalif@mail.ru>
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR resize2fs (8),
|
||||||
|
.BR e2undo (8).
|
|
@ -0,0 +1,166 @@
|
||||||
|
/**
|
||||||
|
* e2patch.c --- Utility to apply/restore patches created by patch_io_manager.
|
||||||
|
*
|
||||||
|
* Copyright (c) Vitaliy Filippov <vitalif@mail.ru> 2014
|
||||||
|
* License: GNU GPLv2 or later
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "ext2fs/ext2_fs.h"
|
||||||
|
#include "ext2fs/ext2fs.h"
|
||||||
|
|
||||||
|
#include "ext2fs/patch.h"
|
||||||
|
|
||||||
|
#define BUF 0x10000
|
||||||
|
#define _(a) (a)
|
||||||
|
|
||||||
|
errcode_t make_backup_patch(char *device, char *io_options, char *patch_file, char *backup_file)
|
||||||
|
{
|
||||||
|
io_manager mgr = unix_io_manager;
|
||||||
|
io_channel io;
|
||||||
|
errcode_t retval;
|
||||||
|
blk64_t blk, start, buf_blocks;
|
||||||
|
int eq;
|
||||||
|
void *buf = NULL;
|
||||||
|
struct ext2fs_patch_file patch = { 0 }, backup = { 0 };
|
||||||
|
retval = mgr->open(device, IO_FLAG_EXCLUSIVE, &io);
|
||||||
|
if (retval) goto out;
|
||||||
|
if (io_options &&
|
||||||
|
(retval = io_channel_set_options(io, io_options)))
|
||||||
|
goto out;
|
||||||
|
retval = ext2fs_patch_open(&patch, patch_file, 0);
|
||||||
|
if (retval) goto out;
|
||||||
|
retval = ext2fs_patch_open(&backup, backup_file, O_CREAT);
|
||||||
|
if (retval) goto out;
|
||||||
|
backup.block_size = patch.block_size;
|
||||||
|
backup.size = patch.size;
|
||||||
|
ext2fs_patch_init_bmap(&backup, NULL);
|
||||||
|
buf_blocks = BUF/patch.block_size;
|
||||||
|
retval = mgr->set_blksize(io, patch.block_size);
|
||||||
|
if (retval) goto out;
|
||||||
|
buf = malloc(BUF);
|
||||||
|
for (start = 0, blk = 0; blk <= patch.size; blk++)
|
||||||
|
{
|
||||||
|
if ((eq = !ext2fs_test_generic_bitmap(patch.bmap, blk)) || blk >= patch.size || blk-start >= buf_blocks)
|
||||||
|
{
|
||||||
|
if (start != blk)
|
||||||
|
{
|
||||||
|
retval = io_channel_read_blk64(io, start, blk-start, buf);
|
||||||
|
if (retval) goto out;
|
||||||
|
retval = ext2fs_patch_write_blk64(&backup, start, blk-start, buf);
|
||||||
|
if (retval) goto out;
|
||||||
|
}
|
||||||
|
start = blk+eq;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
if (buf)
|
||||||
|
free(buf);
|
||||||
|
ext2fs_patch_close(&backup);
|
||||||
|
ext2fs_patch_close(&patch);
|
||||||
|
mgr->close(io);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
errcode_t apply_patch(char *device, char *io_options, char *patch_file)
|
||||||
|
{
|
||||||
|
io_manager mgr = unix_io_manager;
|
||||||
|
io_channel io;
|
||||||
|
errcode_t retval;
|
||||||
|
blk64_t blk, start, buf_blocks;
|
||||||
|
int eq;
|
||||||
|
void *buf = NULL;
|
||||||
|
struct ext2fs_patch_file patch = { 0 };
|
||||||
|
retval = mgr->open(device, IO_FLAG_EXCLUSIVE|IO_FLAG_RW, &io);
|
||||||
|
if (retval) goto out;
|
||||||
|
if (io_options &&
|
||||||
|
(retval = io_channel_set_options(io, io_options)))
|
||||||
|
goto out;
|
||||||
|
retval = ext2fs_patch_open(&patch, patch_file, 0);
|
||||||
|
if (retval) goto out;
|
||||||
|
buf_blocks = BUF/patch.block_size;
|
||||||
|
retval = mgr->set_blksize(io, patch.block_size);
|
||||||
|
if (retval) goto out;
|
||||||
|
buf = malloc(BUF);
|
||||||
|
for (start = 0, blk = 0; blk <= patch.size; blk++)
|
||||||
|
{
|
||||||
|
if ((eq = blk < patch.size && !ext2fs_test_generic_bitmap(patch.bmap, blk)) || blk >= patch.size || blk-start >= buf_blocks)
|
||||||
|
{
|
||||||
|
if (start != blk)
|
||||||
|
{
|
||||||
|
retval = ext2fs_patch_retry_read_at(patch.patch_fd, patch.offset + start*patch.block_size, (blk-start)*patch.block_size, buf);
|
||||||
|
if (retval) goto out;
|
||||||
|
retval = io_channel_write_blk64(io, start, blk-start, buf);
|
||||||
|
if (retval) goto out;
|
||||||
|
}
|
||||||
|
start = blk+eq;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
if (buf)
|
||||||
|
free(buf);
|
||||||
|
ext2fs_patch_close(&patch);
|
||||||
|
mgr->close(io);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int narg, char **args)
|
||||||
|
{
|
||||||
|
errcode_t retval;
|
||||||
|
char *io_options = NULL;
|
||||||
|
if (narg >= 5 && !strcmp(args[1], "backup"))
|
||||||
|
{
|
||||||
|
io_options = strchr(args[2], '?');
|
||||||
|
if (io_options)
|
||||||
|
*io_options++ = 0;
|
||||||
|
retval = make_backup_patch(args[2], io_options, args[3], args[4]);
|
||||||
|
}
|
||||||
|
else if (narg >= 4 && !strcmp(args[1], "apply"))
|
||||||
|
{
|
||||||
|
io_options = strchr(args[2], '?');
|
||||||
|
if (io_options)
|
||||||
|
*io_options++ = 0;
|
||||||
|
retval = apply_patch(args[2], io_options, args[3]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf(
|
||||||
|
"Patch tool for safely applying changes to block devices\n"
|
||||||
|
"License: GNU GPLv2 or later\n"
|
||||||
|
"Copyright (c) Vitaliy Filippov, 2014\n\n"
|
||||||
|
"To create a backup for restoring after bad patch:\n"
|
||||||
|
" e2patch backup <filesystem> <patch_file> <backup_file>\n"
|
||||||
|
"To apply a patch:\n"
|
||||||
|
" e2patch apply <filesystem> <patch_file>\n"
|
||||||
|
);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (retval)
|
||||||
|
{
|
||||||
|
com_err("e2patch", retval, _("while trying to %s"), args[1]);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -474,6 +474,10 @@ static int frag_report(const char *filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (force_bmap || rc < 0) { /* FIEMAP failed, try FIBMAP instead */
|
if (force_bmap || rc < 0) { /* FIEMAP failed, try FIBMAP instead */
|
||||||
|
if (numblocks > (unsigned long)-1L) {
|
||||||
|
fprintf(stderr, "%s: File too big to use FIBMAP\n", filename);
|
||||||
|
goto out_close;
|
||||||
|
}
|
||||||
expected = filefrag_fibmap(fd, blk_shift, &num_extents,
|
expected = filefrag_fibmap(fd, blk_shift, &num_extents,
|
||||||
&st, numblocks, is_ext2);
|
&st, numblocks, is_ext2);
|
||||||
if (expected < 0) {
|
if (expected < 0) {
|
||||||
|
|
|
@ -11,11 +11,11 @@
|
||||||
features = has_journal
|
features = has_journal
|
||||||
}
|
}
|
||||||
ext4 = {
|
ext4 = {
|
||||||
features = has_journal,extent,huge_file,flex_bg,metadata_csum,64bit,dir_nlink,extra_isize
|
features = has_journal,extent,huge_file,flex_bg,64bit,dir_nlink,extra_isize
|
||||||
inode_size = 256
|
inode_size = 256
|
||||||
}
|
}
|
||||||
ext4dev = {
|
ext4dev = {
|
||||||
features = has_journal,extent,huge_file,flex_bg,metadata_csum,inline_data,64bit,dir_nlink,extra_isize
|
features = has_journal,extent,huge_file,flex_bg,inline_data,64bit,dir_nlink,extra_isize
|
||||||
inode_size = 256
|
inode_size = 256
|
||||||
options = test_fs=1
|
options = test_fs=1
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@ misc/e2image.c
|
||||||
misc/e2initrd_helper.c
|
misc/e2initrd_helper.c
|
||||||
misc/e2label.c
|
misc/e2label.c
|
||||||
misc/e2undo.c
|
misc/e2undo.c
|
||||||
|
misc/e2patch.c
|
||||||
misc/e4crypt.c
|
misc/e4crypt.c
|
||||||
misc/e4defrag.c
|
misc/e4defrag.c
|
||||||
misc/filefrag.c
|
misc/filefrag.c
|
||||||
|
|
614
po/e2fsprogs.pot
614
po/e2fsprogs.pot
File diff suppressed because it is too large
Load Diff
BIN
po/zh_CN.gmo
BIN
po/zh_CN.gmo
Binary file not shown.
895
po/zh_CN.po
895
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
|
@ -46,8 +46,8 @@ static char *device_name, *io_options;
|
||||||
|
|
||||||
static void usage (char *prog)
|
static void usage (char *prog)
|
||||||
{
|
{
|
||||||
fprintf (stderr, _("Usage: %s [-d debug_flags] [-f] [-F] [-M] [-P] "
|
fprintf (stderr, _("Usage: %s [-d debug_flags] [-f] [-F] [-M] [-N new_inodes] [-P] "
|
||||||
"[-p] device [-b|-s|new_size] [-z undo_file]\n\n"),
|
"[-p] device [-b|-s|new_size] [-T patch_file] [-z undo_file]\n\n"),
|
||||||
prog);
|
prog);
|
||||||
|
|
||||||
exit (1);
|
exit (1);
|
||||||
|
@ -167,6 +167,20 @@ static void bigalloc_check(ext2_filsys fs, int force)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int resize2fs_setup_patch(const char *device, char *patch_file,
|
||||||
|
io_manager *io_ptr)
|
||||||
|
{
|
||||||
|
set_patch_io_backing_manager(*io_ptr);
|
||||||
|
set_patch_io_patch_file(patch_file);
|
||||||
|
*io_ptr = patch_io_manager;
|
||||||
|
printf(_("To make backup before applying changes run:\n"
|
||||||
|
" e2patch backup %s %s %s.backup\n"
|
||||||
|
"Then, to apply the operation to the real filesystem run:\n"
|
||||||
|
" e2patch apply %s %s\n"),
|
||||||
|
device, patch_file, patch_file, device, patch_file);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int resize2fs_setup_tdb(const char *device, char *undo_file,
|
static int resize2fs_setup_tdb(const char *device, char *undo_file,
|
||||||
io_manager *io_ptr)
|
io_manager *io_ptr)
|
||||||
{
|
{
|
||||||
|
@ -258,6 +272,7 @@ int main (int argc, char ** argv)
|
||||||
blk64_t new_size = 0;
|
blk64_t new_size = 0;
|
||||||
blk64_t max_size = 0;
|
blk64_t max_size = 0;
|
||||||
blk64_t min_size = 0;
|
blk64_t min_size = 0;
|
||||||
|
__u32 new_inodes = 0;
|
||||||
io_manager io_ptr;
|
io_manager io_ptr;
|
||||||
char *new_size_str = 0;
|
char *new_size_str = 0;
|
||||||
int use_stride = -1;
|
int use_stride = -1;
|
||||||
|
@ -267,7 +282,7 @@ int main (int argc, char ** argv)
|
||||||
unsigned int blocksize;
|
unsigned int blocksize;
|
||||||
long sysval;
|
long sysval;
|
||||||
int len, mount_flags;
|
int len, mount_flags;
|
||||||
char *mtpt, *undo_file = NULL;
|
char *mtpt, *undo_file = NULL, *patch_file = NULL;
|
||||||
|
|
||||||
#ifdef ENABLE_NLS
|
#ifdef ENABLE_NLS
|
||||||
setlocale(LC_MESSAGES, "");
|
setlocale(LC_MESSAGES, "");
|
||||||
|
@ -284,7 +299,7 @@ int main (int argc, char ** argv)
|
||||||
if (argc && *argv)
|
if (argc && *argv)
|
||||||
program_name = *argv;
|
program_name = *argv;
|
||||||
|
|
||||||
while ((c = getopt(argc, argv, "d:fFhMPpS:bsz:")) != EOF) {
|
while ((c = getopt(argc, argv, "d:fFhMPN:pS:bsT:z:")) != EOF) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'h':
|
case 'h':
|
||||||
usage(program_name);
|
usage(program_name);
|
||||||
|
@ -301,6 +316,9 @@ int main (int argc, char ** argv)
|
||||||
case 'P':
|
case 'P':
|
||||||
print_min_size = 1;
|
print_min_size = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'N':
|
||||||
|
new_inodes = strtoul(optarg, 0, 0);
|
||||||
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
flags |= atoi(optarg);
|
flags |= atoi(optarg);
|
||||||
break;
|
break;
|
||||||
|
@ -316,6 +334,9 @@ int main (int argc, char ** argv)
|
||||||
case 's':
|
case 's':
|
||||||
flags |= RESIZE_DISABLE_64BIT;
|
flags |= RESIZE_DISABLE_64BIT;
|
||||||
break;
|
break;
|
||||||
|
case 'T':
|
||||||
|
patch_file = optarg;
|
||||||
|
break;
|
||||||
case 'z':
|
case 'z':
|
||||||
undo_file = optarg;
|
undo_file = optarg;
|
||||||
break;
|
break;
|
||||||
|
@ -402,7 +423,11 @@ int main (int argc, char ** argv)
|
||||||
io_flags = EXT2_FLAG_RW | EXT2_FLAG_EXCLUSIVE;
|
io_flags = EXT2_FLAG_RW | EXT2_FLAG_EXCLUSIVE;
|
||||||
|
|
||||||
io_flags |= EXT2_FLAG_64BITS;
|
io_flags |= EXT2_FLAG_64BITS;
|
||||||
if (undo_file) {
|
if (patch_file) {
|
||||||
|
retval = resize2fs_setup_patch(device_name, patch_file, &io_ptr);
|
||||||
|
if (retval)
|
||||||
|
exit(1);
|
||||||
|
} else if (undo_file) {
|
||||||
retval = resize2fs_setup_tdb(device_name, undo_file, &io_ptr);
|
retval = resize2fs_setup_tdb(device_name, undo_file, &io_ptr);
|
||||||
if (retval)
|
if (retval)
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -583,7 +608,7 @@ int main (int argc, char ** argv)
|
||||||
"feature.\n"));
|
"feature.\n"));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
} else if (new_size == ext2fs_blocks_count(fs->super)) {
|
} else if (new_size == ext2fs_blocks_count(fs->super) && !new_inodes) {
|
||||||
fprintf(stderr, _("The filesystem is already %llu (%dk) "
|
fprintf(stderr, _("The filesystem is already %llu (%dk) "
|
||||||
"blocks long. Nothing to do!\n\n"), new_size,
|
"blocks long. Nothing to do!\n\n"), new_size,
|
||||||
blocksize / 1024);
|
blocksize / 1024);
|
||||||
|
@ -612,7 +637,7 @@ int main (int argc, char ** argv)
|
||||||
printf(_("Resizing the filesystem on "
|
printf(_("Resizing the filesystem on "
|
||||||
"%s to %llu (%dk) blocks.\n"),
|
"%s to %llu (%dk) blocks.\n"),
|
||||||
device_name, new_size, blocksize / 1024);
|
device_name, new_size, blocksize / 1024);
|
||||||
retval = resize_fs(fs, &new_size, flags,
|
retval = resize_fs(fs, &new_size, new_inodes, flags,
|
||||||
((flags & RESIZE_PERCENT_COMPLETE) ?
|
((flags & RESIZE_PERCENT_COMPLETE) ?
|
||||||
resize_progress_func : 0));
|
resize_progress_func : 0));
|
||||||
}
|
}
|
||||||
|
|
|
@ -159,6 +159,12 @@ program will heuristically determine the RAID stride that was specified
|
||||||
when the filesystem was created. This option allows the user to
|
when the filesystem was created. This option allows the user to
|
||||||
explicitly specify a RAID stride setting to be used by resize2fs instead.
|
explicitly specify a RAID stride setting to be used by resize2fs instead.
|
||||||
.TP
|
.TP
|
||||||
|
.BI \-T " patch_file"
|
||||||
|
Do not apply changes to the real filesystem; write updates into a sparse file
|
||||||
|
named 'patch_file' to safely apply them later with e2patch(8) utility.
|
||||||
|
You'll also be able to create a backup before applying patch and safely
|
||||||
|
restore it in case of power outage or system crash.
|
||||||
|
.TP
|
||||||
.BI \-z " undo_file"
|
.BI \-z " undo_file"
|
||||||
Before overwriting a file system block, write the old contents of the block to
|
Before overwriting a file system block, write the old contents of the block to
|
||||||
an undo file. This undo file can be used with e2undo(8) to restore the old
|
an undo file. This undo file can be used with e2undo(8) to restore the old
|
||||||
|
|
|
@ -45,19 +45,21 @@ static void fix_uninit_block_bitmaps(ext2_filsys fs);
|
||||||
static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size);
|
static errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size);
|
||||||
static errcode_t blocks_to_move(ext2_resize_t rfs);
|
static errcode_t blocks_to_move(ext2_resize_t rfs);
|
||||||
static errcode_t block_mover(ext2_resize_t rfs);
|
static errcode_t block_mover(ext2_resize_t rfs);
|
||||||
|
static errcode_t inodes_to_move(ext2_resize_t rfs);
|
||||||
static errcode_t inode_scan_and_fix(ext2_resize_t rfs);
|
static errcode_t inode_scan_and_fix(ext2_resize_t rfs);
|
||||||
static errcode_t inode_ref_fix(ext2_resize_t rfs);
|
static errcode_t inode_ref_fix(ext2_resize_t rfs);
|
||||||
static errcode_t move_itables(ext2_resize_t rfs);
|
static errcode_t move_itables(ext2_resize_t rfs);
|
||||||
|
static errcode_t move_inode_tables(ext2_resize_t rfs);
|
||||||
static errcode_t fix_resize_inode(ext2_filsys fs);
|
static errcode_t fix_resize_inode(ext2_filsys fs);
|
||||||
static errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs);
|
static errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs);
|
||||||
static errcode_t fix_sb_journal_backup(ext2_filsys fs);
|
static errcode_t fix_sb_journal_backup(ext2_filsys fs);
|
||||||
static errcode_t mark_table_blocks(ext2_filsys fs,
|
static errcode_t mark_table_blocks(ext2_filsys fs,
|
||||||
ext2fs_block_bitmap bmap);
|
ext2fs_block_bitmap bmap, int skip_inode_tables);
|
||||||
static errcode_t clear_sparse_super2_last_group(ext2_resize_t rfs);
|
static errcode_t clear_sparse_super2_last_group(ext2_resize_t rfs);
|
||||||
static errcode_t reserve_sparse_super2_last_group(ext2_resize_t rfs,
|
static errcode_t reserve_sparse_super2_last_group(ext2_resize_t rfs,
|
||||||
ext2fs_block_bitmap meta_bmap);
|
ext2fs_block_bitmap meta_bmap);
|
||||||
static errcode_t resize_group_descriptors(ext2_resize_t rfs, blk64_t new_size);
|
static errcode_t resize_group_descriptors(ext2_resize_t rfs, blk64_t new_size);
|
||||||
static errcode_t move_bg_metadata(ext2_resize_t rfs);
|
static errcode_t move_bg_metadata(ext2_resize_t rfs, __u32 new_inodes);
|
||||||
static errcode_t zero_high_bits_in_inodes(ext2_resize_t rfs);
|
static errcode_t zero_high_bits_in_inodes(ext2_resize_t rfs);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -94,7 +96,7 @@ static int lazy_itable_init;
|
||||||
/*
|
/*
|
||||||
* This is the top-level routine which does the dirty deed....
|
* This is the top-level routine which does the dirty deed....
|
||||||
*/
|
*/
|
||||||
errcode_t resize_fs(ext2_filsys fs, blk64_t *new_size, int flags,
|
errcode_t resize_fs(ext2_filsys fs, blk64_t *new_size, __u32 new_inodes, int flags,
|
||||||
errcode_t (*progress)(ext2_resize_t rfs, int pass,
|
errcode_t (*progress)(ext2_resize_t rfs, int pass,
|
||||||
unsigned long cur,
|
unsigned long cur,
|
||||||
unsigned long max_val))
|
unsigned long max_val))
|
||||||
|
@ -142,7 +144,7 @@ errcode_t resize_fs(ext2_filsys fs, blk64_t *new_size, int flags,
|
||||||
print_resource_track(rfs, &rtrack, fs->io);
|
print_resource_track(rfs, &rtrack, fs->io);
|
||||||
|
|
||||||
init_resource_track(&rtrack, "move_bg_metadata", fs->io);
|
init_resource_track(&rtrack, "move_bg_metadata", fs->io);
|
||||||
retval = move_bg_metadata(rfs);
|
retval = move_bg_metadata(rfs, new_inodes);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto errout;
|
goto errout;
|
||||||
print_resource_track(rfs, &rtrack, fs->io);
|
print_resource_track(rfs, &rtrack, fs->io);
|
||||||
|
@ -188,6 +190,18 @@ errcode_t resize_fs(ext2_filsys fs, blk64_t *new_size, int flags,
|
||||||
goto errout;
|
goto errout;
|
||||||
print_resource_track(rfs, &rtrack, fs->io);
|
print_resource_track(rfs, &rtrack, fs->io);
|
||||||
|
|
||||||
|
init_resource_track(&rtrack, "inodes_to_move", fs->io);
|
||||||
|
retval = inodes_to_move(rfs);
|
||||||
|
if (retval)
|
||||||
|
goto errout;
|
||||||
|
print_resource_track(rfs, &rtrack, fs->io);
|
||||||
|
|
||||||
|
init_resource_track(&rtrack, "move_inode_tables", fs->io);
|
||||||
|
retval = move_inode_tables(rfs);
|
||||||
|
if (retval)
|
||||||
|
goto errout;
|
||||||
|
print_resource_track(rfs, &rtrack, fs->io);
|
||||||
|
|
||||||
init_resource_track(&rtrack, "inode_scan_and_fix", fs->io);
|
init_resource_track(&rtrack, "inode_scan_and_fix", fs->io);
|
||||||
retval = inode_scan_and_fix(rfs);
|
retval = inode_scan_and_fix(rfs);
|
||||||
if (retval)
|
if (retval)
|
||||||
|
@ -200,11 +214,11 @@ errcode_t resize_fs(ext2_filsys fs, blk64_t *new_size, int flags,
|
||||||
goto errout;
|
goto errout;
|
||||||
print_resource_track(rfs, &rtrack, fs->io);
|
print_resource_track(rfs, &rtrack, fs->io);
|
||||||
|
|
||||||
init_resource_track(&rtrack, "move_itables", fs->io);
|
/* init_resource_track(&rtrack, "move_itables", fs->io);
|
||||||
retval = move_itables(rfs);
|
retval = move_itables(rfs);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto errout;
|
goto errout;
|
||||||
print_resource_track(rfs, &rtrack, fs->io);
|
print_resource_track(rfs, &rtrack, fs->io);*/
|
||||||
|
|
||||||
retval = clear_sparse_super2_last_group(rfs);
|
retval = clear_sparse_super2_last_group(rfs);
|
||||||
if (retval)
|
if (retval)
|
||||||
|
@ -344,8 +358,39 @@ static errcode_t resize_group_descriptors(ext2_resize_t rfs, blk64_t new_size)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inode table resizing:
|
||||||
|
* 1) move_bg_metadata(), calls set_inode_count(): set new inode count
|
||||||
|
* 2) adjust_superblock(): extend bitmaps, write group descriptors
|
||||||
|
* 3) blocks_to_move(): allocate new inode tables and, when extending inode tables,
|
||||||
|
* mark extra blocks needed for new inode tables as 'blocks to move'
|
||||||
|
* 4) block_mover(): move blocks out of the way as usual
|
||||||
|
* 5) inodes_to_move(): when shrinking inode tables, move inodes from the end
|
||||||
|
* of each group's inode table (still operating on old fs inode tables).
|
||||||
|
* it would be possible to rewrite blocks on step 7, but we need to read
|
||||||
|
* extents, and they may be overwritten by inode tables on step 6.
|
||||||
|
* so, rewrite blocks used by inodes here!
|
||||||
|
* 6) move_inode_tables(): move inode tables
|
||||||
|
* 7) inode_scan_and_fix(): rewrite all inode, extent, extattr and ACL checksums
|
||||||
|
* 8) inode_ref_fix(): translate inode numbers (operating on new fs inode tables)
|
||||||
|
*/
|
||||||
|
static int set_inode_count(ext2_filsys fs, __u32 new_inodes)
|
||||||
|
{
|
||||||
|
__u32 old_ipg = fs->super->s_inodes_per_group;
|
||||||
|
__u32 new_ipg = ((new_inodes + fs->group_desc_count - 1) / fs->group_desc_count);
|
||||||
|
new_ipg = (((new_ipg * EXT2_INODE_SIZE(fs->super)) + EXT2_BLOCK_SIZE(fs->super) - 1) / EXT2_BLOCK_SIZE(fs->super))
|
||||||
|
* EXT2_BLOCK_SIZE(fs->super) / EXT2_INODE_SIZE(fs->super);
|
||||||
|
if (new_ipg == old_ipg)
|
||||||
|
return -1;
|
||||||
|
fs->inode_blocks_per_group = new_ipg * EXT2_INODE_SIZE(fs->super) / EXT2_BLOCK_SIZE(fs->super);
|
||||||
|
fs->super->s_inodes_per_group = new_ipg;
|
||||||
|
fs->super->s_inodes_count = fs->group_desc_count * fs->super->s_inodes_per_group;
|
||||||
|
fs->super->s_free_inodes_count += fs->group_desc_count * (new_ipg - old_ipg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Move bitmaps/inode tables out of the way. */
|
/* Move bitmaps/inode tables out of the way. */
|
||||||
static errcode_t move_bg_metadata(ext2_resize_t rfs)
|
static errcode_t move_bg_metadata(ext2_resize_t rfs, __u32 new_inodes)
|
||||||
{
|
{
|
||||||
dgrp_t i;
|
dgrp_t i;
|
||||||
blk64_t b, c, d, old_desc_blocks, new_desc_blocks, j;
|
blk64_t b, c, d, old_desc_blocks, new_desc_blocks, j;
|
||||||
|
@ -354,7 +399,12 @@ static errcode_t move_bg_metadata(ext2_resize_t rfs)
|
||||||
errcode_t retval;
|
errcode_t retval;
|
||||||
int cluster_ratio;
|
int cluster_ratio;
|
||||||
|
|
||||||
if (!(rfs->flags & (RESIZE_DISABLE_64BIT | RESIZE_ENABLE_64BIT)))
|
if (new_inodes) {
|
||||||
|
if (set_inode_count(rfs->new_fs, new_inodes) != 0)
|
||||||
|
new_inodes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!new_inodes && !(rfs->flags & (RESIZE_DISABLE_64BIT | RESIZE_ENABLE_64BIT)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
retval = ext2fs_allocate_block_bitmap(rfs->old_fs, "oldfs", &old_map);
|
retval = ext2fs_allocate_block_bitmap(rfs->old_fs, "oldfs", &old_map);
|
||||||
|
@ -644,7 +694,7 @@ static errcode_t free_gdp_blocks(ext2_filsys fs,
|
||||||
if (retval)
|
if (retval)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
retval = mark_table_blocks(fs, bg_map);
|
retval = mark_table_blocks(fs, bg_map, 0);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -1011,7 +1061,7 @@ retry:
|
||||||
* number of the block group descriptors.
|
* number of the block group descriptors.
|
||||||
*/
|
*/
|
||||||
if (reserve_blocks)
|
if (reserve_blocks)
|
||||||
mark_table_blocks(fs, reserve_blocks);
|
mark_table_blocks(fs, reserve_blocks, 0);
|
||||||
|
|
||||||
errout:
|
errout:
|
||||||
return (retval);
|
return (retval);
|
||||||
|
@ -1145,7 +1195,7 @@ errout:
|
||||||
* filesystem meta-data blocks.
|
* filesystem meta-data blocks.
|
||||||
*/
|
*/
|
||||||
static errcode_t mark_table_blocks(ext2_filsys fs,
|
static errcode_t mark_table_blocks(ext2_filsys fs,
|
||||||
ext2fs_block_bitmap bmap)
|
ext2fs_block_bitmap bmap, int skip_inode_tables)
|
||||||
{
|
{
|
||||||
dgrp_t i;
|
dgrp_t i;
|
||||||
blk64_t blk;
|
blk64_t blk;
|
||||||
|
@ -1156,10 +1206,12 @@ static errcode_t mark_table_blocks(ext2_filsys fs,
|
||||||
/*
|
/*
|
||||||
* Mark the blocks used for the inode table
|
* Mark the blocks used for the inode table
|
||||||
*/
|
*/
|
||||||
blk = ext2fs_inode_table_loc(fs, i);
|
if (!skip_inode_tables) {
|
||||||
if (blk)
|
blk = ext2fs_inode_table_loc(fs, i);
|
||||||
ext2fs_mark_block_bitmap_range2(bmap, blk,
|
if (blk)
|
||||||
fs->inode_blocks_per_group);
|
ext2fs_mark_block_bitmap_range2(bmap, blk,
|
||||||
|
fs->inode_blocks_per_group);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mark block used for the block bitmap
|
* Mark block used for the block bitmap
|
||||||
|
@ -1283,12 +1335,69 @@ static errcode_t blocks_to_move(ext2_resize_t rfs)
|
||||||
if (retval)
|
if (retval)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
retval = mark_table_blocks(old_fs, meta_bmap);
|
retval = mark_table_blocks(old_fs, meta_bmap, 0);
|
||||||
if (retval)
|
if (retval)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
fs = rfs->new_fs;
|
fs = rfs->new_fs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If we're resizing inode tables, we need to reallocate all of them
|
||||||
|
*/
|
||||||
|
if (rfs->old_fs->inode_blocks_per_group != fs->inode_blocks_per_group) {
|
||||||
|
dgrp_t flexbg_size, flex_count, grp_in_flex;
|
||||||
|
ext2fs_block_bitmap empty_bmap;
|
||||||
|
/* // this is how mke2fs allocates inode tables...
|
||||||
|
retval = ext2fs_make_generic_bitmap(EXT2_ET_MAGIC_BLOCK_BITMAP, fs,
|
||||||
|
fs->super->s_first_data_block,
|
||||||
|
ext2fs_blocks_count(fs->super)-1,
|
||||||
|
ext2fs_blocks_count(fs->super)-1, "subcluster inode table bitmap", 0, &empty_bmap);*/
|
||||||
|
retval = ext2fs_allocate_block_bitmap(fs, _("metadata without inode tables"), &empty_bmap);
|
||||||
|
if (retval) {
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
retval = mark_table_blocks(fs, empty_bmap, 1);
|
||||||
|
if (retval) {
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
if (EXT2_HAS_INCOMPAT_FEATURE(fs->super, EXT4_FEATURE_INCOMPAT_FLEX_BG)
|
||||||
|
&& fs->super->s_log_groups_per_flex) {
|
||||||
|
flexbg_size = 1 << fs->super->s_log_groups_per_flex;
|
||||||
|
} else {
|
||||||
|
flexbg_size = 1;
|
||||||
|
}
|
||||||
|
flex_count = (fs->group_desc_count + flexbg_size - 1) / flexbg_size;
|
||||||
|
for (g = 0; g < fs->group_desc_count; g++) {
|
||||||
|
ext2fs_inode_table_loc_set(fs, g, 0);
|
||||||
|
retval = ext2fs_allocate_group_table(fs, g, empty_bmap);
|
||||||
|
if (retval) {
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
/* ext2fs_mark_block_bitmap_range2(empty_bmap,
|
||||||
|
ext2fs_inode_table_loc(fs, g), fs->inode_blocks_per_group);*/
|
||||||
|
group_blk = ext2fs_inode_table_loc(fs, g);
|
||||||
|
if (g > 0 && group_blk < ext2fs_inode_table_loc(fs, g-1)+fs->inode_blocks_per_group) {
|
||||||
|
ext2fs_unmark_block_bitmap_range2(fs->block_map, group_blk, fs->inode_blocks_per_group);
|
||||||
|
group_blk = ext2fs_inode_table_loc(fs, g-1)+fs->inode_blocks_per_group;
|
||||||
|
ext2fs_inode_table_loc_set(fs, g, group_blk);
|
||||||
|
ext2fs_group_desc_csum_set(fs, g);
|
||||||
|
ext2fs_mark_block_bitmap_range2(fs->block_map, group_blk, fs->inode_blocks_per_group);
|
||||||
|
}
|
||||||
|
group_blk += fs->inode_blocks_per_group;
|
||||||
|
// We may need to move some blocks away (mainly if extending inode tables)
|
||||||
|
for (blk = ext2fs_inode_table_loc(fs, g); blk < group_blk; blk++) {
|
||||||
|
if (blk < ext2fs_blocks_count(old_fs->super) &&
|
||||||
|
ext2fs_test_block_bitmap2(old_fs->block_map, blk) &&
|
||||||
|
!ext2fs_test_block_bitmap2(meta_bmap, blk)) {
|
||||||
|
ext2fs_mark_block_bitmap2(rfs->move_blocks, blk);
|
||||||
|
rfs->needed_blocks++;
|
||||||
|
}
|
||||||
|
ext2fs_mark_block_bitmap2(rfs->reserve_blocks, blk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ext2fs_free_block_bitmap(empty_bmap);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we're shrinking the filesystem, we need to move any
|
* If we're shrinking the filesystem, we need to move any
|
||||||
* group's metadata blocks (either allocation bitmaps or the
|
* group's metadata blocks (either allocation bitmaps or the
|
||||||
|
@ -1387,7 +1496,7 @@ static errcode_t blocks_to_move(ext2_resize_t rfs)
|
||||||
if (retval)
|
if (retval)
|
||||||
goto errout;
|
goto errout;
|
||||||
|
|
||||||
retval = mark_table_blocks(fs, new_meta_bmap);
|
retval = mark_table_blocks(fs, new_meta_bmap, 0);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
@ -1848,7 +1957,7 @@ static int process_block(ext2_filsys fs, blk64_t *block_nr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pb->is_dir) {
|
if (pb->is_dir && fs->dblist) {
|
||||||
retval = ext2fs_add_dir_block2(fs->dblist, pb->ino,
|
retval = ext2fs_add_dir_block2(fs->dblist, pb->ino,
|
||||||
block, (int) blockcnt);
|
block, (int) blockcnt);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
|
@ -1895,27 +2004,27 @@ static errcode_t migrate_ea_block(ext2_resize_t rfs, ext2_ino_t ino,
|
||||||
errcode_t err = 0;
|
errcode_t err = 0;
|
||||||
|
|
||||||
/* No EA block or no remapping? Quit early. */
|
/* No EA block or no remapping? Quit early. */
|
||||||
if (ext2fs_file_acl_block(rfs->old_fs, inode) == 0 || !rfs->bmap)
|
if (ext2fs_file_acl_block(rfs->new_fs, inode) == 0 || !rfs->bmap)
|
||||||
return 0;
|
return 0;
|
||||||
new_block = extent_translate(rfs->old_fs, rfs->bmap,
|
new_block = extent_translate(rfs->new_fs, rfs->bmap,
|
||||||
ext2fs_file_acl_block(rfs->old_fs, inode));
|
ext2fs_file_acl_block(rfs->new_fs, inode));
|
||||||
if (new_block == 0)
|
if (new_block == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Set the new ACL block */
|
/* Set the new ACL block */
|
||||||
ext2fs_file_acl_block_set(rfs->old_fs, inode, new_block);
|
ext2fs_file_acl_block_set(rfs->new_fs, inode, new_block);
|
||||||
|
|
||||||
/* Update checksum */
|
/* Update checksum */
|
||||||
if (ext2fs_has_feature_metadata_csum(rfs->new_fs->super)) {
|
if (ext2fs_has_feature_metadata_csum(rfs->new_fs->super)) {
|
||||||
err = ext2fs_get_mem(rfs->old_fs->blocksize, &buf);
|
err = ext2fs_get_mem(rfs->new_fs->blocksize, &buf);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
rfs->old_fs->flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS;
|
rfs->new_fs->flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS;
|
||||||
err = ext2fs_read_ext_attr3(rfs->old_fs, new_block, buf, ino);
|
err = ext2fs_read_ext_attr3(rfs->new_fs, new_block, buf, ino);
|
||||||
rfs->old_fs->flags &= ~EXT2_FLAG_IGNORE_CSUM_ERRORS;
|
rfs->new_fs->flags &= ~EXT2_FLAG_IGNORE_CSUM_ERRORS;
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
err = ext2fs_write_ext_attr3(rfs->old_fs, new_block, buf, ino);
|
err = ext2fs_write_ext_attr3(rfs->new_fs, new_block, buf, ino);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -1986,52 +2095,62 @@ static void quiet_com_err_proc(const char *whoami EXT2FS_ATTR((unused)),
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static errcode_t inode_scan_and_fix(ext2_resize_t rfs)
|
#define TRANSLATE_IPG(ino,old_fs,new_fs) (1 + (((ino)-1) % (old_fs)->super->s_inodes_per_group) + \
|
||||||
|
((ino)-1) / (old_fs)->super->s_inodes_per_group * (new_fs)->super->s_inodes_per_group)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move inodes and rewrite references to blocks moved in blocks_to_move()
|
||||||
|
*/
|
||||||
|
static errcode_t inodes_to_move(ext2_resize_t rfs)
|
||||||
{
|
{
|
||||||
struct process_block_struct pb;
|
struct process_block_struct pb;
|
||||||
ext2_ino_t ino, new_inode;
|
ext2_ino_t ino, new_inode, tr_ino;
|
||||||
struct ext2_inode *inode = NULL;
|
struct ext2_inode *inode = NULL;
|
||||||
ext2_inode_scan scan = NULL;
|
ext2_inode_scan scan = NULL;
|
||||||
errcode_t retval;
|
errcode_t retval;
|
||||||
|
dgrp_t g, old_g;
|
||||||
char *block_buf = 0;
|
char *block_buf = 0;
|
||||||
ext2_ino_t start_to_move;
|
ext2_ino_t start_to_move;
|
||||||
int inode_size;
|
int inode_size;
|
||||||
|
int shrink_inodes = rfs->old_fs->inode_blocks_per_group > rfs->new_fs->inode_blocks_per_group;
|
||||||
|
int change_inodes = rfs->old_fs->inode_blocks_per_group != rfs->new_fs->inode_blocks_per_group;
|
||||||
|
|
||||||
if ((rfs->old_fs->group_desc_count <=
|
if ((rfs->old_fs->group_desc_count <=
|
||||||
rfs->new_fs->group_desc_count) &&
|
rfs->new_fs->group_desc_count) &&
|
||||||
!rfs->bmap)
|
!rfs->bmap &&
|
||||||
|
!change_inodes)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
set_com_err_hook(quiet_com_err_proc);
|
|
||||||
|
|
||||||
retval = ext2fs_open_inode_scan(rfs->old_fs, 0, &scan);
|
retval = ext2fs_open_inode_scan(rfs->old_fs, 0, &scan);
|
||||||
if (retval) goto errout;
|
if (retval) goto errout;
|
||||||
|
|
||||||
retval = ext2fs_init_dblist(rfs->old_fs, 0);
|
|
||||||
if (retval) goto errout;
|
|
||||||
retval = ext2fs_get_array(rfs->old_fs->blocksize, 3, &block_buf);
|
|
||||||
if (retval) goto errout;
|
|
||||||
|
|
||||||
start_to_move = (rfs->new_fs->group_desc_count *
|
start_to_move = (rfs->new_fs->group_desc_count *
|
||||||
rfs->new_fs->super->s_inodes_per_group);
|
rfs->old_fs->super->s_inodes_per_group);
|
||||||
|
for (ino = start_to_move+1; ino <= rfs->old_fs->group_desc_count * rfs->old_fs->super->s_inodes_per_group; ino++) {
|
||||||
if (rfs->progress) {
|
ext2fs_mark_inode_bitmap2(rfs->old_fs->inode_map, ino);
|
||||||
retval = (rfs->progress)(rfs, E2_RSZ_INODE_SCAN_PASS,
|
|
||||||
0, rfs->old_fs->group_desc_count);
|
|
||||||
if (retval)
|
|
||||||
goto errout;
|
|
||||||
}
|
}
|
||||||
ext2fs_set_inode_callback(scan, progress_callback, (void *) rfs);
|
if (shrink_inodes) {
|
||||||
pb.rfs = rfs;
|
for (g = 0; g < rfs->old_fs->group_desc_count; g++) {
|
||||||
pb.inode = inode;
|
ext2_ino_t first_ino = 1+rfs->old_fs->super->s_inodes_per_group*g;
|
||||||
pb.error = 0;
|
for (ino = first_ino+rfs->new_fs->super->s_inodes_per_group; ino < first_ino+rfs->old_fs->super->s_inodes_per_group; ino++) {
|
||||||
new_inode = EXT2_FIRST_INODE(rfs->new_fs->super);
|
ext2fs_mark_inode_bitmap2(rfs->old_fs->inode_map, ino);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
retval = ext2fs_get_array(rfs->new_fs->blocksize, 3, &block_buf);
|
||||||
|
if (retval) goto errout;
|
||||||
|
|
||||||
inode_size = EXT2_INODE_SIZE(rfs->new_fs->super);
|
inode_size = EXT2_INODE_SIZE(rfs->new_fs->super);
|
||||||
inode = malloc(inode_size);
|
inode = malloc(inode_size);
|
||||||
if (!inode) {
|
if (!inode) {
|
||||||
retval = ENOMEM;
|
retval = ENOMEM;
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
pb.rfs = rfs;
|
||||||
|
pb.inode = inode;
|
||||||
|
pb.error = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First, copy all of the inodes that need to be moved
|
* First, copy all of the inodes that need to be moved
|
||||||
* elsewhere in the inode table
|
* elsewhere in the inode table
|
||||||
|
@ -2045,78 +2164,68 @@ static errcode_t inode_scan_and_fix(ext2_resize_t rfs)
|
||||||
if (inode->i_links_count == 0 && ino != EXT2_RESIZE_INO)
|
if (inode->i_links_count == 0 && ino != EXT2_RESIZE_INO)
|
||||||
continue; /* inode not in use */
|
continue; /* inode not in use */
|
||||||
|
|
||||||
pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
|
|
||||||
pb.changed = 0;
|
|
||||||
|
|
||||||
/* Remap EA block */
|
|
||||||
retval = migrate_ea_block(rfs, ino, inode, &pb.changed);
|
|
||||||
if (retval)
|
|
||||||
goto errout;
|
|
||||||
|
|
||||||
new_inode = ino;
|
new_inode = ino;
|
||||||
if (ino <= start_to_move)
|
if (ino > start_to_move ||
|
||||||
goto remap_blocks; /* Don't need to move inode. */
|
(shrink_inodes && (ino-1) % rfs->old_fs->super->s_inodes_per_group >= rfs->new_fs->super->s_inodes_per_group))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Find a new inode. Now that extents and directory blocks
|
||||||
|
* are tied to the inode number through the checksum, we must
|
||||||
|
* set up the new inode before we start rewriting blocks.
|
||||||
|
*/
|
||||||
|
retval = ext2fs_new_inode(rfs->old_fs, 0, 0, 0, &new_inode);
|
||||||
|
if (retval)
|
||||||
|
goto errout;
|
||||||
|
|
||||||
/*
|
/* Translate inode number according to new inodes_per_group */
|
||||||
* Find a new inode. Now that extents and directory blocks
|
tr_ino = TRANSLATE_IPG(new_inode, rfs->old_fs, rfs->new_fs);
|
||||||
* are tied to the inode number through the checksum, we must
|
|
||||||
* set up the new inode before we start rewriting blocks.
|
|
||||||
*/
|
|
||||||
retval = ext2fs_new_inode(rfs->new_fs, 0, 0, 0, &new_inode);
|
|
||||||
if (retval)
|
|
||||||
goto errout;
|
|
||||||
|
|
||||||
ext2fs_inode_alloc_stats2(rfs->new_fs, new_inode, +1,
|
old_g = ext2fs_group_of_ino(rfs->old_fs, ino);
|
||||||
pb.is_dir);
|
ext2fs_inode_alloc_stats2(rfs->old_fs, new_inode, +1, LINUX_S_ISDIR(inode->i_mode));
|
||||||
inode->i_ctime = time(0);
|
if (old_g < rfs->new_fs->group_desc_count)
|
||||||
retval = ext2fs_write_inode_full(rfs->old_fs, new_inode,
|
{
|
||||||
inode, inode_size);
|
/*
|
||||||
if (retval)
|
* Don't bother to adjust free_inodes_count for group because freed
|
||||||
goto errout;
|
* inodes will be accounted as part of inodes_per_group change
|
||||||
pb.changed = 0;
|
*/
|
||||||
|
if (LINUX_S_ISDIR(inode->i_mode))
|
||||||
|
ext2fs_bg_used_dirs_count_set(rfs->new_fs, old_g, ext2fs_bg_used_dirs_count(rfs->new_fs, old_g) - 1);
|
||||||
|
ext2fs_group_desc_csum_set(rfs->new_fs, old_g);
|
||||||
|
}
|
||||||
|
ext2fs_inode_alloc_stats2(rfs->new_fs, tr_ino, +1, LINUX_S_ISDIR(inode->i_mode));
|
||||||
|
inode->i_ctime = time(0);
|
||||||
|
retval = ext2fs_write_inode_full(rfs->old_fs, new_inode, inode, inode_size);
|
||||||
|
if (retval)
|
||||||
|
goto errout;
|
||||||
|
|
||||||
#ifdef RESIZE2FS_DEBUG
|
#ifdef RESIZE2FS_DEBUG
|
||||||
if (rfs->flags & RESIZE_DEBUG_INODEMAP)
|
if (rfs->flags & RESIZE_DEBUG_INODEMAP)
|
||||||
printf("Inode moved %u->%u\n", ino, new_inode);
|
printf("Inode moved %u->%u\n", ino, new_inode);
|
||||||
#endif
|
#endif
|
||||||
if (!rfs->imap) {
|
|
||||||
retval = ext2fs_create_extent_table(&rfs->imap, 0);
|
|
||||||
if (retval)
|
|
||||||
goto errout;
|
|
||||||
}
|
|
||||||
ext2fs_add_extent_entry(rfs->imap, ino, new_inode);
|
|
||||||
|
|
||||||
remap_blocks:
|
if (!rfs->imap) {
|
||||||
if (pb.changed)
|
retval = ext2fs_create_extent_table(&rfs->imap, 0);
|
||||||
retval = ext2fs_write_inode_full(rfs->old_fs,
|
if (retval)
|
||||||
new_inode,
|
goto errout;
|
||||||
inode, inode_size);
|
}
|
||||||
if (retval)
|
ext2fs_add_extent_entry(rfs->imap, ino, new_inode);
|
||||||
goto errout;
|
|
||||||
|
|
||||||
/* Rewrite extent block checksums with new inode number */
|
// continue with rewritten inode number
|
||||||
if (ext2fs_has_feature_metadata_csum(rfs->old_fs->super) &&
|
ino = new_inode;
|
||||||
(inode->i_flags & EXT4_EXTENTS_FL)) {
|
|
||||||
rfs->old_fs->flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS;
|
|
||||||
retval = rewrite_extents(rfs->old_fs, new_inode);
|
|
||||||
rfs->old_fs->flags &= ~EXT2_FLAG_IGNORE_CSUM_ERRORS;
|
|
||||||
if (retval)
|
|
||||||
goto errout;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update inodes to point to new blocks; schedule directory
|
* Update inodes to point to new blocks.
|
||||||
* blocks for inode remapping. Need to write out dir blocks
|
|
||||||
* with new inode numbers if we have metadata_csum enabled.
|
|
||||||
*/
|
*/
|
||||||
if (ext2fs_inode_has_valid_blocks2(rfs->old_fs, inode) &&
|
if (ext2fs_inode_has_valid_blocks2(rfs->old_fs, inode) && rfs->bmap) {
|
||||||
(rfs->bmap || pb.is_dir)) {
|
pb.changed = 0;
|
||||||
pb.ino = new_inode;
|
pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
|
||||||
pb.old_ino = ino;
|
pb.ino = ino;
|
||||||
|
pb.old_ino = ino; // FIXME debug output will show translated inodes
|
||||||
pb.has_extents = inode->i_flags & EXT4_EXTENTS_FL;
|
pb.has_extents = inode->i_flags & EXT4_EXTENTS_FL;
|
||||||
rfs->old_fs->flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS;
|
rfs->old_fs->flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS;
|
||||||
retval = ext2fs_block_iterate3(rfs->old_fs,
|
retval = ext2fs_block_iterate3(rfs->old_fs,
|
||||||
new_inode, 0, block_buf,
|
ino, 0, block_buf,
|
||||||
process_block, &pb);
|
process_block, &pb);
|
||||||
rfs->old_fs->flags &= ~EXT2_FLAG_IGNORE_CSUM_ERRORS;
|
rfs->old_fs->flags &= ~EXT2_FLAG_IGNORE_CSUM_ERRORS;
|
||||||
if (retval)
|
if (retval)
|
||||||
|
@ -2125,16 +2234,134 @@ remap_blocks:
|
||||||
retval = pb.error;
|
retval = pb.error;
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
} else if ((inode->i_flags & EXT4_INLINE_DATA_FL) &&
|
}
|
||||||
(rfs->bmap || pb.is_dir)) {
|
}
|
||||||
|
|
||||||
|
errout:
|
||||||
|
if (scan)
|
||||||
|
ext2fs_close_inode_scan(scan);
|
||||||
|
if (block_buf)
|
||||||
|
ext2fs_free_mem(&block_buf);
|
||||||
|
free(inode);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remap extattr blocks, rewrite inode and extattr checksums
|
||||||
|
* and schedule directory blocks for inode remapping
|
||||||
|
*/
|
||||||
|
static errcode_t inode_scan_and_fix(ext2_resize_t rfs)
|
||||||
|
{
|
||||||
|
struct process_block_struct pb;
|
||||||
|
ext2_ino_t ino, tr_ino;
|
||||||
|
struct ext2_inode *inode = NULL;
|
||||||
|
ext2_inode_scan scan = NULL;
|
||||||
|
errcode_t retval;
|
||||||
|
dgrp_t g;
|
||||||
|
char *block_buf = 0;
|
||||||
|
int inode_size;
|
||||||
|
int change_inodes = rfs->old_fs->inode_blocks_per_group != rfs->new_fs->inode_blocks_per_group;
|
||||||
|
|
||||||
|
if ((rfs->old_fs->group_desc_count <=
|
||||||
|
rfs->new_fs->group_desc_count) &&
|
||||||
|
!rfs->bmap &&
|
||||||
|
!change_inodes)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
set_com_err_hook(quiet_com_err_proc);
|
||||||
|
|
||||||
|
retval = ext2fs_open_inode_scan(rfs->new_fs, 0, &scan);
|
||||||
|
if (retval) goto errout;
|
||||||
|
|
||||||
|
retval = ext2fs_init_dblist(rfs->new_fs, 0);
|
||||||
|
if (retval) goto errout;
|
||||||
|
retval = ext2fs_get_array(rfs->new_fs->blocksize, 3, &block_buf);
|
||||||
|
if (retval) goto errout;
|
||||||
|
|
||||||
|
if (rfs->progress) {
|
||||||
|
retval = (rfs->progress)(rfs, E2_RSZ_INODE_SCAN_PASS,
|
||||||
|
0, rfs->new_fs->group_desc_count);
|
||||||
|
if (retval)
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
ext2fs_set_inode_callback(scan, progress_callback, (void *) rfs);
|
||||||
|
inode_size = EXT2_INODE_SIZE(rfs->new_fs->super);
|
||||||
|
inode = malloc(inode_size);
|
||||||
|
if (!inode) {
|
||||||
|
retval = ENOMEM;
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
pb.rfs = rfs;
|
||||||
|
pb.inode = inode;
|
||||||
|
pb.error = 0;
|
||||||
|
/*
|
||||||
|
* First, copy all of the inodes that need to be moved
|
||||||
|
* elsewhere in the inode table
|
||||||
|
*/
|
||||||
|
while (1) {
|
||||||
|
rfs->new_fs->flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS;
|
||||||
|
retval = ext2fs_get_next_inode_full(scan, &ino, inode, inode_size);
|
||||||
|
rfs->new_fs->flags &= ~EXT2_FLAG_IGNORE_CSUM_ERRORS;
|
||||||
|
if (retval) goto errout;
|
||||||
|
if (!ino)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (inode->i_links_count == 0 && ino != EXT2_RESIZE_INO)
|
||||||
|
continue; /* inode not in use */
|
||||||
|
|
||||||
|
pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
|
||||||
|
pb.changed = change_inodes;
|
||||||
|
|
||||||
|
/* Remap EA block */
|
||||||
|
retval = migrate_ea_block(rfs, ino, inode, &pb.changed);
|
||||||
|
if (retval)
|
||||||
|
goto errout;
|
||||||
|
|
||||||
|
if (pb.changed)
|
||||||
|
retval = ext2fs_write_inode_full(rfs->new_fs,
|
||||||
|
ino,
|
||||||
|
inode, inode_size);
|
||||||
|
if (retval)
|
||||||
|
goto errout;
|
||||||
|
|
||||||
|
/* Rewrite extent block checksums with new inode number */
|
||||||
|
if (ext2fs_has_feature_metadata_csum(rfs->new_fs->super) &&
|
||||||
|
(inode->i_flags & EXT4_EXTENTS_FL)) {
|
||||||
|
rfs->new_fs->flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS;
|
||||||
|
retval = rewrite_extents(rfs->new_fs, ino);
|
||||||
|
rfs->new_fs->flags &= ~EXT2_FLAG_IGNORE_CSUM_ERRORS;
|
||||||
|
if (retval)
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Schedule directory blocks for inode remapping. Need to write out dir blocks
|
||||||
|
* with new inode numbers if we have metadata_csum enabled.
|
||||||
|
*/
|
||||||
|
if (ext2fs_inode_has_valid_blocks2(rfs->new_fs, inode) && pb.is_dir) {
|
||||||
|
pb.ino = ino;
|
||||||
|
pb.old_ino = ino; // FIXME: Debug output will show translated inodes
|
||||||
|
pb.has_extents = inode->i_flags & EXT4_EXTENTS_FL;
|
||||||
|
rfs->new_fs->flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS;
|
||||||
|
retval = ext2fs_block_iterate3(rfs->new_fs,
|
||||||
|
ino, 0, block_buf,
|
||||||
|
process_block, &pb);
|
||||||
|
rfs->new_fs->flags &= ~EXT2_FLAG_IGNORE_CSUM_ERRORS;
|
||||||
|
if (retval)
|
||||||
|
goto errout;
|
||||||
|
if (pb.error) {
|
||||||
|
retval = pb.error;
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
} else if ((inode->i_flags & EXT4_INLINE_DATA_FL) && pb.is_dir) {
|
||||||
/* inline data dir; update it too */
|
/* inline data dir; update it too */
|
||||||
retval = ext2fs_add_dir_block2(rfs->old_fs->dblist,
|
retval = ext2fs_add_dir_block2(rfs->new_fs->dblist,
|
||||||
new_inode, 0, 0);
|
tr_ino, 0, 0);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
io_channel_flush(rfs->old_fs->io);
|
io_channel_flush(rfs->new_fs->io);
|
||||||
|
|
||||||
errout:
|
errout:
|
||||||
reset_com_err_hook();
|
reset_com_err_hook();
|
||||||
|
@ -2150,6 +2377,140 @@ errout:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static errcode_t move_inode_tables(ext2_resize_t rfs)
|
||||||
|
{
|
||||||
|
dgrp_t g, end_g, group_count;
|
||||||
|
dgrp_t move_start, move_count;
|
||||||
|
__u32 old_ipg = rfs->old_fs->super->s_inodes_per_group;
|
||||||
|
__u32 new_ipg = rfs->new_fs->super->s_inodes_per_group;
|
||||||
|
__u32 old_ibg = rfs->old_fs->inode_blocks_per_group;
|
||||||
|
__u32 new_ibg = rfs->new_fs->inode_blocks_per_group;
|
||||||
|
int retval;
|
||||||
|
blk64_t size, blk, ib;
|
||||||
|
int change_inodes = old_ibg != new_ibg;
|
||||||
|
__u32 unused, ino, old_ino, i;
|
||||||
|
ext2fs_block_bitmap meta_bmap = NULL;
|
||||||
|
|
||||||
|
retval = ext2fs_allocate_block_bitmap(rfs->new_fs, _("meta-data blocks"), &meta_bmap);
|
||||||
|
if (retval)
|
||||||
|
return retval;
|
||||||
|
retval = mark_table_blocks(rfs->new_fs, meta_bmap, 1);
|
||||||
|
|
||||||
|
printf("inode blocks per group: %u to %u\n", old_ibg, new_ibg);
|
||||||
|
size = old_ibg;
|
||||||
|
size = size < new_ibg ? size : new_ibg;
|
||||||
|
move_count = 0;
|
||||||
|
group_count = rfs->new_fs->group_desc_count;
|
||||||
|
group_count = group_count < rfs->old_fs->group_desc_count ? group_count : rfs->old_fs->group_desc_count;
|
||||||
|
for (g = 0; g < group_count; g++)
|
||||||
|
{
|
||||||
|
if (change_inodes)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* new_fs may have incorrect itable_unused because we're not adjusting it
|
||||||
|
* before calling inode_alloc_stats2 in inodes_to_move().
|
||||||
|
* and it's OK to take free_inodes_count from old_fs because any inodes
|
||||||
|
* that are freed may only lay in shrinked inode table areas.
|
||||||
|
*/
|
||||||
|
unused = ext2fs_bg_itable_unused(rfs->old_fs, g);
|
||||||
|
if (new_ipg < old_ipg && unused < old_ipg-new_ipg)
|
||||||
|
unused = 0;
|
||||||
|
else
|
||||||
|
unused = unused + new_ipg - old_ipg;
|
||||||
|
ext2fs_bg_itable_unused_set(rfs->new_fs, g, unused);
|
||||||
|
ext2fs_bg_free_inodes_count_set(rfs->new_fs, g,
|
||||||
|
ext2fs_bg_free_inodes_count(rfs->old_fs, g) + new_ipg - old_ipg);
|
||||||
|
ext2fs_group_desc_csum_set(rfs->new_fs, g);
|
||||||
|
}
|
||||||
|
printf("g%u = [%u?] %u->%u free=%u->%u unused=%u->%u\n", g,
|
||||||
|
g > 0 ? ext2fs_inode_table_loc(rfs->old_fs, g-1)+old_ibg : 0,
|
||||||
|
ext2fs_inode_table_loc(rfs->old_fs, g),
|
||||||
|
ext2fs_inode_table_loc(rfs->new_fs, g),
|
||||||
|
ext2fs_bg_free_inodes_count(rfs->old_fs, g),
|
||||||
|
ext2fs_bg_free_inodes_count(rfs->new_fs, g),
|
||||||
|
ext2fs_bg_itable_unused(rfs->old_fs, g),
|
||||||
|
ext2fs_bg_itable_unused(rfs->new_fs, g));
|
||||||
|
if (change_inodes || ext2fs_inode_table_loc(rfs->new_fs, g) != ext2fs_inode_table_loc(rfs->old_fs, g))
|
||||||
|
{
|
||||||
|
move_count++;
|
||||||
|
if (move_count == 1)
|
||||||
|
move_start = g;
|
||||||
|
// check for overlap
|
||||||
|
if (g < rfs->new_fs->group_desc_count-1 &&
|
||||||
|
ext2fs_inode_table_loc(rfs->new_fs, g)+new_ibg > ext2fs_inode_table_loc(rfs->old_fs, g+1))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (move_count > 0)
|
||||||
|
{
|
||||||
|
end_g = g;
|
||||||
|
for (i = 0, g = move_start+move_count-1; i < move_count; i++, g--)
|
||||||
|
{
|
||||||
|
if (!ext2fs_has_group_desc_csum(rfs->new_fs) ||
|
||||||
|
!ext2fs_bg_flags_test(rfs->new_fs, g, EXT2_BG_INODE_UNINIT))
|
||||||
|
{
|
||||||
|
retval = io_channel_read_blk64(rfs->new_fs->io, ext2fs_inode_table_loc(rfs->old_fs, g), size, rfs->itable_buf);
|
||||||
|
if (retval)
|
||||||
|
return retval;
|
||||||
|
retval = io_channel_write_blk64(rfs->new_fs->io, ext2fs_inode_table_loc(rfs->new_fs, g), size, rfs->itable_buf);
|
||||||
|
if (retval)
|
||||||
|
return retval;
|
||||||
|
if (new_ibg > old_ibg)
|
||||||
|
{
|
||||||
|
retval = ext2fs_zero_blocks2(rfs->new_fs,
|
||||||
|
ext2fs_inode_table_loc(rfs->new_fs, g)+old_ibg,
|
||||||
|
new_ibg-old_ibg, NULL, NULL);
|
||||||
|
if (retval)
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
blk = ext2fs_inode_table_loc(rfs->old_fs, g);
|
||||||
|
for (ib = 0; ib < old_ibg; ib++)
|
||||||
|
if (!ext2fs_test_block_bitmap2(meta_bmap, blk+ib))
|
||||||
|
ext2fs_unmark_block_bitmap2(rfs->new_fs->block_map, blk+ib);
|
||||||
|
ext2fs_mark_block_bitmap_range2(rfs->new_fs->block_map, ext2fs_inode_table_loc(rfs->new_fs, g), new_ibg);
|
||||||
|
}
|
||||||
|
move_start = move_count = 0;
|
||||||
|
g = end_g;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (old_ipg < new_ipg)
|
||||||
|
{
|
||||||
|
for (g = 0; g < group_count; g++)
|
||||||
|
{
|
||||||
|
for (i = 0, old_ino = 1 + old_ipg*g, ino = 1 + new_ipg*g; i < old_ipg; i++, ino++, old_ino++)
|
||||||
|
{
|
||||||
|
if (ext2fs_test_inode_bitmap2(rfs->old_fs->inode_map, old_ino))
|
||||||
|
ext2fs_mark_inode_bitmap2(rfs->new_fs->inode_map, ino);
|
||||||
|
else
|
||||||
|
ext2fs_unmark_inode_bitmap2(rfs->new_fs->inode_map, ino);
|
||||||
|
}
|
||||||
|
for (i = old_ipg, ino = 1 + new_ipg*g + old_ipg; i < new_ipg; i++, ino++)
|
||||||
|
ext2fs_unmark_inode_bitmap2(rfs->new_fs->inode_map, ino);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (old_ipg > new_ipg)
|
||||||
|
{
|
||||||
|
dgrp_t n;
|
||||||
|
for (n = 0, g = group_count-1; n < group_count; n++, g--)
|
||||||
|
{
|
||||||
|
for (i = 0, old_ino = 1 + old_ipg*g, ino = 1 + new_ipg*g; i < new_ipg; i++, ino++, old_ino++)
|
||||||
|
{
|
||||||
|
if (ext2fs_test_inode_bitmap2(rfs->old_fs->inode_map, old_ino))
|
||||||
|
ext2fs_mark_inode_bitmap2(rfs->new_fs->inode_map, ino);
|
||||||
|
else
|
||||||
|
ext2fs_unmark_inode_bitmap2(rfs->new_fs->inode_map, ino);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ext2fs_free_block_bitmap(meta_bmap);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------
|
/* --------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* Resize processing, phase 4.
|
* Resize processing, phase 4.
|
||||||
|
@ -2176,9 +2537,10 @@ static int check_and_change_inodes(ext2_ino_t dir,
|
||||||
ext2_ino_t new_inode;
|
ext2_ino_t new_inode;
|
||||||
errcode_t retval;
|
errcode_t retval;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
ext2_ino_t old_dir = TRANSLATE_IPG(dir, is->rfs->new_fs, is->rfs->old_fs);
|
||||||
|
|
||||||
if (is->rfs->progress && offset == 0) {
|
if (is->rfs->progress && offset == 0) {
|
||||||
io_channel_flush(is->rfs->old_fs->io);
|
io_channel_flush(is->rfs->new_fs->io);
|
||||||
is->err = (is->rfs->progress)(is->rfs,
|
is->err = (is->rfs->progress)(is->rfs,
|
||||||
E2_RSZ_INODE_REF_UPD_PASS,
|
E2_RSZ_INODE_REF_UPD_PASS,
|
||||||
++is->num, is->max_dirs);
|
++is->num, is->max_dirs);
|
||||||
|
@ -2191,16 +2553,25 @@ static int check_and_change_inodes(ext2_ino_t dir,
|
||||||
* old fs, then we must rewrite all dir blocks with new checksums.
|
* old fs, then we must rewrite all dir blocks with new checksums.
|
||||||
*/
|
*/
|
||||||
if (ext2fs_has_feature_metadata_csum(is->rfs->old_fs->super) &&
|
if (ext2fs_has_feature_metadata_csum(is->rfs->old_fs->super) &&
|
||||||
!ext2fs_test_inode_bitmap2(is->rfs->old_fs->inode_map, dir))
|
!ext2fs_test_inode_bitmap2(is->rfs->old_fs->inode_map, old_dir))
|
||||||
ret |= DIRENT_CHANGED;
|
ret |= DIRENT_CHANGED;
|
||||||
|
|
||||||
if (!dirent->inode)
|
if (!dirent->inode)
|
||||||
|
{
|
||||||
|
if (old_dir != dir)
|
||||||
|
ret |= DIRENT_CHANGED;
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
new_inode = ext2fs_extent_translate(is->rfs->imap, dirent->inode);
|
new_inode = 0;
|
||||||
|
if (is->rfs->imap)
|
||||||
|
new_inode = ext2fs_extent_translate(is->rfs->imap, dirent->inode);
|
||||||
if (!new_inode)
|
if (!new_inode)
|
||||||
|
new_inode = dirent->inode;
|
||||||
|
new_inode = TRANSLATE_IPG(new_inode, is->rfs->old_fs, is->rfs->new_fs);
|
||||||
|
if (new_inode == dirent->inode && old_dir == dir)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
#ifdef RESIZE2FS_DEBUG
|
#ifdef RESIZE2FS_DEBUG
|
||||||
if (is->rfs->flags & RESIZE_DEBUG_INODEMAP)
|
if (is->rfs->flags & RESIZE_DEBUG_INODEMAP)
|
||||||
printf("Inode translate (dir=%u, name=%.*s, %u->%u)\n",
|
printf("Inode translate (dir=%u, name=%.*s, %u->%u)\n",
|
||||||
|
@ -2211,10 +2582,10 @@ static int check_and_change_inodes(ext2_ino_t dir,
|
||||||
dirent->inode = new_inode;
|
dirent->inode = new_inode;
|
||||||
|
|
||||||
/* Update the directory mtime and ctime */
|
/* Update the directory mtime and ctime */
|
||||||
retval = ext2fs_read_inode(is->rfs->old_fs, dir, &inode);
|
retval = ext2fs_read_inode(is->rfs->new_fs, dir, &inode);
|
||||||
if (retval == 0) {
|
if (retval == 0) {
|
||||||
inode.i_mtime = inode.i_ctime = time(0);
|
inode.i_mtime = inode.i_ctime = time(0);
|
||||||
is->err = ext2fs_write_inode(is->rfs->old_fs, dir, &inode);
|
is->err = ext2fs_write_inode(is->rfs->new_fs, dir, &inode);
|
||||||
if (is->err)
|
if (is->err)
|
||||||
return ret | DIRENT_ABORT;
|
return ret | DIRENT_ABORT;
|
||||||
}
|
}
|
||||||
|
@ -2226,8 +2597,9 @@ static errcode_t inode_ref_fix(ext2_resize_t rfs)
|
||||||
{
|
{
|
||||||
errcode_t retval;
|
errcode_t retval;
|
||||||
struct istruct is;
|
struct istruct is;
|
||||||
|
int change_inodes = rfs->old_fs->inode_blocks_per_group != rfs->new_fs->inode_blocks_per_group;
|
||||||
|
|
||||||
if (!rfs->imap)
|
if (!change_inodes && !rfs->imap)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2235,7 +2607,7 @@ static errcode_t inode_ref_fix(ext2_resize_t rfs)
|
||||||
* inode references
|
* inode references
|
||||||
*/
|
*/
|
||||||
is.num = 0;
|
is.num = 0;
|
||||||
is.max_dirs = ext2fs_dblist_count2(rfs->old_fs->dblist);
|
is.max_dirs = ext2fs_dblist_count2(rfs->new_fs->dblist);
|
||||||
is.rfs = rfs;
|
is.rfs = rfs;
|
||||||
is.err = 0;
|
is.err = 0;
|
||||||
|
|
||||||
|
@ -2246,11 +2618,11 @@ static errcode_t inode_ref_fix(ext2_resize_t rfs)
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
rfs->old_fs->flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS;
|
rfs->new_fs->flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS;
|
||||||
retval = ext2fs_dblist_dir_iterate(rfs->old_fs->dblist,
|
retval = ext2fs_dblist_dir_iterate(rfs->new_fs->dblist,
|
||||||
DIRENT_FLAG_INCLUDE_EMPTY, 0,
|
DIRENT_FLAG_INCLUDE_EMPTY, 0,
|
||||||
check_and_change_inodes, &is);
|
check_and_change_inodes, &is);
|
||||||
rfs->old_fs->flags &= ~EXT2_FLAG_IGNORE_CSUM_ERRORS;
|
rfs->new_fs->flags &= ~EXT2_FLAG_IGNORE_CSUM_ERRORS;
|
||||||
if (retval)
|
if (retval)
|
||||||
goto errout;
|
goto errout;
|
||||||
if (is.err) {
|
if (is.err) {
|
||||||
|
@ -2263,7 +2635,8 @@ static errcode_t inode_ref_fix(ext2_resize_t rfs)
|
||||||
is.max_dirs, is.max_dirs);
|
is.max_dirs, is.max_dirs);
|
||||||
|
|
||||||
errout:
|
errout:
|
||||||
ext2fs_free_extent_table(rfs->imap);
|
if (rfs->imap)
|
||||||
|
ext2fs_free_extent_table(rfs->imap);
|
||||||
rfs->imap = 0;
|
rfs->imap = 0;
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -2319,7 +2692,7 @@ static errcode_t move_itables(ext2_resize_t rfs)
|
||||||
if (retval)
|
if (retval)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
retval = mark_table_blocks(fs, new_bmap);
|
retval = mark_table_blocks(fs, new_bmap, 0);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
@ -2431,7 +2804,7 @@ static errcode_t move_itables(ext2_resize_t rfs)
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mark_table_blocks(fs, fs->block_map);
|
mark_table_blocks(fs, fs->block_map, 0);
|
||||||
ext2fs_flush(fs);
|
ext2fs_flush(fs);
|
||||||
#ifdef RESIZE2FS_DEBUG
|
#ifdef RESIZE2FS_DEBUG
|
||||||
if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE)
|
if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE)
|
||||||
|
|
|
@ -141,7 +141,7 @@ struct ext2_resize_struct {
|
||||||
|
|
||||||
|
|
||||||
/* prototypes */
|
/* prototypes */
|
||||||
extern errcode_t resize_fs(ext2_filsys fs, blk64_t *new_size, int flags,
|
extern errcode_t resize_fs(ext2_filsys fs, blk64_t *new_size, __u32 new_inodes, int flags,
|
||||||
errcode_t (*progress)(ext2_resize_t rfs,
|
errcode_t (*progress)(ext2_resize_t rfs,
|
||||||
int pass, unsigned long cur,
|
int pass, unsigned long cur,
|
||||||
unsigned long max));
|
unsigned long max));
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
Bad required extra isize in superblock (1). Fix? yes
|
||||||
|
|
||||||
|
Bad desired extra isize in superblock (1024). Fix? yes
|
||||||
|
|
||||||
|
Pass 1: Checking inodes, blocks, and sizes
|
||||||
|
Pass 2: Checking directory structure
|
||||||
|
Pass 3: Checking directory connectivity
|
||||||
|
Pass 4: Checking reference counts
|
||||||
|
Pass 5: Checking group summary information
|
||||||
|
|
||||||
|
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
|
||||||
|
test_filesys: 11/32 files (0.0% non-contiguous), 28/200 blocks
|
||||||
|
Exit status is 1
|
|
@ -0,0 +1,7 @@
|
||||||
|
Pass 1: Checking inodes, blocks, and sizes
|
||||||
|
Pass 2: Checking directory structure
|
||||||
|
Pass 3: Checking directory connectivity
|
||||||
|
Pass 4: Checking reference counts
|
||||||
|
Pass 5: Checking group summary information
|
||||||
|
test_filesys: 11/32 files (0.0% non-contiguous), 28/200 blocks
|
||||||
|
Exit status is 0
|
Binary file not shown.
|
@ -0,0 +1 @@
|
||||||
|
check invalid extra_isize fields in superblock
|
|
@ -1,4 +1,7 @@
|
||||||
Pass 1: Checking inodes, blocks, and sizes
|
Pass 1: Checking inodes, blocks, and sizes
|
||||||
|
Inode 12 has a extra size (126) which is invalid
|
||||||
|
Fix? yes
|
||||||
|
|
||||||
Pass 2: Checking directory structure
|
Pass 2: Checking directory structure
|
||||||
Directory inode 12, block #0, offset 4: directory corrupted
|
Directory inode 12, block #0, offset 4: directory corrupted
|
||||||
Salvage? yes
|
Salvage? yes
|
||||||
|
|
|
@ -7,5 +7,5 @@
|
||||||
* file may be redistributed under the GNU Public License v2.
|
* file may be redistributed under the GNU Public License v2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define E2FSPROGS_VERSION "1.43.2"
|
#define E2FSPROGS_VERSION "1.43.3"
|
||||||
#define E2FSPROGS_DATE "01-Sep-2016"
|
#define E2FSPROGS_DATE "04-Sep-2016"
|
||||||
|
|
Loading…
Reference in New Issue