[T106][ZXW-22]7520V3SCV2.01.01.02P42U09_VEC_V0.8_AP_VEC origin source commit

Change-Id: Ic6e05d89ecd62fc34f82b23dcf306c93764aec4b
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/Makefile.in b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/Makefile.in
new file mode 100644
index 0000000..553c361
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/Makefile.in
@@ -0,0 +1,712 @@
+#
+# Standard e2fsprogs prologue....
+#
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+top_builddir = ..
+my_dir = misc
+INSTALL = @INSTALL@
+
+@MCONFIG@
+
+@DEFRAG_CMT@@LINUX_CMT@E4DEFRAG_PROG= e4defrag
+@DEFRAG_CMT@@LINUX_CMT@E4DEFRAG_MAN= e4defrag.8
+
+@IMAGER_CMT@E2IMAGE_PROG= e2image
+@IMAGER_CMT@E2IMAGE_MAN= e2image.8
+
+@UUIDD_CMT@UUIDD_PROG= uuidd
+@UUIDD_CMT@UUIDD_MAN= uuidd.8
+
+@BLKID_CMT@BLKID_PROG= blkid
+@BLKID_CMT@BLKID_MAN= blkid.8
+
+@BLKID_CMT@FINDFS_LINK= findfs
+@BLKID_CMT@FINDFS_MAN= findfs.8
+
+SPROGS=		mke2fs badblocks tune2fs dumpe2fs $(BLKID_PROG) logsave \
+			$(E2IMAGE_PROG) @FSCK_PROG@ e2undo
+USPROGS=	mklost+found filefrag e2freefrag $(UUIDD_PROG) $(E4DEFRAG_PROG)
+SMANPAGES=	tune2fs.8 mklost+found.8 mke2fs.8 dumpe2fs.8 badblocks.8 \
+			e2label.8 $(FINDFS_MAN) $(BLKID_MAN) $(E2IMAGE_MAN) \
+			logsave.8 filefrag.8 e2freefrag.8 e2undo.8 \
+			$(UUIDD_MAN) $(E4DEFRAG_MAN) @FSCK_MAN@
+FMANPAGES=	mke2fs.conf.5 ext4.5
+
+UPROGS=		chattr lsattr @UUID_CMT@ uuidgen
+UMANPAGES=	chattr.1 lsattr.1 @UUID_CMT@ uuidgen.1
+
+LPROGS=		@E2INITRD_PROG@
+
+TUNE2FS_OBJS=	tune2fs.o util.o
+MKLPF_OBJS=	mklost+found.o
+MKE2FS_OBJS=	mke2fs.o util.o profile.o prof_err.o default_profile.o
+CHATTR_OBJS=	chattr.o
+LSATTR_OBJS=	lsattr.o
+UUIDGEN_OBJS=	uuidgen.o
+UUIDD_OBJS=	uuidd.o
+DUMPE2FS_OBJS=	dumpe2fs.o
+BADBLOCKS_OBJS=	badblocks.o
+E2IMAGE_OBJS=	e2image.o
+FSCK_OBJS=	fsck.o base_device.o ismounted.o
+BLKID_OBJS=	blkid.o
+FILEFRAG_OBJS=	filefrag.o
+E2UNDO_OBJS=  e2undo.o
+E4DEFRAG_OBJS=	e4defrag.o
+E2FREEFRAG_OBJS= e2freefrag.o
+
+PROFILED_TUNE2FS_OBJS=	profiled/tune2fs.o profiled/util.o
+PROFILED_MKLPF_OBJS=	profiled/mklost+found.o
+PROFILED_MKE2FS_OBJS=	profiled/mke2fs.o profiled/util.o profiled/profile.o \
+			profiled/prof_err.o profiled/default_profile.o
+PROFILED_CHATTR_OBJS=	profiled/chattr.o
+PROFILED_LSATTR_OBJS=	profiled/lsattr.o
+PROFILED_UUIDGEN_OBJS=	profiled/uuidgen.o
+PROFILED_UUIDD_OBJS=	profiled/uuidd.o
+PROFILED_DUMPE2FS_OBJS=	profiled/dumpe2fs.o
+PROFILED_BADBLOCKS_OBJS=	profiled/badblocks.o
+PROFILED_E2IMAGE_OBJS=	profiled/e2image.o
+PROFILED_FSCK_OBJS=	profiled/fsck.o profiled/base_device.o \
+			profiled/ismounted.o
+PROFILED_BLKID_OBJS=	profiled/blkid.o
+PROFILED_FILEFRAG_OBJS=	profiled/filefrag.o
+PROFILED_E2FREEFRAG_OBJS= profiled/e2freefrag.o
+PROFILED_E2UNDO_OBJS=	profiled/e2undo.o
+PROFILED_E4DEFRAG_OBJS=	profiled/e4defrag.o
+
+SRCS=	$(srcdir)/tune2fs.c $(srcdir)/mklost+found.c $(srcdir)/mke2fs.c \
+		$(srcdir)/chattr.c $(srcdir)/lsattr.c $(srcdir)/dumpe2fs.c \
+		$(srcdir)/badblocks.c $(srcdir)/fsck.c $(srcdir)/util.c \
+		$(srcdir)/uuidgen.c $(srcdir)/blkid.c $(srcdir)/logsave.c \
+		$(srcdir)/filefrag.c $(srcdir)/base_device.c \
+		$(srcdir)/ismounted.c $(srcdir)/../e2fsck/profile.c \
+		$(srcdir)/e2undo.c $(srcdir)/e2freefrag.c
+
+LIBS= $(LIBEXT2FS) $(LIBCOM_ERR) 
+DEPLIBS= $(LIBEXT2FS) $(DEPLIBCOM_ERR)
+PROFILED_LIBS= $(PROFILED_LIBEXT2FS) $(PROFILED_LIBCOM_ERR)
+PROFILED_DEPLIBS= $(PROFILED_LIBEXT2FS) $(DEPPROFILED_LIBCOM_ERR)
+
+STATIC_LIBS= $(STATIC_LIBEXT2FS) $(STATIC_LIBCOM_ERR) 
+STATIC_DEPLIBS= $(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
+
+.c.o:
+	$(E) "	CC $<"
+	$(Q) $(CC) -c $(ALL_CFLAGS) $< -o $@
+	$(Q) $(CHECK_CMD) $(ALL_CFLAGS) $<
+@PROFILE_CMT@	$(Q) $(CC) $(ALL_CFLAGS) -g -pg -o profiled/$*.o -c $<
+
+all:: profiled $(SPROGS) $(UPROGS) $(USPROGS) $(SMANPAGES) $(UMANPAGES) \
+	$(FMANPAGES) $(LPROGS) $(E4DEFRAG_PROG)
+
+@PROFILE_CMT@all:: tune2fs.profiled blkid.profiled e2image.profiled \
+	e2undo.profiled mke2fs.profiled dumpe2fs.profiled fsck.profiled \
+	logsave.profiled filefrag.profiled uuidgen.profiled uuidd.profiled \
+	e2image.profiled e4defrag.profiled e2freefrag.profiled
+
+profiled:
+@PROFILE_CMT@	$(E) "	MKDIR $@"
+@PROFILE_CMT@	$(Q) mkdir profiled
+
+prof_err.c prof_err.h: $(srcdir)/../e2fsck/prof_err.et
+	$(E) "	COMPILE_ET prof_err.et"
+	$(Q) $(COMPILE_ET) $(srcdir)/../e2fsck/prof_err.et
+
+profile.h: $(top_srcdir)/e2fsck/profile.h
+	$(E) "	CP $<"
+	$(Q) cp $< $@
+
+mke2fs.conf: $(srcdir)/mke2fs.conf.in
+	if test -f $(srcdir)/mke2fs.conf.custom.in ; then \
+		cp $(srcdir)/mke2fs.conf.custom.in mke2fs.conf; \
+	else \
+		cp $(srcdir)/mke2fs.conf.in mke2fs.conf; \
+	fi
+
+default_profile.c: mke2fs.conf $(srcdir)/profile-to-c.awk
+	$(E) "	PROFILE_TO_C mke2fs.conf"
+	$(Q) $(AWK) -f $(srcdir)/profile-to-c.awk < mke2fs.conf \
+		>  default_profile.c
+profile.o:
+	$(E) "	CC $<"
+	$(Q) $(CC) -c $(ALL_CFLAGS) $(srcdir)/../e2fsck/profile.c -o $@
+@PROFILE_CMT@	$(Q) $(CC) $(ALL_CFLAGS) -g -pg -o profiled/profile.o -c \
+@PROFILE_CMT@	$(srcdir)/../e2fsck/profile.c
+
+findsuper: findsuper.o
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -o findsuper findsuper.o $(LIBS)
+
+partinfo: partinfo.o
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -o partinfo partinfo.o
+
+e2initrd_helper: e2initrd_helper.o $(DEPLIBS) $(DEPLIBBLKID) $(LIBEXT2FS)
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -o e2initrd_helper e2initrd_helper.o $(LIBS) \
+		$(LIBBLKID) $(LIBEXT2FS) $(LIBINTL)
+
+tune2fs: $(TUNE2FS_OBJS) $(DEPLIBS) $(DEPLIBS_E2P) $(DEPLIBBLKID) \
+		$(DEPLIBUUID) $(DEPLIBQUOTA) $(LIBEXT2FS)
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -o tune2fs $(TUNE2FS_OBJS) $(LIBS) \
+		$(LIBBLKID) $(LIBUUID) $(LIBQUOTA) $(LIBEXT2FS) $(LIBS_E2P) \
+		$(LIBINTL)
+
+tune2fs.static: $(TUNE2FS_OBJS) $(STATIC_DEPLIBS) $(STATIC_LIBE2P) $(DEPSTATIC_LIBBLKID)
+	$(E) "	LD $@"
+	$(Q) $(CC) $(LDFLAGS_STATIC) -o tune2fs.static $(TUNE2FS_OBJS) \
+		$(STATIC_LIBS) $(STATIC_LIBBLKID) $(STATIC_LIBUUID) \
+		$(STATIC_LIBQUOTA) $(STATIC_LIBE2P) $(LIBINTL)
+
+tune2fs.profiled: $(TUNE2FS_OBJS) $(PROFILED_DEPLIBS) \
+		$(PROFILED_E2P) $(DEPPROFILED_LIBBLKID) $(DEPPROFILED_LIBUUID) \
+		$(DEPPROFILED_LIBQUOTA)
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -g -pg -o tune2fs.profiled \
+		$(PROFILED_TUNE2FS_OBJS) $(PROFILED_LIBBLKID) \
+		$(PROFILED_LIBUUID) $(PROFILED_LIBQUOTA) $(PROFILED_LIBE2P) \
+		$(LIBINTL) $(PROFILED_LIBS)
+
+blkid: $(BLKID_OBJS) $(DEPLIBBLKID) $(LIBEXT2FS)
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -o blkid $(BLKID_OBJS) $(LIBBLKID) $(LIBINTL) \
+		$(LIBEXT2FS)
+
+blkid.static: $(BLKID_OBJS) $(STATIC_DEPLIBS) $(DEPSTATIC_LIBBLKID)
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -o blkid.static $(BLKID_OBJS) $(STATIC_LIBS) \
+		$(STATIC_LIBBLKID) $(LIBINTL)
+
+blkid.profiled: $(BLKID_OBJS) $(DEPPROFILED_LIBBLKID) \
+		$(PROFILED_LIBEXT2FS)
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -g -pg -o blkid.profiled $(PROFILED_BLKID_OBJS) \
+		$(PROFILED_LIBBLKID) $(LIBINTL) $(PROFILED_LIBEXT2FS)
+
+e2image: $(E2IMAGE_OBJS) $(DEPLIBS)
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -o e2image $(E2IMAGE_OBJS) $(LIBS) $(LIBINTL)
+
+e2image.profiled: $(E2IMAGE_OBJS) $(PROFILED_DEPLIBS)
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -g -pg -o e2image.profiled \
+		$(PROFILED_E2IMAGE_OBJS) $(PROFILED_LIBS) $(LIBINTL)
+
+e2undo: $(E2UNDO_OBJS) $(DEPLIBS)
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -o e2undo $(E2UNDO_OBJS) $(LIBS) $(LIBINTL)
+
+e2undo.profiled: $(E2UNDO_OBJS) $(PROFILED_DEPLIBS)
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -g -pg -o e2undo.profiled \
+		$(PROFILED_E2UNDO_OBJS) $(PROFILED_LIBS) $(LIBINTL)
+
+e4defrag: $(E4DEFRAG_OBJS) $(DEPLIBS)
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -o e4defrag $(E4DEFRAG_OBJS) $(LIBS)
+
+e4defrag.profiled: $(E4DEFRAG_OBJS) $(PROFILED_DEPLIBS)
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -g -pg -o e4defrag.profiled \
+		$(PROFILED_E4DEFRAG_OBJS) $(PROFILED_LIBS)
+
+base_device: base_device.c
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) $(srcdir)/base_device.c \
+		-DDEBUG -o base_device
+
+check:: base_device
+	./base_device < $(srcdir)/base_device.tst > base_device.out
+	cmp $(srcdir)/base_device.tst base_device.out
+
+mklost+found: $(MKLPF_OBJS)
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -o mklost+found $(MKLPF_OBJS) $(LIBINTL)
+
+mke2fs: $(MKE2FS_OBJS) $(DEPLIBS) $(LIBE2P) $(DEPLIBBLKID) $(DEPLIBUUID) \
+		$(DEPLIBQUOTA) $(LIBEXT2FS)
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -o mke2fs $(MKE2FS_OBJS) $(LIBS) $(LIBBLKID) \
+		$(LIBUUID) $(LIBQUOTA) $(LIBEXT2FS) $(LIBE2P) $(LIBINTL)
+
+mke2fs.static: $(MKE2FS_OBJS) $(STATIC_DEPLIBS) $(STATIC_LIBE2P) $(DEPSTATIC_LIBUUID) \
+		$(DEPSTATIC_LIBQUOTA) $(DEPSTATIC_LIBBLKID)
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -static -o mke2fs.static $(MKE2FS_OBJS) \
+		$(STATIC_LIBQUOTA) $(STATIC_LIBS) $(STATIC_LIBE2P) \
+		$(STATIC_LIBBLKID) $(STATIC_LIBUUID) $(LIBINTL)
+
+mke2fs.profiled: $(MKE2FS_OBJS) $(PROFILED_DEPLIBS) \
+	$(PROFILED_LIBE2P) $(PROFILED_DEPLIBBLKID) $(PROFILED_DEPLIBUUID) \
+	$(PROFILED_LIBQUOTA)
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -g -pg -o mke2fs.profiled \
+		$(PROFILED_MKE2FS_OBJS) $(PROFILED_LIBBLKID) \
+		$(PROFILED_LIBUUID) $(PROFILED_LIBQUOTA) $(PROFILED_LIBE2P) $(LIBINTL) \
+		$(PROFILED_LIBS)
+
+chattr: $(CHATTR_OBJS) $(DEPLIBS_E2P)
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -o chattr $(CHATTR_OBJS) $(LIBS_E2P) $(LIBINTL)
+
+lsattr: $(LSATTR_OBJS) $(DEPLIBS_E2P)
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -o lsattr $(LSATTR_OBJS) $(LIBS_E2P) $(LIBINTL)
+
+uuidgen: $(UUIDGEN_OBJS) $(DEPLIBUUID)
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -o uuidgen $(UUIDGEN_OBJS) $(LIBUUID) $(LIBINTL)
+
+uuidgen.profiled: $(UUIDGEN_OBJS) $(PROFILED_DEPLIBUUID)
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -g -pg -o uuidgen.profiled \
+		$(PROFILED_UUIDGEN_OBJS) $(PROFILED_LIBUUID) $(LIBINTL)
+
+uuidd: $(UUIDD_OBJS) $(DEPLIBUUID)
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -o uuidd $(UUIDD_OBJS) $(LIBUUID) $(LIBINTL)
+
+uuidd.profiled: $(UUIDD_OBJS) $(PROFILED_DEPLIBUUID)
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -g -pg -o uuidd.profiled $(PROFILED_UUIDD_OBJS) \
+		$(PROFILED_LIBUUID) $(LIBINTL)
+
+dumpe2fs: $(DUMPE2FS_OBJS) $(DEPLIBS) $(DEPLIBS_E2P) $(DEPLIBUUID)
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -o dumpe2fs $(DUMPE2FS_OBJS) $(LIBS) \
+		$(LIBS_E2P) $(LIBUUID) $(LIBINTL)
+
+dumpe2fs.profiled: $(DUMPE2FS_OBJS) $(PROFILED_DEPLIBS) \
+		$(PROFILED_LIBE2P) $(PROFILED_DEPLIBUUID)
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -g -pg -o dumpe2fs.profiled \
+		$(PROFILED_DUMPE2FS_OBJS) $(PROFILED_LIBS) \
+		$(PROFILED_LIBE2P) $(PROFILED_LIBUUID) $(LIBINTL)
+
+fsck: $(FSCK_OBJS) $(DEPLIBBLKID)
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -o fsck $(FSCK_OBJS) $(LIBBLKID) $(LIBINTL)
+
+fsck.profiled: $(FSCK_OBJS) $(PROFILED_DEPLIBBLKID)
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -g -pg -o fsck.profiled $(PROFILED_FSCK_OBJS) \
+		$(PROFILED_LIBBLKID) $(LIBINTL)
+
+badblocks: $(BADBLOCKS_OBJS) $(DEPLIBS)
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -o badblocks $(BADBLOCKS_OBJS) $(LIBS) $(LIBINTL)
+
+badblocks.profiled: $(BADBLOCKS_OBJS) $(PROFILED_DEPLIBS)
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -g -pg -o badblocks.profiled \
+		$(PROFILED_BADBLOCKS_OBJS) $(PROFILED_LIBS) $(LIBINTL)
+
+logsave: logsave.o
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -o logsave logsave.o
+
+logsave.profiled: logsave.o
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -g -pg -o logsave.profiled profiled/logsave.o
+
+e2freefrag: $(E2FREEFRAG_OBJS)
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -o e2freefrag $(E2FREEFRAG_OBJS) $(LIBS)
+
+e2freefrag.profiled: $(E2FREEFRAG_OBJS) $(PROFILED_DEPLIBS)
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -g -pg -o e2freefrag.profiled \
+		$(PROFILED_E2FREEFRAG_OBJS) $(PROFILED_LIBS)
+
+filefrag: $(FILEFRAG_OBJS)
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -o filefrag $(FILEFRAG_OBJS) 
+
+filefrag.profiled: $(FILEFRAG_OBJS)
+	$(E) "	LD $@"
+	$(Q) $(CC) $(ALL_LDFLAGS) -g -pg -o filefrag.profiled \
+		$(PROFILED_FILEFRAG_OBJS) 
+
+tst_ismounted: $(srcdir)/ismounted.c $(STATIC_LIBEXT2FS) $(DEPLIBCOM_ERR)
+	$(E) "	LD $@"
+	$(CC) -o tst_ismounted $(srcdir)/ismounted.c -DDEBUG $(ALL_CFLAGS) \
+		$(LIBCOM_ERR)
+
+tune2fs.8: $(DEP_SUBSTITUTE) $(srcdir)/tune2fs.8.in
+	$(E) "	SUBST $@"
+	$(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/tune2fs.8.in tune2fs.8
+
+mklost+found.8: $(DEP_SUBSTITUTE) $(srcdir)/mklost+found.8.in
+	$(E) "	SUBST $@"
+	$(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/mklost+found.8.in mklost+found.8
+
+mke2fs.8: $(DEP_SUBSTITUTE) $(srcdir)/mke2fs.8.in
+	$(E) "	SUBST $@"
+	$(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/mke2fs.8.in mke2fs.8
+
+mke2fs.conf.5: $(DEP_SUBSTITUTE) $(srcdir)/mke2fs.conf.5.in
+	$(E) "	SUBST $@"
+	$(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/mke2fs.conf.5.in mke2fs.conf.5
+
+ext4.5: $(DEP_SUBSTITUTE) $(srcdir)/ext4.5.in
+	$(E) "	SUBST $@"
+	$(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/$@.in $@
+
+e2label.8: $(DEP_SUBSTITUTE) $(srcdir)/e2label.8.in
+	$(E) "	SUBST $@"
+	$(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/e2label.8.in e2label.8
+
+e2undo.8: $(DEP_SUBSTITUTE) $(srcdir)/e2undo.8.in
+	$(E) "	SUBST $@"
+	$(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/e2undo.8.in e2undo.8
+
+findfs.8: $(DEP_SUBSTITUTE) $(srcdir)/findfs.8.in
+	$(E) "	SUBST $@"
+	$(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/findfs.8.in findfs.8
+
+e2image.8: $(DEP_SUBSTITUTE) $(srcdir)/e2image.8.in
+	$(E) "	SUBST $@"
+	$(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/e2image.8.in e2image.8
+
+e4defrag.8: $(DEP_SUBSTITUTE) $(srcdir)/e4defrag.8.in
+	$(E) "	SUBST $@"
+	$(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/e4defrag.8.in e4defrag.8
+
+dumpe2fs.8: $(DEP_SUBSTITUTE) $(srcdir)/dumpe2fs.8.in 
+	$(E) "	SUBST $@"
+	$(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/dumpe2fs.8.in dumpe2fs.8
+
+badblocks.8: $(DEP_SUBSTITUTE) $(srcdir)/badblocks.8.in
+	$(E) "	SUBST $@"
+	$(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/badblocks.8.in badblocks.8	
+
+fsck.8: $(DEP_SUBSTITUTE) $(srcdir)/fsck.8.in
+	$(E) "	SUBST $@"
+	$(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/fsck.8.in fsck.8 
+
+blkid.8: $(DEP_SUBSTITUTE) $(srcdir)/blkid.8.in
+	$(E) "	SUBST $@"
+	$(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/blkid.8.in blkid.8
+
+logsave.8: $(DEP_SUBSTITUTE) $(srcdir)/logsave.8.in
+	$(E) "	SUBST $@"
+	$(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/logsave.8.in logsave.8
+
+uuidd.8: $(DEP_SUBSTITUTE) $(srcdir)/uuidd.8.in
+	$(E) "	SUBST $@"
+	$(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/uuidd.8.in uuidd.8
+
+chattr.1: $(DEP_SUBSTITUTE) $(srcdir)/chattr.1.in
+	$(E) "	SUBST $@"
+	$(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/chattr.1.in chattr.1 
+
+lsattr.1: $(DEP_SUBSTITUTE) $(srcdir)/lsattr.1.in 
+	$(E) "	SUBST $@"
+	$(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/lsattr.1.in lsattr.1 
+
+uuidgen.1: $(DEP_SUBSTITUTE) $(srcdir)/uuidgen.1.in 
+	$(E) "	SUBST $@"
+	$(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/uuidgen.1.in uuidgen.1 
+
+blkid.1: $(DEP_SUBSTITUTE) $(srcdir)/blkid.1.in 
+	$(E) "	SUBST $@"
+	$(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/blkid.1.in blkid.1 
+
+e2freefrag.8: $(DEP_SUBSTITUTE) $(srcdir)/e2freefrag.8.in
+	$(E) "	SUBST $@"
+	@$(SUBSTITUTE_UPTIME) $(srcdir)/e2freefrag.8.in e2freefrag.8
+
+filefrag.8: $(DEP_SUBSTITUTE) $(srcdir)/filefrag.8.in
+	$(E) "	SUBST $@"
+	$(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/filefrag.8.in filefrag.8
+
+installdirs:
+	$(E) "	MKINSTALLDIRS $(sbindir) $(root_sbindir) $(bindir) $(man1dir) $(man8dir) $(libdir) $(root_sysconfdir)"
+	$(Q) $(MKINSTALLDIRS) $(DESTDIR)$(sbindir) \
+		$(DESTDIR)$(root_sbindir) $(DESTDIR)$(bindir) \
+		$(DESTDIR)$(man1dir) $(DESTDIR)$(man8dir) \
+		$(DESTDIR)$(man1dir) $(DESTDIR)$(man5dir) \
+		$(DESTDIR)$(libdir) $(DESTDIR)/$(root_sysconfdir)
+
+install: all $(SMANPAGES) $(UMANPAGES) installdirs
+	$(Q) for i in $(SPROGS); do \
+		$(ES) "	INSTALL $(root_sbindir)/$$i"; \
+		$(INSTALL_PROGRAM) $$i $(DESTDIR)$(root_sbindir)/$$i; \
+	done
+	$(Q) for i in $(USPROGS); do \
+		$(ES) "	INSTALL $(sbindir)/$$i"; \
+		$(INSTALL_PROGRAM) $$i $(DESTDIR)$(sbindir)/$$i; \
+	done
+	$(Q) for i in ext2 ext3 ext4 ext4dev; do \
+		$(ES) "	LINK $(root_sbindir)/mkfs.$$i"; \
+		(cd $(DESTDIR)$(root_sbindir); \
+			$(LN) $(LINK_INSTALL_FLAGS) mke2fs mkfs.$$i); \
+	done
+	$(Q) (cd $(DESTDIR)$(root_sbindir); \
+		$(LN) $(LINK_INSTALL_FLAGS) tune2fs e2label)
+	$(Q) if test -n "$(FINDFS_LINK)"; then \
+		$(ES) "	LINK $(root_sbindir)/findfs"; \
+		(cd $(DESTDIR)$(root_sbindir); \
+		$(LN) $(LINK_INSTALL_FLAGS) tune2fs $(FINDFS_LINK)); \
+	fi
+	$(Q) for i in $(UPROGS); do \
+		$(ES) "	INSTALL $(bindir)/$$i"; \
+		$(INSTALL_PROGRAM) $$i $(DESTDIR)$(bindir)/$$i; \
+	done
+	$(Q) for i in $(LPROGS); do \
+		$(ES) "	INSTALL $(libdir)/$$i"; \
+		$(INSTALL_PROGRAM) $$i $(DESTDIR)$(libdir)/$$i; \
+	done
+	$(Q) for i in $(SMANPAGES); do \
+		for j in $(COMPRESS_EXT); do \
+			$(RM) -f $(DESTDIR)$(man8dir)/$$i.$$j; \
+		done; \
+		$(ES) "	INSTALL_DATA $(man8dir)/$$i"; \
+		$(INSTALL_DATA) $$i $(DESTDIR)$(man8dir)/$$i; \
+	done
+	$(Q) $(RM) -f $(DESTDIR)$(man8dir)/mkfs.ext2.8.gz \
+		$(DESTDIR)$(man8dir)/mkfs.ext3.8.gz
+	$(Q) for i in ext2 ext3 ext4 ext4dev; do \
+		$(ES) "	LINK mkfs.$$i.8"; \
+		(cd $(DESTDIR)$(man8dir); \
+			$(LN) $(LINK_INSTALL_FLAGS) mke2fs.8 mkfs.$$i.8); \
+	done
+	$(Q) for i in $(UMANPAGES); do \
+		for j in $(COMPRESS_EXT); do \
+			$(RM) -f $(DESTDIR)$(man1dir)/$$i.$$j; \
+		done; \
+		$(ES) "	INSTALL_DATA $(man1dir)/$$i"; \
+		$(INSTALL_DATA) $$i $(DESTDIR)$(man1dir)/$$i; \
+	done
+	$(Q) for i in $(FMANPAGES); do \
+		for j in $(COMPRESS_EXT); do \
+			$(RM) -f $(DESTDIR)$(man5dir)/$$i.$$j; \
+		done; \
+		$(ES) "	INSTALL_DATA $(man5dir)/$$i"; \
+		$(INSTALL_DATA) $$i $(DESTDIR)$(man5dir)/$$i; \
+	done
+	$(Q) for i in ext2 ext3; do \
+		$(ES) "	LINK $$i.5"; \
+		(cd $(DESTDIR)$(man5dir); \
+			$(LN) $(LINK_INSTALL_FLAGS) ext4.5 $$i.5); \
+	done
+	$(Q) if test -f $(DESTDIR)$(root_sysconfdir)/mke2fs.conf; then \
+		if cmp -s $(DESTDIR)$(root_sysconfdir)/mke2fs.conf \
+			mke2fs.conf; then \
+			true; \
+		else \
+			if grep -q ext4dev $(DESTDIR)$(root_sysconfdir)/mke2fs.conf ; then \
+				$(ES) "	INSTALL_DATA $(root_sysconfdir)/mke2fs.conf.e2fsprogs-new"; \
+				$(INSTALL_DATA) mke2fs.conf \
+					$(DESTDIR)$(root_sysconfdir)/mke2fs.conf.e2fsprogs-new; \
+				echo "Warning: installing mke2fs.conf in $(DESTDIR)$(root_sysconfdir)/mke2fs.conf.e2fsprogs-new"; \
+				echo "Check to see if you need to update your $(root_sysconfdir)/mke2fs.conf"; \
+			else \
+				$(ES) "	INSTALL_DATA $(root_sysconfdir)/mke2fs.conf"; \
+				mv $(DESTDIR)$(root_sysconfdir)/mke2fs.conf \
+				   $(DESTDIR)$(root_sysconfdir)/mke2fs.conf.e2fsprogs-old; \
+				$(INSTALL_DATA) mke2fs.conf \
+					$(DESTDIR)$(root_sysconfdir)/mke2fs.conf; \
+				echo "Your mke2fs.conf is too old.  Backing up old version in"; \
+				echo "$(DESTDIR)$(root_sysconfdir)/mke2fs.conf.e2fsprogs-old.  Please check to see"; \
+				echo "if you have any local customizations that you wish to preserve."; \
+			fi; \
+			echo " "; \
+		fi; \
+	else \
+		$(ES) "	INSTALL_DATA $(root_sysconfdir)/mke2fs.conf"; \
+		$(INSTALL_DATA) mke2fs.conf \
+			$(DESTDIR)$(root_sysconfdir)/mke2fs.conf; \
+	fi
+
+install-strip: install
+	$(Q) for i in $(SPROGS); do \
+		$(E) "	STRIP $(root_sbindir)/$$i"; \
+		$(STRIP) $(DESTDIR)$(root_sbindir)/$$i; \
+	done
+	$(Q) for i in $(USPROGS); do \
+		$(E) "	STRIP $(sbindir)/$$i"; \
+		$(STRIP) $(DESTDIR)$(sbindir)/$$i; \
+	done
+
+uninstall:
+	for i in $(SPROGS); do \
+		$(RM) -f $(DESTDIR)$(root_sbindir)/$$i; \
+	done
+	for i in $(USPROGS); do \
+		$(RM) -f $(DESTDIR)$(sbindir)/$$i; \
+	done
+	for i in $(LPROGS); do \
+		$(RM) -f $(DESTDIR)$(libdir)/$$i; \
+	done
+	$(RM) -f $(DESTDIR)$(root_sbindir)/mkfs.ext2 \
+			$(DESTDIR)$(root_sbindir)/mkfs.ext3 \
+			$(DESTDIR)$(root_sbindir)/mkfs.ext4 \
+			$(DESTDIR)$(root_sbindir)/mkfs.ext4dev
+	for i in $(UPROGS); do \
+		$(RM) -f $(DESTDIR)$(bindir)/$$i; \
+	done
+	for i in $(SMANPAGES); do \
+		$(RM) -f $(DESTDIR)$(man8dir)/$$i; \
+	done
+	$(RM) -f $(DESTDIR)$(man8dir)/mkfs.ext2.8 \
+		$(DESTDIR)$(man8dir)/mkfs.ext3.8 \
+		$(DESTDIR)$(man8dir)/mkfs.ext4.8 \
+		$(DESTDIR)$(man8dir)/mkfs.ext4dev.8 \
+		$(DESTDIR)$(man8dir)/fsck.ext2.8 \
+		$(DESTDIR)$(man8dir)/fsck.ext3.8 \
+		$(DESTDIR)$(man8dir)/fsck.ext4.8 \
+		$(DESTDIR)$(man8dir)/fsck.ext4dev.8
+
+	for i in $(UMANPAGES); do \
+		$(RM) -f $(DESTDIR)$(man1dir)/$$i; \
+	done
+	for i in $(FINDFS_LINK) e2label ; do \
+		$(RM) -f $(DESTDIR)$(root_sbindir)/$$i; \
+	done
+	for i in $(FMANPAGES); do \
+		$(RM) -f $(DESTDIR)$(man5dir)/$$i; \
+	done
+	$(Q) for i in ext2 ext3; do \
+		$(ES) "	LINK $$i.5"; \
+		$(RM) -f $(DESTDIR)$(man5dir)/$$i.5; \
+	done
+	if cmp -s mke2fs.conf $(DESTDIR)/$(root_sysconfdir)/mke2fs.conf; then \
+		$(RM) $(DESTDIR)/$(root_sysconfdir)/mke2fs.conf; \
+	fi
+
+clean:
+	$(RM) -f $(SPROGS) $(USPROGS) $(UPROGS) $(UMANPAGES) $(SMANPAGES) \
+		$(FMANPAGES) profile.h \
+		base_device base_device.out mke2fs.static filefrag e2freefrag \
+		e2initrd_helper partinfo prof_err.[ch] default_profile.c \
+		uuidd e2image tune2fs.static tst_ismounted fsck.profiled \
+		blkid.profiled tune2fs.profiled e2image.profiled \
+		e2undo.profiled mke2fs.profiled dumpe2fs.profiled \
+		logsave.profiled filefrag.profiled uuidgen.profiled \
+		uuidd.profiled e2image.profiled mke2fs.conf \
+		profiled/*.o \#* *.s *.o *.a *~ core gmon.out
+
+mostlyclean: clean
+distclean: clean
+	$(RM) -f .depend Makefile $(srcdir)/TAGS $(srcdir)/Makefile.in.old
+
+# +++ Dependency line eater +++
+# 
+# Makefile dependencies follow.  This must be the last section in
+# the Makefile.in file
+#
+tune2fs.o: $(srcdir)/tune2fs.c $(top_builddir)/lib/config.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_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 \
+ $(top_srcdir)/lib/e2p/e2p.h $(srcdir)/jfs_user.h \
+ $(top_srcdir)/lib/ext2fs/kernel-jbd.h $(top_srcdir)/lib/ext2fs/jfs_compat.h \
+ $(top_srcdir)/lib/ext2fs/kernel-list.h $(srcdir)/util.h \
+ $(top_srcdir)/lib/quota/mkquota.h $(top_srcdir)/lib/quota/quotaio.h \
+ $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \
+ $(top_srcdir)/lib/../e2fsck/dict.h $(top_srcdir)/version.h \
+ $(srcdir)/nls-enable.h
+mklost+found.o: $(srcdir)/mklost+found.c $(top_builddir)/lib/config.h \
+ $(top_builddir)/lib/dirpaths.h $(top_srcdir)/lib/ext2fs/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(top_srcdir)/version.h \
+ $(srcdir)/nls-enable.h
+mke2fs.o: $(srcdir)/mke2fs.c $(top_builddir)/lib/config.h \
+ $(top_builddir)/lib/dirpaths.h $(top_srcdir)/lib/ext2fs/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(top_srcdir)/lib/ext2fs/ext2fsP.h \
+ $(top_srcdir)/lib/ext2fs/ext2fs.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 \
+ $(top_srcdir)/lib/e2p/e2p.h $(top_srcdir)/lib/ext2fs/ext2fs.h \
+ $(srcdir)/util.h profile.h prof_err.h $(top_srcdir)/version.h \
+ $(srcdir)/nls-enable.h $(top_srcdir)/lib/quota/mkquota.h \
+ $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \
+ $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h
+chattr.o: $(srcdir)/chattr.c $(top_builddir)/lib/config.h \
+ $(top_builddir)/lib/dirpaths.h $(top_srcdir)/lib/ext2fs/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(top_srcdir)/lib/et/com_err.h \
+ $(top_srcdir)/lib/e2p/e2p.h $(top_srcdir)/version.h $(srcdir)/nls-enable.h
+lsattr.o: $(srcdir)/lsattr.c $(top_builddir)/lib/config.h \
+ $(top_builddir)/lib/dirpaths.h $(top_srcdir)/lib/ext2fs/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(top_srcdir)/lib/et/com_err.h \
+ $(top_srcdir)/lib/e2p/e2p.h $(top_srcdir)/version.h $(srcdir)/nls-enable.h
+dumpe2fs.o: $(srcdir)/dumpe2fs.c $(top_builddir)/lib/config.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_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 \
+ $(top_srcdir)/lib/e2p/e2p.h $(srcdir)/jfs_user.h \
+ $(top_srcdir)/lib/ext2fs/kernel-jbd.h $(top_srcdir)/lib/ext2fs/jfs_compat.h \
+ $(top_srcdir)/lib/ext2fs/kernel-list.h $(top_srcdir)/version.h \
+ $(srcdir)/nls-enable.h
+badblocks.o: $(srcdir)/badblocks.c $(top_builddir)/lib/config.h \
+ $(top_builddir)/lib/dirpaths.h $(top_srcdir)/lib/et/com_err.h \
+ $(top_srcdir)/lib/ext2fs/ext2_io.h $(top_srcdir)/lib/ext2fs/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(top_srcdir)/lib/ext2fs/ext2fs.h \
+ $(top_srcdir)/lib/ext2fs/ext3_extents.h \
+ $(top_builddir)/lib/ext2fs/ext2_err.h \
+ $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \
+ $(srcdir)/nls-enable.h
+fsck.o: $(srcdir)/fsck.c $(top_builddir)/lib/config.h \
+ $(top_builddir)/lib/dirpaths.h $(top_srcdir)/version.h \
+ $(srcdir)/nls-enable.h $(srcdir)/fsck.h
+util.o: $(srcdir)/util.c $(top_builddir)/lib/config.h \
+ $(top_builddir)/lib/dirpaths.h $(top_srcdir)/lib/et/com_err.h \
+ $(top_srcdir)/lib/e2p/e2p.h $(top_srcdir)/lib/ext2fs/ext2_fs.h \
+ $(top_builddir)/lib/ext2fs/ext2_types.h $(top_srcdir)/lib/ext2fs/ext2fs.h \
+ $(top_srcdir)/lib/ext2fs/ext3_extents.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 \
+ $(srcdir)/nls-enable.h $(srcdir)/util.h
+uuidgen.o: $(srcdir)/uuidgen.c $(top_builddir)/lib/config.h \
+ $(top_builddir)/lib/dirpaths.h $(srcdir)/nls-enable.h
+blkid.o: $(srcdir)/blkid.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
+logsave.o: $(srcdir)/logsave.c $(top_builddir)/lib/config.h \
+ $(top_builddir)/lib/dirpaths.h
+filefrag.o: $(srcdir)/filefrag.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 \
+ $(top_srcdir)/lib/ext2fs/fiemap.h
+base_device.o: $(srcdir)/base_device.c $(top_builddir)/lib/config.h \
+ $(top_builddir)/lib/dirpaths.h $(srcdir)/fsck.h
+ismounted.o: $(srcdir)/ismounted.c $(top_builddir)/lib/config.h \
+ $(top_builddir)/lib/dirpaths.h $(srcdir)/fsck.h \
+ $(top_srcdir)/lib/et/com_err.h
+profile.o: $(srcdir)/../e2fsck/profile.c $(top_builddir)/lib/config.h \
+ $(top_builddir)/lib/dirpaths.h $(top_srcdir)/lib/et/com_err.h \
+ $(srcdir)/../e2fsck/profile.h prof_err.h
+e2undo.o: $(srcdir)/e2undo.c $(top_builddir)/lib/config.h \
+ $(top_builddir)/lib/dirpaths.h $(top_srcdir)/lib/ext2fs/tdb.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 \
+ $(srcdir)/nls-enable.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/ext2fs/ext2_types.h $(top_srcdir)/lib/ext2fs/ext2fs.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 \
+ $(srcdir)/e2freefrag.h
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/badblocks.8.in b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/badblocks.8.in
new file mode 100644
index 0000000..f507f63
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/badblocks.8.in
@@ -0,0 +1,234 @@
+.\" -*- nroff -*-
+.TH BADBLOCKS 8 "@E2FSPROGS_MONTH@ @E2FSPROGS_YEAR@" "E2fsprogs version @E2FSPROGS_VERSION@"
+.SH NAME
+badblocks \- search a device for bad blocks
+.SH SYNOPSIS
+.B badblocks
+[
+.B \-svwnfBX
+]
+[
+.B \-b
+.I block-size
+]
+[
+.B \-c
+.I blocks_at_once
+]
+[
+.B \-e
+.I max_bad_blocks
+]
+[
+.B \-d
+.I read_delay_factor
+]
+[
+.B \-i
+.I input_file
+]
+[
+.B \-o
+.I output_file
+]
+[
+.B \-p
+.I num_passes
+]
+[
+.B \-t
+.I test_pattern
+]
+.I device
+[
+.I last-block
+] [
+.I first-block 
+]
+.SH DESCRIPTION
+.B badblocks
+is used to search for bad blocks on a device (usually a disk partition).
+.I device
+is the special file corresponding to the device (e.g
+.IR /dev/hdc1 ).
+.I last-block
+is the last block to be checked; if it is not specified, the last block
+on the device is used as a default.
+.I first-block
+is an optional parameter specifying the starting block number
+for the test, which allows the testing to start in the middle of the
+disk.  If it is not specified the first block on the disk is used as a default.
+.PP
+.B Important note:
+If the output of 
+.B badblocks
+is going to be fed to the
+.B e2fsck
+or 
+.B mke2fs
+programs, it is important that the block size is properly specified,
+since the block numbers which are generated are very dependent on the 
+block size in use by the filesystem.   
+For this reason, it is strongly recommended that
+users 
+.B not
+run 
+.B badblocks 
+directly, but rather use the 
+.B \-c
+option of the
+.B e2fsck
+and 
+.B mke2fs
+programs.
+.SH OPTIONS
+.TP
+.BI \-b " block-size"
+Specify the size of blocks in bytes.  The default is 1024.
+.TP
+.BI \-c " number of blocks"
+is the number of blocks which are tested at a time.  The default is 64.
+.TP
+.BI \-e " max bad block count"
+Specify a maximum number of bad blocks before aborting the test.  The
+default is 0, meaning the test will continue until the end of the test
+range is reached.
+.TP
+.BI \-d " read delay factor"
+This parameter, if passed and non-zero, will cause bad blocks to sleep
+between reads if there were no errors encountered in the read
+operation; the delay will be calculated as a percentage of the time it
+took for the read operation to be performed. In other words, a value of 
+100 will cause each read to be delayed by the amount the previous read
+took, and a value of 200 by twice the amount.
+.TP
+.B \-f
+Normally, badblocks will refuse to do a read/write or a non-destructive
+test on a device which is mounted, since either can cause the system to
+potentially crash and/or damage the filesystem even if it is mounted
+read-only.  This can be overridden using the
+.B \-f
+flag, but should almost never be used --- if you think you're smarter
+than the 
+.B badblocks
+program, you almost certainly aren't.  The only time when this option 
+might be safe to use is if the /etc/mtab file is incorrect, and the device
+really isn't mounted.
+.TP
+.BI \-i " input_file"
+Read a list of already existing known bad blocks.
+.B Badblocks
+will skip testing these blocks since they are known to be bad.  If
+.I input_file
+is specified as "-", the list will be read from the standard input.
+Blocks listed in this list will be omitted from the list of
+.I new
+bad blocks produced on the standard output or in the output file.
+The
+.B \-b
+option of
+.BR dumpe2fs (8)
+can be used to retrieve the list of blocks currently marked bad on
+an existing filesystem, in a format suitable for use with this option.
+.TP
+.B \-n
+Use non-destructive read-write mode.  By default only a non-destructive 
+read-only test is done.  This option must not be combined with the 
+.B \-w
+option, as they are mutually exclusive.
+.TP
+.BI \-o " output_file"
+Write the list of bad blocks to the specified file.  Without this option,
+.B badblocks
+displays the list on its standard output.  The format of this file is suitable
+for use by the
+.
+.B \-l
+option in 
+.BR e2fsck (8)
+or
+.BR mke2fs (8).
+.TP
+.BI \-p " num_passes"
+Repeat scanning the disk until there are no new blocks discovered in
+num_passes consecutive scans of the disk.
+Default is 0, meaning
+.B badblocks
+will exit after the first pass.
+.TP
+.B \-s
+Show the progress of the scan by writing out rough percentage completion
+of the current badblocks pass over the disk.  Note that badblocks may do
+multiple test passes over the disk, in particular if the
+.B \-p
+or
+.B \-w
+option is requested by the user.
+.TP
+.BI \-t " test_pattern"
+Specify a test pattern to be read (and written) to disk blocks.   The
+.I test_pattern
+may either be a numeric value between 0 and ULONG_MAX-1 inclusive, or the word 
+"random", which specifies that the block should be filled with a random
+bit pattern.
+For read/write (\fB-w\fR) and non-destructive (\fB-n\fR) modes,
+one or more test patterns may be specified by specifying the
+.B -t
+option for each test pattern desired.  For
+read-only mode only a single pattern may be specified and it may not be
+"random".  Read-only testing with a pattern assumes that the
+specified pattern has previously been written to the disk - if not, large
+numbers of blocks will fail verification.  
+If multiple patterns
+are specified then all blocks will be tested with one pattern 
+before proceeding to the next pattern.
+.TP
+.B \-v
+Verbose mode.  Will write the number of read errors, write errors and data-
+corruptions to stderr.
+.TP
+.B \-w
+Use write-mode test. With this option,
+.B badblocks
+scans for bad blocks by writing some patterns (0xaa, 0x55, 0xff, 0x00) on
+every block of the device, reading every block and comparing the contents.  
+This option may not be combined with the 
+.B \-n 
+option, as they are mutually exclusive.
+.TP
+.B \-B
+Use buffered I/O and do not use Direct I/O, even if it is available.
+.TP
+.B \-X
+Internal flag only to be used by
+.BR e2fsck (8)
+and
+.BR mke2fs (8).
+It bypasses the exclusive mode in-use device safety check.
+.SH WARNING
+Never use the
+.B \-w
+option on a device containing an existing file system.
+This option erases data!  If you want to do write-mode testing on
+an existing file system, use the
+.B \-n
+option instead.  It is slower, but it will preserve your data.  
+.PP
+The
+.B \-e
+option will cause badblocks to output a possibly incomplete list of
+bad blocks. Therefore it is recommended to use it only when one wants
+to know if there are any bad blocks at all on the device, and not when
+the list of bad blocks is wanted.
+.SH AUTHOR
+.B badblocks
+was written by Remy Card <Remy.Card@linux.org>.  Current maintainer is
+Theodore Ts'o <tytso@alum.mit.edu>.  Non-destructive read/write test
+implemented by David Beattie <dbeattie@softhome.net>.
+.SH AVAILABILITY
+.B badblocks
+is part of the e2fsprogs package and is available from 
+http://e2fsprogs.sourceforge.net.
+.SH SEE ALSO
+.BR e2fsck (8),
+.BR mke2fs (8)
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/badblocks.c b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/badblocks.c
new file mode 100644
index 0000000..912ef28
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/badblocks.c
@@ -0,0 +1,1332 @@
+/*
+ * badblocks.c		- Bad blocks checker
+ *
+ * Copyright (C) 1992, 1993, 1994  Remy Card <card@masi.ibp.fr>
+ *                                 Laboratoire MASI, Institut Blaise Pascal
+ *                                 Universite Pierre et Marie Curie (Paris VI)
+ *
+ * Copyright 1995, 1996, 1997, 1998, 1999 by Theodore Ts'o
+ * Copyright 1999 by David Beattie
+ *
+ * This file is based on the minix file system programs fsck and mkfs
+ * written and copyrighted by Linus Torvalds <Linus.Torvalds@cs.helsinki.fi>
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+/*
+ * History:
+ * 93/05/26	- Creation from e2fsck
+ * 94/02/27	- Made a separate bad blocks checker
+ * 99/06/30...99/07/26 - Added non-destructive write-testing,
+ *                       configurable blocks-at-once parameter,
+ * 			 loading of badblocks list to avoid testing
+ * 			 blocks known to be bad, multiple passes to
+ * 			 make sure that no new blocks are added to the
+ * 			 list.  (Work done by David Beattie)
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE /* for O_DIRECT */
+#endif
+
+#include "config.h"
+#include <errno.h>
+#include <fcntl.h>
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#else
+extern char *optarg;
+extern int optind;
+#endif
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <setjmp.h>
+#include <time.h>
+#include <limits.h>
+
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+
+#include "et/com_err.h"
+#include "ext2fs/ext2_io.h"
+#include "ext2fs/ext2_fs.h"
+#include "ext2fs/ext2fs.h"
+#include "nls-enable.h"
+
+#ifndef O_LARGEFILE
+#define O_LARGEFILE 0
+#endif
+
+static const char * program_name = "badblocks";
+static const char * done_string = N_("done                                                 \n");
+
+static int v_flag;			/* verbose */
+static int w_flag;			/* do r/w test: 0=no, 1=yes,
+					 * 2=non-destructive */
+static int s_flag;			/* show progress of test */
+static int force;			/* force check of mounted device */
+static int t_flag;			/* number of test patterns */
+static int t_max;			/* allocated test patterns */
+static unsigned int *t_patts;		/* test patterns */
+static int use_buffered_io;
+static int exclusive_ok;
+static unsigned int max_bb;		/* Abort test if more than this number of bad blocks has been encountered */
+static unsigned int d_flag;		/* delay factor between reads */
+static struct timeval time_start;
+
+#define T_INC 32
+
+static unsigned int sys_page_size = 4096;
+
+static void usage(void)
+{
+	fprintf(stderr, _(
+"Usage: %s [-b block_size] [-i input_file] [-o output_file] [-svwnf]\n"
+"       [-c blocks_at_once] [-d delay_factor_between_reads] [-e max_bad_blocks]\n"
+"       [-p num_passes] [-t test_pattern [-t test_pattern [...]]]\n"
+"       device [last_block [first_block]]\n"),
+		 program_name);
+	exit (1);
+}
+
+static void exclusive_usage(void)
+{
+	fprintf(stderr,
+		_("%s: The -n and -w options are mutually exclusive.\n\n"),
+		program_name);
+	exit(1);
+}
+
+static blk_t currently_testing = 0;
+static blk_t num_blocks = 0;
+static blk_t num_read_errors = 0;
+static blk_t num_write_errors = 0;
+static blk_t num_corruption_errors = 0;
+static ext2_badblocks_list bb_list = NULL;
+static FILE *out;
+static blk_t next_bad = 0;
+static ext2_badblocks_iterate bb_iter = NULL;
+
+enum error_types { READ_ERROR, WRITE_ERROR, CORRUPTION_ERROR };
+
+static void *allocate_buffer(size_t size)
+{
+	void	*ret = 0;
+
+#ifdef HAVE_POSIX_MEMALIGN
+	if (posix_memalign(&ret, sys_page_size, size) < 0)
+		ret = 0;
+#else
+#ifdef HAVE_MEMALIGN
+	ret = memalign(sys_page_size, size);
+#else
+#ifdef HAVE_VALLOC
+	ret = valloc(size);
+#endif /* HAVE_VALLOC */
+#endif /* HAVE_MEMALIGN */
+#endif /* HAVE_POSIX_MEMALIGN */
+
+	if (!ret)
+		ret = malloc(size);
+
+	return ret;
+}
+
+/*
+ * This routine reports a new bad block.  If the bad block has already
+ * been seen before, then it returns 0; otherwise it returns 1.
+ */
+static int bb_output (blk_t bad, enum error_types error_type)
+{
+	errcode_t errcode;
+
+	if (ext2fs_badblocks_list_test(bb_list, bad))
+		return 0;
+
+	fprintf(out, "%lu\n", (unsigned long) bad);
+	fflush(out);
+
+	errcode = ext2fs_badblocks_list_add (bb_list, bad);
+	if (errcode) {
+		com_err (program_name, errcode, "adding to in-memory bad block list");
+		exit (1);
+	}
+
+	/* kludge:
+	   increment the iteration through the bb_list if
+	   an element was just added before the current iteration
+	   position.  This should not cause next_bad to change. */
+	if (bb_iter && bad < next_bad)
+		ext2fs_badblocks_list_iterate (bb_iter, &next_bad);
+
+	if (error_type == READ_ERROR) {
+	  num_read_errors++;
+	} else if (error_type == WRITE_ERROR) {
+	  num_write_errors++;
+	} else if (error_type == CORRUPTION_ERROR) {
+	  num_corruption_errors++;
+	}
+	return 1;
+}
+
+static char *time_diff_format(struct timeval *tv1,
+			      struct timeval *tv2, char *buf)
+{
+        time_t	diff = (tv1->tv_sec - tv2->tv_sec);
+	int	hr,min,sec;
+
+	sec = diff % 60;
+	diff /= 60;
+	min = diff % 60;
+	hr = diff / 60;
+
+	if (hr)
+		sprintf(buf, "%d:%02d:%02d", hr, min, sec);
+	else
+		sprintf(buf, "%d:%02d", min, sec);
+	return buf;
+}
+
+static float calc_percent(unsigned long current, unsigned long total) {
+	float percent = 0.0;
+	if (total <= 0)
+		return percent;
+	if (current >= total) {
+		percent = 100.0;
+	} else {
+		percent=(100.0*(float)current/(float)total);
+	}
+	return percent;
+}
+
+static void print_status(void)
+{
+	struct timeval time_end;
+	char diff_buf[32], line_buf[128];
+	int len;
+
+	gettimeofday(&time_end, 0);
+	len = snprintf(line_buf, sizeof(line_buf), 
+		       _("%6.2f%% done, %s elapsed. "
+		         "(%d/%d/%d errors)"),
+		       calc_percent((unsigned long) currently_testing,
+				    (unsigned long) num_blocks), 
+		       time_diff_format(&time_end, &time_start, diff_buf),
+		       num_read_errors,
+		       num_write_errors,
+		       num_corruption_errors);
+#ifdef HAVE_MBSTOWCS
+	len = mbstowcs(NULL, line_buf, sizeof(line_buf));
+#endif
+	fputs(line_buf, stderr);
+	memset(line_buf, '\b', len);
+	line_buf[len] = 0;
+	fputs(line_buf, stderr);	
+	fflush (stderr);
+}
+
+static void alarm_intr(int alnum EXT2FS_ATTR((unused)))
+{
+	signal (SIGALRM, alarm_intr);
+	alarm(1);
+	if (!num_blocks)
+		return;
+	print_status();
+}
+
+static void *terminate_addr = NULL;
+
+static void terminate_intr(int signo EXT2FS_ATTR((unused)))
+{
+	fflush(out);
+	fprintf(stderr, "\n\nInterrupted at block %llu\n", 
+		(unsigned long long) currently_testing);
+	fflush(stderr);
+	if (terminate_addr)
+		longjmp(terminate_addr,1);
+	exit(1);
+}
+
+static void capture_terminate(jmp_buf term_addr)
+{
+	terminate_addr = term_addr;
+	signal (SIGHUP, terminate_intr);
+	signal (SIGINT, terminate_intr);
+	signal (SIGPIPE, terminate_intr);
+	signal (SIGTERM, terminate_intr);
+	signal (SIGUSR1, terminate_intr);
+	signal (SIGUSR2, terminate_intr);
+}
+
+static void uncapture_terminate(void)
+{
+	terminate_addr = NULL;
+	signal (SIGHUP, SIG_DFL);
+	signal (SIGINT, SIG_DFL);
+	signal (SIGPIPE, SIG_DFL);
+	signal (SIGTERM, SIG_DFL);
+	signal (SIGUSR1, SIG_DFL);
+	signal (SIGUSR2, SIG_DFL);
+}
+
+/* Linux requires that O_DIRECT I/Os be 512-byte sector aligned */
+
+#define O_DIRECT_SIZE 512
+
+static void set_o_direct(int dev, unsigned char *buffer, size_t size,
+			 ext2_loff_t offset)
+{
+#ifdef O_DIRECT
+	static int current_O_DIRECT;	/* Current status of O_DIRECT flag */
+	int new_flag = O_DIRECT;
+	int flag;
+
+	if ((use_buffered_io != 0) ||
+	    (((unsigned long) buffer & (sys_page_size - 1)) != 0) ||
+	    ((size & (sys_page_size - 1)) != 0) ||
+	    ((offset & (O_DIRECT_SIZE - 1)) != 0))
+		new_flag = 0;
+
+	if (new_flag != current_O_DIRECT) {
+	     /* printf("%s O_DIRECT\n", new_flag ? "Setting" : "Clearing"); */
+		flag = fcntl(dev, F_GETFL);
+		if (flag > 0) {
+			flag = (flag & ~O_DIRECT) | new_flag;
+			fcntl(dev, F_SETFL, flag);
+		}
+		current_O_DIRECT = new_flag;
+	}
+#endif
+}
+
+
+static void pattern_fill(unsigned char *buffer, unsigned int pattern,
+			 size_t n)
+{
+	unsigned int	i, nb;
+	unsigned char	bpattern[sizeof(pattern)], *ptr;
+
+	if (pattern == (unsigned int) ~0) {
+		for (ptr = buffer; ptr < buffer + n; ptr++) {
+			(*ptr) = random() % (1 << (8 * sizeof(char)));
+		}
+		if (s_flag | v_flag)
+			fputs(_("Testing with random pattern: "), stderr);
+	} else {
+		bpattern[0] = 0;
+		for (i = 0; i < sizeof(bpattern); i++) {
+			if (pattern == 0)
+				break;
+			bpattern[i] = pattern & 0xFF;
+			pattern = pattern >> 8;
+		}
+		nb = i ? (i-1) : 0;
+		for (ptr = buffer, i = nb; ptr < buffer + n; ptr++) {
+			*ptr = bpattern[i];
+			if (i == 0)
+				i = nb;
+			else
+				i--;
+		}
+		if (s_flag | v_flag) {
+			fputs(_("Testing with pattern 0x"), stderr);
+			for (i = 0; i <= nb; i++)
+				fprintf(stderr, "%02x", buffer[i]);
+			fputs(": ", stderr);
+		}
+	}
+}
+
+/*
+ * Perform a read of a sequence of blocks; return the number of blocks
+ *    successfully sequentially read.
+ */
+static int do_read (int dev, unsigned char * buffer, int try, int block_size,
+		    blk_t current_block)
+{
+	long got;
+	struct timeval tv1, tv2;
+#define NANOSEC (1000000000L)
+#define MILISEC (1000L)
+
+#if 0
+	printf("do_read: block %d, try %d\n", current_block, try);
+#endif
+	set_o_direct(dev, buffer, try * block_size,
+		     ((ext2_loff_t) current_block) * block_size);
+
+	if (v_flag > 1)
+		print_status();
+
+	/* Seek to the correct loc. */
+	if (ext2fs_llseek (dev, (ext2_loff_t) current_block * block_size,
+			 SEEK_SET) != (ext2_loff_t) current_block * block_size)
+		com_err (program_name, errno, "%s", _("during seek"));
+
+	/* Try the read */
+	if (d_flag)
+		gettimeofday(&tv1, NULL);
+	got = read (dev, buffer, try * block_size);
+	if (d_flag)
+		gettimeofday(&tv2, NULL);
+	if (got < 0)
+		got = 0;
+	if (got & 511)
+		fprintf(stderr, _("Weird value (%ld) in do_read\n"), got);
+	got /= block_size;
+	if (d_flag && got == try) {
+#ifdef HAVE_NANOSLEEP
+		struct timespec ts;
+		ts.tv_sec = tv2.tv_sec - tv1.tv_sec;
+		ts.tv_nsec = (tv2.tv_usec - tv1.tv_usec) * MILISEC;
+		if (ts.tv_nsec < 0) {
+			ts.tv_nsec += NANOSEC;
+			ts.tv_sec -= 1;
+		}
+		/* increase/decrease the sleep time based on d_flag value */
+		ts.tv_sec = ts.tv_sec * d_flag / 100;
+		ts.tv_nsec = ts.tv_nsec * d_flag / 100;
+		if (ts.tv_nsec > NANOSEC) {
+			ts.tv_sec += ts.tv_nsec / NANOSEC;
+			ts.tv_nsec %= NANOSEC;
+		}
+		if (ts.tv_sec || ts.tv_nsec)
+			nanosleep(&ts, NULL);
+#else
+#ifdef HAVE_USLEEP
+		struct timeval tv;
+		tv.tv_sec = tv2.tv_sec - tv1.tv_sec;
+		tv.tv_usec = tv2.tv_usec - tv1.tv_usec;
+		tv.tv_sec = tv.tv_sec * d_flag / 100;
+		tv.tv_usec = tv.tv_usec * d_flag / 100;
+		if (tv.tv_usec > 1000000) {
+			tv.tv_sec += tv.tv_usec / 1000000;
+			tv.tv_usec %= 1000000;
+		}
+		if (tv.tv_sec)
+			sleep(tv.tv_sec);
+		if (tv.tv_usec)
+			usleep(tv.tv_usec);
+#endif
+#endif
+	}
+	return got;
+}
+
+/*
+ * Perform a write of a sequence of blocks; return the number of blocks
+ *    successfully sequentially written.
+ */
+static int do_write(int dev, unsigned char * buffer, int try, int block_size,
+		    unsigned long current_block)
+{
+	long got;
+
+#if 0
+	printf("do_write: block %lu, try %d\n", current_block, try);
+#endif
+	set_o_direct(dev, buffer, try * block_size,
+		     ((ext2_loff_t) current_block) * block_size);
+
+	if (v_flag > 1)
+		print_status();
+
+	/* Seek to the correct loc. */
+	if (ext2fs_llseek (dev, (ext2_loff_t) current_block * block_size,
+			 SEEK_SET) != (ext2_loff_t) current_block * block_size)
+		com_err (program_name, errno, "%s", _("during seek"));
+
+	/* Try the write */
+	got = write (dev, buffer, try * block_size);
+	if (got < 0)
+		got = 0;
+	if (got & 511)
+		fprintf(stderr, "Weird value (%ld) in do_write\n", got);
+	got /= block_size;
+	return got;
+}
+
+static int host_dev;
+
+static void flush_bufs(void)
+{
+	errcode_t	retval;
+
+#ifdef O_DIRECT
+	if (!use_buffered_io)
+		return;
+#endif
+	retval = ext2fs_sync_device(host_dev, 1);
+	if (retval)
+		com_err(program_name, retval, "%s",
+			_("during ext2fs_sync_device"));
+}
+
+static unsigned int test_ro (int dev, blk_t last_block,
+			     int block_size, blk_t first_block,
+			     unsigned int blocks_at_once)
+{
+	unsigned char * blkbuf;
+	int try;
+	int got;
+	unsigned int bb_count = 0;
+	errcode_t errcode;
+	blk_t recover_block = ~0;
+
+	/* set up abend handler */
+	capture_terminate(NULL);
+
+	errcode = ext2fs_badblocks_list_iterate_begin(bb_list,&bb_iter);
+	if (errcode) {
+		com_err(program_name, errcode, "%s",
+			_("while beginning bad block list iteration"));
+		exit (1);
+	}
+	do {
+		ext2fs_badblocks_list_iterate (bb_iter, &next_bad);
+	} while (next_bad && next_bad < first_block);
+
+	if (t_flag) {
+		blkbuf = allocate_buffer((blocks_at_once + 1) * block_size);
+	} else {
+		blkbuf = allocate_buffer(blocks_at_once * block_size);
+	}
+	if (!blkbuf)
+	{
+		com_err(program_name, ENOMEM, "%s",
+			_("while allocating buffers"));
+		exit (1);
+	}
+	if (v_flag) {
+		fprintf(stderr, _("Checking blocks %lu to %lu\n"),
+			(unsigned long)first_block,
+			(unsigned long)last_block - 1);
+	}
+	if (t_flag) {
+		fputs(_("Checking for bad blocks in read-only mode\n"), stderr);
+		pattern_fill(blkbuf + blocks_at_once * block_size,
+			     t_patts[0], block_size);
+	}
+	flush_bufs();
+	try = blocks_at_once;
+	currently_testing = first_block;
+	num_blocks = last_block - 1;
+	if (!t_flag && (s_flag || v_flag))
+		fputs(_("Checking for bad blocks (read-only test): "), stderr);
+	if (s_flag && v_flag <= 1)
+		alarm_intr(SIGALRM);
+	while (currently_testing < last_block)
+	{
+		if (max_bb && bb_count >= max_bb) {
+			if (s_flag || v_flag) {
+				fputs(_("Too many bad blocks, aborting test\n"), stderr);
+			}
+			break;
+		}
+		if (next_bad) {
+			if (currently_testing == next_bad) {
+				/* fprintf (out, "%lu\n", nextbad); */
+				ext2fs_badblocks_list_iterate (bb_iter, &next_bad);
+				currently_testing++;
+				continue;
+			}
+			else if (currently_testing + try > next_bad)
+				try = next_bad - currently_testing;
+		}
+		if (currently_testing + try > last_block)
+			try = last_block - currently_testing;
+		got = do_read (dev, blkbuf, try, block_size, currently_testing);
+		if (t_flag) {
+			/* test the comparison between all the
+			   blocks successfully read  */
+			int i;
+			for (i = 0; i < got; ++i)
+				if (memcmp (blkbuf+i*block_size,
+					    blkbuf+blocks_at_once*block_size,
+					    block_size))
+					bb_count += bb_output(currently_testing + i, CORRUPTION_ERROR);
+		}
+		if (got == 0 && try == 1)
+			bb_count += bb_output(currently_testing++, READ_ERROR);
+		currently_testing += got;
+		if (got != try) {
+			try = 1;
+			if (recover_block == ~0U)
+				recover_block = currently_testing - got +
+					blocks_at_once;
+			continue;
+		} else if (currently_testing == recover_block) {
+			try = blocks_at_once;
+			recover_block = ~0;
+		}
+	}
+	num_blocks = 0;
+	alarm(0);
+	if (s_flag || v_flag)
+		fputs(_(done_string), stderr);
+
+	fflush (stderr);
+	free (blkbuf);
+
+	ext2fs_badblocks_list_iterate_end(bb_iter);
+
+	uncapture_terminate();
+
+	return bb_count;
+}
+
+static unsigned int test_rw (int dev, blk_t last_block,
+			     int block_size, blk_t first_block,
+			     unsigned int blocks_at_once)
+{
+	unsigned char *buffer, *read_buffer;
+	const unsigned int patterns[] = {0xaa, 0x55, 0xff, 0x00};
+	const unsigned int *pattern;
+	int i, try, got, nr_pattern, pat_idx;
+	unsigned int bb_count = 0;
+	blk_t recover_block = ~0;
+
+	/* set up abend handler */
+	capture_terminate(NULL);
+
+	buffer = allocate_buffer(2 * blocks_at_once * block_size);
+	read_buffer = buffer + blocks_at_once * block_size;
+
+	if (!buffer) {
+		com_err(program_name, ENOMEM, "%s",
+			_("while allocating buffers"));
+		exit (1);
+	}
+
+	flush_bufs();
+
+	if (v_flag) {
+		fputs(_("Checking for bad blocks in read-write mode\n"),
+		      stderr);
+		fprintf(stderr, _("From block %lu to %lu\n"),
+			(unsigned long) first_block,
+			(unsigned long) last_block - 1);
+	}
+	if (t_flag) {
+		pattern = t_patts;
+		nr_pattern = t_flag;
+	} else {
+		pattern = patterns;
+		nr_pattern = sizeof(patterns) / sizeof(patterns[0]);
+	}
+	for (pat_idx = 0; pat_idx < nr_pattern; pat_idx++) {
+		pattern_fill(buffer, pattern[pat_idx],
+			     blocks_at_once * block_size);
+		num_blocks = last_block - 1;
+		currently_testing = first_block;
+		if (s_flag && v_flag <= 1)
+			alarm_intr(SIGALRM);
+
+		try = blocks_at_once;
+		while (currently_testing < last_block) {
+			if (max_bb && bb_count >= max_bb) {
+				if (s_flag || v_flag) {
+					fputs(_("Too many bad blocks, aborting test\n"), stderr);
+				}
+				break;
+			}
+			if (currently_testing + try > last_block)
+				try = last_block - currently_testing;
+			got = do_write(dev, buffer, try, block_size,
+					currently_testing);
+			if (v_flag > 1)
+				print_status();
+
+			if (got == 0 && try == 1)
+				bb_count += bb_output(currently_testing++, WRITE_ERROR);
+			currently_testing += got;
+			if (got != try) {
+				try = 1;
+				if (recover_block == ~0U)
+					recover_block = currently_testing -
+						got + blocks_at_once;
+				continue;
+			} else if (currently_testing == recover_block) {
+				try = blocks_at_once;
+				recover_block = ~0;
+			}
+		}
+
+		num_blocks = 0;
+		alarm (0);
+		if (s_flag | v_flag)
+			fputs(_(done_string), stderr);
+		flush_bufs();
+		if (s_flag | v_flag)
+			fputs(_("Reading and comparing: "), stderr);
+		num_blocks = last_block;
+		currently_testing = first_block;
+		if (s_flag && v_flag <= 1)
+			alarm_intr(SIGALRM);
+
+		try = blocks_at_once;
+		while (currently_testing < last_block) {
+			if (max_bb && bb_count >= max_bb) {
+				if (s_flag || v_flag) {
+					fputs(_("Too many bad blocks, aborting test\n"), stderr);
+				}
+				break;
+			}
+			if (currently_testing + try > last_block)
+				try = last_block - currently_testing;
+			got = do_read (dev, read_buffer, try, block_size,
+				       currently_testing);
+			if (got == 0 && try == 1)
+				bb_count += bb_output(currently_testing++, READ_ERROR);
+			currently_testing += got;
+			if (got != try) {
+				try = 1;
+				if (recover_block == ~0U)
+					recover_block = currently_testing -
+						got + blocks_at_once;
+				continue;
+			} else if (currently_testing == recover_block) {
+				try = blocks_at_once;
+				recover_block = ~0U;
+			}
+			for (i=0; i < got; i++) {
+				if (memcmp(read_buffer + i * block_size,
+					   buffer + i * block_size,
+					   block_size))
+					bb_count += bb_output(currently_testing+i, CORRUPTION_ERROR);
+			}
+			if (v_flag > 1)
+				print_status();
+		}
+
+		num_blocks = 0;
+		alarm (0);
+		if (s_flag | v_flag)
+			fputs(_(done_string), stderr);
+		flush_bufs();
+	}
+	uncapture_terminate();
+	free(buffer);
+	return bb_count;
+}
+
+struct saved_blk_record {
+	blk_t	block;
+	int	num;
+};
+
+static unsigned int test_nd (int dev, blk_t last_block,
+			     int block_size, blk_t first_block,
+			     unsigned int blocks_at_once)
+{
+	unsigned char *blkbuf, *save_ptr, *test_ptr, *read_ptr;
+	unsigned char *test_base, *save_base, *read_base;
+	int try, i;
+	const unsigned int patterns[] = { ~0 };
+	const unsigned int *pattern;
+	int nr_pattern, pat_idx;
+	int got, used2, written;
+	blk_t save_currently_testing;
+	struct saved_blk_record *test_record;
+	/* This is static to prevent being clobbered by the longjmp */
+	static int num_saved;
+	jmp_buf terminate_env;
+	errcode_t errcode;
+	unsigned long buf_used;
+	static unsigned int bb_count;
+	unsigned int granularity = blocks_at_once;
+	blk_t recover_block = ~0U;
+
+	bb_count = 0;
+	errcode = ext2fs_badblocks_list_iterate_begin(bb_list,&bb_iter);
+	if (errcode) {
+		com_err(program_name, errcode, "%s",
+			_("while beginning bad block list iteration"));
+		exit (1);
+	}
+	do {
+		ext2fs_badblocks_list_iterate (bb_iter, &next_bad);
+	} while (next_bad && next_bad < first_block);
+
+	blkbuf = allocate_buffer(3 * blocks_at_once * block_size);
+	test_record = malloc(blocks_at_once * sizeof(struct saved_blk_record));
+	if (!blkbuf || !test_record) {
+		com_err(program_name, ENOMEM, "%s",
+			_("while allocating buffers"));
+		exit (1);
+	}
+
+	save_base = blkbuf;
+	test_base = blkbuf + (blocks_at_once * block_size);
+	read_base = blkbuf + (2 * blocks_at_once * block_size);
+
+	num_saved = 0;
+
+	flush_bufs();
+	if (v_flag) {
+	    fputs(_("Checking for bad blocks in non-destructive read-write mode\n"), stderr);
+	    fprintf (stderr, _("From block %lu to %lu\n"),
+		     (unsigned long) first_block,
+		     (unsigned long) last_block - 1);
+	}
+	if (s_flag || v_flag > 1) {
+		fputs(_("Checking for bad blocks (non-destructive read-write test)\n"), stderr);
+	}
+	if (setjmp(terminate_env)) {
+		/*
+		 * Abnormal termination by a signal is handled here.
+		 */
+		signal (SIGALRM, SIG_IGN);
+		fputs(_("\nInterrupt caught, cleaning up\n"), stderr);
+
+		save_ptr = save_base;
+		for (i=0; i < num_saved; i++) {
+			do_write(dev, save_ptr, test_record[i].num,
+				 block_size, test_record[i].block);
+			save_ptr += test_record[i].num * block_size;
+		}
+		fflush (out);
+		exit(1);
+	}
+
+	/* set up abend handler */
+	capture_terminate(terminate_env);
+
+	if (t_flag) {
+		pattern = t_patts;
+		nr_pattern = t_flag;
+	} else {
+		pattern = patterns;
+		nr_pattern = sizeof(patterns) / sizeof(patterns[0]);
+	}
+	for (pat_idx = 0; pat_idx < nr_pattern; pat_idx++) {
+		pattern_fill(test_base, pattern[pat_idx],
+			     blocks_at_once * block_size);
+
+		buf_used = 0;
+		bb_count = 0;
+		save_ptr = save_base;
+		test_ptr = test_base;
+		currently_testing = first_block;
+		num_blocks = last_block - 1;
+		if (s_flag && v_flag <= 1)
+			alarm_intr(SIGALRM);
+
+		while (currently_testing < last_block) {
+			if (max_bb && bb_count >= max_bb) {
+				if (s_flag || v_flag) {
+					fputs(_("Too many bad blocks, aborting test\n"), stderr);
+				}
+				break;
+			}
+			got = try = granularity - buf_used;
+			if (next_bad) {
+				if (currently_testing == next_bad) {
+					/* fprintf (out, "%lu\n", nextbad); */
+					ext2fs_badblocks_list_iterate (bb_iter, &next_bad);
+					currently_testing++;
+					goto check_for_more;
+				}
+				else if (currently_testing + try > next_bad)
+					try = next_bad - currently_testing;
+			}
+			if (currently_testing + try > last_block)
+				try = last_block - currently_testing;
+			got = do_read (dev, save_ptr, try, block_size,
+				       currently_testing);
+			if (got == 0) {
+				if (recover_block == ~0U)
+					recover_block = currently_testing +
+						blocks_at_once;
+				if (granularity != 1) {
+					granularity = 1;
+					continue;
+				}
+				/* First block must have been bad. */
+				bb_count += bb_output(currently_testing++, READ_ERROR);
+				goto check_for_more;
+			}
+
+			/*
+			 * Note the fact that we've saved this much data
+			 * *before* we overwrite it with test data
+			 */
+			test_record[num_saved].block = currently_testing;
+			test_record[num_saved].num = got;
+			num_saved++;
+
+			/* Write the test data */
+			written = do_write (dev, test_ptr, got, block_size,
+					    currently_testing);
+			if (written != got)
+				com_err (program_name, errno,
+					 _("during test data write, block %lu"),
+					 (unsigned long) currently_testing +
+					 written);
+
+			buf_used += got;
+			save_ptr += got * block_size;
+			test_ptr += got * block_size;
+			currently_testing += got;
+			if (got != try) {
+				try = 1;
+				if (recover_block == ~0U)
+					recover_block = currently_testing -
+						got + blocks_at_once;
+				continue;
+			}
+
+		check_for_more:
+			/*
+			 * If there's room for more blocks to be tested this
+			 * around, and we're not done yet testing the disk, go
+			 * back and get some more blocks.
+			 */
+			if ((buf_used != granularity) &&
+			    (currently_testing < last_block))
+				continue;
+
+			if (currently_testing >= recover_block) {
+				granularity = blocks_at_once;
+				recover_block = ~0;
+			}
+
+			flush_bufs();
+			save_currently_testing = currently_testing;
+
+			/*
+			 * for each contiguous block that we read into the
+			 * buffer (and wrote test data into afterwards), read
+			 * it back (looping if necessary, to get past newly
+			 * discovered unreadable blocks, of which there should
+			 * be none, but with a hard drive which is unreliable,
+			 * it has happened), and compare with the test data
+			 * that was written; output to the bad block list if
+			 * it doesn't match.
+			 */
+			used2 = 0;
+			save_ptr = save_base;
+			test_ptr = test_base;
+			read_ptr = read_base;
+			try = 0;
+
+			while (1) {
+				if (try == 0) {
+					if (used2 >= num_saved)
+						break;
+					currently_testing = test_record[used2].block;
+					try = test_record[used2].num;
+					used2++;
+				}
+
+				got = do_read (dev, read_ptr, try,
+					       block_size, currently_testing);
+
+				/* test the comparison between all the
+				   blocks successfully read  */
+				for (i = 0; i < got; ++i)
+					if (memcmp (test_ptr+i*block_size,
+						    read_ptr+i*block_size, block_size))
+						bb_count += bb_output(currently_testing + i, CORRUPTION_ERROR);
+				if (got < try) {
+					bb_count += bb_output(currently_testing + got, READ_ERROR);
+					got++;
+				}
+
+				/* write back original data */
+				do_write (dev, save_ptr, got,
+					  block_size, currently_testing);
+				save_ptr += got * block_size;
+
+				currently_testing += got;
+				test_ptr += got * block_size;
+				read_ptr += got * block_size;
+				try -= got;
+			}
+
+			/* empty the buffer so it can be reused */
+			num_saved = 0;
+			buf_used = 0;
+			save_ptr = save_base;
+			test_ptr = test_base;
+			currently_testing = save_currently_testing;
+		}
+		num_blocks = 0;
+		alarm(0);
+		if (s_flag || v_flag > 1)
+			fputs(_(done_string), stderr);
+
+		flush_bufs();
+	}
+	uncapture_terminate();
+	fflush(stderr);
+	free(blkbuf);
+	free(test_record);
+
+	ext2fs_badblocks_list_iterate_end(bb_iter);
+
+	return bb_count;
+}
+
+static void check_mount(char *device_name)
+{
+	errcode_t	retval;
+	int		mount_flags;
+
+	retval = ext2fs_check_if_mounted(device_name, &mount_flags);
+	if (retval) {
+		com_err("ext2fs_check_if_mount", retval,
+			_("while determining whether %s is mounted."),
+			device_name);
+		return;
+	}
+	if (mount_flags & EXT2_MF_MOUNTED) {
+		fprintf(stderr, _("%s is mounted; "), device_name);
+		if (force) {
+			fputs(_("badblocks forced anyway.  "
+				"Hope /etc/mtab is incorrect.\n"), stderr);
+			return;
+		}
+	abort_badblocks:
+		fputs(_("it's not safe to run badblocks!\n"), stderr);
+		exit(1);
+	}
+
+	if ((mount_flags & EXT2_MF_BUSY) && !exclusive_ok) {
+		fprintf(stderr, _("%s is apparently in use by the system; "),
+			device_name);
+		if (force)
+			fputs(_("badblocks forced anyway.\n"), stderr);
+		else
+			goto abort_badblocks;
+	}
+
+}
+
+/*
+ * This function will convert a string to an unsigned long, printing
+ * an error message if it fails, and returning success or failure in err.
+ */
+static unsigned int parse_uint(const char *str, const char *descr)
+{
+	char		*tmp;
+	unsigned long	ret;
+
+	errno = 0;
+	ret = strtoul(str, &tmp, 0);
+	if (*tmp || errno || (ret > UINT_MAX) ||
+	    (ret == ULONG_MAX && errno == ERANGE)) {
+		com_err (program_name, 0, _("invalid %s - %s"), descr, str);
+		exit (1);
+	}
+	return ret;
+}
+
+int main (int argc, char ** argv)
+{
+	int c;
+	char * device_name;
+	char * host_device_name = NULL;
+	char * input_file = NULL;
+	char * output_file = NULL;
+	FILE * in = NULL;
+	int block_size = 1024;
+	unsigned int blocks_at_once = 64;
+	blk64_t last_block, first_block;
+	int num_passes = 0;
+	int passes_clean = 0;
+	int dev;
+	errcode_t errcode;
+	unsigned int pattern;
+	unsigned int (*test_func)(int, blk_t,
+				  int, blk_t,
+				  unsigned int);
+	int open_flag;
+	long sysval;
+	blk64_t inblk;
+
+	setbuf(stdout, NULL);
+	setbuf(stderr, NULL);
+#ifdef ENABLE_NLS
+	setlocale(LC_MESSAGES, "");
+	setlocale(LC_CTYPE, "");
+	bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
+	textdomain(NLS_CAT_NAME);
+	set_com_err_gettext(gettext);
+#endif
+	srandom((unsigned int)time(NULL));  /* simple randomness is enough */
+	test_func = test_ro;
+
+	/* Determine the system page size if possible */
+#ifdef HAVE_SYSCONF
+#if (!defined(_SC_PAGESIZE) && defined(_SC_PAGE_SIZE))
+#define _SC_PAGESIZE _SC_PAGE_SIZE
+#endif
+#ifdef _SC_PAGESIZE
+	sysval = sysconf(_SC_PAGESIZE);
+	if (sysval > 0)
+		sys_page_size = sysval;
+#endif /* _SC_PAGESIZE */
+#endif /* HAVE_SYSCONF */
+
+	if (argc && *argv)
+		program_name = *argv;
+	while ((c = getopt (argc, argv, "b:d:e:fi:o:svwnc:p:h:t:BX")) != EOF) {
+		switch (c) {
+		case 'b':
+			block_size = parse_uint(optarg, "block size");
+			break;
+		case 'f':
+			force++;
+			break;
+		case 'i':
+			input_file = optarg;
+			break;
+		case 'o':
+			output_file = optarg;
+			break;
+		case 's':
+			s_flag = 1;
+			break;
+		case 'v':
+			v_flag++;
+			break;
+		case 'w':
+			if (w_flag)
+				exclusive_usage();
+			test_func = test_rw;
+			w_flag = 1;
+			break;
+		case 'n':
+			if (w_flag)
+				exclusive_usage();
+			test_func = test_nd;
+			w_flag = 2;
+			break;
+		case 'c':
+			blocks_at_once = parse_uint(optarg, "blocks at once");
+			break;
+		case 'e':
+			max_bb = parse_uint(optarg, "max bad block count");
+			break;
+		case 'd':
+			d_flag = parse_uint(optarg, "read delay factor");
+			break;
+		case 'p':
+			num_passes = parse_uint(optarg,
+						"number of clean passes");
+			break;
+		case 'h':
+			host_device_name = optarg;
+			break;
+		case 't':
+			if (t_flag + 1 > t_max) {
+				unsigned int *t_patts_new;
+
+				t_patts_new = realloc(t_patts, sizeof(int) *
+						      (t_max + T_INC));
+				if (!t_patts_new) {
+					com_err(program_name, ENOMEM,
+						_("can't allocate memory for "
+						  "test_pattern - %s"),
+						optarg);
+					exit(1);
+				}
+				t_patts = t_patts_new;
+				t_max += T_INC;
+			}
+			if (!strcmp(optarg, "r") || !strcmp(optarg,"random")) {
+				t_patts[t_flag++] = ~0;
+			} else {
+				pattern = parse_uint(optarg, "test pattern");
+				if (pattern == (unsigned int) ~0)
+					pattern = 0xffff;
+				t_patts[t_flag++] = pattern;
+			}
+			break;
+		case 'B':
+			use_buffered_io = 1;
+			break;
+		case 'X':
+			exclusive_ok++;
+			break;
+		default:
+			usage();
+		}
+	}
+	if (!w_flag) {
+		if (t_flag > 1) {
+			com_err(program_name, 0, "%s",
+				_("Maximum of one test_pattern may be "
+				  "specified in read-only mode"));
+			exit(1);
+		}
+		if (t_patts && (t_patts[0] == (unsigned int) ~0)) {
+			com_err(program_name, 0, "%s",
+				_("Random test_pattern is not allowed "
+				  "in read-only mode"));
+			exit(1);
+		}
+	}
+	if (optind > argc - 1)
+		usage();
+	device_name = argv[optind++];
+	if (optind > argc - 1) {
+		errcode = ext2fs_get_device_size2(device_name,
+						 block_size,
+						 &last_block);
+		if (errcode == EXT2_ET_UNIMPLEMENTED) {
+			com_err(program_name, 0, "%s",
+				_("Couldn't determine device size; you "
+				  "must specify\nthe size manually\n"));
+			exit(1);
+		}
+		if (errcode) {
+			com_err(program_name, errcode, "%s",
+				_("while trying to determine device size"));
+			exit(1);
+		}
+	} else {
+		errno = 0;
+		last_block = parse_uint(argv[optind], _("last block"));
+		last_block++;
+		optind++;
+	}
+	if (optind <= argc-1) {
+		errno = 0;
+		first_block = parse_uint(argv[optind], _("first block"));
+	} else first_block = 0;
+	if (first_block >= last_block) {
+	    com_err (program_name, 0, _("invalid starting block (%llu): must be less than %llu"),
+		     first_block, last_block);
+	    exit (1);
+	}
+	/* ext2 badblocks file can't handle large values */
+	if (last_block >> 32) {
+		com_err(program_name, EOVERFLOW,
+			_("invalid end block (%llu): must be 32-bit value"),
+			last_block);
+		exit(1);
+	}
+	if (w_flag)
+		check_mount(device_name);
+
+	gettimeofday(&time_start, 0);
+	open_flag = O_LARGEFILE | (w_flag ? O_RDWR : O_RDONLY);
+	dev = open (device_name, open_flag);
+	if (dev == -1) {
+		com_err (program_name, errno, _("while trying to open %s"),
+			 device_name);
+		exit (1);
+	}
+	if (host_device_name) {
+		host_dev = open (host_device_name, open_flag);
+		if (host_dev == -1) {
+			com_err (program_name, errno,
+				 _("while trying to open %s"),
+				 host_device_name);
+			exit (1);
+		}
+	} else
+		host_dev = dev;
+	if (input_file) {
+		if (strcmp (input_file, "-") == 0)
+			in = stdin;
+		else {
+			in = fopen (input_file, "r");
+			if (in == NULL)
+			{
+				com_err (program_name, errno,
+					 _("while trying to open %s"),
+					 input_file);
+				exit (1);
+			}
+		}
+	}
+	if (output_file && strcmp (output_file, "-") != 0)
+	{
+		out = fopen (output_file, "w");
+		if (out == NULL)
+		{
+			com_err (program_name, errno,
+				 _("while trying to open %s"),
+				 output_file);
+			exit (1);
+		}
+	}
+	else
+		out = stdout;
+
+	errcode = ext2fs_badblocks_list_create(&bb_list,0);
+	if (errcode) {
+		com_err(program_name, errcode, "%s",
+			_("while creating in-memory bad blocks list"));
+		exit (1);
+	}
+
+	if (in) {
+		for(;;) {
+			switch (fscanf(in, "%llu\n", &inblk)) {
+				case 0:
+					com_err(program_name, 0, "%s",
+						_("input file - bad format"));
+					exit (1);
+				case EOF:
+					break;
+				default:
+					if (inblk >> 32) {
+						com_err(program_name,
+							EOVERFLOW, "%s",
+						_("while adding to in-memory "
+						  "bad block list"));
+						exit(1);
+					}
+					next_bad = inblk;
+					errcode = ext2fs_badblocks_list_add(bb_list,next_bad);
+					if (errcode) {
+						com_err(program_name, errcode,
+							"%s",
+						_("while adding to in-memory "
+						  "bad block list"));
+						exit (1);
+					}
+					continue;
+			}
+			break;
+		}
+
+		if (in != stdin)
+			fclose (in);
+	}
+
+	do {
+		unsigned int bb_count;
+
+		bb_count = test_func(dev, last_block, block_size,
+				     first_block, blocks_at_once);
+		if (bb_count)
+			passes_clean = 0;
+		else
+			++passes_clean;
+
+		if (v_flag)
+			fprintf(stderr,
+				_("Pass completed, %u bad blocks found. (%d/%d/%d errors)\n"),
+				bb_count, num_read_errors, num_write_errors, num_corruption_errors);
+
+	} while (passes_clean < num_passes);
+
+	close (dev);
+	if (out != stdout)
+		fclose (out);
+	free(t_patts);
+	return 0;
+}
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/base_device.c b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/base_device.c
new file mode 100644
index 0000000..b2ce138
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/base_device.c
@@ -0,0 +1,170 @@
+/*
+ * base_device.c
+ *
+ * Return the "base device" given a particular device; this is used to
+ * assure that we only fsck one partition on a particular drive at any
+ * one time.  Otherwise, the disk heads will be seeking all over the
+ * place.  If the base device can not be determined, return NULL.
+ *
+ * The base_device() function returns an allocated string which must
+ * be freed.
+ *
+ * Written by Theodore Ts'o, <tytso@mit.edu>
+ *
+ * Copyright (C) 2000 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+#include "config.h"
+#include <stdio.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <ctype.h>
+#include <string.h>
+
+#include "fsck.h"
+
+/*
+ * Required for the uber-silly devfs /dev/ide/host1/bus2/target3/lun3
+ * pathames.
+ */
+static const char *devfs_hier[] = {
+	"host", "bus", "target", "lun", 0
+};
+
+char *base_device(const char *device)
+{
+	char *str, *cp;
+	const char **hier, *disk;
+	int len;
+
+	str = malloc(strlen(device)+1);
+	if (!str)
+		return NULL;
+	strcpy(str, device);
+	cp = str;
+
+	/* Skip over /dev/; if it's not present, give up. */
+	if (strncmp(cp, "/dev/", 5) != 0)
+		goto errout;
+	cp += 5;
+
+	/* Skip over /dev/dsk/... */
+	if (strncmp(cp, "dsk/", 4) == 0)
+		cp += 4;
+
+	/*
+	 * For md devices, we treat them all as if they were all
+	 * on one disk, since we don't know how to parallelize them.
+	 */
+	if (cp[0] == 'm' && cp[1] == 'd') {
+		*(cp+2) = 0;
+		return str;
+	}
+
+	/* Handle DAC 960 devices */
+	if (strncmp(cp, "rd/", 3) == 0) {
+		cp += 3;
+		if (cp[0] != 'c' || cp[2] != 'd' ||
+		    !isdigit(cp[1]) || !isdigit(cp[3]))
+			goto errout;
+		*(cp+4) = 0;
+		return str;
+	}
+
+	/* Now let's handle /dev/hd* and /dev/sd* devices.... */
+	if ((cp[0] == 'h' || cp[0] == 's') && (cp[1] == 'd')) {
+		cp += 2;
+		/* If there's a single number after /dev/hd, skip it */
+		if (isdigit(*cp))
+			cp++;
+		/* What follows must be an alpha char, or give up */
+		if (!isalpha(*cp))
+			goto errout;
+		*(cp + 1) = 0;
+		return str;
+	}
+
+	/* Now let's handle devfs (ugh) names */
+	len = 0;
+	if (strncmp(cp, "ide/", 4) == 0)
+		len = 4;
+	if (strncmp(cp, "scsi/", 5) == 0)
+		len = 5;
+	if (len) {
+		cp += len;
+		/*
+		 * Now we proceed down the expected devfs hierarchy.
+		 * i.e., .../host1/bus2/target3/lun4/...
+		 * If we don't find the expected token, followed by
+		 * some number of digits at each level, abort.
+		 */
+		for (hier = devfs_hier; *hier; hier++) {
+			len = strlen(*hier);
+			if (strncmp(cp, *hier, len) != 0)
+				goto errout;
+			cp += len;
+			while (*cp != '/' && *cp != 0) {
+				if (!isdigit(*cp))
+					goto errout;
+				cp++;
+			}
+			cp++;
+		}
+		*(cp - 1) = 0;
+		return str;
+	}
+
+	/* Now handle devfs /dev/disc or /dev/disk names */
+	disk = 0;
+	if (strncmp(cp, "discs/", 6) == 0)
+		disk = "disc";
+	else if (strncmp(cp, "disks/", 6) == 0)
+		disk = "disk";
+	if (disk) {
+		cp += 6;
+		if (strncmp(cp, disk, 4) != 0)
+			goto errout;
+		cp += 4;
+		while (*cp != '/' && *cp != 0) {
+			if (!isdigit(*cp))
+				goto errout;
+			cp++;
+		}
+		*cp = 0;
+		return str;
+	}
+
+errout:
+	free(str);
+	return NULL;
+}
+
+#ifdef DEBUG
+int main(int argc, char** argv)
+{
+	const char *base;
+	char  buf[256], *cp;
+
+	while (1) {
+		if (fgets(buf, sizeof(buf), stdin) == NULL)
+			break;
+		cp = strchr(buf, '\n');
+		if (cp)
+			*cp = 0;
+		cp = strchr(buf, '\t');
+		if (cp)
+			*cp = 0;
+		base = base_device(buf);
+		printf("%s\t%s\n", buf, base ? base : "NONE");
+	}
+	exit(0);
+}
+#endif
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/base_device.tst b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/base_device.tst
new file mode 100644
index 0000000..609a58d
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/base_device.tst
@@ -0,0 +1,16 @@
+/dev/hda7	/dev/hda
+/dev/sda1	/dev/sda
+/dev/hda	/dev/hda
+/dev/sda	/dev/sda
+/dev/dsk/hda6	/dev/dsk/hda
+/dev/dsk/sda5	/dev/dsk/sda
+/dev/md4	/dev/md
+/dev/md/4	/dev/md
+/dev/ide/host0/bus1/target2/lun3	/dev/ide/host0/bus1/target2/lun3
+/dev/ide/host0/bus1/target2/lun3/part10	/dev/ide/host0/bus1/target2/lun3
+/dev/ide/host0/bus1/target2/lun3/	/dev/ide/host0/bus1/target2/lun3
+/dev/disks/disk2/part2	/dev/disks/disk2
+/dev/disks/disk2/	/dev/disks/disk2
+/dev/disks/disk2	/dev/disks/disk2
+/dev/discs/disc1/part10	/dev/discs/disc1
+/dev/discs/disc1/	/dev/discs/disc1
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/blkid.8.in b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/blkid.8.in
new file mode 100644
index 0000000..9c42686
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/blkid.8.in
@@ -0,0 +1,164 @@
+.\" Copyright 2000 Andreas Dilger (adilger@turbolinux.com)
+.\"
+.\" This man page was created for blkid from e2fsprogs-1.25.
+.\"
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.\" Based on uuidgen, Mon Sep 17 10:42:12 2000, Andreas Dilger
+.TH BLKID 8 "@E2FSPROGS_MONTH@ @E2FSPROGS_YEAR@" "E2fsprogs version @E2FSPROGS_VERSION@"
+.SH NAME
+blkid \- command\-line utility to locate/print block device attributes
+.SH SYNOPSIS
+.B blkid
+[
+.B \-ghlLv
+]
+[
+[
+.B \-c
+.I cachefile
+]
+.B \-w
+.I writecachefile
+]
+[
+.B \-o
+.I format
+]
+[
+.B \-s
+.I tag
+]
+[
+.B \-t
+.IR NAME = value
+]
+[
+.I device ...
+]
+.SH DESCRIPTION
+The
+.B blkid
+program is the command-line interface to working with
+.BR libblkid (3)
+library.  It can determine the type of content (e.g. filesystem, swap)
+a block device holds, and also attributes (tokens, NAME=value pairs)
+from the content metadata (e.g. LABEL or UUID fields).
+.PP
+.B blkid
+has two main forms of operation: either searching for a device with a
+specific NAME=value pair, or displaying NAME=value pairs for one or
+more devices.
+.SH OPTIONS
+.TP
+.BI \-c " cachefile"
+Read from
+.I cachefile
+instead of reading from the default cache file
+.IR /etc/blkid.tab .
+If you want to start with a clean cache (i.e. don't report devices previously
+scanned but not necessarily available at this time), specify
+.IR /dev/null .
+.TP
+.B \-g
+Perform a garbage collection pass on the blkid cache to remove
+devices which no longer exist.
+.TP
+.B \-h
+Display a usage message and exit.
+.TP
+.B \-l
+Look up one device that matches the search parameter specified using
+the
+.B \-t
+option.  If there are multiple devices that match the specified search
+parameter, then the device with the highest priority is returned, and/or
+the first device found at a given priority.  Device types in order of
+decreasing priority are Device Mapper, EVMS, LVM, MD, and finally regular
+block devices.  If this option is not specified,
+.B blkid
+will print all of the devices that match the search parameter.
+.TP
+.BI \-o " format"
+Display
+.BR blkid 's
+output using the specified format.  The
+.I format
+parameter may be
+.I full
+(the default),
+.I value
+(only print the value of the tags),
+.I list
+(print the devices in a user-friendly format),
+or
+.I device
+(only print the device name).
+.TP
+.B \-L
+Print the devices in a user-friendly list format.  This is the
+equivalent of using the option \fB-o list\fR.
+.TP
+.BI \-s " tag"
+For each (specified) device, show only the tags that match
+.IR tag .
+It is possible to specify multiple
+.B \-s
+options.  If no tag is specified, then all tokens are shown for all
+(specified) devices.
+In order to just refresh the cache without showing any tokens, use
+.B "-s none"
+with no other options.
+.TP
+.BI \-t " NAME" = "value"
+Search for block devices with tokens named
+.I NAME
+that have the value
+.IR value ,
+and display any devices which are found.
+Common values for
+.I NAME
+include
+.BR TYPE ,
+.BR LABEL ,
+and
+.BR UUID .
+If there are no devices specified on the command line, all block devices
+will be searched; otherwise only the specified devices are searched.
+.TP
+.B \-v
+Display version number and exit.
+.TP
+.BI \-w " writecachefile"
+Write the device cache to
+.I writecachefile
+instead of writing it to the default cache file
+.IR /etc/blkid.tab .
+If you don't want to save the cache to the default file, specify
+.IR /dev/null.
+If not specified it will be the same file as that given by the
+.B \-c
+option.
+.TP
+.I device
+Display tokens from only the specified device.  It is possible to
+give multiple
+.I device
+options on the command line.  If none is given, all devices which
+appear in
+.I /proc/partitions
+are shown, if they are recognized.
+.SH "RETURN CODE"
+If the specified token was found, or if any tags were shown from (specified)
+devices, 0 is returned.  If the specified token was not found, or no
+(specified) devices could be identified, an exit code of 2 is returned.
+For usage or other errors, an exit code of 4 is returned.
+.SH AUTHOR
+.B blkid
+was written by Andreas Dilger for libblkid.
+.SH AVAILABILITY
+.B blkid
+is part the e2fsprogs package since version 1.26 and is available from
+http://e2fsprogs.sourceforge.net.
+.SH "SEE ALSO"
+.BR libblkid (3)
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/blkid.c b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/blkid.c
new file mode 100644
index 0000000..a4a8db0
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/blkid.c
@@ -0,0 +1,427 @@
+/*
+ * blkid.c - User command-line interface for libblkid
+ *
+ * Copyright (C) 2001 Andreas Dilger
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ * %End-Header%
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#endif
+#ifdef HAVE_TERMIO_H
+#include <termio.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#else
+extern int getopt(int argc, char * const argv[], const char *optstring);
+extern char *optarg;
+extern int optind;
+#endif
+
+#define OUTPUT_VALUE_ONLY	0x0001
+#define OUTPUT_DEVICE_ONLY	0x0002
+#define OUTPUT_PRETTY_LIST	0x0004
+
+#include "ext2fs/ext2fs.h"
+#include "blkid/blkid.h"
+
+const char *progname = "blkid";
+
+static void print_version(FILE *out)
+{
+	fprintf(out, "%s %s (%s)\n", progname, BLKID_VERSION, BLKID_DATE);
+}
+
+static void usage(int error)
+{
+	FILE *out = error ? stderr : stdout;
+
+	print_version(out);
+	fprintf(out,
+		"usage:\t%s [-c <file>] [-ghlLv] [-o format] "
+		"[-s <tag>] [-t <token>]\n    [-w <file>] [dev ...]\n"
+		"\t-c\tcache file (default: /etc/blkid.tab, /dev/null = none)\n"
+		"\t-h\tprint this usage message and exit\n"
+		"\t-g\tgarbage collect the blkid cache\n"
+		"\t-s\tshow specified tag(s) (default show all tags)\n"
+		"\t-t\tfind device with a specific token (NAME=value pair)\n"
+		"\t-l\tlookup the the first device with arguments specified by -t\n"
+		"\t-v\tprint version and exit\n"
+		"\t-w\twrite cache to different file (/dev/null = no write)\n"
+		"\tdev\tspecify device(s) to probe (default: all devices)\n",
+		progname);
+	exit(error);
+}
+
+/*
+ * This function does "safe" printing.  It will convert non-printable
+ * ASCII characters using '^' and M- notation.
+ */
+static void safe_print(const char *cp, int len)
+{
+	unsigned char	ch;
+
+	if (len < 0)
+		len = strlen(cp);
+
+	while (len--) {
+		ch = *cp++;
+		if (ch > 128) {
+			fputs("M-", stdout);
+			ch -= 128;
+		}
+		if ((ch < 32) || (ch == 0x7f)) {
+			fputc('^', stdout);
+			ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
+		}
+		fputc(ch, stdout);
+	}
+}
+
+static int get_terminal_width(void)
+{
+#ifdef TIOCGSIZE
+	struct ttysize	t_win;
+#endif
+#ifdef TIOCGWINSZ
+	struct winsize	w_win;
+#endif
+        const char	*cp;
+
+#ifdef TIOCGSIZE
+	if (ioctl (0, TIOCGSIZE, &t_win) == 0)
+		return (t_win.ts_cols);
+#endif
+#ifdef TIOCGWINSZ
+	if (ioctl (0, TIOCGWINSZ, &w_win) == 0)
+		return (w_win.ws_col);
+#endif
+        cp = getenv("COLUMNS");
+	if (cp)
+		return strtol(cp, NULL, 10);
+	return 80;
+}
+
+static int pretty_print_word(const char *str, int max_len,
+			     int left_len, int overflow_nl)
+{
+	int len = strlen(str) + left_len;
+	int ret = 0;
+
+	fputs(str, stdout);
+	if (overflow_nl && len > max_len) {
+		fputc('\n', stdout);
+		len = 0;
+	} else if (len > max_len)
+		ret = len - max_len;
+	do
+		fputc(' ', stdout);
+	while (len++ < max_len);
+	return ret;
+}
+
+static void pretty_print_line(const char *device, const char *fs_type,
+			      const char *label, const char *mtpt,
+			      const char *uuid)
+{
+	static int device_len = 10, fs_type_len = 7;
+	static int label_len = 8, mtpt_len = 14;
+	static int term_width = -1;
+	int len, w;
+
+	if (term_width < 0)
+		term_width = get_terminal_width();
+
+	if (term_width > 80) {
+		term_width -= 80;
+		w = term_width / 10;
+		if (w > 8)
+			w = 8;
+		term_width -= 2*w;
+		label_len += w;
+		fs_type_len += w;
+		w = term_width/2;
+		device_len += w;
+		mtpt_len +=w;
+	}
+
+	len = pretty_print_word(device, device_len, 0, 1);
+	len = pretty_print_word(fs_type, fs_type_len, len, 0);
+	len = pretty_print_word(label, label_len, len, 0);
+	len = pretty_print_word(mtpt, mtpt_len, len, 0);
+	fputs(uuid, stdout);
+	fputc('\n', stdout);
+}
+
+static void pretty_print_dev(blkid_dev dev)
+{
+	blkid_tag_iterate	iter;
+	const char		*type, *value, *devname;
+	const char		*uuid = "", *fs_type = "", *label = "";
+	int			len, mount_flags;
+	char			mtpt[80];
+	errcode_t		retval;
+
+	if (dev == NULL) {
+		pretty_print_line("device", "fs_type", "label",
+				  "mount point", "UUID");
+		for (len=get_terminal_width()-1; len > 0; len--)
+			fputc('-', stdout);
+		fputc('\n', stdout);
+		return;
+	}
+
+	devname = blkid_dev_devname(dev);
+	if (access(devname, F_OK))
+		return;
+
+	/* Get the uuid, label, type */
+	iter = blkid_tag_iterate_begin(dev);
+	while (blkid_tag_next(iter, &type, &value) == 0) {
+		if (!strcmp(type, "UUID"))
+			uuid = value;
+		if (!strcmp(type, "TYPE"))
+			fs_type = value;
+		if (!strcmp(type, "LABEL"))
+			label = value;
+	}
+	blkid_tag_iterate_end(iter);
+
+	/* Get the mount point */
+	mtpt[0] = 0;
+	retval = ext2fs_check_mount_point(devname, &mount_flags,
+					  mtpt, sizeof(mtpt));
+	if (retval == 0) {
+		if (mount_flags & EXT2_MF_MOUNTED) {
+			if (!mtpt[0])
+				strcpy(mtpt, "(mounted, mtpt unknown)");
+		} else if (mount_flags & EXT2_MF_BUSY)
+			strcpy(mtpt, "(in use)");
+		else
+			strcpy(mtpt, "(not mounted)");
+	}
+
+	pretty_print_line(devname, fs_type, label, mtpt, uuid);
+}
+
+static void print_tags(blkid_dev dev, char *show[], int numtag, int output)
+{
+	blkid_tag_iterate	iter;
+	const char		*type, *value;
+	int 			i, first = 1;
+
+	if (!dev)
+		return;
+
+	if (output & OUTPUT_PRETTY_LIST) {
+		pretty_print_dev(dev);
+		return;
+	}
+
+	if (output & OUTPUT_DEVICE_ONLY) {
+		printf("%s\n", blkid_dev_devname(dev));
+		return;
+	}
+
+	iter = blkid_tag_iterate_begin(dev);
+	while (blkid_tag_next(iter, &type, &value) == 0) {
+		if (numtag && show) {
+			for (i=0; i < numtag; i++)
+				if (!strcmp(type, show[i]))
+					break;
+			if (i >= numtag)
+				continue;
+		}
+		if (output & OUTPUT_VALUE_ONLY) {
+			fputs(value, stdout);
+			fputc('\n', stdout);
+		} else {
+			if (first) {
+				printf("%s: ", blkid_dev_devname(dev));
+				first = 0;
+			}
+			fputs(type, stdout);
+			fputs("=\"", stdout);
+			safe_print(value, -1);
+			fputs("\" ", stdout);
+		}
+	}
+	blkid_tag_iterate_end(iter);
+
+	if (!first && !(output & OUTPUT_VALUE_ONLY))
+		printf("\n");
+}
+
+int main(int argc, char **argv)
+{
+	blkid_cache cache = NULL;
+	char *devices[128] = { NULL, };
+	char *show[128] = { NULL, };
+	char *search_type = NULL, *search_value = NULL;
+	char *read = NULL;
+	char *write = NULL;
+	unsigned int numdev = 0, numtag = 0;
+	int version = 0;
+	int err = 4;
+	unsigned int i;
+	int output_format = 0;
+	int lookup = 0, gc = 0;
+	int c;
+
+	while ((c = getopt (argc, argv, "c:f:ghlLo:s:t:w:v")) != EOF)
+		switch (c) {
+		case 'c':
+			if (optarg && !*optarg)
+				read = NULL;
+			else
+				read = optarg;
+			if (!write)
+				write = read;
+			break;
+		case 'l':
+			lookup++;
+			break;
+		case 'L':
+			output_format = OUTPUT_PRETTY_LIST;
+			break;
+		case 'g':
+			gc = 1;
+			break;
+		case 'o':
+			if (!strcmp(optarg, "value"))
+				output_format = OUTPUT_VALUE_ONLY;
+			else if (!strcmp(optarg, "device"))
+				output_format = OUTPUT_DEVICE_ONLY;
+			else if (!strcmp(optarg, "list"))
+				output_format = OUTPUT_PRETTY_LIST;
+			else if (!strcmp(optarg, "full"))
+				output_format = 0;
+			else {
+				fprintf(stderr, "Invalid output format %s. "
+					"Choose from value,\n\t"
+					"device, list, or full\n", optarg);
+				exit(1);
+			}
+			break;
+		case 's':
+			if (numtag >= sizeof(show) / sizeof(*show)) {
+				fprintf(stderr, "Too many tags specified\n");
+				usage(err);
+			}
+			show[numtag++] = optarg;
+			break;
+		case 't':
+			if (search_type) {
+				fprintf(stderr, "Can only search for "
+						"one NAME=value pair\n");
+				usage(err);
+			}
+			if (blkid_parse_tag_string(optarg,
+						   &search_type,
+						   &search_value)) {
+				fprintf(stderr, "-t needs NAME=value pair\n");
+				usage(err);
+			}
+			break;
+		case 'v':
+			version = 1;
+			break;
+		case 'w':
+			if (optarg && !*optarg)
+				write = NULL;
+			else
+				write = optarg;
+			break;
+		case 'h':
+			err = 0;
+		default:
+			usage(err);
+		}
+
+	while (optind < argc)
+		devices[numdev++] = argv[optind++];
+
+	if (version) {
+		print_version(stdout);
+		goto exit;
+	}
+
+	if (blkid_get_cache(&cache, read) < 0)
+		goto exit;
+
+	err = 2;
+	if (gc) {
+		blkid_gc_cache(cache);
+		goto exit;
+	}
+	if (output_format & OUTPUT_PRETTY_LIST)
+		pretty_print_dev(NULL);
+
+	if (lookup) {
+		blkid_dev dev;
+
+		if (!search_type) {
+			fprintf(stderr, "The lookup option requires a "
+				"search type specified using -t\n");
+			exit(1);
+		}
+		/* Load any additional devices not in the cache */
+		for (i = 0; i < numdev; i++)
+			blkid_get_dev(cache, devices[i], BLKID_DEV_NORMAL);
+
+		if ((dev = blkid_find_dev_with_tag(cache, search_type,
+						   search_value))) {
+			print_tags(dev, show, numtag, output_format);
+			err = 0;
+		}
+	/* If we didn't specify a single device, show all available devices */
+	} else if (!numdev) {
+		blkid_dev_iterate	iter;
+		blkid_dev		dev;
+
+		blkid_probe_all(cache);
+
+		iter = blkid_dev_iterate_begin(cache);
+		blkid_dev_set_search(iter, search_type, search_value);
+		while (blkid_dev_next(iter, &dev) == 0) {
+			dev = blkid_verify(cache, dev);
+			if (!dev)
+				continue;
+			print_tags(dev, show, numtag, output_format);
+			err = 0;
+		}
+		blkid_dev_iterate_end(iter);
+	/* Add all specified devices to cache (optionally display tags) */
+	} else for (i = 0; i < numdev; i++) {
+		blkid_dev dev = blkid_get_dev(cache, devices[i],
+						  BLKID_DEV_NORMAL);
+
+		if (dev) {
+			if (search_type &&
+			    !blkid_dev_has_tag(dev, search_type,
+					       search_value))
+				continue;
+			print_tags(dev, show, numtag, output_format);
+			err = 0;
+		}
+	}
+
+exit:
+	free(search_type);
+	free(search_value);
+	blkid_put_cache(cache);
+	return err;
+}
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/chattr.1.in b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/chattr.1.in
new file mode 100644
index 0000000..932ef4b
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/chattr.1.in
@@ -0,0 +1,182 @@
+.\" -*- nroff -*-
+.TH CHATTR 1 "@E2FSPROGS_MONTH@ @E2FSPROGS_YEAR@" "E2fsprogs version @E2FSPROGS_VERSION@"
+.SH NAME
+chattr \- change file attributes on a Linux file system
+.SH SYNOPSIS
+.B chattr
+[
+.B \-RVf
+]
+[
+.B \-v
+.I version
+]
+[
+.I mode
+]
+.I files...
+.SH DESCRIPTION
+.B chattr
+changes the file attributes on a Linux file system.
+.PP
+The format of a symbolic mode is +-=[acdeijstuACDST].
+.PP
+The operator `+' causes the selected attributes to be added to the
+existing attributes of the files; `-' causes them to be removed; and
+`=' causes them to be the only attributes that the files have.
+.PP
+The letters `acdeijstuACDST' select the new attributes for the files:
+append only (a), compressed (c), no dump (d), extent format (e), immutable (i),
+data journalling (j), secure deletion (s), no tail-merging (t),
+undeletable (u), no atime updates (A), no copy on write (C),
+synchronous directory updates (D), synchronous updates (S),
+and top of directory hierarchy (T).
+.PP
+The following attributes are read-only, and may be listed by
+.BR lsattr (1)
+but not modified by chattr: huge file (h), compression error (E),
+indexed directory (I), compression raw access (X), and compressed dirty
+file (Z).
+.SH OPTIONS
+.TP
+.B \-R
+Recursively change attributes of directories and their contents.
+.TP
+.B \-V
+Be verbose with chattr's output and print the program version.
+.TP
+.B \-f
+Suppress most error messages.
+.TP
+.BI \-v " version"
+Set the file's version/generation number.
+.SH ATTRIBUTES
+When a file with the 'A' attribute set is accessed, its atime record is
+not modified.  This avoids a certain amount of disk I/O for laptop
+systems.
+.PP
+A file with the `a' attribute set can only be open in append mode for writing.
+Only the superuser or a process possessing the CAP_LINUX_IMMUTABLE
+capability can set or clear this attribute.
+.PP
+A file with the `c' attribute set is automatically compressed on the disk
+by the kernel.  A read from this file returns uncompressed data.  A write to
+this file compresses data before storing them on the disk.  Note: please
+make sure to read the bugs and limitations section at the end of this
+document.
+.PP
+A file with the 'C' attribute set will not be subject to copy-on-write
+updates.  This flag is only supported on file systems which perform
+copy-on-write.  (Note: For btrfs, the 'C' flag should be
+set on new or empty files.  If it is set on a file which already has
+data blocks, it is undefined when the blocks assigned to the file will
+be fully stable.  If the 'C' flag is set on a directory, it will have no
+effect on the directory, but new files created in that directory will
+the No_COW attribute.)
+.PP
+When a directory with the `D' attribute set is modified,
+the changes are written synchronously on the disk; this is equivalent to
+the `dirsync' mount option applied to a subset of the files.
+.PP
+A file with the `d' attribute set is not candidate for backup when the
+.BR dump (8)
+program is run.
+.PP
+The 'E' attribute is used by the experimental compression patches to
+indicate that a compressed file has a compression error.  It may not be
+set or reset using
+.BR chattr (1),
+although it can be displayed by
+.BR lsattr (1).
+.PP
+The 'e' attribute indicates that the file is using extents for mapping
+the blocks on disk.  It may not be removed using
+.BR chattr (1).
+.PP
+The 'I' attribute is used by the htree code to indicate that a directory
+is being indexed using hashed trees.  It may not be set or reset using
+.BR chattr (1),
+although it can be displayed by
+.BR lsattr (1).
+.PP
+The 'h' attribute indicates the file is storing its blocks in units of the
+filesystem blocksize instead of in units of sectors, and means that the file
+is (or at one time was) larger than 2TB.  It may not be set or reset using
+.BR chattr (1),
+although it can be displayed by
+.BR lsattr (1).
+.PP
+A file with the `i' attribute cannot be modified: it cannot be deleted or
+renamed, no link can be created to this file and no data can be written
+to the file.  Only the superuser or a process possessing the
+CAP_LINUX_IMMUTABLE capability can set or clear this attribute.
+.PP
+A file with the `j' attribute has all of its data written to the ext3
+journal before being written to the file itself, if the filesystem is
+mounted with the "data=ordered" or "data=writeback" options.  When the
+filesystem is mounted with the "data=journal" option all file data
+is already journalled and this attribute has no effect.  Only
+the superuser or a process possessing the CAP_SYS_RESOURCE
+capability can set or clear this attribute.
+.PP
+When a file with the `s' attribute set is deleted, its blocks are zeroed
+and written back to the disk.  Note: please make sure to read the bugs
+and limitations section at the end of this document.
+.PP
+When a file with the `S' attribute set is modified,
+the changes are written synchronously on the disk; this is equivalent to
+the `sync' mount option applied to a subset of the files.
+.PP
+A directory with the 'T' attribute will be deemed to be the top of
+directory hierarchies for the purposes of the Orlov block allocator.
+This is a hint to the block allocator used by ext3 and ext4 that the
+subdirectories under this directory are not related, and thus should be
+spread apart for allocation purposes.   For example it is a very good
+idea to set the 'T' attribute on the /home directory, so that /home/john
+and /home/mary are placed into separate block groups.  For directories
+where this attribute is not set, the Orlov block allocator will try to
+group subdirectories closer together where possible.
+.PP
+A file with the 't' attribute will not have a partial block fragment at
+the end of the file merged with other files (for those filesystems which
+support tail-merging).  This is necessary for applications such as LILO
+which read the filesystem directly, and which don't understand tail-merged
+files.  Note: As of this writing, the ext2 or ext3 filesystems do not
+(yet, except in very experimental patches) support tail-merging.
+.PP
+When a file with the `u' attribute set is deleted, its contents are
+saved.  This allows the user to ask for its undeletion.  Note: please
+make sure to read the bugs and limitations section at the end of this
+document.
+.PP
+The 'X' attribute is used by the experimental compression patches to
+indicate that a raw contents of a compressed file can be accessed
+directly.  It currently may not be set or reset using
+.BR chattr (1),
+although it can be displayed by
+.BR lsattr (1).
+.PP
+The 'Z' attribute is used by the experimental compression patches to
+indicate a compressed file is dirty.  It may not be set or reset using
+.BR chattr (1),
+although it can be displayed by
+.BR lsattr (1).
+.PP
+.SH AUTHOR
+.B chattr
+was written by Remy Card <Remy.Card@linux.org>.  It is currently being
+maintained by Theodore Ts'o <tytso@alum.mit.edu>.
+.SH BUGS AND LIMITATIONS
+The `c', 's',  and `u' attributes are not honored
+by the ext2, ext3, and ext4 filesystems as implemented in the current
+mainline Linux kernels.
+.PP
+The `j' option is only useful if the filesystem is mounted as ext3.
+.PP
+The `D' option is only useful on Linux kernel 2.5.19 and later.
+.SH AVAILABILITY
+.B chattr
+is part of the e2fsprogs package and is available from
+http://e2fsprogs.sourceforge.net.
+.SH SEE ALSO
+.BR lsattr (1)
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/chattr.c b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/chattr.c
new file mode 100644
index 0000000..39a6016
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/chattr.c
@@ -0,0 +1,327 @@
+/*
+ * chattr.c		- Change file attributes on an ext2 file system
+ *
+ * Copyright (C) 1993, 1994  Remy Card <card@masi.ibp.fr>
+ *                           Laboratoire MASI, Institut Blaise Pascal
+ *                           Universite Pierre et Marie Curie (Paris VI)
+ *
+ * This file can be redistributed under the terms of the GNU General
+ * Public License
+ */
+
+/*
+ * History:
+ * 93/10/30	- Creation
+ * 93/11/13	- Replace stat() calls by lstat() to avoid loops
+ * 94/02/27	- Integrated in Ted's distribution
+ * 98/12/29	- Ignore symlinks when working recursively (G M Sipe)
+ * 98/12/29	- Display version info only when -V specified (G M Sipe)
+ */
+
+#define _LARGEFILE64_SOURCE
+
+#include "config.h"
+#include <sys/types.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <sys/param.h>
+#include <sys/stat.h>
+#include "ext2fs/ext2_fs.h"
+
+#ifdef __GNUC__
+#define EXT2FS_ATTR(x) __attribute__(x)
+#else
+#define EXT2FS_ATTR(x)
+#endif
+
+#ifndef S_ISLNK			/* So we can compile even with gcc-warn */
+# ifdef __S_IFLNK
+#  define S_ISLNK(mode)	 __S_ISTYPE((mode), __S_IFLNK)
+# else
+#  define S_ISLNK(mode)  0
+# endif
+#endif
+
+#include "et/com_err.h"
+#include "e2p/e2p.h"
+
+#include "../version.h"
+#include "nls-enable.h"
+
+static const char * program_name = "chattr";
+
+static int add;
+static int rem;
+static int set;
+static int set_version;
+
+static unsigned long version;
+
+static int recursive;
+static int verbose;
+static int silent;
+
+static unsigned long af;
+static unsigned long rf;
+static unsigned long sf;
+
+#ifdef _LFS64_LARGEFILE
+#define LSTAT		lstat64
+#define STRUCT_STAT	struct stat64
+#else
+#define LSTAT		lstat
+#define STRUCT_STAT	struct stat
+#endif
+
+static void usage(void)
+{
+	fprintf(stderr,
+		_("Usage: %s [-RVf] [-+=AaCcDdeijsSu] [-v version] files...\n"),
+		program_name);
+	exit(1);
+}
+
+struct flags_char {
+	unsigned long	flag;
+	char 		optchar;
+};
+
+static const struct flags_char flags_array[] = {
+	{ EXT2_NOATIME_FL, 'A' },
+	{ EXT2_SYNC_FL, 'S' },
+	{ EXT2_DIRSYNC_FL, 'D' },
+	{ EXT2_APPEND_FL, 'a' },
+	{ EXT2_COMPR_FL, 'c' },
+	{ EXT2_NODUMP_FL, 'd' },
+	{ EXT4_EXTENTS_FL, 'e'},
+	{ EXT2_IMMUTABLE_FL, 'i' },
+	{ EXT3_JOURNAL_DATA_FL, 'j' },
+	{ EXT2_SECRM_FL, 's' },
+	{ EXT2_UNRM_FL, 'u' },
+	{ EXT2_NOTAIL_FL, 't' },
+	{ EXT2_TOPDIR_FL, 'T' },
+	{ FS_NOCOW_FL, 'C' },
+	{ 0, 0 }
+};
+
+static unsigned long get_flag(char c)
+{
+	const struct flags_char *fp;
+
+	for (fp = flags_array; fp->flag != 0; fp++) {
+		if (fp->optchar == c)
+			return fp->flag;
+	}
+	return 0;
+}
+
+
+static int decode_arg (int * i, int argc, char ** argv)
+{
+	char * p;
+	char * tmp;
+	unsigned long fl;
+
+	switch (argv[*i][0])
+	{
+	case '-':
+		for (p = &argv[*i][1]; *p; p++) {
+			if (*p == 'R') {
+				recursive = 1;
+				continue;
+			}
+			if (*p == 'V') {
+				verbose = 1;
+				continue;
+			}
+			if (*p == 'f') {
+				silent = 1;
+				continue;
+			}
+			if (*p == 'v') {
+				(*i)++;
+				if (*i >= argc)
+					usage ();
+				version = strtol (argv[*i], &tmp, 0);
+				if (*tmp) {
+					com_err (program_name, 0,
+						 _("bad version - %s\n"),
+						 argv[*i]);
+					usage ();
+				}
+				set_version = 1;
+				continue;
+			}
+			if ((fl = get_flag(*p)) == 0)
+				usage();
+			rf |= fl;
+			rem = 1;
+		}
+		break;
+	case '+':
+		add = 1;
+		for (p = &argv[*i][1]; *p; p++) {
+			if ((fl = get_flag(*p)) == 0)
+				usage();
+			af |= fl;
+		}
+		break;
+	case '=':
+		set = 1;
+		for (p = &argv[*i][1]; *p; p++) {
+			if ((fl = get_flag(*p)) == 0)
+				usage();
+			sf |= fl;
+		}
+		break;
+	default:
+		return EOF;
+		break;
+	}
+	return 1;
+}
+
+static int chattr_dir_proc(const char *, struct dirent *, void *);
+
+static int change_attributes(const char * name)
+{
+	unsigned long flags;
+	STRUCT_STAT	st;
+
+	if (LSTAT (name, &st) == -1) {
+		if (!silent)
+			com_err (program_name, errno,
+				 _("while trying to stat %s"), name);
+		return -1;
+	}
+
+	if (fgetflags(name, &flags) == -1) {
+		if (!silent)
+			com_err(program_name, errno,
+					_("while reading flags on %s"), name);
+		return -1;
+	}
+	if (set) {
+		if (verbose) {
+			printf (_("Flags of %s set as "), name);
+			print_flags (stdout, sf, 0);
+			printf ("\n");
+		}
+		if (fsetflags (name, sf) == -1)
+			perror (name);
+	} else {
+		if (rem)
+			flags &= ~rf;
+		if (add)
+			flags |= af;
+		if (verbose) {
+			printf(_("Flags of %s set as "), name);
+			print_flags(stdout, flags, 0);
+			printf("\n");
+		}
+		if (!S_ISDIR(st.st_mode))
+			flags &= ~EXT2_DIRSYNC_FL;
+		if (fsetflags(name, flags) == -1) {
+			if (!silent) {
+				com_err(program_name, errno,
+						_("while setting flags on %s"),
+						name);
+			}
+			return -1;
+		}
+	}
+	if (set_version) {
+		if (verbose)
+			printf (_("Version of %s set as %lu\n"), name, version);
+		if (fsetversion (name, version) == -1) {
+			if (!silent)
+				com_err (program_name, errno,
+					 _("while setting version on %s"),
+					 name);
+			return -1;
+		}
+	}
+	if (S_ISDIR(st.st_mode) && recursive)
+		return iterate_on_dir (name, chattr_dir_proc, NULL);
+	return 0;
+}
+
+static int chattr_dir_proc (const char * dir_name, struct dirent * de,
+			    void * private EXT2FS_ATTR((unused)))
+{
+	int ret = 0;
+
+	if (strcmp (de->d_name, ".") && strcmp (de->d_name, "..")) {
+	        char *path;
+
+		path = malloc(strlen (dir_name) + 1 + strlen (de->d_name) + 1);
+		if (!path) {
+			fprintf(stderr, "%s",
+				_("Couldn't allocate path variable "
+				  "in chattr_dir_proc"));
+			return -1;
+		}
+		sprintf(path, "%s/%s", dir_name, de->d_name);
+		ret = change_attributes(path);
+		free(path);
+	}
+	return ret;
+}
+
+int main (int argc, char ** argv)
+{
+	int i, j;
+	int end_arg = 0;
+	int err, retval = 0;
+
+#ifdef ENABLE_NLS
+	setlocale(LC_MESSAGES, "");
+	setlocale(LC_CTYPE, "");
+	bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
+	textdomain(NLS_CAT_NAME);
+	set_com_err_gettext(gettext);
+#endif
+	if (argc && *argv)
+		program_name = *argv;
+	i = 1;
+	while (i < argc && !end_arg) {
+		/* '--' arg should end option processing */
+		if (strcmp(argv[i], "--") == 0) {
+			i++;
+			end_arg = 1;
+		} else if (decode_arg (&i, argc, argv) == EOF)
+			end_arg = 1;
+		else
+			i++;
+	}
+	if (i >= argc)
+		usage ();
+	if (set && (add || rem)) {
+		fputs(_("= is incompatible with - and +\n"), stderr);
+		exit (1);
+	}
+	if ((rf & af) != 0) {
+		fputs("Can't both set and unset same flag.\n", stderr);
+		exit (1);
+	}
+	if (!(add || rem || set || set_version)) {
+		fputs(_("Must use '-v', =, - or +\n"), stderr);
+		exit (1);
+	}
+	if (verbose)
+		fprintf (stderr, "chattr %s (%s)\n",
+			 E2FSPROGS_VERSION, E2FSPROGS_DATE);
+	for (j = i; j < argc; j++) {
+		err = change_attributes (argv[j]);
+		if (err)
+			retval = 1;
+	}
+	exit(retval);
+}
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/dumpe2fs.8.in b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/dumpe2fs.8.in
new file mode 100644
index 0000000..befaf94
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/dumpe2fs.8.in
@@ -0,0 +1,87 @@
+.\" -*- nroff -*-
+.\" Copyright 1993, 1994, 1995 by Theodore Ts'o.  All Rights Reserved.
+.\" This file may be copied under the terms of the GNU Public License.
+.\" 
+.TH DUMPE2FS 8 "@E2FSPROGS_MONTH@ @E2FSPROGS_YEAR@" "E2fsprogs version @E2FSPROGS_VERSION@"
+.SH NAME
+dumpe2fs \- dump ext2/ext3/ext4 filesystem information
+.SH SYNOPSIS
+.B dumpe2fs
+[
+.B \-bfhixV
+]
+[
+.B \-o superblock=\fIsuperblock
+]
+[
+.B \-o blocksize=\fIblocksize
+]
+.I device
+.SH DESCRIPTION
+.B dumpe2fs
+prints the super block and blocks group information for the filesystem
+present on
+.I device.
+.PP
+.B Note:
+When used with a mounted filesystem, the printed
+information may be old or inconsistent.
+.SH OPTIONS
+.TP
+.B \-b
+print the blocks which are reserved as bad in the filesystem.
+.TP
+.B \-o superblock=\fIsuperblock
+use the block
+.I superblock
+when examining the filesystem.
+This option is not usually needed except by a filesystem wizard who 
+is examining the remains of a very badly corrupted filesystem.
+.TP
+.B \-o blocksize=\fIblocksize
+use blocks of
+.I blocksize
+bytes when examining the filesystem.
+This option is not usually needed except by a filesystem wizard who 
+is examining the remains of a very badly corrupted filesystem.
+.TP
+.B \-f
+force dumpe2fs to display a filesystem even though it may have some 
+filesystem feature flags which dumpe2fs may not understand (and which
+can cause some of dumpe2fs's display to be suspect).
+.TP 
+.B \-h
+only display the superblock information and not any of the block
+group descriptor detail information.
+.TP
+.B \-i
+display the filesystem data from an image file created by 
+.BR e2image ,
+using 
+.I device
+as the pathname to the image file.
+.TP
+.B \-x
+print the detailed group information block numbers in hexadecimal format
+.TP
+.B \-V
+print the version number of 
+.B dumpe2fs
+and exit.
+.SH BUGS
+You need to know the physical filesystem structure to understand the
+output.
+.SH AUTHOR
+.B dumpe2fs 
+was written by Remy Card <Remy.Card@linux.org>.  It is currently being
+maintained by Theodore Ts'o <tytso@alum.mit.edu>.
+.SH AVAILABILITY
+.B dumpe2fs
+is part of the e2fsprogs package and is available from 
+http://e2fsprogs.sourceforge.net.
+.SH SEE ALSO
+.BR e2fsck (8),
+.BR mke2fs (8),
+.BR tune2fs (8).
+.BR ext4 (5)
+
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/dumpe2fs.c b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/dumpe2fs.c
new file mode 100644
index 0000000..d4bde8e
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/dumpe2fs.c
@@ -0,0 +1,640 @@
+/*
+ * dumpe2fs.c		- List the control structures of a second
+ *			  extended filesystem
+ *
+ * Copyright (C) 1992, 1993, 1994  Remy Card <card@masi.ibp.fr>
+ *                                 Laboratoire MASI, Institut Blaise Pascal
+ *                                 Universite Pierre et Marie Curie (Paris VI)
+ *
+ * Copyright 1995, 1996, 1997 by Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+/*
+ * History:
+ * 94/01/09	- Creation
+ * 94/02/27	- Ported to use the ext2fs library
+ */
+
+#include "config.h"
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#else
+extern char *optarg;
+extern int optind;
+#endif
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "ext2fs/ext2_fs.h"
+
+#include "ext2fs/ext2fs.h"
+#include "e2p/e2p.h"
+#include "jfs_user.h"
+#include <uuid/uuid.h>
+
+#include "../version.h"
+#include "nls-enable.h"
+
+#define in_use(m, x)	(ext2fs_test_bit ((x), (m)))
+
+static const char * program_name = "dumpe2fs";
+static char * device_name = NULL;
+static int hex_format = 0;
+static int blocks64 = 0;
+
+static void usage(void)
+{
+	fprintf (stderr, _("Usage: %s [-bfhixV] [-o superblock=<num>] "
+		 "[-o blocksize=<num>] device\n"), program_name);
+	exit (1);
+}
+
+static void print_number(unsigned long long num)
+{
+	if (hex_format) {
+		if (blocks64)
+			printf("0x%08llx", num);
+		else
+			printf("0x%04llx", num);
+	} else
+		printf("%llu", num);
+}
+
+static void print_range(unsigned long long a, unsigned long long b)
+{
+	if (hex_format) {
+		if (blocks64)
+			printf("0x%08llx-0x%08llx", a, b);
+		else
+			printf("0x%04llx-0x%04llx", a, b);
+	} else
+		printf("%llu-%llu", a, b);
+}
+
+static void print_free(unsigned long group, char * bitmap,
+		       unsigned long num, unsigned long offset, int ratio)
+{
+	int p = 0;
+	unsigned long i;
+	unsigned long j;
+
+	offset /= ratio;
+	offset += group * num;
+	for (i = 0; i < num; i++)
+		if (!in_use (bitmap, i))
+		{
+			if (p)
+				printf (", ");
+			print_number((i + offset) * ratio);
+			for (j = i; j < num && !in_use (bitmap, j); j++)
+				;
+			if (--j != i) {
+				fputc('-', stdout);
+				print_number((j + offset) * ratio);
+				i = j;
+			}
+			p = 1;
+		}
+}
+
+static void print_bg_opt(int bg_flags, int mask,
+			  const char *str, int *first)
+{
+	if (bg_flags & mask) {
+		if (*first) {
+			fputs(" [", stdout);
+			*first = 0;
+		} else
+			fputs(", ", stdout);
+		fputs(str, stdout);
+	}
+}
+static void print_bg_opts(ext2_filsys fs, dgrp_t i)
+{
+	int first = 1, bg_flags = 0;
+
+	if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM)
+		bg_flags = ext2fs_bg_flags(fs, i);
+
+	print_bg_opt(bg_flags, EXT2_BG_INODE_UNINIT, "INODE_UNINIT",
+ 		     &first);
+	print_bg_opt(bg_flags, EXT2_BG_BLOCK_UNINIT, "BLOCK_UNINIT",
+ 		     &first);
+	print_bg_opt(bg_flags, EXT2_BG_INODE_ZEROED, "ITABLE_ZEROED",
+ 		     &first);
+	if (!first)
+		fputc(']', stdout);
+	fputc('\n', stdout);
+}
+
+static void print_bg_rel_offset(ext2_filsys fs, blk64_t block, int itable,
+				blk64_t first_block, blk64_t last_block)
+{
+	if ((block >= first_block) && (block <= last_block)) {
+		if (itable && block == first_block)
+			return;
+		printf(" (+%u)", (unsigned)(block - first_block));
+	} else if (fs->super->s_feature_incompat &
+		   EXT4_FEATURE_INCOMPAT_FLEX_BG) {
+		dgrp_t flex_grp = ext2fs_group_of_blk2(fs, block);
+		printf(" (bg #%u + %u)", flex_grp,
+		       (unsigned)(block-ext2fs_group_first_block2(fs,flex_grp)));
+	}
+}
+
+static void list_desc (ext2_filsys fs)
+{
+	unsigned long i;
+	blk64_t	first_block, last_block;
+	blk64_t	super_blk, old_desc_blk, new_desc_blk;
+	char *block_bitmap=NULL, *inode_bitmap=NULL;
+	const char *units = _("blocks");
+	int inode_blocks_per_group, old_desc_blocks, reserved_gdt;
+	int		block_nbytes, inode_nbytes;
+	int has_super;
+	blk64_t		blk_itr = EXT2FS_B2C(fs, fs->super->s_first_data_block);
+	ext2_ino_t	ino_itr = 1;
+	errcode_t	retval;
+
+	if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
+				       EXT4_FEATURE_RO_COMPAT_BIGALLOC))
+		units = _("clusters");
+
+	block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8;
+	inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8;
+
+	if (fs->block_map)
+		block_bitmap = malloc(block_nbytes);
+	if (fs->inode_map)
+		inode_bitmap = malloc(inode_nbytes);
+
+	inode_blocks_per_group = ((fs->super->s_inodes_per_group *
+				   EXT2_INODE_SIZE(fs->super)) +
+				  EXT2_BLOCK_SIZE(fs->super) - 1) /
+				 EXT2_BLOCK_SIZE(fs->super);
+	reserved_gdt = fs->super->s_reserved_gdt_blocks;
+	fputc('\n', stdout);
+	first_block = fs->super->s_first_data_block;
+	if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG)
+		old_desc_blocks = fs->super->s_first_meta_bg;
+	else
+		old_desc_blocks = fs->desc_blocks;
+	for (i = 0; i < fs->group_desc_count; i++) {
+		first_block = ext2fs_group_first_block2(fs, i);
+		last_block = ext2fs_group_last_block2(fs, i);
+
+		ext2fs_super_and_bgd_loc2(fs, i, &super_blk,
+					  &old_desc_blk, &new_desc_blk, 0);
+
+		printf (_("Group %lu: (Blocks "), i);
+		print_range(first_block, last_block);
+		fputs(")", stdout);
+		print_bg_opts(fs, i);
+		if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) {
+			unsigned csum = ext2fs_bg_checksum(fs, i);
+			unsigned exp_csum = ext2fs_group_desc_csum(fs, i);
+
+			printf(_("  Checksum 0x%04x"), csum);
+			if (csum != exp_csum)
+				printf(_(" (EXPECTED 0x%04x)"), exp_csum);
+			printf(_(", unused inodes %u\n"),
+			       ext2fs_bg_itable_unused(fs, i));
+		}
+		has_super = ((i==0) || super_blk);
+		if (has_super) {
+			printf (_("  %s superblock at "),
+				i == 0 ? _("Primary") : _("Backup"));
+			print_number(super_blk);
+		}
+		if (old_desc_blk) {
+			printf("%s", _(", Group descriptors at "));
+			print_range(old_desc_blk,
+				    old_desc_blk + old_desc_blocks - 1);
+			if (reserved_gdt) {
+				printf("%s", _("\n  Reserved GDT blocks at "));
+				print_range(old_desc_blk + old_desc_blocks,
+					    old_desc_blk + old_desc_blocks +
+					    reserved_gdt - 1);
+			}
+		} else if (new_desc_blk) {
+			fputc(has_super ? ',' : ' ', stdout);
+			printf("%s", _(" Group descriptor at "));
+			print_number(new_desc_blk);
+			has_super++;
+		}
+		if (has_super)
+			fputc('\n', stdout);
+		fputs(_("  Block bitmap at "), stdout);
+		print_number(ext2fs_block_bitmap_loc(fs, i));
+		print_bg_rel_offset(fs, ext2fs_block_bitmap_loc(fs, i), 0,
+				    first_block, last_block);
+		fputs(_(", Inode bitmap at "), stdout);
+		print_number(ext2fs_inode_bitmap_loc(fs, i));
+		print_bg_rel_offset(fs, ext2fs_inode_bitmap_loc(fs, i), 0,
+				    first_block, last_block);
+		fputs(_("\n  Inode table at "), stdout);
+		print_range(ext2fs_inode_table_loc(fs, i),
+			    ext2fs_inode_table_loc(fs, i) +
+			    inode_blocks_per_group - 1);
+		print_bg_rel_offset(fs, ext2fs_inode_table_loc(fs, i), 1,
+				    first_block, last_block);
+		printf (_("\n  %u free %s, %u free inodes, "
+			  "%u directories%s"),
+			ext2fs_bg_free_blocks_count(fs, i), units,
+			ext2fs_bg_free_inodes_count(fs, i),
+			ext2fs_bg_used_dirs_count(fs, i),
+			ext2fs_bg_itable_unused(fs, i) ? "" : "\n");
+		if (ext2fs_bg_itable_unused(fs, i))
+			printf (_(", %u unused inodes\n"),
+				ext2fs_bg_itable_unused(fs, i));
+		if (block_bitmap) {
+			fputs(_("  Free blocks: "), stdout);
+			retval = ext2fs_get_block_bitmap_range2(fs->block_map,
+				 blk_itr, block_nbytes << 3, block_bitmap);
+			if (retval)
+				com_err("list_desc", retval,
+					"while reading block bitmap");
+			else
+				print_free(i, block_bitmap,
+					   fs->super->s_clusters_per_group,
+					   fs->super->s_first_data_block,
+					   EXT2FS_CLUSTER_RATIO(fs));
+			fputc('\n', stdout);
+			blk_itr += fs->super->s_clusters_per_group;
+		}
+		if (inode_bitmap) {
+			fputs(_("  Free inodes: "), stdout);
+			retval = ext2fs_get_inode_bitmap_range2(fs->inode_map,
+				 ino_itr, inode_nbytes << 3, inode_bitmap);
+			if (retval)
+				com_err("list_desc", retval,
+					"while reading inode bitmap");
+			else
+				print_free(i, inode_bitmap,
+					   fs->super->s_inodes_per_group,
+					   1, 1);
+			fputc('\n', stdout);
+			ino_itr += fs->super->s_inodes_per_group;
+		}
+	}
+	if (block_bitmap)
+		free(block_bitmap);
+	if (inode_bitmap)
+		free(inode_bitmap);
+}
+
+static void list_bad_blocks(ext2_filsys fs, int dump)
+{
+	badblocks_list		bb_list = 0;
+	badblocks_iterate	bb_iter;
+	blk_t			blk;
+	errcode_t		retval;
+	const char		*header, *fmt;
+
+	retval = ext2fs_read_bb_inode(fs, &bb_list);
+	if (retval) {
+		com_err("ext2fs_read_bb_inode", retval, 0);
+		return;
+	}
+	retval = ext2fs_badblocks_list_iterate_begin(bb_list, &bb_iter);
+	if (retval) {
+		com_err("ext2fs_badblocks_list_iterate_begin", retval,
+			"%s", _("while printing bad block list"));
+		return;
+	}
+	if (dump) {
+		header = fmt = "%u\n";
+	} else {
+		header =  _("Bad blocks: %u");
+		fmt = ", %u";
+	}
+	while (ext2fs_badblocks_list_iterate(bb_iter, &blk)) {
+		printf(header ? header : fmt, blk);
+		header = 0;
+	}
+	ext2fs_badblocks_list_iterate_end(bb_iter);
+	if (!dump)
+		fputc('\n', stdout);
+	ext2fs_badblocks_list_free(bb_list);
+}
+
+static void print_inline_journal_information(ext2_filsys fs)
+{
+	journal_superblock_t	*jsb;
+	struct ext2_inode	inode;
+	ext2_file_t		journal_file;
+	errcode_t		retval;
+	ino_t			ino = fs->super->s_journal_inum;
+	char			buf[1024];
+	__u32			*mask_ptr, mask, m;
+	int			i, j, size, printed = 0;
+
+	if (fs->flags & EXT2_FLAG_IMAGE_FILE)
+		return;
+	retval = ext2fs_read_inode(fs, ino,  &inode);
+	if (retval) {
+		com_err(program_name, retval, "%s",
+			_("while reading journal inode"));
+		exit(1);
+	}
+	retval = ext2fs_file_open2(fs, ino, &inode, 0, &journal_file);
+	if (retval) {
+		com_err(program_name, retval, "%s",
+			_("while opening journal inode"));
+		exit(1);
+	}
+	retval = ext2fs_file_read(journal_file, buf, sizeof(buf), 0);
+	if (retval) {
+		com_err(program_name, retval, "%s",
+			_("while reading journal super block"));
+		exit(1);
+	}
+	ext2fs_file_close(journal_file);
+	jsb = (journal_superblock_t *) buf;
+	if (be32_to_cpu(jsb->s_header.h_magic) != JFS_MAGIC_NUMBER) {
+		fprintf(stderr, "%s",
+			_("Journal superblock magic number invalid!\n"));
+		exit(1);
+	}
+	printf("%s", _("Journal features:        "));
+	for (i=0, mask_ptr=&jsb->s_feature_compat; i <3; i++,mask_ptr++) {
+		mask = be32_to_cpu(*mask_ptr);
+		for (j=0,m=1; j < 32; j++, m<<=1) {
+			if (mask & m) {
+				printf(" %s", e2p_jrnl_feature2string(i, m));
+				printed++;
+			}
+		}
+	}
+	if (printed == 0)
+		printf(" (none)");
+	printf("\n");
+	fputs(_("Journal size:             "), stdout);
+	if ((fs->super->s_feature_ro_compat &
+	     EXT4_FEATURE_RO_COMPAT_HUGE_FILE) &&
+	    (inode.i_flags & EXT4_HUGE_FILE_FL))
+		size = inode.i_blocks / (fs->blocksize / 1024);
+	else
+		size = inode.i_blocks >> 1;
+	if (size < 8192)
+		printf("%uk\n", size);
+	else
+		printf("%uM\n", size >> 10);
+	printf(_("Journal length:           %u\n"
+		 "Journal sequence:         0x%08x\n"
+		 "Journal start:            %u\n"),
+	       (unsigned int)ntohl(jsb->s_maxlen),
+	       (unsigned int)ntohl(jsb->s_sequence),
+	       (unsigned int)ntohl(jsb->s_start));
+	if (jsb->s_errno != 0)
+		printf(_("Journal errno:            %d\n"),
+		       (int) ntohl(jsb->s_errno));
+}
+
+static void print_journal_information(ext2_filsys fs)
+{
+	errcode_t	retval;
+	char		buf[1024];
+	char		str[80];
+	unsigned int	i;
+	journal_superblock_t	*jsb;
+
+	/* Get the journal superblock */
+	if ((retval = io_channel_read_blk64(fs->io,
+					    fs->super->s_first_data_block + 1,
+					    -1024, buf))) {
+		com_err(program_name, retval, "%s",
+			_("while reading journal superblock"));
+		exit(1);
+	}
+	jsb = (journal_superblock_t *) buf;
+	if ((jsb->s_header.h_magic != (unsigned) ntohl(JFS_MAGIC_NUMBER)) ||
+	    (jsb->s_header.h_blocktype !=
+	     (unsigned) ntohl(JFS_SUPERBLOCK_V2))) {
+		com_err(program_name, 0, "%s",
+			_("Couldn't find journal superblock magic numbers"));
+		exit(1);
+	}
+
+	printf(_("\nJournal block size:       %u\n"
+		 "Journal length:           %u\n"
+		 "Journal first block:      %u\n"
+		 "Journal sequence:         0x%08x\n"
+		 "Journal start:            %u\n"
+		 "Journal number of users:  %u\n"),
+	       (unsigned int)ntohl(jsb->s_blocksize),  (unsigned int)ntohl(jsb->s_maxlen),
+	       (unsigned int)ntohl(jsb->s_first), (unsigned int)ntohl(jsb->s_sequence),
+	       (unsigned int)ntohl(jsb->s_start), (unsigned int)ntohl(jsb->s_nr_users));
+
+	for (i=0; i < ntohl(jsb->s_nr_users); i++) {
+		uuid_unparse(&jsb->s_users[i*16], str);
+		printf(i ? "                          %s\n"
+		       : _("Journal users:            %s\n"),
+		       str);
+	}
+}
+
+static void parse_extended_opts(const char *opts, blk64_t *superblock,
+				int *blocksize)
+{
+	char	*buf, *token, *next, *p, *arg, *badopt = 0;
+	int	len;
+	int	do_usage = 0;
+
+	len = strlen(opts);
+	buf = malloc(len+1);
+	if (!buf) {
+		fprintf(stderr, "%s",
+			_("Couldn't allocate memory to parse options!\n"));
+		exit(1);
+	}
+	strcpy(buf, opts);
+	for (token = buf; token && *token; token = next) {
+		p = strchr(token, ',');
+		next = 0;
+		if (p) {
+			*p = 0;
+			next = p+1;
+		}
+		arg = strchr(token, '=');
+		if (arg) {
+			*arg = 0;
+			arg++;
+		}
+		if (strcmp(token, "superblock") == 0 ||
+		    strcmp(token, "sb") == 0) {
+			if (!arg) {
+				do_usage++;
+				badopt = token;
+				continue;
+			}
+			*superblock = strtoul(arg, &p, 0);
+			if (*p) {
+				fprintf(stderr,
+					_("Invalid superblock parameter: %s\n"),
+					arg);
+				do_usage++;
+				continue;
+			}
+		} else if (strcmp(token, "blocksize") == 0 ||
+			   strcmp(token, "bs") == 0) {
+			if (!arg) {
+				do_usage++;
+				badopt = token;
+				continue;
+			}
+			*blocksize = strtoul(arg, &p, 0);
+			if (*p) {
+				fprintf(stderr,
+					_("Invalid blocksize parameter: %s\n"),
+					arg);
+				do_usage++;
+				continue;
+			}
+		} else {
+			do_usage++;
+			badopt = token;
+		}
+	}
+	if (do_usage) {
+		fprintf(stderr, _("\nBad extended option(s) specified: %s\n\n"
+			"Extended options are separated by commas, "
+			"and may take an argument which\n"
+			"\tis set off by an equals ('=') sign.\n\n"
+			"Valid extended options are:\n"
+			"\tsuperblock=<superblock number>\n"
+			"\tblocksize=<blocksize>\n"),
+			badopt ? badopt : "");
+		free(buf);
+		exit(1);
+	}
+	free(buf);
+}
+
+int main (int argc, char ** argv)
+{
+	errcode_t	retval;
+	ext2_filsys	fs;
+	int		print_badblocks = 0;
+	blk64_t		use_superblock = 0;
+	int		use_blocksize = 0;
+	int		image_dump = 0;
+	int		force = 0;
+	int		flags;
+	int		header_only = 0;
+	int		c;
+
+#ifdef ENABLE_NLS
+	setlocale(LC_MESSAGES, "");
+	setlocale(LC_CTYPE, "");
+	bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
+	textdomain(NLS_CAT_NAME);
+	set_com_err_gettext(gettext);
+#endif
+	add_error_table(&et_ext2_error_table);
+	fprintf (stderr, "dumpe2fs %s (%s)\n", E2FSPROGS_VERSION,
+		 E2FSPROGS_DATE);
+	if (argc && *argv)
+		program_name = *argv;
+
+	while ((c = getopt (argc, argv, "bfhixVo:")) != EOF) {
+		switch (c) {
+		case 'b':
+			print_badblocks++;
+			break;
+		case 'f':
+			force++;
+			break;
+		case 'h':
+			header_only++;
+			break;
+		case 'i':
+			image_dump++;
+			break;
+		case 'o':
+			parse_extended_opts(optarg, &use_superblock,
+					    &use_blocksize);
+			break;
+		case 'V':
+			/* Print version number and exit */
+			fprintf(stderr, _("\tUsing %s\n"),
+				error_message(EXT2_ET_BASE));
+			exit(0);
+		case 'x':
+			hex_format++;
+			break;
+		default:
+			usage();
+		}
+	}
+	if (optind > argc - 1)
+		usage();
+	device_name = argv[optind++];
+	flags = EXT2_FLAG_JOURNAL_DEV_OK | EXT2_FLAG_SOFTSUPP_FEATURES | EXT2_FLAG_64BITS;
+	if (force)
+		flags |= EXT2_FLAG_FORCE;
+	if (image_dump)
+		flags |= EXT2_FLAG_IMAGE_FILE;
+
+	if (use_superblock && !use_blocksize) {
+		for (use_blocksize = EXT2_MIN_BLOCK_SIZE;
+		     use_blocksize <= EXT2_MAX_BLOCK_SIZE;
+		     use_blocksize *= 2) {
+			retval = ext2fs_open (device_name, flags,
+					      use_superblock,
+					      use_blocksize, unix_io_manager,
+					      &fs);
+			if (!retval)
+				break;
+		}
+	} else
+		retval = ext2fs_open (device_name, flags, use_superblock,
+				      use_blocksize, unix_io_manager, &fs);
+	if (retval) {
+		com_err (program_name, retval, _("while trying to open %s"),
+			 device_name);
+		printf("%s", _("Couldn't find valid filesystem superblock.\n"));
+		exit (1);
+	}
+	fs->default_bitmap_type = EXT2FS_BMAP64_RBTREE;
+	if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+		blocks64 = 1;
+	if (print_badblocks) {
+		list_bad_blocks(fs, 1);
+	} else {
+		list_super (fs->super);
+		if (fs->super->s_feature_incompat &
+		      EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
+			print_journal_information(fs);
+			ext2fs_close(fs);
+			exit(0);
+		}
+		if ((fs->super->s_feature_compat &
+		     EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
+		    (fs->super->s_journal_inum != 0))
+			print_inline_journal_information(fs);
+		list_bad_blocks(fs, 0);
+		if (header_only) {
+			ext2fs_close (fs);
+			exit (0);
+		}
+		retval = ext2fs_read_bitmaps (fs);
+		list_desc (fs);
+		if (retval) {
+			printf(_("\n%s: %s: error reading bitmaps: %s\n"),
+			       program_name, device_name,
+			       error_message(retval));
+		}
+	}
+	ext2fs_close (fs);
+	remove_error_table(&et_ext2_error_table);
+	exit (0);
+}
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e2freefrag.8.in b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e2freefrag.8.in
new file mode 100644
index 0000000..564be74
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e2freefrag.8.in
@@ -0,0 +1,96 @@
+.\" -*- nroff -*-
+.TH E2FREEFRAG 8 "@E2FSPROGS_MONTH@ @E2FSPROGS_YEAR@" "E2fsprogs version @E2FSPROGS_VERSION@"
+.SH NAME
+e2freefrag \- report free space fragmentation information
+.SH SYNOPSIS
+.B e2freefrag
+[
+.B \-c chunk_kb
+]
+[
+.B \-h
+]
+.B filesys
+
+.SH DESCRIPTION
+.B e2freefrag
+is used to report free space fragmentation on ext2/3/4 file systems.
+.I filesys
+is the filesystem device name (e.g.
+.IR /dev/hdc1 ", " /dev/md0 ).
+The
+.B e2freefrag
+program will scan the block bitmap information to check how many free blocks
+are present as contiguous and aligned free space. The percentage of contiguous
+free blocks of size and of alignment
+.IR chunk_kb
+is reported.  It also displays the minimum/maximum/average free chunk size in
+the filesystem, along with a histogram of all free chunks.  This information
+can be used to gauge the level of free space fragmentation in the filesystem.
+.SH OPTIONS
+.TP
+.BI \-c " chunk_kb"
+If a chunk size is specified, then
+.B e2freefrag
+will print how many free chunks of size
+.I chunk_kb
+are available in units of kilobytes (Kb).  The chunk size must be a
+power of two and be larger than filesystem block size.
+.TP
+.BI \-h
+Print the usage of the program.
+.SH EXAMPLE
+# e2freefrag /dev/vgroot/lvhome
+.br
+Device: /dev/vgroot/lvhome
+.br
+Blocksize: 4096 bytes
+.br
+Total blocks: 1504085
+.br
+Free blocks: 292995 (19.5%)
+.br
+
+Min. free extent: 4 KB
+.br
+Max. free extent: 24008 KB
+.br
+Avg. free extent: 252 KB
+.br
+
+HISTOGRAM OF FREE EXTENT SIZES:
+.br
+Extent Size Range :   Free extents   Free Blocks  Percent
+.br
+    4K...    8K- :           704           704     0.2%
+.br
+    8K...   16K- :           810          1979     0.7%
+.br
+   16K...   32K- :           843          4467     1.5%
+.br
+   32K...   64K- :           579          6263     2.1%
+.br
+   64K...  128K- :           493         11067     3.8%
+.br
+  128K...  256K- :           394         18097     6.2%
+.br
+  256K...  512K- :           281         25477     8.7%
+.br
+  512K... 1024K- :           253         44914    15.3%
+.br
+    1M...    2M- :           143         51897    17.7%
+.br
+    2M...    4M- :            73         50683    17.3%
+.br
+    4M...    8M- :            37         52417    17.9%
+.br
+    8M...   16M- :             7         19028     6.5%
+.br
+   16M...   32M- :             1          6002     2.0%
+.SH AUTHOR
+This version of e2freefrag was written by Rupesh Thakare, and modified by
+Andreas Dilger <adilger@sun.com>, and Kalpak Shah.
+.SH SEE ALSO
+.IR debugfs (8),
+.IR dumpe2fs (8),
+.IR e2fsck (8)
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e2freefrag.c b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e2freefrag.c
new file mode 100644
index 0000000..612ca44
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e2freefrag.c
@@ -0,0 +1,336 @@
+/*
+ * e2freefrag - report filesystem free-space fragmentation
+ *
+ * Copyright (C) 2009 Sun Microsystems, Inc.
+ *
+ * Author: Rupesh Thakare <rupesh@sun.com>
+ *         Andreas Dilger <adilger@sun.com>
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License version 2.
+ * %End-Header%
+ */
+#include "config.h"
+#include <stdio.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#else
+extern char *optarg;
+extern int optind;
+#endif
+
+#include "ext2fs/ext2_fs.h"
+#include "ext2fs/ext2fs.h"
+#include "e2freefrag.h"
+
+static void usage(const char *prog)
+{
+	fprintf(stderr, "usage: %s [-c chunksize in kb] [-h] "
+		"device_name\n", prog);
+#ifndef DEBUGFS
+	exit(1);
+#endif
+}
+
+static int ul_log2(unsigned long arg)
+{
+        int     l = 0;
+
+        arg >>= 1;
+        while (arg) {
+                l++;
+                arg >>= 1;
+        }
+        return l;
+}
+
+static void init_chunk_info(ext2_filsys fs, struct chunk_info *info)
+{
+	int i;
+
+	info->blocksize_bits = ul_log2((unsigned long)fs->blocksize);
+	if (info->chunkbytes) {
+		info->chunkbits = ul_log2(info->chunkbytes);
+		info->blks_in_chunk = info->chunkbytes >> info->blocksize_bits;
+	} else {
+		info->chunkbits = ul_log2(DEFAULT_CHUNKSIZE);
+		info->blks_in_chunk = DEFAULT_CHUNKSIZE >> info->blocksize_bits;
+	}
+
+	info->min = ~0UL;
+	info->max = info->avg = 0;
+	info->real_free_chunks = 0;
+
+	for (i = 0; i < MAX_HIST; i++) {
+		info->histogram.fc_chunks[i] = 0;
+		info->histogram.fc_blocks[i] = 0;
+	}
+}
+
+static void update_chunk_stats(struct chunk_info *info,
+			       unsigned long chunk_size)
+{
+	unsigned long idx;
+
+	idx = ul_log2(chunk_size) + 1;
+	if (idx >= MAX_HIST)
+		idx = MAX_HIST-1;
+	info->histogram.fc_chunks[idx]++;
+	info->histogram.fc_blocks[idx] += chunk_size;
+
+	if (chunk_size > info->max)
+		info->max = chunk_size;
+	if (chunk_size < info->min)
+		info->min = chunk_size;
+	info->avg += chunk_size;
+	info->real_free_chunks++;
+}
+
+static void scan_block_bitmap(ext2_filsys fs, struct chunk_info *info)
+{
+	unsigned long long blocks_count = ext2fs_blocks_count(fs->super);
+	unsigned long long chunks = (blocks_count + info->blks_in_chunk) >>
+				(info->chunkbits - info->blocksize_bits);
+	unsigned long long chunk_num;
+	unsigned long last_chunk_size = 0;
+	unsigned long long chunk_start_blk = 0;
+	int used;
+
+	for (chunk_num = 0; chunk_num < chunks; chunk_num++) {
+		unsigned long long blk, num_blks;
+		int chunk_free;
+
+		/* Last chunk may be smaller */
+		if (chunk_start_blk + info->blks_in_chunk > blocks_count)
+			num_blks = blocks_count - chunk_start_blk;
+		else
+			num_blks = info->blks_in_chunk;
+
+		chunk_free = 0;
+
+		/* Initialize starting block for first chunk correctly else
+		 * there is a segfault when blocksize = 1024 in which case
+		 * block_map->start = 1 */
+		for (blk = 0; blk < num_blks; blk++, chunk_start_blk++) {
+			if (chunk_num == 0 && blk == 0) {
+				blk = fs->super->s_first_data_block;
+				chunk_start_blk = blk;
+			}
+			used = ext2fs_fast_test_block_bitmap2(fs->block_map,
+				chunk_start_blk >> fs->cluster_ratio_bits);
+			if (!used) {
+				last_chunk_size++;
+				chunk_free++;
+			}
+
+			if (used && last_chunk_size != 0) {
+				update_chunk_stats(info, last_chunk_size);
+				last_chunk_size = 0;
+			}
+		}
+
+		if (chunk_free == info->blks_in_chunk)
+			info->free_chunks++;
+	}
+	if (last_chunk_size != 0)
+		update_chunk_stats(info, last_chunk_size);
+}
+
+static errcode_t get_chunk_info(ext2_filsys fs, struct chunk_info *info,
+				FILE *f)
+{
+	unsigned long total_chunks;
+	const char *unitp = "KMGTPEZY";
+	int units = 10;
+	unsigned long start = 0, end;
+	int i, retval = 0;
+
+	scan_block_bitmap(fs, info);
+
+	fprintf(f, "Total blocks: %llu\nFree blocks: %u (%0.1f%%)\n",
+		ext2fs_blocks_count(fs->super), fs->super->s_free_blocks_count,
+		(double)fs->super->s_free_blocks_count * 100 /
+		ext2fs_blocks_count(fs->super));
+
+	if (info->chunkbytes) {
+		fprintf(f, "\nChunksize: %lu bytes (%u blocks)\n",
+			info->chunkbytes, info->blks_in_chunk);
+		total_chunks = (ext2fs_blocks_count(fs->super) +
+				info->blks_in_chunk) >>
+			(info->chunkbits - info->blocksize_bits);
+		fprintf(f, "Total chunks: %lu\nFree chunks: %lu (%0.1f%%)\n",
+			total_chunks, info->free_chunks,
+			(double)info->free_chunks * 100 / total_chunks);
+	}
+
+	/* Display chunk information in KB */
+	if (info->real_free_chunks) {
+		unsigned int scale = fs->blocksize >> 10;
+		info->min = info->min * scale;
+		info->max = info->max * scale;
+		info->avg = info->avg / info->real_free_chunks * scale;
+	} else {
+		info->min = 0;
+	}
+
+	fprintf(f, "\nMin. free extent: %lu KB \nMax. free extent: %lu KB\n"
+		"Avg. free extent: %lu KB\n", info->min, info->max, info->avg);
+	fprintf(f, "Num. free extent: %lu\n", info->real_free_chunks);
+
+	fprintf(f, "\nHISTOGRAM OF FREE EXTENT SIZES:\n");
+	fprintf(f, "%s :  %12s  %12s  %7s\n", "Extent Size Range",
+		"Free extents", "Free Blocks", "Percent");
+	for (i = 0; i < MAX_HIST; i++) {
+		end = 1 << (i + info->blocksize_bits - units);
+		if (info->histogram.fc_chunks[i] != 0) {
+			char end_str[32];
+
+			sprintf(end_str, "%5lu%c-", end, *unitp);
+			if (i == MAX_HIST-1)
+				strcpy(end_str, "max ");
+			fprintf(f, "%5lu%c...%7s  :  %12lu  %12lu  %6.2f%%\n",
+				start, *unitp, end_str,
+				info->histogram.fc_chunks[i],
+				info->histogram.fc_blocks[i],
+				(double)info->histogram.fc_blocks[i] * 100 /
+				fs->super->s_free_blocks_count);
+		}
+		start = end;
+		if (start == 1<<10) {
+			start = 1;
+			units += 10;
+			unitp++;
+		}
+	}
+
+	return retval;
+}
+
+static void close_device(char *device_name, ext2_filsys fs)
+{
+	int retval = ext2fs_close(fs);
+
+	if (retval)
+		com_err(device_name, retval, "while closing the filesystem.\n");
+}
+
+static void collect_info(ext2_filsys fs, struct chunk_info *chunk_info, FILE *f)
+{
+	unsigned int retval = 0;
+
+	fprintf(f, "Device: %s\n", fs->device_name);
+	fprintf(f, "Blocksize: %u bytes\n", fs->blocksize);
+
+	retval = ext2fs_read_block_bitmap(fs);
+	if (retval) {
+		com_err(fs->device_name, retval, "while reading block bitmap");
+		close_device(fs->device_name, fs);
+		exit(1);
+	}
+
+	init_chunk_info(fs, chunk_info);
+
+	retval = get_chunk_info(fs, chunk_info, f);
+	if (retval) {
+		com_err(fs->device_name, retval, "while collecting chunk info");
+                close_device(fs->device_name, fs);
+		exit(1);
+	}
+}
+
+#ifndef DEBUGFS
+static void open_device(char *device_name, ext2_filsys *fs)
+{
+	int retval;
+	int flag = EXT2_FLAG_FORCE | EXT2_FLAG_64BITS;
+
+	retval = ext2fs_open(device_name, flag, 0, 0, unix_io_manager, fs);
+	if (retval) {
+		com_err(device_name, retval, "while opening filesystem");
+		exit(1);
+	}
+	(*fs)->default_bitmap_type = EXT2FS_BMAP64_RBTREE;
+}
+#endif
+
+#ifdef DEBUGFS
+#include "debugfs.h"
+
+void do_freefrag(int argc, char **argv)
+#else
+int main(int argc, char *argv[])
+#endif
+{
+	struct chunk_info chunk_info;
+	ext2_filsys fs = NULL;
+	char *progname;
+	char *end;
+	int c;
+
+#ifdef DEBUGFS
+	if (check_fs_open(argv[0]))
+		return;
+#else
+	char *device_name;
+
+	add_error_table(&et_ext2_error_table);
+#endif
+	progname = argv[0];
+	memset(&chunk_info, 0, sizeof(chunk_info));
+
+	while ((c = getopt(argc, argv, "c:h")) != EOF) {
+		switch (c) {
+		case 'c':
+			chunk_info.chunkbytes = strtoull(optarg, &end, 0);
+			if (*end != '\0') {
+				fprintf(stderr, "%s: bad chunk size '%s'\n",
+					progname, optarg);
+				usage(progname);
+			}
+			if (chunk_info.chunkbytes &
+			    (chunk_info.chunkbytes - 1)) {
+				fprintf(stderr, "%s: chunk size must be a "
+					"power of 2.\n", argv[0]);
+				usage(progname);
+			}
+			chunk_info.chunkbytes *= 1024;
+			break;
+		case 'h':
+		default:
+			usage(progname);
+			break;
+		}
+	}
+
+#ifndef DEBUGFS
+	if (optind == argc) {
+		fprintf(stderr, "%s: missing device name.\n", progname);
+		usage(progname);
+	}
+
+	device_name = argv[optind];
+
+	open_device(device_name, &fs);
+#else
+	fs = current_fs;
+#endif
+
+	if (chunk_info.chunkbytes && (chunk_info.chunkbytes < fs->blocksize)) {
+		fprintf(stderr, "%s: chunksize must be greater than or equal "
+			"to filesystem blocksize.\n", progname);
+		exit(1);
+	}
+	collect_info(fs, &chunk_info, stdout);
+#ifndef DEBUGFS
+	close_device(device_name, fs);
+
+	return 0;
+#endif
+}
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e2freefrag.h b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e2freefrag.h
new file mode 100644
index 0000000..80d1eef
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e2freefrag.h
@@ -0,0 +1,20 @@
+#include <sys/types.h>
+
+#define DEFAULT_CHUNKSIZE (1024*1024)
+
+#define MAX_HIST	32
+struct free_chunk_histogram {
+	unsigned long fc_chunks[MAX_HIST];
+	unsigned long fc_blocks[MAX_HIST];
+};
+
+struct chunk_info {
+	unsigned long chunkbytes;	/* chunk size in bytes */
+	int chunkbits;			/* chunk size in bits */
+	unsigned long free_chunks;	/* total free chunks of given size */
+	unsigned long real_free_chunks; /* free chunks of any size */
+	int blocksize_bits;		/* fs blocksize in bits */
+	int blks_in_chunk;		/* number of blocks in a chunk */
+	unsigned long min, max, avg;	/* chunk size stats */
+	struct free_chunk_histogram histogram; /* histogram of all chunk sizes*/
+};
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e2image.8.in b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e2image.8.in
new file mode 100644
index 0000000..75002d7
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e2image.8.in
@@ -0,0 +1,285 @@
+.\" -*- nroff -*-
+.\" Copyright 2001 by Theodore Ts'o.  All Rights Reserved.
+.\" This file may be copied under the terms of the GNU Public License.
+.\" 
+.TH E2IMAGE 8 "@E2FSPROGS_MONTH@ @E2FSPROGS_YEAR@" "E2fsprogs version @E2FSPROGS_VERSION@"
+.SH NAME
+e2image \- Save critical ext2/ext3/ext4 filesystem metadata to a file
+.SH SYNOPSIS
+.B e2image
+[
+.B \-r|Q
+]
+[
+.B \-fr
+]
+.I device
+.I image-file
+.br
+.B e2image
+.B \-I
+.I device
+.I image-file
+.br
+.B e2image
+.B \-ra
+[
+.B \-cfnp
+]
+[
+.B \-o
+.I src_offset
+]
+[
+.B \-O
+.I dest_offset
+]
+.I src_fs
+[
+.I dest_fs
+]
+.SH DESCRIPTION
+The
+.B e2image
+program will save critical ext2, ext3, or ext4 filesystem metadata located on
+.I device
+to a file specified by
+.IR image-file .
+The image file may be examined by
+.B dumpe2fs
+and
+.BR  debugfs ,
+by using the
+.B \-i
+option to those programs.  This can assist an expert in
+recovering catastrophically corrupted filesystems.  In the future,
+e2fsck will be enhanced to be able to use the image file to help
+recover a badly damaged filesystem.
+.PP
+When saving an e2image for debugging purposes, using either the
+.B \-r
+or
+.B \-Q
+options, the filesystem must be unmounted or be mounted read/only, in order
+for the image file to be in a consistent state.  This requirement can be
+overriden using the
+.B \-f
+option, but the resulting image file is very likely not going to be useful.
+.PP
+If
+.I image-file
+is \-, then the output of
+.B e2image
+will be sent to standard output, so that the output can be piped to
+another program, such as
+.BR gzip (1).
+(Note that this is currently only supported when
+creating a raw image file using the
+.B \-r
+option, since the process of creating a normal image file, or QCOW2
+image currently
+requires random access to the file, which cannot be done using a
+pipe.  This restriction will hopefully be lifted in a future version of
+.BR e2image .)
+.PP
+It is a very good idea to create image files for all of
+filesystems on a system and save the partition
+layout (which can be generated using the
+.B fdisk \-l
+command) at regular intervals --- at boot time, and/or every week or so.
+The image file should be stored on some filesystem other than
+the filesystem whose data it contains, to ensure that this data is
+accessible in the case where the filesystem has been badly damaged.
+.PP
+To save disk space,
+.B e2image
+creates the image file as a sparse file, or in QCOW2 format.
+Hence, if the sparse image file
+needs to be copied to another location, it should
+either be compressed first or copied using the
+.B \-\-sparse=always
+option to the GNU version of
+.BR cp .
+This does not apply to the QCOW2 image, which is not sparse.
+.PP
+The size of an ext2 image file depends primarily on the size of the
+filesystems and how many inodes are in use.  For a typical 10 gigabyte
+filesystem, with 200,000 inodes in use out of 1.2 million inodes, the
+image file will be approximately 35 megabytes; a 4 gigabyte filesystem with
+15,000 inodes in use out of 550,000 inodes will result in a 3 megabyte
+image file.  Image files tend to be quite
+compressible; an image file taking up 32 megabytes of space on
+disk will generally compress down to 3 or 4 megabytes.
+.PP
+.SH RESTORING FILESYSTEM METADATA USING AN IMAGE FILE
+.PP
+The
+.B \-I
+option will cause e2image to install the metadata stored in the image
+file back to the device.  It can be used to restore the filesystem metadata
+back to the device in emergency situations.
+.PP
+.B WARNING!!!!
+The
+.B \-I
+option should only be used as a desperation measure when other
+alternatives have failed.  If the filesystem has changed since the image
+file was created, data
+.B will
+be lost.  In general, you should make a full image
+backup of the filesystem first, in case you wish to try other recovery
+strategies afterwards.
+.PP
+.SH RAW IMAGE FILES
+The
+.B \-r
+option will create a raw image file instead of a normal image file.
+A raw image file differs
+from a normal image file in two ways.  First, the filesystem metadata is
+placed in the proper position so that e2fsck, dumpe2fs, debugfs,
+etc.\& can be run directly on the raw image file.  In order to minimize
+the amount of disk space consumed by a raw image file, the file is
+created as a sparse file.  (Beware of copying or
+compressing/decompressing this file with utilities that don't understand
+how to create sparse files; the file will become as large as the
+filesystem itself!)  Secondly, the raw image file also includes indirect
+blocks and directory blocks, which the standard image file does not have,
+although this may change in the future.
+.PP
+Raw image files are sometimes used when sending filesystems to the maintainer
+as part of bug reports to e2fsprogs.  When used in this capacity, the
+recommended command is as follows (replace hda1 with the appropriate device):
+.PP
+.br
+	\fBe2image \-r /dev/hda1 \- | bzip2 > hda1.e2i.bz2\fR
+.PP
+This will only send the metadata information, without any data blocks.
+However, the filenames in the directory blocks can still reveal
+information about the contents of the filesystem that the bug reporter
+may wish to keep confidential.  To address this concern, the
+.B \-s
+option can be specified.  This will cause
+.B e2image
+to scramble directory entries and zero out any unused portions
+of the directory blocks before writing the image file.  However,
+the
+.B \-s
+option will prevent analysis of problems related to hash-tree indexed
+directories.
+.PP
+Note that this will work even if you substitute "/dev/hda1" for another raw
+disk image, or QCOW2 image previously created by
+.BR e2image .
+.PP
+.SH QCOW2 IMAGE FILES
+The
+.B \-Q
+option will create a QCOW2 image file instead of a normal, or raw image file.
+A QCOW2 image contains all the information the raw image does, however unlike
+the raw image it is not sparse. The QCOW2 image minimize the amount of disk
+space by storing data in special format with pack data closely together, hence
+avoiding holes while still minimizing size.
+.PP
+In order to send filesystem to the maintainer as a part of bug report to
+e2fsprogs, use following commands (replace hda1 with the appropriate device):
+.PP
+.br
+\	\fBe2image \-Q /dev/hda1 hda1.qcow2\fR
+.br
+\	\fBbzip2 -z hda1.qcow2\fR
+.PP
+This will only send the metadata information, without any data blocks.
+However, the filenames in the directory blocks can still reveal
+information about the contents of the filesystem that the bug reporter
+may wish to keep confidential.  To address this concern, the
+.B \-s
+option can be specified.  This will cause
+.B e2image
+to scramble directory entries and zero out any unused portions
+of the directory blocks before writing the image file.  However, the
+.B \-s
+option will prevent analysis of problems related to hash-tree indexed
+directories.
+.PP
+Note that QCOW2 image created by
+.B e2image
+is regular QCOW2 image and can be processed by tools aware of QCOW2 format
+such as for example
+.BR qemu-img .
+.PP
+You can convert a qcow2 image into a raw image with:
+.PP
+.br
+\	\fBe2image \-r hda1.qcow2 hda1.raw\fR
+.br
+.PP
+This can be useful to write a qcow2 image containing all data to a
+sparse image file where it can be loop mounted, or to a disk partition.
+Note that this may not work with qcow2 images not generated by e2image.
+.PP
+.SH INCLUDING DATA
+Normally
+.B e2image
+only includes fs metadata, not regular file data.  The
+.B \-a
+option can be specified to include all data.  This will
+give an image that is suitable to use to clone the entire FS or
+for backup purposes.  Note that this option only works with the
+raw or QCOW2 formats.  The
+.B \-p
+switch may be given to show progress.  If the file system is being
+cloned to a flash-based storage device (where reads are very fast and
+where it is desirable to avoid unnecessary writes to reduce write wear
+on the device), the
+.B \-c
+option which cause e2image to try reading a block from the destination
+to see if it is identical to the block which
+.B e2image
+is about to copy.  If the block is already the same, the write can be
+skipped.  The
+.B \-n
+option will cause all of the writes to be no-ops, and print the blocks
+that would have been written.
+.PP
+.SH OFFSETS
+Normally a filesystem starts at the beginning of a partition, and
+.B e2image
+is run on the partition.  When working with image files, you don't
+have the option of using the partition device, so you can specify
+the offset where the filesystem starts directly with the
+.B \-o
+option.  Similarly the
+.B \-O
+option specifies the offset that should be seeked to in the destination
+before writing the filesystem.
+.PP
+For example, if you have a
+.B dd
+image of a whole hard drive that contains an ext2 fs in a partition
+starting at 1 MiB, you can clone that fs with:
+.PP
+.br
+\	\fBe2image \-aro 1048576 img /dev/sda1\fR
+.br
+.PP
+Or you can clone a fs into an image file, leaving room in the first
+MiB for a partition table with:
+.PP
+.br
+\	\fBe2image -arO 1048576 /dev/sda1 img\fR
+.br
+.PP
+If you specify at least one offset, and only one file, an in-place
+move will be performed, allowing you to safely move the filesystem
+from one offset to another.
+.SH AUTHOR
+.B e2image
+was written by Theodore Ts'o (tytso@mit.edu).
+.SH AVAILABILITY
+.B e2image
+is part of the e2fsprogs package and is available from
+http://e2fsprogs.sourceforge.net.
+.SH SEE ALSO
+.BR dumpe2fs (8),
+.BR debugfs (8)
+
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e2image.c b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e2image.c
new file mode 100644
index 0000000..0537b0d
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e2image.c
@@ -0,0 +1,1663 @@
+/*
+ * e2image.c --- Program which writes an image file backing up
+ * critical metadata for the filesystem.
+ *
+ * Copyright 2000, 2001 by Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#define _LARGEFILE_SOURCE
+#define _LARGEFILE64_SOURCE
+
+#include "config.h"
+#include <fcntl.h>
+#include <grp.h>
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#else
+extern char *optarg;
+extern int optind;
+#endif
+#include <pwd.h>
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <assert.h>
+#include <signal.h>
+
+#include "ext2fs/ext2_fs.h"
+#include "ext2fs/ext2fs.h"
+#include "et/com_err.h"
+#include "uuid/uuid.h"
+#include "e2p/e2p.h"
+#include "ext2fs/e2image.h"
+#include "ext2fs/qcow2.h"
+
+#include "../version.h"
+#include "nls-enable.h"
+
+#define QCOW_OFLAG_COPIED     (1LL << 63)
+#define NO_BLK ((blk64_t) -1)
+
+/* Image types */
+#define E2IMAGE_RAW	1
+#define E2IMAGE_QCOW2	2
+
+/* Image flags */
+#define E2IMAGE_INSTALL_FLAG	1
+#define E2IMAGE_SCRAMBLE_FLAG	2
+#define E2IMAGE_IS_QCOW2_FLAG	4
+#define E2IMAGE_CHECK_ZERO_FLAG	8
+
+static const char * program_name = "e2image";
+static char * device_name = NULL;
+static char all_data;
+static char output_is_blk;
+static char nop_flag;
+/* writing to blk device: don't skip zeroed blocks */
+static blk64_t source_offset, dest_offset;
+static char move_mode;
+static char show_progress;
+static char *check_buf;
+static int skipped_blocks;
+
+static blk64_t align_offset(blk64_t offset, unsigned int n)
+{
+	return (offset + n - 1) & ~((blk64_t) n - 1);
+}
+
+static int get_bits_from_size(size_t size)
+{
+	int res = 0;
+
+	if (size == 0)
+		return -1;
+
+	while (size != 1) {
+		/* Not a power of two */
+		if (size & 1)
+			return -1;
+
+		size >>= 1;
+		res++;
+	}
+	return res;
+}
+
+static void usage(void)
+{
+	fprintf(stderr, _("Usage: %s [ -r|Q ] [ -fr ] device image-file\n"),
+		program_name);
+	fprintf(stderr, _("       %s -I device image-file\n"), program_name);
+	fprintf(stderr, _("       %s -ra  [  -cfnp  ] [ -o src_offset ] "
+			  "[ -O dest_offset ] src_fs [ dest_fs ]\n"),
+		program_name);
+	exit (1);
+}
+
+static ext2_loff_t seek_relative(int fd, int offset)
+{
+	ext2_loff_t ret = ext2fs_llseek(fd, offset, SEEK_CUR);
+	if (ret < 0) {
+		perror("seek_relative");
+		exit(1);
+	}
+	return ret;
+}
+
+static ext2_loff_t seek_set(int fd, ext2_loff_t offset)
+{
+	ext2_loff_t ret = ext2fs_llseek(fd, offset, SEEK_SET);
+	if (ret < 0) {
+		perror("seek_set");
+		exit(1);
+	}
+	return ret;
+}
+
+/*
+ * Returns true if the block we are about to write is identical to
+ * what is already on the disk.
+ */
+static int check_block(int fd, void *buf, void *cbuf, int blocksize)
+{
+	char *cp = cbuf;
+	int count = blocksize, ret;
+
+	if (cbuf == NULL)
+		return 0;
+
+	while (count > 0) {
+		ret = read(fd, cp, count);
+		if (ret < 0) {
+			perror("check_block");
+			exit(1);
+		}
+		count -= ret;
+		cp += ret;
+	}
+	ret = memcmp(buf, cbuf, blocksize);
+	seek_relative(fd, -blocksize);
+	return (ret == 0) ? 1 : 0;
+}
+
+static void generic_write(int fd, void *buf, int blocksize, blk64_t block)
+{
+	int count, free_buf = 0;
+	errcode_t err;
+
+	if (!blocksize)
+		return;
+
+	if (!buf) {
+		free_buf = 1;
+		err = ext2fs_get_arrayzero(1, blocksize, &buf);
+		if (err) {
+			com_err(program_name, err,
+				_("while allocating buffer"));
+			exit(1);
+		}
+	}
+	if (nop_flag) {
+		printf(_("Writing block %llu\n"), (unsigned long long) block);
+		if (fd != 1)
+			seek_relative(fd, blocksize);
+		return;
+	}
+	count = write(fd, buf, blocksize);
+	if (count != blocksize) {
+		if (count == -1)
+			err = errno;
+		else
+			err = 0;
+
+		if (block)
+			com_err(program_name, err,
+				_("error writing block %llu"), block);
+		else
+			com_err(program_name, err, _("error in write()"));
+
+		exit(1);
+	}
+	if (free_buf)
+		ext2fs_free_mem(&buf);
+}
+
+static void write_header(int fd, void *hdr, int hdr_size, int wrt_size)
+{
+	char *header_buf;
+	int ret;
+
+	/* Sanity check */
+	if (hdr_size > wrt_size) {
+		fprintf(stderr, "%s",
+			_("Error: header size is bigger than wrt_size\n"));
+	}
+
+	ret = ext2fs_get_mem(wrt_size, &header_buf);
+	if (ret) {
+		fputs(_("Couldn't allocate header buffer\n"), stderr);
+		exit(1);
+	}
+
+	seek_set(fd, 0);
+	memset(header_buf, 0, wrt_size);
+
+	if (hdr)
+		memcpy(header_buf, hdr, hdr_size);
+
+	generic_write(fd, header_buf, wrt_size, NO_BLK);
+
+	ext2fs_free_mem(&header_buf);
+}
+
+static void write_image_file(ext2_filsys fs, int fd)
+{
+	struct ext2_image_hdr	hdr;
+	struct stat		st;
+	errcode_t		retval;
+
+	write_header(fd, NULL, sizeof(struct ext2_image_hdr), fs->blocksize);
+	memset(&hdr, 0, sizeof(struct ext2_image_hdr));
+
+	hdr.offset_super = seek_relative(fd, 0);
+	retval = ext2fs_image_super_write(fs, fd, 0);
+	if (retval) {
+		com_err(program_name, retval, "%s",
+			_("while writing superblock"));
+		exit(1);
+	}
+
+	hdr.offset_inode = seek_relative(fd, 0);
+	retval = ext2fs_image_inode_write(fs, fd,
+				  (fd != 1) ? IMAGER_FLAG_SPARSEWRITE : 0);
+	if (retval) {
+		com_err(program_name, retval, "%s",
+			_("while writing inode table"));
+		exit(1);
+	}
+
+	hdr.offset_blockmap = seek_relative(fd, 0);
+	retval = ext2fs_image_bitmap_write(fs, fd, 0);
+	if (retval) {
+		com_err(program_name, retval, "%s",
+			_("while writing block bitmap"));
+		exit(1);
+	}
+
+	hdr.offset_inodemap = seek_relative(fd, 0);
+	retval = ext2fs_image_bitmap_write(fs, fd, IMAGER_FLAG_INODEMAP);
+	if (retval) {
+		com_err(program_name, retval, "%s",
+			_("while writing inode bitmap"));
+		exit(1);
+	}
+
+	hdr.magic_number = EXT2_ET_MAGIC_E2IMAGE;
+	strcpy(hdr.magic_descriptor, "Ext2 Image 1.0");
+	gethostname(hdr.fs_hostname, sizeof(hdr.fs_hostname));
+	strncpy(hdr.fs_device_name, device_name, sizeof(hdr.fs_device_name)-1);
+	hdr.fs_device_name[sizeof(hdr.fs_device_name) - 1] = 0;
+	hdr.fs_blocksize = fs->blocksize;
+
+	if (stat(device_name, &st) == 0)
+		hdr.fs_device = st.st_rdev;
+
+	if (fstat(fd, &st) == 0) {
+		hdr.image_device = st.st_dev;
+		hdr.image_inode = st.st_ino;
+	}
+	memcpy(hdr.fs_uuid, fs->super->s_uuid, sizeof(hdr.fs_uuid));
+
+	hdr.image_time = time(0);
+	write_header(fd, &hdr, sizeof(struct ext2_image_hdr), fs->blocksize);
+}
+
+/*
+ * These set of functions are used to write a RAW image file.
+ */
+static ext2fs_block_bitmap meta_block_map;
+static ext2fs_block_bitmap scramble_block_map;	/* Directory blocks to be scrambled */
+static blk64_t meta_blocks_count;
+
+struct process_block_struct {
+	ext2_ino_t	ino;
+	int		is_dir;
+};
+
+/*
+ * These subroutines short circuits ext2fs_get_blocks and
+ * ext2fs_check_directory; we use them since we already have the inode
+ * structure, so there's no point in letting the ext2fs library read
+ * the inode again.
+ */
+static ino_t stashed_ino = 0;
+static struct ext2_inode *stashed_inode;
+
+static errcode_t meta_get_blocks(ext2_filsys fs EXT2FS_ATTR((unused)),
+				 ext2_ino_t ino,
+				 blk_t *blocks)
+{
+	int	i;
+
+	if ((ino != stashed_ino) || !stashed_inode)
+		return EXT2_ET_CALLBACK_NOTHANDLED;
+
+	for (i=0; i < EXT2_N_BLOCKS; i++)
+		blocks[i] = stashed_inode->i_block[i];
+	return 0;
+}
+
+static errcode_t meta_check_directory(ext2_filsys fs EXT2FS_ATTR((unused)),
+				      ext2_ino_t ino)
+{
+	if ((ino != stashed_ino) || !stashed_inode)
+		return EXT2_ET_CALLBACK_NOTHANDLED;
+
+	if (!LINUX_S_ISDIR(stashed_inode->i_mode))
+		return EXT2_ET_NO_DIRECTORY;
+	return 0;
+}
+
+static errcode_t meta_read_inode(ext2_filsys fs EXT2FS_ATTR((unused)),
+				 ext2_ino_t ino,
+				 struct ext2_inode *inode)
+{
+	if ((ino != stashed_ino) || !stashed_inode)
+		return EXT2_ET_CALLBACK_NOTHANDLED;
+	*inode = *stashed_inode;
+	return 0;
+}
+
+static void use_inode_shortcuts(ext2_filsys fs, int use_shortcuts)
+{
+	if (use_shortcuts) {
+		fs->get_blocks = meta_get_blocks;
+		fs->check_directory = meta_check_directory;
+		fs->read_inode = meta_read_inode;
+		stashed_ino = 0;
+	} else {
+		fs->get_blocks = 0;
+		fs->check_directory = 0;
+		fs->read_inode = 0;
+	}
+}
+
+static int process_dir_block(ext2_filsys fs EXT2FS_ATTR((unused)),
+			     blk64_t *block_nr,
+			     e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)),
+			     blk64_t ref_block EXT2FS_ATTR((unused)),
+			     int ref_offset EXT2FS_ATTR((unused)),
+			     void *priv_data EXT2FS_ATTR((unused)))
+{
+	struct process_block_struct *p;
+
+	p = (struct process_block_struct *) priv_data;
+
+	ext2fs_mark_block_bitmap2(meta_block_map, *block_nr);
+	meta_blocks_count++;
+	if (scramble_block_map && p->is_dir && blockcnt >= 0)
+		ext2fs_mark_block_bitmap2(scramble_block_map, *block_nr);
+	return 0;
+}
+
+static int process_file_block(ext2_filsys fs EXT2FS_ATTR((unused)),
+			      blk64_t *block_nr,
+			      e2_blkcnt_t blockcnt,
+			      blk64_t ref_block EXT2FS_ATTR((unused)),
+			      int ref_offset EXT2FS_ATTR((unused)),
+			      void *priv_data EXT2FS_ATTR((unused)))
+{
+	if (blockcnt < 0 || all_data) {
+		ext2fs_mark_block_bitmap2(meta_block_map, *block_nr);
+		meta_blocks_count++;
+	}
+	return 0;
+}
+
+static void mark_table_blocks(ext2_filsys fs)
+{
+	blk64_t	first_block, b;
+	unsigned int	i,j;
+
+	first_block = fs->super->s_first_data_block;
+	/*
+	 * Mark primary superblock
+	 */
+	ext2fs_mark_block_bitmap2(meta_block_map, first_block);
+	meta_blocks_count++;
+
+	/*
+	 * Mark the primary superblock descriptors
+	 */
+	for (j = 0; j < fs->desc_blocks; j++) {
+		ext2fs_mark_block_bitmap2(meta_block_map,
+			 ext2fs_descriptor_block_loc2(fs, first_block, j));
+	}
+	meta_blocks_count += fs->desc_blocks;
+
+	for (i = 0; i < fs->group_desc_count; i++) {
+		/*
+		 * Mark the blocks used for the inode table
+		 */
+		if ((output_is_blk ||
+		     !ext2fs_bg_flags_test(fs, i, EXT2_BG_INODE_UNINIT)) &&
+		    ext2fs_inode_table_loc(fs, i)) {
+			unsigned int end = (unsigned) fs->inode_blocks_per_group;
+			/* skip unused blocks */
+			if (!output_is_blk &&
+			    EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
+						       EXT4_FEATURE_RO_COMPAT_GDT_CSUM))
+				end -= (ext2fs_bg_itable_unused(fs, i) /
+					EXT2_INODES_PER_BLOCK(fs->super));
+			for (j = 0, b = ext2fs_inode_table_loc(fs, i);
+			     j < end;
+			     j++, b++) {
+				ext2fs_mark_block_bitmap2(meta_block_map, b);
+				meta_blocks_count++;
+			}
+		}
+
+		/*
+		 * Mark block used for the block bitmap
+		 */
+		if (!ext2fs_bg_flags_test(fs, i, EXT2_BG_BLOCK_UNINIT) &&
+		    ext2fs_block_bitmap_loc(fs, i)) {
+			ext2fs_mark_block_bitmap2(meta_block_map,
+				     ext2fs_block_bitmap_loc(fs, i));
+			meta_blocks_count++;
+		}
+
+		/*
+		 * Mark block used for the inode bitmap
+		 */
+		if (!ext2fs_bg_flags_test(fs, i, EXT2_BG_INODE_UNINIT) &&
+		    ext2fs_inode_bitmap_loc(fs, i)) {
+			ext2fs_mark_block_bitmap2(meta_block_map,
+				 ext2fs_inode_bitmap_loc(fs, i));
+			meta_blocks_count++;
+		}
+	}
+}
+
+/*
+ * This function returns 1 if the specified block is all zeros
+ */
+static int check_zero_block(char *buf, int blocksize)
+{
+	char	*cp = buf;
+	int	left = blocksize;
+
+	if (output_is_blk)
+		return 0;
+	while (left > 0) {
+		if (*cp++)
+			return 0;
+		left--;
+	}
+	return 1;
+}
+
+static int name_id[256];
+
+#define EXT4_MAX_REC_LEN		((1<<16)-1)
+
+static void scramble_dir_block(ext2_filsys fs, blk64_t blk, char *buf)
+{
+	char *p, *end, *cp;
+	struct ext2_dir_entry_2 *dirent;
+	unsigned int rec_len;
+	int id, len;
+
+	end = buf + fs->blocksize;
+	for (p = buf; p < end-8; p += rec_len) {
+		dirent = (struct ext2_dir_entry_2 *) p;
+		rec_len = dirent->rec_len;
+#ifdef WORDS_BIGENDIAN
+		rec_len = ext2fs_swab16(rec_len);
+#endif
+		if (rec_len == EXT4_MAX_REC_LEN || rec_len == 0)
+			rec_len = fs->blocksize;
+		else 
+			rec_len = (rec_len & 65532) | ((rec_len & 3) << 16);
+#if 0
+		printf("rec_len = %d, name_len = %d\n", rec_len, dirent->name_len);
+#endif
+		if (rec_len < 8 || (rec_len % 4) ||
+		    (p+rec_len > end)) {
+			printf(_("Corrupt directory block %llu: "
+				 "bad rec_len (%d)\n"),
+			       (unsigned long long) blk, rec_len);
+			rec_len = end - p;
+			(void) ext2fs_set_rec_len(fs, rec_len,
+					(struct ext2_dir_entry *) dirent);
+#ifdef WORDS_BIGENDIAN
+			dirent->rec_len = ext2fs_swab16(dirent->rec_len);
+#endif
+			continue;
+		}
+		if (dirent->name_len + 8U > rec_len) {
+			printf(_("Corrupt directory block %llu: "
+				 "bad name_len (%d)\n"),
+			       (unsigned long long) blk, dirent->name_len);
+			dirent->name_len = rec_len - 8;
+			continue;
+		}
+		cp = p+8;
+		len = rec_len - dirent->name_len - 8;
+		if (len > 0)
+			memset(cp+dirent->name_len, 0, len);
+		if (dirent->name_len==1 && cp[0] == '.')
+			continue;
+		if (dirent->name_len==2 && cp[0] == '.' && cp[1] == '.')
+			continue;
+
+		memset(cp, 'A', dirent->name_len);
+		len = dirent->name_len;
+		id = name_id[len]++;
+		while ((len > 0) && (id > 0)) {
+			*cp += id % 26;
+			id = id / 26;
+			cp++;
+			len--;
+		}
+	}
+}
+
+static char got_sigint;
+
+static void sigint_handler(int unused EXT2FS_ATTR((unused)))
+{
+	got_sigint = 1;
+	signal (SIGINT, SIG_DFL);
+}
+
+#define calc_percent(a, b) ((int) ((100.0 * (((float) (a)) / \
+					     ((float) (b)))) + 0.5))
+#define calc_rate(t, b, d) (((float)(t) / ((1024 * 1024) / (b))) / (d))
+
+static int print_progress(blk64_t num, blk64_t total)
+{
+	return fprintf(stderr, _("%llu / %llu blocks (%d%%)"), num, total,
+		      calc_percent(num, total));
+}
+
+static void output_meta_data_blocks(ext2_filsys fs, int fd, int flags)
+{
+	errcode_t	retval;
+	blk64_t		blk;
+	char		*buf, *zero_buf;
+	int		sparse = 0;
+	blk64_t		start = 0;
+	blk64_t		distance = 0;
+	blk64_t		end = ext2fs_blocks_count(fs->super);
+	time_t		last_update = 0;
+	time_t		start_time = 0;
+	blk64_t		total_written = 0;
+	int		bscount = 0;
+
+	retval = ext2fs_get_mem(fs->blocksize, &buf);
+	if (retval) {
+		com_err(program_name, retval, _("while allocating buffer"));
+		exit(1);
+	}
+	retval = ext2fs_get_memzero(fs->blocksize, &zero_buf);
+	if (retval) {
+		com_err(program_name, retval, _("while allocating buffer"));
+		exit(1);
+	}
+	if (show_progress) {
+		fprintf(stderr, _("Copying "));
+		bscount = print_progress(total_written, meta_blocks_count);
+		fflush(stderr);
+		last_update = time(NULL);
+		start_time = time(NULL);
+	}
+	/* when doing an in place move to the right, you can't start
+	   at the beginning or you will overwrite data, so instead
+	   divide the fs up into distance size chunks and write them
+	   in reverse. */
+	if (move_mode && dest_offset > source_offset) {
+		distance = (dest_offset - source_offset) / fs->blocksize;
+		if (distance < ext2fs_blocks_count(fs->super))
+			start = ext2fs_blocks_count(fs->super) - distance;
+	}
+	if (move_mode)
+		signal (SIGINT, sigint_handler);
+more_blocks:
+	if (distance)
+		seek_set(fd, (start * fs->blocksize) + dest_offset);
+	for (blk = start; blk < end; blk++) {
+		if (got_sigint) {
+			if (distance) {
+				/* moving to the right */
+				if (distance >= ext2fs_blocks_count(fs->super) ||
+				    start == ext2fs_blocks_count(fs->super) - distance)
+					kill (getpid(), SIGINT);
+			} else {
+				/* moving to the left */
+				if (blk < (source_offset - dest_offset) / fs->blocksize)
+					kill (getpid(), SIGINT);
+			}
+			if (show_progress)
+				fputc('\r', stderr);
+			fprintf(stderr,
+				_("Stopping now will destroy the filesystem, "
+				 "interrupt again if you are sure\n"));
+			if (show_progress) {
+				fprintf(stderr, _("Copying "));
+				bscount = print_progress(total_written,
+							 meta_blocks_count);
+				fflush(stderr);
+			}
+
+			got_sigint = 0;
+		}
+		if (show_progress && last_update != time(NULL)) {
+			time_t duration;
+			last_update = time(NULL);
+			while (bscount--)
+				fputc('\b', stderr);
+			bscount = print_progress(total_written,
+						 meta_blocks_count);
+			duration = time(NULL) - start_time;
+			if (duration > 5) {
+				time_t est = (duration * meta_blocks_count /
+					      total_written) - duration;
+				char buff[30];
+				strftime(buff, 30, "%T", gmtime(&est));
+				bscount += fprintf(stderr,
+						   _(" %s remaining at %.2f MB/s"),
+						   buff, calc_rate(total_written,
+								   fs->blocksize,
+								   duration));
+			}
+			fflush (stderr);
+		}
+		if ((blk >= fs->super->s_first_data_block) &&
+		    ext2fs_test_block_bitmap2(meta_block_map, blk)) {
+			retval = io_channel_read_blk64(fs->io, blk, 1, buf);
+			if (retval) {
+				com_err(program_name, retval,
+					_("error reading block %llu"), blk);
+			}
+			total_written++;
+			if (scramble_block_map &&
+			    ext2fs_test_block_bitmap2(scramble_block_map, blk))
+				scramble_dir_block(fs, blk, buf);
+			if ((flags & E2IMAGE_CHECK_ZERO_FLAG) &&
+			    check_zero_block(buf, fs->blocksize))
+				goto sparse_write;
+			if (sparse)
+				seek_relative(fd, sparse);
+			sparse = 0;
+			if (check_block(fd, buf, check_buf, fs->blocksize)) {
+				seek_relative(fd, fs->blocksize);
+				skipped_blocks++;
+			} else
+				generic_write(fd, buf, fs->blocksize, blk);
+		} else {
+		sparse_write:
+			if (fd == 1) {
+				if (!nop_flag)
+					generic_write(fd, zero_buf,
+						      fs->blocksize, blk);
+				continue;
+			}
+			sparse += fs->blocksize;
+			if (sparse > 1024*1024) {
+				seek_relative(fd, 1024*1024);
+				sparse -= 1024*1024;
+			}
+		}
+	}
+	if (distance && start) {
+		if (start < distance) {
+			end = start;
+			start = 0;
+		} else {
+			end -= distance;
+			start -= distance;
+			if (end < distance) {
+				/* past overlap, do rest in one go */
+				end = start;
+				start = 0;
+			}
+		}
+		sparse = 0;
+		goto more_blocks;
+	}
+	signal (SIGINT, SIG_DFL);
+	if (show_progress) {
+		time_t duration = time(NULL) - start_time;
+		char buff[30];
+		while (bscount--)
+			fputc('\b', stderr);
+		strftime(buff, 30, "%T", gmtime(&duration));
+		fprintf(stderr, _("\b\b\b\b\b\b\b\bCopied %llu / %llu "
+			 "blocks (%llu%%) in %s at %.2f MB/s       \n"),
+		       total_written, meta_blocks_count,
+		       calc_percent(total_written, meta_blocks_count), buff,
+		       calc_rate(total_written, fs->blocksize, duration));
+	}
+#ifdef HAVE_FTRUNCATE64
+	if (sparse) {
+		ext2_loff_t offset;
+		if (distance)
+			offset = seek_set(fd,
+					  fs->blocksize * ext2fs_blocks_count(fs->super) + dest_offset);
+		else
+			offset = seek_relative(fd, sparse);
+
+		if (ftruncate64(fd, offset) < 0) {
+			seek_relative(fd, -1);
+			generic_write(fd, zero_buf, 1, NO_BLK);
+		}
+	}
+#else
+	if (sparse && !distance) {
+		seek_relative(fd, sparse-1);
+		generic_write(fd, zero_buf, 1, NO_BLK);
+	}
+#endif
+	ext2fs_free_mem(&zero_buf);
+	ext2fs_free_mem(&buf);
+}
+
+static void init_l1_table(struct ext2_qcow2_image *image)
+{
+	__u64 *l1_table;
+	errcode_t ret;
+
+	ret = ext2fs_get_arrayzero(image->l1_size, sizeof(__u64), &l1_table);
+	if (ret) {
+		com_err(program_name, ret, _("while allocating l1 table"));
+		exit(1);
+	}
+
+	image->l1_table = l1_table;
+}
+
+static void init_l2_cache(struct ext2_qcow2_image *image)
+{
+	unsigned int count, i;
+	struct ext2_qcow2_l2_cache *cache;
+	struct ext2_qcow2_l2_table *table;
+	errcode_t ret;
+
+	ret = ext2fs_get_arrayzero(1, sizeof(struct ext2_qcow2_l2_cache),
+				   &cache);
+	if (ret)
+		goto alloc_err;
+
+	count = (image->l1_size > L2_CACHE_PREALLOC) ? L2_CACHE_PREALLOC :
+		 image->l1_size;
+
+	cache->count = count;
+	cache->free = count;
+	cache->next_offset = image->l2_offset;
+
+	for (i = 0; i < count; i++) {
+		ret = ext2fs_get_arrayzero(1,
+				sizeof(struct ext2_qcow2_l2_table), &table);
+		if (ret)
+			goto alloc_err;
+
+		ret = ext2fs_get_arrayzero(image->l2_size,
+						   sizeof(__u64), &table->data);
+		if (ret)
+			goto alloc_err;
+
+		table->next = cache->free_head;
+		cache->free_head = table;
+	}
+
+	image->l2_cache = cache;
+	return;
+
+alloc_err:
+	com_err(program_name, ret, _("while allocating l2 cache"));
+	exit(1);
+}
+
+static void put_l2_cache(struct ext2_qcow2_image *image)
+{
+	struct ext2_qcow2_l2_cache *cache = image->l2_cache;
+	struct ext2_qcow2_l2_table *tmp, *table;
+
+	if (!cache)
+		return;
+
+	table = cache->free_head;
+	cache->free_head = NULL;
+again:
+	while (table) {
+		tmp = table;
+		table = table->next;
+		ext2fs_free_mem(&tmp->data);
+		ext2fs_free_mem(&tmp);
+	}
+
+	if (cache->free != cache->count) {
+		fprintf(stderr, _("Warning: There are still tables in the "
+				  "cache while putting the cache, data will "
+				  "be lost so the image may not be valid.\n"));
+		table = cache->used_head;
+		cache->used_head = NULL;
+		goto again;
+	}
+
+	ext2fs_free_mem(&cache);
+}
+
+static int init_refcount(struct ext2_qcow2_image *img, blk64_t table_offset)
+{
+	struct	ext2_qcow2_refcount	*ref;
+	blk64_t table_clusters;
+	errcode_t ret;
+
+	ref = &(img->refcount);
+
+	/*
+	 * One refcount block addresses 2048 clusters, one refcount table
+	 * addresses cluster/sizeof(__u64) refcount blocks, and we need
+	 * to address meta_blocks_count clusters + qcow2 metadata clusters
+	 * in the worst case.
+	 */
+	table_clusters = meta_blocks_count + (table_offset >>
+					      img->cluster_bits);
+	table_clusters >>= (img->cluster_bits + 6 - 1);
+	table_clusters = (table_clusters == 0) ? 1 : table_clusters;
+
+	ref->refcount_table_offset = table_offset;
+	ref->refcount_table_clusters = table_clusters;
+	ref->refcount_table_index = 0;
+	ref->refcount_block_index = 0;
+
+	/* Allocate refcount table */
+	ret = ext2fs_get_arrayzero(ref->refcount_table_clusters,
+				   img->cluster_size, &ref->refcount_table);
+	if (ret)
+		return ret;
+
+	/* Allocate refcount block */
+	ret = ext2fs_get_arrayzero(1, img->cluster_size, &ref->refcount_block);
+	if (ret)
+		ext2fs_free_mem(&ref->refcount_table);
+
+	return ret;
+}
+
+static int initialize_qcow2_image(int fd, ext2_filsys fs,
+			    struct ext2_qcow2_image *image)
+{
+	struct ext2_qcow2_hdr *header;
+	blk64_t total_size, offset;
+	int shift, l2_bits, header_size, l1_size, ret;
+	int cluster_bits = get_bits_from_size(fs->blocksize);
+	struct ext2_super_block *sb = fs->super;
+
+	/* Allocate header */
+	ret = ext2fs_get_memzero(sizeof(struct ext2_qcow2_hdr), &header);
+	if (ret)
+		return ret;
+
+	total_size = ext2fs_blocks_count(sb) << cluster_bits;
+	image->cluster_size = fs->blocksize;
+	image->l2_size = 1 << (cluster_bits - 3);
+	image->cluster_bits = cluster_bits;
+	image->fd = fd;
+
+	header->magic = ext2fs_cpu_to_be32(QCOW_MAGIC);
+	header->version = ext2fs_cpu_to_be32(QCOW_VERSION);
+	header->size = ext2fs_cpu_to_be64(total_size);
+	header->cluster_bits = ext2fs_cpu_to_be32(cluster_bits);
+
+	header_size = (sizeof(struct ext2_qcow2_hdr) + 7) & ~7;
+	offset = align_offset(header_size, image->cluster_size);
+
+	header->l1_table_offset = ext2fs_cpu_to_be64(offset);
+	image->l1_offset = offset;
+
+	l2_bits = cluster_bits - 3;
+	shift = cluster_bits + l2_bits;
+	l1_size = ((total_size + (1LL << shift) - 1) >> shift);
+	header->l1_size = ext2fs_cpu_to_be32(l1_size);
+	image->l1_size = l1_size;
+
+	/* Make space for L1 table */
+	offset += align_offset(l1_size * sizeof(blk64_t), image->cluster_size);
+
+	/* Initialize refcounting */
+	ret = init_refcount(image, offset);
+	if (ret) {
+		ext2fs_free_mem(&header);
+		return ret;
+	}
+	header->refcount_table_offset = ext2fs_cpu_to_be64(offset);
+	header->refcount_table_clusters =
+		ext2fs_cpu_to_be32(image->refcount.refcount_table_clusters);
+	offset += image->cluster_size;
+	offset += image->refcount.refcount_table_clusters <<
+		image->cluster_bits;
+
+	/* Make space for L2 tables */
+	image->l2_offset = offset;
+	offset += image->cluster_size;
+
+	/* Make space for first refcount block */
+	image->refcount.refcount_block_offset = offset;
+
+	image->hdr = header;
+	/* Initialize l1 and l2 tables */
+	init_l1_table(image);
+	init_l2_cache(image);
+
+	return 0;
+}
+
+static void free_qcow2_image(struct ext2_qcow2_image *img)
+{
+	if (!img)
+		return;
+
+	if (img->hdr)
+		ext2fs_free_mem(&img->hdr);
+
+	if (img->l1_table)
+		ext2fs_free_mem(&img->l1_table);
+
+	if (img->refcount.refcount_table)
+		ext2fs_free_mem(&img->refcount.refcount_table);
+	if (img->refcount.refcount_block)
+		ext2fs_free_mem(&img->refcount.refcount_block);
+
+	put_l2_cache(img);
+
+	ext2fs_free_mem(&img);
+}
+
+/**
+ * Put table from used list (used_head) into free list (free_head).
+ * l2_table is used to return pointer to the next used table (used_head).
+ */
+static void put_used_table(struct ext2_qcow2_image *img,
+			  struct ext2_qcow2_l2_table **l2_table)
+{
+	struct ext2_qcow2_l2_cache *cache = img->l2_cache;
+	struct ext2_qcow2_l2_table *table;
+
+	table = cache->used_head;
+	cache->used_head = table->next;
+
+	assert(table);
+	if (!table->next)
+		cache->used_tail = NULL;
+
+	/* Clean the table for case we will need to use it again */
+	memset(table->data, 0, img->cluster_size);
+	table->next = cache->free_head;
+	cache->free_head = table;
+
+	cache->free++;
+
+	*l2_table = cache->used_head;
+}
+
+static void flush_l2_cache(struct ext2_qcow2_image *image)
+{
+	blk64_t seek = 0;
+	ext2_loff_t offset;
+	struct ext2_qcow2_l2_cache *cache = image->l2_cache;
+	struct ext2_qcow2_l2_table *table = cache->used_head;
+	int fd = image->fd;
+
+	/* Store current position */
+	offset = seek_relative(fd, 0);
+
+	assert(table);
+	while (cache->free < cache->count) {
+		if (seek != table->offset) {
+			seek_set(fd, table->offset);
+			seek = table->offset;
+		}
+
+		generic_write(fd, (char *)table->data, image->cluster_size,
+			      NO_BLK);
+		put_used_table(image, &table);
+		seek += image->cluster_size;
+	}
+
+	/* Restore previous position */
+	seek_set(fd, offset);
+}
+
+/**
+ * Get first free table (from free_head) and put it into tail of used list
+ * (to used_tail).
+ * l2_table is used to return pointer to moved table.
+ * Returns 1 if the cache is full, 0 otherwise.
+ */
+static void get_free_table(struct ext2_qcow2_image *image,
+			  struct ext2_qcow2_l2_table **l2_table)
+{
+	struct ext2_qcow2_l2_table *table;
+	struct ext2_qcow2_l2_cache *cache = image->l2_cache;
+
+	if (0 == cache->free)
+		flush_l2_cache(image);
+
+	table = cache->free_head;
+	assert(table);
+	cache->free_head = table->next;
+
+	if (cache->used_tail)
+		cache->used_tail->next = table;
+	else
+		/* First item in the used list */
+		cache->used_head = table;
+
+	cache->used_tail = table;
+	cache->free--;
+
+	*l2_table = table;
+}
+
+static int add_l2_item(struct ext2_qcow2_image *img, blk64_t blk,
+		       blk64_t data, blk64_t next)
+{
+	struct ext2_qcow2_l2_cache *cache = img->l2_cache;
+	struct ext2_qcow2_l2_table *table = cache->used_tail;
+	blk64_t l1_index = blk / img->l2_size;
+	blk64_t l2_index = blk & (img->l2_size - 1);
+	int ret = 0;
+
+	/*
+	 * Need to create new table if it does not exist,
+	 * or if it is full
+	 */
+	if (!table || (table->l1_index != l1_index)) {
+		get_free_table(img, &table);
+		table->l1_index = l1_index;
+		table->offset = cache->next_offset;
+		cache->next_offset = next;
+		img->l1_table[l1_index] =
+			ext2fs_cpu_to_be64(table->offset | QCOW_OFLAG_COPIED);
+		ret++;
+	}
+
+	table->data[l2_index] = ext2fs_cpu_to_be64(data | QCOW_OFLAG_COPIED);
+	return ret;
+}
+
+static int update_refcount(int fd, struct ext2_qcow2_image *img,
+			   blk64_t offset, blk64_t rfblk_pos)
+{
+	struct	ext2_qcow2_refcount	*ref;
+	__u32	table_index;
+	int ret = 0;
+
+	ref = &(img->refcount);
+	table_index = offset >> (2 * img->cluster_bits - 1);
+
+	/*
+	 * Need to create new refcount block when the offset addresses
+	 * another item in the refcount table
+	 */
+	if (table_index != ref->refcount_table_index) {
+
+		seek_set(fd, ref->refcount_block_offset);
+
+		generic_write(fd, (char *)ref->refcount_block,
+			      img->cluster_size, NO_BLK);
+		memset(ref->refcount_block, 0, img->cluster_size);
+
+		ref->refcount_table[ref->refcount_table_index] =
+			ext2fs_cpu_to_be64(ref->refcount_block_offset);
+		ref->refcount_block_offset = rfblk_pos;
+		ref->refcount_block_index = 0;
+		ref->refcount_table_index = table_index;
+		ret++;
+	}
+
+	/*
+	 * We are relying on the fact that we are creating the qcow2
+	 * image sequentially, hence we will always allocate refcount
+	 * block items sequentialy.
+	 */
+	ref->refcount_block[ref->refcount_block_index] = ext2fs_cpu_to_be16(1);
+	ref->refcount_block_index++;
+	return ret;
+}
+
+static int sync_refcount(int fd, struct ext2_qcow2_image *img)
+{
+	struct	ext2_qcow2_refcount	*ref;
+
+	ref = &(img->refcount);
+
+	ref->refcount_table[ref->refcount_table_index] =
+		ext2fs_cpu_to_be64(ref->refcount_block_offset);
+	seek_set(fd, ref->refcount_table_offset);
+	generic_write(fd, (char *)ref->refcount_table,
+		ref->refcount_table_clusters << img->cluster_bits, NO_BLK);
+
+	seek_set(fd, ref->refcount_block_offset);
+	generic_write(fd, (char *)ref->refcount_block, img->cluster_size,
+		      NO_BLK);
+	return 0;
+}
+
+static void output_qcow2_meta_data_blocks(ext2_filsys fs, int fd)
+{
+	errcode_t		retval;
+	blk64_t			blk, offset, size, end;
+	char			*buf;
+	struct ext2_qcow2_image	*img;
+	unsigned int		header_size;
+
+	/* allocate  struct ext2_qcow2_image */
+	retval = ext2fs_get_mem(sizeof(struct ext2_qcow2_image), &img);
+	if (retval) {
+		com_err(program_name, retval,
+			_("while allocating ext2_qcow2_image"));
+		exit(1);
+	}
+
+	retval = initialize_qcow2_image(fd, fs, img);
+	if (retval) {
+		com_err(program_name, retval,
+			_("while initializing ext2_qcow2_image"));
+		exit(1);
+	}
+	header_size = align_offset(sizeof(struct ext2_qcow2_hdr),
+				   img->cluster_size);
+	write_header(fd, img->hdr, sizeof(struct ext2_qcow2_hdr), header_size);
+
+	/* Refcount all qcow2 related metadata up to refcount_block_offset */
+	end = img->refcount.refcount_block_offset;
+	seek_set(fd, end);
+	blk = end + img->cluster_size;
+	for (offset = 0; offset <= end; offset += img->cluster_size) {
+		if (update_refcount(fd, img, offset, blk)) {
+			blk += img->cluster_size;
+			/*
+			 * If we create new refcount block, we need to refcount
+			 * it as well.
+			 */
+			end += img->cluster_size;
+		}
+	}
+	seek_set(fd, offset);
+
+	retval = ext2fs_get_mem(fs->blocksize, &buf);
+	if (retval) {
+		com_err(program_name, retval, _("while allocating buffer"));
+		exit(1);
+	}
+	/* Write qcow2 data blocks */
+	for (blk = 0; blk < ext2fs_blocks_count(fs->super); blk++) {
+		if ((blk >= fs->super->s_first_data_block) &&
+		    ext2fs_test_block_bitmap2(meta_block_map, blk)) {
+			retval = io_channel_read_blk64(fs->io, blk, 1, buf);
+			if (retval) {
+				com_err(program_name, retval,
+					_("error reading block %llu"), blk);
+				continue;
+			}
+			if (scramble_block_map &&
+			    ext2fs_test_block_bitmap2(scramble_block_map, blk))
+				scramble_dir_block(fs, blk, buf);
+			if (check_zero_block(buf, fs->blocksize))
+				continue;
+
+			if (update_refcount(fd, img, offset, offset)) {
+				/* Make space for another refcount block */
+				offset += img->cluster_size;
+				seek_set(fd, offset);
+				/*
+				 * We have created the new refcount block, this
+				 * means that we need to refcount it as well.
+				 * So the previous update_refcount refcounted
+				 * the block itself and now we are going to
+				 * create refcount for data. New refcount
+				 * block should not be created!
+				 */
+				if (update_refcount(fd, img, offset, offset)) {
+					fprintf(stderr, _("Programming error: "
+						"multiple sequential refcount "
+						"blocks created!\n"));
+					exit(1);
+				}
+			}
+
+			generic_write(fd, buf, fs->blocksize, blk);
+
+			if (add_l2_item(img, blk, offset,
+					offset + img->cluster_size)) {
+				offset += img->cluster_size;
+				if (update_refcount(fd, img, offset,
+					offset + img->cluster_size)) {
+					offset += img->cluster_size;
+					if (update_refcount(fd, img, offset,
+							    offset)) {
+						fprintf(stderr,
+			_("Programming error: multiple sequential refcount "
+			  "blocks created!\n"));
+						exit(1);
+					}
+				}
+				offset += img->cluster_size;
+				seek_set(fd, offset);
+				continue;
+			}
+
+			offset += img->cluster_size;
+		}
+	}
+	update_refcount(fd, img, offset, offset);
+	flush_l2_cache(img);
+	sync_refcount(fd, img);
+
+	/* Write l1_table*/
+	seek_set(fd, img->l1_offset);
+	size = img->l1_size * sizeof(__u64);
+	generic_write(fd, (char *)img->l1_table, size, NO_BLK);
+
+	ext2fs_free_mem(&buf);
+	free_qcow2_image(img);
+}
+
+static void write_raw_image_file(ext2_filsys fs, int fd, int type, int flags)
+{
+	struct process_block_struct	pb;
+	struct ext2_inode		inode;
+	ext2_inode_scan			scan;
+	ext2_ino_t			ino;
+	errcode_t			retval;
+	char *				block_buf;
+
+	meta_blocks_count = 0;
+	retval = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
+					      &meta_block_map);
+	if (retval) {
+		com_err(program_name, retval,
+			_("while allocating block bitmap"));
+		exit(1);
+	}
+
+	if (flags & E2IMAGE_SCRAMBLE_FLAG) {
+		retval = ext2fs_allocate_block_bitmap(fs, "scramble block map",
+						      &scramble_block_map);
+		if (retval) {
+			com_err(program_name, retval,
+				_("while allocating scramble block bitmap"));
+			exit(1);
+		}
+	}
+
+	mark_table_blocks(fs);
+	if (show_progress)
+		printf(_("Scanning inodes...\n"));
+
+	retval = ext2fs_open_inode_scan(fs, 0, &scan);
+	if (retval) {
+		com_err(program_name, retval,"%s",
+			_("while opening inode scan"));
+		exit(1);
+	}
+
+	retval = ext2fs_get_mem(fs->blocksize * 3, &block_buf);
+	if (retval) {
+		com_err(program_name, 0, "%s",
+			_("Can't allocate block buffer"));
+		exit(1);
+	}
+
+	use_inode_shortcuts(fs, 1);
+	stashed_inode = &inode;
+	while (1) {
+		retval = ext2fs_get_next_inode(scan, &ino, &inode);
+		if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
+			continue;
+		if (retval) {
+			com_err(program_name, retval, "%s",
+				_("while getting next inode"));
+			exit(1);
+		}
+		if (ino == 0)
+			break;
+		if (!inode.i_links_count)
+			continue;
+		if (ext2fs_file_acl_block(fs, &inode)) {
+			ext2fs_mark_block_bitmap2(meta_block_map,
+					ext2fs_file_acl_block(fs, &inode));
+			meta_blocks_count++;
+		}
+		if (!ext2fs_inode_has_valid_blocks2(fs, &inode))
+			continue;
+
+		stashed_ino = ino;
+		pb.ino = ino;
+		pb.is_dir = LINUX_S_ISDIR(inode.i_mode);
+		if (LINUX_S_ISDIR(inode.i_mode) ||
+		    (LINUX_S_ISLNK(inode.i_mode) &&
+		     ext2fs_inode_has_valid_blocks2(fs, &inode)) ||
+		    ino == fs->super->s_journal_inum) {
+			retval = ext2fs_block_iterate3(fs, ino,
+					BLOCK_FLAG_READ_ONLY, block_buf,
+					process_dir_block, &pb);
+			if (retval) {
+				com_err(program_name, retval,
+					_("while iterating over inode %u"),
+					ino);
+				exit(1);
+			}
+		} else {
+			if ((inode.i_flags & EXT4_EXTENTS_FL) ||
+			    inode.i_block[EXT2_IND_BLOCK] ||
+			    inode.i_block[EXT2_DIND_BLOCK] ||
+			    inode.i_block[EXT2_TIND_BLOCK] || all_data) {
+				retval = ext2fs_block_iterate3(fs,
+				       ino, BLOCK_FLAG_READ_ONLY, block_buf,
+				       process_file_block, &pb);
+				if (retval) {
+					com_err(program_name, retval,
+					_("while iterating over inode %u"), ino);
+					exit(1);
+				}
+			}
+		}
+	}
+	use_inode_shortcuts(fs, 0);
+
+	if (type & E2IMAGE_QCOW2)
+		output_qcow2_meta_data_blocks(fs, fd);
+	else
+		output_meta_data_blocks(fs, fd, flags);
+
+	ext2fs_free_mem(&block_buf);
+	ext2fs_close_inode_scan(scan);
+	ext2fs_free_block_bitmap(meta_block_map);
+	if (type & E2IMAGE_SCRAMBLE_FLAG)
+		ext2fs_free_block_bitmap(scramble_block_map);
+}
+
+static void install_image(char *device, char *image_fn, int type)
+{
+	errcode_t retval;
+	ext2_filsys fs;
+	int open_flag = EXT2_FLAG_IMAGE_FILE | EXT2_FLAG_64BITS;
+	int fd = 0;
+	io_manager	io_ptr;
+	io_channel	io;
+
+	if (type) {
+		com_err(program_name, 0, _("Raw and qcow2 images cannot"
+					   "be installed"));
+		exit(1);
+	}
+
+#ifdef CONFIG_TESTIO_DEBUG
+	if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) {
+		io_ptr = test_io_manager;
+		test_io_backing_manager = unix_io_manager;
+	} else
+#endif
+		io_ptr = unix_io_manager;
+
+	retval = ext2fs_open (image_fn, open_flag, 0, 0,
+			      io_ptr, &fs);
+        if (retval) {
+		com_err (program_name, retval, _("while trying to open %s"),
+			 image_fn);
+		exit(1);
+	}
+
+	retval = ext2fs_read_bitmaps (fs);
+	if (retval) {
+		com_err(program_name, retval, _("error reading bitmaps"));
+		exit(1);
+	}
+
+	fd = ext2fs_open_file(image_fn, O_RDONLY, 0);
+	if (fd < 0) {
+		perror(image_fn);
+		exit(1);
+	}
+
+	retval = io_ptr->open(device, IO_FLAG_RW, &io);
+	if (retval) {
+		com_err(device, 0, _("while opening device file"));
+		exit(1);
+	}
+
+	ext2fs_rewrite_to_io(fs, io);
+
+	seek_set(fd, fs->image_header->offset_inode);
+
+	retval = ext2fs_image_inode_read(fs, fd, 0);
+	if (retval) {
+		com_err(image_fn, 0, "while restoring the image table");
+		exit(1);
+	}
+
+	close(fd);
+	ext2fs_close (fs);
+}
+
+static struct ext2_qcow2_hdr *check_qcow2_image(int *fd, char *name)
+{
+
+	*fd = ext2fs_open_file(name, O_RDONLY, 0600);
+	if (*fd < 0)
+		return NULL;
+
+	return qcow2_read_header(*fd);
+}
+
+int main (int argc, char ** argv)
+{
+	int c;
+	errcode_t retval;
+	ext2_filsys fs;
+	char *image_fn, offset_opt[64];
+	struct ext2_qcow2_hdr *header = NULL;
+	int open_flag = EXT2_FLAG_64BITS;
+	int img_type = 0;
+	int flags = 0;
+	int mount_flags = 0;
+	int qcow2_fd = 0;
+	int fd = 0;
+	int ret = 0;
+	int ignore_rw_mount = 0;
+	int check = 0;
+	struct stat st;
+
+#ifdef ENABLE_NLS
+	setlocale(LC_MESSAGES, "");
+	setlocale(LC_CTYPE, "");
+	bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
+	textdomain(NLS_CAT_NAME);
+	set_com_err_gettext(gettext);
+#endif
+	fprintf (stderr, "e2image %s (%s)\n", E2FSPROGS_VERSION,
+		 E2FSPROGS_DATE);
+	if (argc && *argv)
+		program_name = *argv;
+	add_error_table(&et_ext2_error_table);
+	while ((c = getopt(argc, argv, "nrsIQafo:O:pc")) != EOF)
+		switch (c) {
+		case 'I':
+			flags |= E2IMAGE_INSTALL_FLAG;
+			break;
+		case 'Q':
+			if (img_type)
+				usage();
+			img_type |= E2IMAGE_QCOW2;
+			break;
+		case 'r':
+			if (img_type)
+				usage();
+			img_type |= E2IMAGE_RAW;
+			break;
+		case 's':
+			flags |= E2IMAGE_SCRAMBLE_FLAG;
+			break;
+		case 'a':
+			all_data = 1;
+			break;
+		case 'f':
+			ignore_rw_mount = 1;
+			break;
+		case 'n':
+			nop_flag = 1;
+			break;
+		case 'o':
+			source_offset = strtoull(optarg, NULL, 0);
+			break;
+		case 'O':
+			dest_offset = strtoull(optarg, NULL, 0);
+			break;
+		case 'p':
+			show_progress = 1;
+			break;
+		case 'c':
+			check = 1;
+			break;
+		default:
+			usage();
+		}
+	if (optind == argc - 1 &&
+	    (source_offset || dest_offset))
+		    move_mode = 1;
+	else if (optind != argc - 2 )
+		usage();
+
+	if (all_data && !img_type) {
+		com_err(program_name, 0, _("-a option can only be used "
+					   "with raw or QCOW2 images."));
+		exit(1);
+	}
+	if ((source_offset || dest_offset) && img_type != E2IMAGE_RAW) {
+		com_err(program_name, 0,
+			_("Offsets are only allowed with raw images."));
+		exit(1);
+	}
+	if (move_mode && img_type != E2IMAGE_RAW) {
+		com_err(program_name, 0,
+			_("Move mode is only allowed with raw images."));
+		exit(1);
+	}
+	if (move_mode && !all_data) {
+		com_err(program_name, 0,
+			_("Move mode requires all data mode."));
+		exit(1);
+	}
+	device_name = argv[optind];
+	if (move_mode)
+		image_fn = device_name;
+	else image_fn = argv[optind+1];
+
+	retval = ext2fs_check_if_mounted(device_name, &mount_flags);
+	if (retval) {
+		com_err(program_name, retval, _("checking if mounted"));
+		exit(1);
+	}
+
+	if (img_type && !ignore_rw_mount &&
+	    (mount_flags & EXT2_MF_MOUNTED) &&
+	   !(mount_flags & EXT2_MF_READONLY)) {
+		fprintf(stderr, _("\nRunning e2image on a R/W mounted "
+			"filesystem can result in an\n"
+			"inconsistent image which will not be useful "
+			"for debugging purposes.\n"
+			"Use -f option if you really want to do that.\n"));
+		exit(1);
+	}
+
+	if (flags & E2IMAGE_INSTALL_FLAG) {
+		install_image(device_name, image_fn, img_type);
+		exit (0);
+	}
+
+	if (img_type & E2IMAGE_RAW) {
+		header = check_qcow2_image(&qcow2_fd, device_name);
+		if (header) {
+			flags |= E2IMAGE_IS_QCOW2_FLAG;
+			goto skip_device;
+		}
+	}
+	sprintf(offset_opt, "offset=%llu", source_offset);
+	retval = ext2fs_open2(device_name, offset_opt, open_flag, 0, 0,
+			      unix_io_manager, &fs);
+        if (retval) {
+		com_err (program_name, retval, _("while trying to open %s"),
+			 device_name);
+		fputs(_("Couldn't find valid filesystem superblock.\n"), stdout);
+		exit(1);
+	}
+
+skip_device:
+	if (strcmp(image_fn, "-") == 0)
+		fd = 1;
+	else {
+		int o_flags = O_CREAT|O_RDWR;
+
+		if (img_type != E2IMAGE_RAW)
+			o_flags |= O_TRUNC;
+		if (access(image_fn, F_OK) != 0)
+			flags |= E2IMAGE_CHECK_ZERO_FLAG;
+		fd = ext2fs_open_file(image_fn, o_flags, 0600);
+		if (fd < 0) {
+			com_err(program_name, errno,
+				_("while trying to open %s"), image_fn);
+			exit(1);
+		}
+	}
+	if (dest_offset)
+		seek_set(fd, dest_offset);
+
+	if ((img_type & E2IMAGE_QCOW2) && (fd == 1)) {
+		com_err(program_name, 0, _("QCOW2 image can not be written to "
+					   "the stdout!\n"));
+		exit(1);
+	}
+	if (fd != 1) {
+		if (fstat(fd, &st)) {
+			com_err(program_name, 0, "Can not stat output\n");
+			exit(1);
+		}
+		if (S_ISBLK(st.st_mode))
+			output_is_blk = 1;
+	}
+	if (flags & E2IMAGE_IS_QCOW2_FLAG) {
+		ret = qcow2_write_raw_image(qcow2_fd, fd, header);
+		if (ret) {
+			if (ret == -QCOW_COMPRESSED)
+				fprintf(stderr, _("Image (%s) is compressed\n"),
+					image_fn);
+			if (ret == -QCOW_ENCRYPTED)
+				fprintf(stderr, _("Image (%s) is encrypted\n"),
+					image_fn);
+			com_err(program_name, ret,
+				_("while trying to convert qcow2 image"
+				  " (%s) into raw image (%s)"),
+				device_name, image_fn);
+		}
+		goto out;
+	}
+
+	if (check) {
+		if (img_type != E2IMAGE_RAW) {
+			fprintf(stderr, _("The -c option only supported "
+					  "in raw mode\n"));
+			exit(1);
+		}
+		if (fd == 1) {
+			fprintf(stderr, _("The -c option is not supported "
+					  "when writing to stdout\n"));
+			exit(1);
+		}
+		retval = ext2fs_get_mem(fs->blocksize, &check_buf);
+		if (retval) {
+			com_err(program_name, retval,
+				_("while allocating check_buf"));
+			exit(1);
+		}
+	}
+	if (show_progress && (img_type != E2IMAGE_RAW)) {
+		fprintf(stderr, _("The -p option only supported "
+				  "in raw mode\n"));
+		exit(1);
+	}
+	if (img_type)
+		write_raw_image_file(fs, fd, img_type, flags);
+	else
+		write_image_file(fs, fd);
+
+	ext2fs_close (fs);
+	if (check)
+		printf(_("%d blocks already contained the data to be copied.\n"),
+		       skipped_blocks);
+
+out:
+	if (header)
+		free(header);
+	if (qcow2_fd)
+		close(qcow2_fd);
+	remove_error_table(&et_ext2_error_table);
+	return ret;
+}
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e2initrd_helper.c b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e2initrd_helper.c
new file mode 100644
index 0000000..765716d
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e2initrd_helper.c
@@ -0,0 +1,397 @@
+/*
+ * e2initrd_helper.c - Get the filesystem table
+ *
+ * Copyright 2004 by Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <unistd.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <ctype.h>
+#include <string.h>
+#include <time.h>
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <utime.h>
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#else
+extern int optind;
+extern char *optarg;
+#endif
+
+#include "ext2fs/ext2_fs.h"
+#include "ext2fs/ext2fs.h"
+#include "blkid/blkid.h"
+
+#include "../version.h"
+#include "nls-enable.h"
+
+static const char * program_name = "e2initrd_helper";
+static char * device_name;
+static int open_flag;
+static int root_type;
+static blkid_cache cache = NULL;
+
+struct mem_file {
+	char	*buf;
+	int	size;
+	int	ptr;
+};
+
+struct fs_info {
+	char  *device;
+	char  *mountpt;
+	char  *type;
+	char  *opts;
+	int   freq;
+	int   passno;
+	int   flags;
+	struct fs_info *next;
+};
+
+static void usage(void)
+{
+	fprintf(stderr,
+		_("Usage: %s -r device\n"), program_name);
+	exit (1);
+}
+
+static errcode_t get_file(ext2_filsys fs, const char * filename,
+		   struct mem_file *ret_file)
+{
+	errcode_t	retval;
+	char 		*buf;
+	ext2_file_t	e2_file = NULL;
+	unsigned int	got;
+	struct ext2_inode inode;
+	ext2_ino_t	ino;
+
+	ret_file->buf = 0;
+	ret_file->size = 0;
+	ret_file->ptr = 0;
+
+	retval = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
+			      filename, &ino);
+	if (retval)
+		return retval;
+
+	retval = ext2fs_read_inode(fs, ino, &inode);
+	if (retval)
+		return retval;
+
+	if (inode.i_size_high || (inode.i_size > 65536))
+		return EFBIG;
+
+	buf = malloc(inode.i_size + 1);
+	if (!buf)
+		return ENOMEM;
+	memset(buf, 0, inode.i_size+1);
+
+	retval = ext2fs_file_open(fs, ino, 0, &e2_file);
+	if (retval)
+		goto errout;
+
+	retval = ext2fs_file_read(e2_file, buf, inode.i_size, &got);
+	if (retval)
+		goto errout;
+
+	retval = ext2fs_file_close(e2_file);
+	if (retval)
+		goto errout;
+
+	ret_file->buf = buf;
+	ret_file->size = (int) got;
+	return 0;
+
+errout:
+	free(buf);
+	if (e2_file)
+		ext2fs_file_close(e2_file);
+	return retval;
+}
+
+static char *get_line(struct mem_file *file)
+{
+	char	*cp, *ret;
+	int	s = 0;
+
+	cp = file->buf + file->ptr;
+	while (*cp && *cp != '\n') {
+		cp++;
+		s++;
+	}
+	ret = malloc(s+1);
+	if (!ret)
+		return 0;
+	ret[s]=0;
+	memcpy(ret, file->buf + file->ptr, s);
+	while (*cp && (*cp == '\n' || *cp == '\r')) {
+		cp++;
+		s++;
+	}
+	file->ptr += s;
+	return ret;
+}
+
+static int mem_file_eof(struct mem_file *file)
+{
+	return (file->ptr >= file->size);
+}
+
+/*
+ * fstab parsing code
+ */
+static char *string_copy(const char *s)
+{
+	char	*ret;
+
+	if (!s)
+		return 0;
+	ret = malloc(strlen(s)+1);
+	if (ret)
+		strcpy(ret, s);
+	return ret;
+}
+
+static char *skip_over_blank(char *cp)
+{
+	while (*cp && isspace(*cp))
+		cp++;
+	return cp;
+}
+
+static char *skip_over_word(char *cp)
+{
+	while (*cp && !isspace(*cp))
+		cp++;
+	return cp;
+}
+
+static char *parse_word(char **buf)
+{
+	char *word, *next;
+
+	word = *buf;
+	if (*word == 0)
+		return 0;
+
+	word = skip_over_blank(word);
+	next = skip_over_word(word);
+	if (*next)
+		*next++ = 0;
+	*buf = next;
+	return word;
+}
+
+static void parse_escape(char *word)
+{
+	char	*p, *q;
+	int	ac, i;
+
+	if (!word)
+		return;
+
+	for (p = word, q = word; *p; p++, q++) {
+		*q = *p;
+		if (*p != '\\')
+			continue;
+		if (*++p == 0)
+			break;
+		if (*p == 't') {
+			*q = '\t';
+			continue;
+		}
+		if (*p == 'n') {
+			*q = '\n';
+			continue;
+		}
+		if (!isdigit(*p)) {
+			*q = *p;
+			continue;
+		}
+		ac = 0;
+		for (i = 0; i < 3; i++, p++) {
+			if (!isdigit(*p))
+				break;
+			ac = (ac * 8) + (*p - '0');
+		}
+		*q = ac;
+		p--;
+	}
+	*q = 0;
+}
+
+static int parse_fstab_line(char *line, struct fs_info *fs)
+{
+	char	*dev, *device, *mntpnt, *type, *opts, *freq, *passno, *cp;
+
+	if ((cp = strchr(line, '#')))
+		*cp = 0;	/* Ignore everything after the comment char */
+	cp = line;
+
+	device = parse_word(&cp);
+	mntpnt = parse_word(&cp);
+	type = parse_word(&cp);
+	opts = parse_word(&cp);
+	freq = parse_word(&cp);
+	passno = parse_word(&cp);
+
+	if (!device)
+		return -1;	/* Allow blank lines */
+
+	if (!mntpnt || !type)
+		return -1;
+
+	parse_escape(device);
+	parse_escape(mntpnt);
+	parse_escape(type);
+	parse_escape(opts);
+	parse_escape(freq);
+	parse_escape(passno);
+
+	dev = blkid_get_devname(cache, device, NULL);
+	if (dev)
+		device = dev;
+
+	if (strchr(type, ','))
+		type = 0;
+
+	fs->device = string_copy(device);
+	fs->mountpt = string_copy(mntpnt);
+	fs->type = string_copy(type);
+	fs->opts = string_copy(opts ? opts : "");
+	fs->freq = freq ? atoi(freq) : -1;
+	fs->passno = passno ? atoi(passno) : -1;
+	fs->flags = 0;
+	fs->next = NULL;
+
+	free(dev);
+
+	return 0;
+}
+
+static void free_fstab_line(struct fs_info *fs)
+{
+	if (fs->device)
+		fs->device = 0;
+	if (fs->mountpt)
+		fs->mountpt = 0;
+	if (fs->type)
+		fs->type = 0;
+	if (fs->opts)
+		fs->opts = 0;
+	memset(fs, 0, sizeof(struct fs_info));
+}
+
+
+static void PRS(int argc, char **argv)
+{
+	int c;
+
+#ifdef ENABLE_NLS
+	setlocale(LC_MESSAGES, "");
+	setlocale(LC_CTYPE, "");
+	bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
+	textdomain(NLS_CAT_NAME);
+	set_com_err_gettext(gettext);
+#endif
+
+	while ((c = getopt(argc, argv, "rv")) != EOF) {
+		switch (c) {
+		case 'r':
+			root_type++;
+			break;
+
+		case 'v':
+			printf("%s %s (%s)\n", program_name,
+			       E2FSPROGS_VERSION, E2FSPROGS_DATE);
+			break;
+		default:
+			usage();
+		}
+	}
+	if (optind < argc - 1 || optind == argc)
+		usage();
+	device_name = blkid_get_devname(NULL, argv[optind], NULL);
+	if (!device_name) {
+		com_err(program_name, 0, _("Unable to resolve '%s'"),
+			argv[optind]);
+		exit(1);
+	}
+}
+
+static void get_root_type(ext2_filsys fs)
+{
+	errcode_t retval;
+	struct mem_file file;
+	char 		*buf;
+	struct fs_info fs_info;
+	int		ret;
+
+	retval = get_file(fs, "/etc/fstab", &file);
+	if (retval) {
+		com_err(program_name, retval, "couldn't open /etc/fstab");
+		exit(1);
+	}
+
+	while (!mem_file_eof(&file)) {
+		buf = get_line(&file);
+		if (!buf)
+			continue;
+
+		ret = parse_fstab_line(buf, &fs_info);
+		if (ret < 0)
+			goto next_line;
+
+		if (!strcmp(fs_info.mountpt, "/"))
+			printf("%s\n", fs_info.type);
+
+		free_fstab_line(&fs_info);
+
+	next_line:
+		free(buf);
+	}
+}
+
+
+int main (int argc, char ** argv)
+{
+	errcode_t retval;
+	ext2_filsys fs;
+	io_manager io_ptr;
+
+	add_error_table(&et_ext2_error_table);
+
+	blkid_get_cache(&cache, NULL);
+	PRS(argc, argv);
+
+#ifdef CONFIG_TESTIO_DEBUG
+	if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) {
+		io_ptr = test_io_manager;
+		test_io_backing_manager = unix_io_manager;
+	} else
+#endif
+		io_ptr = unix_io_manager;
+	retval = ext2fs_open (device_name, open_flag, 0, 0, io_ptr, &fs);
+        if (retval)
+		exit(1);
+
+	if (root_type)
+		get_root_type(fs);
+
+	remove_error_table(&et_ext2_error_table);
+	return (ext2fs_close (fs) ? 1 : 0);
+}
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e2label.8.in b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e2label.8.in
new file mode 100644
index 0000000..aff08d9
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e2label.8.in
@@ -0,0 +1,53 @@
+.\" -*- nroff -*-
+.\" Copyright 1993, 1994, 1995 by Theodore Ts'o.  All Rights Reserved.
+.\" This file may be copied under the terms of the GNU Public License.
+.\" 
+.TH E2LABEL 8 "@E2FSPROGS_MONTH@ @E2FSPROGS_YEAR@" "E2fsprogs version @E2FSPROGS_VERSION@"
+.SH NAME
+e2label \- Change the label on an ext2/ext3/ext4 filesystem
+.SH SYNOPSIS
+.B e2label
+.I device
+[
+.I new-label
+]
+.SH DESCRIPTION
+.B e2label
+will display or change the filesystem label on the ext2, ext3, or ext4 
+filesystem located on
+.I device.  
+.PP
+If the optional argument 
+.I new-label
+is not present, 
+.B e2label
+will simply display the current filesystem label.
+.PP
+If the optional argument
+.I new-label
+is present, then 
+.B e2label
+will set the filesystem label to be
+.IR new-label .
+Ext2 filesystem labels can be at most 16 characters long; if
+.I new-label 
+is longer than 16 characters, 
+.B e2label
+will truncate it and print a warning message.  
+.PP
+It is also possible to set the filesystem label using the
+.B \-L
+option of 
+.BR tune2fs (8).
+.PP
+.SH AUTHOR
+.B e2label 
+was written by Theodore Ts'o (tytso@mit.edu).
+.SH AVAILABILITY
+.B e2label
+is part of the e2fsprogs package and is available from 
+http://e2fsprogs.sourceforge.net.
+.SH SEE ALSO
+.BR mke2fs (8),
+.BR tune2fs (8)
+
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e2label.c b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e2label.c
new file mode 100644
index 0000000..bc87a42
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e2label.c
@@ -0,0 +1,121 @@
+/*
+ * e2label.c		- Print or change the volume label on an ext2 fs
+ *
+ * Written by Andries Brouwer (aeb@cwi.nl), 970714
+ *
+ * Copyright 1997, 1998 by Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <termios.h>
+#include <time.h>
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#else
+extern char *optarg;
+extern int optind;
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include "nls-enable.h"
+
+#define EXT2_SUPER_MAGIC 0xEF53
+
+#define VOLNAMSZ 16
+
+struct ext2_super_block {
+	char  s_dummy0[56];
+	unsigned char  s_magic[2];
+	char  s_dummy1[62];
+	char  s_volume_name[VOLNAMSZ];
+	char  s_last_mounted[64];
+	char  s_dummy2[824];
+} sb;
+
+static int open_e2fs (char *dev, int mode)
+{
+	int fd;
+
+	fd = open(dev, mode);
+	if (fd < 0) {
+	     perror(dev);
+	     fprintf (stderr, _("e2label: cannot open %s\n"), dev);
+	     exit(1);
+	}
+	if (lseek(fd, 1024, SEEK_SET) != 1024) {
+	     perror(dev);
+	     fprintf (stderr, _("e2label: cannot seek to superblock\n"));
+	     exit(1);
+	}
+	if (read(fd, (char *) &sb, sizeof(sb)) != sizeof(sb)) {
+	     perror(dev);
+	     fprintf (stderr, _("e2label: error reading superblock\n"));
+	     exit(1);
+	}
+	if (sb.s_magic[0] + 256*sb.s_magic[1] != EXT2_SUPER_MAGIC) {
+	     fprintf (stderr, _("e2label: not an ext2 filesystem\n"));
+	     exit(1);
+	}
+
+	return fd;
+}
+
+static void print_label (char *dev)
+{
+	char label[VOLNAMSZ+1];
+
+	open_e2fs (dev, O_RDONLY);
+	strncpy(label, sb.s_volume_name, VOLNAMSZ);
+	label[VOLNAMSZ] = 0;
+	printf("%s\n", label);
+}
+
+static void change_label (char *dev, char *label)
+{
+	int fd;
+
+	fd = open_e2fs(dev, O_RDWR);
+	memset(sb.s_volume_name, 0, VOLNAMSZ);
+	strncpy(sb.s_volume_name, label, VOLNAMSZ);
+	if (strlen(label) > VOLNAMSZ)
+		fprintf(stderr, _("Warning: label too long, truncating.\n"));
+	if (lseek(fd, 1024, SEEK_SET) != 1024) {
+	     perror(dev);
+	     fprintf (stderr, _("e2label: cannot seek to superblock again\n"));
+	     exit(1);
+	}
+	if (write(fd, (char *) &sb, sizeof(sb)) != sizeof(sb)) {
+	     perror(dev);
+	     fprintf (stderr, _("e2label: error writing superblock\n"));
+	     exit(1);
+	}
+}
+
+int main (int argc, char ** argv)
+{
+	if (argc == 2)
+	     print_label(argv[1]);
+	else if (argc == 3)
+	     change_label(argv[1], argv[2]);
+	else {
+	     fprintf(stderr, _("Usage: e2label device [newlabel]\n"));
+	     exit(1);
+	}
+	return 0;
+}
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e2undo.8.in b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e2undo.8.in
new file mode 100644
index 0000000..4bf0798
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e2undo.8.in
@@ -0,0 +1,44 @@
+.\" -*- nroff -*-
+.\" Copyright 2008 by Theodore Ts'o.  All Rights Reserved.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH E2UNDO 8 "@E2FSPROGS_MONTH@ @E2FSPROGS_YEAR@" "E2fsprogs version @E2FSPROGS_VERSION@"
+.SH NAME
+e2undo \- Replay an undo log for an ext2/ext3/ext4 filesystem
+.SH SYNOPSIS
+.B e2undo
+[
+.B \-f
+]
+.I undo_log device
+.SH DESCRIPTION
+.B e2undo
+will replay the undo log
+.I undo_log
+for an ext2/ext3/ext4 filesystem found on
+.IR device .
+This can be
+used to undo a failed operation by an e2fsprogs program.
+.SH OPTIONS
+.TP
+.B \-f
+Normally,
+.B e2undo
+will check the filesystem UUID and last modified time to make sure the
+undo log matches with the filesystem on the device.  If they do not
+match,
+.B e2undo
+will refuse to apply the undo log as a safety mechanism.  The
+.B \-f
+option disables this safety mechanism.
+.SH AUTHOR
+.B e2undo
+was written by Aneesh Kumar K.V. (aneesh.kumar@linux.vnet.ibm.com)
+.SH AVAILABILITY
+.B e2undo
+is part of the e2fsprogs package and is available from
+http://e2fsprogs.sourceforge.net.
+.SH SEE ALSO
+.BR mke2fs (8),
+.BR tune2fs (8)
+
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e2undo.c b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e2undo.c
new file mode 100644
index 0000000..a43c26f
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e2undo.c
@@ -0,0 +1,225 @@
+/*
+ * e2undo.c - Replay an undo log onto an ext2/3/4 filesystem
+ *
+ * Copyright IBM Corporation, 2007
+ * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+#include <fcntl.h>
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include "ext2fs/tdb.h"
+#include "ext2fs/ext2fs.h"
+#include "nls-enable.h"
+
+static unsigned char mtime_key[] = "filesystem MTIME";
+static unsigned char uuid_key[] = "filesystem UUID";
+static unsigned char blksize_key[] = "filesystem BLKSIZE";
+
+static char *prg_name;
+
+static void usage(void)
+{
+	fprintf(stderr,
+		_("Usage: %s <transaction file> <filesystem>\n"), prg_name);
+	exit(1);
+}
+
+static int check_filesystem(TDB_CONTEXT *tdb, io_channel channel)
+{
+	__u32   s_mtime;
+	__u8    s_uuid[16];
+	errcode_t retval;
+	TDB_DATA tdb_key, tdb_data;
+	struct ext2_super_block super;
+
+	io_channel_set_blksize(channel, SUPERBLOCK_OFFSET);
+	retval = io_channel_read_blk64(channel, 1, -SUPERBLOCK_SIZE, &super);
+	if (retval) {
+		com_err(prg_name, retval,
+			"%s", _("Failed to read the file system data \n"));
+		return retval;
+	}
+
+	tdb_key.dptr = mtime_key;
+	tdb_key.dsize = sizeof(mtime_key);
+	tdb_data = tdb_fetch(tdb, tdb_key);
+	if (!tdb_data.dptr) {
+		retval = EXT2_ET_TDB_SUCCESS + tdb_error(tdb);
+		com_err(prg_name, retval,
+			_("Failed tdb_fetch %s\n"), tdb_errorstr(tdb));
+		return retval;
+	}
+
+	s_mtime = *(__u32 *)tdb_data.dptr;
+	if (super.s_mtime != s_mtime) {
+
+		com_err(prg_name, 0,
+			_("The file system Mount time didn't match %u\n"),
+			s_mtime);
+
+		return  -1;
+	}
+
+
+	tdb_key.dptr = uuid_key;
+	tdb_key.dsize = sizeof(uuid_key);
+	tdb_data = tdb_fetch(tdb, tdb_key);
+	if (!tdb_data.dptr) {
+		retval = EXT2_ET_TDB_SUCCESS + tdb_error(tdb);
+		com_err(prg_name, retval,
+			_("Failed tdb_fetch %s\n"), tdb_errorstr(tdb));
+		return retval;
+	}
+	memcpy(s_uuid, tdb_data.dptr, sizeof(s_uuid));
+	if (memcmp(s_uuid, super.s_uuid, sizeof(s_uuid))) {
+		com_err(prg_name, 0, "%s",
+			_("The file system UUID didn't match \n"));
+		return -1;
+	}
+
+	return 0;
+}
+
+static int set_blk_size(TDB_CONTEXT *tdb, io_channel channel)
+{
+	int block_size;
+	errcode_t retval;
+	TDB_DATA tdb_key, tdb_data;
+
+	tdb_key.dptr = blksize_key;
+	tdb_key.dsize = sizeof(blksize_key);
+	tdb_data = tdb_fetch(tdb, tdb_key);
+	if (!tdb_data.dptr) {
+		retval = EXT2_ET_TDB_SUCCESS + tdb_error(tdb);
+		com_err(prg_name, retval,
+			_("Failed tdb_fetch %s\n"), tdb_errorstr(tdb));
+		return retval;
+	}
+
+	block_size = *(int *)tdb_data.dptr;
+#ifdef DEBUG
+	printf("Block size %d\n", block_size);
+#endif
+	io_channel_set_blksize(channel, block_size);
+
+	return 0;
+}
+
+int main(int argc, char *argv[])
+{
+	int c,force = 0;
+	TDB_CONTEXT *tdb;
+	TDB_DATA key, data;
+	io_channel channel;
+	errcode_t retval;
+	int  mount_flags;
+	blk64_t  blk_num;
+	char *device_name, *tdb_file;
+	io_manager manager = unix_io_manager;
+
+#ifdef ENABLE_NLS
+	setlocale(LC_MESSAGES, "");
+	setlocale(LC_CTYPE, "");
+	bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
+	textdomain(NLS_CAT_NAME);
+	set_com_err_gettext(gettext);
+#endif
+	add_error_table(&et_ext2_error_table);
+
+	prg_name = argv[0];
+	while((c = getopt(argc, argv, "f")) != EOF) {
+		switch (c) {
+			case 'f':
+				force = 1;
+				break;
+			default:
+				usage();
+		}
+	}
+
+	if (argc != optind + 2)
+		usage();
+
+	tdb_file = argv[optind];
+	device_name = argv[optind+1];
+
+	tdb = tdb_open(tdb_file, 0, 0, O_RDONLY, 0600);
+
+	if (!tdb) {
+		com_err(prg_name, errno,
+				_("Failed tdb_open %s\n"), tdb_file);
+		exit(1);
+	}
+
+	retval = ext2fs_check_if_mounted(device_name, &mount_flags);
+	if (retval) {
+		com_err(prg_name, retval, _("Error while determining whether "
+				"%s is mounted.\n"), device_name);
+		exit(1);
+	}
+
+	if (mount_flags & EXT2_MF_MOUNTED) {
+		com_err(prg_name, retval, "%s", _("e2undo should only be run "
+						"on unmounted file system\n"));
+		exit(1);
+	}
+
+	retval = manager->open(device_name,
+				IO_FLAG_EXCLUSIVE | IO_FLAG_RW,  &channel);
+	if (retval) {
+		com_err(prg_name, retval,
+				_("Failed to open %s\n"), device_name);
+		exit(1);
+	}
+
+	if (!force && check_filesystem(tdb, channel)) {
+		exit(1);
+	}
+
+	if (set_blk_size(tdb, channel)) {
+		exit(1);
+	}
+
+	for (key = tdb_firstkey(tdb); key.dptr; key = tdb_nextkey(tdb, key)) {
+		if (!strcmp((char *) key.dptr, (char *) mtime_key) ||
+		    !strcmp((char *) key.dptr, (char *) uuid_key) ||
+		    !strcmp((char *) key.dptr, (char *) blksize_key)) {
+			continue;
+		}
+
+		data = tdb_fetch(tdb, key);
+		if (!data.dptr) {
+			com_err(prg_name, 0,
+				_("Failed tdb_fetch %s\n"), tdb_errorstr(tdb));
+			exit(1);
+		}
+		blk_num = *(blk64_t *)key.dptr;
+		printf(_("Replayed transaction of size %zd at location %llu\n"),
+							data.dsize, blk_num);
+		retval = io_channel_write_blk64(channel, blk_num,
+						-data.dsize, data.dptr);
+		if (retval == -1) {
+			com_err(prg_name, retval,
+					_("Failed write %s\n"),
+					strerror(errno));
+			exit(1);
+		}
+	}
+	io_channel_close(channel);
+	tdb_close(tdb);
+
+	return 0;
+}
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e4defrag.8.in b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e4defrag.8.in
new file mode 100644
index 0000000..75e1bc9
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e4defrag.8.in
@@ -0,0 +1,80 @@
+.TH E4DEFRAG 8 "May 2009" "e4defrag version 2.0"
+.SH NAME
+e4defrag \- online defragmenter for ext4 filesystem
+.SH SYNOPSIS
+.B e4defrag
+[
+.B \-c
+]
+[
+.B \-v
+]
+.I target
+\&...
+.SH DESCRIPTION
+.B e4defrag
+reduces fragmentation of extent based file. The file targeted by
+.B e4defrag
+is created on ext4 filesystem made with "-O extent" option (see
+.BR mke2fs (8)).
+The targeted file gets more contiguous blocks and improves the file access
+speed.
+.PP
+.I target
+is a regular file, a directory, or a device that is mounted as ext4 filesystem.
+If
+.I target
+is a directory,
+.B e4defrag
+reduces fragmentation of all files in it. If
+.I target
+is a device,
+.B e4defrag
+gets the mount point of it and reduces fragmentation of all files in this mount
+point.
+.SH OPTIONS
+.TP
+.B \-c
+Get a current fragmentation count and an ideal fragmentation count, and
+calculate fragmentation score based on them. By seeing this score, we can
+determine whether we should execute
+.B e4defrag
+to
+.IR target .
+When used with
+.B \-v
+option, the current fragmentation count and the ideal fragmentation count are
+printed for each file.
+.IP
+Also this option outputs the average data size in one extent. If you see it,
+you'll find the file has ideal extents or not. Note that the maximum extent
+size is 131072KB in ext4 filesystem (if block size is 4KB).
+.IP
+If this option is specified,
+.I target
+is never defragmented.
+.TP
+.B \-v
+Print error messages and the fragmentation count before and after defrag for
+each file.
+.SH NOTES
+.B e4defrag
+does not support swap file, files in lost+found directory, and files allocated
+in indirect blocks. When
+.I target
+is a device or a mount point,
+.B e4defrag
+doesn't defragment files in mount point of other device.
+.PP
+Non-privileged users can execute
+.B e4defrag
+to their own file, but the score is not printed if
+.B \-c
+option is specified. Therefore, it is desirable to be executed by root user.
+.SH AUTHOR
+Written by Akira Fujita <a-fujita@rs.jp.nec.com> and Takashi Sato
+<t-sato@yk.jp.nec.com>.
+.SH SEE ALSO
+.BR mke2fs (8),
+.BR mount (8).
+
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e4defrag.c b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e4defrag.c
new file mode 100644
index 0000000..c6a5f0d
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/e4defrag.c
@@ -0,0 +1,2083 @@
+/*
+ * e4defrag.c - ext4 filesystem defragmenter
+ *
+ * Copyright (C) 2009 NEC Software Tohoku, Ltd.
+ *
+ * Author: Akira Fujita	<a-fujita@rs.jp.nec.com>
+ *         Takashi Sato	<t-sato@yk.jp.nec.com>
+ */
+
+#ifndef _LARGEFILE_SOURCE
+#define _LARGEFILE_SOURCE
+#endif
+
+#ifndef _LARGEFILE64_SOURCE
+#define _LARGEFILE64_SOURCE
+#endif
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include "config.h"
+#include <ctype.h>
+#include <dirent.h>
+#include <endian.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <ftw.h>
+#include <limits.h>
+#include <mntent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ext2fs/ext2_types.h>
+#include <ext2fs/ext2fs.h>
+#include <linux/fs.h>
+#include <sys/ioctl.h>
+#include <ext2fs/fiemap.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <sys/syscall.h>
+#include <sys/vfs.h>
+
+/* A relatively new ioctl interface ... */
+#ifndef EXT4_IOC_MOVE_EXT
+#define EXT4_IOC_MOVE_EXT      _IOWR('f', 15, struct move_extent)
+#endif
+
+/* Macro functions */
+#define PRINT_ERR_MSG(msg)	fprintf(stderr, "%s\n", (msg))
+#define IN_FTW_PRINT_ERR_MSG(msg)	\
+	fprintf(stderr, "\t%s\t\t[ NG ]\n", (msg))
+#define PRINT_FILE_NAME(file)	fprintf(stderr, " \"%s\"\n", (file))
+#define PRINT_ERR_MSG_WITH_ERRNO(msg)	\
+	fprintf(stderr, "\t%s:%s\t[ NG ]\n", (msg), strerror(errno))
+#define STATISTIC_ERR_MSG(msg)	\
+	fprintf(stderr, "\t%s\n", (msg))
+#define STATISTIC_ERR_MSG_WITH_ERRNO(msg)	\
+	fprintf(stderr, "\t%s:%s\n", (msg), strerror(errno))
+#define min(x, y) (((x) > (y)) ? (y) : (x))
+#define CALC_SCORE(ratio) \
+	((ratio) > 10 ? (80 + 20 * (ratio) / 100) : (8 * (ratio)))
+/* Wrap up the free function */
+#define FREE(tmp)				\
+	do {					\
+		if ((tmp) != NULL)		\
+			free(tmp);		\
+	} while (0)				\
+/* Insert list2 after list1 */
+#define insert(list1, list2)			\
+	do {					\
+		list2->next = list1->next;	\
+		list1->next->prev = list2;	\
+		list2->prev = list1;		\
+		list1->next = list2;		\
+	} while (0)
+
+/* To delete unused warning */
+#ifdef __GNUC__
+#define EXT2FS_ATTR(x) __attribute__(x)
+#else
+#define EXT2FS_ATTR(x)
+#endif
+
+/* The mode of defrag */
+#define DETAIL			0x01
+#define STATISTIC		0x02
+
+#define DEVNAME			0
+#define DIRNAME			1
+#define FILENAME		2
+
+#define FTW_OPEN_FD		2000
+
+#define FS_EXT4			"ext4"
+#define ROOT_UID		0
+
+#define BOUND_SCORE		55
+#define SHOW_FRAG_FILES	5
+
+/* Magic number for ext4 */
+#define EXT4_SUPER_MAGIC	0xEF53
+
+/* Definition of flex_bg */
+#define EXT4_FEATURE_INCOMPAT_FLEX_BG		0x0200
+
+/* The following macro is used for ioctl FS_IOC_FIEMAP
+ * EXTENT_MAX_COUNT:	the maximum number of extents for exchanging between
+ *			kernel-space and user-space per ioctl
+ */
+#define EXTENT_MAX_COUNT	512
+
+/* The following macros are error message */
+#define MSG_USAGE		\
+"Usage	: e4defrag [-v] file...| directory...| device...\n\
+	: e4defrag  -c  file...| directory...| device...\n"
+
+#define NGMSG_EXT4		"Filesystem is not ext4 filesystem"
+#define NGMSG_FILE_EXTENT	"Failed to get file extents"
+#define NGMSG_FILE_INFO		"Failed to get file information"
+#define NGMSG_FILE_OPEN		"Failed to open"
+#define NGMSG_FILE_UNREG	"File is not regular file"
+#define NGMSG_LOST_FOUND	"Can not process \"lost+found\""
+
+/* Data type for filesystem-wide blocks number */
+typedef unsigned long long ext4_fsblk_t;
+
+struct fiemap_extent_data {
+	__u64 len;			/* blocks count */
+	__u64 logical;		/* start logical block number */
+	ext4_fsblk_t physical;		/* start physical block number */
+};
+
+struct fiemap_extent_list {
+	struct fiemap_extent_list *prev;
+	struct fiemap_extent_list *next;
+	struct fiemap_extent_data data;	/* extent belong to file */
+};
+
+struct fiemap_extent_group {
+	struct fiemap_extent_group *prev;
+	struct fiemap_extent_group *next;
+	__u64 len;	/* length of this continuous region */
+	struct fiemap_extent_list *start;	/* start ext */
+	struct fiemap_extent_list *end;		/* end ext */
+};
+
+struct move_extent {
+	__s32 reserved;	/* original file descriptor */
+	__u32 donor_fd;	/* donor file descriptor */
+	__u64 orig_start;	/* logical start offset in block for orig */
+	__u64 donor_start;	/* logical start offset in block for donor */
+	__u64 len;	/* block length to be moved */
+	__u64 moved_len;	/* moved block length */
+};
+
+struct frag_statistic_ino {
+	int now_count;	/* the file's extents count of before defrag */
+	int best_count; /* the best file's extents count */
+	__u64 size_per_ext;	/* size(KB) per extent */
+	float ratio;	/* the ratio of fragmentation */
+	char msg_buffer[PATH_MAX + 1];	/* pathname of the file */
+};
+
+static char	lost_found_dir[PATH_MAX + 1];
+static int	block_size;
+static int	extents_before_defrag;
+static int	extents_after_defrag;
+static int	mode_flag;
+static unsigned int	current_uid;
+static unsigned int	defraged_file_count;
+static unsigned int	frag_files_before_defrag;
+static unsigned int	frag_files_after_defrag;
+static unsigned int	regular_count;
+static unsigned int	succeed_cnt;
+static unsigned int	total_count;
+static __u8 log_groups_per_flex;
+static __u32 blocks_per_group;
+static __u32 feature_incompat;
+static ext4_fsblk_t	files_block_count;
+static struct frag_statistic_ino	frag_rank[SHOW_FRAG_FILES];
+
+
+/* Local definitions of some syscalls glibc may not yet have */
+
+#ifndef HAVE_POSIX_FADVISE
+#warning Using locally defined posix_fadvise interface.
+
+#ifndef __NR_fadvise64_64
+#error Your kernel headers dont define __NR_fadvise64_64
+#endif
+
+/*
+ * fadvise() -		Give advice about file access.
+ *
+ * @fd:			defrag target file's descriptor.
+ * @offset:		file offset.
+ * @len:		area length.
+ * @advise:		process flag.
+ */
+static int posix_fadvise(int fd, loff_t offset, size_t len, int advise)
+{
+	return syscall(__NR_fadvise64_64, fd, offset, len, advise);
+}
+#endif /* ! HAVE_FADVISE64_64 */
+
+#ifndef HAVE_SYNC_FILE_RANGE
+#warning Using locally defined sync_file_range interface.
+
+#ifndef __NR_sync_file_range
+#ifndef __NR_sync_file_range2 /* ppc */
+#error Your kernel headers dont define __NR_sync_file_range
+#endif
+#endif
+
+/*
+ * sync_file_range() -	Sync file region.
+ *
+ * @fd:			defrag target file's descriptor.
+ * @offset:		file offset.
+ * @length:		area length.
+ * @flag:		process flag.
+ */
+int sync_file_range(int fd, loff_t offset, loff_t length, unsigned int flag)
+{
+#ifdef __NR_sync_file_range
+	return syscall(__NR_sync_file_range, fd, offset, length, flag);
+#else
+	return syscall(__NR_sync_file_range2, fd, flag, offset, length);
+#endif
+}
+#endif /* ! HAVE_SYNC_FILE_RANGE */
+
+#ifndef HAVE_FALLOCATE64
+#warning Using locally defined fallocate syscall interface.
+
+#ifndef __NR_fallocate
+#error Your kernel headers dont define __NR_fallocate
+#endif
+
+/*
+ * fallocate64() -	Manipulate file space.
+ *
+ * @fd:			defrag target file's descriptor.
+ * @mode:		process flag.
+ * @offset:		file offset.
+ * @len:		file size.
+ */
+static int fallocate64(int fd, int mode, loff_t offset, loff_t len)
+{
+	return syscall(__NR_fallocate, fd, mode, offset, len);
+}
+#endif /* ! HAVE_FALLOCATE */
+
+/*
+ * get_mount_point() -	Get device's mount point.
+ *
+ * @devname:		the device's name.
+ * @mount_point:	the mount point.
+ * @dir_path_len:	the length of directory.
+ */
+static int get_mount_point(const char *devname, char *mount_point,
+							int dir_path_len)
+{
+	/* Refer to /etc/mtab */
+	const char	*mtab = MOUNTED;
+	FILE		*fp = NULL;
+	struct mntent	*mnt = NULL;
+	struct stat64	sb;
+
+	if (stat64(devname, &sb) < 0) {
+		perror(NGMSG_FILE_INFO);
+		PRINT_FILE_NAME(devname);
+		return -1;
+	}
+
+	fp = setmntent(mtab, "r");
+	if (fp == NULL) {
+		perror("Couldn't access /etc/mtab");
+		return -1;
+	}
+
+	while ((mnt = getmntent(fp)) != NULL) {
+		struct stat64 ms;
+
+		/*
+		 * To handle device symlinks, we see if the
+		 * device number matches, not the name
+		 */
+		if (stat64(mnt->mnt_fsname, &ms) < 0)
+			continue;
+		if (sb.st_rdev != ms.st_rdev)
+			continue;
+
+		endmntent(fp);
+		if (strcmp(mnt->mnt_type, FS_EXT4) == 0) {
+			strncpy(mount_point, mnt->mnt_dir,
+				dir_path_len);
+			return 0;
+		}
+		PRINT_ERR_MSG(NGMSG_EXT4);
+		return -1;
+	}
+	endmntent(fp);
+	PRINT_ERR_MSG("Filesystem is not mounted");
+	return -1;
+}
+
+/*
+ * is_ext4() -		Whether on an ext4 filesystem.
+ *
+ * @file:		the file's name.
+ */
+static int is_ext4(const char *file, char *devname)
+{
+	int 	maxlen = 0;
+	int	len, ret;
+	FILE	*fp = NULL;
+	char	*mnt_type = NULL;
+	/* Refer to /etc/mtab */
+	const char	*mtab = MOUNTED;
+	char	file_path[PATH_MAX + 1];
+	struct mntent	*mnt = NULL;
+	struct statfs64	fsbuf;
+
+	/* Get full path */
+	if (realpath(file, file_path) == NULL) {
+		perror("Couldn't get full path");
+		PRINT_FILE_NAME(file);
+		return -1;
+	}
+
+	if (statfs64(file_path, &fsbuf) < 0) {
+		perror("Failed to get filesystem information");
+		PRINT_FILE_NAME(file);
+		return -1;
+	}
+
+	if (fsbuf.f_type != EXT4_SUPER_MAGIC) {
+		PRINT_ERR_MSG(NGMSG_EXT4);
+		return -1;
+	}
+
+	fp = setmntent(mtab, "r");
+	if (fp == NULL) {
+		perror("Couldn't access /etc/mtab");
+		return -1;
+	}
+
+	while ((mnt = getmntent(fp)) != NULL) {
+		if (mnt->mnt_fsname[0] != '/')
+			continue;
+		len = strlen(mnt->mnt_dir);
+		ret = memcmp(file_path, mnt->mnt_dir, len);
+		if (ret != 0)
+			continue;
+
+		if (maxlen >= len)
+			continue;
+
+		maxlen = len;
+
+		mnt_type = realloc(mnt_type, strlen(mnt->mnt_type) + 1);
+		if (mnt_type == NULL) {
+			endmntent(fp);
+			return -1;
+		}
+		memset(mnt_type, 0, strlen(mnt->mnt_type) + 1);
+		strncpy(mnt_type, mnt->mnt_type, strlen(mnt->mnt_type));
+		strncpy(lost_found_dir, mnt->mnt_dir, PATH_MAX);
+		strncpy(devname, mnt->mnt_fsname, strlen(mnt->mnt_fsname) + 1);
+	}
+
+	endmntent(fp);
+	if (mnt_type && strcmp(mnt_type, FS_EXT4) == 0) {
+		FREE(mnt_type);
+		return 0;
+	} else {
+		FREE(mnt_type);
+		PRINT_ERR_MSG(NGMSG_EXT4);
+		return -1;
+	}
+}
+
+/*
+ * calc_entry_counts() -	Calculate file counts.
+ *
+ * @file:		file name.
+ * @buf:		file info.
+ * @flag:		file type.
+ * @ftwbuf:		the pointer of a struct FTW.
+ */
+static int calc_entry_counts(const char *file EXT2FS_ATTR((unused)),
+		const struct stat64 *buf, int flag EXT2FS_ATTR((unused)),
+		struct FTW *ftwbuf EXT2FS_ATTR((unused)))
+{
+	if (S_ISREG(buf->st_mode))
+		regular_count++;
+
+	total_count++;
+
+	return 0;
+}
+
+/*
+ * page_in_core() -	Get information on whether pages are in core.
+ *
+ * @fd:			defrag target file's descriptor.
+ * @defrag_data:	data used for defrag.
+ * @vec:		page state array.
+ * @page_num:		page number.
+ */
+static int page_in_core(int fd, struct move_extent defrag_data,
+			unsigned char **vec, unsigned int *page_num)
+{
+	long	pagesize;
+	void	*page = NULL;
+	loff_t	offset, end_offset, length;
+
+	if (vec == NULL || *vec != NULL)
+		return -1;
+
+	pagesize = sysconf(_SC_PAGESIZE);
+	if (pagesize < 0)
+		return -1;
+	/* In mmap, offset should be a multiple of the page size */
+	offset = (loff_t)defrag_data.orig_start * block_size;
+	length = (loff_t)defrag_data.len * block_size;
+	end_offset = offset + length;
+	/* Round the offset down to the nearest multiple of pagesize */
+	offset = (offset / pagesize) * pagesize;
+	length = end_offset - offset;
+
+	page = mmap(NULL, length, PROT_READ, MAP_SHARED, fd, offset);
+	if (page == MAP_FAILED)
+		return -1;
+
+	*page_num = 0;
+	*page_num = (length + pagesize - 1) / pagesize;
+	*vec = (unsigned char *)calloc(*page_num, 1);
+	if (*vec == NULL)
+		return -1;
+
+	/* Get information on whether pages are in core */
+	if (mincore(page, (size_t)length, *vec) == -1 ||
+		munmap(page, length) == -1) {
+		FREE(*vec);
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
+ * defrag_fadvise() -	Predeclare an access pattern for file data.
+ *
+ * @fd:			defrag target file's descriptor.
+ * @defrag_data:	data used for defrag.
+ * @vec:		page state array.
+ * @page_num:		page number.
+ */
+static int defrag_fadvise(int fd, struct move_extent defrag_data,
+		   unsigned char *vec, unsigned int page_num)
+{
+	int	flag = 1;
+	long	pagesize = sysconf(_SC_PAGESIZE);
+	int	fadvise_flag = POSIX_FADV_DONTNEED;
+	int	sync_flag = SYNC_FILE_RANGE_WAIT_BEFORE |
+			    SYNC_FILE_RANGE_WRITE |
+			    SYNC_FILE_RANGE_WAIT_AFTER;
+	unsigned int	i;
+	loff_t	offset;
+
+	if (pagesize < 1)
+		return -1;
+
+	offset = (loff_t)defrag_data.orig_start * block_size;
+	offset = (offset / pagesize) * pagesize;
+
+	/* Sync file for fadvise process */
+	if (sync_file_range(fd, offset,
+		(loff_t)pagesize * page_num, sync_flag) < 0)
+		return -1;
+
+	/* Try to release buffer cache which this process used,
+	 * then other process can use the released buffer
+	 */
+	for (i = 0; i < page_num; i++) {
+		if ((vec[i] & 0x1) == 0) {
+			offset += pagesize;
+			continue;
+		}
+		if (posix_fadvise(fd, offset, pagesize, fadvise_flag) < 0) {
+			if ((mode_flag & DETAIL) && flag) {
+				perror("\tFailed to fadvise");
+				flag = 0;
+			}
+		}
+		offset += pagesize;
+	}
+
+	return 0;
+}
+
+/*
+ * check_free_size() -	Check if there's enough disk space.
+ *
+ * @fd:			defrag target file's descriptor.
+ * @file:		file name.
+ * @blk_count:		file blocks.
+ */
+static int check_free_size(int fd, const char *file, ext4_fsblk_t blk_count)
+{
+	ext4_fsblk_t	free_blk_count;
+	struct statfs64	fsbuf;
+
+	if (fstatfs64(fd, &fsbuf) < 0) {
+		if (mode_flag & DETAIL) {
+			PRINT_FILE_NAME(file);
+			PRINT_ERR_MSG_WITH_ERRNO(
+				"Failed to get filesystem information");
+		}
+		return -1;
+	}
+
+	/* Compute free space for root and normal user separately */
+	if (current_uid == ROOT_UID)
+		free_blk_count = fsbuf.f_bfree;
+	else
+		free_blk_count = fsbuf.f_bavail;
+
+	if (free_blk_count >= blk_count)
+		return 0;
+
+	return -ENOSPC;
+}
+
+/*
+ * file_frag_count() -	Get file fragment count.
+ *
+ * @fd:			defrag target file's descriptor.
+ */
+static int file_frag_count(int fd)
+{
+	int	ret;
+	struct fiemap	fiemap_buf;
+
+	/* When fm_extent_count is 0,
+	 * ioctl just get file fragment count.
+	 */
+	memset(&fiemap_buf, 0, sizeof(struct fiemap));
+	fiemap_buf.fm_start = 0;
+	fiemap_buf.fm_length = FIEMAP_MAX_OFFSET;
+	fiemap_buf.fm_flags |= FIEMAP_FLAG_SYNC;
+
+	ret = ioctl(fd, FS_IOC_FIEMAP, &fiemap_buf);
+	if (ret < 0)
+		return ret;
+
+	return fiemap_buf.fm_mapped_extents;
+}
+
+/*
+ * file_check() -	Check file's attributes.
+ *
+ * @fd:			defrag target file's descriptor.
+ * @buf:		a pointer of the struct stat64.
+ * @file:		file name.
+ * @extents:		file extents.
+ * @blk_count:		file blocks.
+ */
+static int file_check(int fd, const struct stat64 *buf, const char *file,
+		int extents, ext4_fsblk_t blk_count)
+{
+	int	ret;
+	struct flock	lock;
+
+	/* Write-lock check is more reliable */
+	lock.l_type = F_WRLCK;
+	lock.l_start = 0;
+	lock.l_whence = SEEK_SET;
+	lock.l_len = 0;
+
+	/* Free space */
+	ret = check_free_size(fd, file, blk_count);
+	if (ret < 0) {
+		if ((mode_flag & DETAIL) && ret == -ENOSPC) {
+			printf("\033[79;0H\033[K[%u/%u] \"%s\"\t\t"
+				"  extents: %d -> %d\n", defraged_file_count,
+				total_count, file, extents, extents);
+			IN_FTW_PRINT_ERR_MSG(
+			"Defrag size is larger than filesystem's free space");
+		}
+		return -1;
+	}
+
+	/* Access authority */
+	if (current_uid != ROOT_UID &&
+		buf->st_uid != current_uid) {
+		if (mode_flag & DETAIL) {
+			printf("\033[79;0H\033[K[%u/%u] \"%s\"\t\t"
+				"  extents: %d -> %d\n", defraged_file_count,
+				total_count, file, extents, extents);
+			IN_FTW_PRINT_ERR_MSG(
+				"File is not current user's file"
+				" or current user is not root");
+		}
+		return -1;
+	}
+
+	/* Lock status */
+	if (fcntl(fd, F_GETLK, &lock) < 0) {
+		if (mode_flag & DETAIL) {
+			PRINT_FILE_NAME(file);
+			PRINT_ERR_MSG_WITH_ERRNO(
+				"Failed to get lock information");
+		}
+		return -1;
+	} else if (lock.l_type != F_UNLCK) {
+		if (mode_flag & DETAIL) {
+			PRINT_FILE_NAME(file);
+			IN_FTW_PRINT_ERR_MSG("File has been locked");
+		}
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
+ * insert_extent_by_logical() -	Sequentially insert extent by logical.
+ *
+ * @ext_list_head:	the head of logical extent list.
+ * @ext:		the extent element which will be inserted.
+ */
+static int insert_extent_by_logical(struct fiemap_extent_list **ext_list_head,
+			struct fiemap_extent_list *ext)
+{
+	struct fiemap_extent_list	*ext_list_tmp = *ext_list_head;
+
+	if (ext == NULL)
+		goto out;
+
+	/* First element */
+	if (*ext_list_head == NULL) {
+		(*ext_list_head) = ext;
+		(*ext_list_head)->prev = *ext_list_head;
+		(*ext_list_head)->next = *ext_list_head;
+		return 0;
+	}
+
+	if (ext->data.logical <= ext_list_tmp->data.logical) {
+		/* Insert before head */
+		if (ext_list_tmp->data.logical <
+			ext->data.logical + ext->data.len)
+			/* Overlap */
+			goto out;
+		/* Adjust head */
+		*ext_list_head = ext;
+	} else {
+		/* Insert into the middle or last of the list */
+		do {
+			if (ext->data.logical < ext_list_tmp->data.logical)
+				break;
+			ext_list_tmp = ext_list_tmp->next;
+		} while (ext_list_tmp != (*ext_list_head));
+		if (ext->data.logical <
+		    ext_list_tmp->prev->data.logical +
+			ext_list_tmp->prev->data.len)
+			/* Overlap */
+			goto out;
+
+		if (ext_list_tmp != *ext_list_head &&
+		    ext_list_tmp->data.logical <
+		    ext->data.logical + ext->data.len)
+			/* Overlap */
+			goto out;
+	}
+	ext_list_tmp = ext_list_tmp->prev;
+	/* Insert "ext" after "ext_list_tmp" */
+	insert(ext_list_tmp, ext);
+	return 0;
+out:
+	errno = EINVAL;
+	return -1;
+}
+
+/*
+ * insert_extent_by_physical() -	Sequentially insert extent by physical.
+ *
+ * @ext_list_head:	the head of physical extent list.
+ * @ext:		the extent element which will be inserted.
+ */
+static int insert_extent_by_physical(struct fiemap_extent_list **ext_list_head,
+			struct fiemap_extent_list *ext)
+{
+	struct fiemap_extent_list	*ext_list_tmp = *ext_list_head;
+
+	if (ext == NULL)
+		goto out;
+
+	/* First element */
+	if (*ext_list_head == NULL) {
+		(*ext_list_head) = ext;
+		(*ext_list_head)->prev = *ext_list_head;
+		(*ext_list_head)->next = *ext_list_head;
+		return 0;
+	}
+
+	if (ext->data.physical <= ext_list_tmp->data.physical) {
+		/* Insert before head */
+		if (ext_list_tmp->data.physical <
+					ext->data.physical + ext->data.len)
+			/* Overlap */
+			goto out;
+		/* Adjust head */
+		*ext_list_head = ext;
+	} else {
+		/* Insert into the middle or last of the list */
+		do {
+			if (ext->data.physical < ext_list_tmp->data.physical)
+				break;
+			ext_list_tmp = ext_list_tmp->next;
+		} while (ext_list_tmp != (*ext_list_head));
+		if (ext->data.physical <
+		    ext_list_tmp->prev->data.physical +
+				ext_list_tmp->prev->data.len)
+			/* Overlap */
+			goto out;
+
+		if (ext_list_tmp != *ext_list_head &&
+		    ext_list_tmp->data.physical <
+				ext->data.physical + ext->data.len)
+			/* Overlap */
+			goto out;
+	}
+	ext_list_tmp = ext_list_tmp->prev;
+	/* Insert "ext" after "ext_list_tmp" */
+	insert(ext_list_tmp, ext);
+	return 0;
+out:
+	errno = EINVAL;
+	return -1;
+}
+
+/*
+ * insert_exts_group() -	Insert a exts_group.
+ *
+ * @ext_group_head:		the head of a exts_group list.
+ * @exts_group:			the exts_group element which will be inserted.
+ */
+static int insert_exts_group(struct fiemap_extent_group **ext_group_head,
+				struct fiemap_extent_group *exts_group)
+{
+	struct fiemap_extent_group	*ext_group_tmp = NULL;
+
+	if (exts_group == NULL) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	/* Initialize list */
+	if (*ext_group_head == NULL) {
+		(*ext_group_head) = exts_group;
+		(*ext_group_head)->prev = *ext_group_head;
+		(*ext_group_head)->next = *ext_group_head;
+		return 0;
+	}
+
+	ext_group_tmp = (*ext_group_head)->prev;
+	insert(ext_group_tmp, exts_group);
+
+	return 0;
+}
+
+/*
+ * join_extents() -		Find continuous region(exts_group).
+ *
+ * @ext_list_head:		the head of the extent list.
+ * @ext_group_head:		the head of the target exts_group list.
+ */
+static int join_extents(struct fiemap_extent_list *ext_list_head,
+		struct fiemap_extent_group **ext_group_head)
+{
+	__u64	len = ext_list_head->data.len;
+	struct fiemap_extent_list *ext_list_start = ext_list_head;
+	struct fiemap_extent_list *ext_list_tmp = ext_list_head->next;
+
+	do {
+		struct fiemap_extent_group	*ext_group_tmp = NULL;
+
+		/* This extent and previous extent are not continuous,
+		 * so, all previous extents are treated as an extent group.
+		 */
+		if ((ext_list_tmp->prev->data.logical +
+			ext_list_tmp->prev->data.len)
+				!= ext_list_tmp->data.logical) {
+			ext_group_tmp =
+				malloc(sizeof(struct fiemap_extent_group));
+			if (ext_group_tmp == NULL)
+				return -1;
+
+			memset(ext_group_tmp, 0,
+				sizeof(struct fiemap_extent_group));
+			ext_group_tmp->len = len;
+			ext_group_tmp->start = ext_list_start;
+			ext_group_tmp->end = ext_list_tmp->prev;
+
+			if (insert_exts_group(ext_group_head,
+				ext_group_tmp) < 0) {
+				FREE(ext_group_tmp);
+				return -1;
+			}
+			ext_list_start = ext_list_tmp;
+			len = ext_list_tmp->data.len;
+			ext_list_tmp = ext_list_tmp->next;
+			continue;
+		}
+
+		/* This extent and previous extent are continuous,
+		 * so, they belong to the same extent group, and we check
+		 * if the next extent belongs to the same extent group.
+		 */
+		len += ext_list_tmp->data.len;
+		ext_list_tmp = ext_list_tmp->next;
+	} while (ext_list_tmp != ext_list_head->next);
+
+	return 0;
+}
+
+/*
+ * get_file_extents() -	Get file's extent list.
+ *
+ * @fd:			defrag target file's descriptor.
+ * @ext_list_head:	the head of the extent list.
+ */
+static int get_file_extents(int fd, struct fiemap_extent_list **ext_list_head)
+{
+	__u32	i;
+	int	ret;
+	int	ext_buf_size, fie_buf_size;
+	__u64	pos = 0;
+	struct fiemap	*fiemap_buf = NULL;
+	struct fiemap_extent	*ext_buf = NULL;
+	struct fiemap_extent_list	*ext_list = NULL;
+
+	/* Convert units, in bytes.
+	 * Be careful : now, physical block number in extent is 48bit,
+	 * and the maximum blocksize for ext4 is 4K(12bit),
+	 * so there is no overflow, but in future it may be changed.
+	 */
+
+	/* Alloc space for fiemap */
+	ext_buf_size = EXTENT_MAX_COUNT * sizeof(struct fiemap_extent);
+	fie_buf_size = sizeof(struct fiemap) + ext_buf_size;
+
+	fiemap_buf = malloc(fie_buf_size);
+	if (fiemap_buf == NULL)
+		return -1;
+
+	ext_buf = fiemap_buf->fm_extents;
+	memset(fiemap_buf, 0, fie_buf_size);
+	fiemap_buf->fm_length = FIEMAP_MAX_OFFSET;
+	fiemap_buf->fm_flags |= FIEMAP_FLAG_SYNC;
+	fiemap_buf->fm_extent_count = EXTENT_MAX_COUNT;
+
+	do {
+		fiemap_buf->fm_start = pos;
+		memset(ext_buf, 0, ext_buf_size);
+		ret = ioctl(fd, FS_IOC_FIEMAP, fiemap_buf);
+		if (ret < 0 || fiemap_buf->fm_mapped_extents == 0)
+			goto out;
+		for (i = 0; i < fiemap_buf->fm_mapped_extents; i++) {
+			ext_list = NULL;
+			ext_list = malloc(sizeof(struct fiemap_extent_list));
+			if (ext_list == NULL)
+				goto out;
+
+			ext_list->data.physical = ext_buf[i].fe_physical
+						/ block_size;
+			ext_list->data.logical = ext_buf[i].fe_logical
+						/ block_size;
+			ext_list->data.len = ext_buf[i].fe_length
+						/ block_size;
+
+			ret = insert_extent_by_physical(
+					ext_list_head, ext_list);
+			if (ret < 0) {
+				FREE(ext_list);
+				goto out;
+			}
+		}
+		/* Record file's logical offset this time */
+		pos = ext_buf[EXTENT_MAX_COUNT-1].fe_logical +
+			ext_buf[EXTENT_MAX_COUNT-1].fe_length;
+		/*
+		 * If fm_extents array has been filled and
+		 * there are extents left, continue to cycle.
+		 */
+	} while (fiemap_buf->fm_mapped_extents
+					== EXTENT_MAX_COUNT &&
+		!(ext_buf[EXTENT_MAX_COUNT-1].fe_flags
+					& FIEMAP_EXTENT_LAST));
+
+	FREE(fiemap_buf);
+	return 0;
+out:
+	FREE(fiemap_buf);
+	return -1;
+}
+
+/*
+ * get_logical_count() -	Get the file logical extents count.
+ *
+ * @logical_list_head:	the head of the logical extent list.
+ */
+static int get_logical_count(struct fiemap_extent_list *logical_list_head)
+{
+	int ret = 0;
+	struct fiemap_extent_list *ext_list_tmp  = logical_list_head;
+
+	do {
+		ret++;
+		ext_list_tmp = ext_list_tmp->next;
+	} while (ext_list_tmp != logical_list_head);
+
+	return ret;
+}
+
+/*
+ * get_physical_count() -	Get the file physical extents count.
+ *
+ * @physical_list_head:	the head of the physical extent list.
+ */
+static int get_physical_count(struct fiemap_extent_list *physical_list_head)
+{
+	int ret = 0;
+	struct fiemap_extent_list *ext_list_tmp = physical_list_head;
+
+	do {
+		if ((ext_list_tmp->data.physical + ext_list_tmp->data.len)
+				!= ext_list_tmp->next->data.physical) {
+			/* This extent and next extent are not continuous. */
+			ret++;
+		}
+
+		ext_list_tmp = ext_list_tmp->next;
+	} while (ext_list_tmp != physical_list_head);
+
+	return ret;
+}
+
+/*
+ * change_physical_to_logical() -	Change list from physical to logical.
+ *
+ * @physical_list_head:	the head of physical extent list.
+ * @logical_list_head:	the head of logical extent list.
+ */
+static int change_physical_to_logical(
+			struct fiemap_extent_list **physical_list_head,
+			struct fiemap_extent_list **logical_list_head)
+{
+	int ret;
+	struct fiemap_extent_list *ext_list_tmp = *physical_list_head;
+	struct fiemap_extent_list *ext_list_next = ext_list_tmp->next;
+
+	while (1) {
+		if (ext_list_tmp == ext_list_next) {
+			ret = insert_extent_by_logical(
+				logical_list_head, ext_list_tmp);
+			if (ret < 0)
+				return -1;
+
+			*physical_list_head = NULL;
+			break;
+		}
+
+		ext_list_tmp->prev->next = ext_list_tmp->next;
+		ext_list_tmp->next->prev = ext_list_tmp->prev;
+		*physical_list_head = ext_list_next;
+
+		ret = insert_extent_by_logical(
+			logical_list_head, ext_list_tmp);
+		if (ret < 0) {
+			FREE(ext_list_tmp);
+			return -1;
+		}
+		ext_list_tmp = ext_list_next;
+		ext_list_next = ext_list_next->next;
+	}
+
+	return 0;
+}
+
+/* get_file_blocks() -  Get total file blocks.
+ *
+ * @ext_list_head:	the extent list head of the target file
+ */
+static ext4_fsblk_t get_file_blocks(struct fiemap_extent_list *ext_list_head)
+{
+	ext4_fsblk_t blk_count = 0;
+	struct fiemap_extent_list *ext_list_tmp = ext_list_head;
+
+	do {
+		blk_count += ext_list_tmp->data.len;
+		ext_list_tmp = ext_list_tmp->next;
+	} while (ext_list_tmp != ext_list_head);
+
+	return blk_count;
+}
+
+/*
+ * free_ext() -		Free the extent list.
+ *
+ * @ext_list_head:	the extent list head of which will be free.
+ */
+static void free_ext(struct fiemap_extent_list *ext_list_head)
+{
+	struct fiemap_extent_list	*ext_list_tmp = NULL;
+
+	if (ext_list_head == NULL)
+		return;
+
+	while (ext_list_head->next != ext_list_head) {
+		ext_list_tmp = ext_list_head;
+		ext_list_head->prev->next = ext_list_head->next;
+		ext_list_head->next->prev = ext_list_head->prev;
+		ext_list_head = ext_list_head->next;
+		free(ext_list_tmp);
+	}
+	free(ext_list_head);
+}
+
+/*
+ * free_exts_group() -		Free the exts_group.
+ *
+ * @*ext_group_head:	the exts_group list head which will be free.
+ */
+static void free_exts_group(struct fiemap_extent_group *ext_group_head)
+{
+	struct fiemap_extent_group	*ext_group_tmp = NULL;
+
+	if (ext_group_head == NULL)
+		return;
+
+	while (ext_group_head->next != ext_group_head) {
+		ext_group_tmp = ext_group_head;
+		ext_group_head->prev->next = ext_group_head->next;
+		ext_group_head->next->prev = ext_group_head->prev;
+		ext_group_head = ext_group_head->next;
+		free(ext_group_tmp);
+	}
+	free(ext_group_head);
+}
+
+/*
+ * get_best_count() -	Get the file best extents count.
+ *
+ * @block_count:		the file's physical block count.
+ */
+static int get_best_count(ext4_fsblk_t block_count)
+{
+	int ret;
+	unsigned int flex_bg_num;
+
+	/* Calcuate best extents count */
+	if (feature_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG) {
+		flex_bg_num = 1 << log_groups_per_flex;
+		ret = ((block_count - 1) /
+			((ext4_fsblk_t)blocks_per_group *
+				flex_bg_num)) + 1;
+	} else
+		ret = ((block_count - 1) / blocks_per_group) + 1;
+
+	return ret;
+}
+
+
+/*
+ * file_statistic() -	Get statistic info of the file's fragments.
+ *
+ * @file:		the file's name.
+ * @buf:		the pointer of the struct stat64.
+ * @flag:		file type.
+ * @ftwbuf:		the pointer of a struct FTW.
+ */
+static int file_statistic(const char *file, const struct stat64 *buf,
+			int flag EXT2FS_ATTR((unused)),
+			struct FTW *ftwbuf EXT2FS_ATTR((unused)))
+{
+	int	fd;
+	int	ret;
+	int	now_ext_count, best_ext_count = 0, physical_ext_count;
+	int	i, j;
+	__u64	size_per_ext = 0;
+	float	ratio = 0.0;
+	ext4_fsblk_t	blk_count = 0;
+	char	msg_buffer[PATH_MAX + 24];
+	struct fiemap_extent_list *physical_list_head = NULL;
+	struct fiemap_extent_list *logical_list_head = NULL;
+
+	defraged_file_count++;
+
+	if (mode_flag & DETAIL) {
+		if (total_count == 1 && regular_count == 1)
+			printf("<File>\n");
+		else {
+			printf("[%u/%u]", defraged_file_count, total_count);
+			fflush(stdout);
+		}
+	}
+	if (lost_found_dir[0] != '\0' &&
+	    !memcmp(file, lost_found_dir, strnlen(lost_found_dir, PATH_MAX))) {
+		if (mode_flag & DETAIL) {
+			PRINT_FILE_NAME(file);
+			STATISTIC_ERR_MSG(NGMSG_LOST_FOUND);
+		}
+			return 0;
+	}
+
+	if (!S_ISREG(buf->st_mode)) {
+		if (mode_flag & DETAIL) {
+			PRINT_FILE_NAME(file);
+			STATISTIC_ERR_MSG(NGMSG_FILE_UNREG);
+		}
+		return 0;
+	}
+
+	/* Access authority */
+	if (current_uid != ROOT_UID &&
+		buf->st_uid != current_uid) {
+		if (mode_flag & DETAIL) {
+			PRINT_FILE_NAME(file);
+			STATISTIC_ERR_MSG(
+				"File is not current user's file"
+				" or current user is not root");
+		}
+		return 0;
+	}
+
+	/* Empty file */
+	if (buf->st_size == 0) {
+		if (mode_flag & DETAIL) {
+			PRINT_FILE_NAME(file);
+			STATISTIC_ERR_MSG("File size is 0");
+		}
+		return 0;
+	}
+
+	/* Has no blocks */
+	if (buf->st_blocks == 0) {
+		if (mode_flag & DETAIL) {
+			PRINT_FILE_NAME(file);
+			STATISTIC_ERR_MSG("File has no blocks");
+		}
+		return 0;
+	}
+
+	fd = open64(file, O_RDONLY);
+	if (fd < 0) {
+		if (mode_flag & DETAIL) {
+			PRINT_FILE_NAME(file);
+			STATISTIC_ERR_MSG_WITH_ERRNO(NGMSG_FILE_OPEN);
+		}
+		return 0;
+	}
+
+	/* Get file's physical extents  */
+	ret = get_file_extents(fd, &physical_list_head);
+	if (ret < 0) {
+		if (mode_flag & DETAIL) {
+			PRINT_FILE_NAME(file);
+			STATISTIC_ERR_MSG_WITH_ERRNO(NGMSG_FILE_EXTENT);
+		}
+		goto out;
+	}
+
+	/* Get the count of file's continuous physical region */
+	physical_ext_count = get_physical_count(physical_list_head);
+
+	/* Change list from physical to logical */
+	ret = change_physical_to_logical(&physical_list_head,
+							&logical_list_head);
+	if (ret < 0) {
+		if (mode_flag & DETAIL) {
+			PRINT_FILE_NAME(file);
+			STATISTIC_ERR_MSG_WITH_ERRNO(NGMSG_FILE_EXTENT);
+		}
+		goto out;
+	}
+
+	/* Count file fragments before defrag */
+	now_ext_count = get_logical_count(logical_list_head);
+
+	if (current_uid == ROOT_UID) {
+		/* Calculate the size per extent */
+		blk_count = get_file_blocks(logical_list_head);
+
+		best_ext_count = get_best_count(blk_count);
+
+		/* e4defrag rounds size_per_ext up to a block size boundary */
+		size_per_ext = blk_count * (buf->st_blksize / 1024) /
+							now_ext_count;
+
+		ratio = (float)(physical_ext_count - best_ext_count) * 100 /
+							blk_count;
+
+		extents_before_defrag += now_ext_count;
+		extents_after_defrag += best_ext_count;
+		files_block_count += blk_count;
+	}
+
+	if (total_count == 1 && regular_count == 1) {
+		/* File only */
+		if (mode_flag & DETAIL) {
+			int count = 0;
+			struct fiemap_extent_list *ext_list_tmp =
+						logical_list_head;
+
+			/* Print extents info */
+			do {
+				count++;
+				printf("[ext %d]:\tstart %llu:\tlogical "
+						"%llu:\tlen %llu\n", count,
+						ext_list_tmp->data.physical,
+						ext_list_tmp->data.logical,
+						ext_list_tmp->data.len);
+				ext_list_tmp = ext_list_tmp->next;
+			} while (ext_list_tmp != logical_list_head);
+
+		} else {
+			printf("%-40s%10s/%-10s%9s\n",
+					"<File>", "now", "best", "size/ext");
+			if (current_uid == ROOT_UID) {
+				if (strlen(file) > 40)
+					printf("%s\n%50d/%-10d%6llu KB\n",
+						file, now_ext_count,
+						best_ext_count, size_per_ext);
+				else
+					printf("%-40s%10d/%-10d%6llu KB\n",
+						file, now_ext_count,
+						best_ext_count, size_per_ext);
+			} else {
+				if (strlen(file) > 40)
+					printf("%s\n%50d/%-10s%7s\n",
+							file, now_ext_count,
+							"-", "-");
+				else
+					printf("%-40s%10d/%-10s%7s\n",
+							file, now_ext_count,
+							"-", "-");
+			}
+		}
+		succeed_cnt++;
+		goto out;
+	}
+
+	if (mode_flag & DETAIL) {
+		/* Print statistic info */
+		sprintf(msg_buffer, "[%u/%u]%s",
+				defraged_file_count, total_count, file);
+		if (current_uid == ROOT_UID) {
+			if (strlen(msg_buffer) > 40)
+				printf("\033[79;0H\033[K%s\n"
+						"%50d/%-10d%6llu KB\n",
+						msg_buffer, now_ext_count,
+						best_ext_count, size_per_ext);
+			else
+				printf("\033[79;0H\033[K%-40s"
+						"%10d/%-10d%6llu KB\n",
+						msg_buffer, now_ext_count,
+						best_ext_count, size_per_ext);
+		} else {
+			if (strlen(msg_buffer) > 40)
+				printf("\033[79;0H\033[K%s\n%50d/%-10s%7s\n",
+						msg_buffer, now_ext_count,
+							"-", "-");
+			else
+				printf("\033[79;0H\033[K%-40s%10d/%-10s%7s\n",
+						msg_buffer, now_ext_count,
+							"-", "-");
+		}
+	}
+
+	for (i = 0; i < SHOW_FRAG_FILES; i++) {
+		if (ratio >= frag_rank[i].ratio) {
+			for (j = SHOW_FRAG_FILES - 1; j > i; j--) {
+				memset(&frag_rank[j], 0,
+					sizeof(struct frag_statistic_ino));
+				strncpy(frag_rank[j].msg_buffer,
+					frag_rank[j - 1].msg_buffer,
+					strnlen(frag_rank[j - 1].msg_buffer,
+					PATH_MAX));
+				frag_rank[j].now_count =
+					frag_rank[j - 1].now_count;
+				frag_rank[j].best_count =
+					frag_rank[j - 1].best_count;
+				frag_rank[j].size_per_ext =
+					frag_rank[j - 1].size_per_ext;
+				frag_rank[j].ratio =
+					frag_rank[j - 1].ratio;
+			}
+			memset(&frag_rank[i], 0,
+					sizeof(struct frag_statistic_ino));
+			strncpy(frag_rank[i].msg_buffer, file,
+						strnlen(file, PATH_MAX));
+			frag_rank[i].now_count = now_ext_count;
+			frag_rank[i].best_count = best_ext_count;
+			frag_rank[i].size_per_ext = size_per_ext;
+			frag_rank[i].ratio = ratio;
+			break;
+		}
+	}
+
+	succeed_cnt++;
+
+out:
+	close(fd);
+	free_ext(physical_list_head);
+	free_ext(logical_list_head);
+	return 0;
+}
+
+/*
+ * print_progress -	Print defrag progress
+ *
+ * @file:		file name.
+ * @start:		logical offset for defrag target file
+ * @file_size:		defrag target filesize
+ */
+static void print_progress(const char *file, loff_t start, loff_t file_size)
+{
+	int percent = (start * 100) / file_size;
+	printf("\033[79;0H\033[K[%u/%u]%s:\t%3d%%",
+		defraged_file_count, total_count, file, min(percent, 100));
+	fflush(stdout);
+
+	return;
+}
+
+/*
+ * call_defrag() -	Execute the defrag program.
+ *
+ * @fd:			target file descriptor.
+ * @donor_fd:		donor file descriptor.
+ * @file:			target file name.
+ * @buf:			pointer of the struct stat64.
+ * @ext_list_head:	head of the extent list.
+ */
+static int call_defrag(int fd, int donor_fd, const char *file,
+	const struct stat64 *buf, struct fiemap_extent_list *ext_list_head)
+{
+	loff_t	start = 0;
+	unsigned int	page_num;
+	unsigned char	*vec = NULL;
+	int	defraged_ret = 0;
+	int	ret;
+	struct move_extent	move_data;
+	struct fiemap_extent_list	*ext_list_tmp = NULL;
+
+	memset(&move_data, 0, sizeof(struct move_extent));
+	move_data.donor_fd = donor_fd;
+
+	/* Print defrag progress */
+	print_progress(file, start, buf->st_size);
+
+	ext_list_tmp = ext_list_head;
+	do {
+		move_data.orig_start = ext_list_tmp->data.logical;
+		/* Logical offset of orig and donor should be same */
+		move_data.donor_start = move_data.orig_start;
+		move_data.len = ext_list_tmp->data.len;
+		move_data.moved_len = 0;
+
+		ret = page_in_core(fd, move_data, &vec, &page_num);
+		if (ret < 0) {
+			if (mode_flag & DETAIL) {
+				printf("\n");
+				PRINT_ERR_MSG_WITH_ERRNO(
+						"Failed to get file map");
+			} else {
+				printf("\t[ NG ]\n");
+			}
+			return -1;
+		}
+
+		/* EXT4_IOC_MOVE_EXT */
+		defraged_ret =
+			ioctl(fd, EXT4_IOC_MOVE_EXT, &move_data);
+
+		/* Free pages */
+		ret = defrag_fadvise(fd, move_data, vec, page_num);
+		if (vec) {
+			free(vec);
+			vec = NULL;
+		}
+		if (ret < 0) {
+			if (mode_flag & DETAIL) {
+				printf("\n");
+				PRINT_ERR_MSG_WITH_ERRNO(
+					"Failed to free page");
+			} else {
+				printf("\t[ NG ]\n");
+			}
+			return -1;
+		}
+
+		if (defraged_ret < 0) {
+			if (mode_flag & DETAIL) {
+				printf("\n");
+				PRINT_ERR_MSG_WITH_ERRNO(
+					"Failed to defrag with "
+					"EXT4_IOC_MOVE_EXT ioctl");
+				if (errno == ENOTTY)
+					printf("\tAt least 2.6.31-rc1 of "
+						"vanilla kernel is required\n");
+			} else {
+				printf("\t[ NG ]\n");
+			}
+			return -1;
+		}
+		/* Adjust logical offset for next ioctl */
+		move_data.orig_start += move_data.moved_len;
+		move_data.donor_start = move_data.orig_start;
+
+		start = move_data.orig_start * buf->st_blksize;
+
+		/* Print defrag progress */
+		print_progress(file, start, buf->st_size);
+
+		/* End of file */
+		if (start >= buf->st_size)
+			break;
+
+		ext_list_tmp = ext_list_tmp->next;
+	} while (ext_list_tmp != ext_list_head);
+
+	return 0;
+}
+
+/*
+ * file_defrag() -		Check file attributes and call ioctl to defrag.
+ *
+ * @file:		the file's name.
+ * @buf:		the pointer of the struct stat64.
+ * @flag:		file type.
+ * @ftwbuf:		the pointer of a struct FTW.
+ */
+static int file_defrag(const char *file, const struct stat64 *buf,
+			int flag EXT2FS_ATTR((unused)),
+			struct FTW *ftwbuf EXT2FS_ATTR((unused)))
+{
+	int	fd;
+	int	donor_fd = -1;
+	int	ret;
+	int	best;
+	int	file_frags_start, file_frags_end;
+	int	orig_physical_cnt, donor_physical_cnt = 0;
+	char	tmp_inode_name[PATH_MAX + 8];
+	ext4_fsblk_t			blk_count = 0;
+	struct fiemap_extent_list	*orig_list_physical = NULL;
+	struct fiemap_extent_list	*orig_list_logical = NULL;
+	struct fiemap_extent_list	*donor_list_physical = NULL;
+	struct fiemap_extent_list	*donor_list_logical = NULL;
+	struct fiemap_extent_group	*orig_group_head = NULL;
+	struct fiemap_extent_group	*orig_group_tmp = NULL;
+
+	defraged_file_count++;
+
+	if (mode_flag & DETAIL) {
+		printf("[%u/%u]", defraged_file_count, total_count);
+		fflush(stdout);
+	}
+
+	if (lost_found_dir[0] != '\0' &&
+	    !memcmp(file, lost_found_dir, strnlen(lost_found_dir, PATH_MAX))) {
+		if (mode_flag & DETAIL) {
+			PRINT_FILE_NAME(file);
+			IN_FTW_PRINT_ERR_MSG(NGMSG_LOST_FOUND);
+		}
+		return 0;
+	}
+
+	if (!S_ISREG(buf->st_mode)) {
+		if (mode_flag & DETAIL) {
+			PRINT_FILE_NAME(file);
+			IN_FTW_PRINT_ERR_MSG(NGMSG_FILE_UNREG);
+		}
+		return 0;
+	}
+
+	/* Empty file */
+	if (buf->st_size == 0) {
+		if (mode_flag & DETAIL) {
+			PRINT_FILE_NAME(file);
+			IN_FTW_PRINT_ERR_MSG("File size is 0");
+		}
+		return 0;
+	}
+
+	/* Has no blocks */
+	if (buf->st_blocks == 0) {
+		if (mode_flag & DETAIL) {
+			PRINT_FILE_NAME(file);
+			STATISTIC_ERR_MSG("File has no blocks");
+		}
+		return 0;
+	}
+
+	fd = open64(file, O_RDWR);
+	if (fd < 0) {
+		if (mode_flag & DETAIL) {
+			PRINT_FILE_NAME(file);
+			PRINT_ERR_MSG_WITH_ERRNO(NGMSG_FILE_OPEN);
+		}
+		return 0;
+	}
+
+	/* Get file's extents */
+	ret = get_file_extents(fd, &orig_list_physical);
+	if (ret < 0) {
+		if (mode_flag & DETAIL) {
+			PRINT_FILE_NAME(file);
+			PRINT_ERR_MSG_WITH_ERRNO(NGMSG_FILE_EXTENT);
+		}
+		goto out;
+	}
+
+	/* Get the count of file's continuous physical region */
+	orig_physical_cnt = get_physical_count(orig_list_physical);
+
+	/* Change list from physical to logical */
+	ret = change_physical_to_logical(&orig_list_physical,
+							&orig_list_logical);
+	if (ret < 0) {
+		if (mode_flag & DETAIL) {
+			PRINT_FILE_NAME(file);
+			PRINT_ERR_MSG_WITH_ERRNO(NGMSG_FILE_EXTENT);
+		}
+		goto out;
+	}
+
+	/* Count file fragments before defrag */
+	file_frags_start = get_logical_count(orig_list_logical);
+
+	blk_count = get_file_blocks(orig_list_logical);
+	if (file_check(fd, buf, file, file_frags_start, blk_count) < 0)
+		goto out;
+
+	if (fsync(fd) < 0) {
+		if (mode_flag & DETAIL) {
+			PRINT_FILE_NAME(file);
+			PRINT_ERR_MSG_WITH_ERRNO("Failed to sync(fsync)");
+		}
+		goto out;
+	}
+
+	if (current_uid == ROOT_UID)
+		best = get_best_count(blk_count);
+	else
+		best = 1;
+
+	if (file_frags_start <= best)
+		goto check_improvement;
+
+	/* Combine extents to group */
+	ret = join_extents(orig_list_logical, &orig_group_head);
+	if (ret < 0) {
+		if (mode_flag & DETAIL) {
+			PRINT_FILE_NAME(file);
+			PRINT_ERR_MSG_WITH_ERRNO(NGMSG_FILE_EXTENT);
+		}
+		goto out;
+	}
+
+	/* Create donor inode */
+	memset(tmp_inode_name, 0, PATH_MAX + 8);
+	sprintf(tmp_inode_name, "%.*s.defrag",
+				(int)strnlen(file, PATH_MAX), file);
+	donor_fd = open64(tmp_inode_name, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR);
+	if (donor_fd < 0) {
+		if (mode_flag & DETAIL) {
+			PRINT_FILE_NAME(file);
+			if (errno == EEXIST)
+				PRINT_ERR_MSG_WITH_ERRNO(
+				"File is being defraged by other program");
+			else
+				PRINT_ERR_MSG_WITH_ERRNO(NGMSG_FILE_OPEN);
+		}
+		goto out;
+	}
+
+	/* Unlink donor inode */
+	ret = unlink(tmp_inode_name);
+	if (ret < 0) {
+		if (mode_flag & DETAIL) {
+			PRINT_FILE_NAME(file);
+			PRINT_ERR_MSG_WITH_ERRNO("Failed to unlink");
+		}
+		goto out;
+	}
+
+	/* Allocate space for donor inode */
+	orig_group_tmp = orig_group_head;
+	do {
+		ret = fallocate64(donor_fd, 0,
+		  (loff_t)orig_group_tmp->start->data.logical * block_size,
+		  (loff_t)orig_group_tmp->len * block_size);
+		if (ret < 0) {
+			if (mode_flag & DETAIL) {
+				PRINT_FILE_NAME(file);
+				PRINT_ERR_MSG_WITH_ERRNO("Failed to fallocate");
+			}
+			goto out;
+		}
+
+		orig_group_tmp = orig_group_tmp->next;
+	} while (orig_group_tmp != orig_group_head);
+
+	/* Get donor inode's extents */
+	ret = get_file_extents(donor_fd, &donor_list_physical);
+	if (ret < 0) {
+		if (mode_flag & DETAIL) {
+			PRINT_FILE_NAME(file);
+			PRINT_ERR_MSG_WITH_ERRNO(NGMSG_FILE_EXTENT);
+		}
+		goto out;
+	}
+
+	/* Calcuate donor inode's continuous physical region */
+	donor_physical_cnt = get_physical_count(donor_list_physical);
+
+	/* Change donor extent list from physical to logical */
+	ret = change_physical_to_logical(&donor_list_physical,
+							&donor_list_logical);
+	if (ret < 0) {
+		if (mode_flag & DETAIL) {
+			PRINT_FILE_NAME(file);
+			PRINT_ERR_MSG_WITH_ERRNO(NGMSG_FILE_EXTENT);
+		}
+		goto out;
+	}
+
+check_improvement:
+	if (mode_flag & DETAIL) {
+		if (file_frags_start != 1)
+			frag_files_before_defrag++;
+
+		extents_before_defrag += file_frags_start;
+	}
+
+	if (file_frags_start <= best ||
+			orig_physical_cnt <= donor_physical_cnt) {
+		printf("\033[79;0H\033[K[%u/%u]%s:\t%3d%%",
+			defraged_file_count, total_count, file, 100);
+		if (mode_flag & DETAIL)
+			printf("  extents: %d -> %d",
+				file_frags_start, file_frags_start);
+
+		printf("\t[ OK ]\n");
+		succeed_cnt++;
+
+		if (file_frags_start != 1)
+			frag_files_after_defrag++;
+
+		extents_after_defrag += file_frags_start;
+		goto out;
+	}
+
+	/* Defrag the file */
+	ret = call_defrag(fd, donor_fd, file, buf, donor_list_logical);
+
+	/* Count file fragments after defrag and print extents info */
+	if (mode_flag & DETAIL) {
+		file_frags_end = file_frag_count(fd);
+		if (file_frags_end < 0) {
+			printf("\n");
+			PRINT_ERR_MSG_WITH_ERRNO(NGMSG_FILE_INFO);
+			goto out;
+		}
+
+		if (file_frags_end != 1)
+			frag_files_after_defrag++;
+
+		extents_after_defrag += file_frags_end;
+
+		if (ret < 0)
+			goto out;
+
+		printf("  extents: %d -> %d",
+			file_frags_start, file_frags_end);
+		fflush(stdout);
+	}
+
+	if (ret < 0)
+		goto out;
+
+	printf("\t[ OK ]\n");
+	fflush(stdout);
+	succeed_cnt++;
+
+out:
+	close(fd);
+	if (donor_fd != -1)
+		close(donor_fd);
+	free_ext(orig_list_physical);
+	free_ext(orig_list_logical);
+	free_ext(donor_list_physical);
+	free_exts_group(orig_group_head);
+	return 0;
+}
+
+/*
+ * main() -		Ext4 online defrag.
+ *
+ * @argc:		the number of parameter.
+ * @argv[]:		the pointer array of parameter.
+ */
+int main(int argc, char *argv[])
+{
+	int	opt;
+	int	i, j, ret = 0;
+	int	flags = FTW_PHYS | FTW_MOUNT;
+	int	arg_type = -1;
+	int	success_flag = 0;
+	char	dir_name[PATH_MAX + 1];
+	char	dev_name[PATH_MAX + 1];
+	struct stat64	buf;
+	ext2_filsys fs = NULL;
+
+	/* Parse arguments */
+	if (argc == 1)
+		goto out;
+
+	while ((opt = getopt(argc, argv, "vc")) != EOF) {
+		switch (opt) {
+		case 'v':
+			mode_flag |= DETAIL;
+			break;
+		case 'c':
+			mode_flag |= STATISTIC;
+			break;
+		default:
+			goto out;
+		}
+	}
+
+	if (argc == optind)
+		goto out;
+
+	current_uid = getuid();
+
+	/* Main process */
+	for (i = optind; i < argc; i++) {
+		succeed_cnt = 0;
+		regular_count = 0;
+		total_count = 0;
+		frag_files_before_defrag = 0;
+		frag_files_after_defrag = 0;
+		extents_before_defrag = 0;
+		extents_after_defrag = 0;
+		defraged_file_count = 0;
+		files_block_count = 0;
+		blocks_per_group = 0;
+		feature_incompat = 0;
+		log_groups_per_flex = 0;
+
+		memset(dir_name, 0, PATH_MAX + 1);
+		memset(dev_name, 0, PATH_MAX + 1);
+		memset(lost_found_dir, 0, PATH_MAX + 1);
+		memset(frag_rank, 0,
+			sizeof(struct frag_statistic_ino) * SHOW_FRAG_FILES);
+
+		if ((mode_flag & STATISTIC) && i > optind)
+			printf("\n");
+
+#if BYTE_ORDER != BIG_ENDIAN && BYTE_ORDER != LITTLE_ENDIAN
+		PRINT_ERR_MSG("Endian's type is not big/little endian");
+		PRINT_FILE_NAME(argv[i]);
+		continue;
+#endif
+
+		if (lstat64(argv[i], &buf) < 0) {
+			perror(NGMSG_FILE_INFO);
+			PRINT_FILE_NAME(argv[i]);
+			continue;
+		}
+
+		/* Handle i.e. lvm device symlinks */
+		if (S_ISLNK(buf.st_mode)) {
+			struct stat64	buf2;
+
+			if (stat64(argv[i], &buf2) == 0 &&
+			    S_ISBLK(buf2.st_mode))
+				buf = buf2;
+		}
+
+		if (S_ISBLK(buf.st_mode)) {
+			/* Block device */
+			strncpy(dev_name, argv[i], strnlen(argv[i], PATH_MAX));
+			if (get_mount_point(argv[i], dir_name, PATH_MAX) < 0)
+				continue;
+			if (lstat64(dir_name, &buf) < 0) {
+				perror(NGMSG_FILE_INFO);
+				PRINT_FILE_NAME(argv[i]);
+				continue;
+			}
+			arg_type = DEVNAME;
+			if (!(mode_flag & STATISTIC))
+				printf("ext4 defragmentation for device(%s)\n",
+					argv[i]);
+		} else if (S_ISDIR(buf.st_mode)) {
+			/* Directory */
+			if (access(argv[i], R_OK) < 0) {
+				perror(argv[i]);
+				continue;
+			}
+			arg_type = DIRNAME;
+			strncpy(dir_name, argv[i], strnlen(argv[i], PATH_MAX));
+		} else if (S_ISREG(buf.st_mode)) {
+			/* Regular file */
+			arg_type = FILENAME;
+		} else {
+			/* Irregular file */
+			PRINT_ERR_MSG(NGMSG_FILE_UNREG);
+			PRINT_FILE_NAME(argv[i]);
+			continue;
+		}
+
+		/* Set blocksize */
+		block_size = buf.st_blksize;
+
+		/* For device case,
+		 * filesystem type checked in get_mount_point()
+		 */
+		if (arg_type == FILENAME || arg_type == DIRNAME) {
+			if (is_ext4(argv[i], dev_name) < 0)
+				continue;
+			if (realpath(argv[i], dir_name) == NULL) {
+				perror("Couldn't get full path");
+				PRINT_FILE_NAME(argv[i]);
+				continue;
+			}
+		}
+
+		if (current_uid == ROOT_UID) {
+			/* Get super block info */
+			ret = ext2fs_open(dev_name, 0, 0, block_size,
+					unix_io_manager, &fs);
+			if (ret) {
+				if (mode_flag & DETAIL) {
+					perror("Can't get super block info");
+					PRINT_FILE_NAME(argv[i]);
+				}
+				continue;
+			}
+
+			blocks_per_group = fs->super->s_blocks_per_group;
+			feature_incompat = fs->super->s_feature_incompat;
+			log_groups_per_flex = fs->super->s_log_groups_per_flex;
+
+			ext2fs_close(fs);
+		}
+
+		switch (arg_type) {
+			int mount_dir_len = 0;
+
+		case DIRNAME:
+			if (!(mode_flag & STATISTIC))
+				printf("ext4 defragmentation "
+					"for directory(%s)\n", argv[i]);
+
+			mount_dir_len = strnlen(lost_found_dir, PATH_MAX);
+
+			strncat(lost_found_dir, "/lost+found",
+				PATH_MAX - strnlen(lost_found_dir, PATH_MAX));
+
+			/* Not the case("e4defrag  mount_piont_dir") */
+			if (dir_name[mount_dir_len] != '\0') {
+				/*
+				 * "e4defrag mount_piont_dir/lost+found"
+				 * or "e4defrag mount_piont_dir/lost+found/"
+				 */
+				if (strncmp(lost_found_dir, dir_name,
+					    strnlen(lost_found_dir,
+						    PATH_MAX)) == 0 &&
+				    (dir_name[strnlen(lost_found_dir,
+						      PATH_MAX)] == '\0' ||
+				     dir_name[strnlen(lost_found_dir,
+						      PATH_MAX)] == '/')) {
+					PRINT_ERR_MSG(NGMSG_LOST_FOUND);
+					PRINT_FILE_NAME(argv[i]);
+					continue;
+				}
+
+				/* "e4defrag mount_piont_dir/else_dir" */
+				memset(lost_found_dir, 0, PATH_MAX + 1);
+			}
+		case DEVNAME:
+			if (arg_type == DEVNAME) {
+				strncpy(lost_found_dir, dir_name,
+					strnlen(dir_name, PATH_MAX));
+				strncat(lost_found_dir, "/lost+found/",
+					PATH_MAX - strnlen(lost_found_dir,
+							   PATH_MAX));
+			}
+
+			nftw64(dir_name, calc_entry_counts, FTW_OPEN_FD, flags);
+
+			if (mode_flag & STATISTIC) {
+				if (mode_flag & DETAIL)
+					printf("%-40s%10s/%-10s%9s\n",
+					"<File>", "now", "best", "size/ext");
+
+				if (!(mode_flag & DETAIL) &&
+						current_uid != ROOT_UID) {
+					printf(" Done.\n");
+					success_flag = 1;
+					continue;
+				}
+
+				nftw64(dir_name, file_statistic,
+							FTW_OPEN_FD, flags);
+
+				if (succeed_cnt != 0 &&
+					current_uid == ROOT_UID) {
+					if (mode_flag & DETAIL)
+						printf("\n");
+					printf("%-40s%10s/%-10s%9s\n",
+						"<Fragmented files>", "now",
+						"best", "size/ext");
+					for (j = 0; j < SHOW_FRAG_FILES; j++) {
+						if (strlen(frag_rank[j].
+							msg_buffer) > 37) {
+							printf("%d. %s\n%50d/"
+							"%-10d%6llu KB\n",
+							j + 1,
+							frag_rank[j].msg_buffer,
+							frag_rank[j].now_count,
+							frag_rank[j].best_count,
+							frag_rank[j].
+								size_per_ext);
+						} else if (strlen(frag_rank[j].
+							msg_buffer) > 0) {
+							printf("%d. %-37s%10d/"
+							"%-10d%6llu KB\n",
+							j + 1,
+							frag_rank[j].msg_buffer,
+							frag_rank[j].now_count,
+							frag_rank[j].best_count,
+							frag_rank[j].
+								size_per_ext);
+						} else
+							break;
+					}
+				}
+				break;
+			}
+			/* File tree walk */
+			nftw64(dir_name, file_defrag, FTW_OPEN_FD, flags);
+			printf("\n\tSuccess:\t\t\t[ %u/%u ]\n", succeed_cnt,
+				total_count);
+			printf("\tFailure:\t\t\t[ %u/%u ]\n",
+				total_count - succeed_cnt, total_count);
+			if (mode_flag & DETAIL) {
+				printf("\tTotal extents:\t\t\t%4d->%d\n",
+					extents_before_defrag,
+					extents_after_defrag);
+				printf("\tFragmented percentage:\t\t"
+					"%3llu%%->%llu%%\n",
+					!regular_count ? 0 :
+					((unsigned long long)
+					frag_files_before_defrag * 100) /
+					regular_count,
+					!regular_count ? 0 :
+					((unsigned long long)
+					frag_files_after_defrag * 100) /
+					regular_count);
+			}
+			break;
+		case FILENAME:
+			total_count = 1;
+			regular_count = 1;
+			strncat(lost_found_dir, "/lost+found/",
+				PATH_MAX - strnlen(lost_found_dir,
+						   PATH_MAX));
+			if (strncmp(lost_found_dir, dir_name,
+				    strnlen(lost_found_dir,
+					    PATH_MAX)) == 0) {
+				PRINT_ERR_MSG(NGMSG_LOST_FOUND);
+				PRINT_FILE_NAME(argv[i]);
+				continue;
+			}
+
+			if (mode_flag & STATISTIC) {
+				file_statistic(argv[i], &buf, FTW_F, NULL);
+				break;
+			} else
+				printf("ext4 defragmentation for %s\n",
+								 argv[i]);
+			/* Defrag single file process */
+			file_defrag(argv[i], &buf, FTW_F, NULL);
+			if (succeed_cnt != 0)
+				printf(" Success:\t\t\t[1/1]\n");
+			else
+				printf(" Success:\t\t\t[0/1]\n");
+
+			break;
+		}
+
+		if (succeed_cnt != 0)
+			success_flag = 1;
+		if (mode_flag & STATISTIC) {
+			if (current_uid != ROOT_UID) {
+				printf(" Done.\n");
+				continue;
+			}
+
+			if (!succeed_cnt) {
+				if (mode_flag & DETAIL)
+					printf("\n");
+
+				if (arg_type == DEVNAME)
+					printf(" In this device(%s), "
+					"none can be defragmented.\n", argv[i]);
+				else if (arg_type == DIRNAME)
+					printf(" In this directory(%s), "
+					"none can be defragmented.\n", argv[i]);
+				else
+					printf(" This file(%s) "
+					"can't be defragmented.\n", argv[i]);
+			} else {
+				float files_ratio = 0.0;
+				float score = 0.0;
+				__u64 size_per_ext = files_block_count *
+						(buf.st_blksize / 1024) /
+						extents_before_defrag;
+				files_ratio = (float)(extents_before_defrag -
+						extents_after_defrag) *
+						100 / files_block_count;
+				score = CALC_SCORE(files_ratio);
+				printf("\n Total/best extents\t\t\t\t%d/%d\n"
+					" Average size per extent"
+					"\t\t\t%llu KB\n"
+					" Fragmentation score\t\t\t\t%.0f\n",
+						extents_before_defrag,
+						extents_after_defrag,
+						size_per_ext, score);
+				printf(" [0-30 no problem:"
+					" 31-55 a little bit fragmented:"
+					" 56- needs defrag]\n");
+
+				if (arg_type == DEVNAME)
+					printf(" This device (%s) ", argv[i]);
+				else if (arg_type == DIRNAME)
+					printf(" This directory (%s) ",
+								argv[i]);
+				else
+					printf(" This file (%s) ", argv[i]);
+
+				if (score > BOUND_SCORE)
+					printf("needs defragmentation.\n");
+				else
+					printf("does not need "
+							"defragmentation.\n");
+			}
+			printf(" Done.\n");
+		}
+
+	}
+
+	if (success_flag)
+		return 0;
+
+	exit(1);
+
+out:
+	printf(MSG_USAGE);
+	exit(1);
+}
+
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/ext4.5.in b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/ext4.5.in
new file mode 100644
index 0000000..98494ec
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/ext4.5.in
@@ -0,0 +1,257 @@
+.\" -*- nroff -*-
+.\" Copyright 1993, 1994, 1995 by Theodore Ts'o.  All Rights Reserved.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH EXT4 5 "@E2FSPROGS_MONTH@ @E2FSPROGS_YEAR@" "E2fsprogs version @E2FSPROGS_VERSION@"
+.SH NAME
+ext2 \- the second extended file system
+.br
+ext2 \- the third extended file system
+.br
+ext4 \- the fourth extended file system
+.SH DESCRIPTION
+The second, third, and fourth extended file systems, or ext2, ext3, and
+ext4 as they are commonly known, are Linux file systems that have
+historically been the default file system for many Linux distributions.
+They are general purpose file systems that have been designed for
+extensibility and backwards compatibility.  In particular, file systems
+previously intended for use with the ext2 and ext3 file systems can be
+mounted using the ext4 file system driver, and indeed in many modern
+Linux distributions, the ext4 file system driver has been configured
+handle mount requests for ext2 and ext3 file systems.
+.SH FILE SYSTEM FEATURES
+A file system formated for ext2, ext3, or ext4 can be have some
+collection of the follow file system feature flags enabled.  Some of
+these features are not supported by all implementations of the ext2,
+ext3, and ext4 file system drivers, depending on Linux kernel version in
+use.  On other operating systems, such as the GNU/HURD or FreeBSD, only
+a very restrictive set of file system features may be supported in their
+implementations of ext2.
+.RS 1.2i
+.TP
+.B 64bit
+.br
+Enables the file system to be larger than 2^32 blocks.  This feature is set
+automatically, as needed, but it can be useful to specify this feature
+explicitly if the file system might need to be resized larger than 2^32
+blocks, even if it was smaller than that threshold when it was
+originally created.  Note that some older kernels and older versions
+of e2fsprogs will not support file systems with this ext4 feature enabled.
+.TP
+.B bigalloc
+.br
+This ext4 feature enables clustered block allocation, so that the unit of
+allocation is a power of two number of blocks.  That is, each bit in the
+what had traditionally been known as the block allocation bitmap now
+indicates whether a cluster is in use or not, where a cluster is by
+default composed of 16 blocks.  This feature can decrease the time
+spent on doing block allocation and brings smaller fragmentation, especially
+for large files.  The size can be specified using the
+.B \-C option.
+.IP
+.B Warning:
+The bigalloc feature is still under development, and may not be fully
+supported with your kernel or may have various bugs.  Please see the web
+page http://ext4.wiki.kernel.org/index.php/Bigalloc for details.
+May clash with delayed allocation (see
+.BR nodelalloc mount option).
+.IP
+This feature requires that the
+.B extent
+features be enabled.
+.TP
+.B dir_index
+.br
+Use hashed b-trees to speed up name lookups in large directories.  This
+feature is supported by ext3 and ext4 file systems, and is ignored by
+ext2 file systems.
+.TP
+.B dir_nlink
+.br
+This ext4 feature allows more than 65000 subdirectories per directory.
+.TP
+.B extent
+.br
+This ext4 feature allows the mapping of logical block numbers for a
+particular inode to physical blocks on the storage device to be stored
+using an extent tree, which is a more efficient data structure than the
+traditional indirect block scheme used by the ext2 and ext3 file
+systems.  The use of the extent tree decreases metadata block overhead,
+improves file system performance, and decreases the needed to run
+.BR e2fsck (8)
+on the file system.
+(Note: both
+.B extent
+and
+.B extents
+are accepted as valid names for this feature for
+historical/backwards compatibility reasons.)
+.TP
+.B extra_isize
+.br
+This ext4 feature reserves a specific amount of space in each inode for
+extended metadata such as nanosecond timestamps and file creation time,
+even if the current kernel does not current need to reserve this much
+space.  Without this feature, the kernel will reserve the amount of
+space for features currently it currently needs, and the rest may be
+consumed by extended attributes.
+
+For this feature to be useful the inode size must be 256 bytes in size
+or larger.
+.TP
+.B ext_attr
+.br
+This feature enables the use of extended attributes.  This feature is
+supported by ext2, ext3, and ext4.
+.TP
+.B filetype
+.br
+This feature enables the storage file type information in directory
+entries.  This feature is supported by ext2, ext3, and ext4.
+.TP
+.TP
+.B flex_bg
+.br
+This ext4 feature allows the per-block group metadata (allocation
+bitmaps
+and inode tables)
+to be placed anywhere on the storage media.  In addition,
+.B mke2fs
+will place the per-block group metadata together starting at the first
+block group of each "flex_bg group".   The size of the flex_bg group
+can be specified using the
+.B \-G
+option.
+.TP
+.B has_journal
+.br
+Create a journal to ensure filesystem consistency even across unclean
+shutdowns.  Setting the filesystem feature is equivalent to using the
+.B \-j
+option.  This feature is supported by ext3 and ext4, and ignored by the
+ext2 file system driver.
+.TP
+.B huge_file
+.br
+This ext4 feature allows files to be larger than 2 terabytes in size.
+.TP
+.B journal_dev
+.br
+This feature is enabled on the superblock found on an external journal
+device.  The block size for the external journal must be the same as the
+file system which uses it.
+.IP
+The external journal device can be used by a file system by specifying
+the
+.B \-J
+.BR device= <external-device>
+option to
+.BR mke2fs (8)
+or
+.BR tune2fs(8).
+.TP
+.B large_file
+.br
+This feature flag is set automatically by modern kernels when a file
+larger than 2 gigabytes is created.  Very old kernels could not
+handle large files, so this feature flag was used to prohibit those
+kernels from mounting file systems that they could not understand.
+.\" .TP
+.\" .B metadata_csum
+.\" .br
+.\" This ext4 feature enables metadata checksumming.  This feature stores
+.\" checksums for all of the filesystem metadata (superblock, group
+.\" descriptor blocks, inode and block bitmaps, directories, and
+.\" extent tree blocks).  The checksum algorithm used for the metadata
+.\" blocks is different than the one used for group descriptors with the
+.\" .B uninit_bg
+.\" feature, these two features are incompatible and
+.\" .B metadata_csum
+.\" will be used preferentially instead of
+.\" .BR uninit_bg .
+.\" .br
+.\" .B Future feature, available in e2fsprogs 1.43-WIP
+.TP
+.B meta_bg
+.br
+This ext4 feature allows file systems to be resized on-line without explicitly
+needing to reserve space for growth in the size of the block group
+descriptors.  This scheme is also used to resize file systems which are
+larger than 2^32 blocks.  It is not recommended that this feature be set
+when a file system is created, since this alternate method of storing
+the block group descriptor will slow down the time needed to mount the
+file system, and newer kernels can automatically set this feature as
+necessary when doing an online resize and no more reserved space is
+available in the resize inode.
+.TP
+.B mmp
+.br
+This ext4 feature provides multiple mount protection (MMP).  MMP helps to
+protect the filesystem from being multiply mounted and is useful in
+shared storage environments.
+@QUOTA_MAN_COMMENT@.TP
+@QUOTA_MAN_COMMENT@.B quota
+@QUOTA_MAN_COMMENT@.br
+@QUOTA_MAN_COMMENT@Create quota inodes (inode #3 for userquota and inode
+@QUOTA_MAN_COMMENT@#4 for group quota) and set them in the superblock.
+@QUOTA_MAN_COMMENT@With this feature, the quotas will be enabled
+@QUOTA_MAN_COMMENT@automatically when the filesystem is mounted.
+@QUOTA_MAN_COMMENT@.IP
+@QUOTA_MAN_COMMENT@Causes the quota files (i.e., user.quota and
+@QUOTA_MAN_COMMENT@group.quota which existed
+@QUOTA_MAN_COMMENT@in the older quota design) to be hidden inodes.
+@QUOTA_MAN_COMMENT@.IP
+@QUOTA_MAN_COMMENT@.B Warning:
+@QUOTA_MAN_COMMENT@The quota feature is still under development,
+@QUOTA_MAN_COMMENT@and may not be fully supported with your kernel
+@QUOTA_MAN_COMMENT@or may have various bugs.  Please
+@QUOTA_MAN_COMMENT@see https://ext4.wiki.kernel.org/index.php/Quota
+@QUOTA_MAN_COMMENT@for more details.
+.TP
+.B resize_inode
+.br
+This file system feature indicates that space has been reserved so
+the block group descriptor table can be extended by the file system is
+resized while the file system is mounted.  The online resize operation
+is carried out by the kernel, triggered, by
+.BR resize2fs (8).
+By default
+.B mke2fs
+will attempt to reserve enough space so that the
+filesystem may grow to 1024 times its initial size.  This can be changed
+using the
+.B resize
+extended option.
+.IP
+This feature requires that the
+.B sparse_super
+feature be enabled.
+.TP
+.B sparse_super
+.br
+This file system feature is set on all modern ext2, ext3, and ext4 file
+system.  It indicates that backup copies of the superblock and block
+group descriptors be present only on a few block groups, and not all of
+them.
+.TP
+.B uninit_bg
+.br
+This ext4 file system feature indicates that the block group descriptors
+will be protected using checksums, making it safe for
+.BR mke2fs (8)
+to create a file system without initializing all of the block groups.
+The kernel will keep a high watermark of unused inodes, and initialize
+inode tables and block lazily.  This feature speeds up the time to check
+the file system using
+.BR e2fsck (8),
+and it also speeds up the time required for
+.BR mke2fs (8)
+to create the file system.
+.RE
+.SH SEE ALSO
+.BR mke2fs (8),
+.BR mke2fs.conf (5),
+.BR e2fsck (8),
+.BR dumpe2fs (8),
+.BR tune2fs (8),
+.BR debugfs (8)
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/filefrag.8.in b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/filefrag.8.in
new file mode 100644
index 0000000..a6d7b27
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/filefrag.8.in
@@ -0,0 +1,62 @@
+.\" -*- nroff -*-
+.TH FILEFRAG 8 "@E2FSPROGS_MONTH@ @E2FSPROGS_YEAR@" "E2fsprogs version @E2FSPROGS_VERSION@"
+.SH NAME
+filefrag \- report on file fragmentation
+.SH SYNOPSIS
+.B filefrag
+[
+.BI \-b blocksize
+]
+[
+.B \-BeksvxX
+]
+[
+.I files...
+]
+.SH DESCRIPTION
+.B filefrag
+reports on how badly fragmented a particular file might be.  It makes 
+allowances for indirect blocks for ext2 and ext3 filesystems, but can be
+used on files for any filesystem.
+.PP
+The 
+.B filefrag
+program initially attempts to get the
+extent information using FIEMAP ioctl which is more efficient and faster.
+If FIEMAP is not supported then filefrag will fall back to using FIBMAP.
+.SH OPTIONS
+.TP
+.B \-B
+Force the use of the older FIBMAP ioctl instead of the FIEMAP ioctl for
+testing purposes.
+.TP
+.BI \-b blocksize
+Use
+.I blocksize
+in bytes for output instead of the filesystem blocksize.
+For compatibility with earlier versions of
+.BR filefrag ,
+if
+.I blocksize
+is unspecified it defaults to 1024 bytes.
+.TP
+.B \-e
+Print output in extent format, even for block-mapped files.
+.TP
+.BI \-k
+Use 1024\-byte blocksize for output (identical to '\-b 1024').
+.TP
+.B \-s
+Sync the file before requesting the mapping.
+.TP
+.B \-v
+Be verbose when checking for file fragmentation.
+.TP
+.B \-x
+Display mapping of extended attributes.
+.TP
+.B \-X
+Display extent block numbers in hexadecimal format.
+.SH AUTHOR
+.B filefrag
+was written by Theodore Ts'o <tytso@mit.edu>.
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/filefrag.c b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/filefrag.c
new file mode 100644
index 0000000..a050a22
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/filefrag.c
@@ -0,0 +1,525 @@
+/*
+ * filefrag.c -- report if a particular file is fragmented
+ *
+ * Copyright 2003 by Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include "config.h"
+#ifndef __linux__
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+int main(void) {
+	fputs("This program is only supported on Linux!\n", stderr);
+	exit(EXIT_FAILURE);
+}
+#else
+#define _LARGEFILE64_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <time.h>
+#include <fcntl.h>
+#include <errno.h>
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#else
+extern char *optarg;
+extern int optind;
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/vfs.h>
+#include <sys/ioctl.h>
+#include <linux/fd.h>
+#include <ext2fs/ext2fs.h>
+#include <ext2fs/ext2_types.h>
+#include <ext2fs/fiemap.h>
+
+int verbose = 0;
+int blocksize;		/* Use specified blocksize (default 1kB) */
+int sync_file = 0;	/* fsync file before getting the mapping */
+int xattr_map = 0;	/* get xattr mapping */
+int force_bmap;	/* force use of FIBMAP instead of FIEMAP */
+int force_extent;	/* print output in extent format always */
+int logical_width = 8;
+int physical_width = 10;
+const char *ext_fmt = "%4d: %*llu..%*llu: %*llu..%*llu: %6llu: %s\n";
+const char *hex_fmt = "%4d: %*llx..%*llx: %*llx..%*llx: %6llx: %s\n";
+
+#define FILEFRAG_FIEMAP_FLAGS_COMPAT (FIEMAP_FLAG_SYNC | FIEMAP_FLAG_XATTR)
+
+#define FIBMAP		_IO(0x00, 1)	/* bmap access */
+#define FIGETBSZ	_IO(0x00, 2)	/* get the block size used for bmap */
+
+#define LUSTRE_SUPER_MAGIC 0x0BD00BD0
+
+#define	EXT4_EXTENTS_FL			0x00080000 /* Inode uses extents */
+#define	EXT3_IOC_GETFLAGS		_IOR('f', 1, long)
+
+static int int_log2(int arg)
+{
+	int     l = 0;
+
+	arg >>= 1;
+	while (arg) {
+		l++;
+		arg >>= 1;
+	}
+	return l;
+}
+
+static int int_log10(unsigned long long arg)
+{
+	int     l = 0;
+
+	arg = arg / 10;
+	while (arg) {
+		l++;
+		arg = arg / 10;
+	}
+	return l;
+}
+
+static unsigned int div_ceil(unsigned int a, unsigned int b)
+{
+	if (!a)
+		return 0;
+	return ((a - 1) / b) + 1;
+}
+
+static int get_bmap(int fd, unsigned long block, unsigned long *phy_blk)
+{
+	int	ret;
+	unsigned int b;
+
+	b = block;
+	ret = ioctl(fd, FIBMAP, &b); /* FIBMAP takes pointer to integer */
+	if (ret < 0) {
+		if (errno == EPERM) {
+			fprintf(stderr, "No permission to use FIBMAP ioctl; "
+				"must have root privileges\n");
+		}
+	}
+	*phy_blk = b;
+
+	return ret;
+}
+
+static void print_extent_header(void)
+{
+	printf(" ext: %*s %*s length: %*s flags:\n",
+	       logical_width * 2 + 3,
+	       "logical_offset:",
+	       physical_width * 2 + 3, "physical_offset:",
+	       physical_width + 1,
+	       "expected:");
+}
+
+static void print_extent_info(struct fiemap_extent *fm_extent, int cur_ex,
+			      unsigned long long expected, int blk_shift,
+			      ext2fs_struct_stat *st)
+{
+	unsigned long long physical_blk;
+	unsigned long long logical_blk;
+	unsigned long long ext_len;
+	unsigned long long ext_blks;
+	char flags[256] = "";
+
+	/* For inline data all offsets should be in bytes, not blocks */
+	if (fm_extent->fe_flags & FIEMAP_EXTENT_DATA_INLINE)
+		blk_shift = 0;
+
+	ext_len = fm_extent->fe_length >> blk_shift;
+	ext_blks = (fm_extent->fe_length - 1) >> blk_shift;
+	logical_blk = fm_extent->fe_logical >> blk_shift;
+	physical_blk = fm_extent->fe_physical >> blk_shift;
+
+	if (expected)
+		sprintf(flags, ext_fmt == hex_fmt ? "%*llx: " : "%*llu: ",
+			physical_width, expected >> blk_shift);
+	else
+		sprintf(flags, "%.*s  ", physical_width, "                   ");
+
+	if (fm_extent->fe_flags & FIEMAP_EXTENT_UNKNOWN)
+		strcat(flags, "unknown,");
+	if (fm_extent->fe_flags & FIEMAP_EXTENT_DELALLOC)
+		strcat(flags, "delalloc,");
+	if (fm_extent->fe_flags & FIEMAP_EXTENT_DATA_ENCRYPTED)
+		strcat(flags, "encrypted,");
+	if (fm_extent->fe_flags & FIEMAP_EXTENT_NOT_ALIGNED)
+		strcat(flags, "not_aligned,");
+	if (fm_extent->fe_flags & FIEMAP_EXTENT_DATA_INLINE)
+		strcat(flags, "inline,");
+	if (fm_extent->fe_flags & FIEMAP_EXTENT_DATA_TAIL)
+		strcat(flags, "tail_packed,");
+	if (fm_extent->fe_flags & FIEMAP_EXTENT_UNWRITTEN)
+		strcat(flags, "unwritten,");
+	if (fm_extent->fe_flags & FIEMAP_EXTENT_MERGED)
+		strcat(flags, "merged,");
+
+	if (fm_extent->fe_logical + fm_extent->fe_length >= (__u64) st->st_size)
+		strcat(flags, "eof,");
+
+	/* Remove trailing comma, if any */
+	if (flags[0])
+		flags[strlen(flags) - 1] = '\0';
+
+	printf(ext_fmt, cur_ex, logical_width, logical_blk,
+	       logical_width, logical_blk + ext_blks,
+	       physical_width, physical_blk,
+	       physical_width, physical_blk + ext_blks,
+	       ext_len, flags);
+}
+
+static int filefrag_fiemap(int fd, int blk_shift, int *num_extents,
+			   ext2fs_struct_stat *st)
+{
+	char buf[16384];
+	struct fiemap *fiemap = (struct fiemap *)buf;
+	struct fiemap_extent *fm_ext = &fiemap->fm_extents[0];
+	int count = (sizeof(buf) - sizeof(*fiemap)) /
+			sizeof(struct fiemap_extent);
+	unsigned long long expected = 0;
+	unsigned long flags = 0;
+	unsigned int i;
+	static int fiemap_incompat_printed;
+	int fiemap_header_printed = 0;
+	int tot_extents = 0, n = 0;
+	int last = 0;
+	int rc;
+
+	memset(fiemap, 0, sizeof(struct fiemap));
+
+	if (sync_file)
+		flags |= FIEMAP_FLAG_SYNC;
+
+	if (xattr_map)
+		flags |= FIEMAP_FLAG_XATTR;
+
+	do {
+		fiemap->fm_length = ~0ULL;
+		fiemap->fm_flags = flags;
+		fiemap->fm_extent_count = count;
+		rc = ioctl(fd, FS_IOC_FIEMAP, (unsigned long) fiemap);
+		if (rc < 0) {
+			if (errno == EBADR && fiemap_incompat_printed == 0) {
+				printf("FIEMAP failed with unsupported "
+				       "flags %x\n", fiemap->fm_flags);
+				fiemap_incompat_printed = 1;
+			}
+			return rc;
+		}
+
+		/* If 0 extents are returned, then more ioctls are not needed */
+		if (fiemap->fm_mapped_extents == 0)
+			break;
+
+		if (verbose && !fiemap_header_printed) {
+			print_extent_header();
+			fiemap_header_printed = 1;
+		}
+
+		for (i = 0; i < fiemap->fm_mapped_extents; i++) {
+			if (fm_ext[i].fe_logical != 0 &&
+			    fm_ext[i].fe_physical != expected) {
+				tot_extents++;
+			} else {
+				expected = 0;
+				if (!tot_extents)
+					tot_extents = 1;
+			}
+			if (verbose)
+				print_extent_info(&fm_ext[i], n, expected,
+						  blk_shift, st);
+
+			expected = fm_ext[i].fe_physical + fm_ext[i].fe_length;
+			if (fm_ext[i].fe_flags & FIEMAP_EXTENT_LAST)
+				last = 1;
+			n++;
+		}
+
+		fiemap->fm_start = (fm_ext[i - 1].fe_logical +
+				    fm_ext[i - 1].fe_length);
+	} while (last == 0);
+
+	*num_extents = tot_extents;
+
+	return 0;
+}
+
+#define EXT2_DIRECT	12
+
+static int filefrag_fibmap(int fd, int blk_shift, int *num_extents,
+			   ext2fs_struct_stat *st,
+			   unsigned long numblocks, int is_ext2)
+{
+	struct fiemap_extent	fm_ext;
+	unsigned long		i, last_block;
+	unsigned long long	logical;
+				/* Blocks per indirect block */
+	const long		bpib = st->st_blksize / 4;
+	int			count;
+
+	if (force_extent) {
+		memset(&fm_ext, 0, sizeof(fm_ext));
+		fm_ext.fe_flags = FIEMAP_EXTENT_MERGED;
+	}
+
+	if (sync_file)
+		fsync(fd);
+
+	for (i = 0, logical = 0, *num_extents = 0, count = last_block = 0;
+	     i < numblocks;
+	     i++, logical += st->st_blksize) {
+		unsigned long block = 0;
+		int rc;
+
+		if (is_ext2 && last_block) {
+			if (((i - EXT2_DIRECT) % bpib) == 0)
+				last_block++;
+			if (((i - EXT2_DIRECT - bpib) % (bpib * bpib)) == 0)
+				last_block++;
+			if (((i - EXT2_DIRECT - bpib - bpib * bpib) %
+			     (((unsigned long long)bpib) * bpib * bpib)) == 0)
+				last_block++;
+		}
+		rc = get_bmap(fd, i, &block);
+		if (rc < 0)
+			return rc;
+		if (block == 0)
+			continue;
+		if (*num_extents == 0) {
+			(*num_extents)++;
+			if (force_extent) {
+				print_extent_header();
+				fm_ext.fe_physical = block * st->st_blksize;
+			}
+		}
+		count++;
+		if (force_extent && last_block != 0 &&
+		    (block != last_block + 1 ||
+		     fm_ext.fe_logical + fm_ext.fe_length != logical)) {
+			print_extent_info(&fm_ext, *num_extents - 1,
+					  (last_block + 1) * st->st_blksize,
+					  blk_shift, st);
+			fm_ext.fe_logical = logical;
+			fm_ext.fe_physical = block * st->st_blksize;
+			fm_ext.fe_length = 0;
+			(*num_extents)++;
+		} else if (verbose && last_block && (block != last_block + 1)) {
+			printf("Discontinuity: Block %ld is at %lu (was %lu)\n",
+			       i, block, last_block + 1);
+			(*num_extents)++;
+		}
+		fm_ext.fe_length += st->st_blksize;
+		last_block = block;
+	}
+
+	if (force_extent)
+		print_extent_info(&fm_ext, *num_extents - 1,
+				  last_block * st->st_blksize, blk_shift, st);
+
+	return count;
+}
+
+static void frag_report(const char *filename)
+{
+	static struct statfs fsinfo;
+	ext2fs_struct_stat st;
+	int		blk_shift;
+	long		fd;
+	unsigned long	numblocks;
+	int		data_blocks_per_cyl = 1;
+	int		num_extents = 1, expected = ~0;
+	int		is_ext2 = 0;
+	static dev_t	last_device;
+	unsigned int	flags;
+	int		width;
+
+#if defined(HAVE_OPEN64) && !defined(__OSX_AVAILABLE_BUT_DEPRECATED)
+	fd = open64(filename, O_RDONLY);
+#else
+	fd = open(filename, O_RDONLY);
+#endif
+	if (fd < 0) {
+		perror("open");
+		return;
+	}
+
+#if defined(HAVE_FSTAT64) && !defined(__OSX_AVAILABLE_BUT_DEPRECATED)
+	if (fstat64(fd, &st) < 0) {
+#else
+	if (fstat(fd, &st) < 0) {
+#endif
+		close(fd);
+		perror("stat");
+		return;
+	}
+
+	if (last_device != st.st_dev) {
+		if (fstatfs(fd, &fsinfo) < 0) {
+			close(fd);
+			perror("fstatfs");
+			return;
+		}
+		if (verbose)
+			printf("Filesystem type is: %lx\n",
+			       (unsigned long) fsinfo.f_type);
+	}
+	st.st_blksize = fsinfo.f_bsize;
+	if (ioctl(fd, EXT3_IOC_GETFLAGS, &flags) < 0)
+		flags = 0;
+	if (!(flags & EXT4_EXTENTS_FL) &&
+	    ((fsinfo.f_type == 0xef51) || (fsinfo.f_type == 0xef52) ||
+	     (fsinfo.f_type == 0xef53)))
+		is_ext2++;
+
+	if (is_ext2) {
+		long cylgroups = div_ceil(fsinfo.f_blocks, fsinfo.f_bsize * 8);
+
+		if (verbose && last_device != st.st_dev)
+			printf("Filesystem cylinder groups approximately %ld\n",
+			       cylgroups);
+
+		data_blocks_per_cyl = fsinfo.f_bsize * 8 -
+					(fsinfo.f_files / 8 / cylgroups) - 3;
+	}
+	last_device = st.st_dev;
+
+	width = int_log10(fsinfo.f_blocks);
+	if (width > physical_width)
+		physical_width = width;
+
+	numblocks = (st.st_size + fsinfo.f_bsize - 1) / fsinfo.f_bsize;
+	if (blocksize != 0)
+		blk_shift = int_log2(blocksize);
+	else
+		blk_shift = int_log2(fsinfo.f_bsize);
+
+	width = int_log10(numblocks);
+	if (width > logical_width)
+		logical_width = width;
+	if (verbose)
+		printf("File size of %s is %llu (%lu block%s of %d bytes)\n",
+		       filename, (unsigned long long)st.st_size,
+		       numblocks * fsinfo.f_bsize >> blk_shift,
+		       numblocks == 1 ? "" : "s", 1 << blk_shift);
+
+	if (force_bmap ||
+	    filefrag_fiemap(fd, blk_shift, &num_extents, &st) != 0) {
+		expected = filefrag_fibmap(fd, blk_shift, &num_extents,
+					   &st, numblocks, is_ext2);
+		if (expected < 0) {
+			if (errno == EINVAL || errno == ENOTTY) {
+				fprintf(stderr, "%s: FIBMAP unsupported\n",
+					filename);
+			} else if (errno != EPERM) {
+				fprintf(stderr, "%s: FIBMAP error: %s",
+					filename, strerror(errno));
+			}
+			goto out_close;
+		}
+		expected = expected / data_blocks_per_cyl + 1;
+	}
+
+	if (num_extents == 1)
+		printf("%s: 1 extent found", filename);
+	else
+		printf("%s: %d extents found", filename, num_extents);
+	/* count, and thus expected, only set for indirect FIBMAP'd files */
+	if (is_ext2 && expected && expected < num_extents)
+		printf(", perfection would be %d extent%s\n", expected,
+			(expected > 1) ? "s" : "");
+	else
+		fputc('\n', stdout);
+out_close:
+	close(fd);
+}
+
+static void usage(const char *progname)
+{
+	fprintf(stderr, "Usage: %s [-b{blocksize}] [-BeklsvxX] file ...\n",
+		progname);
+	exit(1);
+}
+
+int main(int argc, char**argv)
+{
+	char **cpp;
+	int c;
+
+	while ((c = getopt(argc, argv, "Bb::eksvxX")) != EOF)
+		switch (c) {
+		case 'B':
+			force_bmap++;
+			break;
+		case 'b':
+			if (optarg) {
+				char *end;
+				blocksize = strtoul(optarg, &end, 0);
+				if (end) {
+					switch (end[0]) {
+					case 'g':
+					case 'G':
+						blocksize *= 1024;
+						/* no break */
+					case 'm':
+					case 'M':
+						blocksize *= 1024;
+						/* no break */
+					case 'k':
+					case 'K':
+						blocksize *= 1024;
+						break;
+					default:
+						break;
+					}
+				}
+			} else { /* Allow -b without argument for compat. Remove
+				  * this eventually so "-b {blocksize}" works */
+				fprintf(stderr, "%s: -b needs a blocksize "
+					"option, assuming 1024-byte blocks.\n",
+					argv[0]);
+				blocksize = 1024;
+			}
+			break;
+		case 'e':
+			force_extent++;
+			if (!verbose)
+				verbose++;
+			break;
+		case 'k':
+			blocksize = 1024;
+			break;
+		case 's':
+			sync_file++;
+			break;
+		case 'v':
+			verbose++;
+			break;
+		case 'x':
+			xattr_map++;
+			break;
+		case 'X':
+			ext_fmt = hex_fmt;
+			break;
+		default:
+			usage(argv[0]);
+			break;
+		}
+	if (optind == argc)
+		usage(argv[0]);
+	for (cpp=argv+optind; *cpp; cpp++)
+		frag_report(*cpp);
+	return 0;
+}
+#endif
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/findfs.8.in b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/findfs.8.in
new file mode 100644
index 0000000..d44cbc7
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/findfs.8.in
@@ -0,0 +1,33 @@
+.\" -*- nroff -*-
+.\" Copyright 1993, 1994, 1995 by Theodore Ts'o.  All Rights Reserved.
+.\" This file may be copied under the terms of the GNU Public License.
+.\" 
+.TH FINDFS 8 "@E2FSPROGS_MONTH@ @E2FSPROGS_YEAR@" "E2fsprogs version @E2FSPROGS_VERSION@"
+.SH NAME
+findfs \- Find a filesystem by label or UUID
+.SH SYNOPSIS
+.B findfs 
+.BI LABEL= label
+.sp
+.B findfs
+.BI UUID= uuid
+.SH DESCRIPTION
+.B findfs
+will search the disks in the system looking for a filesystem which has 
+a label matching
+.I label
+or a UUID equal to 
+.IR uuid .
+If the filesystem is found, the device name for the filesystem will
+be printed on stdout.
+.PP
+.SH AUTHOR
+.B findfs 
+was written by Theodore Ts'o (tytso@mit.edu).
+.SH AVAILABILITY
+.B findfs
+is part of the e2fsprogs package and is available from 
+http://e2fsprogs.sourceforge.net.
+.SH SEE ALSO
+.BR fsck (8)
+
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/findsuper.c b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/findsuper.c
new file mode 100644
index 0000000..eb9130b
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/findsuper.c
@@ -0,0 +1,265 @@
+/*
+ * findsuper --- quick hacked up program to find ext2 superblocks.
+ *
+ * This is a hack, and really shouldn't be installed anywhere.  If you
+ * need a program which does this sort of functionality, please try
+ * using gpart program.
+ *
+ * Portions Copyright 1998-2000, Theodore Ts'o.
+ *
+ * Well, here's my linux version of findsuper.
+ * I'm sure you coulda done it faster.  :)
+ * IMHO there isn't as much interesting data to print in the
+ * linux superblock as there is in the SunOS superblock--disk geometry is
+ * not there...and linux seems to update the dates in all the superblocks.
+ * SunOS doesn't ever touch the backup superblocks after the fs is created,
+ * as far as I can tell, so the date is more interesting IMHO and certainly
+ * marks which superblocks are backup ones.
+ *
+ * I wanted to add msdos support, but I couldn't make heads or tails
+ * of the kernel include files to find anything I could look for in msdos.
+ *
+ * Reading every block of a Sun partition is fairly quick.  Doing the
+ * same under linux (slower hardware I suppose) just isn't the same.
+ * It might be more useful to default to reading the first (second?) block
+ * on each cyl; however, if the disk geometry is wrong, this is useless.
+ * But ya could still get the cyl size to print the numbers as cyls instead
+ * of blocks...
+ *
+ * run this as (for example)
+ *   findsuper /dev/hda
+ *   findsuper /dev/hda 437760 1024   (my disk has cyls of 855*512)
+ *
+ * I suppose the next step is to figgure out a way to determine if
+ * the block found is the first superblock somehow, and if so, build
+ * a partition table from the superblocks found... but this is still
+ * useful as is.
+ *
+ *		Steve
+ * ssd@nevets.oau.org
+ * ssd@mae.engr.ucf.edu
+ *
+ * Additional notes by Andreas Dilger <adilger@turbolinux.com>:
+ * - fixed to support > 2G devices by using lseek64
+ * - add reliability checking for the superblock to avoid random garbage
+ * - add adaptive progress meter
+ *
+ * It _should_ also handle signals and tell you the ending block, so
+ * that you can resume at a later time, but it doesn't yet...
+ *
+ * Note that gpart does not appear to find all superblocks that aren't aligned
+ * with the start of a possible partition, so it is not useful in systems
+ * with LVM or similar setups which don't use fat partition alignment.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+/*
+ * Documentation addendum added by Andreas dwguest@win.tue.nl/aeb@cwi.nl
+ *
+ * The program findsuper is a utility that scans a disk and finds
+ * copies of ext2 superblocks (by checking for the ext2 signature).
+ *
+ * For each superblock found, it prints the offset in bytes, the
+ * offset in 1024-byte blocks, the size of the ext2 partition in fs
+ * blocks, the filesystem blocksize (in bytes), the block group number
+ * (always 0 for older ext2 systems), and a timestamp (s_mtime).
+ *
+ * This program can be used to retrieve partitions that have been
+ * lost.  The superblock for block group 0 is found 1 block (2
+ * sectors) after the partition start.
+ *
+ * For new systems that have a block group number in the superblock it
+ * is immediately clear which superblock is the first of a partition.
+ * For old systems where no group numbers are given, the first
+ * superblock can be recognised by the timestamp: all superblock
+ * copies have the creation time in s_mtime, except the first, which
+ * has the last time e2fsck or tune2fs wrote to the filesystem.
+ *
+ */
+
+#define _FILE_OFFSET_BITS 64
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <time.h>
+
+#include "ext2fs/ext2_fs.h"
+#include "ext2fs/ext2fs.h"
+#include "nls-enable.h"
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define WHY(fmt, arg...) { printf("\r%Ld: " fmt, sk, ##arg) ; continue; }
+#else
+#define WHY(fmt, arg...) { continue; }
+#endif
+
+static void usage(void)
+{
+	fprintf(stderr,
+		_("Usage:  findsuper device [skipbytes [startkb]]\n"));
+	exit(1);
+}
+
+
+int main(int argc, char *argv[])
+{
+	int skiprate=512;		/* one sector */
+	loff_t sk=0, skl=0;
+	int fd;
+	char *s;
+	time_t tm, last = time(0);
+	loff_t interval = 1024 * 1024;
+	int c, print_jnl_copies = 0;
+	const char * device_name;
+	struct ext2_super_block ext2;
+	/* interesting fields: EXT2_SUPER_MAGIC
+	 *      s_blocks_count s_log_block_size s_mtime s_magic s_lastcheck */
+
+#ifdef ENABLE_NLS
+	setlocale(LC_MESSAGES, "");
+	setlocale(LC_CTYPE, "");
+	bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
+	textdomain(NLS_CAT_NAME);
+	set_com_err_gettext(gettext);
+#endif
+
+	while ((c = getopt (argc, argv, "j")) != EOF) {
+		switch (c) {
+		case 'j':
+			print_jnl_copies++;
+			break;
+		default:
+			usage();
+		}
+	}
+
+	if (optind == argc)
+		usage();
+
+	device_name = argv[optind++];
+
+	if (optind < argc) {
+		skiprate = strtol(argv[optind], &s, 0);
+		if (s == argv[optind]) {
+			fprintf(stderr,_("skipbytes should be a number, not %s\n"), s);
+			exit(1);
+		}
+		optind++;
+	}
+	if (skiprate & 0x1ff) {
+		fprintf(stderr,
+			_("skipbytes must be a multiple of the sector size\n"));
+		exit(2);
+	}
+	if (optind < argc) {
+		sk = skl = strtoll(argv[optind], &s, 0) << 10;
+		if (s == argv[optind]) {
+			fprintf(stderr,
+				_("startkb should be a number, not %s\n"), s);
+			exit(1);
+		}
+		optind++;
+	}
+	if (sk < 0) {
+		fprintf(stderr, _("startkb should be positive, not %llu\n"),sk);
+		exit(1);
+	}
+
+	fd = open(device_name, O_RDONLY);
+	if (fd < 0) {
+		perror(device_name);
+		exit(1);
+	}
+
+	/* Now, go looking for the superblock! */
+	printf(_("starting at %llu, with %u byte increments\n"), sk, skiprate);
+	if (print_jnl_copies)
+		printf(_("[*] probably superblock written in the ext3 "
+			 "journal superblock,\n\tso start/end/grp wrong\n"));
+	printf(_("byte_offset  byte_start     byte_end  fs_blocks blksz  grp  last_mount_time           sb_uuid label\n"));
+	for (; lseek64(fd, sk, SEEK_SET) != -1 &&
+	       read(fd, &ext2, 512) == 512; sk += skiprate) {
+		static unsigned char last_uuid[16] = "blah";
+		unsigned long long bsize, grpsize;
+		int jnl_copy, sb_offset;
+
+		if (sk && !(sk & (interval - 1))) {
+			time_t now, diff;
+
+			now = time(0);
+			diff = now - last;
+
+			if (diff > 0) {
+				s = ctime(&now);
+				s[24] = 0;
+				printf("\r%11Lu: %8LukB/s @ %s", sk,
+				       (((sk - skl)) / diff) >> 10, s);
+				fflush(stdout);
+			}
+			if (diff < 5)
+				interval <<= 1;
+			else if (diff > 20)
+				interval >>= 1;
+			last = now;
+			skl = sk;
+		}
+		if (ext2.s_magic != EXT2_SUPER_MAGIC)
+			continue;
+		if (ext2.s_log_block_size > 6)
+			WHY("log block size > 6 (%u)\n", ext2.s_log_block_size);
+		if (ext2fs_r_blocks_count(&ext2) > ext2fs_blocks_count(&ext2))
+			WHY("r_blocks_count > blocks_count (%u > %u)\n",
+			    ext2fs_r_blocks_count(&ext2),
+			    ext2fs_blocks_count(&ext2));
+		if (ext2fs_free_blocks_count(&ext2) > ext2fs_blocks_count(&ext2))
+			WHY("free_blocks_count > blocks_count\n (%u > %u)\n",
+			    ext2fs_free_blocks_count(&ext2),
+			    ext2fs_blocks_count(&ext2));
+		if (ext2.s_free_inodes_count > ext2.s_inodes_count)
+			WHY("free_inodes_count > inodes_count (%u > %u)\n",
+			    ext2.s_free_inodes_count, ext2.s_inodes_count);
+
+		tm = ext2.s_mtime;
+		s = ctime(&tm);
+		s[24] = 0;
+		bsize = 1 << (ext2.s_log_block_size + 10);
+		grpsize = bsize * ext2.s_blocks_per_group;
+		if (memcmp(ext2.s_uuid, last_uuid, sizeof(last_uuid)) == 0 &&
+		    ext2.s_rev_level > 0 && ext2.s_block_group_nr == 0) {
+			jnl_copy = 1;
+		} else {
+			jnl_copy = 0;
+			memcpy(last_uuid, ext2.s_uuid, sizeof(last_uuid));
+		}
+		if (ext2.s_block_group_nr == 0 || bsize == 1024)
+			sb_offset = 1024;
+		else
+			sb_offset = 0;
+		if (jnl_copy && !print_jnl_copies)
+			continue;
+		printf("\r%11Lu %11Lu%s %11Lu%s %9u %5Lu %4u%s %s %02x%02x%02x%02x %s\n",
+		       sk, sk - ext2.s_block_group_nr * grpsize - sb_offset,
+		       jnl_copy ? "*":" ",
+		       sk + ext2fs_blocks_count(&ext2) * bsize -
+		            ext2.s_block_group_nr * grpsize - sb_offset,
+		       jnl_copy ? "*" : " ", ext2fs_blocks_count(&ext2), bsize,
+		       ext2.s_block_group_nr, jnl_copy ? "*" : " ", s,
+		       ext2.s_uuid[0], ext2.s_uuid[1],
+		       ext2.s_uuid[2], ext2.s_uuid[3], ext2.s_volume_name);
+	}
+	printf(_("\n%11Lu: finished with errno %d\n"), sk, errno);
+	close(fd);
+
+	return errno;
+}
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/fsck.8.in b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/fsck.8.in
new file mode 100644
index 0000000..50fd8ce
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/fsck.8.in
@@ -0,0 +1,414 @@
+.\" -*- nroff -*-
+.\" Copyright 1993, 1994, 1995 by Theodore Ts'o.  All Rights Reserved.
+.\" This file may be copied under the terms of the GNU Public License.
+.\" 
+.TH FSCK 8 "@E2FSPROGS_MONTH@ @E2FSPROGS_YEAR@" "E2fsprogs version @E2FSPROGS_VERSION@"
+.SH NAME
+fsck \- check and repair a Linux file system
+.SH SYNOPSIS
+.B fsck
+[
+.B \-sAVRTMNP
+]
+[
+.B \-C
+[
+.I fd
+]
+]
+[
+.B \-t
+.I fstype
+] 
+.I [filesys ... ]
+[\-\-] [
+.B fs-specific-options
+]
+.SH DESCRIPTION
+.B fsck
+is used to check and optionally repair one or more Linux file systems.  
+.I filesys
+can be a device name (e.g.
+.IR /dev/hdc1 ", " /dev/sdb2 ),
+a mount point (e.g.
+.IR / ", " /usr ", " /home ),
+or an ext2 label or UUID specifier (e.g.
+UUID=8868abf6-88c5-4a83-98b8-bfc24057f7bd or LABEL=root).  
+Normally, the 
+.B fsck 
+program will try to handle filesystems on different physical disk drives 
+in parallel to reduce the total amount of time needed to check all of the
+filesystems.
+.PP
+If no filesystems are specified on the command line, and the 
+.B \-A 
+option is not specified, 
+.B fsck
+will default to checking filesystems in
+.B /etc/fstab
+serially.  This is equivalent to the 
+.B \-As
+options.
+.PP
+The exit code returned by
+.B fsck
+is the sum of the following conditions:
+.br
+\	0\	\-\ No errors
+.br
+\	1\	\-\ File system errors corrected
+.br
+\	2\	\-\ System should be rebooted
+.br
+\	4\	\-\ File system errors left uncorrected
+.br
+\	8\	\-\ Operational error
+.br
+\	16\	\-\ Usage or syntax error
+.br
+\	32\	\-\ Fsck canceled by user request
+.br
+\	128\	\-\ Shared library error
+.br
+The exit code returned when multiple file systems are checked 
+is the bit-wise OR of the exit codes for each
+file system that is checked.
+.PP
+In actuality,
+.B fsck
+is simply a front-end for the various file system checkers
+(\fBfsck\fR.\fIfstype\fR) available under Linux.  The file
+system-specific checker is searched for in
+.I /sbin
+first, then in
+.I /etc/fs
+and
+.IR /etc ,
+and finally in the directories listed in the PATH environment
+variable.  Please see the file system-specific checker manual pages for
+further details.
+.SH OPTIONS
+.TP
+.B \-s
+Serialize 
+.B fsck 
+operations.  This is a good idea if you are checking multiple
+filesystems and the checkers are in an interactive mode.  (Note:
+.BR e2fsck (8)
+runs in an interactive mode by default.  To make 
+.BR e2fsck (8)
+run in a non-interactive mode, you must either specify the
+.B \-p
+or
+.B \-a
+option, if you wish for errors to be corrected automatically, or the 
+.B \-n
+option if you do not.)
+.TP
+.BI \-t " fslist"
+Specifies the type(s) of file system to be checked.  When the
+.B \-A 
+flag is specified, only filesystems that match 
+.I fslist
+are checked.  The
+.I fslist
+parameter is a comma-separated list of filesystems and options
+specifiers.  All of the filesystems in this comma-separated list may be
+prefixed by a negation operator 
+.RB ' no '
+or 
+.RB ' ! ',
+which requests that only those filesystems not listed in
+.I fslist
+will be checked.  If all of the filesystems in 
+.I fslist
+are not prefixed by a negation operator, then only those filesystems
+listed
+in
+.I fslist
+will be checked.
+.sp
+Options specifiers may be included in the comma-separated
+.IR fslist .
+They must have the format 
+.BI opts= fs-option\fR.
+If an options specifier is present, then only filesystems which contain
+.I fs-option
+in their mount options field of 
+.B /etc/fstab
+will be checked.  If the options specifier is prefixed by a negation
+operator, then only 
+those filesystems that do not have
+.I fs-option
+in their mount options field of
+.B /etc/fstab 
+will be checked.
+.sp
+For example, if
+.B opts=ro
+appears in
+.IR fslist ,
+then only filesystems listed in
+.B /etc/fstab 
+with the
+.B ro
+option will be checked.
+.sp
+For compatibility with Mandrake distributions whose boot scripts
+depend upon an unauthorized UI change to the
+.B fsck
+program, if a filesystem type of
+.B loop
+is found in
+.IR fslist ,
+it is treated as if
+.B opts=loop
+were specified as an argument to the
+.B \-t
+option.
+.sp
+Normally, the filesystem type is deduced by searching for
+.I filesys
+in the 
+.I /etc/fstab 
+file and using the corresponding entry.
+If the type can not be deduced, and there is only a single filesystem 
+given as an argument to the 
+.B \-t 
+option, 
+.B fsck
+will use the specified filesystem type.  If this type is not
+available, then the default file system type (currently ext2) is used. 
+.TP
+.B \-A
+Walk through the
+.I /etc/fstab
+file and try to check all file systems in one run.  This option is
+typically used from the
+.I /etc/rc
+system initialization file, instead of multiple commands for checking
+a single file system.
+.sp
+The root filesystem will be checked first unless the
+.B \-P
+option is specified (see below).  After that, 
+filesystems will be checked in the order specified by the 
+.I fs_passno 
+(the sixth) field in the 
+.I /etc/fstab
+file.  
+Filesystems with a 
+.I fs_passno
+value of 0 are skipped and are not checked at all.  Filesystems with a
+.I fs_passno
+value of greater than zero will be checked in order, 
+with filesystems with the lowest
+.I fs_passno 
+number being checked first.
+If there are multiple filesystems with the same pass number, 
+fsck will attempt to check them in parallel, although it will avoid running 
+multiple filesystem checks on the same physical disk.  
+.sp
+Hence, a very common configuration in 
+.I /etc/fstab
+files is to set the root filesystem to have a 
+.I fs_passno
+value of 1
+and to set all other filesystems to have a
+.I fs_passno
+value of 2.  This will allow
+.B fsck
+to automatically run filesystem checkers in parallel if it is advantageous
+to do so.  System administrators might choose
+not to use this configuration if they need to avoid multiple filesystem
+checks running in parallel for some reason --- for example, if the
+machine in question is short on memory so that
+excessive paging is a concern.
+.TP
+.B \-C\fR [ \fI "fd" \fR ]
+Display completion/progress bars for those filesystem checkers (currently 
+only for ext2 and ext3) which support them.   Fsck will manage the
+filesystem checkers so that only one of them will display  
+a progress bar at a time.  GUI front-ends may specify a file descriptor
+.IR fd ,
+in which case the progress bar information will be sent to that file descriptor.
+.TP
+.B \-M
+Do not check mounted filesystems and return an exit code of 0
+for mounted filesystems.
+.TP
+.B \-N
+Don't execute, just show what would be done.
+.TP
+.B \-P
+When the 
+.B \-A
+flag is set, check the root filesystem in parallel with the other filesystems.
+This is not the safest thing in the world to do,
+since if the root filesystem is in doubt things like the 
+.BR e2fsck (8) 
+executable might be corrupted!  This option is mainly provided
+for those sysadmins who don't want to repartition the root
+filesystem to be small and compact (which is really the right solution).
+.TP
+.B \-R
+When checking all file systems with the
+.B \-A
+flag, skip the root file system (in case it's already mounted read-write).
+.TP
+.B \-T
+Don't show the title on startup.
+.TP
+.B \-V
+Produce verbose output, including all file system-specific commands
+that are executed.
+.TP
+.B fs-specific-options
+Options which are not understood by 
+.B fsck 
+are passed to the filesystem-specific checker.  These arguments
+.B must
+not take arguments, as there is no
+way for 
+.B fsck
+to be able to properly guess which arguments take options and which
+don't.
+.IP
+Options and arguments which follow the
+.B \-\-
+are treated as file system-specific options to be passed to the
+file system-specific checker.
+.IP
+Please note that fsck is not
+designed to pass arbitrarily complicated options to filesystem-specific
+checkers.  If you're doing something complicated, please just
+execute the filesystem-specific checker directly.  If you pass 
+.B fsck
+some horribly complicated option and arguments, and it doesn't do
+what you expect, 
+.B don't bother reporting it as a bug.
+You're almost certainly doing something that you shouldn't be doing
+with 
+.BR fsck.
+.PP
+Options to different filesystem-specific fsck's are not standardized.
+If in doubt, please consult the man pages of the filesystem-specific
+checker.  Although not guaranteed, the following options are supported
+by most file system checkers:
+.TP
+.B \-a
+Automatically repair the file system without any questions (use
+this option with caution).  Note that 
+.BR e2fsck (8)
+supports 
+.B \-a
+for backwards compatibility only.  This option is mapped to 
+.BR e2fsck 's
+.B \-p
+option which is safe to use, unlike the 
+.B \-a 
+option that some file system checkers support.
+.TP
+.B \-n
+For some filesystem-specific checkers, the 
+.B \-n
+option will cause the fs-specific fsck to avoid attempting to repair any 
+problems, but simply report such problems to stdout.  This is however
+not true for all filesystem-specific checkers.  In particular, 
+.BR fsck.reiserfs (8)
+will not report any corruption if given this option.
+.BR fsck.minix (8)
+does not support the 
+.B \-n 
+option at all.
+.TP
+.B \-r
+Interactively repair the filesystem (ask for confirmations).  Note: It
+is generally a bad idea to use this option if multiple fsck's are being
+run in parallel.  Also note that this is 
+.BR e2fsck 's
+default behavior; it supports this option for backwards compatibility
+reasons only.
+.TP
+.B \-y
+For some filesystem-specific checkers, the 
+.B \-y 
+option will cause the fs-specific fsck to always attempt to fix any
+detected filesystem corruption automatically.  Sometimes an expert may
+be able to do better driving the fsck manually.  Note that 
+.B not
+all filesystem-specific checkers implement this option.  In particular 
+.BR fsck.minix (8)
+and
+.BR fsck.cramfs (8)
+does not support the
+.B -y
+option as of this writing.
+.SH AUTHOR
+Theodore Ts'o (tytso@mit.edu)
+.SH FILES
+.IR /etc/fstab .
+.SH ENVIRONMENT VARIABLES
+The
+.B fsck
+program's behavior is affected by the following environment variables:
+.TP
+.B FSCK_FORCE_ALL_PARALLEL
+If this environment variable is set, 
+.B fsck
+will attempt to run all of the specified filesystems in parallel,
+regardless of whether the filesystems appear to be on the same
+device.  (This is useful for RAID systems or high-end storage systems
+such as those sold by companies such as IBM or EMC.)
+.TP
+.B FSCK_MAX_INST
+This environment variable will limit the maximum number of file system
+checkers that can be running at one time.  This allows configurations
+which have a large number of disks to avoid 
+.B fsck
+starting too many file system checkers at once, which might overload
+CPU and memory resources available on the system.  If this value is
+zero, then an unlimited number of processes can be spawned.  This is
+currently the default, but future versions of
+.B fsck
+may attempt to automatically determine how many file system checks can
+be run based on gathering accounting data from the operating system.
+.TP
+.B PATH
+The 
+.B PATH
+environment variable is used to find file system checkers.  A set of
+system directories are searched first: 
+.BR /sbin ,
+.BR /sbin/fs.d ,
+.BR  /sbin/fs ,
+.BR /etc/fs ,
+and 
+.BR /etc .
+Then the set of directories found in the
+.B PATH
+environment are searched.
+.TP
+.B FSTAB_FILE
+This environment variable allows the system administrator 
+to override the standard location of the 
+.B /etc/fstab
+file.  It is also useful for developers who are testing
+.BR fsck .
+.SH SEE ALSO
+.BR fstab (5),
+.BR mkfs (8),
+.BR fsck.ext2 (8)
+or
+.BR fsck.ext3 (8)
+or
+.BR e2fsck (8),
+.BR cramfsck (8),
+.BR fsck.minix (8),
+.BR fsck.msdos (8),
+.BR fsck.jfs (8),
+.BR fsck.nfs (8),
+.BR fsck.vfat (8),
+.BR fsck.xfs (8),
+.BR fsck.xiafs (8),
+.BR reiserfsck (8).
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/fsck.c b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/fsck.c
new file mode 100644
index 0000000..826aaeb
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/fsck.c
@@ -0,0 +1,1343 @@
+/*
+ * pfsck --- A generic, parallelizing front-end for the fsck program.
+ * It will automatically try to run fsck programs in parallel if the
+ * devices are on separate spindles.  It is based on the same ideas as
+ * the generic front end for fsck by David Engel and Fred van Kempen,
+ * but it has been completely rewritten from scratch to support
+ * parallel execution.
+ *
+ * Written by Theodore Ts'o, <tytso@mit.edu>
+ *
+ * Miquel van Smoorenburg (miquels@drinkel.ow.org) 20-Oct-1994:
+ *   o Changed -t fstype to behave like with mount when -A (all file
+ *     systems) or -M (like mount) is specified.
+ *   o fsck looks if it can find the fsck.type program to decide
+ *     if it should ignore the fs type. This way more fsck programs
+ *     can be added without changing this front-end.
+ *   o -R flag skip root file system.
+ *
+ * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+ * 	2001, 2002, 2003, 2004, 2005 by  Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#define _XOPEN_SOURCE 600 /* for inclusion of sa_handler in Solaris */
+
+#include "config.h"
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <time.h>
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#if HAVE_PATHS_H
+#include <paths.h>
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#if HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
+#include "../version.h"
+#include "nls-enable.h"
+#include "fsck.h"
+#include "blkid/blkid.h"
+
+#ifndef _PATH_MNTTAB
+#define	_PATH_MNTTAB	"/etc/fstab"
+#endif
+
+static const char *ignored_types[] = {
+	"ignore",
+	"iso9660",
+	"nfs",
+	"proc",
+	"sw",
+	"swap",
+	"tmpfs",
+	"devpts",
+	NULL
+};
+
+static const char *really_wanted[] = {
+	"minix",
+	"ext2",
+	"ext3",
+	"ext4",
+	"ext4dev",
+	"jfs",
+	"reiserfs",
+	"xiafs",
+	"xfs",
+	NULL
+};
+
+#define BASE_MD "/dev/md"
+
+/*
+ * Global variables for options
+ */
+static char *devices[MAX_DEVICES];
+static char *args[MAX_ARGS];
+static int num_devices, num_args;
+
+static int verbose = 0;
+static int doall = 0;
+static int noexecute = 0;
+static int serialize = 0;
+static int skip_root = 0;
+static int ignore_mounted = 0;
+static int notitle = 0;
+static int parallel_root = 0;
+static int progress = 0;
+static int progress_fd = 0;
+static int force_all_parallel = 0;
+static int num_running = 0;
+static int max_running = 0;
+static volatile int cancel_requested = 0;
+static int kill_sent = 0;
+static char *progname;
+static char *fstype = NULL;
+static struct fs_info *filesys_info = NULL, *filesys_last = NULL;
+static struct fsck_instance *instance_list;
+static const char *fsck_prefix_path = "/sbin:/sbin/fs.d:/sbin/fs:/etc/fs:/etc";
+static char *fsck_path = 0;
+static blkid_cache cache = NULL;
+
+static char *string_copy(const char *s)
+{
+	char	*ret;
+
+	if (!s)
+		return 0;
+	ret = malloc(strlen(s)+1);
+	if (ret)
+		strcpy(ret, s);
+	return ret;
+}
+
+static int string_to_int(const char *s)
+{
+	long l;
+	char *p;
+
+	l = strtol(s, &p, 0);
+	if (*p || l == LONG_MIN || l == LONG_MAX || l < 0 || l > INT_MAX)
+		return -1;
+	else
+		return (int) l;
+}
+
+static int ignore(struct fs_info *);
+
+static char *skip_over_blank(char *cp)
+{
+	while (*cp && isspace(*cp))
+		cp++;
+	return cp;
+}
+
+static char *skip_over_word(char *cp)
+{
+	while (*cp && !isspace(*cp))
+		cp++;
+	return cp;
+}
+
+static void strip_line(char *line)
+{
+	char	*p;
+
+	while (*line) {
+		p = line + strlen(line) - 1;
+		if ((*p == '\n') || (*p == '\r'))
+			*p = 0;
+		else
+			break;
+	}
+}
+
+static char *parse_word(char **buf)
+{
+	char *word, *next;
+
+	word = *buf;
+	if (*word == 0)
+		return 0;
+
+	word = skip_over_blank(word);
+	next = skip_over_word(word);
+	if (*next)
+		*next++ = 0;
+	*buf = next;
+	return word;
+}
+
+static void parse_escape(char *word)
+{
+	char	*p, *q;
+	int	ac, i;
+
+	if (!word)
+		return;
+
+	for (p = word, q = word; *p; p++, q++) {
+		*q = *p;
+		if (*p != '\\')
+			continue;
+		if (*++p == 0)
+			break;
+		if (*p == 't') {
+			*q = '\t';
+			continue;
+		}
+		if (*p == 'n') {
+			*q = '\n';
+			continue;
+		}
+		if (!isdigit(*p)) {
+			*q = *p;
+			continue;
+		}
+		ac = 0;
+		for (i = 0; i < 3; i++, p++) {
+			if (!isdigit(*p))
+				break;
+			ac = (ac * 8) + (*p - '0');
+		}
+		*q = ac;
+		p--;
+	}
+	*q = 0;
+}
+
+static void free_instance(struct fsck_instance *i)
+{
+	free(i->prog);
+	free(i->device);
+	free(i->base_device);
+	free(i);
+	return;
+}
+
+static struct fs_info *create_fs_device(const char *device, const char *mntpnt,
+					const char *type, const char *opts,
+					int freq, int passno)
+{
+	struct fs_info *fs;
+
+	if (!(fs = malloc(sizeof(struct fs_info))))
+		return NULL;
+
+	fs->device = string_copy(device);
+	fs->mountpt = string_copy(mntpnt);
+	fs->type = string_copy(type);
+	fs->opts = string_copy(opts ? opts : "");
+	fs->freq = freq;
+	fs->passno = passno;
+	fs->flags = 0;
+	fs->next = NULL;
+
+	if (!filesys_info)
+		filesys_info = fs;
+	else
+		filesys_last->next = fs;
+	filesys_last = fs;
+
+	return fs;
+}
+
+
+
+static int parse_fstab_line(char *line, struct fs_info **ret_fs)
+{
+	char	*dev, *device, *mntpnt, *type, *opts, *freq, *passno, *cp;
+	struct fs_info *fs;
+
+	*ret_fs = 0;
+	strip_line(line);
+	cp = line;
+
+	device = parse_word(&cp);
+	if (!device || *device == '#')
+		return 0;	/* Ignore blank lines and comments */
+	mntpnt = parse_word(&cp);
+	type = parse_word(&cp);
+	opts = parse_word(&cp);
+	freq = parse_word(&cp);
+	passno = parse_word(&cp);
+
+	if (!mntpnt || !type)
+		return -1;
+
+	parse_escape(device);
+	parse_escape(mntpnt);
+	parse_escape(type);
+	parse_escape(opts);
+	parse_escape(freq);
+	parse_escape(passno);
+
+	dev = blkid_get_devname(cache, device, NULL);
+	if (dev)
+		device = dev;
+
+	if (strchr(type, ','))
+		type = 0;
+
+	fs = create_fs_device(device, mntpnt, type ? type : "auto", opts,
+			      freq ? atoi(freq) : -1,
+			      passno ? atoi(passno) : -1);
+	free(dev);
+
+	if (!fs)
+		return -1;
+	*ret_fs = fs;
+	return 0;
+}
+
+static void interpret_type(struct fs_info *fs)
+{
+	char	*t;
+
+	if (strcmp(fs->type, "auto") != 0)
+		return;
+	t = blkid_get_tag_value(cache, "TYPE", fs->device);
+	if (t) {
+		free(fs->type);
+		fs->type = t;
+	}
+}
+
+/*
+ * Load the filesystem database from /etc/fstab
+ */
+static void load_fs_info(const char *filename)
+{
+	FILE	*f;
+	char	buf[1024];
+	int	lineno = 0;
+	int	old_fstab = 1;
+	struct fs_info *fs;
+
+	if ((f = fopen(filename, "r")) == NULL) {
+		fprintf(stderr, _("WARNING: couldn't open %s: %s\n"),
+			filename, strerror(errno));
+		return;
+	}
+	while (!feof(f)) {
+		lineno++;
+		if (!fgets(buf, sizeof(buf), f))
+			break;
+		buf[sizeof(buf)-1] = 0;
+		if (parse_fstab_line(buf, &fs) < 0) {
+			fprintf(stderr, _("WARNING: bad format "
+				"on line %d of %s\n"), lineno, filename);
+			continue;
+		}
+		if (!fs)
+			continue;
+		if (fs->passno < 0)
+			fs->passno = 0;
+		else
+			old_fstab = 0;
+	}
+
+	fclose(f);
+
+	if (old_fstab && filesys_info) {
+		fputs("\007\007\007", stderr);
+		fputs(_(
+		"WARNING: Your /etc/fstab does not contain the fsck passno\n"
+		"	field.  I will kludge around things for you, but you\n"
+		"	should fix your /etc/fstab file as soon as you can.\n\n"), stderr);
+
+		for (fs = filesys_info; fs; fs = fs->next) {
+			fs->passno = 1;
+		}
+	}
+}
+
+/* Lookup filesys in /etc/fstab and return the corresponding entry. */
+static struct fs_info *lookup(char *filesys)
+{
+	struct fs_info *fs;
+
+	/* No filesys name given. */
+	if (filesys == NULL)
+		return NULL;
+
+	for (fs = filesys_info; fs; fs = fs->next) {
+		if (!strcmp(filesys, fs->device) ||
+		    (fs->mountpt && !strcmp(filesys, fs->mountpt)))
+			break;
+	}
+
+	return fs;
+}
+
+/* Find fsck program for a given fs type. */
+static char *find_fsck(char *type)
+{
+  char *s;
+  const char *tpl;
+  static char prog[256];
+  char *p = string_copy(fsck_path);
+  struct stat st;
+
+  /* Are we looking for a program or just a type? */
+  tpl = (strncmp(type, "fsck.", 5) ? "%s/fsck.%s" : "%s/%s");
+
+  for(s = strtok(p, ":"); s; s = strtok(NULL, ":")) {
+	sprintf(prog, tpl, s, type);
+	if (stat(prog, &st) == 0) break;
+  }
+  free(p);
+  return(s ? prog : NULL);
+}
+
+static int progress_active(NOARGS)
+{
+	struct fsck_instance *inst;
+
+	for (inst = instance_list; inst; inst = inst->next) {
+		if (inst->flags & FLAG_DONE)
+			continue;
+		if (inst->flags & FLAG_PROGRESS)
+			return 1;
+	}
+	return 0;
+}
+
+/*
+ * Execute a particular fsck program, and link it into the list of
+ * child processes we are waiting for.
+ */
+static int execute(const char *type, const char *device, const char *mntpt,
+		   int interactive)
+{
+	char *s, *argv[80], prog[80];
+	int  argc, i;
+	struct fsck_instance *inst, *p;
+	pid_t	pid;
+
+	inst = malloc(sizeof(struct fsck_instance));
+	if (!inst)
+		return ENOMEM;
+	memset(inst, 0, sizeof(struct fsck_instance));
+
+	sprintf(prog, "fsck.%s", type);
+	argv[0] = string_copy(prog);
+	argc = 1;
+
+	for (i=0; i <num_args; i++)
+		argv[argc++] = string_copy(args[i]);
+
+	if (progress) {
+		if ((strcmp(type, "ext2") == 0) ||
+		    (strcmp(type, "ext3") == 0) ||
+		    (strcmp(type, "ext4") == 0) ||
+		    (strcmp(type, "ext4dev") == 0)) {
+			char tmp[80];
+
+			tmp[0] = 0;
+			if (!progress_active()) {
+				snprintf(tmp, 80, "-C%d", progress_fd);
+				inst->flags |= FLAG_PROGRESS;
+			} else if (progress_fd)
+				snprintf(tmp, 80, "-C%d", progress_fd * -1);
+			if (tmp[0])
+				argv[argc++] = string_copy(tmp);
+		}
+	}
+
+	argv[argc++] = string_copy(device);
+	argv[argc] = 0;
+
+	s = find_fsck(prog);
+	if (s == NULL) {
+		fprintf(stderr, _("fsck: %s: not found\n"), prog);
+		free(inst);
+		return ENOENT;
+	}
+
+	if (verbose || noexecute) {
+		printf("[%s (%d) -- %s] ", s, num_running,
+		       mntpt ? mntpt : device);
+		for (i=0; i < argc; i++)
+			printf("%s ", argv[i]);
+		printf("\n");
+	}
+
+	/* Fork and execute the correct program. */
+	if (noexecute)
+		pid = -1;
+	else if ((pid = fork()) < 0) {
+		perror("fork");
+		free(inst);
+		return errno;
+	} else if (pid == 0) {
+		if (!interactive)
+			close(0);
+		(void) execv(s, argv);
+		perror(argv[0]);
+		free(inst);
+		exit(EXIT_ERROR);
+	}
+
+	for (i=0; i < argc; i++)
+		free(argv[i]);
+
+	inst->pid = pid;
+	inst->prog = string_copy(prog);
+	inst->type = string_copy(type);
+	inst->device = string_copy(device);
+	inst->base_device = base_device(device);
+	inst->start_time = time(0);
+	inst->next = NULL;
+
+	/*
+	 * Find the end of the list, so we add the instance on at the end.
+	 */
+	for (p = instance_list; p && p->next; p = p->next);
+
+	if (p)
+		p->next = inst;
+	else
+		instance_list = inst;
+
+	return 0;
+}
+
+/*
+ * Send a signal to all outstanding fsck child processes
+ */
+static int kill_all(int signum)
+{
+	struct fsck_instance *inst;
+	int	n = 0;
+
+	for (inst = instance_list; inst; inst = inst->next) {
+		if (inst->flags & FLAG_DONE)
+			continue;
+		kill(inst->pid, signum);
+		n++;
+	}
+	return n;
+}
+
+/*
+ * Wait for one child process to exit; when it does, unlink it from
+ * the list of executing child processes, and return it.
+ */
+static struct fsck_instance *wait_one(int flags)
+{
+	int	status;
+	int	sig;
+	struct fsck_instance *inst, *inst2, *prev;
+	pid_t	pid;
+
+	if (!instance_list)
+		return NULL;
+
+	if (noexecute) {
+		inst = instance_list;
+		prev = 0;
+#ifdef RANDOM_DEBUG
+		while (inst->next && (random() & 1)) {
+			prev = inst;
+			inst = inst->next;
+		}
+#endif
+		inst->exit_status = 0;
+		goto ret_inst;
+	}
+
+	/*
+	 * gcc -Wall fails saving throw against stupidity
+	 * (inst and prev are thought to be uninitialized variables)
+	 */
+	inst = prev = NULL;
+
+	do {
+		pid = waitpid(-1, &status, flags);
+		if (cancel_requested && !kill_sent) {
+			kill_all(SIGTERM);
+			kill_sent++;
+		}
+		if ((pid == 0) && (flags & WNOHANG))
+			return NULL;
+		if (pid < 0) {
+			if ((errno == EINTR) || (errno == EAGAIN))
+				continue;
+			if (errno == ECHILD) {
+				fprintf(stderr,
+					_("%s: wait: No more child process?!?\n"),
+					progname);
+				return NULL;
+			}
+			perror("wait");
+			continue;
+		}
+		for (prev = 0, inst = instance_list;
+		     inst;
+		     prev = inst, inst = inst->next) {
+			if (inst->pid == pid)
+				break;
+		}
+	} while (!inst);
+
+	if (WIFEXITED(status))
+		status = WEXITSTATUS(status);
+	else if (WIFSIGNALED(status)) {
+		sig = WTERMSIG(status);
+		if (sig == SIGINT) {
+			status = EXIT_UNCORRECTED;
+		} else {
+			printf(_("Warning... %s for device %s exited "
+			       "with signal %d.\n"),
+			       inst->prog, inst->device, sig);
+			status = EXIT_ERROR;
+		}
+	} else {
+		printf(_("%s %s: status is %x, should never happen.\n"),
+		       inst->prog, inst->device, status);
+		status = EXIT_ERROR;
+	}
+	inst->exit_status = status;
+	inst->flags |= FLAG_DONE;
+	if (progress && (inst->flags & FLAG_PROGRESS) &&
+	    !progress_active()) {
+		for (inst2 = instance_list; inst2; inst2 = inst2->next) {
+			if (inst2->flags & FLAG_DONE)
+				continue;
+			if (strcmp(inst2->type, "ext2") &&
+			    strcmp(inst2->type, "ext3") &&
+			    strcmp(inst2->type, "ext4") &&
+			    strcmp(inst2->type, "ext4dev"))
+				continue;
+			/*
+			 * If we've just started the fsck, wait a tiny
+			 * bit before sending the kill, to give it
+			 * time to set up the signal handler
+			 */
+			if (inst2->start_time < time(0)+2) {
+				if (fork() == 0) {
+					sleep(1);
+					kill(inst2->pid, SIGUSR1);
+					exit(0);
+				}
+			} else
+				kill(inst2->pid, SIGUSR1);
+			inst2->flags |= FLAG_PROGRESS;
+			break;
+		}
+	}
+ret_inst:
+	if (prev)
+		prev->next = inst->next;
+	else
+		instance_list = inst->next;
+	if (verbose > 1)
+		printf(_("Finished with %s (exit status %d)\n"),
+		       inst->device, inst->exit_status);
+	num_running--;
+	return inst;
+}
+
+#define FLAG_WAIT_ALL		0
+#define FLAG_WAIT_ATLEAST_ONE	1
+/*
+ * Wait until all executing child processes have exited; return the
+ * logical OR of all of their exit code values.
+ */
+static int wait_many(int flags)
+{
+	struct fsck_instance *inst;
+	int	global_status = 0;
+	int	wait_flags = 0;
+
+	while ((inst = wait_one(wait_flags))) {
+		global_status |= inst->exit_status;
+		free_instance(inst);
+#ifdef RANDOM_DEBUG
+		if (noexecute && (flags & WNOHANG) && !(random() % 3))
+			break;
+#endif
+		if (flags & FLAG_WAIT_ATLEAST_ONE)
+			wait_flags = WNOHANG;
+	}
+	return global_status;
+}
+
+/*
+ * Run the fsck program on a particular device
+ *
+ * If the type is specified using -t, and it isn't prefixed with "no"
+ * (as in "noext2") and only one filesystem type is specified, then
+ * use that type regardless of what is specified in /etc/fstab.
+ *
+ * If the type isn't specified by the user, then use either the type
+ * specified in /etc/fstab, or DEFAULT_FSTYPE.
+ */
+static void fsck_device(struct fs_info *fs, int interactive)
+{
+	const char *type;
+	int retval;
+
+	interpret_type(fs);
+
+	if (strcmp(fs->type, "auto") != 0)
+		type = fs->type;
+	else if (fstype && strncmp(fstype, "no", 2) &&
+	    strncmp(fstype, "opts=", 5) && strncmp(fstype, "loop", 4) &&
+	    !strchr(fstype, ','))
+		type = fstype;
+	else
+		type = DEFAULT_FSTYPE;
+
+	num_running++;
+	retval = execute(type, fs->device, fs->mountpt, interactive);
+	if (retval) {
+		fprintf(stderr, _("%s: Error %d while executing fsck.%s "
+			"for %s\n"), progname, retval, type, fs->device);
+		num_running--;
+	}
+}
+
+
+/*
+ * Deal with the fsck -t argument.
+ */
+static struct fs_type_compile {
+	char **list;
+	int *type;
+	int  negate;
+} fs_type_compiled;
+
+#define FS_TYPE_NORMAL	0
+#define FS_TYPE_OPT	1
+#define FS_TYPE_NEGOPT	2
+
+static const char *fs_type_syntax_error =
+N_("Either all or none of the filesystem types passed to -t must be prefixed\n"
+   "with 'no' or '!'.\n");
+
+static void compile_fs_type(char *fs_type, struct fs_type_compile *cmp)
+{
+	char 	*cp, *list, *s;
+	int	num = 2;
+	int	negate, first_negate = 1;
+
+	if (fs_type) {
+		for (cp=fs_type; *cp; cp++) {
+			if (*cp == ',')
+				num++;
+		}
+	}
+
+	cmp->list = malloc(num * sizeof(char *));
+	cmp->type = malloc(num * sizeof(int));
+	if (!cmp->list || !cmp->type) {
+		fputs(_("Couldn't allocate memory for filesystem types\n"),
+		      stderr);
+		exit(EXIT_ERROR);
+	}
+	memset(cmp->list, 0, num * sizeof(char *));
+	memset(cmp->type, 0, num * sizeof(int));
+	cmp->negate = 0;
+
+	if (!fs_type)
+		return;
+
+	list = string_copy(fs_type);
+	num = 0;
+	s = strtok(list, ",");
+	while(s) {
+		negate = 0;
+		if (strncmp(s, "no", 2) == 0) {
+			s += 2;
+			negate = 1;
+		} else if (*s == '!') {
+			s++;
+			negate = 1;
+		}
+		if (strcmp(s, "loop") == 0)
+			/* loop is really short-hand for opts=loop */
+			goto loop_special_case;
+		else if (strncmp(s, "opts=", 5) == 0) {
+			s += 5;
+		loop_special_case:
+			cmp->type[num] = negate ? FS_TYPE_NEGOPT : FS_TYPE_OPT;
+		} else {
+			if (first_negate) {
+				cmp->negate = negate;
+				first_negate = 0;
+			}
+			if ((negate && !cmp->negate) ||
+			    (!negate && cmp->negate)) {
+				fputs(_(fs_type_syntax_error), stderr);
+				exit(EXIT_USAGE);
+			}
+		}
+#if 0
+		printf("Adding %s to list (type %d).\n", s, cmp->type[num]);
+#endif
+	        cmp->list[num++] = string_copy(s);
+		s = strtok(NULL, ",");
+	}
+	free(list);
+}
+
+/*
+ * This function returns true if a particular option appears in a
+ * comma-delimited options list
+ */
+static int opt_in_list(const char *opt, char *optlist)
+{
+	char	*list, *s;
+
+	if (!optlist)
+		return 0;
+	list = string_copy(optlist);
+
+	s = strtok(list, ",");
+	while(s) {
+		if (strcmp(s, opt) == 0) {
+			free(list);
+			return 1;
+		}
+		s = strtok(NULL, ",");
+	}
+        free(list);
+	return 0;
+}
+
+/* See if the filesystem matches the criteria given by the -t option */
+static int fs_match(struct fs_info *fs, struct fs_type_compile *cmp)
+{
+	int n, ret = 0, checked_type = 0;
+	char *cp;
+
+	if (cmp->list == 0 || cmp->list[0] == 0)
+		return 1;
+
+	for (n=0; (cp = cmp->list[n]); n++) {
+		switch (cmp->type[n]) {
+		case FS_TYPE_NORMAL:
+			checked_type++;
+			if (strcmp(cp, fs->type) == 0) {
+				ret = 1;
+			}
+			break;
+		case FS_TYPE_NEGOPT:
+			if (opt_in_list(cp, fs->opts))
+				return 0;
+			break;
+		case FS_TYPE_OPT:
+			if (!opt_in_list(cp, fs->opts))
+				return 0;
+			break;
+		}
+	}
+	if (checked_type == 0)
+		return 1;
+	return (cmp->negate ? !ret : ret);
+}
+
+/* Check if we should ignore this filesystem. */
+static int ignore(struct fs_info *fs)
+{
+	const char **ip;
+	int wanted = 0;
+
+	/*
+	 * If the pass number is 0, ignore it.
+	 */
+	if (fs->passno == 0)
+		return 1;
+
+	/*
+	 * If this is a bind mount, ignore it.
+	 */
+	if (opt_in_list("bind", fs->opts)) {
+		fprintf(stderr,
+			_("%s: skipping bad line in /etc/fstab: bind mount with nonzero fsck pass number\n"),
+			fs->mountpt);
+		return 1;
+	}
+
+	interpret_type(fs);
+
+	/*
+	 * If a specific fstype is specified, and it doesn't match,
+	 * ignore it.
+	 */
+	if (!fs_match(fs, &fs_type_compiled)) return 1;
+
+	/* Are we ignoring this type? */
+	for(ip = ignored_types; *ip; ip++)
+		if (strcmp(fs->type, *ip) == 0) return 1;
+
+	/* Do we really really want to check this fs? */
+	for(ip = really_wanted; *ip; ip++)
+		if (strcmp(fs->type, *ip) == 0) {
+			wanted = 1;
+			break;
+		}
+
+	/* See if the <fsck.fs> program is available. */
+	if (find_fsck(fs->type) == NULL) {
+		if (wanted)
+			fprintf(stderr, _("fsck: cannot check %s: fsck.%s not found\n"),
+				fs->device, fs->type);
+		return 1;
+	}
+
+	/* We can and want to check this file system type. */
+	return 0;
+}
+
+/*
+ * Returns TRUE if a partition on the same disk is already being
+ * checked.
+ */
+static int device_already_active(char *device)
+{
+	struct fsck_instance *inst;
+	char *base;
+
+	if (force_all_parallel)
+		return 0;
+
+#ifdef BASE_MD
+	/* Don't check a soft raid disk with any other disk */
+	if (instance_list &&
+	    (!strncmp(instance_list->device, BASE_MD, sizeof(BASE_MD)-1) ||
+	     !strncmp(device, BASE_MD, sizeof(BASE_MD)-1)))
+		return 1;
+#endif
+
+	base = base_device(device);
+	/*
+	 * If we don't know the base device, assume that the device is
+	 * already active if there are any fsck instances running.
+	 */
+	if (!base)
+		return (instance_list != 0);
+	for (inst = instance_list; inst; inst = inst->next) {
+		if (!inst->base_device || !strcmp(base, inst->base_device)) {
+			free(base);
+			return 1;
+		}
+	}
+	free(base);
+	return 0;
+}
+
+/* Check all file systems, using the /etc/fstab table. */
+static int check_all(NOARGS)
+{
+	struct fs_info *fs = NULL;
+	int status = EXIT_OK;
+	int not_done_yet = 1;
+	int passno = 1;
+	int pass_done;
+
+	if (verbose)
+		fputs(_("Checking all file systems.\n"), stdout);
+
+	/*
+	 * Do an initial scan over the filesystem; mark filesystems
+	 * which should be ignored as done, and resolve any "auto"
+	 * filesystem types (done as a side-effect of calling ignore()).
+	 */
+	for (fs = filesys_info; fs; fs = fs->next) {
+		if (ignore(fs))
+			fs->flags |= FLAG_DONE;
+	}
+
+	/*
+	 * Find and check the root filesystem.
+	 */
+	if (!parallel_root) {
+		for (fs = filesys_info; fs; fs = fs->next) {
+			if (!strcmp(fs->mountpt, "/"))
+				break;
+		}
+		if (fs) {
+			if (!skip_root && !ignore(fs) &&
+			    !(ignore_mounted && is_mounted(fs->device))) {
+				fsck_device(fs, 1);
+				status |= wait_many(FLAG_WAIT_ALL);
+				if (status > EXIT_NONDESTRUCT)
+					return status;
+			}
+			fs->flags |= FLAG_DONE;
+		}
+	}
+	/*
+	 * This is for the bone-headed user who enters the root
+	 * filesystem twice.  Skip root will skep all root entries.
+	 */
+	if (skip_root)
+		for (fs = filesys_info; fs; fs = fs->next)
+			if (!strcmp(fs->mountpt, "/"))
+				fs->flags |= FLAG_DONE;
+
+	while (not_done_yet) {
+		not_done_yet = 0;
+		pass_done = 1;
+
+		for (fs = filesys_info; fs; fs = fs->next) {
+			if (cancel_requested)
+				break;
+			if (fs->flags & FLAG_DONE)
+				continue;
+			/*
+			 * If the filesystem's pass number is higher
+			 * than the current pass number, then we don't
+			 * do it yet.
+			 */
+			if (fs->passno > passno) {
+				not_done_yet++;
+				continue;
+			}
+			if (ignore_mounted && is_mounted(fs->device)) {
+				fs->flags |= FLAG_DONE;
+				continue;
+			}
+			/*
+			 * If a filesystem on a particular device has
+			 * already been spawned, then we need to defer
+			 * this to another pass.
+			 */
+			if (device_already_active(fs->device)) {
+				pass_done = 0;
+				continue;
+			}
+			/*
+			 * Spawn off the fsck process
+			 */
+			fsck_device(fs, serialize);
+			fs->flags |= FLAG_DONE;
+
+			/*
+			 * Only do one filesystem at a time, or if we
+			 * have a limit on the number of fsck's extant
+			 * at one time, apply that limit.
+			 */
+			if (serialize ||
+			    (max_running && (num_running >= max_running))) {
+				pass_done = 0;
+				break;
+			}
+		}
+		if (cancel_requested)
+			break;
+		if (verbose > 1)
+			printf(_("--waiting-- (pass %d)\n"), passno);
+		status |= wait_many(pass_done ? FLAG_WAIT_ALL :
+				    FLAG_WAIT_ATLEAST_ONE);
+		if (pass_done) {
+			if (verbose > 1)
+				printf("----------------------------------\n");
+			passno++;
+		} else
+			not_done_yet++;
+	}
+	if (cancel_requested && !kill_sent) {
+		kill_all(SIGTERM);
+		kill_sent++;
+	}
+	status |= wait_many(FLAG_WAIT_ATLEAST_ONE);
+	return status;
+}
+
+static void usage(NOARGS)
+{
+	fputs(_("Usage: fsck [-AMNPRTV] [ -C [ fd ] ] [-t fstype] [fs-options] [filesys ...]\n"), stderr);
+	exit(EXIT_USAGE);
+}
+
+#ifdef HAVE_SIGNAL_H
+static void signal_cancel(int sig FSCK_ATTR((unused)))
+{
+	cancel_requested++;
+}
+#endif
+
+static void PRS(int argc, char *argv[])
+{
+	int	i, j;
+	char	*arg, *dev, *tmp = 0;
+	char	options[128];
+	int	opt = 0;
+	int     opts_for_fsck = 0;
+#ifdef HAVE_SIGNAL_H
+	struct sigaction	sa;
+
+	/*
+	 * Set up signal action
+	 */
+	memset(&sa, 0, sizeof(struct sigaction));
+	sa.sa_handler = signal_cancel;
+	sigaction(SIGINT, &sa, 0);
+	sigaction(SIGTERM, &sa, 0);
+#endif
+
+	num_devices = 0;
+	num_args = 0;
+	instance_list = 0;
+
+	progname = argv[0];
+
+	for (i=1; i < argc; i++) {
+		arg = argv[i];
+		if (!arg)
+			continue;
+		if ((arg[0] == '/' && !opts_for_fsck) || strchr(arg, '=')) {
+			if (num_devices >= MAX_DEVICES) {
+				fprintf(stderr, _("%s: too many devices\n"),
+					progname);
+				exit(EXIT_ERROR);
+			}
+			dev = blkid_get_devname(cache, arg, NULL);
+			if (!dev && strchr(arg, '=')) {
+				/*
+				 * Check to see if we failed because
+				 * /proc/partitions isn't found.
+				 */
+				if (access("/proc/partitions", R_OK) < 0) {
+					fprintf(stderr, "Couldn't open /proc/partitions: %s\n",
+						strerror(errno));
+					fprintf(stderr, "Is /proc mounted?\n");
+					exit(EXIT_ERROR);
+				}
+				/*
+				 * Check to see if this is because
+				 * we're not running as root
+				 */
+				if (geteuid())
+					fprintf(stderr,
+		"Must be root to scan for matching filesystems: %s\n", arg);
+				else
+					fprintf(stderr,
+		"Couldn't find matching filesystem: %s\n", arg);
+				exit(EXIT_ERROR);
+			}
+			devices[num_devices++] = dev ? dev : string_copy(arg);
+			continue;
+		}
+		if (arg[0] != '-' || opts_for_fsck) {
+			if (num_args >= MAX_ARGS) {
+				fprintf(stderr, _("%s: too many arguments\n"),
+					progname);
+				exit(EXIT_ERROR);
+			}
+			args[num_args++] = string_copy(arg);
+			continue;
+		}
+		for (j=1; arg[j]; j++) {
+			if (opts_for_fsck) {
+				options[++opt] = arg[j];
+				continue;
+			}
+			switch (arg[j]) {
+			case 'A':
+				doall++;
+				break;
+			case 'C':
+				progress++;
+				if (arg[j+1]) {
+					progress_fd = string_to_int(arg+j+1);
+					if (progress_fd < 0)
+						progress_fd = 0;
+					else
+						goto next_arg;
+				} else if ((i+1) < argc &&
+					   !strncmp(argv[i+1], "-", 1) == 0) {
+					progress_fd = string_to_int(argv[i]);
+					if (progress_fd < 0)
+						progress_fd = 0;
+					else {
+						++i;
+						goto next_arg;
+					}
+				}
+				break;
+			case 'V':
+				verbose++;
+				break;
+			case 'N':
+				noexecute++;
+				break;
+			case 'R':
+				skip_root++;
+				break;
+			case 'T':
+				notitle++;
+				break;
+			case 'M':
+				ignore_mounted++;
+				break;
+			case 'P':
+				parallel_root++;
+				break;
+			case 's':
+				serialize++;
+				break;
+			case 't':
+				tmp = 0;
+				if (fstype)
+					usage();
+				if (arg[j+1])
+					tmp = arg+j+1;
+				else if ((i+1) < argc)
+					tmp = argv[++i];
+				else
+					usage();
+				fstype = string_copy(tmp);
+				compile_fs_type(fstype, &fs_type_compiled);
+				goto next_arg;
+			case '-':
+				opts_for_fsck++;
+				break;
+			case '?':
+				usage();
+				break;
+			default:
+				options[++opt] = arg[j];
+				break;
+			}
+		}
+	next_arg:
+		if (opt) {
+			options[0] = '-';
+			options[++opt] = '\0';
+			if (num_args >= MAX_ARGS) {
+				fprintf(stderr,
+					_("%s: too many arguments\n"),
+					progname);
+				exit(EXIT_ERROR);
+			}
+			args[num_args++] = string_copy(options);
+			opt = 0;
+		}
+	}
+	if (getenv("FSCK_FORCE_ALL_PARALLEL"))
+		force_all_parallel++;
+	if ((tmp = getenv("FSCK_MAX_INST")))
+	    max_running = atoi(tmp);
+}
+
+int main(int argc, char *argv[])
+{
+	int i, status = 0;
+	int interactive = 0;
+	char *oldpath = getenv("PATH");
+	const char *fstab;
+	struct fs_info *fs;
+
+	setvbuf(stdout, NULL, _IONBF, BUFSIZ);
+	setvbuf(stderr, NULL, _IONBF, BUFSIZ);
+
+#ifdef ENABLE_NLS
+	setlocale(LC_MESSAGES, "");
+	setlocale(LC_CTYPE, "");
+	bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
+	textdomain(NLS_CAT_NAME);
+#endif
+	blkid_get_cache(&cache, NULL);
+	PRS(argc, argv);
+
+	if (!notitle)
+		printf("fsck %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE);
+
+	fstab = getenv("FSTAB_FILE");
+	if (!fstab)
+		fstab = _PATH_MNTTAB;
+	load_fs_info(fstab);
+
+	/* Update our search path to include uncommon directories. */
+	if (oldpath) {
+		fsck_path = malloc (strlen (fsck_prefix_path) + 1 +
+				    strlen (oldpath) + 1);
+		if (!fsck_path) {
+			fprintf(stderr, "%s: Unable to allocate memory for fsck_path\n", progname);
+			exit(EXIT_ERROR);
+		}
+		strcpy (fsck_path, fsck_prefix_path);
+		strcat (fsck_path, ":");
+		strcat (fsck_path, oldpath);
+	} else {
+		fsck_path = string_copy(fsck_prefix_path);
+	}
+
+	if ((num_devices == 1) || (serialize))
+		interactive = 1;
+
+	/* If -A was specified ("check all"), do that! */
+	if (doall)
+		return check_all();
+
+	if (num_devices == 0) {
+		serialize++;
+		interactive++;
+		return check_all();
+	}
+	for (i = 0 ; i < num_devices; i++) {
+		if (cancel_requested) {
+			if (!kill_sent) {
+				kill_all(SIGTERM);
+				kill_sent++;
+			}
+			break;
+		}
+		fs = lookup(devices[i]);
+		if (!fs) {
+			fs = create_fs_device(devices[i], 0, "auto",
+					      0, -1, -1);
+			if (!fs)
+				continue;
+		}
+		if (ignore_mounted && is_mounted(fs->device))
+			continue;
+		fsck_device(fs, interactive);
+		if (serialize ||
+		    (max_running && (num_running >= max_running))) {
+			struct fsck_instance *inst;
+
+			inst = wait_one(0);
+			if (inst) {
+				status |= inst->exit_status;
+				free_instance(inst);
+			}
+			if (verbose > 1)
+				printf("----------------------------------\n");
+		}
+	}
+	status |= wait_many(FLAG_WAIT_ALL);
+	free(fsck_path);
+	blkid_put_cache(cache);
+	return status;
+}
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/fsck.h b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/fsck.h
new file mode 100644
index 0000000..8a0f70e
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/fsck.h
@@ -0,0 +1,73 @@
+/*
+ * fsck.h
+ */
+
+#include <time.h>
+
+#ifdef __STDC__
+#define NOARGS void
+#else
+#define NOARGS
+#define const
+#endif
+
+#ifdef __GNUC__
+#define FSCK_ATTR(x) __attribute__(x)
+#else
+#define FSCK_ATTR(x)
+#endif
+
+
+#ifndef DEFAULT_FSTYPE
+#define DEFAULT_FSTYPE	"ext2"
+#endif
+
+#define MAX_DEVICES 32
+#define MAX_ARGS 32
+
+#define EXIT_OK          0
+#define EXIT_NONDESTRUCT 1
+#define EXIT_DESTRUCT    2
+#define EXIT_UNCORRECTED 4
+#define EXIT_ERROR       8
+#define EXIT_USAGE       16
+#define EXIT_LIBRARY     128
+
+/*
+ * Internal structure for mount tabel entries.
+ */
+
+struct fs_info {
+	char  *device;
+	char  *mountpt;
+	char  *type;
+	char  *opts;
+	int   freq;
+	int   passno;
+	int   flags;
+	struct fs_info *next;
+};
+
+#define FLAG_DONE 1
+#define FLAG_PROGRESS 2
+
+/*
+ * Structure to allow exit codes to be stored
+ */
+struct fsck_instance {
+	int	pid;
+	int	flags;
+	int	exit_status;
+	time_t	start_time;
+	char *	prog;
+	char *	type;
+	char *	device;
+	char *	base_device;
+	struct fsck_instance *next;
+};
+
+extern char *base_device(const char *device);
+extern const char *identify_fs(const char *fs_name, const char *fs_types);
+
+/* ismounted.h */
+extern int is_mounted(const char *file);
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/ismounted.c b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/ismounted.c
new file mode 100644
index 0000000..6aa0e04
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/ismounted.c
@@ -0,0 +1,218 @@
+/*
+ * ismounted.c --- Check to see if the filesystem was mounted
+ *
+ * Copyright (C) 1995,1996,1997,1998,1999,2000,2008 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include "config.h"
+#include <stdio.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <fcntl.h>
+#ifdef HAVE_LINUX_FD_H
+#include <linux/fd.h>
+#endif
+#ifdef HAVE_MNTENT_H
+#include <mntent.h>
+#endif
+#include <string.h>
+#include <sys/stat.h>
+#include <ctype.h>
+
+#include "fsck.h"
+
+/*
+ * ext2fs_check_if_mounted flags
+ */
+#define MF_MOUNTED		1
+
+#include "et/com_err.h"
+
+#ifdef HAVE_SETMNTENT
+static char *skip_over_blank(char *cp)
+{
+	while (*cp && isspace(*cp))
+		cp++;
+	return cp;
+}
+
+static char *skip_over_word(char *cp)
+{
+	while (*cp && !isspace(*cp))
+		cp++;
+	return cp;
+}
+
+static char *parse_word(char **buf)
+{
+	char *word, *next;
+
+	word = *buf;
+	if (*word == 0)
+		return 0;
+
+	word = skip_over_blank(word);
+	next = skip_over_word(word);
+	if (*next)
+		*next++ = 0;
+	*buf = next;
+	return word;
+}
+#endif
+
+/*
+ * Helper function which checks a file in /etc/mtab format to see if a
+ * filesystem is mounted.  Returns an error if the file doesn't exist
+ * or can't be opened.
+ */
+static errcode_t check_mntent_file(const char *mtab_file, const char *file,
+				   int *mount_flags)
+{
+#ifdef HAVE_SETMNTENT
+	struct stat	st_buf;
+	errcode_t	retval = 0;
+	dev_t		file_dev=0, file_rdev=0;
+	ino_t		file_ino=0;
+	FILE 		*f;
+	char		buf[1024], *device = 0, *mnt_dir = 0, *cp;
+
+	*mount_flags = 0;
+	if ((f = setmntent (mtab_file, "r")) == NULL)
+		return errno;
+	if (stat(file, &st_buf) == 0) {
+		if (S_ISBLK(st_buf.st_mode)) {
+#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
+			file_rdev = st_buf.st_rdev;
+#endif	/* __GNU__ */
+		} else {
+			file_dev = st_buf.st_dev;
+			file_ino = st_buf.st_ino;
+		}
+	}
+	while (1) {
+		if (!fgets(buf, sizeof(buf), f)) {
+			device = mnt_dir = 0;
+			break;
+		}
+		buf[sizeof(buf)-1] = 0;
+
+		cp = buf;
+		device = parse_word(&cp);
+		if (!device || *device == '#')
+			return 0;	/* Ignore blank lines and comments */
+		mnt_dir = parse_word(&cp);
+
+		if (device[0] != '/')
+			continue;
+
+		if (strcmp(file, device) == 0)
+			break;
+		if (stat(device, &st_buf) == 0) {
+			if (S_ISBLK(st_buf.st_mode)) {
+#ifndef __GNU__
+				if (file_rdev && (file_rdev == st_buf.st_rdev))
+					break;
+#endif	/* __GNU__ */
+			} else {
+				if (file_dev && ((file_dev == st_buf.st_dev) &&
+						 (file_ino == st_buf.st_ino)))
+					break;
+			}
+		}
+	}
+
+	if (mnt_dir == 0) {
+#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
+		/*
+		 * Do an extra check to see if this is the root device.  We
+		 * can't trust /etc/mtab, and /proc/mounts will only list
+		 * /dev/root for the root filesystem.  Argh.  Instead we
+		 * check if the given device has the same major/minor number
+		 * as the device that the root directory is on.
+		 */
+		if (file_rdev && (stat("/", &st_buf) == 0) &&
+		    (st_buf.st_dev == file_rdev))
+			*mount_flags = MF_MOUNTED;
+#endif	/* __GNU__ */
+		goto errout;
+	}
+#ifndef __GNU__ /* The GNU hurd is deficient; what else is new? */
+	/* Validate the entry in case /etc/mtab is out of date */
+	/*
+	 * We need to be paranoid, because some broken distributions
+	 * (read: Slackware) don't initialize /etc/mtab before checking
+	 * all of the non-root filesystems on the disk.
+	 */
+	if (stat(mnt_dir, &st_buf) < 0) {
+		retval = errno;
+		if (retval == ENOENT) {
+#ifdef DEBUG
+			printf("Bogus entry in %s!  (%s does not exist)\n",
+			       mtab_file, mnt_dir);
+#endif /* DEBUG */
+			retval = 0;
+		}
+		goto errout;
+	}
+	if (file_rdev && (st_buf.st_dev != file_rdev)) {
+#ifdef DEBUG
+		printf("Bogus entry in %s!  (%s not mounted on %s)\n",
+		       mtab_file, file, mnt_dir);
+#endif /* DEBUG */
+		goto errout;
+	}
+#endif /* __GNU__ */
+	*mount_flags = MF_MOUNTED;
+
+	retval = 0;
+errout:
+	endmntent (f);
+	return retval;
+#else /* !HAVE_SETMNTENT */
+	return 0;
+#endif /* HAVE_MNTENT_H */
+}
+
+int is_mounted(const char *file)
+{
+	errcode_t	retval;
+	int		mount_flags = 0;
+
+#ifdef __linux__
+	retval = check_mntent_file("/proc/mounts", file, &mount_flags);
+	if (retval)
+		return 0;
+	if (mount_flags)
+		return 1;
+#endif /* __linux__ */
+	retval = check_mntent_file("/etc/mtab", file, &mount_flags);
+	if (retval)
+		return 0;
+	return (mount_flags);
+}
+
+#ifdef DEBUG
+int main(int argc, char **argv)
+{
+	if (argc < 2) {
+		fprintf(stderr, "Usage: %s device\n", argv[0]);
+		exit(1);
+	}
+
+	if (is_mounted(argv[1]))
+		printf("\t%s is mounted.\n", argv[1]);
+	exit(0);
+}
+#endif /* DEBUG */
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/jfs_user.h b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/jfs_user.h
new file mode 100644
index 0000000..3070cd5
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/jfs_user.h
@@ -0,0 +1,8 @@
+#ifndef _JFS_USER_H
+#define _JFS_USER_H
+
+typedef unsigned short kdev_t;
+
+#include <ext2fs/kernel-jbd.h>
+
+#endif /* _JFS_USER_H */
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/logsave.8.in b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/logsave.8.in
new file mode 100644
index 0000000..f0fbe41
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/logsave.8.in
@@ -0,0 +1,61 @@
+.\" -*- nroff -*-
+.\" Copyright 2003 by Theodore Ts'o.  All Rights Reserved.
+.\" This file may be copied under the terms of the GNU Public License.
+.\" 
+.TH LOGSAVE 8 "@E2FSPROGS_MONTH@ @E2FSPROGS_YEAR@" "E2fsprogs version @E2FSPROGS_VERSION@"
+.SH NAME
+logsave \- save the output of a command in a logfile
+.SH SYNOPSIS
+.B logsave
+[
+.B \-asv
+]
+.I logfile cmd_prog [ ... ]
+.SH DESCRIPTION
+The
+.B logsave
+program will execute
+.I cmd_prog 
+with the specified argument(s), and save a copy of its output to
+.IR logfile .
+If the containing directory for
+.I logfile
+does not exist, 
+.B logsave
+will accumulate the output in memory until it can be written out.
+A copy of the output will also be written to standard output.
+.PP
+If 
+.I cmd_prog
+is a single hyphen ('-'), then instead of executing a program,
+.B logsave
+will take its input from standard input and save it in
+.I logfile
+.PP
+.B logsave
+is useful for saving the output of initial boot scripts 
+until the /var partition is mounted, so the output can be written to 
+/var/log.
+.SH OPTIONS
+.TP
+.B \-a
+This option will cause the output to be appended to 
+.IR logfile ,
+instead of replacing its current contents.
+.TP
+.B \-s
+This option will cause 
+.B logsave
+to skip writing to the log file text which is bracketed with a control-A 
+(ASCII 001 or Start of Header) and control-B (ASCII 002 or Start of
+Text).  This allows progress bar information to be visible to the user
+on the console, while not being written to the log file.
+.TP
+.B \-v
+This option will make
+.B logsave
+to be more verbose in its output to the user.
+.SH AUTHOR
+Theodore Ts'o (tytso@mit.edu)
+.SH SEE ALSO
+.BR fsck (8)
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/logsave.c b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/logsave.c
new file mode 100644
index 0000000..8612edf
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/logsave.c
@@ -0,0 +1,334 @@
+/*
+ * logsave.c --- A program which saves the output of a program until
+ *	/var/log is mounted.
+ *
+ * Copyright (C) 2003 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#define _XOPEN_SOURCE 600 /* for inclusion of sa_handler in Solaris */
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <time.h>
+#include <errno.h>
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#else
+extern char *optarg;
+extern int optind;
+#endif
+
+static int	outfd = -1;
+static int	outbufsize = 0;
+static void	*outbuf = 0;
+static int	verbose = 0;
+static int	do_skip = 0;
+static int	skip_mode = 0;
+static pid_t	child_pid = -1;
+
+static void usage(char *progname)
+{
+	printf("Usage: %s [-asv] logfile program\n", progname);
+	exit(1);
+}
+
+#define SEND_LOG	0x01
+#define SEND_CONSOLE	0x02
+#define SEND_BOTH	0x03
+
+/*
+ * Helper function that does the right thing if write returns a
+ * partial write, or an EGAIN/EINTR error.
+ */
+static int write_all(int fd, const char *buf, size_t count)
+{
+	ssize_t ret;
+	int c = 0;
+
+	while (count > 0) {
+		ret = write(fd, buf, count);
+		if (ret < 0) {
+			if ((errno == EAGAIN) || (errno == EINTR))
+				continue;
+			return -1;
+		}
+		count -= ret;
+		buf += ret;
+		c += ret;
+	}
+	return c;
+}
+
+static void send_output(const char *buffer, int c, int flag)
+{
+	const char	*cp;
+	char		*n;
+	int		cnt, d, del;
+
+	if (c == 0)
+		c = strlen(buffer);
+
+	if (flag & SEND_CONSOLE) {
+		cnt = c;
+		cp = buffer;
+		while (cnt) {
+			del = 0;
+			for (d=0; d < cnt; d++) {
+				if (skip_mode &&
+				    (cp[d] == '\001' || cp[d] == '\002')) {
+					del = 1;
+					break;
+				}
+			}
+			write_all(1, cp, d);
+			if (del)
+				d++;
+			cnt -= d;
+			cp += d;
+		}
+	}
+	if (!(flag & SEND_LOG))
+		return;
+	if (outfd > 0)
+		write_all(outfd, buffer, c);
+	else {
+		n = realloc(outbuf, outbufsize + c);
+		if (n) {
+			outbuf = n;
+			memcpy(((char *)outbuf)+outbufsize, buffer, c);
+			outbufsize += c;
+		}
+	}
+}
+
+static int do_read(int fd)
+{
+	int	c;
+	char	buffer[4096], *cp, *sep;
+
+	c = read(fd, buffer, sizeof(buffer)-1);
+	if (c <= 0)
+		return c;
+	if (do_skip) {
+		send_output(buffer, c, SEND_CONSOLE);
+		buffer[c] = 0;
+		cp = buffer;
+		while (*cp) {
+			if (skip_mode) {
+				cp = strchr(cp, '\002');
+				if (!cp)
+					return 0;
+				cp++;
+				skip_mode = 0;
+				continue;
+			}
+			sep = strchr(cp, '\001');
+			if (sep)
+				*sep = 0;
+			send_output(cp, 0, SEND_LOG);
+			if (sep) {
+				cp = sep + 1;
+				skip_mode = 1;
+			} else
+				break;
+		}
+	} else
+		send_output(buffer, c, SEND_BOTH);
+	return c;
+}
+
+static void signal_term(int sig)
+{
+	if (child_pid > 0)
+		kill(child_pid, sig);
+}
+
+static int run_program(char **argv)
+{
+	int	fds[2];
+	int	status, rc, pid;
+	char	buffer[80];
+#ifdef HAVE_SIGNAL_H
+	struct sigaction	sa;
+#endif
+
+	if (pipe(fds) < 0) {
+		perror("pipe");
+		exit(1);
+	}
+
+#ifdef HAVE_SIGNAL_H
+	memset(&sa, 0, sizeof(struct sigaction));
+	sa.sa_handler = signal_term;
+	sigaction(SIGINT, &sa, 0);
+	sigaction(SIGTERM, &sa, 0);
+#ifdef SA_RESTART
+	sa.sa_flags = SA_RESTART;
+#endif
+#endif
+
+	pid = fork();
+	if (pid < 0) {
+		perror("vfork");
+		exit(1);
+	}
+	if (pid == 0) {
+		dup2(fds[1],1);		/* fds[1] replaces stdout */
+		dup2(fds[1],2);  	/* fds[1] replaces stderr */
+		close(fds[0]);	/* don't need this here */
+		close(fds[1]);
+
+		execvp(argv[0], argv);
+		perror(argv[0]);
+		exit(1);
+	}
+	child_pid = pid;
+	close(fds[1]);
+
+	while (!(waitpid(pid, &status, WNOHANG ))) {
+		do_read(fds[0]);
+	}
+	child_pid = -1;
+	do_read(fds[0]);
+	close(fds[0]);
+
+	if ( WIFEXITED(status) ) {
+		rc = WEXITSTATUS(status);
+		if (rc) {
+			send_output(argv[0], 0, SEND_BOTH);
+			sprintf(buffer, " died with exit status %d\n", rc);
+			send_output(buffer, 0, SEND_BOTH);
+		}
+	} else {
+		if (WIFSIGNALED(status)) {
+			send_output(argv[0], 0, SEND_BOTH);
+			sprintf(buffer, "died with signal %d\n",
+				WTERMSIG(status));
+			send_output(buffer, 0, SEND_BOTH);
+			rc = 1;
+		}
+		rc = 0;
+	}
+	return rc;
+}
+
+static int copy_from_stdin(void)
+{
+	int	c, bad_read = 0;
+
+	while (1) {
+		c = do_read(0);
+		if ((c == 0 ) ||
+		    ((c < 0) && ((errno == EAGAIN) || (errno == EINTR)))) {
+			if (bad_read++ > 3)
+				break;
+			continue;
+		}
+		if (c < 0) {
+			perror("read");
+			exit(1);
+		}
+		bad_read = 0;
+	}
+	return 0;
+}
+
+
+
+int main(int argc, char **argv)
+{
+	int	c, pid, rc;
+	char	*outfn, **cpp;
+	int	openflags = O_CREAT|O_WRONLY|O_TRUNC;
+	int	send_flag = SEND_LOG;
+	int	do_stdin;
+	time_t	t;
+
+	while ((c = getopt(argc, argv, "+asv")) != EOF) {
+		switch (c) {
+		case 'a':
+			openflags &= ~O_TRUNC;
+			openflags |= O_APPEND;
+			break;
+		case 's':
+			do_skip = 1;
+			break;
+		case 'v':
+			verbose++;
+			send_flag |= SEND_CONSOLE;
+			break;
+		}
+	}
+	if (optind == argc || optind+1 == argc)
+		usage(argv[0]);
+	outfn = argv[optind];
+	optind++;
+	argv += optind;
+	argc -= optind;
+
+	outfd = open(outfn, openflags, 0644);
+	do_stdin = !strcmp(argv[0], "-");
+
+	send_output("Log of ", 0, send_flag);
+	if (do_stdin)
+		send_output("stdin", 0, send_flag);
+	else {
+		for (cpp = argv; *cpp; cpp++) {
+			send_output(*cpp, 0, send_flag);
+			send_output(" ", 0, send_flag);
+		}
+	}
+	send_output("\n", 0, send_flag);
+	t = time(0);
+	send_output(ctime(&t), 0, send_flag);
+	send_output("\n", 0, send_flag);
+
+	if (do_stdin)
+		rc = copy_from_stdin();
+	else
+		rc = run_program(argv);
+
+	send_output("\n", 0, send_flag);
+	t = time(0);
+	send_output(ctime(&t), 0, send_flag);
+	send_output("----------------\n", 0, send_flag);
+
+	if (outbuf) {
+		pid = fork();
+		if (pid < 0) {
+			perror("fork");
+			exit(1);
+		}
+		if (pid) {
+			if (verbose)
+				printf("Backgrounding to save %s later\n",
+				       outfn);
+			exit(rc);
+		}
+		setsid();	/* To avoid getting killed by init */
+		while (outfd < 0) {
+			outfd = open(outfn, openflags, 0644);
+			sleep(1);
+		}
+		write_all(outfd, outbuf, outbufsize);
+		free(outbuf);
+	}
+	if (outfd >= 0)
+		close(outfd);
+
+	exit(rc);
+}
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/lsattr.1.in b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/lsattr.1.in
new file mode 100644
index 0000000..7798a34
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/lsattr.1.in
@@ -0,0 +1,45 @@
+.\" -*- nroff -*-
+.TH LSATTR 1 "@E2FSPROGS_MONTH@ @E2FSPROGS_YEAR@" "E2fsprogs version @E2FSPROGS_VERSION@"
+.SH NAME
+lsattr \- list file attributes on a Linux second extended file system
+.SH SYNOPSIS
+.B lsattr
+[
+.B \-RVadv
+]
+[
+.I files...
+]
+.SH DESCRIPTION
+.B lsattr
+lists the file attributes on a second extended file system.  See
+.BR chattr (1)
+for a description of the attributes and what they mean.
+.SH OPTIONS
+.TP
+.B \-R
+Recursively list attributes of directories and their contents.
+.TP
+.B \-V
+Display the program version.
+.TP
+.B \-a
+List all files in directories, including files that start with `.'.
+.TP
+.B \-d
+List directories like other files, rather than listing their contents.
+.TP
+.B \-v
+List the file's version/generation number.
+.SH AUTHOR
+.B lsattr
+was written by Remy Card <Remy.Card@linux.org>.  It is currently being
+maintained by Theodore Ts'o <tytso@alum.mit.edu>.
+.SH BUGS
+There are none :-).
+.SH AVAILABILITY
+.B lsattr
+is part of the e2fsprogs package and is available from
+http://e2fsprogs.sourceforge.net.
+.SH SEE ALSO
+.BR chattr (1)
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/lsattr.c b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/lsattr.c
new file mode 100644
index 0000000..e5e5969
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/lsattr.c
@@ -0,0 +1,213 @@
+/*
+ * lsattr.c		- List file attributes on an ext2 file system
+ *
+ * Copyright (C) 1993, 1994  Remy Card <card@masi.ibp.fr>
+ *                           Laboratoire MASI, Institut Blaise Pascal
+ *                           Universite Pierre et Marie Curie (Paris VI)
+ *
+ * This file can be redistributed under the terms of the GNU General
+ * Public License
+ */
+
+/*
+ * History:
+ * 93/10/30	- Creation
+ * 93/11/13	- Replace stat() calls by lstat() to avoid loops
+ * 94/02/27	- Integrated in Ted's distribution
+ * 98/12/29	- Display version info only when -V specified (G M Sipe)
+ */
+
+#define _LARGEFILE64_SOURCE
+
+#include "config.h"
+#include <sys/types.h>
+#include <dirent.h>
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <fcntl.h>
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#else
+extern int optind;
+extern char *optarg;
+#endif
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include "ext2fs/ext2_fs.h"
+#include "et/com_err.h"
+#include "e2p/e2p.h"
+
+#include "../version.h"
+#include "nls-enable.h"
+
+#ifdef __GNUC__
+#define EXT2FS_ATTR(x) __attribute__(x)
+#else
+#define EXT2FS_ATTR(x)
+#endif
+
+static const char * program_name = "lsattr";
+
+static int all;
+static int dirs_opt;
+static unsigned pf_options;
+static int recursive;
+static int verbose;
+static int generation_opt;
+
+#ifdef _LFS64_LARGEFILE
+#define LSTAT		lstat64
+#define STRUCT_STAT	struct stat64
+#else
+#define LSTAT		lstat
+#define STRUCT_STAT	struct stat
+#endif
+
+static void usage(void)
+{
+	fprintf(stderr, _("Usage: %s [-RVadlv] [files...]\n"), program_name);
+	exit(1);
+}
+
+static int list_attributes (const char * name)
+{
+	unsigned long flags;
+	unsigned long generation;
+
+	if (fgetflags (name, &flags) == -1) {
+		com_err (program_name, errno, _("While reading flags on %s"),
+			 name);
+		return -1;
+	}
+	if (generation_opt) {
+		if (fgetversion (name, &generation) == -1) {
+			com_err (program_name, errno,
+				 _("While reading version on %s"),
+				 name);
+			return -1;
+		}
+		printf ("%5lu ", generation);
+	}
+	if (pf_options & PFOPT_LONG) {
+		printf("%-28s ", name);
+		print_flags(stdout, flags, pf_options);
+		fputc('\n', stdout);
+	} else {
+		print_flags(stdout, flags, pf_options);
+		printf(" %s\n", name);
+	}
+	return 0;
+}
+
+static int lsattr_dir_proc (const char *, struct dirent *, void *);
+
+static int lsattr_args (const char * name)
+{
+	STRUCT_STAT	st;
+	int retval = 0;
+
+	if (LSTAT (name, &st) == -1) {
+		com_err (program_name, errno, _("while trying to stat %s"),
+			 name);
+		retval = -1;
+	} else {
+		if (S_ISDIR(st.st_mode) && !dirs_opt)
+			retval = iterate_on_dir (name, lsattr_dir_proc, NULL);
+		else
+			retval = list_attributes (name);
+	}
+	return retval;
+}
+
+static int lsattr_dir_proc (const char * dir_name, struct dirent * de,
+			    void * private EXT2FS_ATTR((unused)))
+{
+	STRUCT_STAT	st;
+	char *path;
+	int dir_len = strlen(dir_name);
+
+	path = malloc(dir_len + strlen (de->d_name) + 2);
+
+	if (dir_len && dir_name[dir_len-1] == '/')
+		sprintf (path, "%s%s", dir_name, de->d_name);
+	else
+		sprintf (path, "%s/%s", dir_name, de->d_name);
+	if (LSTAT (path, &st) == -1)
+		perror (path);
+	else {
+		if (de->d_name[0] != '.' || all) {
+			list_attributes (path);
+			if (S_ISDIR(st.st_mode) && recursive &&
+			    strcmp(de->d_name, ".") &&
+			    strcmp(de->d_name, "..")) {
+				printf ("\n%s:\n", path);
+				iterate_on_dir (path, lsattr_dir_proc, NULL);
+				printf ("\n");
+			}
+		}
+	}
+	free(path);
+	return 0;
+}
+
+int main (int argc, char ** argv)
+{
+	int c;
+	int i;
+	int err, retval = 0;
+
+#ifdef ENABLE_NLS
+	setlocale(LC_MESSAGES, "");
+	setlocale(LC_CTYPE, "");
+	bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
+	textdomain(NLS_CAT_NAME);
+	set_com_err_gettext(gettext);
+#endif
+	if (argc && *argv)
+		program_name = *argv;
+	while ((c = getopt (argc, argv, "RVadlv")) != EOF)
+		switch (c)
+		{
+			case 'R':
+				recursive = 1;
+				break;
+			case 'V':
+				verbose = 1;
+				break;
+			case 'a':
+				all = 1;
+				break;
+			case 'd':
+				dirs_opt = 1;
+				break;
+			case 'l':
+				pf_options = PFOPT_LONG;
+				break;
+			case 'v':
+				generation_opt = 1;
+				break;
+			default:
+				usage();
+		}
+
+	if (verbose)
+		fprintf (stderr, "lsattr %s (%s)\n",
+			 E2FSPROGS_VERSION, E2FSPROGS_DATE);
+	if (optind > argc - 1) {
+		if (lsattr_args (".") == -1)
+			retval = 1;
+	} else {
+		for (i = optind; i < argc; i++) {
+			err = lsattr_args (argv[i]);
+			if (err)
+				retval = 1;
+		}
+	}
+	exit(retval);
+}
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/mke2fs-hurd.conf b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/mke2fs-hurd.conf
new file mode 100644
index 0000000..4f0527d
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/mke2fs-hurd.conf
@@ -0,0 +1,42 @@
+[defaults]
+	base_features = sparse_super,filetype,resize_inode,dir_index,ext_attr
+	default_mntopts = acl,user_xattr
+	enable_periodic_fsck = 0
+	blocksize = 4096
+	inode_size = 128
+	inode_ratio = 16384
+
+[fs_types]
+	ext3 = {
+		features = has_journal
+	}
+	ext4 = {
+		features = has_journal,extent,huge_file,flex_bg,uninit_bg,dir_nlink,extra_isize
+		auto_64-bit_support = 1
+		inode_size = 256
+	}
+	small = {
+		inode_ratio = 4096
+	}
+	floppy = {
+		inode_ratio = 8192
+	}
+	big = {
+		inode_ratio = 32768
+	}
+	huge = {
+		inode_ratio = 65536
+	}
+	news = {
+		inode_ratio = 4096
+	}
+	largefile = {
+		inode_ratio = 1048576
+	}
+	largefile4 = {
+		inode_ratio = 4194304
+	}
+	hurd = {
+	     blocksize = 4096
+	     inode_size = 128
+	}
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/mke2fs.8.in b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/mke2fs.8.in
new file mode 100644
index 0000000..fea50da
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/mke2fs.8.in
@@ -0,0 +1,700 @@
+.\" -*- nroff -*-
+.\" Copyright 1993, 1994, 1995 by Theodore Ts'o.  All Rights Reserved.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH MKE2FS 8 "@E2FSPROGS_MONTH@ @E2FSPROGS_YEAR@" "E2fsprogs version @E2FSPROGS_VERSION@"
+.SH NAME
+mke2fs \- create an ext2/ext3/ext4 filesystem
+.SH SYNOPSIS
+.B mke2fs
+[
+.B \-c
+|
+.B \-l
+.I filename
+]
+[
+.B \-b
+.I block-size
+]
+[
+.B \-D
+]
+[
+.B \-f
+.I fragment-size
+]
+[
+.B \-g
+.I blocks-per-group
+]
+[
+.B \-G
+.I number-of-groups
+]
+[
+.B \-i
+.I bytes-per-inode
+]
+[
+.B \-I
+.I inode-size
+]
+[
+.B \-j
+]
+[
+.B \-J
+.I journal-options
+]
+[
+.B \-N
+.I number-of-inodes
+]
+[
+.B \-n
+]
+[
+.B \-m
+.I reserved-blocks-percentage
+]
+[
+.B \-o
+.I creator-os
+]
+[
+.B \-O
+.IR feature [,...]
+]
+[
+.B \-q
+]
+[
+.B \-r
+.I fs-revision-level
+]
+[
+.B \-E
+.I extended-options
+]
+[
+.B \-v
+]
+[
+.B \-F
+]
+[
+.B \-L
+.I volume-label
+]
+[
+.B \-M
+.I last-mounted-directory
+]
+[
+.B \-S
+]
+[
+.B \-t
+.I fs-type
+]
+[
+.B \-T
+.I usage-type
+]
+[
+.B \-U
+.I UUID
+]
+[
+.B \-V
+]
+.I device
+[
+.I blocks-count
+]
+@JDEV@.sp
+@JDEV@.B "mke2fs \-O journal_dev"
+@JDEV@[
+@JDEV@.B \-b
+@JDEV@.I block-size
+@JDEV@]
+.\" No external-journal specific journal options yet (size is ignored)
+.\" @JDEV@[
+.\" @JDEV@.B \-J
+.\" @JDEV@.I journal-options
+.\" @JDEV@]
+@JDEV@[
+@JDEV@.B \-L
+@JDEV@.I volume-label
+@JDEV@]
+@JDEV@[
+@JDEV@.B \-n
+@JDEV@]
+@JDEV@[
+@JDEV@.B \-q
+@JDEV@]
+@JDEV@[
+@JDEV@.B \-v
+@JDEV@]
+@JDEV@.I external-journal
+@JDEV@[
+@JDEV@.I blocks-count
+@JDEV@]
+.SH DESCRIPTION
+.B mke2fs
+is used to create an ext2, ext3, or ext4 filesystem, usually in a disk
+partition.
+.I device
+is the special file corresponding to the device (e.g
+.IR /dev/hdXX ).
+.I blocks-count
+is the number of blocks on the device.  If omitted,
+.B mke2fs
+automagically figures the file system size.  If called as
+.B mkfs.ext3
+a journal is created as if the
+.B \-j
+option was specified.
+.PP
+The defaults of the parameters for the newly created filesystem, if not
+overridden by the options listed below, are controlled by the
+.B /etc/mke2fs.conf
+configuration file.  See the
+.BR mke2fs.conf (5)
+manual page for more details.
+.SH OPTIONS
+.TP
+.BI \-b " block-size"
+Specify the size of blocks in bytes.  Valid block-size values are 1024,
+2048 and 4096 bytes per block.  If omitted,
+block-size is heuristically determined by the filesystem size and
+the expected usage of the filesystem (see the
+.B \-T
+option).  If
+.I block-size
+is preceded by a negative sign ('-'), then
+.B mke2fs
+will use heuristics to determine the
+appropriate block size, with the constraint that the block size will be
+at least
+.I block-size
+bytes.  This is useful for certain hardware devices which require that
+the blocksize be a multiple of 2k.
+.TP
+.B \-c
+Check the device for bad blocks before creating the file system.  If
+this option is specified twice, then a slower read-write
+test is used instead of a fast read-only test.
+.TP
+.B \-C " cluster-size"
+Specify the size of cluster in bytes for filesystems using the bigalloc
+feature.  Valid cluster-size values are from 2048 to 256M bytes per
+cluster.  This can only be specified if the bigalloc feature is
+enabled.  (See the
+.B ext4 (5)
+man page for more details about bigalloc.)   The default cluster size if
+bigalloc is enabled is 16 times the block size.
+.TP
+.B \-D
+Use direct I/O when writing to the disk.  This avoids mke2fs dirtying a
+lot of buffer cache memory, which may impact other applications running
+on a busy server.  This option will cause mke2fs to run much more
+slowly, however, so there is a tradeoff to using direct I/O.
+.TP
+.BI \-E " extended-options"
+Set extended options for the filesystem.  Extended options are comma
+separated, and may take an argument using the equals ('=') sign.  The
+.B \-E
+option used to be
+.B \-R
+in earlier versions of
+.BR mke2fs .
+The
+.B \-R
+option is still accepted for backwards compatibility, but is deprecated.
+The following extended options are supported:
+.RS 1.2i
+.TP
+.BI mmp_update_interval= interval
+Adjust the initial MMP update interval to
+.I interval
+seconds.  Specifying an
+.I interval
+of 0 means to use the default interval.  The specified interval must
+be less than 300 seconds.  Requires that the
+.B mmp
+feature be enabled.
+.TP
+.BI stride= stride-size
+Configure the filesystem for a RAID array with
+.I stride-size
+filesystem blocks. This is the number of blocks read or written to disk
+before moving to the next disk, which is sometimes referred to as the
+.I chunk size.
+This mostly affects placement of filesystem metadata like bitmaps at
+.B mke2fs
+time to avoid placing them on a single disk, which can hurt performance.
+It may also be used by the block allocator.
+.TP
+.BI stripe_width= stripe-width
+Configure the filesystem for a RAID array with
+.I stripe-width
+filesystem blocks per stripe. This is typically stride-size * N, where
+N is the number of data-bearing disks in the RAID (e.g. for RAID 5 there is one
+parity disk, so N will be the number of disks in the array minus 1).
+This allows the block allocator to prevent read-modify-write of the
+parity in a RAID stripe if possible when the data is written.
+.TP
+.BI resize= max-online-resize
+Reserve enough space so that the block group descriptor table can grow
+to support a filesystem that has
+.I max-online-resize
+blocks.
+.TP
+.B lazy_itable_init\fR[\fB= \fI<0 to disable, 1 to enable>\fR]
+If enabled and the uninit_bg feature is enabled, the inode table will
+not be fully initialized by
+.BR mke2fs .
+This speeds up filesystem
+initialization noticeably, but it requires the kernel to finish
+initializing the filesystem in the background when the filesystem is
+first mounted.  If the option value is omitted, it defaults to 1 to
+enable lazy inode table zeroing.
+.TP
+.B lazy_journal_init\fR[\fB= \fI<0 to disable, 1 to enable>\fR]
+If enabled, the journal inode will not be fully zeroed out by
+.BR mke2fs .
+This speeds up filesystem initialization noticeably, but carries some
+small risk if the system crashes before the journal has been overwritten
+entirely one time.  If the option value is omitted, it defaults to 1 to
+enable lazy journal inode zeroing.
+.TP
+.BI root_owner [=uid:gid]
+Specify the numeric user and group ID of the root directory.  If no UID:GID
+is specified, use the user and group ID of the user running \fBmke2fs\fR.
+In \fBmke2fs\fR 1.42 and earlier the UID and GID of the root directory were
+set by default to the UID and GID of the user running the mke2fs command.
+The \fBroot_owner=\fR option allows explicitly specifying these values,
+and avoid side-effects for users that do not expect the contents of the
+filesystem to change based on the user running \fBmke2fs\fR.
+.TP
+.B test_fs
+Set a flag in the filesystem superblock indicating that it may be
+mounted using experimental kernel code, such as the ext4dev filesystem.
+.TP
+.BI discard
+Attempt to discard blocks at mkfs time (discarding blocks initially is useful
+on solid state devices and sparse / thin-provisioned storage). When the device
+advertises that discard also zeroes data (any subsequent read after the discard
+and before write returns zero), then mark all not-yet-zeroed inode tables as
+zeroed. This significantly speeds up filesystem initialization. This is set
+as default.
+.TP
+.BI nodiscard
+Do not attempt to discard blocks at mkfs time.
+@QUOTA_MAN_COMMENT@.TP
+@QUOTA_MAN_COMMENT@.BI quotatype
+@QUOTA_MAN_COMMENT@Specify which quota type ('usr' or 'grp') is to be
+@QUOTA_MAN_COMMENT@initialized. This option has effect only if the
+@QUOTA_MAN_COMMENT@.B quota
+@QUOTA_MAN_COMMENT@feature is set. Without this extended option, the default
+@QUOTA_MAN_COMMENT@behavior is to initialize both user and group quotas.
+.RE
+.TP
+.BI \-f " fragment-size"
+Specify the size of fragments in bytes.
+.TP
+.B \-F
+Force
+.B mke2fs
+to create a filesystem, even if the specified device is not a partition
+on a block special device, or if other parameters do not make sense.
+In order to force
+.B mke2fs
+to create a filesystem even if the filesystem appears to be in use
+or is mounted (a truly dangerous thing to do), this option must be
+specified twice.
+.TP
+.BI \-g " blocks-per-group"
+Specify the number of blocks in a block group.  There is generally no
+reason for the user to ever set this parameter, as the default is optimal
+for the filesystem.  (For administrators who are creating
+filesystems on RAID arrays, it is preferable to use the
+.I stride
+RAID parameter as part of the
+.B \-E
+option rather than manipulating the number of blocks per group.)
+This option is generally used by developers who
+are developing test cases.
+.IP
+If the bigalloc feature is enabled, the
+.B \-g
+option will specify the number of clusters in a block group.
+.TP
+.BI \-G " number-of-groups"
+Specify the number of block groups that will be packed together to
+create a larger virtual block group (or "flex_bg group") in an
+ext4 filesystem.  This improves meta-data locality and performance
+on meta-data heavy workloads.  The number of groups must be a power
+of 2 and may only be specified if the 
+.B flex_bg
+filesystem feature is enabled.
+.TP
+.BI \-i " bytes-per-inode"
+Specify the bytes/inode ratio.
+.B mke2fs
+creates an inode for every
+.I bytes-per-inode
+bytes of space on the disk.  The larger the
+.I bytes-per-inode
+ratio, the fewer inodes will be created.  This value generally shouldn't
+be smaller than the blocksize of the filesystem, since in that case more
+inodes would be made than can ever be used.  Be warned that it is not
+possible to change this ratio on a filesystem after it is created, so be
+careful deciding the correct value for this parameter.  Note that resizing
+a filesystem changes the numer of inodes to maintain this ratio.
+.TP
+.BI \-I " inode-size"
+Specify the size of each inode in bytes.
+The
+.I inode-size
+value must be a power of 2 larger or equal to 128.  The larger the
+.I inode-size
+the more space the inode table will consume, and this reduces the usable
+space in the filesystem and can also negatively impact performance.
+It is not
+possible to change this value after the filesystem is created.
+.IP
+In kernels after 2.6.10 and some
+earlier vendor kernels it is possible to utilize inodes larger than
+128 bytes to store
+extended attributes for improved performance.
+Extended attributes
+stored in large inodes are not visible with older kernels, and such
+filesystems will not be mountable with 2.4 kernels at all.  
+.IP
+The default inode size is controlled by the
+.BR mke2fs.conf (5)
+file.  In the
+.B mke2fs.conf
+file shipped with e2fsprogs, the default inode size is 256 bytes for
+most file systems, except for small file systems where the inode size
+will be 128 bytes.
+.TP
+.B \-j
+Create the filesystem with an ext3 journal.  If the
+.B \-J
+option is not specified, the default journal parameters will be used to
+create an appropriately sized journal (given the size of the filesystem)
+stored within the filesystem.  Note that you must be using a kernel
+which has ext3 support in order to actually make use of the journal.
+.TP
+.BI \-J " journal-options"
+Create the ext3 journal using options specified on the command-line.
+Journal options are comma
+separated, and may take an argument using the equals ('=')  sign.
+The following journal options are supported:
+.RS 1.2i
+.TP
+.BI size= journal-size
+Create an internal journal (i.e., stored inside the filesystem) of size
+.I journal-size
+megabytes.
+The size of the journal must be at least 1024 filesystem blocks
+(i.e., 1MB if using 1k blocks, 4MB if using 4k blocks, etc.)
+and may be no more than 10,240,000 filesystem blocks or half the total
+file system size (whichever is smaller)
+@JDEV@.TP
+@JDEV@.BI device= external-journal
+@JDEV@Attach the filesystem to the journal block device located on
+@JDEV@.IR external-journal .
+@JDEV@The external
+@JDEV@journal must already have been created using the command
+@JDEV@.IP
+@JDEV@.B mke2fs -O journal_dev
+@JDEV@.I external-journal
+@JDEV@.IP
+@JDEV@Note that
+@JDEV@.I external-journal
+@JDEV@must have been created with the
+@JDEV@same block size as the new filesystem.
+@JDEV@In addition, while there is support for attaching
+@JDEV@multiple filesystems to a single external journal,
+@JDEV@the Linux kernel and
+@JDEV@.BR e2fsck (8)
+@JDEV@do not currently support shared external journals yet.
+@JDEV@.IP
+@JDEV@Instead of specifying a device name directly,
+@JDEV@.I external-journal
+@JDEV@can also be specified by either
+@JDEV@.BI LABEL= label
+@JDEV@or
+@JDEV@.BI UUID= UUID
+@JDEV@to locate the external journal by either the volume label or UUID
+@JDEV@stored in the ext2 superblock at the start of the journal.  Use
+@JDEV@.BR dumpe2fs (8)
+@JDEV@to display a journal device's volume label and UUID.  See also the
+@JDEV@.B -L
+@JDEV@option of
+@JDEV@.BR tune2fs (8).
+.RE
+@JDEV@.IP
+@JDEV@Only one of the
+@JDEV@.BR size " or " device
+@JDEV@options can be given for a filesystem.
+.TP
+.BI \-l " filename"
+Read the bad blocks list from
+.IR filename .
+Note that the block numbers in the bad block list must be generated
+using the same block size as used by
+.BR mke2fs .
+As a result, the
+.B \-c
+option to
+.B mke2fs
+is a much simpler and less error-prone method of checking a disk for bad
+blocks before formatting it, as
+.B mke2fs
+will automatically pass the correct parameters to the
+.B badblocks
+program.
+.TP
+.BI \-L " new-volume-label"
+Set the volume label for the filesystem to
+.IR new-volume-label .
+The maximum length of the
+volume label is 16 bytes.
+.TP
+.BI \-m " reserved-blocks-percentage"
+Specify the percentage of the filesystem blocks reserved for
+the super-user.  This avoids fragmentation, and allows root-owned
+daemons, such as
+.BR syslogd (8),
+to continue to function correctly after non-privileged processes are
+prevented from writing to the filesystem.  The default percentage
+is 5%.
+.TP
+.BI \-M " last-mounted-directory"
+Set the last mounted directory for the filesystem.  This might be useful
+for the sake of utilities that key off of the last mounted directory to
+determine where the filesystem should be mounted.
+.TP
+.B \-n
+Causes
+.B mke2fs
+to not actually create a filesystem, but display what it
+would do if it were to create a filesystem.  This can be used to
+determine the location of the backup superblocks for a particular
+filesystem, so long as the
+.B mke2fs
+parameters that were passed when the
+filesystem was originally created are used again.  (With the
+.B \-n
+option added, of course!)
+.TP
+.BI \-N " number-of-inodes"
+Overrides the default calculation of the number of inodes that should be
+reserved for the filesystem (which is based on the number of blocks and
+the
+.I bytes-per-inode
+ratio).  This allows the user to specify the number
+of desired inodes directly.
+.TP
+.BI \-o " creator-os"
+Overrides the default value of the "creator operating system" field of the
+filesystem.  The creator field is set by default to the name of the OS the
+.B mke2fs
+executable was compiled for.
+.TP
+.B "\-O \fIfeature\fR[,...]"
+Create a filesystem with the given features (filesystem options),
+overriding the default filesystem options.  The features that are
+enabled by default are specified by the
+.I base_features
+relation, either in the
+.I [defaults]
+section in the
+.B /etc/mke2fs.conf
+configuration file,
+or in the
+.I [fs_types]
+subsections for the usage types as specified by the
+.B \-T
+option, further modified by the
+.I features
+relation found in the
+.I [fs_types]
+subsections for the filesystem and usage types.  See the
+.BR mke2fs.conf (5)
+manual page for more details.
+The filesystem type-specific configuration setting found in the
+.I [fs_types]
+section will override the global default found in
+.IR [defaults] .
+.sp
+The filesystem feature set will be further edited
+using either the feature set specified by this option,
+or if this option is not given, by the
+.I default_features
+relation for the filesystem type being created, or in the
+.I [defaults]
+section of the configuration file.
+.sp
+The filesystem feature set is comprised of a list of features, separated
+by commas, that are to be enabled.  To disable a feature, simply
+prefix the feature name with a  caret ('^') or a minus ('-') character.
+Features with dependencies will not be removed successfully.
+The pseudo-filesystem feature "none" will clear all filesystem features.
+.TP
+For more information about the features which can be set, please see
+the manual page
+.BR ext4 (5).
+.TP
+.B \-q
+Quiet execution.  Useful if
+.B mke2fs
+is run in a script.
+.TP
+.BI \-r " revision"
+Set the filesystem revision for the new filesystem.  Note that 1.2
+kernels only support revision 0 filesystems.  The default is to
+create revision 1 filesystems.
+.TP
+.B \-S
+Write superblock and group descriptors only.  This is useful if all of
+the superblock and backup superblocks are corrupted, and a last-ditch
+recovery method is desired.  It causes
+.B mke2fs
+to reinitialize the
+superblock and group descriptors, while not touching the inode table
+and the block and inode bitmaps.  The
+.B e2fsck
+program should be run immediately after this option is used, and there
+is no guarantee that any data will be salvageable.  It is critical to
+specify the correct filesystem blocksize when using this option,
+or there is no chance of recovery.
+.\" .TP
+.\" .BI \-t " test"
+.\" Check the device for bad blocks before creating the file system
+.\" using the specified test.
+.TP
+.BI \-t " fs-type"
+Specify the filesystem type (i.e., ext2, ext3, ext4, etc.) that is
+to be created.
+If this option is not specified,
+.B mke2fs
+will pick a default either via how
+the command was run (for example, using a name of the form mkfs.ext2,
+mkfs.ext3, etc.) or via a default as defined by the
+.B /etc/mke2fs.conf
+file.   This option controls which filesystem options are used by
+default, based on the
+.B fstypes
+configuration stanza in
+.BR /etc/mke2fs.conf .
+.sp
+If the
+.B \-O
+option is used to explicitly add or remove filesystem options that
+should be set in the newly created filesystem, the
+resulting filesystem may not be supported by the requested
+.IR fs-type .
+(e.g., "\fBmke2fs \-t ext3 \-O extent /dev/sdXX\fR" will create a
+filesystem that is not supported by the ext3 implementation as found in
+the Linux kernel; and "\fBmke2fs \-t ext3 \-O ^has_journal /dev/hdXX\fR"
+will create a filesystem that does not have a journal and hence will not
+be supported by the ext3 filesystem code in the Linux kernel.)
+.TP
+.BI \-T " usage-type[,...]"
+Specify how the filesystem is going to be used, so that
+.B mke2fs
+can choose optimal filesystem parameters for that use.  The usage
+types that are supported are defined in the configuration file
+.BR /etc/mke2fs.conf .
+The user may specify one or more usage types
+using a comma separated list.
+.sp
+If this option is is not specified,
+.B mke2fs
+will pick a single default usage type based on the size of the filesystem to
+be created.  If the filesystem size is less than or equal to 3 megabytes,
+.B mke2fs
+will use the filesystem type
+.IR floppy .
+If the filesystem size is greater than 3 but less than or equal to
+512 megabytes,
+.BR mke2fs (8)
+will use the filesystem type
+.IR small .
+If the filesystem size is greater than or equal to 4 terabytes but less than
+16 terabytes,
+.BR mke2fs (8)
+will use the filesystem type
+.IR big .
+If the filesystem size is greater than or equal to 16 terabytes,
+.BR mke2fs (8)
+will use the filesystem type
+.IR huge .
+Otherwise,
+.BR mke2fs (8)
+will use the default filesystem type
+.IR default .
+.TP
+.BI \-U " UUID"
+Create the filesystem with the specified UUID.
+.TP
+.B \-v
+Verbose execution.
+.TP
+.B \-V
+Print the version number of
+.B mke2fs
+and exit.
+.SH ENVIRONMENT
+.TP
+.BI MKE2FS_SYNC
+If set to non-zero integer value, its value is used to determine how often
+.BR sync (2)
+is called during inode table initialization.
+.TP
+.BI MKE2FS_CONFIG
+Determines the location of the configuration file (see
+.BR mke2fs.conf (5)).
+.TP
+.BI MKE2FS_FIRST_META_BG
+If set to non-zero integer value, its value is used to determine first meta
+block group. This is mostly for debugging purposes.
+.TP
+.BI MKE2FS_DEVICE_SECTSIZE
+If set to non-zero integer value, its value is used to determine physical
+sector size of the
+.IR device .
+.TP
+.BI MKE2FS_SKIP_CHECK_MSG
+If set, do not show the message of filesystem automatic check caused by
+mount count or check interval.
+.SH AUTHOR
+This version of
+.B mke2fs
+has been written by Theodore Ts'o <tytso@mit.edu>.
+.SH BUGS
+.B mke2fs
+accepts the
+.B \-f
+option but currently ignores it because the second
+extended file system does not support fragments yet.
+.br
+There may be other ones.  Please, report them to the author.
+.SH AVAILABILITY
+.B mke2fs
+is part of the e2fsprogs package and is available from
+http://e2fsprogs.sourceforge.net.
+.SH SEE ALSO
+.BR mke2fs.conf (5),
+.BR badblocks (8),
+.BR dumpe2fs (8),
+.BR e2fsck (8),
+.BR tune2fs (8),
+.BR ext4 (5)
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/mke2fs.c b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/mke2fs.c
new file mode 100644
index 0000000..2e8ba60
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/mke2fs.c
@@ -0,0 +1,2751 @@
+/*
+ * mke2fs.c - Make a ext2fs filesystem.
+ *
+ * Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+ * 	2003, 2004, 2005 by Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+/* Usage: mke2fs [options] device
+ *
+ * The device may be a block device or a image of one, but this isn't
+ * enforced (but it's not much fun on a character device :-).
+ */
+
+#define _XOPEN_SOURCE 600 /* for inclusion of PATH_MAX in Solaris */
+
+#include "config.h"
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <time.h>
+#ifdef __linux__
+#include <sys/utsname.h>
+#endif
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#else
+extern char *optarg;
+extern int optind;
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <libgen.h>
+#include <limits.h>
+#include <blkid/blkid.h>
+
+#include "ext2fs/ext2_fs.h"
+#include "ext2fs/ext2fsP.h"
+#include "et/com_err.h"
+#include "uuid/uuid.h"
+#include "e2p/e2p.h"
+#include "ext2fs/ext2fs.h"
+#include "util.h"
+#include "profile.h"
+#include "prof_err.h"
+#include "../version.h"
+#include "nls-enable.h"
+#include "quota/mkquota.h"
+
+#define STRIDE_LENGTH 8
+
+#define MAX_32_NUM ((((unsigned long long) 1) << 32) - 1)
+
+#ifndef __sparc__
+#define ZAP_BOOTBLOCK
+#endif
+
+#define DISCARD_STEP_MB		(2048)
+
+extern int isatty(int);
+extern FILE *fpopen(const char *cmd, const char *mode);
+
+static const char * program_name = "mke2fs";
+static const char * device_name /* = NULL */;
+
+/* Command line options */
+static int	cflag;
+static int	verbose;
+static int	quiet;
+static int	super_only;
+static int	discard = 1;	/* attempt to discard device before fs creation */
+static int	direct_io;
+static int	force;
+static int	noaction;
+static uid_t	root_uid;
+static gid_t	root_gid;
+int	journal_size;
+int	journal_flags;
+static int	lazy_itable_init;
+static char	*bad_blocks_filename = NULL;
+static __u32	fs_stride;
+static int	quotatype = -1;  /* Initialize both user and group quotas by default */
+
+static struct ext2_super_block fs_param;
+static char *fs_uuid = NULL;
+static char *creator_os;
+static char *volume_label;
+static char *mount_dir;
+char *journal_device;
+static int sync_kludge;	/* Set using the MKE2FS_SYNC env. option */
+static char **fs_types;
+
+static profile_t	profile;
+
+static int sys_page_size = 4096;
+static int linux_version_code = 0;
+
+static void usage(void)
+{
+	fprintf(stderr, _("Usage: %s [-c|-l filename] [-b block-size] "
+	"[-C cluster-size]\n\t[-i bytes-per-inode] [-I inode-size] "
+	"[-J journal-options]\n"
+	"\t[-G flex-group-size] [-N number-of-inodes]\n"
+	"\t[-m reserved-blocks-percentage] [-o creator-os]\n"
+	"\t[-g blocks-per-group] [-L volume-label] "
+	"[-M last-mounted-directory]\n\t[-O feature[,...]] "
+	"[-r fs-revision] [-E extended-option[,...]]\n"
+	"\t[-t fs-type] [-T usage-type ] [-U UUID] "
+	"[-jnqvDFKSV] device [blocks-count]\n"),
+		program_name);
+	exit(1);
+}
+
+static int int_log2(unsigned long long arg)
+{
+	int	l = 0;
+
+	arg >>= 1;
+	while (arg) {
+		l++;
+		arg >>= 1;
+	}
+	return l;
+}
+
+static int int_log10(unsigned long long arg)
+{
+	int	l;
+
+	for (l=0; arg ; l++)
+		arg = arg / 10;
+	return l;
+}
+
+#ifdef __linux__
+static int parse_version_number(const char *s)
+{
+	int	major, minor, rev;
+	char	*endptr;
+	const char *cp = s;
+
+	if (!s)
+		return 0;
+	major = strtol(cp, &endptr, 10);
+	if (cp == endptr || *endptr != '.')
+		return 0;
+	cp = endptr + 1;
+	minor = strtol(cp, &endptr, 10);
+	if (cp == endptr || *endptr != '.')
+		return 0;
+	cp = endptr + 1;
+	rev = strtol(cp, &endptr, 10);
+	if (cp == endptr)
+		return 0;
+	return ((((major * 256) + minor) * 256) + rev);
+}
+#endif
+
+/*
+ * Helper function for read_bb_file and test_disk
+ */
+static void invalid_block(ext2_filsys fs EXT2FS_ATTR((unused)), blk_t blk)
+{
+	fprintf(stderr, _("Bad block %u out of range; ignored.\n"), blk);
+	return;
+}
+
+/*
+ * Reads the bad blocks list from a file
+ */
+static void read_bb_file(ext2_filsys fs, badblocks_list *bb_list,
+			 const char *bad_blocks_file)
+{
+	FILE		*f;
+	errcode_t	retval;
+
+	f = fopen(bad_blocks_file, "r");
+	if (!f) {
+		com_err("read_bad_blocks_file", errno,
+			_("while trying to open %s"), bad_blocks_file);
+		exit(1);
+	}
+	retval = ext2fs_read_bb_FILE(fs, f, bb_list, invalid_block);
+	fclose (f);
+	if (retval) {
+		com_err("ext2fs_read_bb_FILE", retval, "%s",
+			_("while reading in list of bad blocks from file"));
+		exit(1);
+	}
+}
+
+/*
+ * Runs the badblocks program to test the disk
+ */
+static void test_disk(ext2_filsys fs, badblocks_list *bb_list)
+{
+	FILE		*f;
+	errcode_t	retval;
+	char		buf[1024];
+
+	sprintf(buf, "badblocks -b %d -X %s%s%s %llu", fs->blocksize,
+		quiet ? "" : "-s ", (cflag > 1) ? "-w " : "",
+		fs->device_name, ext2fs_blocks_count(fs->super)-1);
+	if (verbose)
+		printf(_("Running command: %s\n"), buf);
+	f = popen(buf, "r");
+	if (!f) {
+		com_err("popen", errno,
+			_("while trying to run '%s'"), buf);
+		exit(1);
+	}
+	retval = ext2fs_read_bb_FILE(fs, f, bb_list, invalid_block);
+	pclose(f);
+	if (retval) {
+		com_err("ext2fs_read_bb_FILE", retval, "%s",
+			_("while processing list of bad blocks from program"));
+		exit(1);
+	}
+}
+
+static void handle_bad_blocks(ext2_filsys fs, badblocks_list bb_list)
+{
+	dgrp_t			i;
+	blk_t			j;
+	unsigned 		must_be_good;
+	blk_t			blk;
+	badblocks_iterate	bb_iter;
+	errcode_t		retval;
+	blk_t			group_block;
+	int			group;
+	int			group_bad;
+
+	if (!bb_list)
+		return;
+
+	/*
+	 * The primary superblock and group descriptors *must* be
+	 * good; if not, abort.
+	 */
+	must_be_good = fs->super->s_first_data_block + 1 + fs->desc_blocks;
+	for (i = fs->super->s_first_data_block; i <= must_be_good; i++) {
+		if (ext2fs_badblocks_list_test(bb_list, i)) {
+			fprintf(stderr, _("Block %d in primary "
+				"superblock/group descriptor area bad.\n"), i);
+			fprintf(stderr, _("Blocks %u through %u must be good "
+				"in order to build a filesystem.\n"),
+				fs->super->s_first_data_block, must_be_good);
+			fputs(_("Aborting....\n"), stderr);
+			exit(1);
+		}
+	}
+
+	/*
+	 * See if any of the bad blocks are showing up in the backup
+	 * superblocks and/or group descriptors.  If so, issue a
+	 * warning and adjust the block counts appropriately.
+	 */
+	group_block = fs->super->s_first_data_block +
+		fs->super->s_blocks_per_group;
+
+	for (i = 1; i < fs->group_desc_count; i++) {
+		group_bad = 0;
+		for (j=0; j < fs->desc_blocks+1; j++) {
+			if (ext2fs_badblocks_list_test(bb_list,
+						       group_block + j)) {
+				if (!group_bad)
+					fprintf(stderr,
+_("Warning: the backup superblock/group descriptors at block %u contain\n"
+"	bad blocks.\n\n"),
+						group_block);
+				group_bad++;
+				group = ext2fs_group_of_blk2(fs, group_block+j);
+				ext2fs_bg_free_blocks_count_set(fs, group, ext2fs_bg_free_blocks_count(fs, group) + 1);
+				ext2fs_group_desc_csum_set(fs, group);
+				ext2fs_free_blocks_count_add(fs->super, 1);
+			}
+		}
+		group_block += fs->super->s_blocks_per_group;
+	}
+
+	/*
+	 * Mark all the bad blocks as used...
+	 */
+	retval = ext2fs_badblocks_list_iterate_begin(bb_list, &bb_iter);
+	if (retval) {
+		com_err("ext2fs_badblocks_list_iterate_begin", retval, "%s",
+			_("while marking bad blocks as used"));
+		exit(1);
+	}
+	while (ext2fs_badblocks_list_iterate(bb_iter, &blk))
+		ext2fs_mark_block_bitmap2(fs->block_map, EXT2FS_B2C(fs, blk));
+	ext2fs_badblocks_list_iterate_end(bb_iter);
+}
+
+static void write_inode_tables(ext2_filsys fs, int lazy_flag, int itable_zeroed)
+{
+	errcode_t	retval;
+	blk64_t		blk;
+	dgrp_t		i;
+	int		num;
+	struct ext2fs_numeric_progress_struct progress;
+
+	ext2fs_numeric_progress_init(fs, &progress,
+				     _("Writing inode tables: "),
+				     fs->group_desc_count);
+
+	for (i = 0; i < fs->group_desc_count; i++) {
+		ext2fs_numeric_progress_update(fs, &progress, i);
+
+		blk = ext2fs_inode_table_loc(fs, i);
+		num = fs->inode_blocks_per_group;
+
+		if (lazy_flag)
+			num = ext2fs_div_ceil((fs->super->s_inodes_per_group -
+					       ext2fs_bg_itable_unused(fs, i)) *
+					      EXT2_INODE_SIZE(fs->super),
+					      EXT2_BLOCK_SIZE(fs->super));
+		if (!lazy_flag || itable_zeroed) {
+			/* The kernel doesn't need to zero the itable blocks */
+			ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_ZEROED);
+			ext2fs_group_desc_csum_set(fs, i);
+		}
+		retval = ext2fs_zero_blocks2(fs, blk, num, &blk, &num);
+		if (retval) {
+			fprintf(stderr, _("\nCould not write %d "
+				  "blocks in inode table starting at %llu: %s\n"),
+				num, blk, error_message(retval));
+			exit(1);
+		}
+		if (sync_kludge) {
+			if (sync_kludge == 1)
+				sync();
+			else if ((i % sync_kludge) == 0)
+				sync();
+		}
+	}
+	ext2fs_zero_blocks2(0, 0, 0, 0, 0);
+	ext2fs_numeric_progress_close(fs, &progress,
+				      _("done                            \n"));
+}
+
+static void create_root_dir(ext2_filsys fs)
+{
+	errcode_t		retval;
+	struct ext2_inode	inode;
+
+	retval = ext2fs_mkdir(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, 0);
+	if (retval) {
+		com_err("ext2fs_mkdir", retval, "%s",
+			_("while creating root dir"));
+		exit(1);
+	}
+	if (root_uid != 0 || root_gid != 0) {
+		retval = ext2fs_read_inode(fs, EXT2_ROOT_INO, &inode);
+		if (retval) {
+			com_err("ext2fs_read_inode", retval, "%s",
+				_("while reading root inode"));
+			exit(1);
+		}
+
+		inode.i_uid = root_uid;
+		ext2fs_set_i_uid_high(inode, root_uid >> 16);
+		inode.i_gid = root_gid;
+		ext2fs_set_i_gid_high(inode, root_gid >> 16);
+
+		retval = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
+		if (retval) {
+			com_err("ext2fs_write_inode", retval, "%s",
+				_("while setting root inode ownership"));
+			exit(1);
+		}
+	}
+}
+
+static void create_lost_and_found(ext2_filsys fs)
+{
+	unsigned int		lpf_size = 0;
+	errcode_t		retval;
+	ext2_ino_t		ino;
+	const char		*name = "lost+found";
+	int			i;
+
+	fs->umask = 077;
+	retval = ext2fs_mkdir(fs, EXT2_ROOT_INO, 0, name);
+	if (retval) {
+		com_err("ext2fs_mkdir", retval, "%s",
+			_("while creating /lost+found"));
+		exit(1);
+	}
+
+	retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name, strlen(name), 0, &ino);
+	if (retval) {
+		com_err("ext2_lookup", retval, "%s",
+			_("while looking up /lost+found"));
+		exit(1);
+	}
+
+	for (i=1; i < EXT2_NDIR_BLOCKS; i++) {
+		/* Ensure that lost+found is at least 2 blocks, so we always
+		 * test large empty blocks for big-block filesystems.  */
+		if ((lpf_size += fs->blocksize) >= 16*1024 &&
+		    lpf_size >= 2 * fs->blocksize)
+			break;
+		retval = ext2fs_expand_dir(fs, ino);
+		if (retval) {
+			com_err("ext2fs_expand_dir", retval, "%s",
+				_("while expanding /lost+found"));
+			exit(1);
+		}
+	}
+}
+
+static void create_bad_block_inode(ext2_filsys fs, badblocks_list bb_list)
+{
+	errcode_t	retval;
+
+	ext2fs_mark_inode_bitmap2(fs->inode_map, EXT2_BAD_INO);
+	ext2fs_inode_alloc_stats2(fs, EXT2_BAD_INO, +1, 0);
+	retval = ext2fs_update_bb_inode(fs, bb_list);
+	if (retval) {
+		com_err("ext2fs_update_bb_inode", retval, "%s",
+			_("while setting bad block inode"));
+		exit(1);
+	}
+
+}
+
+static void reserve_inodes(ext2_filsys fs)
+{
+	ext2_ino_t	i;
+
+	for (i = EXT2_ROOT_INO + 1; i < EXT2_FIRST_INODE(fs->super); i++)
+		ext2fs_inode_alloc_stats2(fs, i, +1, 0);
+	ext2fs_mark_ib_dirty(fs);
+}
+
+#define BSD_DISKMAGIC   (0x82564557UL)  /* The disk magic number */
+#define BSD_MAGICDISK   (0x57455682UL)  /* The disk magic number reversed */
+#define BSD_LABEL_OFFSET        64
+
+static void zap_sector(ext2_filsys fs, int sect, int nsect)
+{
+	char *buf;
+	int retval;
+	unsigned int *magic;
+
+	buf = malloc(512*nsect);
+	if (!buf) {
+		printf(_("Out of memory erasing sectors %d-%d\n"),
+		       sect, sect + nsect - 1);
+		exit(1);
+	}
+
+	if (sect == 0) {
+		/* Check for a BSD disklabel, and don't erase it if so */
+		retval = io_channel_read_blk64(fs->io, 0, -512, buf);
+		if (retval)
+			fprintf(stderr,
+				_("Warning: could not read block 0: %s\n"),
+				error_message(retval));
+		else {
+			magic = (unsigned int *) (buf + BSD_LABEL_OFFSET);
+			if ((*magic == BSD_DISKMAGIC) ||
+			    (*magic == BSD_MAGICDISK))
+				return;
+		}
+	}
+
+	memset(buf, 0, 512*nsect);
+	io_channel_set_blksize(fs->io, 512);
+	retval = io_channel_write_blk64(fs->io, sect, -512*nsect, buf);
+	io_channel_set_blksize(fs->io, fs->blocksize);
+	free(buf);
+	if (retval)
+		fprintf(stderr, _("Warning: could not erase sector %d: %s\n"),
+			sect, error_message(retval));
+}
+
+static void create_journal_dev(ext2_filsys fs)
+{
+	struct ext2fs_numeric_progress_struct progress;
+	errcode_t		retval;
+	char			*buf;
+	blk64_t			blk, err_blk;
+	int			c, count, err_count;
+
+	retval = ext2fs_create_journal_superblock(fs,
+				  ext2fs_blocks_count(fs->super), 0, &buf);
+	if (retval) {
+		com_err("create_journal_dev", retval, "%s",
+			_("while initializing journal superblock"));
+		exit(1);
+	}
+
+	if (journal_flags & EXT2_MKJOURNAL_LAZYINIT)
+		goto write_superblock;
+
+	ext2fs_numeric_progress_init(fs, &progress,
+				     _("Zeroing journal device: "),
+				     ext2fs_blocks_count(fs->super));
+	blk = 0;
+	count = ext2fs_blocks_count(fs->super);
+	while (count > 0) {
+		if (count > 1024)
+			c = 1024;
+		else
+			c = count;
+		retval = ext2fs_zero_blocks2(fs, blk, c, &err_blk, &err_count);
+		if (retval) {
+			com_err("create_journal_dev", retval,
+				_("while zeroing journal device "
+				  "(block %llu, count %d)"),
+				err_blk, err_count);
+			exit(1);
+		}
+		blk += c;
+		count -= c;
+		ext2fs_numeric_progress_update(fs, &progress, blk);
+	}
+	ext2fs_zero_blocks2(0, 0, 0, 0, 0);
+
+	ext2fs_numeric_progress_close(fs, &progress, NULL);
+write_superblock:
+	retval = io_channel_write_blk64(fs->io,
+					fs->super->s_first_data_block+1,
+					1, buf);
+	if (retval) {
+		com_err("create_journal_dev", retval, "%s",
+			_("while writing journal superblock"));
+		exit(1);
+	}
+}
+
+static void show_stats(ext2_filsys fs)
+{
+	struct ext2_super_block *s = fs->super;
+	char 			buf[80];
+        char                    *os;
+	blk64_t			group_block;
+	dgrp_t			i;
+	int			need, col_left;
+
+	if (ext2fs_blocks_count(&fs_param) != ext2fs_blocks_count(s))
+		fprintf(stderr, _("warning: %llu blocks unused.\n\n"),
+		       ext2fs_blocks_count(&fs_param) - ext2fs_blocks_count(s));
+
+	memset(buf, 0, sizeof(buf));
+	strncpy(buf, s->s_volume_name, sizeof(s->s_volume_name));
+	printf(_("Filesystem label=%s\n"), buf);
+	os = e2p_os2string(fs->super->s_creator_os);
+	if (os)
+		printf(_("OS type: %s\n"), os);
+	free(os);
+	printf(_("Block size=%u (log=%u)\n"), fs->blocksize,
+		s->s_log_block_size);
+	if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
+				       EXT4_FEATURE_RO_COMPAT_BIGALLOC))
+		printf(_("Cluster size=%u (log=%u)\n"),
+		       fs->blocksize << fs->cluster_ratio_bits,
+		       s->s_log_cluster_size);
+	else
+		printf(_("Fragment size=%u (log=%u)\n"), EXT2_CLUSTER_SIZE(s),
+		       s->s_log_cluster_size);
+	printf(_("Stride=%u blocks, Stripe width=%u blocks\n"),
+	       s->s_raid_stride, s->s_raid_stripe_width);
+	printf(_("%u inodes, %llu blocks\n"), s->s_inodes_count,
+	       ext2fs_blocks_count(s));
+	printf(_("%llu blocks (%2.2f%%) reserved for the super user\n"),
+		ext2fs_r_blocks_count(s),
+	       100.0 *  ext2fs_r_blocks_count(s) / ext2fs_blocks_count(s));
+	printf(_("First data block=%u\n"), s->s_first_data_block);
+	if (root_uid != 0 || root_gid != 0)
+		printf(_("Root directory owner=%u:%u\n"), root_uid, root_gid);
+	if (s->s_reserved_gdt_blocks)
+		printf(_("Maximum filesystem blocks=%lu\n"),
+		       (s->s_reserved_gdt_blocks + fs->desc_blocks) *
+		       EXT2_DESC_PER_BLOCK(s) * s->s_blocks_per_group);
+	if (fs->group_desc_count > 1)
+		printf(_("%u block groups\n"), fs->group_desc_count);
+	else
+		printf(_("%u block group\n"), fs->group_desc_count);
+	if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
+				       EXT4_FEATURE_RO_COMPAT_BIGALLOC))
+		printf(_("%u blocks per group, %u clusters per group\n"),
+		       s->s_blocks_per_group, s->s_clusters_per_group);
+	else
+		printf(_("%u blocks per group, %u fragments per group\n"),
+		       s->s_blocks_per_group, s->s_clusters_per_group);
+	printf(_("%u inodes per group\n"), s->s_inodes_per_group);
+
+	if (fs->group_desc_count == 1) {
+		printf("\n");
+		return;
+	}
+
+	printf("%s", _("Superblock backups stored on blocks: "));
+	group_block = s->s_first_data_block;
+	col_left = 0;
+	for (i = 1; i < fs->group_desc_count; i++) {
+		group_block += s->s_blocks_per_group;
+		if (!ext2fs_bg_has_super(fs, i))
+			continue;
+		if (i != 1)
+			printf(", ");
+		need = int_log10(group_block) + 2;
+		if (need > col_left) {
+			printf("\n\t");
+			col_left = 72;
+		}
+		col_left -= need;
+		printf("%llu", group_block);
+	}
+	printf("\n\n");
+}
+
+/*
+ * Set the S_CREATOR_OS field.  Return true if OS is known,
+ * otherwise, 0.
+ */
+static int set_os(struct ext2_super_block *sb, char *os)
+{
+	if (isdigit (*os))
+		sb->s_creator_os = atoi (os);
+	else if (strcasecmp(os, "linux") == 0)
+		sb->s_creator_os = EXT2_OS_LINUX;
+	else if (strcasecmp(os, "GNU") == 0 || strcasecmp(os, "hurd") == 0)
+		sb->s_creator_os = EXT2_OS_HURD;
+	else if (strcasecmp(os, "freebsd") == 0)
+		sb->s_creator_os = EXT2_OS_FREEBSD;
+	else if (strcasecmp(os, "lites") == 0)
+		sb->s_creator_os = EXT2_OS_LITES;
+	else
+		return 0;
+	return 1;
+}
+
+#define PATH_SET "PATH=/sbin"
+
+static void parse_extended_opts(struct ext2_super_block *param,
+				const char *opts)
+{
+	char	*buf, *token, *next, *p, *arg, *badopt = 0;
+	int	len;
+	int	r_usage = 0;
+
+	len = strlen(opts);
+	buf = malloc(len+1);
+	if (!buf) {
+		fprintf(stderr, "%s",
+			_("Couldn't allocate memory to parse options!\n"));
+		exit(1);
+	}
+	strcpy(buf, opts);
+	for (token = buf; token && *token; token = next) {
+		p = strchr(token, ',');
+		next = 0;
+		if (p) {
+			*p = 0;
+			next = p+1;
+		}
+		arg = strchr(token, '=');
+		if (arg) {
+			*arg = 0;
+			arg++;
+		}
+		if (strcmp(token, "desc-size") == 0 ||
+		    strcmp(token, "desc_size") == 0) {
+			int desc_size;
+
+			if (!(fs_param.s_feature_incompat &
+			      EXT4_FEATURE_INCOMPAT_64BIT)) {
+				fprintf(stderr,
+					_("%s requires '-O 64bit'\n"), token);
+				r_usage++;
+				continue;
+			}
+			if (param->s_reserved_gdt_blocks != 0) {
+				fprintf(stderr,
+					_("'%s' must be before 'resize=%u'\n"),
+					token, param->s_reserved_gdt_blocks);
+				r_usage++;
+				continue;
+			}
+			if (!arg) {
+				r_usage++;
+				badopt = token;
+				continue;
+			}
+			desc_size = strtoul(arg, &p, 0);
+			if (*p || (desc_size & (desc_size - 1))) {
+				fprintf(stderr,
+					_("Invalid desc_size: '%s'\n"), arg);
+				r_usage++;
+				continue;
+			}
+			param->s_desc_size = desc_size;
+		} else if (strcmp(token, "mmp_update_interval") == 0) {
+			if (!arg) {
+				r_usage++;
+				badopt = token;
+				continue;
+			}
+			param->s_mmp_update_interval = strtoul(arg, &p, 0);
+			if (*p) {
+				fprintf(stderr,
+					_("Invalid mmp_update_interval: %s\n"),
+					arg);
+				r_usage++;
+				continue;
+			}
+		} else if (strcmp(token, "stride") == 0) {
+			if (!arg) {
+				r_usage++;
+				badopt = token;
+				continue;
+			}
+			param->s_raid_stride = strtoul(arg, &p, 0);
+			if (*p) {
+				fprintf(stderr,
+					_("Invalid stride parameter: %s\n"),
+					arg);
+				r_usage++;
+				continue;
+			}
+		} else if (strcmp(token, "stripe-width") == 0 ||
+			   strcmp(token, "stripe_width") == 0) {
+			if (!arg) {
+				r_usage++;
+				badopt = token;
+				continue;
+			}
+			param->s_raid_stripe_width = strtoul(arg, &p, 0);
+			if (*p) {
+				fprintf(stderr,
+					_("Invalid stripe-width parameter: %s\n"),
+					arg);
+				r_usage++;
+				continue;
+			}
+		} else if (!strcmp(token, "resize")) {
+			blk64_t resize;
+			unsigned long bpg, rsv_groups;
+			unsigned long group_desc_count, desc_blocks;
+			unsigned int gdpb, blocksize;
+			int rsv_gdb;
+
+			if (!arg) {
+				r_usage++;
+				badopt = token;
+				continue;
+			}
+
+			resize = parse_num_blocks2(arg,
+						   param->s_log_block_size);
+
+			if (resize == 0) {
+				fprintf(stderr,
+					_("Invalid resize parameter: %s\n"),
+					arg);
+				r_usage++;
+				continue;
+			}
+			if (resize <= ext2fs_blocks_count(param)) {
+				fprintf(stderr, "%s",
+					_("The resize maximum must be greater "
+					  "than the filesystem size.\n"));
+				r_usage++;
+				continue;
+			}
+
+			blocksize = EXT2_BLOCK_SIZE(param);
+			bpg = param->s_blocks_per_group;
+			if (!bpg)
+				bpg = blocksize * 8;
+			gdpb = EXT2_DESC_PER_BLOCK(param);
+			group_desc_count = (__u32) ext2fs_div64_ceil(
+				ext2fs_blocks_count(param), bpg);
+			desc_blocks = (group_desc_count +
+				       gdpb - 1) / gdpb;
+			rsv_groups = ext2fs_div64_ceil(resize, bpg);
+			rsv_gdb = ext2fs_div_ceil(rsv_groups, gdpb) -
+				desc_blocks;
+			if (rsv_gdb > (int) EXT2_ADDR_PER_BLOCK(param))
+				rsv_gdb = EXT2_ADDR_PER_BLOCK(param);
+
+			if (rsv_gdb > 0) {
+				if (param->s_rev_level == EXT2_GOOD_OLD_REV) {
+					fprintf(stderr, "%s",
+	_("On-line resizing not supported with revision 0 filesystems\n"));
+					free(buf);
+					exit(1);
+				}
+				param->s_feature_compat |=
+					EXT2_FEATURE_COMPAT_RESIZE_INODE;
+
+				param->s_reserved_gdt_blocks = rsv_gdb;
+			}
+		} else if (!strcmp(token, "test_fs")) {
+			param->s_flags |= EXT2_FLAGS_TEST_FILESYS;
+		} else if (!strcmp(token, "lazy_itable_init")) {
+			if (arg)
+				lazy_itable_init = strtoul(arg, &p, 0);
+			else
+				lazy_itable_init = 1;
+		} else if (!strcmp(token, "lazy_journal_init")) {
+			if (arg)
+				journal_flags |= strtoul(arg, &p, 0) ?
+						EXT2_MKJOURNAL_LAZYINIT : 0;
+			else
+				journal_flags |= EXT2_MKJOURNAL_LAZYINIT;
+		} else if (!strcmp(token, "root_owner")) {
+			if (arg) {
+				root_uid = strtoul(arg, &p, 0);
+				if (*p != ':') {
+					fprintf(stderr,
+						_("Invalid root_owner: '%s'\n"),
+						arg);
+					r_usage++;
+					continue;
+				}
+				p++;
+				root_gid = strtoul(p, &p, 0);
+				if (*p) {
+					fprintf(stderr,
+						_("Invalid root_owner: '%s'\n"),
+						arg);
+					r_usage++;
+					continue;
+				}
+			} else {
+				root_uid = getuid();
+				root_gid = getgid();
+			}
+		} else if (!strcmp(token, "discard")) {
+			discard = 1;
+		} else if (!strcmp(token, "nodiscard")) {
+			discard = 0;
+		} else if (!strcmp(token, "quotatype")) {
+			if (!arg) {
+				r_usage++;
+				badopt = token;
+				continue;
+			}
+			if (!strncmp(arg, "usr", 3)) {
+				quotatype = 0;
+			} else if (!strncmp(arg, "grp", 3)) {
+				quotatype = 1;
+			} else {
+				fprintf(stderr,
+					_("Invalid quotatype parameter: %s\n"),
+					arg);
+				r_usage++;
+				continue;
+			}
+		} else {
+			r_usage++;
+			badopt = token;
+		}
+	}
+	if (r_usage) {
+		fprintf(stderr, _("\nBad option(s) specified: %s\n\n"
+			"Extended options are separated by commas, "
+			"and may take an argument which\n"
+			"\tis set off by an equals ('=') sign.\n\n"
+			"Valid extended options are:\n"
+			"\tstride=<RAID per-disk data chunk in blocks>\n"
+			"\tstripe-width=<RAID stride * data disks in blocks>\n"
+			"\tresize=<resize maximum size in blocks>\n"
+			"\tlazy_itable_init=<0 to disable, 1 to enable>\n"
+			"\tlazy_journal_init=<0 to disable, 1 to enable>\n"
+			"\troot_uid=<uid of root directory>\n"
+			"\troot_gid=<gid of root directory>\n"
+			"\ttest_fs\n"
+			"\tdiscard\n"
+			"\tnodiscard\n"
+			"\tquotatype=<usr OR grp>\n\n"),
+			badopt ? badopt : "");
+		free(buf);
+		exit(1);
+	}
+	if (param->s_raid_stride &&
+	    (param->s_raid_stripe_width % param->s_raid_stride) != 0)
+		fprintf(stderr, _("\nWarning: RAID stripe-width %u not an even "
+				  "multiple of stride %u.\n\n"),
+			param->s_raid_stripe_width, param->s_raid_stride);
+
+	free(buf);
+}
+
+static __u32 ok_features[3] = {
+	/* Compat */
+	EXT3_FEATURE_COMPAT_HAS_JOURNAL |
+		EXT2_FEATURE_COMPAT_RESIZE_INODE |
+		EXT2_FEATURE_COMPAT_DIR_INDEX |
+		EXT2_FEATURE_COMPAT_EXT_ATTR,
+	/* Incompat */
+	EXT2_FEATURE_INCOMPAT_FILETYPE|
+		EXT3_FEATURE_INCOMPAT_EXTENTS|
+		EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|
+		EXT2_FEATURE_INCOMPAT_META_BG|
+		EXT4_FEATURE_INCOMPAT_FLEX_BG|
+		EXT4_FEATURE_INCOMPAT_MMP |
+		EXT4_FEATURE_INCOMPAT_64BIT,
+	/* R/O compat */
+	EXT2_FEATURE_RO_COMPAT_LARGE_FILE|
+		EXT4_FEATURE_RO_COMPAT_HUGE_FILE|
+		EXT4_FEATURE_RO_COMPAT_DIR_NLINK|
+		EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE|
+		EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|
+		EXT4_FEATURE_RO_COMPAT_GDT_CSUM|
+		EXT4_FEATURE_RO_COMPAT_BIGALLOC|
+#ifdef CONFIG_QUOTA
+		EXT4_FEATURE_RO_COMPAT_QUOTA|
+#endif
+		0
+};
+
+
+static void syntax_err_report(const char *filename, long err, int line_num)
+{
+	fprintf(stderr,
+		_("Syntax error in mke2fs config file (%s, line #%d)\n\t%s\n"),
+		filename, line_num, error_message(err));
+	exit(1);
+}
+
+static const char *config_fn[] = { ROOT_SYSCONFDIR "/mke2fs.conf", 0 };
+
+static void edit_feature(const char *str, __u32 *compat_array)
+{
+	if (!str)
+		return;
+
+	if (e2p_edit_feature(str, compat_array, ok_features)) {
+		fprintf(stderr, _("Invalid filesystem option set: %s\n"),
+			str);
+		exit(1);
+	}
+}
+
+static void edit_mntopts(const char *str, __u32 *mntopts)
+{
+	if (!str)
+		return;
+
+	if (e2p_edit_mntopts(str, mntopts, ~0)) {
+		fprintf(stderr, _("Invalid mount option set: %s\n"),
+			str);
+		exit(1);
+	}
+}
+
+struct str_list {
+	char **list;
+	int num;
+	int max;
+};
+
+static errcode_t init_list(struct str_list *sl)
+{
+	sl->num = 0;
+	sl->max = 0;
+	sl->list = malloc((sl->max+1) * sizeof(char *));
+	if (!sl->list)
+		return ENOMEM;
+	sl->list[0] = 0;
+	return 0;
+}
+
+static errcode_t push_string(struct str_list *sl, const char *str)
+{
+	char **new_list;
+
+	if (sl->num >= sl->max) {
+		sl->max += 2;
+		new_list = realloc(sl->list, (sl->max+1) * sizeof(char *));
+		if (!new_list)
+			return ENOMEM;
+		sl->list = new_list;
+	}
+	sl->list[sl->num] = malloc(strlen(str)+1);
+	if (sl->list[sl->num] == 0)
+		return ENOMEM;
+	strcpy(sl->list[sl->num], str);
+	sl->num++;
+	sl->list[sl->num] = 0;
+	return 0;
+}
+
+static void print_str_list(char **list)
+{
+	char **cpp;
+
+	for (cpp = list; *cpp; cpp++) {
+		printf("'%s'", *cpp);
+		if (cpp[1])
+			fputs(", ", stdout);
+	}
+	fputc('\n', stdout);
+}
+
+/*
+ * Return TRUE if the profile has the given subsection
+ */
+static int profile_has_subsection(profile_t prof, const char *section,
+				  const char *subsection)
+{
+	void			*state;
+	const char		*names[4];
+	char			*name;
+	int			ret = 0;
+
+	names[0] = section;
+	names[1] = subsection;
+	names[2] = 0;
+
+	if (profile_iterator_create(prof, names,
+				    PROFILE_ITER_LIST_SECTION |
+				    PROFILE_ITER_RELATIONS_ONLY, &state))
+		return 0;
+
+	if ((profile_iterator(&state, &name, 0) == 0) && name) {
+		free(name);
+		ret = 1;
+	}
+
+	profile_iterator_free(&state);
+	return ret;
+}
+
+static char **parse_fs_type(const char *fs_type,
+			    const char *usage_types,
+			    struct ext2_super_block *sb,
+			    blk64_t fs_blocks_count,
+			    char *progname)
+{
+	const char	*ext_type = 0;
+	char		*parse_str;
+	char		*profile_type = 0;
+	char		*cp, *t;
+	const char	*size_type;
+	struct str_list	list;
+	unsigned long long meg;
+	int		is_hurd = 0;
+
+	if (init_list(&list))
+		return 0;
+
+	if (creator_os && (!strcasecmp(creator_os, "GNU") ||
+			   !strcasecmp(creator_os, "hurd")))
+		is_hurd = 1;
+
+	if (fs_type)
+		ext_type = fs_type;
+	else if (is_hurd)
+		ext_type = "ext2";
+	else if (!strcmp(program_name, "mke3fs"))
+		ext_type = "ext3";
+	else if (!strcmp(program_name, "mke4fs"))
+		ext_type = "ext4";
+	else if (progname) {
+		ext_type = strrchr(progname, '/');
+		if (ext_type)
+			ext_type++;
+		else
+			ext_type = progname;
+
+		if (!strncmp(ext_type, "mkfs.", 5)) {
+			ext_type += 5;
+			if (ext_type[0] == 0)
+				ext_type = 0;
+		} else
+			ext_type = 0;
+	}
+
+	if (!ext_type) {
+		profile_get_string(profile, "defaults", "fs_type", 0,
+				   "ext2", &profile_type);
+		ext_type = profile_type;
+		if (!strcmp(ext_type, "ext2") && (journal_size != 0))
+			ext_type = "ext3";
+	}
+
+
+	if (!profile_has_subsection(profile, "fs_types", ext_type) &&
+	    strcmp(ext_type, "ext2")) {
+		printf(_("\nYour mke2fs.conf file does not define the "
+			 "%s filesystem type.\n"), ext_type);
+		if (!strcmp(ext_type, "ext3") || !strcmp(ext_type, "ext4") ||
+		    !strcmp(ext_type, "ext4dev")) {
+			printf("%s", _("You probably need to install an "
+				       "updated mke2fs.conf file.\n\n"));
+		}
+		if (!force) {
+			printf("%s", _("Aborting...\n"));
+			exit(1);
+		}
+	}
+
+	meg = (1024 * 1024) / EXT2_BLOCK_SIZE(sb);
+	if (fs_blocks_count < 3 * meg)
+		size_type = "floppy";
+	else if (fs_blocks_count < 512 * meg)
+		size_type = "small";
+	else if (fs_blocks_count < 4 * 1024 * 1024 * meg)
+		size_type = "default";
+	else if (fs_blocks_count < 16 * 1024 * 1024 * meg)
+		size_type = "big";
+	else
+		size_type = "huge";
+
+	if (!usage_types)
+		usage_types = size_type;
+
+	parse_str = malloc(strlen(usage_types)+1);
+	if (!parse_str) {
+		free(profile_type);
+		free(list.list);
+		return 0;
+	}
+	strcpy(parse_str, usage_types);
+
+	if (ext_type)
+		push_string(&list, ext_type);
+	cp = parse_str;
+	while (1) {
+		t = strchr(cp, ',');
+		if (t)
+			*t = '\0';
+
+		if (*cp) {
+			if (profile_has_subsection(profile, "fs_types", cp))
+				push_string(&list, cp);
+			else if (strcmp(cp, "default") != 0)
+				fprintf(stderr,
+					_("\nWarning: the fs_type %s is not "
+					  "defined in mke2fs.conf\n\n"),
+					cp);
+		}
+		if (t)
+			cp = t+1;
+		else
+			break;
+	}
+	free(parse_str);
+	free(profile_type);
+	if (is_hurd)
+		push_string(&list, "hurd");
+	return (list.list);
+}
+
+static char *get_string_from_profile(char **types, const char *opt,
+				     const char *def_val)
+{
+	char *ret = 0;
+	int i;
+
+	for (i=0; types[i]; i++);
+	for (i-=1; i >=0 ; i--) {
+		profile_get_string(profile, "fs_types", types[i],
+				   opt, 0, &ret);
+		if (ret)
+			return ret;
+	}
+	profile_get_string(profile, "defaults", opt, 0, def_val, &ret);
+	return (ret);
+}
+
+static int get_int_from_profile(char **types, const char *opt, int def_val)
+{
+	int ret;
+	char **cpp;
+
+	profile_get_integer(profile, "defaults", opt, 0, def_val, &ret);
+	for (cpp = types; *cpp; cpp++)
+		profile_get_integer(profile, "fs_types", *cpp, opt, ret, &ret);
+	return ret;
+}
+
+static double get_double_from_profile(char **types, const char *opt,
+				      double def_val)
+{
+	double ret;
+	char **cpp;
+
+	profile_get_double(profile, "defaults", opt, 0, def_val, &ret);
+	for (cpp = types; *cpp; cpp++)
+		profile_get_double(profile, "fs_types", *cpp, opt, ret, &ret);
+	return ret;
+}
+
+static int get_bool_from_profile(char **types, const char *opt, int def_val)
+{
+	int ret;
+	char **cpp;
+
+	profile_get_boolean(profile, "defaults", opt, 0, def_val, &ret);
+	for (cpp = types; *cpp; cpp++)
+		profile_get_boolean(profile, "fs_types", *cpp, opt, ret, &ret);
+	return ret;
+}
+
+extern const char *mke2fs_default_profile;
+static const char *default_files[] = { "<default>", 0 };
+
+#ifdef HAVE_BLKID_PROBE_GET_TOPOLOGY
+/*
+ * Sets the geometry of a device (stripe/stride), and returns the
+ * device's alignment offset, if any, or a negative error.
+ */
+static int get_device_geometry(const char *file,
+			       struct ext2_super_block *fs_param,
+			       int psector_size)
+{
+	int rc = -1;
+	int blocksize;
+	blkid_probe pr;
+	blkid_topology tp;
+	unsigned long min_io;
+	unsigned long opt_io;
+	struct stat statbuf;
+
+	/* Nothing to do for a regular file */
+	if (!stat(file, &statbuf) && S_ISREG(statbuf.st_mode))
+		return 0;
+
+	pr = blkid_new_probe_from_filename(file);
+	if (!pr)
+		goto out;
+
+	tp = blkid_probe_get_topology(pr);
+	if (!tp)
+		goto out;
+
+	min_io = blkid_topology_get_minimum_io_size(tp);
+	opt_io = blkid_topology_get_optimal_io_size(tp);
+	blocksize = EXT2_BLOCK_SIZE(fs_param);
+	if ((min_io == 0) && (psector_size > blocksize))
+		min_io = psector_size;
+	if ((opt_io == 0) && min_io)
+		opt_io = min_io;
+	if ((opt_io == 0) && (psector_size > blocksize))
+		opt_io = psector_size;
+
+	/* setting stripe/stride to blocksize is pointless */
+	if (min_io > blocksize)
+		fs_param->s_raid_stride = min_io / blocksize;
+	if (opt_io > blocksize)
+		fs_param->s_raid_stripe_width = opt_io / blocksize;
+
+	rc = blkid_topology_get_alignment_offset(tp);
+out:
+	blkid_free_probe(pr);
+	return rc;
+}
+#endif
+
+static void PRS(int argc, char *argv[])
+{
+	int		b, c;
+	int		cluster_size = 0;
+	char 		*tmp, **cpp;
+	int		blocksize = 0;
+	int		inode_ratio = 0;
+	int		inode_size = 0;
+	unsigned long	flex_bg_size = 0;
+	double		reserved_ratio = -1.0;
+	int		lsector_size = 0, psector_size = 0;
+	int		show_version_only = 0;
+	unsigned long long num_inodes = 0; /* unsigned long long to catch too-large input */
+	errcode_t	retval;
+	char *		oldpath = getenv("PATH");
+	char *		extended_opts = 0;
+	char *		fs_type = 0;
+	char *		usage_types = 0;
+	blk64_t		dev_size;
+	/*
+	 * NOTE: A few words about fs_blocks_count and blocksize:
+	 *
+	 * Initially, blocksize is set to zero, which implies 1024.
+	 * If -b is specified, blocksize is updated to the user's value.
+	 *
+	 * Next, the device size or the user's "blocks" command line argument
+	 * is used to set fs_blocks_count; the units are blocksize.
+	 *
+	 * Later, if blocksize hasn't been set and the profile specifies a
+	 * blocksize, then blocksize is updated and fs_blocks_count is scaled
+	 * appropriately.  Note the change in units!
+	 *
+	 * Finally, we complain about fs_blocks_count > 2^32 on a non-64bit fs.
+	 */
+	blk64_t		fs_blocks_count = 0;
+#ifdef __linux__
+	struct 		utsname ut;
+#endif
+	long		sysval;
+	int		s_opt = -1, r_opt = -1;
+	char		*fs_features = 0;
+	int		use_bsize;
+	char		*newpath;
+	int		pathlen = sizeof(PATH_SET) + 1;
+
+	if (oldpath)
+		pathlen += strlen(oldpath);
+	newpath = malloc(pathlen);
+	if (!newpath) {
+		fprintf(stderr, "%s",
+			_("Couldn't allocate memory for new PATH.\n"));
+		exit(1);
+	}
+	strcpy(newpath, PATH_SET);
+
+	/* Update our PATH to include /sbin  */
+	if (oldpath) {
+		strcat (newpath, ":");
+		strcat (newpath, oldpath);
+	}
+	putenv (newpath);
+
+	tmp = getenv("MKE2FS_SYNC");
+	if (tmp)
+		sync_kludge = atoi(tmp);
+
+	/* Determine the system page size if possible */
+#ifdef HAVE_SYSCONF
+#if (!defined(_SC_PAGESIZE) && defined(_SC_PAGE_SIZE))
+#define _SC_PAGESIZE _SC_PAGE_SIZE
+#endif
+#ifdef _SC_PAGESIZE
+	sysval = sysconf(_SC_PAGESIZE);
+	if (sysval > 0)
+		sys_page_size = sysval;
+#endif /* _SC_PAGESIZE */
+#endif /* HAVE_SYSCONF */
+
+	if ((tmp = getenv("MKE2FS_CONFIG")) != NULL)
+		config_fn[0] = tmp;
+	profile_set_syntax_err_cb(syntax_err_report);
+	retval = profile_init(config_fn, &profile);
+	if (retval == ENOENT) {
+		retval = profile_init(default_files, &profile);
+		if (retval)
+			goto profile_error;
+		retval = profile_set_default(profile, mke2fs_default_profile);
+		if (retval)
+			goto profile_error;
+	} else if (retval) {
+profile_error:
+		fprintf(stderr, _("Couldn't init profile successfully"
+				  " (error: %ld).\n"), retval);
+		exit(1);
+	}
+
+	setbuf(stdout, NULL);
+	setbuf(stderr, NULL);
+	add_error_table(&et_ext2_error_table);
+	add_error_table(&et_prof_error_table);
+	memset(&fs_param, 0, sizeof(struct ext2_super_block));
+	fs_param.s_rev_level = 1;  /* Create revision 1 filesystems now */
+
+#ifdef __linux__
+	if (uname(&ut)) {
+		perror("uname");
+		exit(1);
+	}
+	linux_version_code = parse_version_number(ut.release);
+	if (linux_version_code && linux_version_code < (2*65536 + 2*256))
+		fs_param.s_rev_level = 0;
+#endif
+
+	if (argc && *argv) {
+		program_name = get_progname(*argv);
+
+		/* If called as mkfs.ext3, create a journal inode */
+		if (!strcmp(program_name, "mkfs.ext3") ||
+		    !strcmp(program_name, "mke3fs"))
+			journal_size = -1;
+	}
+
+	while ((c = getopt (argc, argv,
+		    "b:cg:i:jl:m:no:qr:s:t:vC:DE:FG:I:J:KL:M:N:O:R:ST:U:V")) != EOF) {
+		switch (c) {
+		case 'b':
+			blocksize = parse_num_blocks2(optarg, -1);
+			b = (blocksize > 0) ? blocksize : -blocksize;
+			if (b < EXT2_MIN_BLOCK_SIZE ||
+			    b > EXT2_MAX_BLOCK_SIZE) {
+				com_err(program_name, 0,
+					_("invalid block size - %s"), optarg);
+				exit(1);
+			}
+			if (blocksize > 4096)
+				fprintf(stderr, _("Warning: blocksize %d not "
+						  "usable on most systems.\n"),
+					blocksize);
+			if (blocksize > 0)
+				fs_param.s_log_block_size =
+					int_log2(blocksize >>
+						 EXT2_MIN_BLOCK_LOG_SIZE);
+			break;
+		case 'c':	/* Check for bad blocks */
+			cflag++;
+			break;
+		case 'C':
+			cluster_size = parse_num_blocks2(optarg, -1);
+			if (cluster_size <= EXT2_MIN_CLUSTER_SIZE ||
+			    cluster_size > EXT2_MAX_CLUSTER_SIZE) {
+				com_err(program_name, 0,
+					_("invalid cluster size - %s"),
+					optarg);
+				exit(1);
+			}
+			break;
+		case 'D':
+			direct_io = 1;
+			break;
+		case 'R':
+			com_err(program_name, 0, "%s",
+				_("'-R' is deprecated, use '-E' instead"));
+			/* fallthrough */
+		case 'E':
+			extended_opts = optarg;
+			break;
+		case 'F':
+			force++;
+			break;
+		case 'g':
+			fs_param.s_blocks_per_group = strtoul(optarg, &tmp, 0);
+			if (*tmp) {
+				com_err(program_name, 0, "%s",
+				_("Illegal number for blocks per group"));
+				exit(1);
+			}
+			if ((fs_param.s_blocks_per_group % 8) != 0) {
+				com_err(program_name, 0, "%s",
+				_("blocks per group must be multiple of 8"));
+				exit(1);
+			}
+			break;
+		case 'G':
+			flex_bg_size = strtoul(optarg, &tmp, 0);
+			if (*tmp) {
+				com_err(program_name, 0, "%s",
+					_("Illegal number for flex_bg size"));
+				exit(1);
+			}
+			if (flex_bg_size < 1 ||
+			    (flex_bg_size & (flex_bg_size-1)) != 0) {
+				com_err(program_name, 0, "%s",
+					_("flex_bg size must be a power of 2"));
+				exit(1);
+			}
+			break;
+		case 'i':
+			inode_ratio = strtoul(optarg, &tmp, 0);
+			if (inode_ratio < EXT2_MIN_BLOCK_SIZE ||
+			    inode_ratio > EXT2_MAX_BLOCK_SIZE * 1024 ||
+			    *tmp) {
+				com_err(program_name, 0,
+					_("invalid inode ratio %s (min %d/max %d)"),
+					optarg, EXT2_MIN_BLOCK_SIZE,
+					EXT2_MAX_BLOCK_SIZE * 1024);
+				exit(1);
+			}
+			break;
+		case 'I':
+			inode_size = strtoul(optarg, &tmp, 0);
+			if (*tmp) {
+				com_err(program_name, 0,
+					_("invalid inode size - %s"), optarg);
+				exit(1);
+			}
+			break;
+		case 'j':
+			if (!journal_size)
+				journal_size = -1;
+			break;
+		case 'J':
+			parse_journal_opts(optarg);
+			break;
+		case 'K':
+			fprintf(stderr, "%s",
+				_("Warning: -K option is deprecated and "
+				  "should not be used anymore. Use "
+				  "\'-E nodiscard\' extended option "
+				  "instead!\n"));
+			discard = 0;
+			break;
+		case 'l':
+			bad_blocks_filename = realloc(bad_blocks_filename,
+						      strlen(optarg) + 1);
+			if (!bad_blocks_filename) {
+				com_err(program_name, ENOMEM, "%s",
+					_("in malloc for bad_blocks_filename"));
+				exit(1);
+			}
+			strcpy(bad_blocks_filename, optarg);
+			break;
+		case 'L':
+			volume_label = optarg;
+			break;
+		case 'm':
+			reserved_ratio = strtod(optarg, &tmp);
+			if ( *tmp || reserved_ratio > 50 ||
+			     reserved_ratio < 0) {
+				com_err(program_name, 0,
+					_("invalid reserved blocks percent - %s"),
+					optarg);
+				exit(1);
+			}
+			break;
+		case 'M':
+			mount_dir = optarg;
+			break;
+		case 'n':
+			noaction++;
+			break;
+		case 'N':
+			num_inodes = strtoul(optarg, &tmp, 0);
+			if (*tmp) {
+				com_err(program_name, 0,
+					_("bad num inodes - %s"), optarg);
+					exit(1);
+			}
+			break;
+		case 'o':
+			creator_os = optarg;
+			break;
+		case 'O':
+			fs_features = optarg;
+			break;
+		case 'q':
+			quiet = 1;
+			break;
+		case 'r':
+			r_opt = strtoul(optarg, &tmp, 0);
+			if (*tmp) {
+				com_err(program_name, 0,
+					_("bad revision level - %s"), optarg);
+				exit(1);
+			}
+			fs_param.s_rev_level = r_opt;
+			break;
+		case 's':	/* deprecated */
+			s_opt = atoi(optarg);
+			break;
+		case 'S':
+			super_only = 1;
+			break;
+		case 't':
+			if (fs_type) {
+				com_err(program_name, 0, "%s",
+				    _("The -t option may only be used once"));
+				exit(1);
+			}
+			fs_type = strdup(optarg);
+			break;
+		case 'T':
+			if (usage_types) {
+				com_err(program_name, 0, "%s",
+				    _("The -T option may only be used once"));
+				exit(1);
+			}
+			usage_types = strdup(optarg);
+			break;
+		case 'U':
+			fs_uuid = optarg;
+			break;
+		case 'v':
+			verbose = 1;
+			break;
+		case 'V':
+			/* Print version number and exit */
+			show_version_only++;
+			break;
+		default:
+			usage();
+		}
+	}
+	if ((optind == argc) && !show_version_only)
+		usage();
+	device_name = argv[optind++];
+
+	if (!quiet || show_version_only)
+		fprintf (stderr, "mke2fs %s (%s)\n", E2FSPROGS_VERSION,
+			 E2FSPROGS_DATE);
+
+	if (show_version_only) {
+		fprintf(stderr, _("\tUsing %s\n"),
+			error_message(EXT2_ET_BASE));
+		exit(0);
+	}
+
+	/*
+	 * If there's no blocksize specified and there is a journal
+	 * device, use it to figure out the blocksize
+	 */
+	if (blocksize <= 0 && journal_device) {
+		ext2_filsys	jfs;
+		io_manager	io_ptr;
+
+#ifdef CONFIG_TESTIO_DEBUG
+		if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) {
+			io_ptr = test_io_manager;
+			test_io_backing_manager = unix_io_manager;
+		} else
+#endif
+			io_ptr = unix_io_manager;
+		retval = ext2fs_open(journal_device,
+				     EXT2_FLAG_JOURNAL_DEV_OK, 0,
+				     0, io_ptr, &jfs);
+		if (retval) {
+			com_err(program_name, retval,
+				_("while trying to open journal device %s\n"),
+				journal_device);
+			exit(1);
+		}
+		if ((blocksize < 0) && (jfs->blocksize < (unsigned) (-blocksize))) {
+			com_err(program_name, 0,
+				_("Journal dev blocksize (%d) smaller than "
+				  "minimum blocksize %d\n"), jfs->blocksize,
+				-blocksize);
+			exit(1);
+		}
+		blocksize = jfs->blocksize;
+		printf(_("Using journal device's blocksize: %d\n"), blocksize);
+		fs_param.s_log_block_size =
+			int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE);
+		ext2fs_close(jfs);
+	}
+
+	if (optind < argc) {
+		fs_blocks_count = parse_num_blocks2(argv[optind++],
+						   fs_param.s_log_block_size);
+		if (!fs_blocks_count) {
+			com_err(program_name, 0,
+				_("invalid blocks '%s' on device '%s'"),
+				argv[optind - 1], device_name);
+			exit(1);
+		}
+	}
+	if (optind < argc)
+		usage();
+
+	if (!force)
+		check_plausibility(device_name);
+	check_mount(device_name, force, _("filesystem"));
+
+	/* Determine the size of the device (if possible) */
+	if (noaction && fs_blocks_count) {
+		dev_size = fs_blocks_count;
+		retval = 0;
+	} else
+		retval = ext2fs_get_device_size2(device_name,
+						 EXT2_BLOCK_SIZE(&fs_param),
+						 &dev_size);
+
+	if (retval && (retval != EXT2_ET_UNIMPLEMENTED)) {
+		com_err(program_name, retval, "%s",
+			_("while trying to determine filesystem size"));
+		exit(1);
+	}
+	if (!fs_blocks_count) {
+		if (retval == EXT2_ET_UNIMPLEMENTED) {
+			com_err(program_name, 0, "%s",
+				_("Couldn't determine device size; you "
+				"must specify\nthe size of the "
+				"filesystem\n"));
+			exit(1);
+		} else {
+			if (dev_size == 0) {
+				com_err(program_name, 0, "%s",
+				_("Device size reported to be zero.  "
+				  "Invalid partition specified, or\n\t"
+				  "partition table wasn't reread "
+				  "after running fdisk, due to\n\t"
+				  "a modified partition being busy "
+				  "and in use.  You may need to reboot\n\t"
+				  "to re-read your partition table.\n"
+				  ));
+				exit(1);
+			}
+			fs_blocks_count = dev_size;
+			if (sys_page_size > EXT2_BLOCK_SIZE(&fs_param))
+				fs_blocks_count &= ~((blk64_t) ((sys_page_size /
+					     EXT2_BLOCK_SIZE(&fs_param))-1));
+		}
+	} else if (!force && (fs_blocks_count > dev_size)) {
+		com_err(program_name, 0, "%s",
+			_("Filesystem larger than apparent device size."));
+		proceed_question();
+	}
+
+	if (!fs_type)
+		profile_get_string(profile, "devices", device_name,
+				   "fs_type", 0, &fs_type);
+	if (!usage_types)
+		profile_get_string(profile, "devices", device_name,
+				   "usage_types", 0, &usage_types);
+
+	/*
+	 * We have the file system (or device) size, so we can now
+	 * determine the appropriate file system types so the fs can
+	 * be appropriately configured.
+	 */
+	fs_types = parse_fs_type(fs_type, usage_types, &fs_param,
+				 fs_blocks_count ? fs_blocks_count : dev_size,
+				 argv[0]);
+	if (!fs_types) {
+		fprintf(stderr, "%s", _("Failed to parse fs types list\n"));
+		exit(1);
+	}
+
+	/* Figure out what features should be enabled */
+
+	tmp = NULL;
+	if (fs_param.s_rev_level != EXT2_GOOD_OLD_REV) {
+		tmp = get_string_from_profile(fs_types, "base_features",
+		      "sparse_super,filetype,resize_inode,dir_index");
+		edit_feature(tmp, &fs_param.s_feature_compat);
+		free(tmp);
+
+		/* And which mount options as well */
+		tmp = get_string_from_profile(fs_types, "default_mntopts",
+					      "acl,user_xattr");
+		edit_mntopts(tmp, &fs_param.s_default_mount_opts);
+		if (tmp)
+			free(tmp);
+
+		for (cpp = fs_types; *cpp; cpp++) {
+			tmp = NULL;
+			profile_get_string(profile, "fs_types", *cpp,
+					   "features", "", &tmp);
+			if (tmp && *tmp)
+				edit_feature(tmp, &fs_param.s_feature_compat);
+			if (tmp)
+				free(tmp);
+		}
+		tmp = get_string_from_profile(fs_types, "default_features",
+					      "");
+	}
+	edit_feature(fs_features ? fs_features : tmp,
+		     &fs_param.s_feature_compat);
+	if (tmp)
+		free(tmp);
+
+	/* Get the hardware sector sizes, if available */
+	retval = ext2fs_get_device_sectsize(device_name, &lsector_size);
+	if (retval) {
+		com_err(program_name, retval, "%s",
+			_("while trying to determine hardware sector size"));
+		exit(1);
+	}
+	retval = ext2fs_get_device_phys_sectsize(device_name, &psector_size);
+	if (retval) {
+		com_err(program_name, retval, "%s",
+			_("while trying to determine physical sector size"));
+		exit(1);
+	}
+
+	tmp = getenv("MKE2FS_DEVICE_SECTSIZE");
+	if (tmp != NULL)
+		lsector_size = atoi(tmp);
+	tmp = getenv("MKE2FS_DEVICE_PHYS_SECTSIZE");
+	if (tmp != NULL)
+		psector_size = atoi(tmp);
+
+	/* Older kernels may not have physical/logical distinction */
+	if (!psector_size)
+		psector_size = lsector_size;
+
+	if (blocksize <= 0) {
+		use_bsize = get_int_from_profile(fs_types, "blocksize", 4096);
+
+		if (use_bsize == -1) {
+			use_bsize = sys_page_size;
+			if ((linux_version_code < (2*65536 + 6*256)) &&
+			    (use_bsize > 4096))
+				use_bsize = 4096;
+		}
+		if (lsector_size && use_bsize < lsector_size)
+			use_bsize = lsector_size;
+		if ((blocksize < 0) && (use_bsize < (-blocksize)))
+			use_bsize = -blocksize;
+		blocksize = use_bsize;
+		fs_blocks_count /= (blocksize / 1024);
+	} else {
+		if (blocksize < lsector_size) {			/* Impossible */
+			com_err(program_name, EINVAL, "%s",
+				_("while setting blocksize; too small "
+				  "for device\n"));
+			exit(1);
+		} else if ((blocksize < psector_size) &&
+			   (psector_size <= sys_page_size)) {	/* Suboptimal */
+			fprintf(stderr, _("Warning: specified blocksize %d is "
+				"less than device physical sectorsize %d\n"),
+				blocksize, psector_size);
+		}
+	}
+
+	fs_param.s_log_block_size =
+		int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE);
+
+	/*
+	 * We now need to do a sanity check of fs_blocks_count for
+	 * 32-bit vs 64-bit block number support.
+	 */
+	if ((fs_blocks_count > MAX_32_NUM) &&
+	    !(fs_param.s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) &&
+	    get_bool_from_profile(fs_types, "auto_64-bit_support", 0)) {
+		fs_param.s_feature_incompat |= EXT4_FEATURE_INCOMPAT_64BIT;
+		fs_param.s_feature_compat &= ~EXT2_FEATURE_COMPAT_RESIZE_INODE;
+	}
+	if ((fs_blocks_count > MAX_32_NUM) &&
+	    !(fs_param.s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)) {
+		fprintf(stderr, _("%s: Size of device (0x%llx blocks) %s "
+				  "too big to be expressed\n\t"
+				  "in 32 bits using a blocksize of %d.\n"),
+			program_name, fs_blocks_count, device_name,
+			EXT2_BLOCK_SIZE(&fs_param));
+		exit(1);
+	}
+
+	ext2fs_blocks_count_set(&fs_param, fs_blocks_count);
+
+	if (fs_param.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
+		fs_types[0] = strdup("journal");
+		fs_types[1] = 0;
+	}
+
+	if (verbose) {
+		fputs(_("fs_types for mke2fs.conf resolution: "), stdout);
+		print_str_list(fs_types);
+	}
+
+	if (r_opt == EXT2_GOOD_OLD_REV &&
+	    (fs_param.s_feature_compat || fs_param.s_feature_incompat ||
+	     fs_param.s_feature_ro_compat)) {
+		fprintf(stderr, "%s", _("Filesystem features not supported "
+					"with revision 0 filesystems\n"));
+		exit(1);
+	}
+
+	if (s_opt > 0) {
+		if (r_opt == EXT2_GOOD_OLD_REV) {
+			fprintf(stderr, "%s",
+				_("Sparse superblocks not supported "
+				  "with revision 0 filesystems\n"));
+			exit(1);
+		}
+		fs_param.s_feature_ro_compat |=
+			EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
+	} else if (s_opt == 0)
+		fs_param.s_feature_ro_compat &=
+			~EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
+
+	if (journal_size != 0) {
+		if (r_opt == EXT2_GOOD_OLD_REV) {
+			fprintf(stderr, "%s", _("Journals not supported with "
+						"revision 0 filesystems\n"));
+			exit(1);
+		}
+		fs_param.s_feature_compat |=
+			EXT3_FEATURE_COMPAT_HAS_JOURNAL;
+	}
+
+	/* Get reserved_ratio from profile if not specified on cmd line. */
+	if (reserved_ratio < 0.0) {
+		reserved_ratio = get_double_from_profile(
+					fs_types, "reserved_ratio", 5.0);
+		if (reserved_ratio > 50 || reserved_ratio < 0) {
+			com_err(program_name, 0,
+				_("invalid reserved blocks percent - %lf"),
+				reserved_ratio);
+			exit(1);
+		}
+	}
+
+	if (fs_param.s_feature_incompat &
+	    EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
+		reserved_ratio = 0;
+		fs_param.s_feature_incompat = EXT3_FEATURE_INCOMPAT_JOURNAL_DEV;
+		fs_param.s_feature_compat = 0;
+		fs_param.s_feature_ro_compat = 0;
+ 	}
+
+	/* Check the user's mkfs options for 64bit */
+	if ((fs_param.s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) &&
+	    !(fs_param.s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS)) {
+		printf("%s", _("Extents MUST be enabled for a 64-bit "
+			       "filesystem.  Pass -O extents to rectify.\n"));
+		exit(1);
+	}
+
+	/* Set first meta blockgroup via an environment variable */
+	/* (this is mostly for debugging purposes) */
+	if ((fs_param.s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) &&
+	    ((tmp = getenv("MKE2FS_FIRST_META_BG"))))
+		fs_param.s_first_meta_bg = atoi(tmp);
+	if (fs_param.s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_BIGALLOC) {
+		if (!cluster_size)
+			cluster_size = get_int_from_profile(fs_types,
+							    "cluster_size",
+							    blocksize*16);
+		fs_param.s_log_cluster_size =
+			int_log2(cluster_size >> EXT2_MIN_CLUSTER_LOG_SIZE);
+		if (fs_param.s_log_cluster_size &&
+		    fs_param.s_log_cluster_size < fs_param.s_log_block_size) {
+			com_err(program_name, 0, "%s",
+				_("The cluster size may not be "
+				  "smaller than the block size.\n"));
+			exit(1);
+		}
+	} else if (cluster_size) {
+		com_err(program_name, 0, "%s",
+			_("specifying a cluster size requires the "
+			  "bigalloc feature"));
+		exit(1);
+	} else
+		fs_param.s_log_cluster_size = fs_param.s_log_block_size;
+
+	if (inode_ratio == 0) {
+		inode_ratio = get_int_from_profile(fs_types, "inode_ratio",
+						   8192);
+		if (inode_ratio < blocksize)
+			inode_ratio = blocksize;
+		if (inode_ratio < EXT2_CLUSTER_SIZE(&fs_param))
+			inode_ratio = EXT2_CLUSTER_SIZE(&fs_param);
+	}
+
+#ifdef HAVE_BLKID_PROBE_GET_TOPOLOGY
+	retval = get_device_geometry(device_name, &fs_param, psector_size);
+	if (retval < 0) {
+		fprintf(stderr,
+			_("warning: Unable to get device geometry for %s\n"),
+			device_name);
+	} else if (retval) {
+		printf(_("%s alignment is offset by %lu bytes.\n"),
+		       device_name, retval);
+		printf(_("This may result in very poor performance, "
+			  "(re)-partitioning suggested.\n"));
+	}
+#endif
+
+	blocksize = EXT2_BLOCK_SIZE(&fs_param);
+
+	/*
+	 * Initialize s_desc_size so that the parse_extended_opts()
+	 * can correctly handle "-E resize=NNN" if the 64-bit option
+	 * is set.
+	 */
+	if (fs_param.s_feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT)
+		fs_param.s_desc_size = EXT2_MIN_DESC_SIZE_64BIT;
+
+	/* This check should happen beyond the last assignment to blocksize */
+	if (blocksize > sys_page_size) {
+		if (!force) {
+			com_err(program_name, 0,
+				_("%d-byte blocks too big for system (max %d)"),
+				blocksize, sys_page_size);
+			proceed_question();
+		}
+		fprintf(stderr, _("Warning: %d-byte blocks too big for system "
+				  "(max %d), forced to continue\n"),
+			blocksize, sys_page_size);
+	}
+
+	lazy_itable_init = 0;
+	if (access("/sys/fs/ext4/features/lazy_itable_init", R_OK) == 0)
+		lazy_itable_init = 1;
+
+	lazy_itable_init = get_bool_from_profile(fs_types,
+						 "lazy_itable_init",
+						 lazy_itable_init);
+	discard = get_bool_from_profile(fs_types, "discard" , discard);
+	journal_flags |= get_bool_from_profile(fs_types,
+					       "lazy_journal_init", 0) ?
+					       EXT2_MKJOURNAL_LAZYINIT : 0;
+	journal_flags |= EXT2_MKJOURNAL_NO_MNT_CHECK;
+
+	/* Get options from profile */
+	for (cpp = fs_types; *cpp; cpp++) {
+		tmp = NULL;
+		profile_get_string(profile, "fs_types", *cpp, "options", "", &tmp);
+			if (tmp && *tmp)
+				parse_extended_opts(&fs_param, tmp);
+			free(tmp);
+	}
+
+	if (extended_opts)
+		parse_extended_opts(&fs_param, extended_opts);
+
+	/* Can't support bigalloc feature without extents feature */
+	if ((fs_param.s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_BIGALLOC) &&
+	    !(fs_param.s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS)) {
+		com_err(program_name, 0, "%s",
+			_("Can't support bigalloc feature without "
+			  "extents feature"));
+		exit(1);
+	}
+
+	if ((fs_param.s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) &&
+	    (fs_param.s_feature_compat & EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
+		fprintf(stderr, "%s", _("The resize_inode and meta_bg "
+					"features are not compatible.\n"
+					"They can not be both enabled "
+					"simultaneously.\n"));
+		exit(1);
+	}
+
+	if (!quiet &&
+	    (fs_param.s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_BIGALLOC))
+		fprintf(stderr, "%s", _("\nWarning: the bigalloc feature is "
+				  "still under development\n"
+				  "See https://ext4.wiki.kernel.org/"
+				  "index.php/Bigalloc for more information\n\n"));
+
+	if (!quiet &&
+	    (fs_param.s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_QUOTA))
+		fprintf(stderr, "%s", _("\nWarning: the quota feature is "
+				  "still under development\n"
+				  "See https://ext4.wiki.kernel.org/"
+				  "index.php/Quota for more information\n\n"));
+
+	/* Since sparse_super is the default, we would only have a problem
+	 * here if it was explicitly disabled.
+	 */
+	if ((fs_param.s_feature_compat & EXT2_FEATURE_COMPAT_RESIZE_INODE) &&
+	    !(fs_param.s_feature_ro_compat&EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) {
+		com_err(program_name, 0, "%s",
+			_("reserved online resize blocks not supported "
+			  "on non-sparse filesystem"));
+		exit(1);
+	}
+
+	if (fs_param.s_blocks_per_group) {
+		if (fs_param.s_blocks_per_group < 256 ||
+		    fs_param.s_blocks_per_group > 8 * (unsigned) blocksize) {
+			com_err(program_name, 0, "%s",
+				_("blocks per group count out of range"));
+			exit(1);
+		}
+	}
+
+	/*
+	 * If the bigalloc feature is enabled, then the -g option will
+	 * specify the number of clusters per group.
+	 */
+	if (fs_param.s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_BIGALLOC) {
+		fs_param.s_clusters_per_group = fs_param.s_blocks_per_group;
+		fs_param.s_blocks_per_group = 0;
+	}
+
+	if (inode_size == 0)
+		inode_size = get_int_from_profile(fs_types, "inode_size", 0);
+	if (!flex_bg_size && (fs_param.s_feature_incompat &
+			      EXT4_FEATURE_INCOMPAT_FLEX_BG))
+		flex_bg_size = get_int_from_profile(fs_types,
+						    "flex_bg_size", 16);
+	if (flex_bg_size) {
+		if (!(fs_param.s_feature_incompat &
+		      EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
+			com_err(program_name, 0, "%s",
+				_("Flex_bg feature not enabled, so "
+				  "flex_bg size may not be specified"));
+			exit(1);
+		}
+		fs_param.s_log_groups_per_flex = int_log2(flex_bg_size);
+	}
+
+	if (inode_size && fs_param.s_rev_level >= EXT2_DYNAMIC_REV) {
+		if (inode_size < EXT2_GOOD_OLD_INODE_SIZE ||
+		    inode_size > EXT2_BLOCK_SIZE(&fs_param) ||
+		    inode_size & (inode_size - 1)) {
+			com_err(program_name, 0,
+				_("invalid inode size %d (min %d/max %d)"),
+				inode_size, EXT2_GOOD_OLD_INODE_SIZE,
+				blocksize);
+			exit(1);
+		}
+		fs_param.s_inode_size = inode_size;
+	}
+
+	/* Make sure number of inodes specified will fit in 32 bits */
+	if (num_inodes == 0) {
+		unsigned long long n;
+		n = ext2fs_blocks_count(&fs_param) * blocksize / inode_ratio;
+		if (n > MAX_32_NUM) {
+			if (fs_param.s_feature_incompat &
+			    EXT4_FEATURE_INCOMPAT_64BIT)
+				num_inodes = MAX_32_NUM;
+			else {
+				com_err(program_name, 0,
+					_("too many inodes (%llu), raise "
+					  "inode ratio?"), n);
+				exit(1);
+			}
+		}
+	} else if (num_inodes > MAX_32_NUM) {
+		com_err(program_name, 0,
+			_("too many inodes (%llu), specify < 2^32 inodes"),
+			  num_inodes);
+		exit(1);
+	}
+	/*
+	 * Calculate number of inodes based on the inode ratio
+	 */
+	fs_param.s_inodes_count = num_inodes ? num_inodes :
+		(ext2fs_blocks_count(&fs_param) * blocksize) / inode_ratio;
+
+	if ((((unsigned long long)fs_param.s_inodes_count) *
+	     (inode_size ? inode_size : EXT2_GOOD_OLD_INODE_SIZE)) >=
+	    ((ext2fs_blocks_count(&fs_param)) *
+	     EXT2_BLOCK_SIZE(&fs_param))) {
+		com_err(program_name, 0, _("inode_size (%u) * inodes_count "
+					  "(%u) too big for a\n\t"
+					  "filesystem with %llu blocks, "
+					  "specify higher inode_ratio (-i)\n\t"
+					  "or lower inode count (-N).\n"),
+			inode_size ? inode_size : EXT2_GOOD_OLD_INODE_SIZE,
+			fs_param.s_inodes_count,
+			(unsigned long long) ext2fs_blocks_count(&fs_param));
+		exit(1);
+	}
+
+	/*
+	 * Calculate number of blocks to reserve
+	 */
+	ext2fs_r_blocks_count_set(&fs_param, reserved_ratio *
+				  ext2fs_blocks_count(&fs_param) / 100.0);
+
+	free(fs_type);
+	free(usage_types);
+}
+
+static int should_do_undo(const char *name)
+{
+	errcode_t retval;
+	io_channel channel;
+	__u16	s_magic;
+	struct ext2_super_block super;
+	io_manager manager = unix_io_manager;
+	int csum_flag, force_undo;
+
+	csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(&fs_param,
+					       EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
+	force_undo = get_int_from_profile(fs_types, "force_undo", 0);
+	if (!force_undo && (!csum_flag || !lazy_itable_init))
+		return 0;
+
+	retval = manager->open(name, IO_FLAG_EXCLUSIVE,  &channel);
+	if (retval) {
+		/*
+		 * We don't handle error cases instead we
+		 * declare that the file system doesn't exist
+		 * and let the rest of mke2fs take care of
+		 * error
+		 */
+		retval = 0;
+		goto open_err_out;
+	}
+
+	io_channel_set_blksize(channel, SUPERBLOCK_OFFSET);
+	retval = io_channel_read_blk64(channel, 1, -SUPERBLOCK_SIZE, &super);
+	if (retval) {
+		retval = 0;
+		goto err_out;
+	}
+
+#if defined(WORDS_BIGENDIAN)
+	s_magic = ext2fs_swab16(super.s_magic);
+#else
+	s_magic = super.s_magic;
+#endif
+
+	if (s_magic == EXT2_SUPER_MAGIC)
+		retval = 1;
+
+err_out:
+	io_channel_close(channel);
+
+open_err_out:
+
+	return retval;
+}
+
+static int mke2fs_setup_tdb(const char *name, io_manager *io_ptr)
+{
+	errcode_t retval = ENOMEM;
+	char *tdb_dir = NULL, *tdb_file = NULL;
+	char *dev_name, *tmp_name;
+	int free_tdb_dir = 0;
+
+	/*
+	 * Configuration via a conf file would be
+	 * nice
+	 */
+	tdb_dir = getenv("E2FSPROGS_UNDO_DIR");
+	if (!tdb_dir) {
+		profile_get_string(profile, "defaults",
+				   "undo_dir", 0, "/var/lib/e2fsprogs",
+				   &tdb_dir);
+		free_tdb_dir = 1;
+	}
+
+	if (!strcmp(tdb_dir, "none") || (tdb_dir[0] == 0) ||
+	    access(tdb_dir, W_OK)) {
+		if (free_tdb_dir)
+			free(tdb_dir);
+		return 0;
+	}
+
+	tmp_name = strdup(name);
+	if (!tmp_name)
+		goto errout;
+	dev_name = basename(tmp_name);
+	tdb_file = malloc(strlen(tdb_dir) + 8 + strlen(dev_name) + 7 + 1);
+	if (!tdb_file) {
+		free(tmp_name);
+		goto errout;
+	}
+	sprintf(tdb_file, "%s/mke2fs-%s.e2undo", tdb_dir, dev_name);
+	free(tmp_name);
+
+	if (!access(tdb_file, F_OK)) {
+		if (unlink(tdb_file) < 0) {
+			retval = errno;
+			goto errout;
+		}
+	}
+
+	set_undo_io_backing_manager(*io_ptr);
+	*io_ptr = undo_io_manager;
+	retval = set_undo_io_backup_file(tdb_file);
+	if (retval)
+		goto errout;
+	printf(_("Overwriting existing filesystem; this can be undone "
+		 "using the command:\n"
+		 "    e2undo %s %s\n\n"), tdb_file, name);
+
+	if (free_tdb_dir)
+		free(tdb_dir);
+	free(tdb_file);
+	return 0;
+
+errout:
+	if (free_tdb_dir)
+		free(tdb_dir);
+	free(tdb_file);
+	com_err(program_name, retval, "%s",
+		_("while trying to setup undo file\n"));
+	return retval;
+}
+
+static int mke2fs_discard_device(ext2_filsys fs)
+{
+	struct ext2fs_numeric_progress_struct progress;
+	blk64_t blocks = ext2fs_blocks_count(fs->super);
+	blk64_t count = DISCARD_STEP_MB;
+	blk64_t cur;
+	int retval = 0;
+
+	/*
+	 * Let's try if discard really works on the device, so
+	 * we do not print numeric progress resulting in failure
+	 * afterwards.
+	 */
+	retval = io_channel_discard(fs->io, 0, fs->blocksize);
+	if (retval)
+		return retval;
+	cur = fs->blocksize;
+
+	count *= (1024 * 1024);
+	count /= fs->blocksize;
+
+	ext2fs_numeric_progress_init(fs, &progress,
+				     _("Discarding device blocks: "),
+				     blocks);
+	while (cur < blocks) {
+		ext2fs_numeric_progress_update(fs, &progress, cur);
+
+		if (cur + count > blocks)
+			count = blocks - cur;
+
+		retval = io_channel_discard(fs->io, cur, count);
+		if (retval)
+			break;
+		cur += count;
+	}
+
+	if (retval) {
+		ext2fs_numeric_progress_close(fs, &progress,
+				      _("failed - "));
+		if (!quiet)
+			printf("%s\n",error_message(retval));
+	} else
+		ext2fs_numeric_progress_close(fs, &progress,
+				      _("done                            \n"));
+
+	return retval;
+}
+
+static void fix_cluster_bg_counts(ext2_filsys fs)
+{
+	blk64_t	cluster, num_clusters, tot_free;
+	unsigned num = 0;
+	int	grp_free, num_free, group;
+
+	num_clusters = EXT2FS_B2C(fs, ext2fs_blocks_count(fs->super));
+	tot_free = num_free = group = grp_free = 0;
+	for (cluster = EXT2FS_B2C(fs, fs->super->s_first_data_block);
+	     cluster < num_clusters; cluster++) {
+		if (!ext2fs_test_block_bitmap2(fs->block_map,
+					       EXT2FS_C2B(fs, cluster))) {
+			grp_free++;
+			tot_free++;
+		}
+		num++;
+		if ((num == fs->super->s_clusters_per_group) ||
+		    (cluster == num_clusters-1)) {
+			ext2fs_bg_free_blocks_count_set(fs, group, grp_free);
+			ext2fs_group_desc_csum_set(fs, group);
+			num = 0;
+			grp_free = 0;
+			group++;
+		}
+	}
+	ext2fs_free_blocks_count_set(fs->super, EXT2FS_C2B(fs, tot_free));
+}
+
+static int create_quota_inodes(ext2_filsys fs)
+{
+	quota_ctx_t qctx;
+
+	quota_init_context(&qctx, fs, -1);
+	quota_compute_usage(qctx);
+	quota_write_inode(qctx, quotatype);
+	quota_release_context(&qctx);
+
+	return 0;
+}
+
+int main (int argc, char *argv[])
+{
+	errcode_t	retval = 0;
+	ext2_filsys	fs;
+	badblocks_list	bb_list = 0;
+	unsigned int	journal_blocks;
+	unsigned int	i, checkinterval;
+	int		max_mnt_count;
+	int		val, hash_alg;
+	int		flags;
+	int		old_bitmaps;
+	io_manager	io_ptr;
+	char		tdb_string[40];
+	char		*hash_alg_str;
+	int		itable_zeroed = 0;
+
+#ifdef ENABLE_NLS
+	setlocale(LC_MESSAGES, "");
+	setlocale(LC_CTYPE, "");
+	bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
+	textdomain(NLS_CAT_NAME);
+	set_com_err_gettext(gettext);
+#endif
+	PRS(argc, argv);
+
+#ifdef CONFIG_TESTIO_DEBUG
+	if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) {
+		io_ptr = test_io_manager;
+		test_io_backing_manager = unix_io_manager;
+	} else
+#endif
+		io_ptr = unix_io_manager;
+
+	if (should_do_undo(device_name)) {
+		retval = mke2fs_setup_tdb(device_name, &io_ptr);
+		if (retval)
+			exit(1);
+	}
+
+	/*
+	 * Initialize the superblock....
+	 */
+	flags = EXT2_FLAG_EXCLUSIVE;
+	if (direct_io)
+		flags |= EXT2_FLAG_DIRECT_IO;
+	profile_get_boolean(profile, "options", "old_bitmaps", 0, 0,
+			    &old_bitmaps);
+	if (!old_bitmaps)
+		flags |= EXT2_FLAG_64BITS;
+	/*
+	 * By default, we print how many inode tables or block groups
+	 * or whatever we've written so far.  The quiet flag disables
+	 * this, along with a lot of other output.
+	 */
+	if (!quiet)
+		flags |= EXT2_FLAG_PRINT_PROGRESS;
+	retval = ext2fs_initialize(device_name, flags, &fs_param, io_ptr, &fs);
+	if (retval) {
+		com_err(device_name, retval, "%s",
+			_("while setting up superblock"));
+		exit(1);
+	}
+
+	/* Calculate journal blocks */
+	if (!journal_device && ((journal_size) ||
+		(fs_param.s_feature_compat &
+		 EXT3_FEATURE_COMPAT_HAS_JOURNAL)))
+		journal_blocks = figure_journal_size(journal_size, fs);
+
+	/* Can't undo discard ... */
+	if (!noaction && discard && (io_ptr != undo_io_manager)) {
+		retval = mke2fs_discard_device(fs);
+		if (!retval && io_channel_discard_zeroes_data(fs->io)) {
+			if (verbose)
+				printf("%s",
+				       _("Discard succeeded and will return "
+					 "0s - skipping inode table wipe\n"));
+			lazy_itable_init = 1;
+			itable_zeroed = 1;
+		}
+	}
+
+	sprintf(tdb_string, "tdb_data_size=%d", fs->blocksize <= 4096 ?
+		32768 : fs->blocksize * 8);
+	io_channel_set_options(fs->io, tdb_string);
+
+	if (fs_param.s_flags & EXT2_FLAGS_TEST_FILESYS)
+		fs->super->s_flags |= EXT2_FLAGS_TEST_FILESYS;
+
+	if ((fs_param.s_feature_incompat &
+	     (EXT3_FEATURE_INCOMPAT_EXTENTS|EXT4_FEATURE_INCOMPAT_FLEX_BG)) ||
+	    (fs_param.s_feature_ro_compat &
+	     (EXT4_FEATURE_RO_COMPAT_HUGE_FILE|EXT4_FEATURE_RO_COMPAT_GDT_CSUM|
+	      EXT4_FEATURE_RO_COMPAT_DIR_NLINK|
+	      EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE)))
+		fs->super->s_kbytes_written = 1;
+
+	/*
+	 * Wipe out the old on-disk superblock
+	 */
+	if (!noaction)
+		zap_sector(fs, 2, 6);
+
+	/*
+	 * Parse or generate a UUID for the filesystem
+	 */
+	if (fs_uuid) {
+		if (uuid_parse(fs_uuid, fs->super->s_uuid) !=0) {
+			com_err(device_name, 0, "could not parse UUID: %s\n",
+				fs_uuid);
+			exit(1);
+		}
+	} else
+		uuid_generate(fs->super->s_uuid);
+
+	/*
+	 * Initialize the directory index variables
+	 */
+	hash_alg_str = get_string_from_profile(fs_types, "hash_alg",
+					       "half_md4");
+	hash_alg = e2p_string2hash(hash_alg_str);
+	free(hash_alg_str);
+	fs->super->s_def_hash_version = (hash_alg >= 0) ? hash_alg :
+		EXT2_HASH_HALF_MD4;
+	uuid_generate((unsigned char *) fs->super->s_hash_seed);
+
+	/*
+	 * Periodic checks can be enabled/disabled via config file.
+	 * Note we override the kernel include file's idea of what the default
+	 * check interval (never) should be.  It's a good idea to check at
+	 * least *occasionally*, specially since servers will never rarely get
+	 * to reboot, since Linux is so robust these days.  :-)
+	 *
+	 * 180 days (six months) seems like a good value.
+	 */
+#ifdef EXT2_DFL_CHECKINTERVAL
+#undef EXT2_DFL_CHECKINTERVAL
+#endif
+#define EXT2_DFL_CHECKINTERVAL (86400L * 180L)
+
+	if (get_bool_from_profile(fs_types, "enable_periodic_fsck", 0)) {
+		fs->super->s_checkinterval = EXT2_DFL_CHECKINTERVAL;
+		fs->super->s_max_mnt_count = EXT2_DFL_MAX_MNT_COUNT;
+		/*
+		 * Add "jitter" to the superblock's check interval so that we
+		 * don't check all the filesystems at the same time.  We use a
+		 * kludgy hack of using the UUID to derive a random jitter value
+		 */
+		for (i = 0, val = 0 ; i < sizeof(fs->super->s_uuid); i++)
+			val += fs->super->s_uuid[i];
+		fs->super->s_max_mnt_count += val % EXT2_DFL_MAX_MNT_COUNT;
+	} else
+		fs->super->s_max_mnt_count = -1;
+
+	/*
+	 * Override the creator OS, if applicable
+	 */
+	if (creator_os && !set_os(fs->super, creator_os)) {
+		com_err (program_name, 0, _("unknown os - %s"), creator_os);
+		exit(1);
+	}
+
+	/*
+	 * For the Hurd, we will turn off filetype since it doesn't
+	 * support it.
+	 */
+	if (fs->super->s_creator_os == EXT2_OS_HURD)
+		fs->super->s_feature_incompat &=
+			~EXT2_FEATURE_INCOMPAT_FILETYPE;
+
+	/*
+	 * Set the volume label...
+	 */
+	if (volume_label) {
+		memset(fs->super->s_volume_name, 0,
+		       sizeof(fs->super->s_volume_name));
+		strncpy(fs->super->s_volume_name, volume_label,
+			sizeof(fs->super->s_volume_name));
+	}
+
+	/*
+	 * Set the last mount directory
+	 */
+	if (mount_dir) {
+		memset(fs->super->s_last_mounted, 0,
+		       sizeof(fs->super->s_last_mounted));
+		strncpy(fs->super->s_last_mounted, mount_dir,
+			sizeof(fs->super->s_last_mounted));
+	}
+
+	if (!quiet || noaction)
+		show_stats(fs);
+
+	if (noaction)
+		exit(0);
+
+	if (fs->super->s_feature_incompat &
+	    EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
+		create_journal_dev(fs);
+		exit(ext2fs_close(fs) ? 1 : 0);
+	}
+
+	if (bad_blocks_filename)
+		read_bb_file(fs, &bb_list, bad_blocks_filename);
+	if (cflag)
+		test_disk(fs, &bb_list);
+
+	handle_bad_blocks(fs, bb_list);
+	fs->stride = fs_stride = fs->super->s_raid_stride;
+	if (!quiet)
+		printf("%s", _("Allocating group tables: "));
+	retval = ext2fs_allocate_tables(fs);
+	if (retval) {
+		com_err(program_name, retval, "%s",
+			_("while trying to allocate filesystem tables"));
+		exit(1);
+	}
+	if (!quiet)
+		printf("%s", _("done                            \n"));
+
+	retval = ext2fs_convert_subcluster_bitmap(fs, &fs->block_map);
+	if (retval) {
+		com_err(program_name, retval, "%s",
+			_("\n\twhile converting subcluster bitmap"));
+		exit(1);
+	}
+
+	if (super_only) {
+		fs->super->s_state |= EXT2_ERROR_FS;
+		fs->flags &= ~(EXT2_FLAG_IB_DIRTY|EXT2_FLAG_BB_DIRTY);
+		/* 
+		 * The command "mke2fs -S" is used to recover
+		 * corrupted file systems, so do not mark any of the
+		 * inodes as unused; we want e2fsck to consider all
+		 * inodes as potentially containing recoverable data.
+		 */
+		if (fs->super->s_feature_ro_compat &
+		    EXT4_FEATURE_RO_COMPAT_GDT_CSUM) {
+			for (i = 0; i < fs->group_desc_count; i++)
+				ext2fs_bg_itable_unused_set(fs, i, 0);
+		}
+	} else {
+		/* rsv must be a power of two (64kB is MD RAID sb alignment) */
+		blk64_t rsv = 65536 / fs->blocksize;
+		blk64_t blocks = ext2fs_blocks_count(fs->super);
+		blk64_t start;
+		blk64_t ret_blk;
+
+#ifdef ZAP_BOOTBLOCK
+		zap_sector(fs, 0, 2);
+#endif
+
+		/*
+		 * Wipe out any old MD RAID (or other) metadata at the end
+		 * of the device.  This will also verify that the device is
+		 * as large as we think.  Be careful with very small devices.
+		 */
+		start = (blocks & ~(rsv - 1));
+		if (start > rsv)
+			start -= rsv;
+		if (start > 0)
+			retval = ext2fs_zero_blocks2(fs, start, blocks - start,
+						    &ret_blk, NULL);
+
+		if (retval) {
+			com_err(program_name, retval,
+				_("while zeroing block %llu at end of filesystem"),
+				ret_blk);
+		}
+		write_inode_tables(fs, lazy_itable_init, itable_zeroed);
+		create_root_dir(fs);
+		create_lost_and_found(fs);
+		reserve_inodes(fs);
+		create_bad_block_inode(fs, bb_list);
+		if (fs->super->s_feature_compat &
+		    EXT2_FEATURE_COMPAT_RESIZE_INODE) {
+			retval = ext2fs_create_resize_inode(fs);
+			if (retval) {
+				com_err("ext2fs_create_resize_inode", retval,
+					"%s",
+				_("while reserving blocks for online resize"));
+				exit(1);
+			}
+		}
+	}
+
+	if (journal_device) {
+		ext2_filsys	jfs;
+
+		if (!force)
+			check_plausibility(journal_device);
+		check_mount(journal_device, force, _("journal"));
+
+		retval = ext2fs_open(journal_device, EXT2_FLAG_RW|
+				     EXT2_FLAG_JOURNAL_DEV_OK, 0,
+				     fs->blocksize, unix_io_manager, &jfs);
+		if (retval) {
+			com_err(program_name, retval,
+				_("while trying to open journal device %s\n"),
+				journal_device);
+			exit(1);
+		}
+		if (!quiet) {
+			printf(_("Adding journal to device %s: "),
+			       journal_device);
+			fflush(stdout);
+		}
+		retval = ext2fs_add_journal_device(fs, jfs);
+		if(retval) {
+			com_err (program_name, retval,
+				 _("\n\twhile trying to add journal to device %s"),
+				 journal_device);
+			exit(1);
+		}
+		if (!quiet)
+			printf("%s", _("done\n"));
+		ext2fs_close(jfs);
+		free(journal_device);
+	} else if ((journal_size) ||
+		   (fs_param.s_feature_compat &
+		    EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
+		if (super_only) {
+			printf("%s", _("Skipping journal creation in super-only mode\n"));
+			fs->super->s_journal_inum = EXT2_JOURNAL_INO;
+			goto no_journal;
+		}
+
+		if (!journal_blocks) {
+			fs->super->s_feature_compat &=
+				~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
+			goto no_journal;
+		}
+		if (!quiet) {
+			printf(_("Creating journal (%u blocks): "),
+			       journal_blocks);
+			fflush(stdout);
+		}
+		retval = ext2fs_add_journal_inode(fs, journal_blocks,
+						  journal_flags);
+		if (retval) {
+			com_err(program_name, retval, "%s",
+				_("\n\twhile trying to create journal"));
+			exit(1);
+		}
+		if (!quiet)
+			printf("%s", _("done\n"));
+	}
+no_journal:
+	if (!super_only &&
+	    fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_MMP) {
+		retval = ext2fs_mmp_init(fs);
+		if (retval) {
+			fprintf(stderr, "%s",
+				_("\nError while enabling multiple "
+				  "mount protection feature."));
+			exit(1);
+		}
+		if (!quiet)
+			printf(_("Multiple mount protection is enabled "
+				 "with update interval %d seconds.\n"),
+			       fs->super->s_mmp_update_interval);
+	}
+
+	if (EXT2_HAS_RO_COMPAT_FEATURE(&fs_param,
+				       EXT4_FEATURE_RO_COMPAT_BIGALLOC))
+		fix_cluster_bg_counts(fs);
+	if (EXT2_HAS_RO_COMPAT_FEATURE(&fs_param,
+				       EXT4_FEATURE_RO_COMPAT_QUOTA))
+		create_quota_inodes(fs);
+
+	if (!quiet)
+		printf("%s", _("Writing superblocks and "
+		       "filesystem accounting information: "));
+	checkinterval = fs->super->s_checkinterval;
+	max_mnt_count = fs->super->s_max_mnt_count;
+	retval = ext2fs_close(fs);
+	if (retval) {
+		fprintf(stderr, "%s",
+			_("\nWarning, had trouble writing out superblocks."));
+	} else if (!quiet) {
+		printf("%s", _("done\n\n"));
+		if (!getenv("MKE2FS_SKIP_CHECK_MSG"))
+			print_check_message(max_mnt_count, checkinterval);
+	}
+
+	remove_error_table(&et_ext2_error_table);
+	remove_error_table(&et_prof_error_table);
+	profile_release(profile);
+	for (i=0; fs_types[i]; i++)
+		free(fs_types[i]);
+	free(fs_types);
+	return retval;
+}
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/mke2fs.conf.5.in b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/mke2fs.conf.5.in
new file mode 100644
index 0000000..0625d0e
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/mke2fs.conf.5.in
@@ -0,0 +1,431 @@
+.\" -*- nroff -*-
+.\" Copyright 2006 by Theodore Ts'o.  All Rights Reserved.
+.\" This file may be copied under the terms of the GNU Public License.
+.\" 
+.TH mke2fs.conf 5 "@E2FSPROGS_MONTH@ @E2FSPROGS_YEAR@" "E2fsprogs version @E2FSPROGS_VERSION@"
+.SH NAME
+mke2fs.conf \- Configuration file for mke2fs
+.SH DESCRIPTION
+.I mke2fs.conf
+is the configuration file for 
+.BR mke2fs (8).  
+It controls the default parameters used by 
+.BR mke2fs (8)
+when it is creating ext2, ext3, or ext4 filesystems.
+.PP
+The
+.I mke2fs.conf
+file uses an INI-style format.  Stanzas, or top-level sections, are 
+delimited by square braces: [ ].  Within each section, each line 
+defines a relation, which assigns tags to values, or to a subsection,
+which contains further relations or subsections.   
+.\" Tags can be assigned multiple values
+An example of the INI-style format used by this configuration file 
+follows below:
+.P
+	[section1]
+.br
+		tag1 = value_a
+.br
+		tag1 = value_b
+.br
+		tag2 = value_c
+.P
+	[section 2]
+.br
+		tag3 = {
+.br
+			subtag1 = subtag_value_a
+.br
+			subtag1 = subtag_value_b
+.br
+			subtag2 = subtag_value_c
+.br
+		}
+.br
+		tag1 = value_d
+.br
+		tag2 = value_e
+.br
+	}
+.P
+Comments are delimited by a semicolon (';') or a hash ('#') character 
+at the beginning of the comment, and are terminated by the end of 
+line character.
+.P
+Tags and values must be quoted using double quotes if they contain
+spaces.  Within a quoted string, the standard backslash interpretations 
+apply: "\en" (for the newline character), 
+"\et" (for the tab character), "\eb" (for the backspace character), 
+and "\e\e" (for the backslash character).
+.P
+Some relations expect a boolean value.  The parser is quite liberal on
+recognizing ``yes'', '`y'', ``true'', ``t'', ``1'', ``on'', etc. as a
+boolean true value, and ``no'', ``n'', ``false'', ``nil'', ``0'',
+``off'' as a boolean false value.
+.P
+The following stanzas are used in the 
+.I mke2fs.conf
+file.  They will be described in more detail in future sections of this
+document.
+.TP 
+.I [defaults]
+Contains relations which define the default parameters
+used by
+.BR mke2fs (8).
+In general, these defaults may be overridden by a definition in the
+.B fs_types
+stanza, or by an command-line option provided by the user.
+.TP 
+.I [fs_types]
+Contains relations which define defaults that should be used for specific
+filesystem types.  The filesystem type can be specified explicitly using
+the 
+.B -T
+option to
+.BR mke2fs (8).
+.SH THE [defaults] STANZA
+The following relations are defined in the 
+.I [defaults]
+stanza.
+.TP
+.I base_features
+This relation specifies the filesystems features which are enabled in
+newly created filesystems.  It may be overridden by the
+.I base_features
+relation found in the filesystem or usage type subsection of
+the
+.I [fs_types] 
+stanza.
+.TP
+.I default_features
+This relation specifies a set of features that should be added or
+removed to the features listed in the
+.I base_features
+relation.  It may be overridden by the filesystem-specific 
+.I default_features
+in the filesystem or usage type subsection of
+.IR [fs_types] ,
+and by the 
+.B -O
+command-line option
+to 
+.BR mke2fs (8).
+.TP
+.I enable_periodic_fsck
+This boolean relation specifies whether periodic filesystem checks should be
+enforced at boot time.  If set to true, checks will be forced every
+180 days, or after a random number of mounts.  These values may
+be changed later via the
+.B -i
+and
+.B -c
+command-line options to
+.BR tune2fs (8).
+.TP
+.I force_undo
+This boolean relation, if set to a value of true, forces
+.B mke2fs
+to always try to create an undo file, even if the undo file might be
+huge and it might extend the time to create the filesystem image
+because the inode table isn't being initialized lazily.
+.TP
+.I fs_type
+This relation specifies the default filesystem type if the user does not
+specify it via the
+.B \-t
+option, or if
+.B mke2fs
+is not started using a program name of the form
+.BI mkfs. fs-type\fR.
+If both the user and the
+.B mke2fs.conf
+file does not specify a default filesystem type, mke2fs will use a
+default filesystem type of
+.IR ext3
+if a journal was requested via a command-line option, or
+.I ext2
+if not.
+.TP
+.I blocksize
+This relation specifies the default blocksize if the user does not
+specify a blocksize on the command line, and the filesystem-type
+specific section of the configuration file does not specify a blocksize.
+.TP
+.I hash_alg
+This relation specifies the default hash algorithm used for the
+new filesystems with hashed b-tree directories.  Valid algorithms
+accepted are:
+.IR legacy ,
+.IR half_md4 ,
+and
+.IR tea .
+.TP
+.I inode_ratio
+This relation specifies the default inode ratio if the user does not
+specify one on the command line, and the filesystem-type
+specific section of the configuration file does not specify a default
+inode ratio.
+.TP
+.I inode_size
+This relation specifies the default inode size if the user does not
+specify one on the command line, and the filesystem-type
+specific section of the configuration file does not specify a default
+inode size.
+.TP
+.I reserved_ratio
+This relation specifies the default percentage of filesystem blocks
+reserved for the super-user, if the user does not
+specify one on the command line, and the filesystem-type
+specific section of the configuration file does not specify a default
+reserved ratio. This value can be a floating point number.
+.TP
+.I undo_dir
+This relation specifies the directory where the undo file should be
+stored.  It can be overridden via the
+.B E2FSPROGS_UNDO_DIR
+environment variable.  If the directory location is set to the value
+.IR none ,
+.B mke2fs
+will not create an undo file.
+.SH THE [fs_types] STANZA
+Each tag in the
+.I [fs_types] 
+stanza names a filesystem type or usage type which can be specified via the
+.B \-t
+or
+.B \-T
+options to
+.BR mke2fs (8),
+respectively.
+.P
+The
+.B mke2fs
+program constructs a list of fs_types by concatenating the filesystem
+type (i.e., ext2, ext3, etc.) with the usage type list.  For most
+configuration options,
+.B mke2fs
+will look for a subsection in the
+.I [fs_types]
+stanza corresponding with each entry in the constructed list, with later
+entries overriding earlier filesystem or usage types.
+For
+example, consider the following
+.B mke2fs.conf
+fragment:
+.P
+[defaults]
+.br
+	base_features = sparse_super,filetype,resize_inode,dir_index
+.br
+	blocksize = 4096
+.br
+	inode_size = 256
+.br
+	inode_ratio = 16384
+.br
+
+.br
+[fs_types]
+.br
+	ext3 = {
+.br
+		features = has_journal
+.br
+	}
+.br
+	ext4 = {
+.br
+		features = extents,flex_bg
+.br
+		inode_size = 256
+.br
+	}
+.br
+	small = {
+.br
+		blocksize = 1024
+.br
+		inode_ratio = 4096
+.br
+	}
+.br
+	floppy = {
+.br
+		features = ^resize_inode
+.br
+		blocksize = 1024
+.br
+		inode_size = 128
+.br
+	}
+.P
+If mke2fs started with a program name of
+.BR mke2fs.ext4 ,
+then the filesystem type of ext4 will be used.  If the filesystem is
+smaller than 3 megabytes, and no usage type is specified, then
+.B mke2fs
+will use a default
+usage type of
+.IR floppy .
+This results in an fs_types list of "ext4, floppy".   Both the ext4
+subsection and the floppy subsection define an
+.I inode_size
+relation, but since the later entries in the fs_types list supersede
+earlier ones, the configuration parameter for fs_types.floppy.inode_size
+will be used, so the filesystem  will have an inode size of 128.
+.P
+The exception to this resolution is the
+.I features
+tag, which is specifies a set of changes to the features used by the
+filesystem, and which is cumulative.  So in the above example, first
+the configuration relation defaults.base_features would enable an
+initial feature set with the sparse_super, filetype, resize_inode, and
+dir_index features enabled.  Then configuration relation
+fs_types.ext4.features would enable the extents and flex_bg
+features, and finally the configuration relation
+fs_types.floppy.features would remove
+the resize_inode feature, resulting in a filesystem feature set
+consisting of the sparse_super, filetype, resize_inode, dir_index,
+extents_and flex_bg features.
+.P
+For each filesystem type, the following tags may be used in that 
+fs_type's subsection:
+.TP
+.I base_features
+This relation specifies the features which are initially enabled for this
+filesystem type.  Only one
+.I base_features
+will be used, so if there are multiple entries in the fs_types list
+whose subsections define the
+.I base_features
+relation, only the last will be used by
+.BR mke2fs (8).
+.TP
+.I features
+This relation specifies a comma-separated list of features edit
+requests which modify the feature set
+used by the newly constructed filesystem.  The syntax is the same as the
+.B -O
+command-line option to
+.BR mke2fs (8);
+that is, a feature can be prefixed by a caret ('^') symbol to disable
+a named feature.  Each
+.I feature
+relation specified in the fs_types list will be applied in the order
+found in the fs_types list.
+.TP
+.I default_features
+This relation specifies set of features which should be enabled or 
+disabled after applying the features listed in the
+.I base_features
+and
+.I features
+relations.  It may be overridden by the
+.B -O
+command-line option to
+.BR mke2fs (8).
+.TP
+.I auto_64-bit_support
+This relation is a boolean which specifies whether
+.BR mke2fs (8)
+should automatically add the 64bit feature if the number of blocks for
+the file system requires this feature to be enabled.  The resize_inode
+feature is also automatically disabled since it doesn't support 64-bit
+block numbers.
+.TP
+.I default_mntopts
+This relation specifies the set of mount options which should be enabled
+by default.  These may be changed at a later time with the
+.B -o
+command-line option to
+.BR tune2fs (8).
+.TP
+.I blocksize
+This relation specifies the default blocksize if the user does not
+specify a blocksize on the command line.
+.TP
+.I lazy_itable_init
+This boolean relation specifies whether the inode table should 
+be lazily initialized.  It only has meaning if the uninit_bg feature is
+enabled.  If lazy_itable_init is true and the uninit_bg feature is
+enabled,  the inode table will
+not fully initialized by 
+.BR mke2fs (8).
+This speeds up filesystem
+initialization noticeably, but it requires the kernel to finish
+initializing the filesystem in the background when the filesystem is
+first mounted.
+.TP
+.I inode_ratio
+This relation specifies the default inode ratio if the user does not
+specify one on the command line.
+.TP
+.I inode_size
+This relation specifies the default inode size if the user does not
+specify one on the command line.
+.TP
+.I reserved_ratio
+This relation specifies the default percentage of filesystem blocks
+reserved for the super-user, if the user does not specify one on the command
+line.
+.TP
+.I hash_alg
+This relation specifies the default hash algorithm used for the
+new filesystems with hashed b-tree directories.  Valid algorithms
+accepted are:
+.IR legacy ,
+.IR half_md4 ,
+and
+.IR tea .
+.TP
+.I flex_bg_size
+This relation specifies the number of block groups that will be packed
+together to create one large virtual block group on an ext4 filesystem.
+This improves meta-data locality and performance on meta-data heavy
+workloads.  The number of groups must be a power of 2 and may only be
+specified if the flex_bg filesystem feature is enabled.
+.TP
+.I options
+This relation specifies additional extended options which should be
+treated by
+.BR mke2fs (8)
+as if they were prepended to the argument of the
+.B -E
+option.  This can be used to configure the default extended options used
+by
+.BR mke2fs (8)
+on a per-filesystem type basis.
+.TP
+.I discard
+This boolean relation specifies whether the
+.BR mke2fs (8)
+should attempt to discard device prior to filesystem creation.
+.TP
+.I cluster_size
+This relation specifies the default cluster size if the bigalloc file
+system feature is enabled.  It can be overridden via the
+.B \-C
+command line option to
+.BR mke2fs (8)
+.SH THE [devices] STANZA
+Each tag in the
+.I [devices] 
+stanza names device name so that per-device defaults can be specified.
+.TP
+.I fs_type
+This relation specifies the default parameter for the
+.B \-t
+option, if this option isn't specified on the command line.
+.TP
+.I usage_types
+This relation specifies the default parameter for the
+.B \-T
+option, if this option isn't specified on the command line.
+.SH FILES
+.TP
+.I /etc/mke2fs.conf
+The configuration file for 
+.BR mke2fs (8).
+.SH SEE ALSO
+.BR mke2fs (8)
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/mke2fs.conf.in b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/mke2fs.conf.in
new file mode 100644
index 0000000..0871f77
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/mke2fs.conf.in
@@ -0,0 +1,53 @@
+[defaults]
+	base_features = sparse_super,filetype,resize_inode,dir_index,ext_attr
+	default_mntopts = acl,user_xattr
+	enable_periodic_fsck = 0
+	blocksize = 4096
+	inode_size = 256
+	inode_ratio = 16384
+
+[fs_types]
+	ext3 = {
+		features = has_journal
+	}
+	ext4 = {
+		features = has_journal,extent,huge_file,flex_bg,uninit_bg,dir_nlink,extra_isize
+		auto_64-bit_support = 1
+		inode_size = 256
+	}
+	ext4dev = {
+		features = has_journal,extent,huge_file,flex_bg,uninit_bg,dir_nlink,extra_isize
+		inode_size = 256
+		options = test_fs=1
+	}
+	small = {
+		blocksize = 1024
+		inode_size = 128
+		inode_ratio = 4096
+	}
+	floppy = {
+		blocksize = 1024
+		inode_size = 128
+		inode_ratio = 8192
+	}
+	big = {
+		inode_ratio = 32768
+	}
+	huge = {
+		inode_ratio = 65536
+	}
+	news = {
+		inode_ratio = 4096
+	}
+	largefile = {
+		inode_ratio = 1048576
+		blocksize = -1
+	}
+	largefile4 = {
+		inode_ratio = 4194304
+		blocksize = -1
+	}
+	hurd = {
+	     blocksize = 4096
+	     inode_size = 128
+	}
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/mklost+found.8.in b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/mklost+found.8.in
new file mode 100644
index 0000000..712740c
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/mklost+found.8.in
@@ -0,0 +1,43 @@
+.\" -*- nroff -*-
+.\" Copyright 1993, 1994, 1995 by Theodore Ts'o.  All Rights Reserved.
+.\" This file may be copied under the terms of the GNU Public License.
+.\" 
+.TH MKLOST+FOUND 8 "@E2FSPROGS_MONTH@ @E2FSPROGS_YEAR@" "E2fsprogs version @E2FSPROGS_VERSION@"
+.SH NAME
+mklost+found \- create a lost+found directory on a mounted Linux
+second extended file system
+.SH SYNOPSIS
+.B mklost+found
+.SH DESCRIPTION
+.B mklost+found
+is used to create a
+.I lost+found
+directory in the current working directory on a Linux second extended
+file system.  There is normally a
+.I lost+found
+directory in the root directory of each filesystem.
+.PP
+.B mklost+found
+pre-allocates disk blocks to the
+.I lost+found
+directory so that when
+.BR e2fsck (8)
+is being run to recover a filesystem, it does not need to allocate blocks in
+the filesystem to store a large number of unlinked files.  This ensures that
+.B e2fsck
+will not have to allocate data blocks in the filesystem during recovery.
+.SH OPTIONS
+There are none.
+.SH AUTHOR
+.B mklost+found
+has been written by Remy Card <Remy.Card@linux.org>.  It is currently being
+maintained by Theodore Ts'o <tytso@alum.mit.edu>.
+.SH BUGS
+There are none :-)
+.SH AVAILABILITY
+.B mklost+found
+is part of the e2fsprogs package and is available from 
+http://e2fsprogs.sourceforge.net.
+.SH SEE ALSO
+.BR e2fsck (8),
+.BR mke2fs (8)
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/mklost+found.c b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/mklost+found.c
new file mode 100644
index 0000000..134e824
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/mklost+found.c
@@ -0,0 +1,87 @@
+/*
+ * mklost+found.c	- Creates a directory lost+found on a mounted second
+ *			  extended file system
+ *
+ * Copyright (C) 1992, 1993  Remy Card <card@masi.ibp.fr>
+ *
+ * This file can be redistributed under the terms of the GNU General
+ * Public License
+ */
+
+/*
+ * History:
+ * 93/04/22	- Creation
+ */
+
+#include "config.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include "ext2fs/ext2_fs.h"
+#include "../version.h"
+#include "nls-enable.h"
+
+#define LPF "lost+found"
+
+int main (int argc, char ** argv)
+{
+	char name [EXT2_NAME_LEN];
+	char path [sizeof (LPF) + 1 + 256];
+	struct stat st;
+	int i, j;
+	int d;
+
+#ifdef ENABLE_NLS
+	setlocale(LC_MESSAGES, "");
+	setlocale(LC_CTYPE, "");
+	bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
+	textdomain(NLS_CAT_NAME);
+#endif
+	fprintf (stderr, "mklost+found %s (%s)\n", E2FSPROGS_VERSION,
+		 E2FSPROGS_DATE);
+	if (argc != 1) {
+		(void)argv; /* avoid unused argument warning */
+		fprintf (stderr, "%s", _("Usage: mklost+found\n"));
+		exit(1);
+	}
+	if (mkdir (LPF, 0700) == -1) {
+		perror ("mkdir");
+		exit(1);
+	}
+
+	i = 0;
+	memset (name, 'x', 246);
+	do {
+		sprintf (name + 246, "%08d", i);
+		strcpy (path, LPF);
+		strcat (path, "/");
+		strcat (path, name);
+		if ((d = creat (path, 0644)) == -1) {
+			perror ("creat");
+			exit (1);
+		}
+		i++;
+		close (d);
+		if (stat (LPF, &st) == -1) {
+			perror ("stat");
+			exit (1);
+		}
+	} while (st.st_size <= (EXT2_NDIR_BLOCKS - 1) * st.st_blksize);
+	for (j = 0; j < i; j++) {
+		sprintf (name + 246, "%08d", j);
+		strcpy (path, LPF);
+		strcat (path, "/");
+		strcat (path, name);
+		if (unlink (path) == -1) {
+			perror ("unlink");
+			exit (1);
+		}
+	}
+	exit (0);
+}
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/nls-enable.h b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/nls-enable.h
new file mode 100644
index 0000000..a91dcc1
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/nls-enable.h
@@ -0,0 +1,21 @@
+#ifdef ENABLE_NLS
+#include <libintl.h>
+#include <locale.h>
+#define _(a) (gettext (a))
+#ifdef gettext_noop
+#define N_(a) gettext_noop (a)
+#else
+#define N_(a) (a)
+#endif
+#define P_(singular, plural, n) (ngettext (singular, plural, n))
+#ifndef NLS_CAT_NAME
+#define NLS_CAT_NAME "e2fsprogs"
+#endif
+#ifndef LOCALEDIR
+#define LOCALEDIR "/usr/share/locale"
+#endif
+#else
+#define _(a) (a)
+#define N_(a) a
+#define P_(singular, plural, n) ((n) == 1 ? (singular) : (plural))
+#endif
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/partinfo.c b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/partinfo.c
new file mode 100644
index 0000000..c461e80
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/partinfo.c
@@ -0,0 +1,78 @@
+/*
+ * partinfo.c
+ *
+ * Originally written by Alain Knaff, <alknaff@innet.lu>.
+ *
+ * Cleaned up by Theodore Ts'o, <tytso@mit.edu>.
+ *
+ */
+
+#include "config.h"
+#include <sys/types.h>
+#include <fcntl.h>
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#include <stdio.h>
+#include <linux/hdreg.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "nls-enable.h"
+
+#if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE)
+#define BLKGETSIZE _IO(0x12,96)	/* return device size */
+#endif
+
+int main(int argc, char **argv)
+{
+	struct hd_geometry loc;
+	int fd, i;
+	unsigned long size;
+
+#ifdef ENABLE_NLS
+	setlocale(LC_MESSAGES, "");
+	setlocale(LC_CTYPE, "");
+	bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
+	textdomain(NLS_CAT_NAME);
+	set_com_err_gettext(gettext);
+#endif
+	if (argc == 1) {
+		fprintf(stderr, _("Usage:  %s device...\n\nPrints out the "
+			"partition information for each given device.\n"
+			"For example: %s /dev/hda\n\n"), argv[0], argv[0]);
+		exit(1);
+	}
+
+	for (i=1; i < argc; i++) {
+		fd = open(argv[i], O_RDONLY);
+
+		if (fd < 0) {
+			fprintf(stderr, _("Cannot open %s: %s"),
+				argv[i], strerror(errno));
+			continue;
+		}
+
+		if (ioctl(fd, HDIO_GETGEO, &loc) < 0) {
+			fprintf(stderr, _("Cannot get geometry of %s: %s"),
+				argv[i], strerror(errno));
+			close(fd);
+			continue;
+		}
+
+
+		if (ioctl(fd, BLKGETSIZE, &size) < 0) {
+			fprintf(stderr, _("Cannot get size of %s: %s"),
+				argv[i], strerror(errno));
+			close(fd);
+			continue;
+		}
+
+		printf(_("%s: h=%3d s=%3d c=%4d   start=%8d size=%8lu end=%8d\n"),
+		       argv[i],
+		       loc.heads, (int)loc.sectors, loc.cylinders,
+		       (int)loc.start, size, (int) loc.start + size -1);
+		close(fd);
+	}
+	exit(0);
+}
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/profile-to-c.awk b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/profile-to-c.awk
new file mode 100644
index 0000000..f964efd
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/profile-to-c.awk
@@ -0,0 +1,12 @@
+#!/bin/awk
+BEGIN {
+  printf("const char *mke2fs_default_profile = \n");
+}
+
+{
+  printf("  \"%s\\n\"\n", $0);
+}
+
+END {
+  printf(";\n", str)
+}
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/tune2fs.8.in b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/tune2fs.8.in
new file mode 100644
index 0000000..da21080
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/tune2fs.8.in
@@ -0,0 +1,696 @@
+.\" Revision 1.0 93/06/3 23:00  chk
+.\" Initial revision
+.\"
+.\"
+.TH TUNE2FS 8 "@E2FSPROGS_MONTH@ @E2FSPROGS_YEAR@" "E2fsprogs version @E2FSPROGS_VERSION@"
+.SH NAME
+tune2fs \- adjust tunable filesystem parameters on ext2/ext3/ext4 filesystems
+.SH SYNOPSIS
+.B tune2fs
+[
+.B \-l
+]
+[
+.B \-c
+.I max-mount-counts
+]
+[
+.B \-e
+.I errors-behavior
+]
+[
+.B \-f
+]
+[
+.B \-i
+.I interval-between-checks
+]
+[
+.B \-j
+]
+[
+.B \-J
+.I journal-options
+]
+[
+.B \-m
+.I reserved-blocks-percentage
+]
+[
+.B \-o
+.RI [^]mount-options [,...]
+]
+[
+.B \-r
+.I reserved-blocks-count
+]
+[
+.B \-s
+.I sparse-super-flag
+]
+[
+.B \-u
+.I user
+]
+[
+.B \-g
+.I group
+]
+[
+.B \-C
+.I mount-count
+]
+[
+.B \-E
+.I extended-options
+]
+[
+.B \-L
+.I volume-name
+]
+[
+.B \-M
+.I last-mounted-directory
+]
+[
+.B \-O 
+.RI [^] feature [,...]
+]
+[
+.B \-Q
+.I quota-options
+]
+[
+.B \-T
+.I time-last-checked
+]
+[
+.B \-U
+.I UUID
+]
+device
+.SH DESCRIPTION
+.BI tune2fs
+allows the system administrator to adjust various tunable filesystem 
+parameters on Linux ext2, ext3, or ext4 filesystems.  The current values 
+of these options can be displayed by using the
+.B -l
+option to
+.BR tune2fs (8)
+program, or by using the
+.BR dumpe2fs (8)
+program.
+.PP
+The
+.I device
+specifier can either be a filename (i.e., /dev/sda1), or a LABEL or UUID
+specifier: "\fBLABEL=\fIvolume-name\fR" or "\fBUUID=\fIuuid\fR".  (i.e.,
+LABEL=home or UUID=e40486c6-84d5-4f2f-b99c-032281799c9d).
+.SH OPTIONS
+.TP
+.BI \-c " max-mount-counts"
+Adjust the number of mounts after which the filesystem will be checked by 
+.BR e2fsck (8).  
+If
+.I max-mount-counts
+is 0 or \-1, the number of times the filesystem is mounted will be disregarded 
+by
+.BR e2fsck (8)
+and the kernel.
+.sp
+Staggering the mount-counts at which filesystems are forcibly
+checked will avoid all filesystems being checked at one time
+when using journaled filesystems.
+.sp
+You should strongly consider the consequences of disabling
+mount-count-dependent checking entirely.  Bad disk drives, cables,
+memory, and kernel bugs could all corrupt a filesystem without
+marking the filesystem dirty or in error.  If you are using
+journaling on your filesystem, your filesystem will
+.B never
+be marked dirty, so it will not normally be checked.  A
+filesystem error detected by the kernel will still force
+an fsck on the next reboot, but it may already be too late
+to prevent data loss at that point.
+.sp
+See also the
+.B \-i
+option for time-dependent checking.
+.TP
+.BI \-C " mount-count"
+Set the number of times the filesystem has been mounted.
+If set to a greater value than the max-mount-counts parameter
+set by the 
+.B \-c
+option,
+.BR e2fsck (8) 
+will check the filesystem at the next reboot.
+.TP
+.BI \-e " error-behavior"
+Change the behavior of the kernel code when errors are detected.
+In all cases, a filesystem error will cause
+.BR e2fsck (8)
+to check the filesystem on the next boot.
+.I error-behavior
+can be one of the following:
+.RS 1.2i
+.TP 1.2i
+.B continue
+Continue normal execution.
+.TP
+.B remount-ro
+Remount filesystem read-only.
+.TP
+.B panic
+Cause a kernel panic.
+.RE
+.TP
+.BI \-E " extended-options"
+Set extended options for the filesystem.  Extended options are comma
+separated, and may take an argument using the equals ('=') sign.
+The following extended options are supported:
+.RS 1.2i
+.TP
+.B clear_mmp
+Reset the MMP block (if any) back to the clean state.  Use only if
+absolutely certain the device is not currently mounted or being
+fscked, or major filesystem corruption can result.  Needs '-f'.
+.TP
+.BI mmp_update_interval= interval
+Adjust the initial MMP update interval to
+.I interval
+seconds.  Specifying an
+.I interval
+of 0 means to use the default interval.  The specified interval must
+be less than 300 seconds.  Requires that the
+.B mmp
+feature be enabled.
+.TP
+.BI stride= stride-size
+Configure the filesystem for a RAID array with
+.I stride-size
+filesystem blocks. This is the number of blocks read or written to disk
+before moving to next disk. This mostly affects placement of filesystem
+metadata like bitmaps at
+.BR mke2fs (2)
+time to avoid placing them on a single disk, which can hurt the performance.
+It may also be used by block allocator.
+.TP
+.BI stripe_width= stripe-width
+Configure the filesystem for a RAID array with
+.I stripe-width
+filesystem blocks per stripe. This is typically be stride-size * N, where
+N is the number of data disks in the RAID (e.g. RAID 5 N+1, RAID 6 N+2).
+This allows the block allocator to prevent read-modify-write of the
+parity in a RAID stripe if possible when the data is written.
+.TP
+.BI hash_alg= hash-alg
+Set the default hash algorithm used for filesystems with hashed b-tree
+directories.  Valid algorithms accepted are:
+.IR legacy ,
+.IR half_md4 ,
+and
+.IR tea .
+.TP
+.BI mount_opts= mount_option_string
+Set a set of default mount options which will be used when the file
+system is mounted.  Unlike the bitmask-based default mount options which
+can be specified with the
+.B -o
+option,
+.I mount_option_string
+is an arbitrary string with a maximum length of 63 bytes, which is
+stored in the superblock.
+.IP
+The ext4 file system driver will first apply
+the bitmask-based default options, and then parse the
+.IR mount_option_string ,
+before parsing the mount options passed from the
+.BR mount (8)
+program.
+.IP
+This superblock setting is only honored in 2.6.35+ kernels;
+and not at all by the ext2 and ext3 file system drivers.
+.TP
+.B test_fs
+Set a flag in the filesystem superblock indicating that it may be
+mounted using experimental kernel code, such as the ext4dev filesystem.
+.TP
+.B ^test_fs
+Clear the test_fs flag, indicating the filesystem should only be mounted
+using production-level filesystem code.
+.RE
+.TP
+.B \-f
+Force the tune2fs operation to complete even in the face of errors.  This 
+option is useful when removing the 
+.B has_journal
+filesystem feature from a filesystem which has 
+an external journal (or is corrupted
+such that it appears to have an external journal), but that 
+external journal is not available.   
+.sp
+.B WARNING:
+Removing an external journal from a filesystem which was not cleanly unmounted
+without first replaying the external journal can result in
+severe data loss and filesystem corruption.
+.TP
+.BI \-g " group"
+Set the group which can use the reserved filesystem blocks.
+The 
+.I group
+parameter can be a numerical gid or a group name.  If a group name is given,
+it is converted to a numerical gid before it is stored in the superblock.
+.TP
+.B \-i " \fIinterval-between-checks\fR[\fBd\fR|\fBm\fR|\fBw\fR]"
+Adjust the maximal time between two filesystem checks. 
+No suffix or
+.B d
+will interpret the number
+.I interval-between-checks
+as days,
+.B m
+as months, and
+.B w
+as weeks.  A value of zero will disable the time-dependent checking.
+.sp
+It is strongly recommended that either
+.B \-c
+(mount-count-dependent) or
+.B \-i
+(time-dependent) checking be enabled to force periodic full
+.BR e2fsck (8)
+checking of the filesystem.  Failure to do so may lead to filesystem
+corruption (due to bad disks, cables, memory, or kernel bugs) going
+unnoticed, ultimately resulting in data loss or corruption.
+.TP
+.B \-j
+Add an ext3 journal to the filesystem.  If the 
+.B \-J
+option is not specified, the default journal parameters will be used to create
+an appropriately sized journal (given the size of the filesystem) 
+stored within the filesystem.  Note that you must be using a kernel
+which has ext3 support in order to actually make use of the journal.
+.IP
+If this option is used to create a journal on a mounted filesystem, an
+immutable file,
+.BR .journal ,
+will be created in the top-level directory of the filesystem, as it is
+the only safe way to create the journal inode while the filesystem is
+mounted.  While the ext3 journal is visible, it is not safe to
+delete it, or modify it while the filesystem is mounted; for this
+reason the file is marked immutable.
+While checking unmounted filesystems, 
+.BR e2fsck (8)
+will automatically move 
+.B .journal
+files to the invisible, reserved journal inode.  For all filesystems
+except for the root filesystem,  this should happen automatically and
+naturally during the next reboot cycle.  Since the root filesystem is
+mounted read-only,
+.BR e2fsck (8)
+must be run from a rescue floppy in order to effect this transition.
+.IP
+On some distributions, such as Debian, if an initial ramdisk is used,
+the initrd scripts will automatically convert an ext2 root filesystem
+to ext3 if the  
+.BR /etc/fstab
+file specifies the ext3 filesystem for the root filesystem in order to
+avoid requiring the use of a rescue floppy to add an ext3 journal to
+the root filesystem.
+.TP
+.BR \-J " journal-options"
+Override the default ext3 journal parameters. Journal options are comma
+separated, and may take an argument using the equals ('=')  sign.
+The following journal options are supported:
+.RS 1.2i
+.TP
+.BI size= journal-size
+Create a journal stored in the filesystem of size
+.I journal-size
+megabytes.   The size of the journal must be at least 1024 filesystem blocks
+(i.e., 1MB if using 1k blocks, 4MB if using 4k blocks, etc.)
+and may be no more than 102,400 filesystem blocks.
+There must be enough free space in the filesystem to create a journal of
+that size.
+@JDEV@.TP
+@JDEV@.BI device= external-journal
+@JDEV@Attach the filesystem to the journal block device located on
+@JDEV@.IR external-journal .
+@JDEV@The external 
+@JDEV@journal must have been already created using the command
+@JDEV@.IP
+@JDEV@.B mke2fs -O journal_dev 
+@JDEV@.I external-journal
+@JDEV@.IP
+@JDEV@Note that
+@JDEV@.I external-journal
+@JDEV@must be formatted with the same block
+@JDEV@size as filesystems which will be using it.
+@JDEV@In addition, while there is support for attaching
+@JDEV@multiple filesystems to a single external journal,
+@JDEV@the Linux kernel and 
+@JDEV@.BR e2fsck (8)
+@JDEV@do not currently support shared external journals yet.
+@JDEV@.IP
+@JDEV@Instead of specifying a device name directly,
+@JDEV@.I external-journal
+@JDEV@can also be specified by either
+@JDEV@.BI LABEL= label
+@JDEV@or
+@JDEV@.BI UUID= UUID
+@JDEV@to locate the external journal by either the volume label or UUID
+@JDEV@stored in the ext2 superblock at the start of the journal.  Use
+@JDEV@.BR dumpe2fs (8)
+@JDEV@to display a journal device's volume label and UUID.  See also the
+@JDEV@.B -L
+@JDEV@option of
+@JDEV@.BR tune2fs (8).
+.RE
+@JDEV@.IP
+@JDEV@Only one of the
+@JDEV@.BR size " or " device
+@JDEV@options can be given for a filesystem.
+.TP
+.B \-l
+List the contents of the filesystem superblock, including the current
+values of the parameters that can be set via this program.
+.TP
+.BI \-L " volume-label"
+Set the volume label of the filesystem.  
+Ext2 filesystem labels can be at most 16 characters long; if
+.I volume-label 
+is longer than 16 characters, 
+.B tune2fs
+will truncate it and print a warning.  The volume label can be used
+by
+.BR mount (8),
+.BR fsck (8),
+and
+.BR /etc/fstab (5)
+(and possibly others) by specifying
+.BI LABEL= volume_label
+instead of a block special device name like
+.BR /dev/hda5 .
+.TP
+.BI \-m " reserved-blocks-percentage"
+Set the percentage of the filesystem which may only be allocated
+by privileged processes.   Reserving some number of filesystem blocks 
+for use by privileged processes is done 
+to avoid filesystem fragmentation, and to allow system
+daemons, such as 
+.BR syslogd (8),
+to continue to function correctly after non-privileged processes are 
+prevented from writing to the filesystem.  Normally, the default percentage 
+of reserved blocks is 5%.
+.TP
+.BI \-M " last-mounted-directory"
+Set the last-mounted directory for the filesystem.
+.TP
+.BR \-o " [^]\fImount-option\fR[,...]"
+Set or clear the indicated default mount options in the filesystem.
+Default mount options can be overridden by mount options specified 
+either in 
+.BR /etc/fstab (5)
+or on the command line arguments to
+.BR mount (8).   
+Older kernels may not support this feature; in particular,
+kernels which predate 2.4.20 will almost certainly ignore the
+default mount options field in the superblock.
+.IP
+More than one mount option can be cleared or set by separating
+features with commas.  Mount options prefixed with a 
+caret character ('^') will be cleared in the filesystem's superblock; 
+mount options without a prefix character or prefixed with a plus 
+character ('+') will be added to the filesystem.
+.IP
+The following mount options can be set or cleared using
+.BR tune2fs :
+.RS 1.2i
+.TP
+.B debug
+Enable debugging code for this filesystem.
+.TP
+.B bsdgroups
+Emulate BSD behavior when creating new files: they will take the group-id
+of the directory in which they were created.  The standard System V behavior
+is the default, where newly created files take on the fsgid of the current
+process, unless the directory has the setgid bit set, in which case it takes 
+the gid from the parent directory, and also gets the setgid bit set if it is 
+a directory itself.
+.TP
+.B user_xattr
+Enable user-specified extended attributes.
+.TP
+.B acl
+Enable Posix Access Control Lists.
+.TP
+.B uid16
+Disables 32-bit UIDs and GIDs.  This is for interoperability with
+older kernels which only store and expect 16-bit values.
+.TP
+.B journal_data
+When the filesystem is mounted with journalling enabled, all data
+(not just metadata) is committed into the journal prior to being written
+into the main filesystem.
+.TP
+.B journal_data_ordered
+When the filesystem is mounted with journalling enabled, all data is forced
+directly out to the main file system prior to its metadata being committed 
+to the journal.
+.TP
+.B journal_data_writeback
+When the filesystem is mounted with journalling enabled, data may be
+written into the main filesystem after its metadata has been committed
+to the journal.  This may increase throughput, however, it may allow old
+data to appear in files after a crash and journal recovery.
+.TP
+.B nobarrier
+The file system will be mounted with barrier operations in the journal
+disabled.  (This option is currently only supported by the ext4 file
+system driver in 2.6.35+ kernels.)
+.TP
+.B block_validity
+The file system will be mounted with the block_validity option enabled,
+which causes extra checks to be performed after reading or writing from
+the file system.  This prevents corrupted metadata blocks from causing
+file system damage by overwriting parts of the inode table or block
+group descriptors.  This comes at the cost of increased memory and CPU
+overhead, so it is enabled only for debugging purposes.  (This option is
+currently only supported by the ext4 file system driver in 2.6.35+
+kernels.)
+.TP
+.B discard
+The file system will be mounted with the discard mount option.  This will
+cause the file system driver to attempt to use the trim/discard feature
+of some storage devices (such as SSD's and thin-provisioned drives
+available in some enterprise storage arrays) to inform the storage
+device that blocks belonging to deleted files can be reused for other
+purposes.  (This option is currently only supported by the ext4 file
+system driver in 2.6.35+ kernels.)
+.TP
+.B nodelalloc
+The file system will be mounted with the nodelalloc mount option.  This
+will disable the delayed allocation feature.  (This option is currently
+only supported by the ext4 file system driver in 2.6.35+ kernels.)
+.RE
+.TP
+.BR \-O " [^]\fIfeature\fR[,...]"
+Set or clear the indicated filesystem features (options) in the filesystem.
+More than one filesystem feature can be cleared or set by separating
+features with commas.  Filesystem features prefixed with a 
+caret character ('^') will be cleared in the filesystem's superblock; 
+filesystem features without a prefix character or prefixed with a plus 
+character ('+') will be added to the filesystem.  For a detailed
+description of the file system features, please see the man page
+.BR ext4 (5).
+.IP
+The following filesystem features can be set or cleared using
+.BR tune2fs :
+.RS 1.2i
+.TP
+.B dir_index
+Use hashed b-trees to speed up lookups for large directories.
+.TP
+.B dir_nlink
+Allow more than 65000 subdirectories per directory.
+.TP
+.B extent
+Enable the use of extent trees to store the location of data blocks in inodes.
+.TP
+.B extra_isize
+Enable the extended inode fields used by ext4.
+.TP
+.B filetype
+Store file type information in directory entries.
+.TP
+.B flex_bg
+Allow bitmaps and inode tables for a block group to be placed
+anywhere on the storage media.  \fBTune2fs\fR will not reorganize
+the location of the inode tables and allocation bitmaps, as
+.BR mke2fs (8)
+will do when it creates a freshly formatted file system with
+.B flex_bg
+enabled.
+.TP
+.B has_journal
+Use a journal to ensure filesystem consistency even across unclean shutdowns.
+Setting the filesystem feature is equivalent to using the 
+.B \-j
+option.
+.TP
+.B huge_file
+Support files larger than 2 terabytes in size.
+.TP
+.B large_file
+Filesystem can contain files that are greater than 2GB.
+.TP
+.B resize_inode
+Reserve space so the block group descriptor table may grow in the
+future.
+.B Tune2fs 
+only supports clearing this filesystem feature.
+.TP
+.B mmp
+Enable or disable multiple mount protection (MMP) feature.
+@QUOTA_MAN_COMMENT@.TP
+@QUOTA_MAN_COMMENT@.B quota
+@QUOTA_MAN_COMMENT@Enable internal file system quota inodes.
+.TP
+.B sparse_super
+Limit the number of backup superblocks to save space on large filesystems.
+.TP
+.B uninit_bg
+Allow the kernel to initialize bitmaps and inode tables lazily, and to
+keep a high watermark for the unused inodes in a filesystem, to reduce
+.BR e2fsck (8)
+time.  This first e2fsck run after enabling this feature will take the
+full time, but subsequent e2fsck runs will take only a fraction of the
+original time, depending on how full the file system is.
+.RE
+.IP
+After setting or clearing 
+.BR sparse_super ,
+.BR uninit_bg ,
+.BR filetype ,
+or
+.B resize_inode
+filesystem features,
+.BR e2fsck (8)
+must be run on the filesystem to return the filesystem to a consistent state.
+.B Tune2fs
+will print a message requesting that the system administrator run
+.BR e2fsck (8)
+if necessary.  After setting the 
+.B dir_index
+feature, 
+.B e2fsck -D
+can be run to convert existing directories to the hashed B-tree format.
+Enabling certain filesystem features may prevent the filesystem from being
+mounted by kernels which do not support those features.  In particular, the
+.BR uninit_bg
+and
+.BR flex_bg
+features are only supported by the ext4 filesystem.
+.TP
+.BI \-p " mmp_check_interval"
+Set the desired MMP check interval in seconds. It is 5 seconds by default.
+.TP
+.BI \-r " reserved-blocks-count"
+Set the number of reserved filesystem blocks.
+.TP
+.BI \-Q " quota-options"
+Sets 'quota' feature on the superblock and works on the quota files for the
+given quota type. Quota options could be one or more of the following:
+.RS 1.2i
+.TP
+.BR [^]usrquota
+Sets/clears user quota inode in the superblock.
+.TP
+.BR [^]grpquota
+Sets/clears group quota inode in the superblock.
+.RE
+.TP
+.BI \-T " time-last-checked"
+Set the time the filesystem was last checked using
+.BR  e2fsck .
+The time is interpreted using the current (local) timezone.
+This can be useful in scripts which use a Logical Volume Manager to make
+a consistent snapshot of a filesystem, and then check the filesystem 
+during off hours to make sure it hasn't been corrupted due to 
+hardware problems, etc.  If the filesystem was clean, then this option can 
+be used to set the last checked time on the original filesystem.  The format 
+of 
+.I time-last-checked
+is the international date format, with an optional time specifier, i.e.
+YYYYMMDD[HH[MM[SS]]].   The keyword 
+.B now
+is also accepted, in which case the last checked time will be set to the 
+current time.
+.TP
+.BI \-u " user"
+Set the user who can use the reserved filesystem blocks.
+.I user
+can be a numerical uid or a user name.  If a user name is given, it 
+is converted to a numerical uid before it is stored in the superblock.
+.TP
+.BI \-U " UUID"
+Set the universally unique identifier (UUID) of the filesystem to
+.IR UUID .
+The format of the UUID is a series of hex digits separated by hyphens, 
+like this: 
+"c1b9d5a2-f162-11cf-9ece-0020afc76f16".  
+The 
+.I UUID
+parameter may also be one of the following:
+.RS 1.2i
+.TP
+.I clear
+clear the filesystem UUID
+.TP
+.I random
+generate a new randomly-generated UUID
+.TP
+.I time
+generate a new time-based UUID
+.RE
+.IP
+The UUID may be used by
+.BR mount (8),
+.BR fsck (8),
+and
+.BR /etc/fstab (5)
+(and possibly others) by specifying
+.BI UUID= uuid
+instead of a block special device name like
+.BR /dev/hda1 .
+.IP
+See
+.BR uuidgen (8)
+for more information.
+If the system does not have a good random number generator such as
+.I /dev/random
+or
+.IR /dev/urandom ,
+.B tune2fs
+will automatically use a time-based UUID instead of a randomly-generated UUID.
+.SH BUGS
+We haven't found any bugs yet.  That doesn't mean there aren't any...
+.SH AUTHOR
+.B tune2fs 
+was written by Remy Card <Remy.Card@linux.org>.  It is currently being
+maintained by Theodore Ts'o <tytso@alum.mit.edu>.
+.B tune2fs
+uses the ext2fs library written by Theodore Ts'o <tytso@mit.edu>.
+This manual page was written by Christian Kuhtz <chk@data-hh.Hanse.DE>.
+Time-dependent checking was added by Uwe Ohse <uwe@tirka.gun.de>.
+.SH AVAILABILITY
+.B tune2fs
+is part of the e2fsprogs package and is available from 
+http://e2fsprogs.sourceforge.net.
+.SH SEE ALSO
+.BR debugfs (8),
+.BR dumpe2fs (8),
+.BR e2fsck (8),
+.BR mke2fs (8),
+.BR ext4 (5)
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/tune2fs.c b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/tune2fs.c
new file mode 100644
index 0000000..568fb30
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/tune2fs.c
@@ -0,0 +1,2270 @@
+/*
+ * tune2fs.c - Change the file system parameters on an ext2 file system
+ *
+ * Copyright (C) 1992, 1993, 1994  Remy Card <card@masi.ibp.fr>
+ *                                 Laboratoire MASI, Institut Blaise Pascal
+ *                                 Universite Pierre et Marie Curie (Paris VI)
+ *
+ * Copyright 1995, 1996, 1997, 1998, 1999, 2000 by Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+/*
+ * History:
+ * 93/06/01	- Creation
+ * 93/10/31	- Added the -c option to change the maximal mount counts
+ * 93/12/14	- Added -l flag to list contents of superblock
+ *                M.J.E. Mol (marcel@duteca.et.tudelft.nl)
+ *                F.W. ten Wolde (franky@duteca.et.tudelft.nl)
+ * 93/12/29	- Added the -e option to change errors behavior
+ * 94/02/27	- Ported to use the ext2fs library
+ * 94/03/06	- Added the checks interval from Uwe Ohse (uwe@tirka.gun.de)
+ */
+
+#define _XOPEN_SOURCE 600 /* for inclusion of strptime() */
+#include "config.h"
+#include <fcntl.h>
+#include <grp.h>
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#else
+extern char *optarg;
+extern int optind;
+#endif
+#include <pwd.h>
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRINGS_H
+#include <strings.h>	/* for strcasecmp() */
+#else
+#define _BSD_SOURCE	/* for inclusion of strcasecmp() via <string.h> */
+#endif
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <libgen.h>
+#include <limits.h>
+
+#include "ext2fs/ext2_fs.h"
+#include "ext2fs/ext2fs.h"
+#include "et/com_err.h"
+#include "uuid/uuid.h"
+#include "e2p/e2p.h"
+#include "jfs_user.h"
+#include "util.h"
+#include "blkid/blkid.h"
+#include "quota/mkquota.h"
+
+#include "../version.h"
+#include "nls-enable.h"
+
+#define QOPT_ENABLE	(1)
+#define QOPT_DISABLE	(-1)
+
+extern int ask_yn(const char *string, int def);
+
+const char *program_name = "tune2fs";
+char *device_name;
+char *new_label, *new_last_mounted, *new_UUID;
+char *io_options;
+static int c_flag, C_flag, e_flag, f_flag, g_flag, i_flag, l_flag, L_flag;
+static int m_flag, M_flag, Q_flag, r_flag, s_flag = -1, u_flag, U_flag, T_flag;
+static int I_flag;
+static int clear_mmp;
+static time_t last_check_time;
+static int print_label;
+static int max_mount_count, mount_count, mount_flags;
+static unsigned long interval;
+static blk64_t reserved_blocks;
+static double reserved_ratio;
+static unsigned long resgid, resuid;
+static unsigned short errors;
+static int open_flag;
+static char *features_cmd;
+static char *mntopts_cmd;
+static int stride, stripe_width;
+static int stride_set, stripe_width_set;
+static char *extended_cmd;
+static unsigned long new_inode_size;
+static char *ext_mount_opts;
+static int usrquota, grpquota;
+
+int journal_size, journal_flags;
+char *journal_device;
+
+static struct list_head blk_move_list;
+
+struct blk_move {
+	struct list_head list;
+	blk64_t old_loc;
+	blk64_t new_loc;
+};
+
+
+static const char *please_fsck = N_("Please run e2fsck on the filesystem.\n");
+
+#ifdef CONFIG_BUILD_FINDFS
+void do_findfs(int argc, char **argv);
+#endif
+
+static void usage(void)
+{
+	fprintf(stderr,
+		_("Usage: %s [-c max_mounts_count] [-e errors_behavior] "
+		  "[-g group]\n"
+		  "\t[-i interval[d|m|w]] [-j] [-J journal_options] [-l]\n"
+		  "\t[-m reserved_blocks_percent] "
+		  "[-o [^]mount_options[,...]] [-p mmp_update_interval]\n"
+		  "\t[-r reserved_blocks_count] [-u user] [-C mount_count] "
+		  "[-L volume_label]\n"
+		  "\t[-M last_mounted_dir] [-O [^]feature[,...]]\n"
+#ifdef CONFIG_QUOTA
+		  "\t[-Q quota_options]\n"
+#endif
+		  "\t[-E extended-option[,...]] [-T last_check_time] "
+		  "[-U UUID]\n\t[ -I new_inode_size ] device\n"), program_name);
+	exit(1);
+}
+
+static __u32 ok_features[3] = {
+	/* Compat */
+	EXT3_FEATURE_COMPAT_HAS_JOURNAL |
+		EXT2_FEATURE_COMPAT_DIR_INDEX,
+	/* Incompat */
+	EXT2_FEATURE_INCOMPAT_FILETYPE |
+		EXT3_FEATURE_INCOMPAT_EXTENTS |
+		EXT4_FEATURE_INCOMPAT_FLEX_BG |
+		EXT4_FEATURE_INCOMPAT_MMP,
+	/* R/O compat */
+	EXT2_FEATURE_RO_COMPAT_LARGE_FILE |
+		EXT4_FEATURE_RO_COMPAT_HUGE_FILE|
+		EXT4_FEATURE_RO_COMPAT_DIR_NLINK|
+		EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE|
+		EXT4_FEATURE_RO_COMPAT_GDT_CSUM |
+#ifdef CONFIG_QUOTA
+		EXT4_FEATURE_RO_COMPAT_QUOTA |
+#endif
+		EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER
+};
+
+static __u32 clear_ok_features[3] = {
+	/* Compat */
+	EXT3_FEATURE_COMPAT_HAS_JOURNAL |
+		EXT2_FEATURE_COMPAT_RESIZE_INODE |
+		EXT2_FEATURE_COMPAT_DIR_INDEX,
+	/* Incompat */
+	EXT2_FEATURE_INCOMPAT_FILETYPE |
+		EXT4_FEATURE_INCOMPAT_FLEX_BG |
+		EXT4_FEATURE_INCOMPAT_MMP,
+	/* R/O compat */
+	EXT2_FEATURE_RO_COMPAT_LARGE_FILE |
+		EXT4_FEATURE_RO_COMPAT_HUGE_FILE|
+		EXT4_FEATURE_RO_COMPAT_DIR_NLINK|
+		EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE|
+#ifdef CONFIG_QUOTA
+		EXT4_FEATURE_RO_COMPAT_QUOTA |
+#endif
+		EXT4_FEATURE_RO_COMPAT_GDT_CSUM
+};
+
+/*
+ * Remove an external journal from the filesystem
+ */
+static int remove_journal_device(ext2_filsys fs)
+{
+	char		*journal_path;
+	ext2_filsys	jfs;
+	char		buf[1024];
+	journal_superblock_t	*jsb;
+	int		i, nr_users;
+	errcode_t	retval;
+	int		commit_remove_journal = 0;
+	io_manager	io_ptr;
+
+	if (f_flag)
+		commit_remove_journal = 1; /* force removal even if error */
+
+	uuid_unparse(fs->super->s_journal_uuid, buf);
+	journal_path = blkid_get_devname(NULL, "UUID", buf);
+
+	if (!journal_path) {
+		journal_path =
+			ext2fs_find_block_device(fs->super->s_journal_dev);
+		if (!journal_path)
+			goto no_valid_journal;
+	}
+
+#ifdef CONFIG_TESTIO_DEBUG
+	if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) {
+		io_ptr = test_io_manager;
+		test_io_backing_manager = unix_io_manager;
+	} else
+#endif
+		io_ptr = unix_io_manager;
+	retval = ext2fs_open(journal_path, EXT2_FLAG_RW|
+			     EXT2_FLAG_JOURNAL_DEV_OK, 0,
+			     fs->blocksize, io_ptr, &jfs);
+	if (retval) {
+		com_err(program_name, retval, "%s",
+			_("while trying to open external journal"));
+		goto no_valid_journal;
+	}
+	if (!(jfs->super->s_feature_incompat &
+	      EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
+		fprintf(stderr, _("%s is not a journal device.\n"),
+			journal_path);
+		goto no_valid_journal;
+	}
+
+	/* Get the journal superblock */
+	if ((retval = io_channel_read_blk64(jfs->io, 1, -1024, buf))) {
+		com_err(program_name, retval, "%s",
+			_("while reading journal superblock"));
+		goto no_valid_journal;
+	}
+
+	jsb = (journal_superblock_t *) buf;
+	if ((jsb->s_header.h_magic != (unsigned)ntohl(JFS_MAGIC_NUMBER)) ||
+	    (jsb->s_header.h_blocktype != (unsigned)ntohl(JFS_SUPERBLOCK_V2))) {
+		fputs(_("Journal superblock not found!\n"), stderr);
+		goto no_valid_journal;
+	}
+
+	/* Find the filesystem UUID */
+	nr_users = ntohl(jsb->s_nr_users);
+	for (i = 0; i < nr_users; i++) {
+		if (memcmp(fs->super->s_uuid, &jsb->s_users[i * 16], 16) == 0)
+			break;
+	}
+	if (i >= nr_users) {
+		fputs(_("Filesystem's UUID not found on journal device.\n"),
+		      stderr);
+		commit_remove_journal = 1;
+		goto no_valid_journal;
+	}
+	nr_users--;
+	for (i = 0; i < nr_users; i++)
+		memcpy(&jsb->s_users[i * 16], &jsb->s_users[(i + 1) * 16], 16);
+	jsb->s_nr_users = htonl(nr_users);
+
+	/* Write back the journal superblock */
+	if ((retval = io_channel_write_blk64(jfs->io, 1, -1024, buf))) {
+		com_err(program_name, retval,
+			"while writing journal superblock.");
+		goto no_valid_journal;
+	}
+
+	commit_remove_journal = 1;
+
+no_valid_journal:
+	if (commit_remove_journal == 0) {
+		fputs(_("Cannot locate journal device. It was NOT removed\n"
+			"Use -f option to remove missing journal device.\n"),
+		      stderr);
+		return 1;
+	}
+	fs->super->s_journal_dev = 0;
+	uuid_clear(fs->super->s_journal_uuid);
+	ext2fs_mark_super_dirty(fs);
+	fputs(_("Journal removed\n"), stdout);
+	free(journal_path);
+
+	return 0;
+}
+
+/* Helper function for remove_journal_inode */
+static int release_blocks_proc(ext2_filsys fs, blk64_t *blocknr,
+			       e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)),
+			       blk64_t ref_block EXT2FS_ATTR((unused)),
+			       int ref_offset EXT2FS_ATTR((unused)),
+			       void *private EXT2FS_ATTR((unused)))
+{
+	blk64_t	block;
+	int	group;
+
+	block = *blocknr;
+	ext2fs_unmark_block_bitmap2(fs->block_map, block);
+	group = ext2fs_group_of_blk2(fs, block);
+	ext2fs_bg_free_blocks_count_set(fs, group, ext2fs_bg_free_blocks_count(fs, group) + 1);
+	ext2fs_group_desc_csum_set(fs, group);
+	ext2fs_free_blocks_count_add(fs->super, EXT2FS_CLUSTER_RATIO(fs));
+	return 0;
+}
+
+/*
+ * Remove the journal inode from the filesystem
+ */
+static errcode_t remove_journal_inode(ext2_filsys fs)
+{
+	struct ext2_inode	inode;
+	errcode_t		retval;
+	ino_t			ino = fs->super->s_journal_inum;
+
+	retval = ext2fs_read_inode(fs, ino,  &inode);
+	if (retval) {
+		com_err(program_name, retval, "%s",
+			_("while reading journal inode"));
+		return retval;
+	}
+	if (ino == EXT2_JOURNAL_INO) {
+		retval = ext2fs_read_bitmaps(fs);
+		if (retval) {
+			com_err(program_name, retval, "%s",
+				_("while reading bitmaps"));
+			return retval;
+		}
+		retval = ext2fs_block_iterate3(fs, ino,
+					       BLOCK_FLAG_READ_ONLY, NULL,
+					       release_blocks_proc, NULL);
+		if (retval) {
+			com_err(program_name, retval, "%s",
+				_("while clearing journal inode"));
+			return retval;
+		}
+		memset(&inode, 0, sizeof(inode));
+		ext2fs_mark_bb_dirty(fs);
+		fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
+	} else
+		inode.i_flags &= ~EXT2_IMMUTABLE_FL;
+	retval = ext2fs_write_inode(fs, ino, &inode);
+	if (retval) {
+		com_err(program_name, retval, "%s",
+			_("while writing journal inode"));
+		return retval;
+	}
+	fs->super->s_journal_inum = 0;
+	ext2fs_mark_super_dirty(fs);
+
+	return 0;
+}
+
+/*
+ * Update the default mount options
+ */
+static int update_mntopts(ext2_filsys fs, char *mntopts)
+{
+	struct ext2_super_block *sb = fs->super;
+
+	if (e2p_edit_mntopts(mntopts, &sb->s_default_mount_opts, ~0)) {
+		fprintf(stderr, _("Invalid mount option set: %s\n"),
+			mntopts);
+		return 1;
+	}
+	ext2fs_mark_super_dirty(fs);
+
+	return 0;
+}
+
+static int check_fsck_needed(ext2_filsys fs)
+{
+	if (fs->super->s_state & EXT2_VALID_FS)
+		return 0;
+	printf("\n%s\n", _(please_fsck));
+	if (mount_flags & EXT2_MF_READONLY)
+		printf(_("(and reboot afterwards!)\n"));
+	return 1;
+}
+
+static void request_fsck_afterwards(ext2_filsys fs)
+{
+	static int requested = 0;
+
+	if (requested++)
+		return;
+	fs->super->s_state &= ~EXT2_VALID_FS;
+	printf("\n%s\n", _(please_fsck));
+	if (mount_flags & EXT2_MF_READONLY)
+		printf("%s", _("(and reboot afterwards!)\n"));
+}
+
+/*
+ * Update the feature set as provided by the user.
+ */
+static int update_feature_set(ext2_filsys fs, char *features)
+{
+	struct ext2_super_block *sb = fs->super;
+	struct ext2_group_desc *gd;
+	__u32		old_features[3];
+	dgrp_t		i;
+	int		type_err;
+	unsigned int	mask_err;
+
+#define FEATURE_ON(type, mask) (!(old_features[(type)] & (mask)) && \
+				((&sb->s_feature_compat)[(type)] & (mask)))
+#define FEATURE_OFF(type, mask) ((old_features[(type)] & (mask)) && \
+				 !((&sb->s_feature_compat)[(type)] & (mask)))
+#define FEATURE_CHANGED(type, mask) ((mask) & \
+		     (old_features[(type)] ^ (&sb->s_feature_compat)[(type)]))
+
+	old_features[E2P_FEATURE_COMPAT] = sb->s_feature_compat;
+	old_features[E2P_FEATURE_INCOMPAT] = sb->s_feature_incompat;
+	old_features[E2P_FEATURE_RO_INCOMPAT] = sb->s_feature_ro_compat;
+
+	if (e2p_edit_feature2(features, &sb->s_feature_compat,
+			      ok_features, clear_ok_features,
+			      &type_err, &mask_err)) {
+		if (!mask_err)
+			fprintf(stderr,
+				_("Invalid filesystem option set: %s\n"),
+				features);
+		else if (type_err & E2P_FEATURE_NEGATE_FLAG)
+			fprintf(stderr, _("Clearing filesystem feature '%s' "
+					  "not supported.\n"),
+				e2p_feature2string(type_err &
+						   E2P_FEATURE_TYPE_MASK,
+						   mask_err));
+		else
+			fprintf(stderr, _("Setting filesystem feature '%s' "
+					  "not supported.\n"),
+				e2p_feature2string(type_err, mask_err));
+		return 1;
+	}
+
+	if (FEATURE_OFF(E2P_FEATURE_COMPAT, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
+		if ((mount_flags & EXT2_MF_MOUNTED) &&
+		    !(mount_flags & EXT2_MF_READONLY)) {
+			fputs(_("The has_journal feature may only be "
+				"cleared when the filesystem is\n"
+				"unmounted or mounted "
+				"read-only.\n"), stderr);
+			return 1;
+		}
+		if (sb->s_feature_incompat &
+		    EXT3_FEATURE_INCOMPAT_RECOVER) {
+			fputs(_("The needs_recovery flag is set.  "
+				"Please run e2fsck before clearing\n"
+				"the has_journal flag.\n"), stderr);
+			return 1;
+		}
+		if (sb->s_journal_inum) {
+			if (remove_journal_inode(fs))
+				return 1;
+		}
+		if (sb->s_journal_dev) {
+			if (remove_journal_device(fs))
+				return 1;
+		}
+	}
+	if (FEATURE_ON(E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_MMP)) {
+		int error;
+
+		if ((mount_flags & EXT2_MF_MOUNTED) ||
+		    (mount_flags & EXT2_MF_READONLY)) {
+			fputs(_("The multiple mount protection feature can't\n"
+				"be set if the filesystem is mounted or\n"
+				"read-only.\n"), stderr);
+			return 1;
+		}
+
+		error = ext2fs_mmp_init(fs);
+		if (error) {
+			fputs(_("\nError while enabling multiple mount "
+				"protection feature."), stderr);
+			return 1;
+		}
+
+		/*
+		 * We want to update group desc with the new free blocks count
+		 */
+		fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
+
+		printf(_("Multiple mount protection has been enabled "
+			 "with update interval %ds.\n"),
+		       sb->s_mmp_update_interval);
+	}
+
+	if (FEATURE_OFF(E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_MMP)) {
+		int error;
+
+		if (mount_flags & EXT2_MF_READONLY) {
+			fputs(_("The multiple mount protection feature cannot\n"
+				"be disabled if the filesystem is readonly.\n"),
+				stderr);
+			return 1;
+		}
+
+		error = ext2fs_read_bitmaps(fs);
+		if (error) {
+			fputs(_("Error while reading bitmaps\n"), stderr);
+			return 1;
+		}
+
+		error = ext2fs_mmp_read(fs, sb->s_mmp_block, NULL);
+		if (error) {
+			struct mmp_struct *mmp_cmp = fs->mmp_cmp;
+
+			if (error == EXT2_ET_MMP_MAGIC_INVALID)
+				printf(_("Magic number in MMP block does not "
+					 "match. expected: %x, actual: %x\n"),
+					 EXT4_MMP_MAGIC, mmp_cmp->mmp_magic);
+			else
+				com_err(program_name, error, "%s",
+					_("while reading MMP block."));
+			goto mmp_error;
+		}
+
+		/* We need to force out the group descriptors as well */
+		fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
+		ext2fs_block_alloc_stats2(fs, sb->s_mmp_block, -1);
+mmp_error:
+		sb->s_mmp_block = 0;
+		sb->s_mmp_update_interval = 0;
+	}
+
+	if (FEATURE_ON(E2P_FEATURE_COMPAT, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
+		/*
+		 * If adding a journal flag, let the create journal
+		 * code below handle setting the flag and creating the
+		 * journal.  We supply a default size if necessary.
+		 */
+		if (!journal_size)
+			journal_size = -1;
+		sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
+	}
+
+	if (FEATURE_ON(E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_INDEX)) {
+		if (!sb->s_def_hash_version)
+			sb->s_def_hash_version = EXT2_HASH_HALF_MD4;
+		if (uuid_is_null((unsigned char *) sb->s_hash_seed))
+			uuid_generate((unsigned char *) sb->s_hash_seed);
+	}
+
+	if (FEATURE_OFF(E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
+		if (ext2fs_check_desc(fs)) {
+			fputs(_("Clearing the flex_bg flag would "
+				"cause the the filesystem to be\n"
+				"inconsistent.\n"), stderr);
+			return 1;
+		}
+	}
+
+	if (FEATURE_OFF(E2P_FEATURE_RO_INCOMPAT,
+			    EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) {
+		if ((mount_flags & EXT2_MF_MOUNTED) &&
+		    !(mount_flags & EXT2_MF_READONLY)) {
+			fputs(_("The huge_file feature may only be "
+				"cleared when the filesystem is\n"
+				"unmounted or mounted "
+				"read-only.\n"), stderr);
+			return 1;
+		}
+	}
+
+	if (FEATURE_ON(E2P_FEATURE_RO_INCOMPAT,
+		       EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
+		for (i = 0; i < fs->group_desc_count; i++) {
+			gd = ext2fs_group_desc(fs, fs->group_desc, i);
+			gd->bg_itable_unused = 0;
+			gd->bg_flags = EXT2_BG_INODE_ZEROED;
+			ext2fs_group_desc_csum_set(fs, i);
+		}
+		fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
+	}
+
+	if (FEATURE_OFF(E2P_FEATURE_RO_INCOMPAT,
+			EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) {
+		for (i = 0; i < fs->group_desc_count; i++) {
+			gd = ext2fs_group_desc(fs, fs->group_desc, i);
+			if ((gd->bg_flags & EXT2_BG_INODE_ZEROED) == 0) {
+				/* 
+				 * XXX what we really should do is zap
+				 * uninitialized inode tables instead.
+				 */
+				request_fsck_afterwards(fs);
+				break;
+			}
+			gd->bg_itable_unused = 0;
+			gd->bg_flags = 0;
+			gd->bg_checksum = 0;
+		}
+		fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
+	}
+
+	if (FEATURE_ON(E2P_FEATURE_RO_INCOMPAT,
+				EXT4_FEATURE_RO_COMPAT_QUOTA)) {
+		/*
+		 * Set the Q_flag here and handle the quota options in the code
+		 * below.
+		 */
+		if (!Q_flag) {
+			Q_flag = 1;
+			/* Enable both user quota and group quota by default */
+			usrquota = QOPT_ENABLE;
+			grpquota = QOPT_ENABLE;
+		}
+		sb->s_feature_ro_compat &= ~EXT4_FEATURE_RO_COMPAT_QUOTA;
+	}
+
+	if (FEATURE_OFF(E2P_FEATURE_RO_INCOMPAT,
+				EXT4_FEATURE_RO_COMPAT_QUOTA)) {
+		/*
+		 * Set the Q_flag here and handle the quota options in the code
+		 * below.
+		 */
+		if (Q_flag)
+			fputs(_("\nWarning: '^quota' option overrides '-Q'"
+				"arguments.\n"), stderr);
+		Q_flag = 1;
+		/* Disable both user quota and group quota by default */
+		usrquota = QOPT_DISABLE;
+		grpquota = QOPT_DISABLE;
+	}
+
+	if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
+	    (sb->s_feature_compat || sb->s_feature_ro_compat ||
+	     sb->s_feature_incompat))
+		ext2fs_update_dynamic_rev(fs);
+
+	if (FEATURE_CHANGED(E2P_FEATURE_RO_INCOMPAT,
+			    EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) ||
+	    FEATURE_OFF(E2P_FEATURE_RO_INCOMPAT,
+			EXT4_FEATURE_RO_COMPAT_HUGE_FILE) ||
+	    FEATURE_CHANGED(E2P_FEATURE_INCOMPAT,
+			    EXT2_FEATURE_INCOMPAT_FILETYPE) ||
+	    FEATURE_CHANGED(E2P_FEATURE_COMPAT,
+			    EXT2_FEATURE_COMPAT_RESIZE_INODE) ||
+	    FEATURE_OFF(E2P_FEATURE_RO_INCOMPAT,
+			EXT2_FEATURE_RO_COMPAT_LARGE_FILE))
+		request_fsck_afterwards(fs);
+
+	if ((old_features[E2P_FEATURE_COMPAT] != sb->s_feature_compat) ||
+	    (old_features[E2P_FEATURE_INCOMPAT] != sb->s_feature_incompat) ||
+	    (old_features[E2P_FEATURE_RO_INCOMPAT] != sb->s_feature_ro_compat))
+		ext2fs_mark_super_dirty(fs);
+
+	return 0;
+}
+
+/*
+ * Add a journal to the filesystem.
+ */
+static int add_journal(ext2_filsys fs)
+{
+	unsigned long journal_blocks;
+	errcode_t	retval;
+	ext2_filsys	jfs;
+	io_manager	io_ptr;
+
+	if (fs->super->s_feature_compat &
+	    EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
+		fputs(_("The filesystem already has a journal.\n"), stderr);
+		goto err;
+	}
+	if (journal_device) {
+		check_plausibility(journal_device);
+		check_mount(journal_device, 0, _("journal"));
+#ifdef CONFIG_TESTIO_DEBUG
+		if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) {
+			io_ptr = test_io_manager;
+			test_io_backing_manager = unix_io_manager;
+		} else
+#endif
+			io_ptr = unix_io_manager;
+		retval = ext2fs_open(journal_device, EXT2_FLAG_RW|
+				     EXT2_FLAG_JOURNAL_DEV_OK, 0,
+				     fs->blocksize, io_ptr, &jfs);
+		if (retval) {
+			com_err(program_name, retval,
+				_("\n\twhile trying to open journal on %s\n"),
+				journal_device);
+			goto err;
+		}
+		printf(_("Creating journal on device %s: "),
+		       journal_device);
+		fflush(stdout);
+
+		retval = ext2fs_add_journal_device(fs, jfs);
+		ext2fs_close(jfs);
+		if (retval) {
+			com_err(program_name, retval,
+				_("while adding filesystem to journal on %s"),
+				journal_device);
+			goto err;
+		}
+		fputs(_("done\n"), stdout);
+	} else if (journal_size) {
+		fputs(_("Creating journal inode: "), stdout);
+		fflush(stdout);
+		journal_blocks = figure_journal_size(journal_size, fs);
+
+		retval = ext2fs_add_journal_inode(fs, journal_blocks,
+						  journal_flags);
+		if (retval) {
+			fprintf(stderr, "\n");
+			com_err(program_name, retval, "%s",
+				_("\n\twhile trying to create journal file"));
+			return retval;
+		} else
+			fputs(_("done\n"), stdout);
+		/*
+		 * If the filesystem wasn't mounted, we need to force
+		 * the block group descriptors out.
+		 */
+		if ((mount_flags & EXT2_MF_MOUNTED) == 0)
+			fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
+	}
+	print_check_message(fs->super->s_max_mnt_count,
+			    fs->super->s_checkinterval);
+	return 0;
+
+err:
+	free(journal_device);
+	return 1;
+}
+
+static void handle_quota_options(ext2_filsys fs)
+{
+	quota_ctx_t qctx;
+	ext2_ino_t qf_ino;
+
+	if (!usrquota && !grpquota)
+		/* Nothing to do. */
+		return;
+
+	quota_init_context(&qctx, fs, -1);
+
+	if (usrquota == QOPT_ENABLE || grpquota == QOPT_ENABLE)
+		quota_compute_usage(qctx);
+
+	if (usrquota == QOPT_ENABLE && !fs->super->s_usr_quota_inum) {
+		if ((qf_ino = quota_file_exists(fs, USRQUOTA,
+						QFMT_VFS_V1)) > 0)
+			quota_update_limits(qctx, qf_ino, USRQUOTA);
+		quota_write_inode(qctx, USRQUOTA);
+	} else if (usrquota == QOPT_DISABLE) {
+		quota_remove_inode(fs, USRQUOTA);
+	}
+
+	if (grpquota == QOPT_ENABLE && !fs->super->s_grp_quota_inum) {
+		if ((qf_ino = quota_file_exists(fs, GRPQUOTA,
+						QFMT_VFS_V1)) > 0)
+			quota_update_limits(qctx, qf_ino, GRPQUOTA);
+		quota_write_inode(qctx, GRPQUOTA);
+	} else if (grpquota == QOPT_DISABLE) {
+		quota_remove_inode(fs, GRPQUOTA);
+	}
+
+	quota_release_context(&qctx);
+
+	if ((usrquota == QOPT_ENABLE) || (grpquota == QOPT_ENABLE)) {
+		fprintf(stderr, "%s", _("\nWarning: the quota feature is still "
+				  "under development\n"
+				  "See https://ext4.wiki.kernel.org/"
+				  "index.php/Quota for more information\n\n"));
+		fs->super->s_feature_ro_compat |= EXT4_FEATURE_RO_COMPAT_QUOTA;
+		ext2fs_mark_super_dirty(fs);
+	} else if (!fs->super->s_usr_quota_inum &&
+		   !fs->super->s_grp_quota_inum) {
+		fs->super->s_feature_ro_compat &= ~EXT4_FEATURE_RO_COMPAT_QUOTA;
+		ext2fs_mark_super_dirty(fs);
+	}
+
+	return;
+}
+
+#ifdef CONFIG_QUOTA
+static void parse_quota_opts(const char *opts)
+{
+	char	*buf, *token, *next, *p;
+	int	len;
+
+	len = strlen(opts);
+	buf = malloc(len+1);
+	if (!buf) {
+		fputs(_("Couldn't allocate memory to parse quota "
+			"options!\n"), stderr);
+		exit(1);
+	}
+	strcpy(buf, opts);
+	for (token = buf; token && *token; token = next) {
+		p = strchr(token, ',');
+		next = 0;
+		if (p) {
+			*p = 0;
+			next = p+1;
+		}
+
+		if (strcmp(token, "usrquota") == 0) {
+			usrquota = QOPT_ENABLE;
+		} else if (strcmp(token, "^usrquota") == 0) {
+			usrquota = QOPT_DISABLE;
+		} else if (strcmp(token, "grpquota") == 0) {
+			grpquota = QOPT_ENABLE;
+		} else if (strcmp(token, "^grpquota") == 0) {
+			grpquota = QOPT_DISABLE;
+		} else {
+			fputs(_("\nBad quota options specified.\n\n"
+				"Following valid quota options are available "
+				"(pass by separating with comma):\n"
+				"\t[^]usrquota\n"
+				"\t[^]grpquota\n"
+				"\n\n"), stderr);
+			free(buf);
+			exit(1);
+		}
+	}
+	free(buf);
+}
+#endif
+
+static void parse_e2label_options(int argc, char ** argv)
+{
+	if ((argc < 2) || (argc > 3)) {
+		fputs(_("Usage: e2label device [newlabel]\n"), stderr);
+		exit(1);
+	}
+	io_options = strchr(argv[1], '?');
+	if (io_options)
+		*io_options++ = 0;
+	device_name = blkid_get_devname(NULL, argv[1], NULL);
+	if (!device_name) {
+		com_err("e2label", 0, _("Unable to resolve '%s'"),
+			argv[1]);
+		exit(1);
+	}
+	open_flag = EXT2_FLAG_JOURNAL_DEV_OK;
+	if (argc == 3) {
+		open_flag |= EXT2_FLAG_RW;
+		L_flag = 1;
+		new_label = argv[2];
+	} else
+		print_label++;
+}
+
+static time_t parse_time(char *str)
+{
+	struct	tm	ts;
+
+	if (strcmp(str, "now") == 0) {
+		return (time(0));
+	}
+	memset(&ts, 0, sizeof(ts));
+#ifdef HAVE_STRPTIME
+	strptime(str, "%Y%m%d%H%M%S", &ts);
+#else
+	sscanf(str, "%4d%2d%2d%2d%2d%2d", &ts.tm_year, &ts.tm_mon,
+	       &ts.tm_mday, &ts.tm_hour, &ts.tm_min, &ts.tm_sec);
+	ts.tm_year -= 1900;
+	ts.tm_mon -= 1;
+	if (ts.tm_year < 0 || ts.tm_mon < 0 || ts.tm_mon > 11 ||
+	    ts.tm_mday < 0 || ts.tm_mday > 31 || ts.tm_hour > 23 ||
+	    ts.tm_min > 59 || ts.tm_sec > 61)
+		ts.tm_mday = 0;
+#endif
+	if (ts.tm_mday == 0) {
+		com_err(program_name, 0,
+			_("Couldn't parse date/time specifier: %s"),
+			str);
+		usage();
+	}
+	ts.tm_isdst = -1;
+	return (mktime(&ts));
+}
+
+static void parse_tune2fs_options(int argc, char **argv)
+{
+	int c;
+	char *tmp;
+	struct group *gr;
+	struct passwd *pw;
+	char optstring[100] = "c:e:fg:i:jlm:o:r:s:u:C:E:I:J:L:M:O:T:U:";
+
+#ifdef CONFIG_QUOTA
+	strcat(optstring, "Q:");
+#endif
+	open_flag = 0;
+
+	printf("tune2fs %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE);
+	while ((c = getopt(argc, argv, optstring)) != EOF)
+		switch (c) {
+		case 'c':
+			max_mount_count = strtol(optarg, &tmp, 0);
+			if (*tmp || max_mount_count > 16000) {
+				com_err(program_name, 0,
+					_("bad mounts count - %s"),
+					optarg);
+				usage();
+			}
+			if (max_mount_count == 0)
+				max_mount_count = -1;
+			c_flag = 1;
+			open_flag = EXT2_FLAG_RW;
+			break;
+		case 'C':
+			mount_count = strtoul(optarg, &tmp, 0);
+			if (*tmp || mount_count > 16000) {
+				com_err(program_name, 0,
+					_("bad mounts count - %s"),
+					optarg);
+				usage();
+			}
+			C_flag = 1;
+			open_flag = EXT2_FLAG_RW;
+			break;
+		case 'e':
+			if (strcmp(optarg, "continue") == 0)
+				errors = EXT2_ERRORS_CONTINUE;
+			else if (strcmp(optarg, "remount-ro") == 0)
+				errors = EXT2_ERRORS_RO;
+			else if (strcmp(optarg, "panic") == 0)
+				errors = EXT2_ERRORS_PANIC;
+			else {
+				com_err(program_name, 0,
+					_("bad error behavior - %s"),
+					optarg);
+				usage();
+			}
+			e_flag = 1;
+			open_flag = EXT2_FLAG_RW;
+			break;
+		case 'E':
+			extended_cmd = optarg;
+			open_flag |= EXT2_FLAG_RW;
+			break;
+		case 'f': /* Force */
+			f_flag = 1;
+			break;
+		case 'g':
+			resgid = strtoul(optarg, &tmp, 0);
+			if (*tmp) {
+				gr = getgrnam(optarg);
+				if (gr == NULL)
+					tmp = optarg;
+				else {
+					resgid = gr->gr_gid;
+					*tmp = 0;
+				}
+			}
+			if (*tmp) {
+				com_err(program_name, 0,
+					_("bad gid/group name - %s"),
+					optarg);
+				usage();
+			}
+			g_flag = 1;
+			open_flag = EXT2_FLAG_RW;
+			break;
+		case 'i':
+			interval = strtoul(optarg, &tmp, 0);
+			switch (*tmp) {
+			case 's':
+				tmp++;
+				break;
+			case '\0':
+			case 'd':
+			case 'D': /* days */
+				interval *= 86400;
+				if (*tmp != '\0')
+					tmp++;
+				break;
+			case 'm':
+			case 'M': /* months! */
+				interval *= 86400 * 30;
+				tmp++;
+				break;
+			case 'w':
+			case 'W': /* weeks */
+				interval *= 86400 * 7;
+				tmp++;
+				break;
+			}
+			if (*tmp) {
+				com_err(program_name, 0,
+					_("bad interval - %s"), optarg);
+				usage();
+			}
+			i_flag = 1;
+			open_flag = EXT2_FLAG_RW;
+			break;
+		case 'j':
+			if (!journal_size)
+				journal_size = -1;
+			open_flag = EXT2_FLAG_RW;
+			break;
+		case 'J':
+			parse_journal_opts(optarg);
+			open_flag = EXT2_FLAG_RW;
+			break;
+		case 'l':
+			l_flag = 1;
+			break;
+		case 'L':
+			new_label = optarg;
+			L_flag = 1;
+			open_flag |= EXT2_FLAG_RW |
+				EXT2_FLAG_JOURNAL_DEV_OK;
+			break;
+		case 'm':
+			reserved_ratio = strtod(optarg, &tmp);
+			if (*tmp || reserved_ratio > 50 ||
+			    reserved_ratio < 0) {
+				com_err(program_name, 0,
+					_("bad reserved block ratio - %s"),
+					optarg);
+				usage();
+			}
+			m_flag = 1;
+			open_flag = EXT2_FLAG_RW;
+			break;
+		case 'M':
+			new_last_mounted = optarg;
+			M_flag = 1;
+			open_flag = EXT2_FLAG_RW;
+			break;
+		case 'o':
+			if (mntopts_cmd) {
+				com_err(program_name, 0, "%s",
+					_("-o may only be specified once"));
+				usage();
+			}
+			mntopts_cmd = optarg;
+			open_flag = EXT2_FLAG_RW;
+			break;
+		case 'O':
+			if (features_cmd) {
+				com_err(program_name, 0, "%s",
+					_("-O may only be specified once"));
+				usage();
+			}
+			features_cmd = optarg;
+			open_flag = EXT2_FLAG_RW;
+			break;
+#ifdef CONFIG_QUOTA
+		case 'Q':
+			Q_flag = 1;
+			parse_quota_opts(optarg);
+			open_flag = EXT2_FLAG_RW;
+			break;
+#endif
+		case 'r':
+			reserved_blocks = strtoul(optarg, &tmp, 0);
+			if (*tmp) {
+				com_err(program_name, 0,
+					_("bad reserved blocks count - %s"),
+					optarg);
+				usage();
+			}
+			r_flag = 1;
+			open_flag = EXT2_FLAG_RW;
+			break;
+		case 's': /* Deprecated */
+			s_flag = atoi(optarg);
+			open_flag = EXT2_FLAG_RW;
+			break;
+		case 'T':
+			T_flag = 1;
+			last_check_time = parse_time(optarg);
+			open_flag = EXT2_FLAG_RW;
+			break;
+		case 'u':
+				resuid = strtoul(optarg, &tmp, 0);
+				if (*tmp) {
+					pw = getpwnam(optarg);
+					if (pw == NULL)
+						tmp = optarg;
+					else {
+						resuid = pw->pw_uid;
+						*tmp = 0;
+					}
+				}
+				if (*tmp) {
+					com_err(program_name, 0,
+						_("bad uid/user name - %s"),
+						optarg);
+					usage();
+				}
+				u_flag = 1;
+				open_flag = EXT2_FLAG_RW;
+				break;
+		case 'U':
+			new_UUID = optarg;
+			U_flag = 1;
+			open_flag = EXT2_FLAG_RW |
+				EXT2_FLAG_JOURNAL_DEV_OK;
+			break;
+		case 'I':
+			new_inode_size = strtoul(optarg, &tmp, 0);
+			if (*tmp) {
+				com_err(program_name, 0,
+					_("bad inode size - %s"),
+					optarg);
+				usage();
+			}
+			if (!((new_inode_size &
+			       (new_inode_size - 1)) == 0)) {
+				com_err(program_name, 0,
+					_("Inode size must be a "
+					  "power of two- %s"),
+					optarg);
+				usage();
+			}
+			open_flag = EXT2_FLAG_RW;
+			I_flag = 1;
+			break;
+		default:
+			usage();
+		}
+	if (optind < argc - 1 || optind == argc)
+		usage();
+	if (!open_flag && !l_flag)
+		usage();
+	io_options = strchr(argv[optind], '?');
+	if (io_options)
+		*io_options++ = 0;
+	device_name = blkid_get_devname(NULL, argv[optind], NULL);
+	if (!device_name) {
+		com_err(program_name, 0, _("Unable to resolve '%s'"),
+			argv[optind]);
+		exit(1);
+	}
+}
+
+#ifdef CONFIG_BUILD_FINDFS
+void do_findfs(int argc, char **argv)
+{
+	char	*dev;
+
+	if ((argc != 2) ||
+	    (strncmp(argv[1], "LABEL=", 6) && strncmp(argv[1], "UUID=", 5))) {
+		fprintf(stderr, "Usage: findfs LABEL=<label>|UUID=<uuid>\n");
+		exit(2);
+	}
+	dev = blkid_get_devname(NULL, argv[1], NULL);
+	if (!dev) {
+		com_err("findfs", 0, _("Unable to resolve '%s'"),
+			argv[1]);
+		exit(1);
+	}
+	puts(dev);
+	exit(0);
+}
+#endif
+
+static int parse_extended_opts(ext2_filsys fs, const char *opts)
+{
+	char	*buf, *token, *next, *p, *arg;
+	int	len, hash_alg;
+	int	r_usage = 0;
+
+	len = strlen(opts);
+	buf = malloc(len+1);
+	if (!buf) {
+		fprintf(stderr, "%s",
+			_("Couldn't allocate memory to parse options!\n"));
+		return 1;
+	}
+	strcpy(buf, opts);
+	for (token = buf; token && *token; token = next) {
+		p = strchr(token, ',');
+		next = 0;
+		if (p) {
+			*p = 0;
+			next = p+1;
+		}
+		arg = strchr(token, '=');
+		if (arg) {
+			*arg = 0;
+			arg++;
+		}
+		if (strcmp(token, "clear-mmp") == 0 ||
+		    strcmp(token, "clear_mmp") == 0) {
+			clear_mmp = 1;
+		} else if (strcmp(token, "mmp_update_interval") == 0) {
+			unsigned long intv;
+			if (!arg) {
+				r_usage++;
+				continue;
+			}
+			intv = strtoul(arg, &p, 0);
+			if (*p) {
+				fprintf(stderr,
+					_("Invalid mmp_update_interval: %s\n"),
+					arg);
+				r_usage++;
+				continue;
+			}
+			if (intv == 0) {
+				intv = EXT4_MMP_UPDATE_INTERVAL;
+			} else if (intv > EXT4_MMP_MAX_UPDATE_INTERVAL) {
+				fprintf(stderr,
+					_("mmp_update_interval too big: %lu\n"),
+					intv);
+				r_usage++;
+				continue;
+			}
+			printf(P_("Setting multiple mount protection update "
+				  "interval to %lu second\n",
+				  "Setting multiple mount protection update "
+				  "interval to %lu seconds\n", intv),
+			       intv);
+			fs->super->s_mmp_update_interval = intv;
+			ext2fs_mark_super_dirty(fs);
+		} else if (!strcmp(token, "test_fs")) {
+			fs->super->s_flags |= EXT2_FLAGS_TEST_FILESYS;
+			printf("Setting test filesystem flag\n");
+			ext2fs_mark_super_dirty(fs);
+		} else if (!strcmp(token, "^test_fs")) {
+			fs->super->s_flags &= ~EXT2_FLAGS_TEST_FILESYS;
+			printf("Clearing test filesystem flag\n");
+			ext2fs_mark_super_dirty(fs);
+		} else if (strcmp(token, "stride") == 0) {
+			if (!arg) {
+				r_usage++;
+				continue;
+			}
+			stride = strtoul(arg, &p, 0);
+			if (*p) {
+				fprintf(stderr,
+					_("Invalid RAID stride: %s\n"),
+					arg);
+				r_usage++;
+				continue;
+			}
+			stride_set = 1;
+		} else if (strcmp(token, "stripe-width") == 0 ||
+			   strcmp(token, "stripe_width") == 0) {
+			if (!arg) {
+				r_usage++;
+				continue;
+			}
+			stripe_width = strtoul(arg, &p, 0);
+			if (*p) {
+				fprintf(stderr,
+					_("Invalid RAID stripe-width: %s\n"),
+					arg);
+				r_usage++;
+				continue;
+			}
+			stripe_width_set = 1;
+		} else if (strcmp(token, "hash_alg") == 0 ||
+			   strcmp(token, "hash-alg") == 0) {
+			if (!arg) {
+				r_usage++;
+				continue;
+			}
+			hash_alg = e2p_string2hash(arg);
+			if (hash_alg < 0) {
+				fprintf(stderr,
+					_("Invalid hash algorithm: %s\n"),
+					arg);
+				r_usage++;
+				continue;
+			}
+			fs->super->s_def_hash_version = hash_alg;
+			printf(_("Setting default hash algorithm "
+				 "to %s (%d)\n"),
+			       arg, hash_alg);
+			ext2fs_mark_super_dirty(fs);
+		} else if (!strcmp(token, "mount_opts")) {
+			if (!arg) {
+				r_usage++;
+				continue;
+			}
+			if (strlen(arg) >= sizeof(fs->super->s_mount_opts)) {
+				fprintf(stderr,
+					"Extended mount options too long\n");
+				continue;
+			}
+			ext_mount_opts = strdup(arg);
+		} else
+			r_usage++;
+	}
+	if (r_usage) {
+		fprintf(stderr, "%s", _("\nBad options specified.\n\n"
+			"Extended options are separated by commas, "
+			"and may take an argument which\n"
+			"\tis set off by an equals ('=') sign.\n\n"
+			"Valid extended options are:\n"
+			"\tclear_mmp\n"
+			"\thash_alg=<hash algorithm>\n"
+			"\tmount_opts=<extended default mount options>\n"
+			"\tstride=<RAID per-disk chunk size in blocks>\n"
+			"\tstripe_width=<RAID stride*data disks in blocks>\n"
+			"\ttest_fs\n"
+			"\t^test_fs\n"));
+		free(buf);
+		return 1;
+	}
+	free(buf);
+
+	return 0;
+}
+
+/*
+ * Fill in the block bitmap bmap with the information regarding the
+ * blocks to be moved
+ */
+static int get_move_bitmaps(ext2_filsys fs, int new_ino_blks_per_grp,
+			    ext2fs_block_bitmap bmap)
+{
+	dgrp_t i;
+	int retval;
+	ext2_badblocks_list bb_list = 0;
+	blk64_t j, needed_blocks = 0;
+	blk64_t start_blk, end_blk;
+
+	retval = ext2fs_read_bb_inode(fs, &bb_list);
+	if (retval)
+		return retval;
+
+	for (i = 0; i < fs->group_desc_count; i++) {
+		start_blk = ext2fs_inode_table_loc(fs, i) +
+					fs->inode_blocks_per_group;
+
+		end_blk = ext2fs_inode_table_loc(fs, i) +
+					new_ino_blks_per_grp;
+
+		for (j = start_blk; j < end_blk; j++) {
+			if (ext2fs_test_block_bitmap2(fs->block_map, j)) {
+				/*
+				 * IF the block is a bad block we fail
+				 */
+				if (ext2fs_badblocks_list_test(bb_list, j)) {
+					ext2fs_badblocks_list_free(bb_list);
+					return ENOSPC;
+				}
+
+				ext2fs_mark_block_bitmap2(bmap, j);
+			} else {
+				/*
+				 * We are going to use this block for
+				 * inode table. So mark them used.
+				 */
+				ext2fs_mark_block_bitmap2(fs->block_map, j);
+			}
+		}
+		needed_blocks += end_blk - start_blk;
+	}
+
+	ext2fs_badblocks_list_free(bb_list);
+	if (needed_blocks > ext2fs_free_blocks_count(fs->super))
+		return ENOSPC;
+
+	return 0;
+}
+
+static int ext2fs_is_meta_block(ext2_filsys fs, blk64_t blk)
+{
+	dgrp_t group;
+	group = ext2fs_group_of_blk2(fs, blk);
+	if (ext2fs_block_bitmap_loc(fs, group) == blk)
+		return 1;
+	if (ext2fs_inode_bitmap_loc(fs, group) == blk)
+		return 1;
+	return 0;
+}
+
+static int ext2fs_is_block_in_group(ext2_filsys fs, dgrp_t group, blk64_t blk)
+{
+	blk64_t start_blk, end_blk;
+	start_blk = fs->super->s_first_data_block +
+			EXT2_BLOCKS_PER_GROUP(fs->super) * group;
+	/*
+	 * We cannot get new block beyond end_blk for for the last block group
+	 * so we can check with EXT2_BLOCKS_PER_GROUP even for last block group
+	 */
+	end_blk   = start_blk + EXT2_BLOCKS_PER_GROUP(fs->super);
+	if (blk >= start_blk && blk <= end_blk)
+		return 1;
+	return 0;
+}
+
+static int move_block(ext2_filsys fs, ext2fs_block_bitmap bmap)
+{
+
+	char *buf;
+	dgrp_t group = 0;
+	errcode_t retval;
+	int meta_data = 0;
+	blk64_t blk, new_blk, goal;
+	struct blk_move *bmv;
+
+	retval = ext2fs_get_mem(fs->blocksize, &buf);
+	if (retval)
+		return retval;
+
+	for (new_blk = blk = fs->super->s_first_data_block;
+	     blk < ext2fs_blocks_count(fs->super); blk++) {
+		if (!ext2fs_test_block_bitmap2(bmap, blk))
+			continue;
+
+		if (ext2fs_is_meta_block(fs, blk)) {
+			/*
+			 * If the block is mapping a fs meta data block
+			 * like group desc/block bitmap/inode bitmap. We
+			 * should find a block in the same group and fix
+			 * the respective fs metadata pointers. Otherwise
+			 * fail
+			 */
+			group = ext2fs_group_of_blk2(fs, blk);
+			goal = ext2fs_group_first_block2(fs, group);
+			meta_data = 1;
+
+		} else {
+			goal = new_blk;
+		}
+		retval = ext2fs_new_block2(fs, goal, NULL, &new_blk);
+		if (retval)
+			goto err_out;
+
+		/* new fs meta data block should be in the same group */
+		if (meta_data && !ext2fs_is_block_in_group(fs, group, new_blk)) {
+			retval = ENOSPC;
+			goto err_out;
+		}
+
+		/* Mark this block as allocated */
+		ext2fs_mark_block_bitmap2(fs->block_map, new_blk);
+
+		/* Add it to block move list */
+		retval = ext2fs_get_mem(sizeof(struct blk_move), &bmv);
+		if (retval)
+			goto err_out;
+
+		bmv->old_loc = blk;
+		bmv->new_loc = new_blk;
+
+		list_add(&(bmv->list), &blk_move_list);
+
+		retval = io_channel_read_blk64(fs->io, blk, 1, buf);
+		if (retval)
+			goto err_out;
+
+		retval = io_channel_write_blk64(fs->io, new_blk, 1, buf);
+		if (retval)
+			goto err_out;
+	}
+
+err_out:
+	ext2fs_free_mem(&buf);
+	return retval;
+}
+
+static blk64_t translate_block(blk64_t blk)
+{
+	struct list_head *entry;
+	struct blk_move *bmv;
+
+	list_for_each(entry, &blk_move_list) {
+		bmv = list_entry(entry, struct blk_move, list);
+		if (bmv->old_loc == blk)
+			return bmv->new_loc;
+	}
+
+	return 0;
+}
+
+static int process_block(ext2_filsys fs EXT2FS_ATTR((unused)),
+			 blk64_t *block_nr,
+			 e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)),
+			 blk64_t ref_block EXT2FS_ATTR((unused)),
+			 int ref_offset EXT2FS_ATTR((unused)),
+			 void *priv_data)
+{
+	int ret = 0;
+	blk64_t new_blk;
+	ext2fs_block_bitmap bmap = (ext2fs_block_bitmap) priv_data;
+
+	if (!ext2fs_test_block_bitmap2(bmap, *block_nr))
+		return 0;
+	new_blk = translate_block(*block_nr);
+	if (new_blk) {
+		*block_nr = new_blk;
+		/*
+		 * This will force the ext2fs_write_inode in the iterator
+		 */
+		ret |= BLOCK_CHANGED;
+	}
+
+	return ret;
+}
+
+static int inode_scan_and_fix(ext2_filsys fs, ext2fs_block_bitmap bmap)
+{
+	errcode_t retval = 0;
+	ext2_ino_t ino;
+	blk64_t blk;
+	char *block_buf = 0;
+	struct ext2_inode inode;
+	ext2_inode_scan	scan = NULL;
+
+	retval = ext2fs_get_mem(fs->blocksize * 3, &block_buf);
+	if (retval)
+		return retval;
+
+	retval = ext2fs_open_inode_scan(fs, 0, &scan);
+	if (retval)
+		goto err_out;
+
+	while (1) {
+		retval = ext2fs_get_next_inode(scan, &ino, &inode);
+		if (retval)
+			goto err_out;
+
+		if (!ino)
+			break;
+
+		if (inode.i_links_count == 0)
+			continue; /* inode not in use */
+
+		/* FIXME!!
+		 * If we end up modifying the journal inode
+		 * the sb->s_jnl_blocks will differ. But a
+		 * subsequent e2fsck fixes that.
+		 * Do we need to fix this ??
+		 */
+
+		if (ext2fs_file_acl_block(fs, &inode) &&
+		    ext2fs_test_block_bitmap2(bmap,
+					ext2fs_file_acl_block(fs, &inode))) {
+			blk = translate_block(ext2fs_file_acl_block(fs,
+								    &inode));
+			if (!blk)
+				continue;
+
+			ext2fs_file_acl_block_set(fs, &inode, blk);
+
+			/*
+			 * Write the inode to disk so that inode table
+			 * resizing can work
+			 */
+			retval = ext2fs_write_inode(fs, ino, &inode);
+			if (retval)
+				goto err_out;
+		}
+
+		if (!ext2fs_inode_has_valid_blocks2(fs, &inode))
+			continue;
+
+		retval = ext2fs_block_iterate3(fs, ino, 0, block_buf,
+					       process_block, bmap);
+		if (retval)
+			goto err_out;
+
+	}
+
+err_out:
+	ext2fs_free_mem(&block_buf);
+
+	return retval;
+}
+
+/*
+ * We need to scan for inode and block bitmaps that may need to be
+ * moved.  This can take place if the filesystem was formatted for
+ * RAID arrays using the mke2fs's extended option "stride".
+ */
+static int group_desc_scan_and_fix(ext2_filsys fs, ext2fs_block_bitmap bmap)
+{
+	dgrp_t i;
+	blk64_t blk, new_blk;
+
+	for (i = 0; i < fs->group_desc_count; i++) {
+		blk = ext2fs_block_bitmap_loc(fs, i);
+		if (ext2fs_test_block_bitmap2(bmap, blk)) {
+			new_blk = translate_block(blk);
+			if (!new_blk)
+				continue;
+			ext2fs_block_bitmap_loc_set(fs, i, new_blk);
+		}
+
+		blk = ext2fs_inode_bitmap_loc(fs, i);
+		if (ext2fs_test_block_bitmap2(bmap, blk)) {
+			new_blk = translate_block(blk);
+			if (!new_blk)
+				continue;
+			ext2fs_inode_bitmap_loc_set(fs, i, new_blk);
+		}
+	}
+	return 0;
+}
+
+static int expand_inode_table(ext2_filsys fs, unsigned long new_ino_size)
+{
+	dgrp_t i;
+	blk64_t blk;
+	errcode_t retval;
+	int new_ino_blks_per_grp;
+	unsigned int j;
+	char *old_itable = NULL, *new_itable = NULL;
+	char *tmp_old_itable = NULL, *tmp_new_itable = NULL;
+	unsigned long old_ino_size;
+	int old_itable_size, new_itable_size;
+
+	old_itable_size = fs->inode_blocks_per_group * fs->blocksize;
+	old_ino_size = EXT2_INODE_SIZE(fs->super);
+
+	new_ino_blks_per_grp = ext2fs_div_ceil(
+					EXT2_INODES_PER_GROUP(fs->super) *
+					new_ino_size,
+					fs->blocksize);
+
+	new_itable_size = new_ino_blks_per_grp * fs->blocksize;
+
+	retval = ext2fs_get_mem(old_itable_size, &old_itable);
+	if (retval)
+		return retval;
+
+	retval = ext2fs_get_mem(new_itable_size, &new_itable);
+	if (retval)
+		goto err_out;
+
+	tmp_old_itable = old_itable;
+	tmp_new_itable = new_itable;
+
+	for (i = 0; i < fs->group_desc_count; i++) {
+		blk = ext2fs_inode_table_loc(fs, i);
+		retval = io_channel_read_blk64(fs->io, blk,
+				fs->inode_blocks_per_group, old_itable);
+		if (retval)
+			goto err_out;
+
+		for (j = 0; j < EXT2_INODES_PER_GROUP(fs->super); j++) {
+			memcpy(new_itable, old_itable, old_ino_size);
+
+			memset(new_itable+old_ino_size, 0,
+					new_ino_size - old_ino_size);
+
+			new_itable += new_ino_size;
+			old_itable += old_ino_size;
+		}
+
+		/* reset the pointer */
+		old_itable = tmp_old_itable;
+		new_itable = tmp_new_itable;
+
+		retval = io_channel_write_blk64(fs->io, blk,
+					new_ino_blks_per_grp, new_itable);
+		if (retval)
+			goto err_out;
+	}
+
+	/* Update the meta data */
+	fs->inode_blocks_per_group = new_ino_blks_per_grp;
+	fs->super->s_inode_size = new_ino_size;
+
+err_out:
+	if (old_itable)
+		ext2fs_free_mem(&old_itable);
+
+	if (new_itable)
+		ext2fs_free_mem(&new_itable);
+
+	return retval;
+}
+
+static errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs)
+{
+	blk64_t		blk;
+	ext2_ino_t	ino;
+	unsigned int	group = 0;
+	unsigned int	count = 0;
+	int		total_free = 0;
+	int		group_free = 0;
+
+	/*
+	 * First calculate the block statistics
+	 */
+	for (blk = fs->super->s_first_data_block;
+	     blk < ext2fs_blocks_count(fs->super); blk++) {
+		if (!ext2fs_fast_test_block_bitmap2(fs->block_map, blk)) {
+			group_free++;
+			total_free++;
+		}
+		count++;
+		if ((count == fs->super->s_blocks_per_group) ||
+		    (blk == ext2fs_blocks_count(fs->super)-1)) {
+			ext2fs_bg_free_blocks_count_set(fs, group++,
+							group_free);
+			count = 0;
+			group_free = 0;
+		}
+	}
+	total_free = EXT2FS_C2B(fs, total_free);
+	ext2fs_free_blocks_count_set(fs->super, total_free);
+
+	/*
+	 * Next, calculate the inode statistics
+	 */
+	group_free = 0;
+	total_free = 0;
+	count = 0;
+	group = 0;
+
+	/* Protect loop from wrap-around if s_inodes_count maxed */
+	for (ino = 1; ino <= fs->super->s_inodes_count && ino > 0; ino++) {
+		if (!ext2fs_fast_test_inode_bitmap2(fs->inode_map, ino)) {
+			group_free++;
+			total_free++;
+		}
+		count++;
+		if ((count == fs->super->s_inodes_per_group) ||
+		    (ino == fs->super->s_inodes_count)) {
+			ext2fs_bg_free_inodes_count_set(fs, group++,
+							group_free);
+			count = 0;
+			group_free = 0;
+		}
+	}
+	fs->super->s_free_inodes_count = total_free;
+	ext2fs_mark_super_dirty(fs);
+	return 0;
+}
+
+#define list_for_each_safe(pos, pnext, head) \
+	for (pos = (head)->next, pnext = pos->next; pos != (head); \
+	     pos = pnext, pnext = pos->next)
+
+static void free_blk_move_list(void)
+{
+	struct list_head *entry, *tmp;
+	struct blk_move *bmv;
+
+	list_for_each_safe(entry, tmp, &blk_move_list) {
+		bmv = list_entry(entry, struct blk_move, list);
+		list_del(entry);
+		ext2fs_free_mem(&bmv);
+	}
+	return;
+}
+
+static int resize_inode(ext2_filsys fs, unsigned long new_size)
+{
+	errcode_t retval;
+	int new_ino_blks_per_grp;
+	ext2fs_block_bitmap bmap;
+
+	retval = ext2fs_read_inode_bitmap(fs);
+	if (retval) {
+		fputs(_("Failed to read inode bitmap\n"), stderr);
+		return retval;
+	}
+	retval = ext2fs_read_block_bitmap(fs);
+	if (retval) {
+		fputs(_("Failed to read block bitmap\n"), stderr);
+		return retval;
+	}
+	INIT_LIST_HEAD(&blk_move_list);
+
+
+	new_ino_blks_per_grp = ext2fs_div_ceil(
+					EXT2_INODES_PER_GROUP(fs->super)*
+					new_size,
+					fs->blocksize);
+
+	/* We may change the file system.
+	 * Mark the file system as invalid so that
+	 * the user is prompted to run fsck.
+	 */
+	fs->super->s_state &= ~EXT2_VALID_FS;
+
+	retval = ext2fs_allocate_block_bitmap(fs, _("blocks to be moved"),
+						&bmap);
+	if (retval) {
+		fputs(_("Failed to allocate block bitmap when "
+				"increasing inode size\n"), stderr);
+		return retval;
+	}
+	retval = get_move_bitmaps(fs, new_ino_blks_per_grp, bmap);
+	if (retval) {
+		fputs(_("Not enough space to increase inode size \n"), stderr);
+		goto err_out;
+	}
+	retval = move_block(fs, bmap);
+	if (retval) {
+		fputs(_("Failed to relocate blocks during inode resize \n"),
+		      stderr);
+		goto err_out;
+	}
+	retval = inode_scan_and_fix(fs, bmap);
+	if (retval)
+		goto err_out_undo;
+
+	retval = group_desc_scan_and_fix(fs, bmap);
+	if (retval)
+		goto err_out_undo;
+
+	retval = expand_inode_table(fs, new_size);
+	if (retval)
+		goto err_out_undo;
+
+	ext2fs_calculate_summary_stats(fs);
+
+	fs->super->s_state |= EXT2_VALID_FS;
+	/* mark super block and block bitmap as dirty */
+	ext2fs_mark_super_dirty(fs);
+	ext2fs_mark_bb_dirty(fs);
+
+err_out:
+	free_blk_move_list();
+	ext2fs_free_block_bitmap(bmap);
+
+	return retval;
+
+err_out_undo:
+	free_blk_move_list();
+	ext2fs_free_block_bitmap(bmap);
+	fputs(_("Error in resizing the inode size.\n"
+			"Run e2undo to undo the "
+			"file system changes. \n"), stderr);
+
+	return retval;
+}
+
+static int tune2fs_setup_tdb(const char *name, io_manager *io_ptr)
+{
+	errcode_t retval = 0;
+	const char *tdb_dir;
+	char *tdb_file;
+	char *dev_name, *tmp_name;
+
+#if 0 /* FIXME!! */
+	/*
+	 * Configuration via a conf file would be
+	 * nice
+	 */
+	profile_get_string(profile, "scratch_files",
+					"directory", 0, 0,
+					&tdb_dir);
+#endif
+	tmp_name = strdup(name);
+	if (!tmp_name) {
+	alloc_fn_fail:
+		com_err(program_name, ENOMEM, "%s",
+			_("Couldn't allocate memory for tdb filename\n"));
+		return ENOMEM;
+	}
+	dev_name = basename(tmp_name);
+
+	tdb_dir = getenv("E2FSPROGS_UNDO_DIR");
+	if (!tdb_dir)
+		tdb_dir = "/var/lib/e2fsprogs";
+
+	if (!strcmp(tdb_dir, "none") || (tdb_dir[0] == 0) ||
+	    access(tdb_dir, W_OK))
+		return 0;
+
+	tdb_file = malloc(strlen(tdb_dir) + 9 + strlen(dev_name) + 7 + 1);
+	if (!tdb_file)
+		goto alloc_fn_fail;
+	sprintf(tdb_file, "%s/tune2fs-%s.e2undo", tdb_dir, dev_name);
+
+	if (!access(tdb_file, F_OK)) {
+		if (unlink(tdb_file) < 0) {
+			retval = errno;
+			com_err(program_name, retval,
+				_("while trying to delete %s"),
+				tdb_file);
+			free(tdb_file);
+			return retval;
+		}
+	}
+
+	set_undo_io_backing_manager(*io_ptr);
+	*io_ptr = undo_io_manager;
+	set_undo_io_backup_file(tdb_file);
+	printf(_("To undo the tune2fs operation please run "
+		 "the command\n    e2undo %s %s\n\n"),
+		 tdb_file, name);
+	free(tdb_file);
+	free(tmp_name);
+	return retval;
+}
+
+int main(int argc, char **argv)
+{
+	errcode_t retval;
+	ext2_filsys fs;
+	struct ext2_super_block *sb;
+	io_manager io_ptr, io_ptr_orig = NULL;
+	int rc = 0;
+
+#ifdef ENABLE_NLS
+	setlocale(LC_MESSAGES, "");
+	setlocale(LC_CTYPE, "");
+	bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
+	textdomain(NLS_CAT_NAME);
+	set_com_err_gettext(gettext);
+#endif
+	if (argc && *argv)
+		program_name = *argv;
+	add_error_table(&et_ext2_error_table);
+
+#ifdef CONFIG_BUILD_FINDFS
+	if (strcmp(get_progname(argv[0]), "findfs") == 0)
+		do_findfs(argc, argv);
+#endif
+	if (strcmp(get_progname(argv[0]), "e2label") == 0)
+		parse_e2label_options(argc, argv);
+	else
+		parse_tune2fs_options(argc, argv);
+
+#ifdef CONFIG_TESTIO_DEBUG
+	if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_DEBUG")) {
+		io_ptr = test_io_manager;
+		test_io_backing_manager = unix_io_manager;
+	} else
+#endif
+		io_ptr = unix_io_manager;
+
+retry_open:
+	if ((open_flag & EXT2_FLAG_RW) == 0 || f_flag)
+		open_flag |= EXT2_FLAG_SKIP_MMP;
+
+	open_flag |= EXT2_FLAG_64BITS;
+
+	/* keep the filesystem struct around to dump MMP data */
+	open_flag |= EXT2_FLAG_NOFREE_ON_ERROR;
+
+	retval = ext2fs_open2(device_name, io_options, open_flag,
+			      0, 0, io_ptr, &fs);
+	if (retval) {
+		com_err(program_name, retval,
+			_("while trying to open %s"),
+			device_name);
+		if (retval == EXT2_ET_MMP_FSCK_ON ||
+		    retval == EXT2_ET_MMP_UNKNOWN_SEQ)
+			dump_mmp_msg(fs->mmp_buf,
+				     _("If you are sure the filesystem "
+				       "is not in use on any node, run:\n"
+				       "'tune2fs -f -E clear_mmp {device}'\n"));
+		else if (retval == EXT2_ET_MMP_FAILED)
+			dump_mmp_msg(fs->mmp_buf, NULL);
+		else if (retval == EXT2_ET_MMP_MAGIC_INVALID)
+			fprintf(stderr,
+				_("MMP block magic is bad. Try to fix it by "
+				  "running:\n'e2fsck -f %s'\n"), device_name);
+		else if (retval != EXT2_ET_MMP_FAILED)
+			fprintf(stderr, "%s",
+			     _("Couldn't find valid filesystem superblock.\n"));
+
+		ext2fs_free(fs);
+		exit(1);
+	}
+	fs->default_bitmap_type = EXT2FS_BMAP64_RBTREE;
+
+	if (I_flag && !io_ptr_orig) {
+		/*
+		 * Check the inode size is right so we can issue an
+		 * error message and bail before setting up the tdb
+		 * file.
+		 */
+		if (new_inode_size == EXT2_INODE_SIZE(fs->super)) {
+			fprintf(stderr, _("The inode size is already %lu\n"),
+				new_inode_size);
+			rc = 1;
+			goto closefs;
+		}
+		if (new_inode_size < EXT2_INODE_SIZE(fs->super)) {
+			fprintf(stderr, "%s",
+				_("Shrinking inode size is not supported\n"));
+			rc = 1;
+			goto closefs;
+		}
+		if (new_inode_size > fs->blocksize) {
+			fprintf(stderr, _("Invalid inode size %lu (max %d)\n"),
+				new_inode_size, fs->blocksize);
+			rc = 1;
+			goto closefs;
+		}
+
+		/*
+		 * If inode resize is requested use the
+		 * Undo I/O manager
+		 */
+		io_ptr_orig = io_ptr;
+		retval = tune2fs_setup_tdb(device_name, &io_ptr);
+		if (retval) {
+			rc = 1;
+			goto closefs;
+		}
+		if (io_ptr != io_ptr_orig) {
+			ext2fs_close(fs);
+			goto retry_open;
+		}
+	}
+
+	sb = fs->super;
+	fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
+
+	if (print_label) {
+		/* For e2label emulation */
+		printf("%.*s\n", (int) sizeof(sb->s_volume_name),
+		       sb->s_volume_name);
+		remove_error_table(&et_ext2_error_table);
+		goto closefs;
+	}
+
+	retval = ext2fs_check_if_mounted(device_name, &mount_flags);
+	if (retval) {
+		com_err("ext2fs_check_if_mount", retval,
+			_("while determining whether %s is mounted."),
+			device_name);
+		rc = 1;
+		goto closefs;
+	}
+	/* Normally we only need to write out the superblock */
+	fs->flags |= EXT2_FLAG_SUPER_ONLY;
+
+	if (c_flag) {
+		sb->s_max_mnt_count = max_mount_count;
+		ext2fs_mark_super_dirty(fs);
+		printf(_("Setting maximal mount count to %d\n"),
+		       max_mount_count);
+	}
+	if (C_flag) {
+		sb->s_mnt_count = mount_count;
+		ext2fs_mark_super_dirty(fs);
+		printf(_("Setting current mount count to %d\n"), mount_count);
+	}
+	if (e_flag) {
+		sb->s_errors = errors;
+		ext2fs_mark_super_dirty(fs);
+		printf(_("Setting error behavior to %d\n"), errors);
+	}
+	if (g_flag) {
+		sb->s_def_resgid = resgid;
+		ext2fs_mark_super_dirty(fs);
+		printf(_("Setting reserved blocks gid to %lu\n"), resgid);
+	}
+	if (i_flag) {
+		if (interval >= (1ULL << 32)) {
+			com_err(program_name, 0,
+				_("interval between checks is too big (%lu)"),
+				interval);
+			rc = 1;
+			goto closefs;
+		}
+		sb->s_checkinterval = interval;
+		ext2fs_mark_super_dirty(fs);
+		printf(_("Setting interval between checks to %lu seconds\n"),
+		       interval);
+	}
+	if (m_flag) {
+		ext2fs_r_blocks_count_set(sb, reserved_ratio *
+					  ext2fs_blocks_count(sb) / 100.0);
+		ext2fs_mark_super_dirty(fs);
+		printf (_("Setting reserved blocks percentage to %g%% (%llu blocks)\n"),
+			reserved_ratio, ext2fs_r_blocks_count(sb));
+	}
+	if (r_flag) {
+		if (reserved_blocks > ext2fs_blocks_count(sb)/2) {
+			com_err(program_name, 0,
+				_("reserved blocks count is too big (%llu)"),
+				reserved_blocks);
+			rc = 1;
+			goto closefs;
+		}
+		ext2fs_r_blocks_count_set(sb, reserved_blocks);
+		ext2fs_mark_super_dirty(fs);
+		printf(_("Setting reserved blocks count to %llu\n"),
+		       reserved_blocks);
+	}
+	if (s_flag == 1) {
+		if (sb->s_feature_ro_compat &
+		    EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)
+			fputs(_("\nThe filesystem already has sparse "
+				"superblocks.\n"), stderr);
+		else {
+			sb->s_feature_ro_compat |=
+				EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
+			sb->s_state &= ~EXT2_VALID_FS;
+			ext2fs_mark_super_dirty(fs);
+			printf(_("\nSparse superblock flag set.  %s"),
+			       _(please_fsck));
+		}
+	}
+	if (s_flag == 0) {
+		fputs(_("\nClearing the sparse superflag not supported.\n"),
+		      stderr);
+		rc = 1;
+		goto closefs;
+	}
+	if (T_flag) {
+		sb->s_lastcheck = last_check_time;
+		ext2fs_mark_super_dirty(fs);
+		printf(_("Setting time filesystem last checked to %s\n"),
+		       ctime(&last_check_time));
+	}
+	if (u_flag) {
+		sb->s_def_resuid = resuid;
+		ext2fs_mark_super_dirty(fs);
+		printf(_("Setting reserved blocks uid to %lu\n"), resuid);
+	}
+	if (L_flag) {
+		if (strlen(new_label) > sizeof(sb->s_volume_name))
+			fputs(_("Warning: label too long, truncating.\n"),
+			      stderr);
+		memset(sb->s_volume_name, 0, sizeof(sb->s_volume_name));
+		strncpy(sb->s_volume_name, new_label,
+			sizeof(sb->s_volume_name));
+		ext2fs_mark_super_dirty(fs);
+	}
+	if (M_flag) {
+		memset(sb->s_last_mounted, 0, sizeof(sb->s_last_mounted));
+		strncpy(sb->s_last_mounted, new_last_mounted,
+			sizeof(sb->s_last_mounted));
+		ext2fs_mark_super_dirty(fs);
+	}
+	if (mntopts_cmd) {
+		rc = update_mntopts(fs, mntopts_cmd);
+		if (rc)
+			goto closefs;
+	}
+	if (features_cmd) {
+		rc = update_feature_set(fs, features_cmd);
+		if (rc)
+			goto closefs;
+	}
+	if (extended_cmd) {
+		rc = parse_extended_opts(fs, extended_cmd);
+		if (rc)
+			goto closefs;
+		if (clear_mmp && !f_flag) {
+			fputs(_("Error in using clear_mmp. "
+				"It must be used with -f\n"),
+			      stderr);
+			goto closefs;
+		}
+	}
+	if (clear_mmp) {
+		rc = ext2fs_mmp_clear(fs);
+		goto closefs;
+	}
+	if (journal_size || journal_device) {
+		rc = add_journal(fs);
+		if (rc)
+			goto closefs;
+	}
+
+	if (Q_flag) {
+		if (mount_flags & EXT2_MF_MOUNTED) {
+			fputs(_("The quota feature may only be changed when "
+				"the filesystem is unmounted.\n"), stderr);
+			rc = 1;
+			goto closefs;
+		}
+		handle_quota_options(fs);
+	}
+
+	if (U_flag) {
+		int set_csum = 0;
+		dgrp_t i;
+
+		if (sb->s_feature_ro_compat &
+		    EXT4_FEATURE_RO_COMPAT_GDT_CSUM) {
+			/*
+			 * Changing the UUID requires rewriting all metadata,
+			 * which can race with a mounted fs.  Don't allow that.
+			 */
+			if (mount_flags & EXT2_MF_MOUNTED) {
+				fputs(_("The UUID may only be "
+					"changed when the filesystem is "
+					"unmounted.\n"), stderr);
+				exit(1);
+			}
+			if (check_fsck_needed(fs))
+				exit(1);
+
+			/*
+			 * Determine if the block group checksums are
+			 * correct so we know whether or not to set
+			 * them later on.
+			 */
+			for (i = 0; i < fs->group_desc_count; i++)
+				if (!ext2fs_group_desc_csum_verify(fs, i))
+					break;
+			if (i >= fs->group_desc_count)
+				set_csum = 1;
+		}
+		if ((strcasecmp(new_UUID, "null") == 0) ||
+		    (strcasecmp(new_UUID, "clear") == 0)) {
+			uuid_clear(sb->s_uuid);
+		} else if (strcasecmp(new_UUID, "time") == 0) {
+			uuid_generate_time(sb->s_uuid);
+		} else if (strcasecmp(new_UUID, "random") == 0) {
+			uuid_generate(sb->s_uuid);
+		} else if (uuid_parse(new_UUID, sb->s_uuid)) {
+			com_err(program_name, 0, "%s",
+				_("Invalid UUID format\n"));
+			rc = 1;
+			goto closefs;
+		}
+		if (set_csum) {
+			for (i = 0; i < fs->group_desc_count; i++)
+				ext2fs_group_desc_csum_set(fs, i);
+			fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
+		}
+		ext2fs_mark_super_dirty(fs);
+	}
+	if (I_flag) {
+		if (mount_flags & EXT2_MF_MOUNTED) {
+			fputs(_("The inode size may only be "
+				"changed when the filesystem is "
+				"unmounted.\n"), stderr);
+			rc = 1;
+			goto closefs;
+		}
+		if (fs->super->s_feature_incompat &
+		    EXT4_FEATURE_INCOMPAT_FLEX_BG) {
+			fputs(_("Changing the inode size not supported for "
+				"filesystems with the flex_bg\n"
+				"feature enabled.\n"),
+			      stderr);
+			rc = 1;
+			goto closefs;
+		}
+		/*
+		 * We want to update group descriptor also
+		 * with the new free inode count
+		 */
+		fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
+		if (resize_inode(fs, new_inode_size) == 0) {
+			printf(_("Setting inode size %lu\n"),
+							new_inode_size);
+		} else {
+			printf("%s", _("Failed to change inode size\n"));
+			rc = 1;
+			goto closefs;
+		}
+	}
+
+	if (l_flag)
+		list_super(sb);
+	if (stride_set) {
+		sb->s_raid_stride = stride;
+		ext2fs_mark_super_dirty(fs);
+		printf(_("Setting stride size to %d\n"), stride);
+	}
+	if (stripe_width_set) {
+		sb->s_raid_stripe_width = stripe_width;
+		ext2fs_mark_super_dirty(fs);
+		printf(_("Setting stripe width to %d\n"), stripe_width);
+	}
+	if (ext_mount_opts) {
+		strncpy((char *)(fs->super->s_mount_opts), ext_mount_opts,
+			sizeof(fs->super->s_mount_opts));
+		fs->super->s_mount_opts[sizeof(fs->super->s_mount_opts)-1] = 0;
+		ext2fs_mark_super_dirty(fs);
+		printf(_("Setting extended default mount options to '%s'\n"),
+		       ext_mount_opts);
+		free(ext_mount_opts);
+	}
+	free(device_name);
+	remove_error_table(&et_ext2_error_table);
+
+closefs:
+	if (rc) {
+		ext2fs_mmp_stop(fs);
+		exit(1);
+	}
+
+	return (ext2fs_close(fs) ? 1 : 0);
+}
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/util.c b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/util.c
new file mode 100644
index 0000000..40c8858
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/util.c
@@ -0,0 +1,305 @@
+/*
+ * util.c --- helper functions used by tune2fs and mke2fs
+ *
+ * Copyright 1995, 1996, 1997, 1998, 1999, 2000 by Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#define _LARGEFILE_SOURCE
+#define _LARGEFILE64_SOURCE
+
+#include "config.h"
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_LINUX_MAJOR_H
+#include <linux/major.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#include <time.h>
+
+#include "et/com_err.h"
+#include "e2p/e2p.h"
+#include "ext2fs/ext2_fs.h"
+#include "ext2fs/ext2fs.h"
+#include "nls-enable.h"
+#include "blkid/blkid.h"
+#include "util.h"
+
+#ifndef HAVE_STRCASECMP
+int strcasecmp (char *s1, char *s2)
+{
+	while (*s1 && *s2) {
+		int ch1 = *s1++, ch2 = *s2++;
+		if (isupper (ch1))
+			ch1 = tolower (ch1);
+		if (isupper (ch2))
+			ch2 = tolower (ch2);
+		if (ch1 != ch2)
+			return ch1 - ch2;
+	}
+	return *s1 ? 1 : *s2 ? -1 : 0;
+}
+#endif
+
+/*
+ * Given argv[0], return the program name.
+ */
+char *get_progname(char *argv_zero)
+{
+	char	*cp;
+
+	cp = strrchr(argv_zero, '/');
+	if (!cp )
+		return argv_zero;
+	else
+		return cp+1;
+}
+
+void proceed_question(void)
+{
+	char buf[256];
+	const char *short_yes = _("yY");
+
+	fflush(stdout);
+	fflush(stderr);
+	fputs(_("Proceed anyway? (y,n) "), stdout);
+	buf[0] = 0;
+	if (!fgets(buf, sizeof(buf), stdin) ||
+	    strchr(short_yes, buf[0]) == 0)
+		exit(1);
+}
+
+void check_plausibility(const char *device)
+{
+	int val;
+	ext2fs_struct_stat s;
+
+	val = ext2fs_stat(device, &s);
+
+	if(val == -1) {
+		fprintf(stderr, _("Could not stat %s --- %s\n"),
+			device, error_message(errno));
+		if (errno == ENOENT)
+			fputs(_("\nThe device apparently does not exist; "
+				"did you specify it correctly?\n"), stderr);
+		exit(1);
+	}
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+	/* On FreeBSD, all disk devices are character specials */
+	if (!S_ISBLK(s.st_mode) && !S_ISCHR(s.st_mode))
+#else
+	if (!S_ISBLK(s.st_mode))
+#endif
+	{
+		printf(_("%s is not a block special device.\n"), device);
+		proceed_question();
+		return;
+	}
+
+#ifdef HAVE_LINUX_MAJOR_H
+#ifndef MAJOR
+#define MAJOR(dev)	((dev)>>8)
+#define MINOR(dev)	((dev) & 0xff)
+#endif
+#ifndef SCSI_BLK_MAJOR
+#ifdef SCSI_DISK0_MAJOR
+#ifdef SCSI_DISK8_MAJOR
+#define SCSI_DISK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR || \
+  ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR) || \
+  ((M) >= SCSI_DISK8_MAJOR && (M) <= SCSI_DISK15_MAJOR))
+#else
+#define SCSI_DISK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR || \
+  ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR))
+#endif /* defined(SCSI_DISK8_MAJOR) */
+#define SCSI_BLK_MAJOR(M) (SCSI_DISK_MAJOR((M)) || (M) == SCSI_CDROM_MAJOR)
+#else
+#define SCSI_BLK_MAJOR(M)  ((M) == SCSI_DISK_MAJOR || (M) == SCSI_CDROM_MAJOR)
+#endif /* defined(SCSI_DISK0_MAJOR) */
+#endif /* defined(SCSI_BLK_MAJOR) */
+	if (((MAJOR(s.st_rdev) == HD_MAJOR &&
+	      MINOR(s.st_rdev)%64 == 0) ||
+	     (SCSI_BLK_MAJOR(MAJOR(s.st_rdev)) &&
+	      MINOR(s.st_rdev)%16 == 0))) {
+		printf(_("%s is entire device, not just one partition!\n"),
+		       device);
+		proceed_question();
+	}
+#endif
+}
+
+void check_mount(const char *device, int force, const char *type)
+{
+	errcode_t	retval;
+	int		mount_flags;
+
+	retval = ext2fs_check_if_mounted(device, &mount_flags);
+	if (retval) {
+		com_err("ext2fs_check_if_mount", retval,
+			_("while determining whether %s is mounted."),
+			device);
+		return;
+	}
+	if (mount_flags & EXT2_MF_MOUNTED) {
+		fprintf(stderr, _("%s is mounted; "), device);
+		if (force >= 2) {
+			fputs(_("mke2fs forced anyway.  Hope /etc/mtab is "
+				"incorrect.\n"), stderr);
+			return;
+		}
+	abort_mke2fs:
+		fprintf(stderr, _("will not make a %s here!\n"), type);
+		exit(1);
+	}
+	if (mount_flags & EXT2_MF_BUSY) {
+		fprintf(stderr, _("%s is apparently in use by the system; "),
+			device);
+		if (force >= 2) {
+			fputs(_("mke2fs forced anyway.\n"), stderr);
+			return;
+		}
+		goto abort_mke2fs;
+	}
+}
+
+void parse_journal_opts(const char *opts)
+{
+	char	*buf, *token, *next, *p, *arg;
+	int	len;
+	int	journal_usage = 0;
+
+	len = strlen(opts);
+	buf = malloc(len+1);
+	if (!buf) {
+		fputs(_("Couldn't allocate memory to parse journal "
+			"options!\n"), stderr);
+		exit(1);
+	}
+	strcpy(buf, opts);
+	for (token = buf; token && *token; token = next) {
+		p = strchr(token, ',');
+		next = 0;
+		if (p) {
+			*p = 0;
+			next = p+1;
+		}
+		arg = strchr(token, '=');
+		if (arg) {
+			*arg = 0;
+			arg++;
+		}
+#if 0
+		printf("Journal option=%s, argument=%s\n", token,
+		       arg ? arg : "NONE");
+#endif
+		if (strcmp(token, "device") == 0) {
+			journal_device = blkid_get_devname(NULL, arg, NULL);
+			if (!journal_device) {
+				if (arg)
+					fprintf(stderr, _("\nCould not find "
+						"journal device matching %s\n"),
+						arg);
+				journal_usage++;
+				continue;
+			}
+		} else if (strcmp(token, "size") == 0) {
+			if (!arg) {
+				journal_usage++;
+				continue;
+			}
+			journal_size = strtoul(arg, &p, 0);
+			if (*p)
+				journal_usage++;
+		} else if (strcmp(token, "v1_superblock") == 0) {
+			journal_flags |= EXT2_MKJOURNAL_V1_SUPER;
+			continue;
+		} else
+			journal_usage++;
+	}
+	if (journal_usage) {
+		fputs(_("\nBad journal options specified.\n\n"
+			"Journal options are separated by commas, "
+			"and may take an argument which\n"
+			"\tis set off by an equals ('=') sign.\n\n"
+			"Valid journal options are:\n"
+			"\tsize=<journal size in megabytes>\n"
+			"\tdevice=<journal device>\n\n"
+			"The journal size must be between "
+			"1024 and 10240000 filesystem blocks.\n\n"), stderr);
+		free(buf);
+		exit(1);
+	}
+	free(buf);
+}
+
+/*
+ * Determine the number of journal blocks to use, either via
+ * user-specified # of megabytes, or via some intelligently selected
+ * defaults.
+ *
+ * Find a reasonable journal file size (in blocks) given the number of blocks
+ * in the filesystem.  For very small filesystems, it is not reasonable to
+ * have a journal that fills more than half of the filesystem.
+ */
+unsigned int figure_journal_size(int size, ext2_filsys fs)
+{
+	int j_blocks;
+
+	j_blocks = ext2fs_default_journal_size(ext2fs_blocks_count(fs->super));
+	if (j_blocks < 0) {
+		fputs(_("\nFilesystem too small for a journal\n"), stderr);
+		return 0;
+	}
+
+	if (size > 0) {
+		j_blocks = size * 1024 / (fs->blocksize	/ 1024);
+		if (j_blocks < 1024 || j_blocks > 10240000) {
+			fprintf(stderr, _("\nThe requested journal "
+				"size is %d blocks; it must be\n"
+				"between 1024 and 10240000 blocks.  "
+				"Aborting.\n"),
+				j_blocks);
+			exit(1);
+		}
+		if ((unsigned) j_blocks > ext2fs_free_blocks_count(fs->super) / 2) {
+			fputs(_("\nJournal size too big for filesystem.\n"),
+			      stderr);
+			exit(1);
+		}
+	}
+	return j_blocks;
+}
+
+void print_check_message(int mnt, unsigned int check)
+{
+	if (mnt < 0)
+		mnt = 0;
+	if (!mnt && !check)
+		return;
+	printf(_("This filesystem will be automatically "
+		 "checked every %d mounts or\n"
+		 "%g days, whichever comes first.  "
+		 "Use tune2fs -c or -i to override.\n"),
+	       mnt, ((double) check) / (3600 * 24));
+}
+
+void dump_mmp_msg(struct mmp_struct *mmp, const char *msg)
+{
+
+	if (msg)
+		printf("MMP check failed: %s\n", msg);
+	if (mmp) {
+		time_t t = mmp->mmp_time;
+
+		printf("MMP error info: last update: %s node: %s device: %s\n",
+		       ctime(&t), mmp->mmp_nodename, mmp->mmp_bdevname);
+	}
+}
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/util.h b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/util.h
new file mode 100644
index 0000000..f872c38
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/util.h
@@ -0,0 +1,27 @@
+/*
+ * util.h --- header file defining prototypes for helper functions
+ * used by tune2fs and mke2fs
+ *
+ * Copyright 2000 by Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+extern int	 journal_size;
+extern int	 journal_flags;
+extern char	*journal_device;
+
+#ifndef HAVE_STRCASECMP
+extern int strcasecmp (char *s1, char *s2);
+#endif
+extern char *get_progname(char *argv_zero);
+extern void proceed_question(void);
+extern void check_plausibility(const char *device);
+extern void parse_journal_opts(const char *opts);
+extern void check_mount(const char *device, int force, const char *type);
+extern unsigned int figure_journal_size(int size, ext2_filsys fs);
+extern void print_check_message(int, unsigned int);
+extern void dump_mmp_msg(struct mmp_struct *mmp, const char *msg);
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/uuidd.8.in b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/uuidd.8.in
new file mode 100644
index 0000000..e65e391
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/uuidd.8.in
@@ -0,0 +1,97 @@
+.\" -*- nroff -*-
+.\" Copyright 2007 by Theodore Ts'o.  All Rights Reserved.
+.\" This file may be copied under the terms of the GNU Public License.
+.\"
+.TH UUIDD 8 "@E2FSPROGS_MONTH@ @E2FSPROGS_YEAR@" "E2fsprogs version @E2FSPROGS_VERSION@"
+.SH NAME
+uuidd \- UUID generation daemon
+.SH SYNOPSIS
+.B uuidd
+[
+.B \-d
+]
+[
+.B \-p
+.I pidfile
+]
+[
+.B \-s
+.I socketpath
+]
+[
+.B \-T
+.I timeout
+]
+
+.B uuidd
+[
+.B \-r
+|
+.B \-t
+]
+[
+.B \-n
+.I number
+]
+[
+.B \-s
+.I socketpath
+]
+
+.B uuidd \-k
+.SH DESCRIPTION
+The
+.B uuidd
+daemon is used by the UUID library to generate
+universally unique identifiers (UUIDs), especially time-based UUID's
+in a secure and guaranteed-unique fashion, even in the face of large
+numbers of threads trying to grab UUID's running on different CPU's.
+.SH OPTIONS
+.TP
+.B \-d
+Run
+.B uuidd
+in debugging mode.  This prevents uuidd from running as a daemon.
+.TP
+.B \-k
+If a currently uuidd daemon is running, kill it.
+.TP
+.BI \-n " number"
+When issuing a test request to a running uuidd, request a bulk response
+of
+.I number
+UUID's.
+.TP
+.BI \-p  " pidfile"
+Specify the pathname where the pid file should be written.  By default,
+the pid file is written to /var/lib/libuuid/uuidd.pid.
+.TP
+.BI \-s " socketpath"
+Specify the pathname used for the unix-domain socket used by uuidd.  By
+default, the pathname used is /var/lib/libuuid/request.  This is primarily
+for debugging purposes, since the pathname is hard-coded in the libuuid
+library.
+.TP
+.B \-r
+Test uuidd by trying to connect to a running uuidd daemon and
+request it to return a random-based UUID.
+.TP
+.B \-t
+Test uuidd by trying to connect to a running uuidd daemon and
+request it to return a time-based UUID.
+.TP
+.BI \-T " timeout"
+Specify a timeout for uuidd.  If specified, then uuidd will exit after
+.I timeout
+seconds of inactivity.
+.SH AUTHOR
+The
+.B uuidd
+daemon  was written by Theodore Ts'o <tytso@mit.edu>.
+.SH AVAILABILITY
+.B uuidd
+is part of libuuid from the e2fsprogs package and is available from
+http://e2fsprogs.sourceforge.net.
+.SH "SEE ALSO"
+.BR libuuid (3),
+.BR uuidgen (1)
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/uuidd.c b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/uuidd.c
new file mode 100644
index 0000000..5a53138
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/uuidd.c
@@ -0,0 +1,599 @@
+/*
+ * uuidd.c --- UUID-generation daemon
+ *
+ * Copyright (C) 2007  Theodore Ts'o
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#define _GNU_SOURCE /* for setres[ug]id() */
+
+#include "config.h"
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <unistd.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <string.h>
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#else
+extern int getopt(int argc, char * const argv[], const char *optstring);
+extern char *optarg;
+extern int optind;
+#endif
+#include "uuid/uuid.h"
+#include "uuid/uuidd.h"
+#include "nls-enable.h"
+
+#ifdef __GNUC__
+#define CODE_ATTR(x) __attribute__(x)
+#else
+#define CODE_ATTR(x)
+#endif
+
+static void usage(const char *progname)
+{
+	fprintf(stderr, _("Usage: %s [-d] [-p pidfile] [-s socketpath] "
+			  "[-T timeout]\n"), progname);
+	fprintf(stderr, _("       %s [-r|t] [-n num] [-s socketpath]\n"),
+		progname);
+	fprintf(stderr, _("       %s -k\n"), progname);
+	exit(1);
+}
+
+static void die(const char *msg)
+{
+	perror(msg);
+	exit(1);
+}
+
+static void create_daemon(void)
+{
+	pid_t pid;
+	uid_t euid;
+
+	pid = fork();
+	if (pid == -1) {
+		perror("fork");
+		exit(1);
+	} else if (pid != 0) {
+	    exit(0);
+	}
+
+	close(0);
+	close(1);
+	close(2);
+	open("/dev/null", O_RDWR);
+	open("/dev/null", O_RDWR);
+	open("/dev/null", O_RDWR);
+
+	if (chdir("/")) {}	/* Silence warn_unused_result warning */
+	(void) setsid();
+	euid = geteuid();
+	if (setreuid(euid, euid) < 0)
+		die("setreuid");
+}
+
+static ssize_t read_all(int fd, char *buf, size_t count)
+{
+	ssize_t ret;
+	ssize_t c = 0;
+	int tries = 0;
+
+	memset(buf, 0, count);
+	while (count > 0) {
+		ret = read(fd, buf, count);
+		if (ret <= 0) {
+			if ((errno == EAGAIN || errno == EINTR || ret == 0) &&
+			    (tries++ < 5))
+				continue;
+			return c ? c : -1;
+		}
+		if (ret > 0)
+			tries = 0;
+		count -= ret;
+		buf += ret;
+		c += ret;
+	}
+	return c;
+}
+
+static int write_all(int fd, char *buf, size_t count)
+{
+	ssize_t ret;
+	int c = 0;
+
+	while (count > 0) {
+		ret = write(fd, buf, count);
+		if (ret < 0) {
+			if ((errno == EAGAIN) || (errno == EINTR))
+				continue;
+			return -1;
+		}
+		count -= ret;
+		buf += ret;
+		c += ret;
+	}
+	return c;
+}
+
+static const char *cleanup_pidfile, *cleanup_socket;
+
+static void terminate_intr(int signo CODE_ATTR((unused)))
+{
+	(void) unlink(cleanup_pidfile);
+	if (cleanup_socket)
+		(void) unlink(cleanup_socket);
+	exit(0);
+}
+
+static int call_daemon(const char *socket_path, int op, char *buf,
+		       int buflen, int *num, const char **err_context)
+{
+	char op_buf[8];
+	int op_len;
+	int s;
+	ssize_t ret;
+	int32_t reply_len = 0;
+	struct sockaddr_un srv_addr;
+
+	if (((op == 4) || (op == 5)) && !num) {
+		if (err_context)
+			*err_context = _("bad arguments");
+		errno = EINVAL;
+		return -1;
+	}
+
+	if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
+		if (err_context)
+			*err_context = _("socket");
+		return -1;
+	}
+
+	srv_addr.sun_family = AF_UNIX;
+	strncpy(srv_addr.sun_path, socket_path, sizeof(srv_addr.sun_path));
+	srv_addr.sun_path[sizeof(srv_addr.sun_path)-1] = '\0';
+
+	if (connect(s, (const struct sockaddr *) &srv_addr,
+		    sizeof(struct sockaddr_un)) < 0) {
+		if (err_context)
+			*err_context = _("connect");
+		close(s);
+		return -1;
+	}
+
+	if (op == 5) {
+		if ((*num)*16 > buflen-4)
+			*num = (buflen-4) / 16;
+	}
+	op_buf[0] = op;
+	op_len = 1;
+	if ((op == 4) || (op == 5)) {
+		memcpy(op_buf+1, num, sizeof(int));
+		op_len += sizeof(int);
+	}
+
+	ret = write_all(s, op_buf, op_len);
+	if (ret < op_len) {
+		if (err_context)
+			*err_context = _("write");
+		close(s);
+		return -1;
+	}
+
+	ret = read_all(s, (char *) &reply_len, sizeof(reply_len));
+	if (ret < 0) {
+		if (err_context)
+			*err_context = _("read count");
+		close(s);
+		return -1;
+	}
+	if (reply_len < 0 || reply_len > buflen) {
+		if (err_context)
+			*err_context = _("bad response length");
+		close(s);
+		return -1;
+	}
+	ret = read_all(s, (char *) buf, reply_len);
+
+	if ((ret > 0) && (op == 4)) {
+		if (reply_len >= (int) (16+sizeof(int)))
+			memcpy(buf+16, num, sizeof(int));
+		else
+			*num = -1;
+	}
+	if ((ret > 0) && (op == 5)) {
+		if (*num >= (int) sizeof(int))
+			memcpy(buf, num, sizeof(int));
+		else
+			*num = -1;
+	}
+
+	close(s);
+
+	return ret;
+}
+
+static void server_loop(const char *socket_path, const char *pidfile_path,
+			int debug, int timeout, int quiet)
+{
+	struct sockaddr_un	my_addr, from_addr;
+	struct flock		fl;
+	socklen_t		fromlen;
+	int32_t			reply_len = 0;
+	uuid_t			uu;
+	mode_t			save_umask;
+	char			reply_buf[1024], *cp;
+	char			op, str[37];
+	int			i, s, ns, len, num;
+	int			fd_pidfile, ret;
+
+	fd_pidfile = open(pidfile_path, O_CREAT | O_RDWR, 0664);
+	if (fd_pidfile < 0) {
+		if (!quiet)
+			fprintf(stderr, "Failed to open/create %s: %s\n",
+				pidfile_path, strerror(errno));
+		exit(1);
+	}
+	cleanup_pidfile = pidfile_path;
+	cleanup_socket = 0;
+	signal(SIGALRM, terminate_intr);
+	alarm(30);
+ 	fl.l_type = F_WRLCK;
+ 	fl.l_whence = SEEK_SET;
+ 	fl.l_start = 0;
+ 	fl.l_len = 0;
+ 	fl.l_pid = 0;
+ 	while (fcntl(fd_pidfile, F_SETLKW, &fl) < 0) {
+		if ((errno == EAGAIN) || (errno == EINTR))
+			continue;
+		if (!quiet)
+			fprintf(stderr, "Failed to lock %s: %s\n",
+				pidfile_path, strerror(errno));
+		exit(1);
+	}
+	ret = call_daemon(socket_path, 0, reply_buf, sizeof(reply_buf), 0, 0);
+	if (ret > 0) {
+		if (!quiet)
+			printf(_("uuidd daemon already running at pid %s\n"),
+			       reply_buf);
+		exit(1);
+	}
+	alarm(0);
+
+	if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
+		if (!quiet)
+			fprintf(stderr, _("Couldn't create unix stream "
+					  "socket: %s"), strerror(errno));
+		exit(1);
+	}
+
+	/*
+	 * Make sure the socket isn't using fd numbers 0-2 to avoid it
+	 * getting closed by create_daemon()
+	 */
+	while (!debug && s <= 2) {
+		s = dup(s);
+		if (s < 0) {
+			perror("dup");
+			exit(1);
+		}
+	}
+
+	/*
+	 * Create the address we will be binding to.
+	 */
+	my_addr.sun_family = AF_UNIX;
+	strncpy(my_addr.sun_path, socket_path, sizeof(my_addr.sun_path));
+	my_addr.sun_path[sizeof(my_addr.sun_path)-1] = '\0';
+	(void) unlink(socket_path);
+	save_umask = umask(0);
+	if (bind(s, (const struct sockaddr *) &my_addr,
+		 sizeof(struct sockaddr_un)) < 0) {
+		if (!quiet)
+			fprintf(stderr,
+				_("Couldn't bind unix socket %s: %s\n"),
+				socket_path, strerror(errno));
+		exit(1);
+	}
+	(void) umask(save_umask);
+
+	if (listen(s, 5) < 0) {
+		if (!quiet)
+			fprintf(stderr, _("Couldn't listen on unix "
+					  "socket %s: %s\n"), socket_path,
+				strerror(errno));
+		exit(1);
+	}
+
+	cleanup_socket = socket_path;
+	if (!debug)
+		create_daemon();
+	signal(SIGHUP, terminate_intr);
+	signal(SIGINT, terminate_intr);
+	signal(SIGTERM, terminate_intr);
+	signal(SIGALRM, terminate_intr);
+	signal(SIGPIPE, SIG_IGN);
+
+	sprintf(reply_buf, "%8d\n", getpid());
+	if (ftruncate(fd_pidfile, 0)) {} /* Silence warn_unused_result */
+	write_all(fd_pidfile, reply_buf, strlen(reply_buf));
+	if (fd_pidfile > 1)
+		close(fd_pidfile); /* Unlock the pid file */
+
+	while (1) {
+		fromlen = sizeof(from_addr);
+		if (timeout > 0)
+			alarm(timeout);
+		ns = accept(s, (struct sockaddr *) &from_addr, &fromlen);
+		alarm(0);
+		if (ns < 0) {
+			if ((errno == EAGAIN) || (errno == EINTR))
+				continue;
+			perror("accept");
+			exit(1);
+		}
+		len = read(ns, &op, 1);
+		if (len != 1) {
+			if (len < 0)
+				perror("read");
+			else
+				printf(_("Error reading from client, "
+					 "len = %d\n"), len);
+			goto shutdown_socket;
+		}
+		if ((op == 4) || (op == 5)) {
+			if (read_all(ns, (char *) &num, sizeof(num)) != 4)
+				goto shutdown_socket;
+			if (debug)
+				printf(_("operation %d, incoming num = %d\n"),
+				       op, num);
+		} else if (debug)
+			printf("operation %d\n", op);
+
+		switch(op) {
+		case UUIDD_OP_GETPID:
+			sprintf(reply_buf, "%d", getpid());
+			reply_len = strlen(reply_buf)+1;
+			break;
+		case UUIDD_OP_GET_MAXOP:
+			sprintf(reply_buf, "%d", UUIDD_MAX_OP);
+			reply_len = strlen(reply_buf)+1;
+			break;
+		case UUIDD_OP_TIME_UUID:
+			num = 1;
+			uuid__generate_time(uu, &num);
+			if (debug) {
+				uuid_unparse(uu, str);
+				printf(_("Generated time UUID: %s\n"), str);
+			}
+			memcpy(reply_buf, uu, sizeof(uu));
+			reply_len = sizeof(uu);
+			break;
+		case UUIDD_OP_RANDOM_UUID:
+			num = 1;
+			uuid__generate_random(uu, &num);
+			if (debug) {
+				uuid_unparse(uu, str);
+				printf(_("Generated random UUID: %s\n"), str);
+			}
+			memcpy(reply_buf, uu, sizeof(uu));
+			reply_len = sizeof(uu);
+			break;
+		case UUIDD_OP_BULK_TIME_UUID:
+			uuid__generate_time(uu, &num);
+			if (debug) {
+				uuid_unparse(uu, str);
+				printf(P_("Generated time UUID %s and "
+					  "subsequent UUID\n",
+					  "Generated time UUID %s and %d "
+					  "subsequent UUIDs\n", num),
+				       str, num);
+			}
+			memcpy(reply_buf, uu, sizeof(uu));
+			reply_len = sizeof(uu);
+			memcpy(reply_buf+reply_len, &num, sizeof(num));
+			reply_len += sizeof(num);
+			break;
+		case UUIDD_OP_BULK_RANDOM_UUID:
+			if (num < 0)
+				num = 1;
+			if (num > 1000)
+				num = 1000;
+			if (num*16 > (int) (sizeof(reply_buf)-sizeof(num)))
+				num = (sizeof(reply_buf)-sizeof(num)) / 16;
+			uuid__generate_random((unsigned char *) reply_buf +
+					      sizeof(num), &num);
+			if (debug) {
+				printf(_("Generated %d UUID's:\n"), num);
+				for (i=0, cp=reply_buf+sizeof(num);
+				     i < num; i++, cp+=16) {
+					uuid_unparse((unsigned char *)cp, str);
+					printf("\t%s\n", str);
+				}
+			}
+			reply_len = (num*16) + sizeof(num);
+			memcpy(reply_buf, &num, sizeof(num));
+			break;
+		default:
+			if (debug)
+				printf(_("Invalid operation %d\n"), op);
+			goto shutdown_socket;
+		}
+		write_all(ns, (char *) &reply_len, sizeof(reply_len));
+		write_all(ns, reply_buf, reply_len);
+	shutdown_socket:
+		close(ns);
+	}
+}
+
+int main(int argc, char **argv)
+{
+	const char	*socket_path = UUIDD_SOCKET_PATH;
+	const char	*pidfile_path = UUIDD_PIDFILE_PATH;
+	const char	*err_context;
+	char		buf[1024], *cp;
+	char   		str[37], *tmp;
+	uuid_t		uu;
+	uid_t		uid;
+	gid_t 		gid;
+	int		i, c, ret;
+	int		debug = 0, do_type = 0, do_kill = 0, num = 0;
+	int		timeout = 0, quiet = 0, drop_privs = 0;
+
+#ifdef ENABLE_NLS
+	setlocale(LC_MESSAGES, "");
+	setlocale(LC_CTYPE, "");
+	bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
+	textdomain(NLS_CAT_NAME);
+#endif
+
+	while ((c = getopt (argc, argv, "dkn:qp:s:tT:r")) != EOF) {
+		switch (c) {
+		case 'd':
+			debug++;
+			drop_privs = 1;
+			break;
+		case 'k':
+			do_kill++;
+			drop_privs = 1;
+			break;
+		case 'n':
+			num = strtol(optarg, &tmp, 0);
+			if ((num < 0) || *tmp) {
+				fprintf(stderr, _("Bad number: %s\n"), optarg);
+				exit(1);
+			}
+			break;
+		case 'p':
+			pidfile_path = optarg;
+			drop_privs = 1;
+			break;
+		case 'q':
+			quiet++;
+			break;
+		case 's':
+			socket_path = optarg;
+			drop_privs = 1;
+			break;
+		case 't':
+			do_type = UUIDD_OP_TIME_UUID;
+			drop_privs = 1;
+			break;
+		case 'T':
+			timeout = strtol(optarg, &tmp, 0);
+			if ((timeout < 0) || *tmp) {
+				fprintf(stderr, _("Bad number: %s\n"), optarg);
+				exit(1);
+			}
+			break;
+		case 'r':
+			do_type = UUIDD_OP_RANDOM_UUID;
+			drop_privs = 1;
+			break;
+		default:
+			usage(argv[0]);
+		}
+	}
+	uid = getuid();
+	if (uid && drop_privs) {
+		gid = getgid();
+#ifdef HAVE_SETRESGID
+		if (setresgid(gid, gid, gid) < 0)
+			die("setresgid");
+#else
+		if (setregid(gid, gid) < 0)
+			die("setregid");
+#endif
+
+#ifdef HAVE_SETRESUID
+		if (setresuid(uid, uid, uid) < 0)
+			die("setresuid");
+#else
+		if (setreuid(uid, uid) < 0)
+			die("setreuid");
+#endif
+	}
+	if (num && do_type) {
+		ret = call_daemon(socket_path, do_type+2, buf,
+				  sizeof(buf), &num, &err_context);
+		if (ret < 0) {
+			printf(_("Error calling uuidd daemon (%s): %s\n"),
+			       err_context, strerror(errno));
+			exit(1);
+		}
+		if (do_type == UUIDD_OP_TIME_UUID) {
+			if (ret != sizeof(uu) + sizeof(num))
+				goto unexpected_size;
+
+			uuid_unparse((unsigned char *) buf, str);
+
+			printf(P_("%s and subsequent UUID\n",
+				  "%s and subsequent %d UUIDs\n", num),
+			       str, num);
+		} else {
+			printf("%s", _("List of UUID's:\n"));
+			cp = buf + 4;
+			if (ret != (int) (sizeof(num) + num*sizeof(uu)))
+				goto unexpected_size;
+			for (i=0; i < num; i++, cp+=16) {
+				uuid_unparse((unsigned char *) cp, str);
+				printf("\t%s\n", str);
+			}
+		}
+		exit(0);
+	}
+	if (do_type) {
+		ret = call_daemon(socket_path, do_type, (char *) &uu,
+				  sizeof(uu), 0, &err_context);
+		if (ret < 0) {
+			printf(_("Error calling uuidd daemon (%s): %s\n"),
+			       err_context, strerror(errno));
+			exit(1);
+		}
+		if (ret != sizeof(uu)) {
+		unexpected_size:
+			printf(_("Unexpected reply length from server %d\n"),
+			       ret);
+			exit(1);
+		}
+		uuid_unparse(uu, str);
+
+		printf("%s\n", str);
+		exit(0);
+	}
+
+	if (do_kill) {
+		ret = call_daemon(socket_path, 0, buf, sizeof(buf), 0, 0);
+		if ((ret > 0) && ((do_kill = atoi((char *) buf)) > 0)) {
+			ret = kill(do_kill, SIGTERM);
+			if (ret < 0) {
+				if (!quiet)
+					fprintf(stderr,
+						_("Couldn't kill uuidd running "
+						  "at pid %d: %s\n"), do_kill,
+						strerror(errno));
+				exit(1);
+			}
+			if (!quiet)
+				printf(_("Killed uuidd running at pid %d\n"),
+				       do_kill);
+		}
+		exit(0);
+	}
+
+	server_loop(socket_path, pidfile_path, debug, timeout, quiet);
+	return 0;
+}
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/uuidd.rc b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/uuidd.rc
new file mode 100644
index 0000000..d35645a
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/uuidd.rc
@@ -0,0 +1,55 @@
+#! /bin/sh -e
+### BEGIN INIT INFO
+# Provides:          uuidd
+# Required-Start:    $time $local_fs
+# Required-Stop:     $time $local_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: uuidd daemon
+# Description:       Init script for the uuid generation daemon
+### END INIT INFO
+#
+# Author:	"Theodore Ts'o" <tytso@mit.edu>
+#
+set -e
+
+PATH=/bin:/usr/bin:/sbin:/usr/sbin
+DAEMON=/usr/sbin/uuidd
+PIDFILE=/var/run/uuidd/uuidd.pid
+
+test -x $DAEMON || exit 0
+
+. /lib/lsb/init-functions
+
+case "$1" in
+    start)
+	log_daemon_msg "Starting uuid generator" "uuidd"
+	start_daemon -p $PIDFILE $DAEMON
+	log_end_msg $?
+    ;;
+  stop)
+	log_daemon_msg "Stopping uuidd generator" "uuidd"
+	killproc -p $PIDFILE $DAEMON
+	log_end_msg $?
+    ;;
+  status)
+	if pidofproc -p $PIDFILE $DAEMON >& /dev/null ; then
+	    echo "$DAEMON is running";
+	    exit 0;
+	else
+	    echo "$DAEMON is NOT running";
+	    if test -f /var/run/uuidd.pid; then exit 2; fi
+	    exit 3;
+	fi
+	;;
+  force-reload|restart)
+    $0 stop
+    $0 start
+    ;;
+  *)
+    echo "Usage: /etc/init.d/uuidd {start|stop|restart|force-reload}"
+    exit 1
+    ;;
+esac
+
+exit 0
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/uuidgen.1.in b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/uuidgen.1.in
new file mode 100644
index 0000000..985e80d
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/uuidgen.1.in
@@ -0,0 +1,63 @@
+.\" Copyright 1999 Andreas Dilger (adilger@enel.ucalgary.ca)
+.\"
+.\" This man page was created for libuuid.so.1.1 from e2fsprogs-1.14.
+.\" 
+.\" This file may be copied under the terms of the GNU Public License.
+.\" 
+.\" Created  Wed Mar 10 17:42:12 1999, Andreas Dilger
+.TH UUIDGEN 1 "@E2FSPROGS_MONTH@ @E2FSPROGS_YEAR@" "E2fsprogs version @E2FSPROGS_VERSION@"
+.SH NAME
+uuidgen \- command\-line utility to create a new UUID value
+.SH SYNOPSIS
+.B uuidgen 
+[
+.B \-r
+|
+.B \-t
+]
+.SH DESCRIPTION
+The
+.B uuidgen
+program creates (and prints) 
+a new universally unique identifier (UUID) using the
+.BR libuuid (3)
+library.  The new UUID can reasonably be considered unique among 
+all UUIDs created on the local system, 
+and among UUIDs created on other systems in the past
+and in the future.
+.PP
+There are two types of UUID's which 
+.B uuidgen
+can generate: time-based UUID's and random-based UUID's.  By 
+default 
+.B uuidgen
+will generate a random-based UUID if a high-quality random number
+generator is present.  Otherwise, it will chose a time-based UUID.  It 
+is possible to force the generation of one of these two 
+UUID types by using the
+.B \-r
+or
+.B \-t
+options.
+.SH OPTIONS
+.TP
+.B \-r
+Generate a random-based UUID.  This method creates a UUID consisting mostly
+of random bits.  It requires that the operating system have a high
+quality random number generator, such as
+.IR /dev/random .
+.TP
+.B \-t
+Generate a time-based UUID.  This method creates a UUID based on the system 
+clock plus the system's ethernet hardware address, if present.
+.SH "CONFORMING TO"
+OSF DCE 1.1
+.SH AUTHOR
+.B uuidgen
+was written by Andreas Dilger for libuuid.
+.SH AVAILABILITY
+.B uuidgen
+is part of libuuid from the e2fsprogs package and is available from
+http://e2fsprogs.sourceforge.net.
+.SH "SEE ALSO"
+.BR libuuid (3)
diff --git a/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/uuidgen.c b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/uuidgen.c
new file mode 100644
index 0000000..f181d19
--- /dev/null
+++ b/ap/app/e2fsprogs/e2fsprogs-1.42.9/misc/uuidgen.c
@@ -0,0 +1,80 @@
+/*
+ * gen_uuid.c --- generate a DCE-compatible uuid
+ *
+ * Copyright (C) 1999, Andreas Dilger and Theodore Ts'o
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include "config.h"
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#else
+extern int getopt(int argc, char * const argv[], const char *optstring);
+extern char *optarg;
+extern int optind;
+#endif
+#include "uuid/uuid.h"
+#include "nls-enable.h"
+
+#define DO_TYPE_TIME	1
+#define DO_TYPE_RANDOM	2
+
+static void usage(const char *progname)
+{
+	fprintf(stderr, _("Usage: %s [-r] [-t]\n"), progname);
+	exit(1);
+}
+
+int
+main (int argc, char *argv[])
+{
+	int    c;
+	int    do_type = 0;
+	char   str[37];
+	uuid_t uu;
+
+#ifdef ENABLE_NLS
+	setlocale(LC_MESSAGES, "");
+	setlocale(LC_CTYPE, "");
+	bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
+	textdomain(NLS_CAT_NAME);
+#endif
+
+	while ((c = getopt (argc, argv, "tr")) != EOF)
+		switch (c) {
+		case 't':
+			do_type = DO_TYPE_TIME;
+			break;
+		case 'r':
+			do_type = DO_TYPE_RANDOM;
+			break;
+		default:
+			usage(argv[0]);
+		}
+
+	switch (do_type) {
+	case DO_TYPE_TIME:
+		uuid_generate_time(uu);
+		break;
+	case DO_TYPE_RANDOM:
+		uuid_generate_random(uu);
+		break;
+	default:
+		uuid_generate(uu);
+		break;
+	}
+
+	uuid_unparse(uu, str);
+
+	printf("%s\n", str);
+
+	return 0;
+}