Add the ability to log messages about a file system to a specified directory, using a file name templace that can be specified in /etc/e2fsck.conf. This allows us to suppress the output of overly verbose e2fsck outputs while still allowing the full logging output to go to an appropriate file. Signed-off-by: "Theodore Ts'o" <tytso@xxxxxxx> --- e2fsck/Makefile.in | 186 ++++++++++++++--------- e2fsck/e2fsck.c | 3 + e2fsck/e2fsck.conf.5.in | 134 +++++++++++++++++ e2fsck/e2fsck.h | 17 ++- e2fsck/logfile.c | 383 +++++++++++++++++++++++++++++++++++++++++++++++ e2fsck/message.c | 182 +++++++++++----------- e2fsck/problem.c | 30 +++-- e2fsck/problem.h | 2 +- e2fsck/unix.c | 266 +++++++++++++++++++-------------- e2fsck/util.c | 99 ++++++++----- 10 files changed, 978 insertions(+), 324 deletions(-) create mode 100644 e2fsck/logfile.c diff --git a/e2fsck/Makefile.in b/e2fsck/Makefile.in index b5336a4..d558985 100644 --- a/e2fsck/Makefile.in +++ b/e2fsck/Makefile.in @@ -68,7 +68,7 @@ OBJS= crc32.o dict.o unix.o e2fsck.o super.o pass1.o pass1b.o pass2.o \ pass3.o pass4.o pass5.o journal.o badblocks.o util.o dirinfo.o \ dx_dirinfo.o ehandler.o problem.o message.o quota.o recovery.o \ region.o revoke.o ea_refcount.o rehash.o profile.o prof_err.o \ - sigcatcher.o $(MTRACE_OBJ) + logfile.o sigcatcher.o $(MTRACE_OBJ) PROFILED_OBJS= profiled/dict.o profiled/unix.o profiled/e2fsck.o \ profiled/super.o profiled/pass1.o profiled/pass1b.o \ @@ -78,7 +78,8 @@ PROFILED_OBJS= profiled/dict.o profiled/unix.o profiled/e2fsck.o \ profiled/message.o profiled/problem.o profiled/quota.o \ profiled/recovery.o profiled/region.o profiled/revoke.o \ profiled/ea_refcount.o profiled/rehash.o profiled/profile.o \ - profiled/crc32.o profiled/prof_err.o profiled/sigcatcher.o + profiled/crc32.o profiled/prof_err.o profiled/logfile.o \ + profiled/sigcatcher.o SRCS= $(srcdir)/e2fsck.c \ $(srcdir)/crc32.c \ @@ -107,6 +108,7 @@ SRCS= $(srcdir)/e2fsck.c \ $(srcdir)/region.c \ $(srcdir)/profile.c \ $(srcdir)/sigcatcher.c \ + $(srcdir)/logfile.c \ prof_err.c \ $(srcdir)/quota.c \ $(MTRACE_SRC) @@ -160,6 +162,11 @@ tst_refcount: ea_refcount.c $(DEPLIBCOM_ERR) $(Q) $(CC) -o tst_refcount $(srcdir)/ea_refcount.c \ $(ALL_CFLAGS) -DTEST_PROGRAM $(LIBCOM_ERR) $(LIBEXT2FS) +tst_logfile: $(srcdir)/logfile.c + $(E) " LD $@" + $(Q) $(CC) -o tst_logfile $(srcdir)/logfile.c $(ALL_CFLAGS) \ + -DTEST_PROGRAM + tst_region: region.c $(DEPLIBCOM_ERR) $(E) " LD $@" $(Q) $(CC) -o tst_region $(srcdir)/region.c \ @@ -279,7 +286,8 @@ distclean: clean # Makefile dependencies follow. This must be the last section in # the Makefile.in file # -e2fsck.o: $(srcdir)/e2fsck.c $(top_builddir)/lib/config.h $(srcdir)/e2fsck.h \ +e2fsck.o: $(srcdir)/e2fsck.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.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 \ @@ -288,7 +296,8 @@ e2fsck.o: $(srcdir)/e2fsck.c $(top_builddir)/lib/config.h $(srcdir)/e2fsck.h \ $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/mkquota.h \ $(top_srcdir)/lib/quota/quota.h $(top_srcdir)/lib/../e2fsck/dict.h \ $(srcdir)/problem.h -crc32.o: $(srcdir)/crc32.c $(top_builddir)/lib/config.h $(srcdir)/e2fsck.h \ +crc32.o: $(srcdir)/crc32.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.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 \ @@ -297,10 +306,11 @@ crc32.o: $(srcdir)/crc32.c $(top_builddir)/lib/config.h $(srcdir)/e2fsck.h \ $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/mkquota.h \ $(top_srcdir)/lib/quota/quota.h $(top_srcdir)/lib/../e2fsck/dict.h \ $(srcdir)/crc32defs.h crc32table.h -gen_crc32table.o: $(srcdir)/gen_crc32table.c $(top_builddir)/lib/config.h \ - $(srcdir)/crc32defs.h -dict.o: $(srcdir)/dict.c $(top_builddir)/lib/config.h $(srcdir)/dict.h -super.o: $(srcdir)/super.c $(top_builddir)/lib/config.h $(srcdir)/e2fsck.h \ +gen_crc32table.o: $(srcdir)/gen_crc32table.c $(srcdir)/crc32defs.h +dict.o: $(srcdir)/dict.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/dict.h +super.o: $(srcdir)/super.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.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 \ @@ -309,7 +319,8 @@ super.o: $(srcdir)/super.c $(top_builddir)/lib/config.h $(srcdir)/e2fsck.h \ $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/mkquota.h \ $(top_srcdir)/lib/quota/quota.h $(top_srcdir)/lib/../e2fsck/dict.h \ $(srcdir)/problem.h -pass1.o: $(srcdir)/pass1.c $(top_builddir)/lib/config.h $(srcdir)/e2fsck.h \ +pass1.o: $(srcdir)/pass1.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.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 \ @@ -319,15 +330,17 @@ pass1.o: $(srcdir)/pass1.c $(top_builddir)/lib/config.h $(srcdir)/e2fsck.h \ $(top_srcdir)/lib/quota/quota.h $(top_srcdir)/lib/../e2fsck/dict.h \ $(srcdir)/problem.h pass1b.o: $(srcdir)/pass1b.c $(top_builddir)/lib/config.h \ - $(top_srcdir)/lib/et/com_err.h $(srcdir)/e2fsck.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_builddir)/lib/dirpaths.h $(top_srcdir)/lib/et/com_err.h \ + $(srcdir)/e2fsck.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)/profile.h prof_err.h $(top_srcdir)/lib/quota/mkquota.h \ $(top_srcdir)/lib/quota/quota.h $(top_srcdir)/lib/../e2fsck/dict.h \ $(srcdir)/problem.h $(srcdir)/dict.h -pass2.o: $(srcdir)/pass2.c $(top_builddir)/lib/config.h $(srcdir)/e2fsck.h \ +pass2.o: $(srcdir)/pass2.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.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 \ @@ -336,7 +349,8 @@ pass2.o: $(srcdir)/pass2.c $(top_builddir)/lib/config.h $(srcdir)/e2fsck.h \ $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/mkquota.h \ $(top_srcdir)/lib/quota/quota.h $(top_srcdir)/lib/../e2fsck/dict.h \ $(srcdir)/problem.h $(srcdir)/dict.h -pass3.o: $(srcdir)/pass3.c $(top_builddir)/lib/config.h $(srcdir)/e2fsck.h \ +pass3.o: $(srcdir)/pass3.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.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 \ @@ -345,7 +359,8 @@ pass3.o: $(srcdir)/pass3.c $(top_builddir)/lib/config.h $(srcdir)/e2fsck.h \ $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/mkquota.h \ $(top_srcdir)/lib/quota/quota.h $(top_srcdir)/lib/../e2fsck/dict.h \ $(srcdir)/problem.h -pass4.o: $(srcdir)/pass4.c $(top_builddir)/lib/config.h $(srcdir)/e2fsck.h \ +pass4.o: $(srcdir)/pass4.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.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 \ @@ -354,7 +369,8 @@ pass4.o: $(srcdir)/pass4.c $(top_builddir)/lib/config.h $(srcdir)/e2fsck.h \ $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/mkquota.h \ $(top_srcdir)/lib/quota/quota.h $(top_srcdir)/lib/../e2fsck/dict.h \ $(srcdir)/problem.h -pass5.o: $(srcdir)/pass5.c $(top_builddir)/lib/config.h $(srcdir)/e2fsck.h \ +pass5.o: $(srcdir)/pass5.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.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 \ @@ -364,44 +380,49 @@ pass5.o: $(srcdir)/pass5.c $(top_builddir)/lib/config.h $(srcdir)/e2fsck.h \ $(top_srcdir)/lib/quota/quota.h $(top_srcdir)/lib/../e2fsck/dict.h \ $(srcdir)/problem.h journal.o: $(srcdir)/journal.c $(top_builddir)/lib/config.h \ - $(srcdir)/jfs_user.h $(srcdir)/e2fsck.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_builddir)/lib/dirpaths.h $(srcdir)/jfs_user.h $(srcdir)/e2fsck.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)/profile.h prof_err.h $(top_srcdir)/lib/quota/mkquota.h \ $(top_srcdir)/lib/quota/quota.h $(top_srcdir)/lib/../e2fsck/dict.h \ $(top_srcdir)/lib/ext2fs/kernel-jbd.h $(top_srcdir)/lib/ext2fs/jfs_compat.h \ $(top_srcdir)/lib/ext2fs/kernel-list.h $(srcdir)/problem.h recovery.o: $(srcdir)/recovery.c $(top_builddir)/lib/config.h \ - $(srcdir)/jfs_user.h $(srcdir)/e2fsck.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_builddir)/lib/dirpaths.h $(srcdir)/jfs_user.h $(srcdir)/e2fsck.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)/profile.h prof_err.h $(top_srcdir)/lib/quota/mkquota.h \ $(top_srcdir)/lib/quota/quota.h $(top_srcdir)/lib/../e2fsck/dict.h \ $(top_srcdir)/lib/ext2fs/kernel-jbd.h $(top_srcdir)/lib/ext2fs/jfs_compat.h \ $(top_srcdir)/lib/ext2fs/kernel-list.h revoke.o: $(srcdir)/revoke.c $(top_builddir)/lib/config.h \ - $(srcdir)/jfs_user.h $(srcdir)/e2fsck.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_builddir)/lib/dirpaths.h $(srcdir)/jfs_user.h $(srcdir)/e2fsck.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)/profile.h prof_err.h $(top_srcdir)/lib/quota/mkquota.h \ $(top_srcdir)/lib/quota/quota.h $(top_srcdir)/lib/../e2fsck/dict.h \ $(top_srcdir)/lib/ext2fs/kernel-jbd.h $(top_srcdir)/lib/ext2fs/jfs_compat.h \ $(top_srcdir)/lib/ext2fs/kernel-list.h badblocks.o: $(srcdir)/badblocks.c $(top_builddir)/lib/config.h \ - $(top_srcdir)/lib/et/com_err.h $(srcdir)/e2fsck.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_builddir)/lib/dirpaths.h $(top_srcdir)/lib/et/com_err.h \ + $(srcdir)/e2fsck.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)/profile.h prof_err.h $(top_srcdir)/lib/quota/mkquota.h \ $(top_srcdir)/lib/quota/quota.h $(top_srcdir)/lib/../e2fsck/dict.h -util.o: $(srcdir)/util.c $(top_builddir)/lib/config.h $(srcdir)/e2fsck.h \ +util.o: $(srcdir)/util.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.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 \ @@ -410,67 +431,74 @@ util.o: $(srcdir)/util.c $(top_builddir)/lib/config.h $(srcdir)/e2fsck.h \ $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/mkquota.h \ $(top_srcdir)/lib/quota/quota.h $(top_srcdir)/lib/../e2fsck/dict.h unix.o: $(srcdir)/unix.c $(top_builddir)/lib/config.h \ - $(top_srcdir)/lib/e2p/e2p.h $(top_srcdir)/lib/ext2fs/ext2_fs.h \ - $(top_builddir)/lib/ext2fs/ext2_types.h $(top_srcdir)/lib/et/com_err.h \ - $(srcdir)/e2fsck.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_builddir)/lib/dirpaths.h $(top_srcdir)/lib/e2p/e2p.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/et/com_err.h $(srcdir)/e2fsck.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)/profile.h prof_err.h $(top_srcdir)/lib/quota/mkquota.h \ $(top_srcdir)/lib/quota/quota.h $(top_srcdir)/lib/../e2fsck/dict.h \ $(srcdir)/problem.h $(top_srcdir)/version.h dirinfo.o: $(srcdir)/dirinfo.c $(top_builddir)/lib/config.h \ - $(srcdir)/e2fsck.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_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.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)/profile.h prof_err.h $(top_srcdir)/lib/quota/mkquota.h \ $(top_srcdir)/lib/quota/quota.h $(top_srcdir)/lib/../e2fsck/dict.h \ $(top_srcdir)/lib/ext2fs/tdb.h dx_dirinfo.o: $(srcdir)/dx_dirinfo.c $(top_builddir)/lib/config.h \ - $(srcdir)/e2fsck.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_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.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)/profile.h prof_err.h $(top_srcdir)/lib/quota/mkquota.h \ $(top_srcdir)/lib/quota/quota.h $(top_srcdir)/lib/../e2fsck/dict.h ehandler.o: $(srcdir)/ehandler.c $(top_builddir)/lib/config.h \ - $(srcdir)/e2fsck.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_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.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)/profile.h prof_err.h $(top_srcdir)/lib/quota/mkquota.h \ $(top_srcdir)/lib/quota/quota.h $(top_srcdir)/lib/../e2fsck/dict.h problem.o: $(srcdir)/problem.c $(top_builddir)/lib/config.h \ - $(srcdir)/e2fsck.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_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.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)/profile.h prof_err.h $(top_srcdir)/lib/quota/mkquota.h \ $(top_srcdir)/lib/quota/quota.h $(top_srcdir)/lib/../e2fsck/dict.h \ $(srcdir)/problem.h $(srcdir)/problemP.h message.o: $(srcdir)/message.c $(top_builddir)/lib/config.h \ - $(srcdir)/e2fsck.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_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.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)/profile.h prof_err.h $(top_srcdir)/lib/quota/mkquota.h \ $(top_srcdir)/lib/quota/quota.h $(top_srcdir)/lib/../e2fsck/dict.h \ $(srcdir)/problem.h ea_refcount.o: $(srcdir)/ea_refcount.c $(top_builddir)/lib/config.h \ - $(srcdir)/e2fsck.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_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.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)/profile.h prof_err.h $(top_srcdir)/lib/quota/mkquota.h \ $(top_srcdir)/lib/quota/quota.h $(top_srcdir)/lib/../e2fsck/dict.h -rehash.o: $(srcdir)/rehash.c $(top_builddir)/lib/config.h $(srcdir)/e2fsck.h \ +rehash.o: $(srcdir)/rehash.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.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 \ @@ -479,7 +507,8 @@ rehash.o: $(srcdir)/rehash.c $(top_builddir)/lib/config.h $(srcdir)/e2fsck.h \ $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/mkquota.h \ $(top_srcdir)/lib/quota/quota.h $(top_srcdir)/lib/../e2fsck/dict.h \ $(srcdir)/problem.h -region.o: $(srcdir)/region.c $(top_builddir)/lib/config.h $(srcdir)/e2fsck.h \ +region.o: $(srcdir)/region.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.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 \ @@ -488,17 +517,29 @@ region.o: $(srcdir)/region.c $(top_builddir)/lib/config.h $(srcdir)/e2fsck.h \ $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/mkquota.h \ $(top_srcdir)/lib/quota/quota.h $(top_srcdir)/lib/../e2fsck/dict.h profile.o: $(srcdir)/profile.c $(top_builddir)/lib/config.h \ - $(top_srcdir)/lib/et/com_err.h $(srcdir)/profile.h prof_err.h + $(top_builddir)/lib/dirpaths.h $(top_srcdir)/lib/et/com_err.h \ + $(srcdir)/profile.h prof_err.h sigcatcher.o: $(srcdir)/sigcatcher.c $(top_builddir)/lib/config.h \ - $(srcdir)/e2fsck.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_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.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)/profile.h prof_err.h $(top_srcdir)/lib/quota/mkquota.h \ + $(top_srcdir)/lib/quota/quota.h $(top_srcdir)/lib/../e2fsck/dict.h +logfile.o: $(srcdir)/logfile.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.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)/profile.h prof_err.h $(top_srcdir)/lib/quota/mkquota.h \ $(top_srcdir)/lib/quota/quota.h $(top_srcdir)/lib/../e2fsck/dict.h prof_err.o: prof_err.c -quota.o: $(srcdir)/quota.c $(top_builddir)/lib/config.h $(srcdir)/e2fsck.h \ +quota.o: $(srcdir)/quota.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.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 \ @@ -506,4 +547,5 @@ quota.o: $(srcdir)/quota.c $(top_builddir)/lib/config.h $(srcdir)/e2fsck.h \ $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/mkquota.h \ $(top_srcdir)/lib/quota/quota.h $(top_srcdir)/lib/../e2fsck/dict.h \ - $(srcdir)/problem.h + $(srcdir)/problem.h $(top_srcdir)/lib/quota/quotaio.h \ + $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h diff --git a/e2fsck/e2fsck.c b/e2fsck/e2fsck.c index c6e137b..994f80e 100644 --- a/e2fsck/e2fsck.c +++ b/e2fsck/e2fsck.c @@ -187,6 +187,9 @@ void e2fsck_free_context(e2fsck_t ctx) if (ctx->device_name) ext2fs_free_mem(&ctx->device_name); + if (ctx->log_fn) + free(ctx->log_fn); + ext2fs_free_mem(&ctx); } diff --git a/e2fsck/e2fsck.conf.5.in b/e2fsck/e2fsck.conf.5.in index a89d7b4..0d4651b 100644 --- a/e2fsck/e2fsck.conf.5.in +++ b/e2fsck/e2fsck.conf.5.in @@ -136,6 +136,47 @@ filesystem checks (either based on time or number of mounts) should be doubled if the system is running on battery. This setting defaults to true. .TP +.I log_dir +If the +.I log_filename +relation contains a relative pathname, then the log file will be placed +in the directory named by the +.I log_dir +relation. +.TP +.I log_dir_fallback +This relation contains an alternate directory that will be used if the +directory specified by +.I log_dir +is not available or is not writeable. +.TP +.I log_dir_wait +If this boolean relation is true, them if the directories specified by +.I log_dir +or +.I log_dir_fallback +are not available or are not yet writeable, e2fsck will save the output +in a memory buffer, and a child process will periodically test to see if +the log directory has become available after the boot sequence has +mounted the requiste filesytem for reading/writing. This implements the +functionality provided by +.BR logsave (8) +for e2fsck log files. +.TP +.I log_filename +This relation specifies the file name where a copy of e2fsck's output +will be written. If certain problem reports are suppressed using the +.I max_count_problems +relation, (or on a per-problem basis using the +.I max_count +relation), the full set of problem reports will be written to the log +file. The filename may contain various percent-expressions (%D, %T, %N, +etc.) which will be expanded so that the file name for the log file can +include things like date, time, device name, and other run-time +parameters. See the +.B LOGGING +section for more details. +.TP .I max_count_problems This relation specifies the maximum number of problem reports of a particular type will be printed to stdout before further problem reports @@ -241,6 +282,76 @@ defaults to true. This relation controls whether or not the scratch file directory is used instead of an in-memory data structure when tracking inode counts. It defaults to true. +.SH LOGGING +E2fsck has the facility to save the information from an e2fsck run in a +directory so that a system administrator can review its output at their +leisure. This allows information captured during the automatic e2fsck +preen run, as well as a manually started e2fsck run, to be saved for +posterity. This facility is controlled by the +.IR log_filename , +.IR log_dir , +.IR log_dir_fallback , +and +.I log_dir_wait +relations in the +.I [options] +stanza. +.PP +The filename in +.I log_filename +may contain the following percent-expressions that will be expanded as +follows. +.TP +.B %d +The current day of the month +.TP +.B %D +The current date; this is a equivalent of +.B %Y%m%d +.TP +.B %h +The hostname of the system. +.TP +.B %H +The current hour in 24-hour format (00..23) +.TP +.B %m +The current month as a two-digit number (01..12) +.TP +.B %M +The current minute (00..59) +.TP +.B %N +The name of the block device containing the file system, with any +directory pathname stripped off. +.TP +.B %p +The pid of the e2fsck process +.TP +.B %s +The current time expressed as the number of seconds since 1970-01-01 +00:00:00 UTC +.TP +.B %S +The current second (00..59) +.TP +.B %T +The current time; this is equivalent of +.B %H%M%S +.TP +.B %u +The name of the user running e2fsck. +.TP +.B %U +This percent expression does not expand to anything, but it signals that +any following date or time expressions should be expressed in UTC time +instead of the local timzeone. +.TP +.B %y +The last two digits of the current year (00..99) +.TP +.B %Y +The current year (i.e., 2012). .SH EXAMPLES The following recipe will prevent e2fsck from aborting during the boot process when a filesystem contains orphaned files. (Of course, this is @@ -259,6 +370,29 @@ things out may be dangerous.) description = "@u @i %i. " .br } +.P +The following recipe will cause an e2fsck logfile to be written to the +directory /var/log/e2fsck, with a filename that contains the device +name, the hostname of the system, the date, and time: e.g., +"e2fsck-sda3.server.INFO.20120314-112142". If the directory containing +/var/log is located on the root file system +which is initially mounted read-only, then the output will be saved in +memory and written out once the root file system has been remounted +read/write. To avoid too much detail from being written to the serial +console (which could potentially slow down the boot sequence), only print +no more than 16 instances of each type of file system corruption. +.P +.br + [options] +.br + max_count_problems = 16 +.br + log_dir = /var/log/e2fsck +.br + log_filename = e2fsck-%N.%h.INFO.%D-%T +.br + log_dir_wait = true +.P .SH FILES .TP .I /etc/e2fsck.conf diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h index ed8b0c7..971390e 100644 --- a/e2fsck/e2fsck.h +++ b/e2fsck/e2fsck.h @@ -61,6 +61,12 @@ #define P_(singular, plural, n) ((n) == 1 ? (singular) : (plural)) #endif +#ifdef __GNUC__ +#define E2FSCK_ATTR(x) __attribute__(x) +#else +#define E2FSCK_ATTR(x) +#endif + #include "quota/mkquota.h" /* @@ -214,6 +220,8 @@ struct e2fsck_struct { char *filesystem_name; char *device_name; char *io_options; + FILE *logf; + char *log_fn; int flags; /* E2fsck internal flags */ int options; int blocksize; /* blocksize */ @@ -449,6 +457,9 @@ extern int e2fsck_run_ext3_journal(e2fsck_t ctx); extern void e2fsck_move_ext3_journal(e2fsck_t ctx); extern int e2fsck_fix_ext3_journal_hint(e2fsck_t ctx); +/* logfile.c */ +extern void set_up_logging(e2fsck_t ctx); + /* quota.c */ extern void e2fsck_hide_quota(e2fsck_t ctx); @@ -498,8 +509,12 @@ void check_resize_inode(e2fsck_t ctx); extern void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size, const char *description); extern int ask(e2fsck_t ctx, const char * string, int def); -extern int ask_yn(const char * string, int def); +extern int ask_yn(e2fsck_t ctx, const char * string, int def); extern void fatal_error(e2fsck_t ctx, const char * fmt_string); +extern void log_out(e2fsck_t ctx, const char *fmt, ...) + E2FSCK_ATTR((format(printf, 2, 3))); +extern void log_err(e2fsck_t ctx, const char *fmt, ...) + E2FSCK_ATTR((format(printf, 2, 3))); extern void e2fsck_read_bitmaps(e2fsck_t ctx); extern void e2fsck_write_bitmaps(e2fsck_t ctx); extern void preenhalt(e2fsck_t ctx); diff --git a/e2fsck/logfile.c b/e2fsck/logfile.c new file mode 100644 index 0000000..76ae52d --- /dev/null +++ b/e2fsck/logfile.c @@ -0,0 +1,383 @@ +/* + * logfile.c --- set up e2fsck log files + * + * Copyright 1996, 1997 by Theodore Ts'o + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include "config.h" +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif + +#include "e2fsck.h" +#include <pwd.h> + +struct string { + char *s; + int len; + int end; +}; + +static void alloc_string(struct string *s, int len) +{ + s->s = malloc(len); +/* e2fsck_allocate_memory(ctx, len, "logfile name"); */ + s->len = len; + s->end = 0; +} + +static void append_string(struct string *s, const char *a, int len) +{ + if (!len) + len = strlen(a); + + if (s->end + len >= s->len) { + char *n = realloc(s, s->len * 2); + + if (n) { + s->s = n; + s->len = s->len * 2; + } else { + len = s->len - s->end - 1; + if (len <= 0) + return; + } + } + memcpy(s->s + s->end, a, len); + s->end += len; + s->s[s->end] = 0; +} + +#define FLAG_UTC 0x0001 + +static void expand_percent_expression(e2fsck_t ctx, char ch, + struct string *s, int *flags) +{ + struct tm *tm = NULL, tm_struct; + struct passwd *pw = NULL, pw_struct; + char *cp; + char buf[256]; + + if ((ch == 'D') || (ch == 'd') || (ch == 'm') || (ch == 'y') || + (ch == 'Y') || + (ch == 'T') || (ch == 'H') || (ch == 'M') || (ch == 'S')) { + tzset(); + tm = (*flags & FLAG_UTC) ? gmtime_r(&ctx->now, &tm_struct) : + localtime_r(&ctx->now, &tm_struct); + } + + switch (ch) { + case '%': + append_string(s, "%", 1); + return; + case 'd': + sprintf(buf, "%02d", tm->tm_mday); + break; + case 'D': + sprintf(buf, "%d%02d%02d", tm->tm_year + 1900, tm->tm_mon + 1, + tm->tm_mday); + break; + case 'h': +#ifdef TEST_PROGRAM + strcpy(buf, "server"); +#else + buf[0] = 0; + gethostname(buf, sizeof(buf)); + buf[sizeof(buf)-1] = 0; +#endif + break; + case 'H': + sprintf(buf, "%02d", tm->tm_hour); + break; + case 'm': + sprintf(buf, "%02d", tm->tm_mon + 1); + break; + case 'M': + sprintf(buf, "%02d", tm->tm_min); + break; + case 'N': /* block device name */ + cp = strrchr(ctx->filesystem_name, '/'); + if (cp) + cp++; + else + cp = ctx->filesystem_name; + append_string(s, cp, 0); + return; + case 'p': + sprintf(buf, "%lu", (unsigned long) getpid()); + break; + case 's': + sprintf(buf, "%lu", (unsigned long) ctx->now); + break; + case 'S': + sprintf(buf, "%02d", tm->tm_sec); + break; + case 'T': + sprintf(buf, "%02d%02d%02d", tm->tm_hour, tm->tm_min, + tm->tm_sec); + break; + case 'u': +#ifdef TEST_PROGRAM + strcpy(buf, "tytso"); + break; +#else + getpwuid_r(getuid(), &pw_struct, buf, sizeof(buf), &pw); + if (pw) + append_string(s, pw->pw_name, 0); + return; +#endif + case 'U': + *flags |= FLAG_UTC; + return; + case 'y': + sprintf(buf, "%02d", tm->tm_year % 100); + break; + case 'Y': + sprintf(buf, "%d", tm->tm_year + 1900); + break; + } + append_string(s, buf, 0); +} + +static void expand_logfn(e2fsck_t ctx, const char *log_fn, struct string *s) +{ + const char *cp; + int i; + int flags = 0; + + alloc_string(s, 100); + for (cp = log_fn; *cp; cp++) { + if (cp[0] == '%') { + cp++; + expand_percent_expression(ctx, *cp, s, &flags); + continue; + } + for (i = 0; cp[i]; i++) + if (cp[i] == '%') + break; + append_string(s, cp, i); + cp += i-1; + } +} + +static int outbufsize; +static void *outbuf; + +static int do_read(int fd) +{ + int c; + char *n; + char buffer[4096]; + + c = read(fd, buffer, sizeof(buffer)-1); + if (c <= 0) + return c; + + n = realloc(outbuf, outbufsize + c); + if (n) { + outbuf = n; + memcpy(((char *)outbuf)+outbufsize, buffer, c); + outbufsize += c; + } + return c; +} + +/* + * Fork a child process to save the output of the logfile until the + * appropriate file system is mounted read/write. + */ +static FILE *save_output(const char *s0, const char *s1, const char *s2) +{ + int c, fd, fds[2]; + char *cp; + pid_t pid; + FILE *ret; + + if (s0 && *s0 == 0) + s0 = 0; + if (s1 && *s1 == 0) + s1 = 0; + if (s2 && *s2 == 0) + s2 = 0; + + /* At least one potential output file name is valid */ + if (!s0 && !s1 && !s2) + return NULL; + if (pipe(fds) < 0) { + perror("pipe"); + exit(1); + } + + pid = fork(); + if (pid < 0) { + perror("fork"); + exit(1); + } + + if (pid == 0) { + if (daemon(0, 0) < 0) { + perror("daemon"); + exit(1); + } + /* + * Grab the output from our parent + */ + close(fds[1]); + while (do_read(fds[0]) > 0) + ; + close(fds[0]); + + /* OK, now let's try to open the output file */ + fd = -1; + while (1) { + if (fd < 0 && s0) + fd = open(s0, O_WRONLY|O_CREAT|O_TRUNC, 0644); + if (fd < 0 && s1) + fd = open(s1, O_WRONLY|O_CREAT|O_TRUNC, 0644); + if (fd < 0 && s2) + fd = open(s2, O_WRONLY|O_CREAT|O_TRUNC, 0644); + if (fd >= 0) + break; + sleep(1); + } + + cp = outbuf; + while (outbufsize > 0) { + c = write(fd, cp, outbufsize); + if (c < 0) { + if ((errno == EAGAIN) || (errno == EINTR)) + continue; + break; + } + outbufsize -= c; + cp += c; + } + exit(0); + } + + close(fds[0]); + ret = fdopen(fds[1], "w"); + if (!ret) + close(fds[1]); + return ret; +} + +#ifndef TEST_PROGRAM +void set_up_logging(e2fsck_t ctx) +{ + struct string s, s1, s2; + char *s0 = 0, *log_dir = 0, *log_fn = 0; + int log_dir_wait = 0; + + s.s = s1.s = s2.s = 0; + + profile_get_boolean(ctx->profile, "options", "log_dir_wait", 0, 0, + &log_dir_wait); + if (ctx->log_fn) + log_fn = string_copy(ctx, ctx->log_fn, 0); + else + profile_get_string(ctx->profile, "options", "log_filename", + 0, 0, &log_fn); + profile_get_string(ctx->profile, "options", "log_dir", 0, 0, &log_dir); + + if (!log_fn || !log_fn[0]) + goto out; + + expand_logfn(ctx, log_fn, &s); + if ((log_fn[0] == '/') || !log_dir || !log_dir[0]) + s0 = s.s; + + if (log_dir && log_dir[0]) { + alloc_string(&s1, strlen(log_dir) + strlen(s.s) + 2); + append_string(&s1, log_dir, 0); + append_string(&s1, "/", 1); + append_string(&s1, s.s, 0); + } + + free(log_dir); + profile_get_string(ctx->profile, "options", "log_dir_fallback", 0, 0, + &log_dir); + if (log_dir && log_dir[0]) { + alloc_string(&s2, strlen(log_dir) + strlen(s.s) + 2); + append_string(&s2, log_dir, 0); + append_string(&s2, "/", 1); + append_string(&s2, s.s, 0); + printf("%s\n", s2.s); + } + + if (s0) + ctx->logf = fopen(s0, "w"); + if (!ctx->logf && s1.s) + ctx->logf = fopen(s1.s, "w"); + if (!ctx->logf && s2.s) + ctx->logf = fopen(s2.s, "w"); + if (!ctx->logf && log_dir_wait) + ctx->logf = save_output(s0, s1.s, s2.s); + +out: + free(s.s); + free(s1.s); + free(s2.s); + free(log_fn); + free(log_dir); + return; +} +#else +void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size, + const char *description) +{ + void *ret; + char buf[256]; + + ret = malloc(size); + if (!ret) { + sprintf(buf, "Can't allocate %s\n", description); + exit(1); + } + memset(ret, 0, size); + return ret; +} + +errcode_t e2fsck_allocate_context(e2fsck_t *ret) +{ + e2fsck_t context; + errcode_t retval; + char *time_env; + + context = malloc(sizeof(struct e2fsck_struct)); + if (!context) + return ENOMEM; + + memset(context, 0, sizeof(struct e2fsck_struct)); + + context->now = 1332006474; + + context->filesystem_name = "/dev/sda3"; + context->device_name = "fslabel"; + + *ret = context; + return 0; +} + +int main(int argc, char **argv) +{ + e2fsck_t ctx; + struct string s; + + putenv("TZ=EST+5:00"); + e2fsck_allocate_context(&ctx); + expand_logfn(ctx, "e2fsck-%N.%h.%u.%D-%T", &s); + printf("%s\n", s.s); + free(s.s); + expand_logfn(ctx, "e2fsck-%N.%h.%u.%Y%m%d-%H%M%S", &s); + printf("%s\n", s.s); + free(s.s); + + return 0; +} +#endif diff --git a/e2fsck/message.c b/e2fsck/message.c index 6274824..980dc4b 100644 --- a/e2fsck/message.c +++ b/e2fsck/message.c @@ -168,7 +168,7 @@ static const char *special_inode_name[] = * 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) +static void safe_print(FILE *f, const char *cp, int len) { unsigned char ch; @@ -178,14 +178,14 @@ static void safe_print(const char *cp, int len) while (len--) { ch = *cp++; if (ch > 128) { - fputs("M-", stdout); + fputs("M-", f); ch -= 128; } if ((ch < 32) || (ch == 0x7f)) { - fputc('^', stdout); + fputc('^', f); ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */ } - fputc(ch, stdout); + fputc(ch, f); } } @@ -194,27 +194,28 @@ static void safe_print(const char *cp, int len) * This function prints a pathname, using the ext2fs_get_pathname * function */ -static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino) +static void print_pathname(FILE *f, ext2_filsys fs, ext2_ino_t dir, + ext2_ino_t ino) { errcode_t retval; char *path; if (!dir && (ino < num_special_inodes)) { - fputs(_(special_inode_name[ino]), stdout); + fputs(_(special_inode_name[ino]), f); return; } if (fs) retval = ext2fs_get_pathname(fs, dir, ino, &path); if (!fs || retval) - fputs("???", stdout); + fputs("???", f); else { - safe_print(path, -1); + safe_print(f, path, -1); ext2fs_free_mem(&path); } } -static void print_time(time_t t) +static void print_time(FILE *f, time_t t) { const char * time_str; static int do_gmt = -1; @@ -229,7 +230,7 @@ static void print_time(time_t t) } #endif time_str = asctime((do_gmt > 0) ? gmtime(&t) : localtime(&t)); - printf("%.24s", time_str); + fprintf(f, "%.24s", time_str); } /* @@ -237,7 +238,7 @@ static void print_time(time_t t) * expansion; an @ expression can contain further '@' and '%' * expressions. */ -static _INLINE_ void expand_at_expression(e2fsck_t ctx, char ch, +static _INLINE_ void expand_at_expression(FILE *f, e2fsck_t ctx, char ch, struct problem_context *pctx, int *first, int recurse) { @@ -252,17 +253,17 @@ static _INLINE_ void expand_at_expression(e2fsck_t ctx, char ch, str = _(*cpp) + 1; if (*first && islower(*str)) { *first = 0; - fputc(toupper(*str++), stdout); + fputc(toupper(*str++), f); } - print_e2fsck_message(ctx, str, pctx, *first, recurse+1); + print_e2fsck_message(f, ctx, str, pctx, *first, recurse+1); } else - printf("@%c", ch); + fprintf(f, "@%c", ch); } /* * This function expands '%IX' expressions */ -static _INLINE_ void expand_inode_expression(ext2_filsys fs, char ch, +static _INLINE_ void expand_inode_expression(FILE *f, ext2_filsys fs, char ch, struct problem_context *ctx) { struct ext2_inode *inode; @@ -277,78 +278,78 @@ static _INLINE_ void expand_inode_expression(ext2_filsys fs, char ch, switch (ch) { case 's': if (LINUX_S_ISDIR(inode->i_mode)) - printf("%u", inode->i_size); + fprintf(f, "%u", inode->i_size); else { #ifdef EXT2_NO_64_TYPE if (inode->i_size_high) - printf("0x%x%08x", inode->i_size_high, - inode->i_size); + fprintf(f, "0x%x%08x", inode->i_size_high, + inode->i_size); else - printf("%u", inode->i_size); + fprintf(f, "%u", inode->i_size); #else - printf("%llu", EXT2_I_SIZE(inode)); + fprintf(f, "%llu", EXT2_I_SIZE(inode)); #endif } break; case 'S': - printf("%u", large_inode->i_extra_isize); + fprintf(f, "%u", large_inode->i_extra_isize); break; case 'b': if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_HUGE_FILE) - printf("%llu", inode->i_blocks + - (((long long) inode->osd2.linux2.l_i_blocks_hi) - << 32)); + fprintf(f, "%llu", inode->i_blocks + + (((long long) inode->osd2.linux2.l_i_blocks_hi) + << 32)); else - printf("%u", inode->i_blocks); + fprintf(f, "%u", inode->i_blocks); break; case 'l': - printf("%d", inode->i_links_count); + fprintf(f, "%d", inode->i_links_count); break; case 'm': - printf("0%o", inode->i_mode); + fprintf(f, "0%o", inode->i_mode); break; case 'M': - print_time(inode->i_mtime); + print_time(f, inode->i_mtime); break; case 'F': - printf("%u", inode->i_faddr); + fprintf(f, "%u", inode->i_faddr); break; case 'f': - printf("%llu", ext2fs_file_acl_block(fs, inode)); + fprintf(f, "%llu", ext2fs_file_acl_block(fs, inode)); break; case 'd': - printf("%u", (LINUX_S_ISDIR(inode->i_mode) ? - inode->i_dir_acl : 0)); + fprintf(f, "%u", (LINUX_S_ISDIR(inode->i_mode) ? + inode->i_dir_acl : 0)); break; case 'u': - printf("%d", inode_uid(*inode)); + fprintf(f, "%d", inode_uid(*inode)); break; case 'g': - printf("%d", inode_gid(*inode)); + fprintf(f, "%d", inode_gid(*inode)); break; case 't': if (LINUX_S_ISREG(inode->i_mode)) - printf(_("regular file")); + fputs(_("regular file"), f); else if (LINUX_S_ISDIR(inode->i_mode)) - printf(_("directory")); + fputs(_("directory"), f); else if (LINUX_S_ISCHR(inode->i_mode)) - printf(_("character device")); + fputs(_("character device"), f); else if (LINUX_S_ISBLK(inode->i_mode)) - printf(_("block device")); + fputs(_("block device"), f); else if (LINUX_S_ISFIFO(inode->i_mode)) - printf(_("named pipe")); + fputs(_("named pipe"), f); else if (LINUX_S_ISLNK(inode->i_mode)) - printf(_("symbolic link")); + fputs(_("symbolic link"), f); else if (LINUX_S_ISSOCK(inode->i_mode)) - printf(_("socket")); + fputs(_("socket"), f); else - printf(_("unknown file type with mode 0%o"), - inode->i_mode); + fprintf(f, _("unknown file type with mode 0%o"), + inode->i_mode); break; default: no_inode: - printf("%%I%c", ch); + fprintf(f, "%%I%c", ch); break; } } @@ -356,7 +357,7 @@ static _INLINE_ void expand_inode_expression(ext2_filsys fs, char ch, /* * This function expands '%dX' expressions */ -static _INLINE_ void expand_dirent_expression(ext2_filsys fs, char ch, +static _INLINE_ void expand_dirent_expression(FILE *f, ext2_filsys fs, char ch, struct problem_context *ctx) { struct ext2_dir_entry *dirent; @@ -370,34 +371,34 @@ static _INLINE_ void expand_dirent_expression(ext2_filsys fs, char ch, switch (ch) { case 'i': - printf("%u", dirent->inode); + fprintf(f, "%u", dirent->inode); break; case 'n': len = dirent->name_len & 0xFF; if ((ext2fs_get_rec_len(fs, dirent, &rec_len) == 0) && (len > rec_len)) len = rec_len; - safe_print(dirent->name, len); + safe_print(f, dirent->name, len); break; case 'r': (void) ext2fs_get_rec_len(fs, dirent, &rec_len); - printf("%u", rec_len); + fprintf(f, "%u", rec_len); break; case 'l': - printf("%u", dirent->name_len & 0xFF); + fprintf(f, "%u", dirent->name_len & 0xFF); break; case 't': - printf("%u", dirent->name_len >> 8); + fprintf(f, "%u", dirent->name_len >> 8); break; default: no_dirent: - printf("%%D%c", ch); + fprintf(f, "%%D%c", ch); break; } } -static _INLINE_ void expand_percent_expression(ext2_filsys fs, char ch, - int width, int *first, +static _INLINE_ void expand_percent_expression(FILE *f, ext2_filsys fs, + char ch, int width, int *first, struct problem_context *ctx) { e2fsck_t e2fsck_ctx = fs ? (e2fsck_t) fs->priv_data : NULL; @@ -408,13 +409,13 @@ static _INLINE_ void expand_percent_expression(ext2_filsys fs, char ch, switch (ch) { case '%': - fputc('%', stdout); + fputc('%', f); break; case 'b': #ifdef EXT2_NO_64_TYPE - printf("%*u", width, (unsigned long) ctx->blk); + fprintf(f, "%*u", width, (unsigned long) ctx->blk); #else - printf("%*llu", width, (unsigned long long) ctx->blk); + fprintf(f, "%*llu", width, (unsigned long long) ctx->blk); #endif break; case 'B': @@ -429,98 +430,98 @@ static _INLINE_ void expand_percent_expression(ext2_filsys fs, char ch, else m = _("block #"); if (*first && islower(m[0])) - fputc(toupper(*m++), stdout); - fputs(m, stdout); + fputc(toupper(*m++), f); + fputs(m, f); if (ctx->blkcount >= 0) { #ifdef EXT2_NO_64_TYPE - printf("%d", ctx->blkcount); + fprintf(f, "%d", ctx->blkcount); #else - printf("%lld", (long long) ctx->blkcount); + fprintf(f, "%lld", (long long) ctx->blkcount); #endif } break; case 'c': #ifdef EXT2_NO_64_TYPE - printf("%*u", width, (unsigned long) ctx->blk2); + fprintf(f, "%*u", width, (unsigned long) ctx->blk2); #else - printf("%*llu", width, (unsigned long long) ctx->blk2); + fprintf(f, "%*llu", width, (unsigned long long) ctx->blk2); #endif break; case 'd': - printf("%*u", width, ctx->dir); + fprintf(f, "%*u", width, ctx->dir); break; case 'g': - printf("%*d", width, ctx->group); + fprintf(f, "%*d", width, ctx->group); break; case 'i': - printf("%*u", width, ctx->ino); + fprintf(f, "%*u", width, ctx->ino); break; case 'j': - printf("%*u", width, ctx->ino2); + fprintf(f, "%*u", width, ctx->ino2); break; case 'm': - printf("%*s", width, error_message(ctx->errcode)); + fprintf(f, "%*s", width, error_message(ctx->errcode)); break; case 'N': #ifdef EXT2_NO_64_TYPE - printf("%*u", width, ctx->num); + fprintf(f, "%*u", width, ctx->num); #else - printf("%*llu", width, (long long)ctx->num); + fprintf(f, "%*llu", width, (long long)ctx->num); #endif break; case 'p': - print_pathname(fs, ctx->ino, 0); + print_pathname(f, fs, ctx->ino, 0); break; case 'P': - print_pathname(fs, ctx->ino2, + print_pathname(f, fs, ctx->ino2, ctx->dirent ? ctx->dirent->inode : 0); break; case 'q': - print_pathname(fs, ctx->dir, 0); + print_pathname(f, fs, ctx->dir, 0); break; case 'Q': - print_pathname(fs, ctx->dir, ctx->ino); + print_pathname(f, fs, ctx->dir, ctx->ino); break; case 'r': #ifdef EXT2_NO_64_TYPE - printf("%*d", width, ctx->blkcount); + fprintf(f, "%*d", width, ctx->blkcount); #else - printf("%*lld", width, (long long) ctx->blkcount); + fprintf(f, "%*lld", width, (long long) ctx->blkcount); #endif break; case 'S': - printf("%u", get_backup_sb(NULL, fs, NULL, NULL)); + fprintf(f, "%u", get_backup_sb(NULL, fs, NULL, NULL)); break; case 's': - printf("%*s", width, ctx->str ? ctx->str : "NULL"); + fprintf(f, "%*s", width, ctx->str ? ctx->str : "NULL"); break; case 't': - print_time((time_t) ctx->num); + print_time(f, (time_t) ctx->num); break; case 'T': - print_time(e2fsck_ctx ? e2fsck_ctx->now : time(0)); + print_time(f, e2fsck_ctx ? e2fsck_ctx->now : time(0)); break; case 'x': - printf("0x%0*x", width, ctx->csum1); + fprintf(f, "0x%0*x", width, ctx->csum1); break; case 'X': #ifdef EXT2_NO_64_TYPE - printf("0x%0*x", width, ctx->num); + fprintf(f, "0x%0*x", width, ctx->num); #else - printf("0x%0*llx", width, (long long)ctx->num); + fprintf(f, "0x%0*llx", width, (long long)ctx->num); #endif break; case 'y': - printf("0x%0*x", width, ctx->csum2); + fprintf(f, "0x%0*x", width, ctx->csum2); break; default: no_context: - printf("%%%c", ch); + fprintf(f, "%%%c", ch); break; } } -void print_e2fsck_message(e2fsck_t ctx, const char *msg, +void print_e2fsck_message(FILE *f, e2fsck_t ctx, const char *msg, struct problem_context *pctx, int first, int recurse) { @@ -532,7 +533,8 @@ void print_e2fsck_message(e2fsck_t ctx, const char *msg, for (cp = msg; *cp; cp++) { if (cp[0] == '@') { cp++; - expand_at_expression(ctx, *cp, pctx, &first, recurse); + expand_at_expression(f, ctx, *cp, pctx, &first, + recurse); } else if (cp[0] == '%') { cp++; width = 0; @@ -542,19 +544,19 @@ void print_e2fsck_message(e2fsck_t ctx, const char *msg, } if (cp[0] == 'I') { cp++; - expand_inode_expression(fs, *cp, pctx); + expand_inode_expression(f, fs, *cp, pctx); } else if (cp[0] == 'D') { cp++; - expand_dirent_expression(fs, *cp, pctx); + expand_dirent_expression(f, fs, *cp, pctx); } else { - expand_percent_expression(fs, *cp, width, + expand_percent_expression(f, fs, *cp, width, &first, pctx); } } else { for (i=0; cp[i]; i++) if ((cp[i] == '@') || cp[i] == '%') break; - printf("%.*s", i, cp); + fprintf(f, "%.*s", i, cp); cp += i-1; } first = 0; diff --git a/e2fsck/problem.c b/e2fsck/problem.c index 06eb179..56d10b1 100644 --- a/e2fsck/problem.c +++ b/e2fsck/problem.c @@ -1877,16 +1877,20 @@ int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx) fflush(stdout); } } + message = ptr->e2p_description; + if (*message) + message = _(message); if (!suppress) { - message = ptr->e2p_description; if ((ctx->options & E2F_OPT_PREEN) && !(ptr->flags & PR_PREEN_NOHDR)) { printf("%s: ", ctx->device_name ? ctx->device_name : ctx->filesystem_name); } if (*message) - print_e2fsck_message(ctx, _(message), pctx, 1, 0); + print_e2fsck_message(stdout, ctx, message, pctx, 1, 0); } + if (ctx->logf && message) + print_e2fsck_message(ctx->logf, ctx, message, pctx, 1, 0); if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE)) preenhalt(ctx); @@ -1901,16 +1905,14 @@ int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx) } else { if (ptr->flags & PR_FORCE_NO) { answer = 0; - if (!suppress) - print_answer = 1; + print_answer = 1; } else if (ctx->options & E2F_OPT_PREEN) { answer = def_yn; if (!(ptr->flags & PR_PREEN_NOMSG)) print_answer = 1; } else if ((ptr->flags & PR_LATCH_MASK) && (ldesc->flags & (PRL_YES | PRL_NO))) { - if (!suppress) - print_answer = 1; + print_answer = 1; if (ldesc->flags & PRL_YES) answer = 1; else @@ -1921,10 +1923,16 @@ int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx) if (!answer && !(ptr->flags & PR_NO_OK)) ext2fs_unmark_valid(fs); - if (print_answer) - printf("%s.\n", answer ? - _(preen_msg[(int) ptr->prompt]) : _("IGNORED")); - + if (print_answer) { + if (!suppress) + printf("%s.\n", answer ? + _(preen_msg[(int) ptr->prompt]) : + _("IGNORED")); + if (ctx->logf) + fprintf(ctx->logf, "%s.\n", answer ? + _(preen_msg[(int) ptr->prompt]) : + _("IGNORED")); + } } if ((ptr->prompt == PROMPT_ABORT) && answer) @@ -1955,7 +1963,7 @@ profile_get_integer(profile_t profile, const char *name, const char *subname, return 0; } -void print_e2fsck_message(e2fsck_t ctx, const char *msg, +void print_e2fsck_message(FILE *f, e2fsck_t ctx, const char *msg, struct problem_context *pctx, int first, int recurse) { diff --git a/e2fsck/problem.h b/e2fsck/problem.h index 5c1579d..6633055 100644 --- a/e2fsck/problem.h +++ b/e2fsck/problem.h @@ -1034,7 +1034,7 @@ int get_latch_flags(int mask, int *value); void clear_problem_context(struct problem_context *pctx); /* message.c */ -void print_e2fsck_message(e2fsck_t ctx, const char *msg, +void print_e2fsck_message(FILE *f, e2fsck_t ctx, const char *msg, struct problem_context *pctx, int first, int recurse); diff --git a/e2fsck/unix.c b/e2fsck/unix.c index b31a1e3..4f73a4b 100644 --- a/e2fsck/unix.c +++ b/e2fsck/unix.c @@ -130,70 +130,76 @@ static void show_stats(e2fsck_t ctx) frag_percent_total = (frag_percent_total + 5) / 10; if (!verbose) { - printf(_("%s: %u/%u files (%0d.%d%% non-contiguous), %llu/%llu blocks\n"), - ctx->device_name, inodes_used, inodes, - frag_percent_total / 10, frag_percent_total % 10, - blocks_used, blocks); + log_out(ctx, _("%s: %u/%u files (%0d.%d%% non-contiguous), " + "%llu/%llu blocks\n"), + ctx->device_name, inodes_used, inodes, + frag_percent_total / 10, frag_percent_total % 10, + blocks_used, blocks); return; } - printf (P_("\n%8u inode used (%2.2f%%)\n", "\n%8u inodes used (%2.2f%%)\n", - inodes_used), inodes_used, 100.0 * inodes_used / inodes); - printf (P_("%8u non-contiguous file (%0d.%d%%)\n", - "%8u non-contiguous files (%0d.%d%%)\n", - ctx->fs_fragmented), + log_out(ctx, P_("\n%8u inode used (%2.2f%%)\n", + "\n%8u inodes used (%2.2f%%)\n", + inodes_used), inodes_used, + 100.0 * inodes_used / inodes); + log_out(ctx, P_("%8u non-contiguous file (%0d.%d%%)\n", + "%8u non-contiguous files (%0d.%d%%)\n", + ctx->fs_fragmented), ctx->fs_fragmented, frag_percent_file / 10, frag_percent_file % 10); - printf (P_("%8u non-contiguous directory (%0d.%d%%)\n", - "%8u non-contiguous directories (%0d.%d%%)\n", - ctx->fs_fragmented_dir), + log_out(ctx, P_("%8u non-contiguous directory (%0d.%d%%)\n", + "%8u non-contiguous directories (%0d.%d%%)\n", + ctx->fs_fragmented_dir), ctx->fs_fragmented_dir, frag_percent_dir / 10, frag_percent_dir % 10); - printf (_(" # of inodes with ind/dind/tind blocks: %u/%u/%u\n"), + log_out(ctx, _(" # of inodes with ind/dind/tind blocks: " + "%u/%u/%u\n"), ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count); for (j=MAX_EXTENT_DEPTH_COUNT-1; j >=0; j--) if (ctx->extent_depth_count[j]) break; if (++j) { - printf (_(" Extent depth histogram: ")); + log_out(ctx, _(" Extent depth histogram: ")); for (i=0; i < j; i++) { if (i) fputc('/', stdout); - printf("%u", ctx->extent_depth_count[i]); + log_out(ctx, "%u", ctx->extent_depth_count[i]); } - fputc('\n', stdout); + log_out(ctx, "\n"); } - printf (P_("%8llu block used (%2.2f%%)\n", - "%8llu blocks used (%2.2f%%)\n", + log_out(ctx, P_("%8llu block used (%2.2f%%)\n", + "%8llu blocks used (%2.2f%%)\n", blocks_used), blocks_used, 100.0 * blocks_used / blocks); - printf (P_("%8u bad block\n", "%8u bad blocks\n", - ctx->fs_badblocks_count), ctx->fs_badblocks_count); - printf (P_("%8u large file\n", "%8u large files\n", - ctx->large_files), ctx->large_files); - printf (P_("\n%8u regular file\n", "\n%8u regular files\n", - ctx->fs_regular_count), ctx->fs_regular_count); - printf (P_("%8u directory\n", "%8u directories\n", - ctx->fs_directory_count), ctx->fs_directory_count); - printf (P_("%8u character device file\n", - "%8u character device files\n", ctx->fs_chardev_count), + log_out(ctx, P_("%8u bad block\n", "%8u bad blocks\n", + ctx->fs_badblocks_count), ctx->fs_badblocks_count); + log_out(ctx, P_("%8u large file\n", "%8u large files\n", + ctx->large_files), ctx->large_files); + log_out(ctx, P_("\n%8u regular file\n", "\n%8u regular files\n", + ctx->fs_regular_count), ctx->fs_regular_count); + log_out(ctx, P_("%8u directory\n", "%8u directories\n", + ctx->fs_directory_count), ctx->fs_directory_count); + log_out(ctx, P_("%8u character device file\n", + "%8u character device files\n", ctx->fs_chardev_count), ctx->fs_chardev_count); - printf (P_("%8u block device file\n", "%8u block device files\n", - ctx->fs_blockdev_count), ctx->fs_blockdev_count); - printf (P_("%8u fifo\n", "%8u fifos\n", ctx->fs_fifo_count), + log_out(ctx, P_("%8u block device file\n", "%8u block device files\n", + ctx->fs_blockdev_count), ctx->fs_blockdev_count); + log_out(ctx, P_("%8u fifo\n", "%8u fifos\n", ctx->fs_fifo_count), ctx->fs_fifo_count); - printf (P_("%8u link\n", "%8u links\n", - ctx->fs_links_count - dir_links), + log_out(ctx, P_("%8u link\n", "%8u links\n", + ctx->fs_links_count - dir_links), ctx->fs_links_count - dir_links); - printf (P_("%8u symbolic link", "%8u symbolic links", - ctx->fs_symlinks_count), ctx->fs_symlinks_count); - printf (P_(" (%u fast symbolic link)\n", " (%u fast symbolic links)\n", - ctx->fs_fast_symlinks_count), ctx->fs_fast_symlinks_count); - printf (P_("%8u socket\n", "%8u sockets\n", ctx->fs_sockets_count), + log_out(ctx, P_("%8u symbolic link", "%8u symbolic links", + ctx->fs_symlinks_count), ctx->fs_symlinks_count); + log_out(ctx, P_(" (%u fast symbolic link)\n", + " (%u fast symbolic links)\n", + ctx->fs_fast_symlinks_count), + ctx->fs_fast_symlinks_count); + log_out(ctx, P_("%8u socket\n", "%8u sockets\n", ctx->fs_sockets_count), ctx->fs_sockets_count); - printf ("--------\n"); - printf (P_("%8u file\n", "%8u files\n", - ctx->fs_total_count - dir_links), + log_out(ctx, "--------\n"); + log_out(ctx, P_("%8u file\n", "%8u files\n", + ctx->fs_total_count - dir_links), ctx->fs_total_count - dir_links); } @@ -224,19 +230,21 @@ static void check_mount(e2fsck_t ctx) if ((ctx->options & E2F_OPT_READONLY) && !(ctx->options & E2F_OPT_WRITECHECK)) { - printf(_("Warning! %s is mounted.\n"), ctx->filesystem_name); + log_out(ctx, _("Warning! %s is mounted.\n"), + ctx->filesystem_name); return; } - printf(_("%s is mounted. "), ctx->filesystem_name); + log_out(ctx, _("%s is mounted. "), ctx->filesystem_name); if (!ctx->interactive) fatal_error(ctx, _("Cannot continue, aborting.\n\n")); puts("\007\007\007\007"); - printf(_("\n\nWARNING!!! " - "The filesystem is mounted. If you continue you ***WILL***\n" - "cause ***SEVERE*** filesystem damage.\n\n")); + log_out(ctx, _("\n\nWARNING!!! " + "The filesystem is mounted. " + "If you continue you ***WILL***\n" + "cause ***SEVERE*** filesystem damage.\n\n")); puts("\007\007\007"); - cont = ask_yn(_("Do you really want to continue"), 0); + cont = ask_yn(ctx, _("Do you really want to continue"), 0); if (!cont) { printf (_("check aborted.\n")); exit (0); @@ -356,9 +364,9 @@ static void check_if_skip(e2fsck_t ctx) reason = 0; } if (reason) { - fputs(ctx->device_name, stdout); - printf(reason, reason_arg); - fputs(_(", check forced.\n"), stdout); + log_out(ctx, "%s", ctx->device_name); + log_out(ctx, reason, reason_arg); + log_out(ctx, _(", check forced.\n")); return; } @@ -391,12 +399,13 @@ static void check_if_skip(e2fsck_t ctx) } /* Print the summary message when we're skipping a full check */ - printf(_("%s: clean, %u/%u files, %llu/%llu blocks"), ctx->device_name, - fs->super->s_inodes_count - fs->super->s_free_inodes_count, - fs->super->s_inodes_count, - ext2fs_blocks_count(fs->super) - - ext2fs_free_blocks_count(fs->super), - ext2fs_blocks_count(fs->super)); + log_out(ctx, _("%s: clean, %u/%u files, %llu/%llu blocks"), + ctx->device_name, + fs->super->s_inodes_count - fs->super->s_free_inodes_count, + fs->super->s_inodes_count, + ext2fs_blocks_count(fs->super) - + ext2fs_free_blocks_count(fs->super), + ext2fs_blocks_count(fs->super)); next_check = 100000; if (fs->super->s_max_mnt_count > 0) { next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count; @@ -409,14 +418,14 @@ static void check_if_skip(e2fsck_t ctx) if (next_check <= 5) { if (next_check == 1) { if (batt) - fputs(_(" (check deferred; on battery)"), - stdout); + log_out(ctx, _(" (check deferred; " + "on battery)")); else - fputs(_(" (check after next mount)"), stdout); + log_out(ctx, _(" (check after next mount)")); } else - printf(_(" (check in %ld mounts)"), next_check); + log_out(ctx, _(" (check in %ld mounts)"), next_check); } - fputc('\n', stdout); + log_out(ctx, "\n"); skip: ext2fs_close(fs); ctx->fs = NULL; @@ -653,6 +662,12 @@ static void parse_extended_opts(e2fsck_t ctx, const char *opts) } else if (strcmp(token, "nodiscard") == 0) { ctx->options &= ~E2F_OPT_DISCARD; continue; + } else if (strcmp(token, "log_filename") == 0) { + if (!arg) + extended_usage++; + else + ctx->log_fn = string_copy(ctx, arg, 0); + continue; } else { fprintf(stderr, _("Unknown extended option: %s\n"), token); @@ -1071,8 +1086,8 @@ int e2fsck_check_mmp(ext2_filsys fs, e2fsck_t ctx) /* Print warning if e2fck will wait for more than 20 secs. */ if (verbose || wait_time > EXT4_MMP_MIN_CHECK_INTERVAL * 4) { - printf("MMP interval is %u seconds and total wait time is %u " - "seconds. Please wait...\n", + log_out(ctx, _("MMP interval is %u seconds and total wait " + "time is %u seconds. Please wait...\n"), mmp_check_interval, wait_time * 2); } @@ -1157,13 +1172,25 @@ int main (int argc, char *argv[]) } reserve_stdio_fds(); + set_up_logging(ctx); + if (ctx->logf) { + int i; + fputs("E2fsck run: ", ctx->logf); + for (i = 0; i < argc; i++) { + if (i) + fputc(' ', ctx->logf); + fputs(argv[i], ctx->logf); + } + fputc('\n', ctx->logf); + } + init_resource_track(&ctx->global_rtrack, NULL); if (!(ctx->options & E2F_OPT_PREEN) || show_version_only) - fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string, + log_err(ctx, "e2fsck %s (%s)\n", my_ver_string, my_ver_date); if (show_version_only) { - fprintf(stderr, _("\tUsing %s, %s\n"), + log_err(ctx, _("\tUsing %s, %s\n"), error_message(EXT2_ET_BASE), lib_ver_date); exit(FSCK_OK); } @@ -1214,10 +1241,10 @@ restart: fs = NULL; } if (!fs || (fs->group_desc_count > 1)) { - printf(_("%s: %s trying backup blocks...\n"), - ctx->program_name, - retval ? _("Superblock invalid,") : - _("Group descriptors look bad...")); + log_out(ctx, _("%s: %s trying backup blocks...\n"), + ctx->program_name, + retval ? _("Superblock invalid,") : + _("Group descriptors look bad...")); orig_superblock = ctx->superblock; get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr); if (fs) @@ -1227,10 +1254,13 @@ restart: if ((orig_retval == 0) && retval != 0) { if (fs) ext2fs_close(fs); - com_err(ctx->program_name, retval, - "when using the backup blocks"); - printf(_("%s: going back to original " - "superblock\n"), ctx->program_name); + log_out(ctx, _("%s: %s while using the " + "backup blocks"), + ctx->program_name, + error_message(retval)); + log_out(ctx, _("%s: going back to original " + "superblock\n"), + ctx->program_name); ctx->superblock = orig_superblock; retval = try_open_fs(ctx, flags, io_ptr, &fs); } @@ -1256,30 +1286,32 @@ failure: com_err(ctx->program_name, retval, _("while trying to open %s"), ctx->filesystem_name); if (retval == EXT2_ET_REV_TOO_HIGH) { - printf(_("The filesystem revision is apparently " + log_out(ctx, _("The filesystem revision is apparently " "too high for this version of e2fsck.\n" "(Or the filesystem superblock " "is corrupt)\n\n")); fix_problem(ctx, PR_0_SB_CORRUPT, &pctx); } else if (retval == EXT2_ET_SHORT_READ) - printf(_("Could this be a zero-length partition?\n")); + log_out(ctx, _("Could this be a zero-length " + "partition?\n")); else if ((retval == EPERM) || (retval == EACCES)) - printf(_("You must have %s access to the " + log_out(ctx, _("You must have %s access to the " "filesystem or be root\n"), (ctx->options & E2F_OPT_READONLY) ? "r/o" : "r/w"); else if (retval == ENXIO) - printf(_("Possibly non-existent or swap device?\n")); + log_out(ctx, _("Possibly non-existent or " + "swap device?\n")); else if (retval == EBUSY) - printf(_("Filesystem mounted or opened exclusively " - "by another program?\n")); + log_out(ctx, _("Filesystem mounted or opened " + "exclusively by another program?\n")); else if (retval == ENOENT) - printf(_("Possibly non-existent device?\n")); + log_out(ctx, _("Possibly non-existent device?\n")); #ifdef EROFS else if (retval == EROFS) - printf(_("Disk write-protected; use the -n option " - "to do a read-only\n" - "check of the device.\n")); + log_out(ctx, _("Disk write-protected; use the -n " + "option to do a read-only\n" + "check of the device.\n")); #endif else fix_problem(ctx, PR_0_SB_CORRUPT, &pctx); @@ -1336,6 +1368,7 @@ failure: fs->priv_data = ctx; fs->now = ctx->now; sb = fs->super; + if (sb->s_rev_level > E2FSCK_CURRENT_REV) { com_err(ctx->program_name, EXT2_ET_REV_TOO_HIGH, _("while trying to open %s"), @@ -1377,6 +1410,10 @@ failure: goto restart; } + if (ctx->logf) + fprintf(ctx->logf, "Filesystem UUID: %s\n", + e2p_uuid2str(sb->s_uuid)); + if ((ctx->mount_flags & EXT2_MF_MOUNTED) && !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER)) goto skip_journal; @@ -1398,9 +1435,9 @@ failure: */ if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) { if (ctx->options & E2F_OPT_READONLY) { - printf(_("Warning: skipping journal recovery " - "because doing a read-only filesystem " - "check.\n")); + log_out(ctx, _("Warning: skipping journal recovery " + "because doing a read-only filesystem " + "check.\n")); io_channel_flush(ctx->fs->io); } else { if (ctx->flags & E2F_FLAG_RESTARTED) { @@ -1442,30 +1479,30 @@ print_unsupp_features: int i, j; __u32 *mask = features, m; - fprintf(stderr, _("%s has unsupported feature(s):"), + log_err(ctx, _("%s has unsupported feature(s):"), ctx->filesystem_name); for (i=0; i <3; i++,mask++) { for (j=0,m=1; j < 32; j++, m<<=1) { if (*mask & m) - fprintf(stderr, " %s", + log_err(ctx, " %s", e2p_feature2string(i, m)); } } - putc('\n', stderr); + log_err(ctx, "\n"); goto get_newer; } #ifdef ENABLE_COMPRESSION if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION) - com_err(ctx->program_name, 0, - _("Warning: compression support is experimental.\n")); + log_err(ctx, _("%s: warning: compression support " + "is experimental.\n"), + ctx->program_name); #endif #ifndef ENABLE_HTREE if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) { - com_err(ctx->program_name, 0, - _("E2fsck not compiled with HTREE support,\n\t" + log_err(ctx, _("%s: e2fsck not compiled with HTREE support,\n\t" "but filesystem %s has HTREE directories.\n"), - ctx->device_name); + ctx->program_name, ctx->device_name); goto get_newer; } #endif @@ -1515,11 +1552,11 @@ print_unsupp_features: retval = ext2fs_read_bb_inode(fs, &fs->badblocks); if (retval) { - com_err(ctx->program_name, retval, - _("while reading bad blocks inode")); + log_out(ctx, _("%s: %s while reading bad blocks inode\n"), + ctx->program_name, error_message(retval)); preenhalt(ctx); - printf(_("This doesn't bode well," - " but we'll try to go on...\n")); + log_out(ctx, _("This doesn't bode well, " + "but we'll try to go on...\n")); } /* @@ -1556,22 +1593,22 @@ print_unsupp_features: fs->super->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL; fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY; - com_err(ctx->program_name, 0, - _("Couldn't determine journal size")); + log_out(ctx, "%s: Couldn't determine " + "journal size\n", ctx->program_name); goto no_journal; } - printf(_("Creating journal (%d blocks): "), + log_out(ctx, _("Creating journal (%d blocks): "), journal_size); fflush(stdout); retval = ext2fs_add_journal_inode(fs, journal_size, 0); if (retval) { - com_err("Error ", retval, - _("\n\twhile trying to create journal")); + log_out(ctx, "%s: while trying to create " + "journal\n", error_message(retval)); goto no_journal; } - printf(_(" Done.\n")); - printf(_("\n*** journal has been re-created - " + log_out(ctx, _(" Done.\n")); + log_out(ctx, _("\n*** journal has been re-created - " "filesystem is now ext3 again ***\n")); } } @@ -1583,7 +1620,7 @@ no_journal: } if (run_result == E2F_FLAG_RESTART) { - printf(_("Restarting e2fsck from the beginning...\n")); + log_out(ctx, _("Restarting e2fsck from the beginning...\n")); retval = e2fsck_reset_context(ctx); if (retval) { com_err(ctx->program_name, retval, @@ -1594,8 +1631,8 @@ no_journal: goto restart; } if (run_result & E2F_FLAG_CANCEL) { - printf(_("%s: e2fsck canceled.\n"), ctx->device_name ? - ctx->device_name : ctx->filesystem_name); + log_out(ctx, _("%s: e2fsck canceled.\n"), ctx->device_name ? + ctx->device_name : ctx->filesystem_name); exit_value |= FSCK_CANCELED; } if (run_result & E2F_FLAG_ABORT) @@ -1611,19 +1648,20 @@ no_journal: if (ext2fs_test_changed(fs)) { exit_value |= FSCK_NONDESTRUCT; if (!(ctx->options & E2F_OPT_PREEN)) - printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"), - ctx->device_name); + log_out(ctx, _("\n%s: ***** FILE SYSTEM WAS " + "MODIFIED *****\n"), + ctx->device_name); if (ctx->mount_flags & EXT2_MF_ISROOT) { - printf(_("%s: ***** REBOOT LINUX *****\n"), - ctx->device_name); + log_out(ctx, _("%s: ***** REBOOT LINUX *****\n"), + ctx->device_name); exit_value |= FSCK_REBOOT; } } if (!ext2fs_test_valid(fs) || ((exit_value & FSCK_CANCELED) && (sb->s_state & EXT2_ERROR_FS))) { - printf(_("\n%s: ********** WARNING: Filesystem still has " - "errors **********\n\n"), ctx->device_name); + log_out(ctx, _("\n%s: ********** WARNING: Filesystem still has " + "errors **********\n\n"), ctx->device_name); exit_value |= FSCK_UNCORRECTED; exit_value &= ~FSCK_NONDESTRUCT; } diff --git a/e2fsck/util.c b/e2fsck/util.c index 6e3a1dc..7c4caab 100644 --- a/e2fsck/util.c +++ b/e2fsck/util.c @@ -41,6 +41,7 @@ extern e2fsck_t e2fsck_global_ctx; /* Try your very best not to use this! */ +#include <stdarg.h> #include <time.h> #include <sys/time.h> #include <sys/resource.h> @@ -59,18 +60,18 @@ void fatal_error(e2fsck_t ctx, const char *msg) if (ctx->fs->io->magic == EXT2_ET_MAGIC_IO_CHANNEL) io_channel_flush(ctx->fs->io); else - fprintf(stderr, "e2fsck: io manager magic bad!\n"); + log_err(ctx, "e2fsck: io manager magic bad!\n"); } if (ext2fs_test_changed(fs)) { exit_value |= FSCK_NONDESTRUCT; - printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"), + log_out(ctx, _("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"), ctx->device_name); if (ctx->mount_flags & EXT2_MF_ISROOT) exit_value |= FSCK_REBOOT; } if (!ext2fs_test_valid(fs)) { - printf(_("\n%s: ********** WARNING: Filesystem still has " - "errors **********\n\n"), ctx->device_name); + log_out(ctx, _("\n%s: ********** WARNING: Filesystem still has " + "errors **********\n\n"), ctx->device_name); exit_value |= FSCK_UNCORRECTED; exit_value &= ~FSCK_NONDESTRUCT; } @@ -81,6 +82,34 @@ out: exit(exit_value); } +void log_out(e2fsck_t ctx, const char *fmt, ...) +{ + va_list pvar; + + va_start(pvar, fmt); + vprintf(fmt, pvar); + va_end(pvar); + if (ctx->logf) { + va_start(pvar, fmt); + vfprintf(ctx->logf, fmt, pvar); + va_end(pvar); + } +} + +void log_err(e2fsck_t ctx, const char *fmt, ...) +{ + va_list pvar; + + va_start(pvar, fmt); + vfprintf(stderr, fmt, pvar); + va_end(pvar); + if (ctx->logf) { + va_start(pvar, fmt); + vfprintf(ctx->logf, fmt, pvar); + va_end(pvar); + } +} + void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size, const char *description) { @@ -153,7 +182,7 @@ static int read_a_char(void) } #endif -int ask_yn(const char * string, int def) +int ask_yn(e2fsck_t ctx, const char * string, int def) { int c; const char *defstr; @@ -177,7 +206,7 @@ int ask_yn(const char * string, int def) defstr = _(_("<n>")); else defstr = _(" (y/n)"); - printf("%s%s? ", string, defstr); + log_out(ctx, "%s%s? ", string, defstr); while (1) { fflush (stdout); if ((c = read_a_char()) == EOF) @@ -186,12 +215,11 @@ int ask_yn(const char * string, int def) #ifdef HAVE_TERMIOS_H tcsetattr (0, TCSANOW, &termios); #endif - if (e2fsck_global_ctx && - e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) { - puts("\n"); + if (ctx->flags & E2F_FLAG_SETJMP_OK) { + log_out(ctx, "\n"); longjmp(e2fsck_global_ctx->abort_loc, 1); } - puts(_("cancelled!\n")); + log_out(ctx, _("cancelled!\n")); return 0; } if (strchr(short_yes, (char) c)) { @@ -206,9 +234,9 @@ int ask_yn(const char * string, int def) break; } if (def) - puts(_("yes\n")); + log_out(ctx, _("yes\n")); else - puts (_("no\n")); + log_out(ctx, _("no\n")); #ifdef HAVE_TERMIOS_H tcsetattr (0, TCSANOW, &termios); #endif @@ -218,18 +246,18 @@ int ask_yn(const char * string, int def) int ask (e2fsck_t ctx, const char * string, int def) { if (ctx->options & E2F_OPT_NO) { - printf (_("%s? no\n\n"), string); + log_out(ctx, _("%s? no\n\n"), string); return 0; } if (ctx->options & E2F_OPT_YES) { - printf (_("%s? yes\n\n"), string); + log_out(ctx, _("%s? yes\n\n"), string); return 1; } if (ctx->options & E2F_OPT_PREEN) { - printf ("%s? %s\n\n", string, def ? _("yes") : _("no")); + log_out(ctx, "%s? %s\n\n", string, def ? _("yes") : _("no")); return def; } - return ask_yn(string, def); + return ask_yn(ctx, string, def); } void e2fsck_read_bitmaps(e2fsck_t ctx) @@ -283,7 +311,7 @@ void preenhalt(e2fsck_t ctx) if (!(ctx->options & E2F_OPT_PREEN)) return; - fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; " + log_err(ctx, _("\n\n%s: UNEXPECTED INCONSISTENCY; " "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"), ctx->device_name); ctx->flags |= E2F_FLAG_EXITING; @@ -358,30 +386,30 @@ void print_resource_track(e2fsck_t ctx, const char *desc, gettimeofday(&time_end, 0); if (desc) - printf("%s: ", desc); + log_out(ctx, "%s: ", desc); #ifdef HAVE_MALLINFO #define kbytes(x) (((unsigned long)(x) + 1023) / 1024) malloc_info = mallinfo(); - printf(_("Memory used: %luk/%luk (%luk/%luk), "), - kbytes(malloc_info.arena), kbytes(malloc_info.hblkhd), - kbytes(malloc_info.uordblks), kbytes(malloc_info.fordblks)); + log_out(ctx, _("Memory used: %luk/%luk (%luk/%luk), "), + kbytes(malloc_info.arena), kbytes(malloc_info.hblkhd), + kbytes(malloc_info.uordblks), kbytes(malloc_info.fordblks)); #else - printf(_("Memory used: %lu, "), - (unsigned long) (((char *) sbrk(0)) - - ((char *) track->brk_start))); + log_out(ctx, _("Memory used: %lu, "), + (unsigned long) (((char *) sbrk(0)) - + ((char *) track->brk_start))); #endif #ifdef HAVE_GETRUSAGE getrusage(RUSAGE_SELF, &r); - printf(_("time: %5.2f/%5.2f/%5.2f\n"), - timeval_subtract(&time_end, &track->time_start), - timeval_subtract(&r.ru_utime, &track->user_start), - timeval_subtract(&r.ru_stime, &track->system_start)); + log_out(ctx, _("time: %5.2f/%5.2f/%5.2f\n"), + timeval_subtract(&time_end, &track->time_start), + timeval_subtract(&r.ru_utime, &track->user_start), + timeval_subtract(&r.ru_stime, &track->system_start)); #else - printf(_("elapsed time: %6.3f\n"), - timeval_subtract(&time_end, &track->time_start)); + log_out(ctx, _("elapsed time: %6.3f\n"), + timeval_subtract(&time_end, &track->time_start)); #endif #define mbytes(x) (((x) + 1048575) / 1048576) if (channel && channel->manager && channel->manager->get_stats) { @@ -390,7 +418,7 @@ void print_resource_track(e2fsck_t ctx, const char *desc, unsigned long long bytes_written = 0; if (desc) - printf("%s: ", desc); + log_out(ctx, "%s: ", desc); channel->manager->get_stats(channel, &delta); if (delta) { @@ -398,10 +426,11 @@ void print_resource_track(e2fsck_t ctx, const char *desc, bytes_written = delta->bytes_written - track->bytes_written; } - printf("I/O read: %lluMB, write: %lluMB, rate: %.2fMB/s\n", - mbytes(bytes_read), mbytes(bytes_written), - (double)mbytes(bytes_read + bytes_written) / - timeval_subtract(&time_end, &track->time_start)); + log_out(ctx, "I/O read: %lluMB, write: %lluMB, " + "rate: %.2fMB/s\n", + mbytes(bytes_read), mbytes(bytes_written), + (double)mbytes(bytes_read + bytes_written) / + timeval_subtract(&time_end, &track->time_start)); } } #endif /* RESOURCE_TRACK */ -- 1.7.9.107.g97f9a -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html