Skip to content

Commit

Permalink
mke2fs: the -d option can now handle tarball input
Browse files Browse the repository at this point in the history
If archive.h is available during compilation, enable mke2fs to read a
tarball as input. Since libarchive.so.13 is opened with dlopen,
libarchive is not a hard library dependency of the resulting binary.

In comparison with feeding a directory tree to mke2fs via -d this has
the following advantages:

 - no superuser privileges, nor fakeroot, nor unshared user namespaces
   are needed to create filesystems with arbitrary ownership information
   and special files like device nodes which otherwise require being root

 - by reading a tarball from standard input, no temporary files need to
   be written out first as mke2fs can be used as part of a shell pipeline
   which reduces disk usage and makes the conversion independent of the
   underlying file system

A round-trip from tarball to ext4 to tarball yields bit-by-bit identical
results

Signed-off-by: Johannes Schauer Marin Rodrigues <josch@mister-muffin.de>
  • Loading branch information
josch committed Apr 18, 2024
1 parent 260dfea commit 7e3a4f0
Show file tree
Hide file tree
Showing 25 changed files with 1,846 additions and 35 deletions.
1 change: 1 addition & 0 deletions MCONFIG.in
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ LIBFUSE = @FUSE_LIB@
LIBSUPPORT = $(LIBINTL) $(LIB)/libsupport@STATIC_LIB_EXT@
LIBBLKID = @LIBBLKID@ @PRIVATE_LIBS_CMT@ $(LIBUUID)
LIBINTL = @LIBINTL@
LIBARCHIVE = @ARCHIVE_LIB@
SYSLIBS = @LIBS@ @PTHREAD_LIBS@
DEPLIBSS = $(LIB)/libss@LIB_EXT@
DEPLIBCOM_ERR = $(LIB)/libcom_err@LIB_EXT@
Expand Down
52 changes: 52 additions & 0 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,7 @@ SEM_INIT_LIB
FUSE_CMT
FUSE_LIB
CLOCK_GETTIME_LIB
ARCHIVE_LIB
MAGIC_LIB
SOCKET_LIB
SIZEOF_TIME_T
Expand Down Expand Up @@ -13540,6 +13541,57 @@ if test "$ac_cv_func_dlopen" = yes ; then
MAGIC_LIB=$DLOPEN_LIB
fi

{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for archive_read_new in -larchive" >&5
printf %s "checking for archive_read_new in -larchive... " >&6; }
if test ${ac_cv_lib_archive_archive_read_new+y}
then :
printf %s "(cached) " >&6
else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-larchive $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
char archive_read_new ();
int
main (void)
{
return archive_read_new ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
ac_cv_lib_archive_archive_read_new=yes
else $as_nop
ac_cv_lib_archive_archive_read_new=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_archive_archive_read_new" >&5
printf "%s\n" "$ac_cv_lib_archive_archive_read_new" >&6; }
if test "x$ac_cv_lib_archive_archive_read_new" = xyes
then :
ARCHIVE_LIB=-larchive
ac_fn_c_check_header_compile "$LINENO" "archive.h" "ac_cv_header_archive_h" "$ac_includes_default"
if test "x$ac_cv_header_archive_h" = xyes
then :
printf "%s\n" "#define HAVE_ARCHIVE_H 1" >>confdefs.h

fi

fi

if test "$ac_cv_func_dlopen" = yes ; then
ARCHIVE_LIB=$DLOPEN_LIB
fi

{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
printf %s "checking for clock_gettime in -lrt... " >&6; }
if test ${ac_cv_lib_rt_clock_gettime+y}
Expand Down
9 changes: 9 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -1298,6 +1298,15 @@ if test "$ac_cv_func_dlopen" = yes ; then
fi
AC_SUBST(MAGIC_LIB)
dnl
dnl libarchive
dnl
AC_CHECK_LIB(archive, archive_read_new, [ARCHIVE_LIB=-larchive
AC_CHECK_HEADERS([archive.h])])
if test "$ac_cv_func_dlopen" = yes ; then
ARCHIVE_LIB=$DLOPEN_LIB
fi
AC_SUBST(ARCHIVE_LIB)
dnl
dnl Check to see if librt is required for clock_gettime() (glibc < 2.17)
dnl
AC_CHECK_LIB(rt, clock_gettime, [CLOCK_GETTIME_LIB=-lrt])
Expand Down
25 changes: 21 additions & 4 deletions debugfs/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ MK_CMDS= _SS_DIR_OVERRIDE=$(srcdir)/../lib/ss ../lib/ss/mk_cmds
DEBUG_OBJS= debug_cmds.o debugfs.o util.o ncheck.o icheck.o ls.o \
lsdel.o dump.o set_fields.o logdump.o htree.o unused.o e2freefrag.o \
filefrag.o extent_cmds.o extent_inode.o zap.o create_inode.o \
quota.o xattrs.o journal.o revoke.o recovery.o do_journal.o
create_inode_libarchive.o quota.o xattrs.o journal.o revoke.o \
recovery.o do_journal.o

RO_DEBUG_OBJS= ro_debug_cmds.o ro_debugfs.o util.o ncheck.o icheck.o ls.o \
lsdel.o logdump.o htree.o e2freefrag.o filefrag.o extent_cmds.o \
Expand All @@ -31,12 +32,13 @@ SRCS= debug_cmds.c $(srcdir)/debugfs.c $(srcdir)/util.c $(srcdir)/ls.c \
$(srcdir)/dump.c $(srcdir)/set_fields.c ${srcdir}/logdump.c \
$(srcdir)/htree.c $(srcdir)/unused.c ${srcdir}/../misc/e2freefrag.c \
$(srcdir)/filefrag.c $(srcdir)/extent_inode.c $(srcdir)/zap.c \
$(srcdir)/../misc/create_inode.c $(srcdir)/xattrs.c $(srcdir)/quota.c \
$(srcdir)/journal.c $(srcdir)/../e2fsck/revoke.c \
$(srcdir)/../misc/create_inode.c \
$(srcdir)/../misc/create_inode_libarchive.c $(srcdir)/xattrs.c \
$(srcdir)/quota.c $(srcdir)/journal.c $(srcdir)/../e2fsck/revoke.c \
$(srcdir)/../e2fsck/recovery.c $(srcdir)/do_journal.c

LIBS= $(LIBSUPPORT) $(LIBEXT2FS) $(LIBE2P) $(LIBSS) $(LIBCOM_ERR) $(LIBBLKID) \
$(LIBUUID) $(LIBMAGIC) $(SYSLIBS)
$(LIBUUID) $(LIBMAGIC) $(SYSLIBS) $(LIBARCHIVE)
DEPLIBS= $(DEPLIBSUPPORT) $(LIBEXT2FS) $(LIBE2P) $(DEPLIBSS) $(DEPLIBCOM_ERR) \
$(DEPLIBBLKID) $(DEPLIBUUID)

Expand Down Expand Up @@ -113,6 +115,11 @@ create_inode.o: $(srcdir)/../misc/create_inode.c
$(Q) $(CC) -c $(ALL_CFLAGS) -I$(srcdir) \
$(srcdir)/../misc/create_inode.c -o $@

create_inode_libarchive.o: $(srcdir)/../misc/create_inode_libarchive.c
$(E) " CC $@"
$(Q) $(CC) -c $(ALL_CFLAGS) -I$(srcdir) \
$(srcdir)/../misc/create_inode_libarchive.c -o $@

debugfs.8: $(DEP_SUBSTITUTE) $(srcdir)/debugfs.8.in
$(E) " SUBST $@"
$(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/debugfs.8.in debugfs.8
Expand Down Expand Up @@ -357,6 +364,16 @@ create_inode.o: $(srcdir)/../misc/create_inode.c $(top_builddir)/lib/config.h \
$(top_srcdir)/lib/ext2fs/bitops.h $(top_srcdir)/lib/ext2fs/fiemap.h \
$(srcdir)/../misc/create_inode.h $(top_srcdir)/lib/e2p/e2p.h \
$(top_srcdir)/lib/support/nls-enable.h
create_inode_libarchive.o: $(srcdir)/../misc/create_inode_libarchive.c \
$(top_builddir)/lib/config.h $(srcdir)/../misc/create_inode_libarchive.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/hashmap.h \
$(top_srcdir)/lib/ext2fs/bitops.h $(top_srcdir)/lib/ext2fs/fiemap.h \
$(srcdir)/../misc/create_inode.h $(top_srcdir)/lib/e2p/e2p.h \
$(top_srcdir)/lib/support/nls-enable.h
xattrs.o: $(srcdir)/xattrs.c $(top_builddir)/lib/config.h \
$(top_builddir)/lib/dirpaths.h $(top_srcdir)/lib/support/cstring.h \
$(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \
Expand Down
3 changes: 3 additions & 0 deletions lib/config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@
/* Define to 1 if you have the `add_key' function. */
#undef HAVE_ADD_KEY

/* Define to 1 if you have the <archive.h> header file. */
#undef HAVE_ARCHIVE_H

/* Define to 1 if you have the <attr/xattr.h> header file. */
#undef HAVE_ATTR_XATTR_H

Expand Down
25 changes: 21 additions & 4 deletions lib/ext2fs/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ COMPILE_ET= _ET_DIR_OVERRIDE=$(srcdir)/../et ../et/compile_et
DEBUG_OBJS= debug_cmds.o extent_cmds.o tst_cmds.o debugfs.o util.o \
ncheck.o icheck.o ls.o lsdel.o dump.o set_fields.o logdump.o \
htree.o unused.o e2freefrag.o filefrag.o extent_inode.o zap.o \
xattrs.o quota.o tst_libext2fs.o create_inode.o journal.o \
revoke.o recovery.o do_journal.o
xattrs.o quota.o tst_libext2fs.o create_inode.o \
create_inode_libarchive.o journal.o revoke.o recovery.o do_journal.o

DEBUG_SRCS= debug_cmds.c extent_cmds.c tst_cmds.c \
$(top_srcdir)/debugfs/debugfs.c \
Expand All @@ -46,6 +46,7 @@ DEBUG_SRCS= debug_cmds.c extent_cmds.c tst_cmds.c \
$(top_srcdir)/debugfs/xattrs.c \
$(top_srcdir)/misc/e2freefrag.c \
$(top_srcdir)/misc/create_inode.c \
$(top_srcdir)/misc/create_inode_libarchive.c \
$(top_srcdir)/debugfs/journal.c \
$(top_srcdir)/e2fsck/revoke.c \
$(top_srcdir)/e2fsck/recovery.c \
Expand Down Expand Up @@ -458,7 +459,13 @@ e2freefrag.o: $(top_srcdir)/misc/e2freefrag.c
$(E) " CC $<"
$(Q) $(CC) $(ALL_CFLAGS) -DDEBUGFS -I$(top_srcdir)/debugfs -c $< -o $@

create_inode.o: $(top_srcdir)/misc/create_inode.c
create_inode.o: $(top_srcdir)/misc/create_inode.c \
$(top_srcdir)/misc/create_inode_libarchive.c
$(E) " CC $<"
$(Q) $(CC) $(ALL_CFLAGS) -DDEBUGFS -c $< -o $@

create_inode_libarchive.o: $(top_srcdir)/misc/create_inode_libarchive.c \
$(top_srcdir)/misc/create_inode_libarchive.c
$(E) " CC $<"
$(Q) $(CC) $(ALL_CFLAGS) -DDEBUGFS -c $< -o $@

Expand Down Expand Up @@ -499,7 +506,7 @@ tst_libext2fs: $(DEBUG_OBJS) \
$(Q) $(CC) -o tst_libext2fs $(ALL_LDFLAGS) -DDEBUG $(DEBUG_OBJS) \
$(STATIC_LIBSS) $(STATIC_LIBE2P) $(LIBSUPPORT) \
$(STATIC_LIBEXT2FS) $(LIBBLKID) $(LIBUUID) $(LIBMAGIC) \
$(STATIC_LIBCOM_ERR) $(SYSLIBS) -I $(top_srcdir)/debugfs
$(STATIC_LIBCOM_ERR) $(SYSLIBS) $(LIBARCHIVE) -I $(top_srcdir)/debugfs

tst_inline: $(srcdir)/inline.c $(STATIC_LIBEXT2FS) $(DEPSTATIC_LIBCOM_ERR)
$(E) " LD $@"
Expand Down Expand Up @@ -1413,6 +1420,16 @@ e2freefrag.o: $(top_srcdir)/misc/e2freefrag.c $(top_builddir)/lib/config.h \
$(top_srcdir)/lib/support/dqblk_v2.h \
$(top_srcdir)/lib/support/quotaio_tree.h
create_inode.o: $(top_srcdir)/misc/create_inode.c \
$(top_srcdir)/misc/create_inode_libarchive.c \
$(top_builddir)/lib/config.h $(top_builddir)/lib/dirpaths.h \
$(srcdir)/ext2fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
$(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \
$(srcdir)/ext2_ext_attr.h $(srcdir)/hashmap.h $(srcdir)/bitops.h \
$(srcdir)/fiemap.h $(top_srcdir)/misc/create_inode.h \
$(top_srcdir)/lib/e2p/e2p.h $(top_srcdir)/lib/support/nls-enable.h
create_inode_libarchive.o: $(top_srcdir)/misc/create_inode_libarchive.c \
$(top_srcdir)/misc/create_inode_libarchive.c \
$(top_builddir)/lib/config.h $(top_builddir)/lib/dirpaths.h \
$(srcdir)/ext2fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \
$(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \
Expand Down
17 changes: 14 additions & 3 deletions misc/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ LPROGS= @E2INITRD_PROG@
TUNE2FS_OBJS= tune2fs.o util.o journal.o recovery.o revoke.o
MKLPF_OBJS= mklost+found.o
MKE2FS_OBJS= mke2fs.o util.o default_profile.o mk_hugefiles.o \
create_inode.o
create_inode.o create_inode_libarchive.o
CHATTR_OBJS= chattr.o
LSATTR_OBJS= lsattr.o
UUIDGEN_OBJS= uuidgen.o
Expand All @@ -80,7 +80,8 @@ PROFILED_MKLPF_OBJS= profiled/mklost+found.o
PROFILED_MKE2FS_OBJS= profiled/mke2fs.o profiled/util.o \
profiled/default_profile.o \
profiled/mk_hugefiles.o \
profiled/create_inode.o
profiled/create_inode.o \
profiled/create_inode_libarchive.o
PROFILED_CHATTR_OBJS= profiled/chattr.o
PROFILED_LSATTR_OBJS= profiled/lsattr.o
PROFILED_UUIDGEN_OBJS= profiled/uuidgen.o
Expand Down Expand Up @@ -281,7 +282,7 @@ mke2fs: $(MKE2FS_OBJS) $(DEPLIBS) $(LIBE2P) $(DEPLIBBLKID) $(DEPLIBUUID) \
$(E) " LD $@"
$(Q) $(CC) $(ALL_LDFLAGS) -o mke2fs $(MKE2FS_OBJS) $(LIBS) $(LIBBLKID) \
$(LIBUUID) $(LIBEXT2FS) $(LIBE2P) $(LIBINTL) \
$(SYSLIBS) $(LIBMAGIC)
$(SYSLIBS) $(LIBMAGIC) $(LIBARCHIVE)

mke2fs.static: $(MKE2FS_OBJS) $(STATIC_DEPLIBS) $(STATIC_LIBE2P) $(DEPSTATIC_LIBUUID) \
$(DEPSTATIC_LIBBLKID)
Expand Down Expand Up @@ -857,6 +858,16 @@ create_inode.o: $(srcdir)/create_inode.c $(top_builddir)/lib/config.h \
$(top_srcdir)/lib/ext2fs/bitops.h $(top_srcdir)/lib/ext2fs/fiemap.h \
$(srcdir)/create_inode.h $(top_srcdir)/lib/e2p/e2p.h \
$(top_srcdir)/lib/support/nls-enable.h
create_inode_libarchive.o: $(srcdir)/create_inode_libarchive.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/hashmap.h \
$(top_srcdir)/lib/ext2fs/bitops.h $(top_srcdir)/lib/ext2fs/fiemap.h \
$(srcdir)/create_inode.h $(top_srcdir)/lib/e2p/e2p.h \
$(top_srcdir)/lib/support/nls-enable.h
fuse2fs.o: $(srcdir)/fuse2fs.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 \
Expand Down
45 changes: 31 additions & 14 deletions misc/create_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
#include "create_inode.h"
#include "support/nls-enable.h"

#include "create_inode_libarchive.h"

/* 64KiB is the minimum blksize to best minimize system call overhead. */
#define COPY_FILE_BUFLEN 65536

Expand Down Expand Up @@ -69,7 +71,7 @@ static int ext2_file_type(unsigned int mode)
}

/* Link an inode number to a directory */
static errcode_t add_link(ext2_filsys fs, ext2_ino_t parent_ino,
errcode_t add_link(ext2_filsys fs, ext2_ino_t parent_ino,
ext2_ino_t ino, const char *name)
{
struct ext2_inode inode;
Expand Down Expand Up @@ -108,8 +110,8 @@ static errcode_t add_link(ext2_filsys fs, ext2_ino_t parent_ino,
}

/* Set the uid, gid, mode and time for the inode */
static errcode_t set_inode_extra(ext2_filsys fs, ext2_ino_t ino,
struct stat *st)
errcode_t set_inode_extra(ext2_filsys fs, ext2_ino_t ino,
const struct stat *st)
{
errcode_t retval;
struct ext2_inode inode;
Expand Down Expand Up @@ -720,12 +722,6 @@ errcode_t do_write_internal(ext2_filsys fs, ext2_ino_t cwd, const char *src,
return retval;
}

struct file_info {
char *path;
size_t path_len;
size_t path_max_len;
};

static errcode_t path_append(struct file_info *target, const char *file)
{
if (strlen(file) + target->path_len + 1 > target->path_max_len) {
Expand Down Expand Up @@ -1044,7 +1040,7 @@ static errcode_t __populate_fs(ext2_filsys fs, ext2_ino_t parent_ino,
}

errcode_t populate_fs2(ext2_filsys fs, ext2_ino_t parent_ino,
const char *source_dir, ext2_ino_t root,
const char *source, ext2_ino_t root,
struct fs_ops_callbacks *fs_callbacks)
{
struct file_info file_info;
Expand All @@ -1069,14 +1065,35 @@ errcode_t populate_fs2(ext2_filsys fs, ext2_ino_t parent_ino,
file_info.path_max_len = 255;
file_info.path = calloc(file_info.path_max_len, 1);

retval = set_inode_xattr(fs, root, source_dir);
/* interpret input as tarball either if it's "-" (stdin) or if it's
* a regular file (or a symlink pointing to a regular file)
*/
if (strcmp(source, "-") == 0) {
retval = __populate_fs_from_tar(fs, parent_ino, NULL, root, &hdlinks,
&file_info, fs_callbacks);
goto out;
}

struct stat st;
if (stat(source, &st)) {
retval = errno;
com_err(__func__, retval, _("while calling stat"));
return retval;
}
if (S_ISREG(st.st_mode)) {
retval = __populate_fs_from_tar(fs, parent_ino, source, root, &hdlinks,
&file_info, fs_callbacks);
goto out;
}

retval = set_inode_xattr(fs, root, source);
if (retval) {
com_err(__func__, retval,
_("while copying xattrs on root directory"));
goto out;
}

retval = __populate_fs(fs, parent_ino, source_dir, root, &hdlinks,
retval = __populate_fs(fs, parent_ino, source, root, &hdlinks,
&file_info, fs_callbacks);

out:
Expand All @@ -1086,7 +1103,7 @@ errcode_t populate_fs2(ext2_filsys fs, ext2_ino_t parent_ino,
}

errcode_t populate_fs(ext2_filsys fs, ext2_ino_t parent_ino,
const char *source_dir, ext2_ino_t root)
const char *source, ext2_ino_t root)
{
return populate_fs2(fs, parent_ino, source_dir, root, NULL);
return populate_fs2(fs, parent_ino, source, root, NULL);
}
10 changes: 10 additions & 0 deletions misc/create_inode.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ struct hdlinks_s
struct hdlink_s *hdl;
};

struct file_info {
char *path;
size_t path_len;
size_t path_max_len;
};

#define HDLINK_CNT (4)

struct fs_ops_callbacks {
Expand Down Expand Up @@ -53,5 +59,9 @@ extern errcode_t do_mkdir_internal(ext2_filsys fs, ext2_ino_t cwd,
extern errcode_t do_write_internal(ext2_filsys fs, ext2_ino_t cwd,
const char *src, const char *dest,
ext2_ino_t root);
extern errcode_t add_link(ext2_filsys fs, ext2_ino_t parent_ino,
ext2_ino_t ino, const char *name);
extern errcode_t set_inode_extra(ext2_filsys fs, ext2_ino_t ino,
const struct stat *st);

#endif /* _CREATE_INODE_H */

0 comments on commit 7e3a4f0

Please sign in to comment.