./0000775000175000017500000000000012511411356011434 5ustar nielsenrnielsenr./0004-misc-create_inode.c-create-symlink.patch0000664000175000017500000000332512511411356021561 0ustar nielsenrnielsenrFrom 09d3049776882167f7249ee26265b4163d7222c1 Mon Sep 17 00:00:00 2001 From: Robert Yang Date: Mon, 23 Dec 2013 03:19:55 -0500 Subject: [PATCH 04/11] misc/create_inode.c: create symlink The do_symlink_internal() is used for creating symlinks, most of the code are from debugfs/debugfs.c, the debugfs/debugfs.c will be modified to use this function. Upstream-Status: Backport Signed-off-by: Robert Yang Reviewed-by: Darren Hart --- misc/create_inode.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/misc/create_inode.c b/misc/create_inode.c index 4da8aff..f845103 100644 --- a/misc/create_inode.c +++ b/misc/create_inode.c @@ -88,6 +88,38 @@ errcode_t do_mknod_internal(ext2_ino_t cwd, const char *name, struct stat *st) /* Make a symlink name -> target */ errcode_t do_symlink_internal(ext2_ino_t cwd, const char *name, char *target) { + char *cp; + ext2_ino_t parent_ino; + errcode_t retval; + struct ext2_inode inode; + struct stat st; + + cp = strrchr(name, '/'); + if (cp) { + *cp = 0; + if ((retval = ext2fs_namei(current_fs, root, cwd, name, &parent_ino))){ + com_err(name, retval, 0); + return retval; + } + name = cp+1; + } else + parent_ino = cwd; + +try_again: + retval = ext2fs_symlink(current_fs, parent_ino, 0, name, target); + if (retval == EXT2_ET_DIR_NO_SPACE) { + retval = ext2fs_expand_dir(current_fs, parent_ino); + if (retval) { + com_err("do_symlink_internal", retval, "while expanding directory"); + return retval; + } + goto try_again; + } + if (retval) { + com_err("ext2fs_symlink", retval, 0); + return retval; + } + } /* Make a directory in the fs */ -- 1.7.10.4 ./quiet-debugfs.patch0000664000175000017500000000114312511411356015220 0ustar nielsenrnielsenrWhen executing a script don't echo every command, as we do this for entire filesystems at rootfs time. Upstream-Status: Inappropriate Signed-off-by: Ross Burton diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c index 5590295..ac57292 100644 --- a/debugfs/debugfs.c +++ b/debugfs/debugfs.c @@ -2378,7 +2378,7 @@ static int source_file(const char *cmd_file, int ss_idx) cp = strchr(buf, '\r'); if (cp) *cp = 0; - printf("debugfs: %s\n", buf); + /*printf("debugfs: %s\n", buf);*/ retval = ss_execute_line(ss_idx, buf); if (retval) { ss_perror(ss_idx, retval, buf); ./mkdir.patch0000664000175000017500000000203512511411356013563 0ustar nielsenrnielsenrUpstream-Status: Inappropriate [configuration] Signed-off-by: Mei Lei Index: e2fsprogs-1.41.5/po/Makefile.in.in =================================================================== --- e2fsprogs-1.41.5.orig/po/Makefile.in.in 2009-02-14 13:49:08.000000000 +0000 +++ e2fsprogs-1.41.5/po/Makefile.in.in 2009-08-19 17:52:31.000000000 +0100 @@ -30,7 +30,7 @@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ MKINSTALLDIRS = @MKINSTALLDIRS@ -mkinstalldirs = $(SHELL) $(MKINSTALLDIRS) +mkinstalldirs = $(MKINSTALLDIRS) GMSGFMT = @GMSGFMT@ MSGFMT = @MSGFMT@ Index: e2fsprogs-1.41.5/configure.in =================================================================== --- e2fsprogs-1.41.5.orig/configure.in 2009-08-19 17:53:50.000000000 +0100 +++ e2fsprogs-1.41.5/configure.in 2009-08-19 17:48:38.000000000 +0100 @@ -970,6 +970,8 @@ fi AC_SUBST(BUILD_CFLAGS) AC_SUBST(BUILD_LDFLAGS) +MKINSTALLDIRS="mkdir -p" +AC_SUBST(MKINSTALLDIRS) dnl dnl Make our output files, being sure that we create the some miscellaneous dnl directories ./acinclude.m40000664000175000017500000001161412511411356013630 0ustar nielsenrnielsenr# Extracted from the package's shipped aclocal.m4. Custom macros should be in # acinclude.m4 so running aclocal doesn't blow them away. # # Signed-off-by: Ross Burton # from http://autoconf-archive.cryp.to/ax_tls.html # # This was licensed under the GPL with the following exception: # # As a special exception, the respective Autoconf Macro's copyright # owner gives unlimited permission to copy, distribute and modify the # configure scripts that are the output of Autoconf when processing # the Macro. You need not follow the terms of the GNU General Public # License when using or distributing such scripts, even though # portions of the text of the Macro appear in them. The GNU General # Public License (GPL) does govern all other use of the material that # constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the # Autoconf Macro released by the Autoconf Macro Archive. When you make # and distribute a modified version of the Autoconf Macro, you may # extend this special exception to the GPL to apply to your modified # version as well. # AC_DEFUN([AX_TLS], [ AC_MSG_CHECKING(for thread local storage (TLS) class) AC_CACHE_VAL(ac_cv_tls, [ ax_tls_keywords="__thread __declspec(thread) none" for ax_tls_keyword in $ax_tls_keywords; do case $ax_tls_keyword in none) ac_cv_tls=none ; break ;; *) AC_TRY_COMPILE( [#include static void foo(void) { static ] $ax_tls_keyword [ int bar; exit(1); }], [], [ac_cv_tls=$ax_tls_keyword ; break], ac_cv_tls=none ) esac done ]) if test "$ac_cv_tls" != "none"; then dnl AC_DEFINE([TLS], [], [If the compiler supports a TLS storage class define it to that here]) AC_DEFINE_UNQUOTED([TLS], $ac_cv_tls, [If the compiler supports a TLS storage class define it to that here]) fi AC_MSG_RESULT($ac_cv_tls) ]) # =========================================================================== # http://www.nongnu.org/autoconf-archive/check_gnu_make.html # =========================================================================== # # SYNOPSIS # # CHECK_GNU_MAKE() # # DESCRIPTION # # This macro searches for a GNU version of make. If a match is found, the # makefile variable `ifGNUmake' is set to the empty string, otherwise it # is set to "#". This is useful for including a special features in a # Makefile, which cannot be handled by other versions of make. The # variable _cv_gnu_make_command is set to the command to invoke GNU make # if it exists, the empty string otherwise. # # Here is an example of its use: # # Makefile.in might contain: # # # A failsafe way of putting a dependency rule into a makefile # $(DEPEND): # $(CC) -MM $(srcdir)/*.c > $(DEPEND) # # @ifGNUmake@ ifeq ($(DEPEND),$(wildcard $(DEPEND))) # @ifGNUmake@ include $(DEPEND) # @ifGNUmake@ endif # # Then configure.in would normally contain: # # CHECK_GNU_MAKE() # AC_OUTPUT(Makefile) # # Then perhaps to cause gnu make to override any other make, we could do # something like this (note that GNU make always looks for GNUmakefile # first): # # if ! test x$_cv_gnu_make_command = x ; then # mv Makefile GNUmakefile # echo .DEFAULT: > Makefile ; # echo \ $_cv_gnu_make_command \$@ >> Makefile; # fi # # Then, if any (well almost any) other make is called, and GNU make also # exists, then the other make wraps the GNU make. # # LICENSE # # Copyright (c) 2008 John Darrington # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. # # Note: Modified by Ted Ts'o to add @ifNotGNUMake@ AC_DEFUN( [CHECK_GNU_MAKE], [ AC_CACHE_CHECK( for GNU make,_cv_gnu_make_command, _cv_gnu_make_command='' ; dnl Search all the common names for GNU make for a in "$MAKE" make gmake gnumake ; do if test -z "$a" ; then continue ; fi ; if ( sh -c "$a --version" 2> /dev/null | grep GNU 2>&1 > /dev/null ) ; then _cv_gnu_make_command=$a ; break; fi done ; ) ; dnl If there was a GNU version, then set @ifGNUmake@ to the empty string, '#' otherwise if test "x$_cv_gnu_make_command" != "x" ; then ifGNUmake='' ; ifNotGNUmake='#' ; else ifGNUmake='#' ; ifNotGNUmake='' ; AC_MSG_RESULT("Not found"); fi AC_SUBST(ifGNUmake) AC_SUBST(ifNotGNUmake) ] ) ./0002-misc-create_inode.c-copy-files-recursively.patch0000664000175000017500000000737212511411356023262 0ustar nielsenrnielsenrFrom 08dfbaf4e3f704232ff46d78c0758a6cfe3961c8 Mon Sep 17 00:00:00 2001 From: Robert Yang Date: Mon, 23 Dec 2013 02:59:10 -0500 Subject: [PATCH 02/11] misc/create_inode.c: copy files recursively Use opendir() and readdir() to read the native directory, then use lstat() to identify the file type and call the corresponding function to add the file to the filesystem, call the populate_fs() recursively if it is a directory. NOTE: the libext2fs can't create the socket file. Upstream-Status: Backport Signed-off-by: Robert Yang Reviewed-by: Darren Hart --- misc/create_inode.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/misc/create_inode.c b/misc/create_inode.c index 46aaa60..b68b910 100644 --- a/misc/create_inode.c +++ b/misc/create_inode.c @@ -1,5 +1,13 @@ #include "create_inode.h" +#if __STDC_VERSION__ < 199901L +# if __GNUC__ >= 2 +# define __func__ __FUNCTION__ +# else +# define __func__ "" +# endif +#endif + /* Make a special file which is block, character and fifo */ errcode_t do_mknod_internal(ext2_ino_t cwd, const char *name, struct stat *st) { @@ -23,4 +31,93 @@ errcode_t do_write_internal(ext2_ino_t cwd, const char *src, const char *dest) /* Copy files from source_dir to fs */ errcode_t populate_fs(ext2_ino_t parent_ino, const char *source_dir) { + const char *name; + DIR *dh; + struct dirent *dent; + struct stat st; + char ln_target[PATH_MAX]; + ext2_ino_t ino; + errcode_t retval; + int read_cnt; + + root = EXT2_ROOT_INO; + + if (chdir(source_dir) < 0) { + com_err(__func__, errno, + _("while changing working directory to \"%s\""), source_dir); + return errno; + } + + if (!(dh = opendir("."))) { + com_err(__func__, errno, + _("while openning directory \"%s\""), source_dir); + return errno; + } + + while((dent = readdir(dh))) { + if((!strcmp(dent->d_name, ".")) || (!strcmp(dent->d_name, ".."))) + continue; + lstat(dent->d_name, &st); + name = dent->d_name; + + switch(st.st_mode & S_IFMT) { + case S_IFCHR: + case S_IFBLK: + case S_IFIFO: + if ((retval = do_mknod_internal(parent_ino, name, &st))) { + com_err(__func__, retval, + _("while creating special file \"%s\""), name); + return retval; + } + break; + case S_IFSOCK: + /* FIXME: there is no make socket function atm. */ + com_err(__func__, 0, + _("ignoring socket file \"%s\""), name); + continue; + case S_IFLNK: + if((read_cnt = readlink(name, ln_target, sizeof(ln_target))) == -1) { + com_err(__func__, errno, + _("while trying to readlink \"%s\""), name); + return errno; + } + ln_target[read_cnt] = '\0'; + if ((retval = do_symlink_internal(parent_ino, name, ln_target))) { + com_err(__func__, retval, + _("while writing symlink\"%s\""), name); + return retval; + } + break; + case S_IFREG: + if ((retval = do_write_internal(parent_ino, name, name))) { + com_err(__func__, retval, + _("while writing file \"%s\""), name); + return retval; + } + break; + case S_IFDIR: + if ((retval = do_mkdir_internal(parent_ino, name, &st))) { + com_err(__func__, retval, + _("while making dir \"%s\""), name); + return retval; + } + if ((retval = ext2fs_namei(current_fs, root, parent_ino, name, &ino))) { + com_err(name, retval, 0); + return retval; + } + /* Populate the dir recursively*/ + retval = populate_fs(ino, name); + if (retval) { + com_err(__func__, retval, _("while adding dir \"%s\""), name); + return retval; + } + chdir(".."); + break; + default: + com_err(__func__, 0, + _("ignoring entry \"%s\""), name); + } + } + closedir(dh); + return retval; } -- 1.7.10.4 ./0012-Fix-musl-build-failures.patch0000664000175000017500000000327012511411356017450 0ustar nielsenrnielsenrFrom c6ff7feb9038d6e8aaffe2e69b205ad5fa33df2f Mon Sep 17 00:00:00 2001 From: Paul Barker Date: Mon, 18 Aug 2014 21:02:56 +0200 Subject: [PATCH] Fix musl build failures In lib/ext2fs/unix_io.c, __u64 should be used instead of __uint64_t. This type is guaranteed by the e2fsprogs build system. (795c02def3681a99cc792a5ebc162d06f8a1eeb7) In misc/create_inode.c, is needed for the definition of PATH_MAX. (bbccc6f3c6a106721fb6f1ef4df6bc32c7986235) Both of these fixes have been made upstream with the git commit IDs given but those are larger commits containing other changes not needed here. Signed-off-by: Paul Barker Upstream-status: Backport --- lib/ext2fs/unix_io.c | 6 +++--- misc/create_inode.c | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/ext2fs/unix_io.c b/lib/ext2fs/unix_io.c index 19be630..0cc0f52 100644 --- a/lib/ext2fs/unix_io.c +++ b/lib/ext2fs/unix_io.c @@ -931,10 +931,10 @@ static errcode_t unix_discard(io_channel channel, unsigned long long block, if (channel->flags & CHANNEL_FLAGS_BLOCK_DEVICE) { #ifdef BLKDISCARD - __uint64_t range[2]; + __u64 range[2]; - range[0] = (__uint64_t)(block) * channel->block_size; - range[1] = (__uint64_t)(count) * channel->block_size; + range[0] = (__u64)(block) * channel->block_size; + range[1] = (__u64)(count) * channel->block_size; ret = ioctl(data->dev, BLKDISCARD, &range); #else diff --git a/misc/create_inode.c b/misc/create_inode.c index 6d8de04..fcec5aa 100644 --- a/misc/create_inode.c +++ b/misc/create_inode.c @@ -1,4 +1,5 @@ #include "create_inode.h" +#include #if __STDC_VERSION__ < 199901L # if __GNUC__ >= 2 -- 1.9.1 ./0011-mke2fs.8.in-update-the-manual-for-the-d-option.patch0000664000175000017500000000214212511411356023377 0ustar nielsenrnielsenrFrom 89fca439f1b58595f2f424598a27869f8c7bd815 Mon Sep 17 00:00:00 2001 From: Robert Yang Date: Mon, 23 Dec 2013 04:43:18 -0500 Subject: [PATCH 11/11] mke2fs.8.in: update the manual for the -d option Update the manual for the -d option Upstream-Status: Backport Signed-off-by: Robert Yang Reviewed-by: Darren Hart --- misc/mke2fs.8.in | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/misc/mke2fs.8.in b/misc/mke2fs.8.in index fea50da..b1ca486 100644 --- a/misc/mke2fs.8.in +++ b/misc/mke2fs.8.in @@ -52,6 +52,10 @@ mke2fs \- create an ext2/ext3/ext4 filesystem .I number-of-inodes ] [ +.B \-d +.I root-directory +] +[ .B \-n ] [ @@ -502,6 +506,9 @@ the ratio). This allows the user to specify the number of desired inodes directly. .TP +.BI \-d " root-directory" +Add the files from the root-directory to the filesystem. +.TP .BI \-o " creator-os" Overrides the default value of the "creator operating system" field of the filesystem. The creator field is set by default to the name of the OS the -- 1.7.10.4 ./0008-mke2fs.c-add-an-option-d-root-directory.patch0000664000175000017500000001337312511411356022315 0ustar nielsenrnielsenrFrom df856929e42bd4f3bdc8d4f59ee82ae8b28532e6 Mon Sep 17 00:00:00 2001 From: Robert Yang Date: Tue, 24 Dec 2013 01:50:45 -0500 Subject: [PATCH 08/11] mke2fs.c: add an option: -d root-directory This option is used for adding the files from a given directory (the root-directory) to the filesystem, it is similiar to genext2fs, but genext2fs doesn't fully support ext4. Upstream-Status: Backport Signed-off-by: Robert Yang Reviewed-by: Darren Hart --- misc/Makefile.in | 14 ++++++++++---- misc/mke2fs.c | 32 +++++++++++++++++++++++--------- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/misc/Makefile.in b/misc/Makefile.in index 553c361..8253723 100644 --- a/misc/Makefile.in +++ b/misc/Makefile.in @@ -42,7 +42,8 @@ LPROGS= @E2INITRD_PROG@ TUNE2FS_OBJS= tune2fs.o util.o MKLPF_OBJS= mklost+found.o -MKE2FS_OBJS= mke2fs.o util.o profile.o prof_err.o default_profile.o +MKE2FS_OBJS= mke2fs.o util.o profile.o prof_err.o default_profile.o \ + create_inode.o CHATTR_OBJS= chattr.o LSATTR_OBJS= lsattr.o UUIDGEN_OBJS= uuidgen.o @@ -60,7 +61,8 @@ E2FREEFRAG_OBJS= e2freefrag.o PROFILED_TUNE2FS_OBJS= profiled/tune2fs.o profiled/util.o PROFILED_MKLPF_OBJS= profiled/mklost+found.o PROFILED_MKE2FS_OBJS= profiled/mke2fs.o profiled/util.o profiled/profile.o \ - profiled/prof_err.o profiled/default_profile.o + profiled/prof_err.o profiled/default_profile.o \ + profiled/create_inode.o PROFILED_CHATTR_OBJS= profiled/chattr.o PROFILED_LSATTR_OBJS= profiled/lsattr.o PROFILED_UUIDGEN_OBJS= profiled/uuidgen.o @@ -82,7 +84,7 @@ SRCS= $(srcdir)/tune2fs.c $(srcdir)/mklost+found.c $(srcdir)/mke2fs.c \ $(srcdir)/uuidgen.c $(srcdir)/blkid.c $(srcdir)/logsave.c \ $(srcdir)/filefrag.c $(srcdir)/base_device.c \ $(srcdir)/ismounted.c $(srcdir)/../e2fsck/profile.c \ - $(srcdir)/e2undo.c $(srcdir)/e2freefrag.c + $(srcdir)/e2undo.c $(srcdir)/e2freefrag.c $(srcdir)/create_inode.c LIBS= $(LIBEXT2FS) $(LIBCOM_ERR) DEPLIBS= $(LIBEXT2FS) $(DEPLIBCOM_ERR) @@ -630,7 +632,7 @@ mke2fs.o: $(srcdir)/mke2fs.c $(top_builddir)/lib/config.h \ $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ $(top_srcdir)/lib/e2p/e2p.h $(top_srcdir)/lib/ext2fs/ext2fs.h \ $(srcdir)/util.h profile.h prof_err.h $(top_srcdir)/version.h \ - $(srcdir)/nls-enable.h $(top_srcdir)/lib/quota/mkquota.h \ + $(srcdir)/nls-enable.h $(top_srcdir)/lib/quota/mkquota.h $(srcdir)/create_inode.h\ $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \ $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h chattr.o: $(srcdir)/chattr.c $(top_builddir)/lib/config.h \ @@ -710,3 +712,7 @@ e2freefrag.o: $(srcdir)/e2freefrag.c $(top_builddir)/lib/config.h \ $(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ $(srcdir)/e2freefrag.h +create_inode.o: $(srcdir)/create_inode.h $(srcdir)/create_inode.c \ + $(top_builddir)/lib/config.h $(top_srcdir)/lib/ext2fs/ext2fs.h \ + $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/e2p/e2p.h \ + $(srcdir)/nls-enable.h diff --git a/misc/mke2fs.c b/misc/mke2fs.c index 2e8ba60..578b62d 100644 --- a/misc/mke2fs.c +++ b/misc/mke2fs.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #ifdef __linux__ @@ -44,24 +43,19 @@ extern int optind; #include #endif #include -#include -#include #include #include #include #include "ext2fs/ext2_fs.h" #include "ext2fs/ext2fsP.h" -#include "et/com_err.h" #include "uuid/uuid.h" -#include "e2p/e2p.h" -#include "ext2fs/ext2fs.h" #include "util.h" #include "profile.h" #include "prof_err.h" #include "../version.h" -#include "nls-enable.h" #include "quota/mkquota.h" +#include "create_inode.h" #define STRIDE_LENGTH 8 @@ -105,6 +99,7 @@ static char *mount_dir; char *journal_device; static int sync_kludge; /* Set using the MKE2FS_SYNC env. option */ static char **fs_types; +const char *root_dir; /* Copy files from the specified directory */ static profile_t profile; @@ -116,7 +111,8 @@ static void usage(void) fprintf(stderr, _("Usage: %s [-c|-l filename] [-b block-size] " "[-C cluster-size]\n\t[-i bytes-per-inode] [-I inode-size] " "[-J journal-options]\n" - "\t[-G flex-group-size] [-N number-of-inodes]\n" + "\t[-G flex-group-size] [-N number-of-inodes] " + "[-d root-directory]\n" "\t[-m reserved-blocks-percentage] [-o creator-os]\n" "\t[-g blocks-per-group] [-L volume-label] " "[-M last-mounted-directory]\n\t[-O feature[,...]] " @@ -1394,7 +1390,7 @@ profile_error: } while ((c = getopt (argc, argv, - "b:cg:i:jl:m:no:qr:s:t:vC:DE:FG:I:J:KL:M:N:O:R:ST:U:V")) != EOF) { + "b:cg:i:jl:m:no:qr:s:t:d:vC:DE:FG:I:J:KL:M:N:O:R:ST:U:V")) != EOF) { switch (c) { case 'b': blocksize = parse_num_blocks2(optarg, -1); @@ -1582,6 +1578,9 @@ profile_error: case 'U': fs_uuid = optarg; break; + case 'd': + root_dir = optarg; + break; case 'v': verbose = 1; break; @@ -2726,6 +2725,21 @@ no_journal: EXT4_FEATURE_RO_COMPAT_QUOTA)) create_quota_inodes(fs); + /* Copy files from the specified directory */ + if (root_dir) { + if (!quiet) + printf("%s", _("Copying files into the device: ")); + + current_fs = fs; + root = EXT2_ROOT_INO; + retval = populate_fs(root, root_dir); + if (retval) + fprintf(stderr, "%s", + _("\nError while populating file system")); + else if (!quiet) + printf("%s", _("done\n")); + } + if (!quiet) printf("%s", _("Writing superblocks and " "filesystem accounting information: ")); -- 1.7.10.4 ./0009-misc-create_inode.c-handle-hardlinks.patch0000664000175000017500000001277212511411356022055 0ustar nielsenrnielsenrFrom d83dc950b3ec1fbde33b23d42c5154091a74f4d9 Mon Sep 17 00:00:00 2001 From: Robert Yang Date: Mon, 23 Dec 2013 03:44:03 -0500 Subject: [PATCH 09/11] misc/create_inode.c: handle hardlinks Create the inode and save the native inode number when we meet the hard link (st_nlink > 1) at the first time, use ext2fs_link() to link the name to the target inode number when we meet the same native inode number again. This algorithm is referred from the genext2fs. Upstream-Status: Backport Signed-off-by: Robert Yang Reviewed-by: Darren Hart --- misc/create_inode.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++ misc/create_inode.h | 18 +++++++++++ misc/mke2fs.c | 12 +++++++ 3 files changed, 118 insertions(+) diff --git a/misc/create_inode.c b/misc/create_inode.c index aad7354..763504d 100644 --- a/misc/create_inode.c +++ b/misc/create_inode.c @@ -18,6 +18,44 @@ #define S_BLKSIZE 512 #endif +/* For saving the hard links */ +int hdlink_cnt = HDLINK_CNT; + +/* Link an inode number to a directory */ +static errcode_t add_link(ext2_ino_t parent_ino, ext2_ino_t ino, const char *name) +{ + struct ext2_inode inode; + errcode_t retval; + + retval = ext2fs_read_inode(current_fs, ino, &inode); + if (retval) { + com_err(__func__, retval, "while reading inode %u", ino); + return retval; + } + + retval = ext2fs_link(current_fs, parent_ino, name, ino, inode.i_flags); + if (retval == EXT2_ET_DIR_NO_SPACE) { + retval = ext2fs_expand_dir(current_fs, parent_ino); + if (retval) { + com_err(__func__, retval, "while expanding directory"); + return retval; + } + retval = ext2fs_link(current_fs, parent_ino, name, ino, inode.i_flags); + } + if (retval) { + com_err(__func__, retval, "while linking %s", name); + return retval; + } + + inode.i_links_count++; + + retval = ext2fs_write_inode(current_fs, ino, &inode); + if (retval) + com_err(__func__, retval, "while writing inode %u", ino); + + return retval; +} + /* Fill the uid, gid, mode and time for the inode */ static void fill_inode(struct ext2_inode *inode, struct stat *st) { @@ -278,6 +316,17 @@ fail: return retval; } +int is_hardlink(ext2_ino_t ino) +{ + int i; + + for(i = 0; i < hdlinks.count; i++) { + if(hdlinks.hdl[i].src_ino == ino) + return i; + } + return -1; +} + /* Copy the native file to the fs */ errcode_t do_write_internal(ext2_ino_t cwd, const char *src, const char *dest) { @@ -388,9 +437,11 @@ errcode_t populate_fs(ext2_ino_t parent_ino, const char *source_dir) struct dirent *dent; struct stat st; char ln_target[PATH_MAX]; + unsigned int save_inode; ext2_ino_t ino; errcode_t retval; int read_cnt; + int hdlink; root = EXT2_ROOT_INO; @@ -412,6 +463,22 @@ errcode_t populate_fs(ext2_ino_t parent_ino, const char *source_dir) lstat(dent->d_name, &st); name = dent->d_name; + /* Check for hardlinks */ + save_inode = 0; + if (!S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode) && st.st_nlink > 1) { + hdlink = is_hardlink(st.st_ino); + if (hdlink >= 0) { + retval = add_link(parent_ino, + hdlinks.hdl[hdlink].dst_ino, name); + if (retval) { + com_err(__func__, retval, "while linking %s", name); + return retval; + } + continue; + } else + save_inode = 1; + } + switch(st.st_mode & S_IFMT) { case S_IFCHR: case S_IFBLK: @@ -480,6 +547,27 @@ errcode_t populate_fs(ext2_ino_t parent_ino, const char *source_dir) _("while setting inode for \"%s\""), name); return retval; } + + /* Save the hardlink ino */ + if (save_inode) { + /* + * Check whether need more memory, and we don't need + * free() since the lifespan will be over after the fs + * populated. + */ + if (hdlinks.count == hdlink_cnt) { + if ((hdlinks.hdl = realloc (hdlinks.hdl, + (hdlink_cnt + HDLINK_CNT) * + sizeof (struct hdlink_s))) == NULL) { + com_err(name, errno, "Not enough memory"); + return errno; + } + hdlink_cnt += HDLINK_CNT; + } + hdlinks.hdl[hdlinks.count].src_ino = st.st_ino; + hdlinks.hdl[hdlinks.count].dst_ino = ino; + hdlinks.count++; + } } closedir(dh); return retval; diff --git a/misc/create_inode.h b/misc/create_inode.h index 9fc97fa..2b6d429 100644 --- a/misc/create_inode.h +++ b/misc/create_inode.h @@ -6,9 +6,27 @@ #include "ext2fs/ext2fs.h" #include "nls-enable.h" +struct hdlink_s +{ + ext2_ino_t src_ino; + ext2_ino_t dst_ino; +}; + +struct hdlinks_s +{ + int count; + struct hdlink_s *hdl; +}; + +struct hdlinks_s hdlinks; + ext2_filsys current_fs; ext2_ino_t root; +/* For saving the hard links */ +#define HDLINK_CNT 4 +extern int hdlink_cnt; + /* For populating the filesystem */ extern errcode_t populate_fs(ext2_ino_t parent_ino, const char *source_dir); extern errcode_t do_mknod_internal(ext2_ino_t cwd, const char *name, struct stat *st); diff --git a/misc/mke2fs.c b/misc/mke2fs.c index 578b62d..a63f0b7 100644 --- a/misc/mke2fs.c +++ b/misc/mke2fs.c @@ -2730,6 +2730,18 @@ no_journal: if (!quiet) printf("%s", _("Copying files into the device: ")); + /* + * Allocate memory for the hardlinks, we don't need free() + * since the lifespan will be over after the fs populated. + */ + if ((hdlinks.hdl = (struct hdlink_s *) + malloc(hdlink_cnt * sizeof(struct hdlink_s))) == NULL) { + fprintf(stderr, "%s", _("\nNot enough memory\n")); + retval = ext2fs_close(fs); + return retval; + } + + hdlinks.count = 0; current_fs = fs; root = EXT2_ROOT_INO; retval = populate_fs(root, root_dir); -- 1.7.10.4 ./fix-icache.patch0000664000175000017500000000375212511411356014464 0ustar nielsenrnielsenrinode.c: only update the icache for ext2_inode We only read the cache when: bufsize == sizeof(struct ext2_inode) then we should only update the cache in the same condition, otherwise there would be errors, for example: cache[0]: cached ino 14 when bufsize = 128 by ext2fs_write_inode_full() cache[1]: cached ino 14 when bufsize = 156 by ext2fs_read_inode_full() Then update the cache: cache[0]: cached ino 15 when bufsize = 156 by ext2fs_read_inode_full() Then the ino 14 would hit the cache[1] when bufsize = 128 (but it was cached by bufsize = 156), so there would be errors. Upstream-Status: [Submitted] Signed-off-by: Robert Yang --- lib/ext2fs/inode.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/lib/ext2fs/inode.c b/lib/ext2fs/inode.c --- a/lib/ext2fs/inode.c +++ b/lib/ext2fs/inode.c @@ -612,10 +612,12 @@ errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino, #endif /* Update the inode cache */ - fs->icache->cache_last = (fs->icache->cache_last + 1) % - fs->icache->cache_size; - fs->icache->cache[fs->icache->cache_last].ino = ino; - fs->icache->cache[fs->icache->cache_last].inode = *inode; + if (bufsize == sizeof(struct ext2_inode)) { + fs->icache->cache_last = (fs->icache->cache_last + 1) % + fs->icache->cache_size; + fs->icache->cache[fs->icache->cache_last].ino = ino; + fs->icache->cache[fs->icache->cache_last].inode = *inode; + } return 0; } @@ -648,10 +650,12 @@ errcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino, /* Check to see if the inode cache needs to be updated */ if (fs->icache) { - for (i=0; i < fs->icache->cache_size; i++) { - if (fs->icache->cache[i].ino == ino) { - fs->icache->cache[i].inode = *inode; - break; + if (bufsize == sizeof(struct ext2_inode)) { + for (i=0; i < fs->icache->cache_size; i++) { + if (fs->icache->cache[i].ino == ino) { + fs->icache->cache[i].inode = *inode; + break; + } } } } else { -- 1.8.1.2 ./0010-debugfs-use-the-functions-in-misc-create_inode.c.patch0000664000175000017500000003270312511411356024232 0ustar nielsenrnielsenrFrom db89992fab2215f52dce4c595a39271b4ff3000b Mon Sep 17 00:00:00 2001 From: Robert Yang Date: Mon, 23 Dec 2013 04:22:22 -0500 Subject: [PATCH 10/11] debugfs: use the functions in misc/create_inode.c * Use the functions in misc/create_inode.c, and remove the duplicated code. * The CREATE_INODE_DEPS in the debugfs/Makefile.in is used for recording create_inode.o's depends which is from misc/Makefile.in, we have to recompile create_inode.o because we need it to print more messages when it is used by debugfs, just like we recompile e2freefrag.o, but it seems that the e2freefrag.o's depends in debugfs/Makefile.in is incorrect, it would not rebuild when its depends (e.g.: lib/config.h) is changed, which would cause unexpected errors. Make duplicated code in debugfs/Makefile.in and misc/Makefile.in is not a good idea, maybe we'd better define CREATE_INODE_DEPS in the top Makefile, I'd like to send another patch and fix the e2freefrag if you are fine with it. Upstream-Status: Backport Signed-off-by: Robert Yang Reviewed-by: Darren Hart --- debugfs/Makefile.in | 17 ++- debugfs/debugfs.c | 305 +++------------------------------------------------ debugfs/debugfs.h | 1 + 3 files changed, 31 insertions(+), 292 deletions(-) diff --git a/debugfs/Makefile.in b/debugfs/Makefile.in index bf037e0..f51b78e 100644 --- a/debugfs/Makefile.in +++ b/debugfs/Makefile.in @@ -18,7 +18,7 @@ MK_CMDS= _SS_DIR_OVERRIDE=../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 + filefrag.o extent_cmds.o extent_inode.o zap.o create_inode.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 \ @@ -28,7 +28,13 @@ SRCS= debug_cmds.c $(srcdir)/debugfs.c $(srcdir)/util.c $(srcdir)/ls.c \ $(srcdir)/ncheck.c $(srcdir)/icheck.c $(srcdir)/lsdel.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)/filefrag.c $(srcdir)/extent_inode.c $(srcdir)/zap.c \ + $(srcdir)/../misc/create_inode.c + +CREATE_INODE_DEPS= $(srcdir)/../misc/create_inode.h \ + $(srcdir)/../misc/create_inode.c $(top_builddir)/lib/config.h \ + $(srcdir)/../lib/ext2fs/ext2fs.h $(srcdir)/../lib/et/com_err.h \ + $(srcdir)/../lib/e2p/e2p.h $(srcdir)/../misc/nls-enable.h LIBS= $(LIBEXT2FS) $(LIBE2P) $(LIBSS) $(LIBCOM_ERR) $(LIBBLKID) \ $(LIBUUID) @@ -81,6 +87,11 @@ e2freefrag.o: $(srcdir)/../misc/e2freefrag.c $(E) " CC $@" $(Q) $(CC) -c $(ALL_CFLAGS) -I$(srcdir) $< -DDEBUGFS -o $@ +create_inode.o: $(CREATE_INODE_DEPS) + $(E) " CC $@" + $(Q) $(CC) -c $(ALL_CFLAGS) -I$(srcdir) \ + $(srcdir)/../misc/create_inode.c -DDEBUGFS -o $@ + debugfs.8: $(DEP_SUBSTITUTE) $(srcdir)/debugfs.8.in $(E) " SUBST $@" $(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/debugfs.8.in debugfs.8 @@ -142,7 +153,7 @@ debugfs.o: $(srcdir)/debugfs.c $(top_srcdir)/lib/et/com_err.h \ $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ $(top_srcdir)/lib/e2p/e2p.h $(top_srcdir)/version.h $(srcdir)/jfs_user.h \ $(top_srcdir)/lib/ext2fs/kernel-jbd.h $(top_srcdir)/lib/ext2fs/jfs_compat.h \ - $(top_srcdir)/lib/ext2fs/kernel-list.h + $(top_srcdir)/lib/ext2fs/kernel-list.h $(top_srcdir)/misc/util.h util.o: $(srcdir)/util.c $(srcdir)/debugfs.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 \ diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c index 9c215f7..62e9f44 100644 --- a/debugfs/debugfs.c +++ b/debugfs/debugfs.c @@ -25,8 +25,6 @@ extern char *optarg; #include #endif #include -#include -#include #include "debugfs.h" #include "uuid/uuid.h" @@ -41,22 +39,11 @@ extern char *optarg; #define BUFSIZ 8192 #endif -/* 64KiB is the minimium blksize to best minimize system call overhead. */ -#ifndef IO_BUFSIZE -#define IO_BUFSIZE 64*1024 -#endif - -/* Block size for `st_blocks' */ -#ifndef S_BLKSIZE -#define S_BLKSIZE 512 -#endif - ss_request_table *extra_cmds; const char *debug_prog_name; int sci_idx; -ext2_filsys current_fs = NULL; -ext2_ino_t root, cwd; +ext2_ino_t cwd; static void open_filesystem(char *device, int open_flags, blk64_t superblock, blk64_t blocksize, int catastrophic, @@ -1576,189 +1563,24 @@ void do_find_free_inode(int argc, char *argv[]) } #ifndef READ_ONLY -static errcode_t copy_file(int fd, ext2_ino_t newfile, int bufsize, int make_holes) -{ - ext2_file_t e2_file; - errcode_t retval; - int got; - unsigned int written; - char *buf; - char *ptr; - char *zero_buf; - int cmp; - - retval = ext2fs_file_open(current_fs, newfile, - EXT2_FILE_WRITE, &e2_file); - if (retval) - return retval; - - retval = ext2fs_get_mem(bufsize, &buf); - if (retval) { - com_err("copy_file", retval, "can't allocate buffer\n"); - return retval; - } - - /* This is used for checking whether the whole block is zero */ - retval = ext2fs_get_memzero(bufsize, &zero_buf); - if (retval) { - com_err("copy_file", retval, "can't allocate buffer\n"); - ext2fs_free_mem(&buf); - return retval; - } - - while (1) { - got = read(fd, buf, bufsize); - if (got == 0) - break; - if (got < 0) { - retval = errno; - goto fail; - } - ptr = buf; - - /* Sparse copy */ - if (make_holes) { - /* Check whether all is zero */ - cmp = memcmp(ptr, zero_buf, got); - if (cmp == 0) { - /* The whole block is zero, make a hole */ - retval = ext2fs_file_lseek(e2_file, got, EXT2_SEEK_CUR, NULL); - if (retval) - goto fail; - got = 0; - } - } - - /* Normal copy */ - while (got > 0) { - retval = ext2fs_file_write(e2_file, ptr, - got, &written); - if (retval) - goto fail; - - got -= written; - ptr += written; - } - } - ext2fs_free_mem(&buf); - ext2fs_free_mem(&zero_buf); - retval = ext2fs_file_close(e2_file); - return retval; - -fail: - ext2fs_free_mem(&buf); - ext2fs_free_mem(&zero_buf); - (void) ext2fs_file_close(e2_file); - return retval; -} - - void do_write(int argc, char *argv[]) { - int fd; - struct stat statbuf; - ext2_ino_t newfile; errcode_t retval; - struct ext2_inode inode; - int bufsize = IO_BUFSIZE; - int make_holes = 0; if (common_args_process(argc, argv, 3, 3, "write", " ", CHECK_FS_RW)) return; - fd = open(argv[1], O_RDONLY); - if (fd < 0) { - com_err(argv[1], errno, 0); - return; - } - if (fstat(fd, &statbuf) < 0) { - com_err(argv[1], errno, 0); - close(fd); - return; - } - - retval = ext2fs_namei(current_fs, root, cwd, argv[2], &newfile); - if (retval == 0) { - com_err(argv[0], 0, "The file '%s' already exists\n", argv[2]); - close(fd); - return; - } - - retval = ext2fs_new_inode(current_fs, cwd, 010755, 0, &newfile); - if (retval) { + if ((retval = do_write_internal(cwd, argv[1], argv[2]))) com_err(argv[0], retval, 0); - close(fd); - return; - } - printf("Allocated inode: %u\n", newfile); - retval = ext2fs_link(current_fs, cwd, argv[2], newfile, - EXT2_FT_REG_FILE); - if (retval == EXT2_ET_DIR_NO_SPACE) { - retval = ext2fs_expand_dir(current_fs, cwd); - if (retval) { - com_err(argv[0], retval, "while expanding directory"); - close(fd); - return; - } - retval = ext2fs_link(current_fs, cwd, argv[2], newfile, - EXT2_FT_REG_FILE); - } - if (retval) { - com_err(argv[2], retval, 0); - close(fd); - return; - } - if (ext2fs_test_inode_bitmap2(current_fs->inode_map,newfile)) - com_err(argv[0], 0, "Warning: inode already set"); - ext2fs_inode_alloc_stats2(current_fs, newfile, +1, 0); - memset(&inode, 0, sizeof(inode)); - inode.i_mode = (statbuf.st_mode & ~LINUX_S_IFMT) | LINUX_S_IFREG; - inode.i_atime = inode.i_ctime = inode.i_mtime = - current_fs->now ? current_fs->now : time(0); - inode.i_links_count = 1; - inode.i_size = statbuf.st_size; - if (current_fs->super->s_feature_incompat & - EXT3_FEATURE_INCOMPAT_EXTENTS) { - int i; - struct ext3_extent_header *eh; - - eh = (struct ext3_extent_header *) &inode.i_block[0]; - eh->eh_depth = 0; - eh->eh_entries = 0; - eh->eh_magic = ext2fs_cpu_to_le16(EXT3_EXT_MAGIC); - i = (sizeof(inode.i_block) - sizeof(*eh)) / - sizeof(struct ext3_extent); - eh->eh_max = ext2fs_cpu_to_le16(i); - inode.i_flags |= EXT4_EXTENTS_FL; - } - if (debugfs_write_new_inode(newfile, &inode, argv[0])) { - close(fd); - return; - } - if (LINUX_S_ISREG(inode.i_mode)) { - if (statbuf.st_blocks < statbuf.st_size / S_BLKSIZE) { - make_holes = 1; - /* - * Use I/O blocksize as buffer size when - * copying sparse files. - */ - bufsize = statbuf.st_blksize; - } - retval = copy_file(fd, newfile, bufsize, make_holes); - if (retval) - com_err("copy_file", retval, 0); - } - close(fd); } void do_mknod(int argc, char *argv[]) { unsigned long mode, major, minor; - ext2_ino_t newfile; errcode_t retval; - struct ext2_inode inode; int filetype, nr; + struct stat st; if (check_fs_open(argv[0])) return; @@ -1767,115 +1589,50 @@ void do_mknod(int argc, char *argv[]) com_err(argv[0], 0, "Usage: mknod [p| [c|b] ]"); return; } + mode = minor = major = 0; switch (argv[2][0]) { case 'p': - mode = LINUX_S_IFIFO; - filetype = EXT2_FT_FIFO; + st.st_mode = S_IFIFO; nr = 3; break; case 'c': - mode = LINUX_S_IFCHR; - filetype = EXT2_FT_CHRDEV; + st.st_mode = S_IFCHR; nr = 5; break; case 'b': - mode = LINUX_S_IFBLK; - filetype = EXT2_FT_BLKDEV; + st.st_mode = S_IFBLK; nr = 5; break; default: - filetype = 0; nr = 0; } + if (nr == 5) { major = strtoul(argv[3], argv+3, 0); minor = strtoul(argv[4], argv+4, 0); if (major > 65535 || minor > 65535 || argv[3][0] || argv[4][0]) nr = 0; } + if (argc != nr) goto usage; - if (check_fs_read_write(argv[0])) - return; - retval = ext2fs_new_inode(current_fs, cwd, 010755, 0, &newfile); - if (retval) { + + st.st_rdev = makedev(major, minor); + if ((retval = do_mknod_internal(cwd, argv[1], &st))) com_err(argv[0], retval, 0); - return; - } - printf("Allocated inode: %u\n", newfile); - retval = ext2fs_link(current_fs, cwd, argv[1], newfile, filetype); - if (retval == EXT2_ET_DIR_NO_SPACE) { - retval = ext2fs_expand_dir(current_fs, cwd); - if (retval) { - com_err(argv[0], retval, "while expanding directory"); - return; - } - retval = ext2fs_link(current_fs, cwd, argv[1], newfile, - filetype); - } - if (retval) { - com_err(argv[1], retval, 0); - return; - } - if (ext2fs_test_inode_bitmap2(current_fs->inode_map,newfile)) - com_err(argv[0], 0, "Warning: inode already set"); - ext2fs_inode_alloc_stats2(current_fs, newfile, +1, 0); - memset(&inode, 0, sizeof(inode)); - inode.i_mode = mode; - inode.i_atime = inode.i_ctime = inode.i_mtime = - current_fs->now ? current_fs->now : time(0); - if ((major < 256) && (minor < 256)) { - inode.i_block[0] = major*256+minor; - inode.i_block[1] = 0; - } else { - inode.i_block[0] = 0; - inode.i_block[1] = (minor & 0xff) | (major << 8) | ((minor & ~0xff) << 12); - } - inode.i_links_count = 1; - if (debugfs_write_new_inode(newfile, &inode, argv[0])) - return; } void do_mkdir(int argc, char *argv[]) { - char *cp; - ext2_ino_t parent; - char *name; errcode_t retval; if (common_args_process(argc, argv, 2, 2, "mkdir", "", CHECK_FS_RW)) return; - cp = strrchr(argv[1], '/'); - if (cp) { - *cp = 0; - parent = string_to_inode(argv[1]); - if (!parent) { - com_err(argv[1], ENOENT, 0); - return; - } - name = cp+1; - } else { - parent = cwd; - name = argv[1]; - } - -try_again: - retval = ext2fs_mkdir(current_fs, parent, 0, name); - if (retval == EXT2_ET_DIR_NO_SPACE) { - retval = ext2fs_expand_dir(current_fs, parent); - if (retval) { - com_err(argv[0], retval, "while expanding directory"); - return; - } - goto try_again; - } - if (retval) { - com_err("ext2fs_mkdir", retval, 0); - return; - } + if ((retval = do_mkdir_internal(cwd, argv[1], NULL))) + com_err(argv[0], retval, 0); } @@ -2270,44 +2027,14 @@ void do_punch(int argc, char *argv[]) void do_symlink(int argc, char *argv[]) { - char *cp; - ext2_ino_t parent; - char *name, *target; errcode_t retval; if (common_args_process(argc, argv, 3, 3, "symlink", " ", CHECK_FS_RW)) return; - cp = strrchr(argv[1], '/'); - if (cp) { - *cp = 0; - parent = string_to_inode(argv[1]); - if (!parent) { - com_err(argv[1], ENOENT, 0); - return; - } - name = cp+1; - } else { - parent = cwd; - name = argv[1]; - } - target = argv[2]; - -try_again: - retval = ext2fs_symlink(current_fs, parent, 0, name, target); - if (retval == EXT2_ET_DIR_NO_SPACE) { - retval = ext2fs_expand_dir(current_fs, parent); - if (retval) { - com_err(argv[0], retval, "while expanding directory"); - return; - } - goto try_again; - } - if (retval) { - com_err("ext2fs_symlink", retval, 0); - return; - } + if ((retval = do_symlink_internal(cwd, argv[1], argv[2]))) + com_err(argv[0], retval, 0); } diff --git a/debugfs/debugfs.h b/debugfs/debugfs.h index 6b4f6ef..2d464c1 100644 --- a/debugfs/debugfs.h +++ b/debugfs/debugfs.h @@ -5,6 +5,7 @@ #include "ss/ss.h" #include "ext2fs/ext2_fs.h" #include "ext2fs/ext2fs.h" +#include "../misc/create_inode.h" #ifdef __STDC__ #define NOARGS void -- 1.7.10.4 ./0003-misc-create_inode.c-create-special-file.patch0000664000175000017500000000561312511411356022431 0ustar nielsenrnielsenrFrom ae7d33823bfc330e08b25c5fe4d25838ef7c77ce Mon Sep 17 00:00:00 2001 From: Robert Yang Date: Mon, 23 Dec 2013 03:13:28 -0500 Subject: [PATCH 03/11] misc/create_inode.c: create special file The do_mknod_internal() is used for creating special file which is block, character and fifo, most of the code are from debugfs/debugfs.c, the debugfs/debugfs.c will be modified to use this function. Upstream-Status: Backport Signed-off-by: Robert Yang Reviewed-by: Darren Hart --- misc/create_inode.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/misc/create_inode.c b/misc/create_inode.c index b68b910..4da8aff 100644 --- a/misc/create_inode.c +++ b/misc/create_inode.c @@ -11,6 +11,78 @@ /* Make a special file which is block, character and fifo */ errcode_t do_mknod_internal(ext2_ino_t cwd, const char *name, struct stat *st) { + ext2_ino_t ino; + errcode_t retval; + struct ext2_inode inode; + unsigned long major, minor, mode; + int filetype; + + switch(st->st_mode & S_IFMT) { + case S_IFCHR: + mode = LINUX_S_IFCHR; + filetype = EXT2_FT_CHRDEV; + break; + case S_IFBLK: + mode = LINUX_S_IFBLK; + filetype = EXT2_FT_BLKDEV; + break; + case S_IFIFO: + mode = LINUX_S_IFIFO; + filetype = EXT2_FT_FIFO; + break; + } + + if (!(current_fs->flags & EXT2_FLAG_RW)) { + com_err(__func__, 0, "Filesystem opened read/only"); + return -1; + } + retval = ext2fs_new_inode(current_fs, cwd, 010755, 0, &ino); + if (retval) { + com_err(__func__, retval, 0); + return retval; + } + +#ifdef DEBUGFS + printf("Allocated inode: %u\n", ino); +#endif + retval = ext2fs_link(current_fs, cwd, name, ino, filetype); + if (retval == EXT2_ET_DIR_NO_SPACE) { + retval = ext2fs_expand_dir(current_fs, cwd); + if (retval) { + com_err(__func__, retval, "while expanding directory"); + return retval; + } + retval = ext2fs_link(current_fs, cwd, name, ino, filetype); + } + if (retval) { + com_err(name, retval, 0); + return -1; + } + if (ext2fs_test_inode_bitmap2(current_fs->inode_map, ino)) + com_err(__func__, 0, "Warning: inode already set"); + ext2fs_inode_alloc_stats2(current_fs, ino, +1, 0); + memset(&inode, 0, sizeof(inode)); + inode.i_mode = mode; + inode.i_atime = inode.i_ctime = inode.i_mtime = + current_fs->now ? current_fs->now : time(0); + + major = major(st->st_rdev); + minor = minor(st->st_rdev); + + if ((major < 256) && (minor < 256)) { + inode.i_block[0] = major * 256 + minor; + inode.i_block[1] = 0; + } else { + inode.i_block[0] = 0; + inode.i_block[1] = (minor & 0xff) | (major << 8) | ((minor & ~0xff) << 12); + } + inode.i_links_count = 1; + + retval = ext2fs_write_new_inode(current_fs, ino, &inode); + if (retval) + com_err(__func__, retval, "while creating inode %u", ino); + + return retval; } /* Make a symlink name -> target */ -- 1.7.10.4 ./remove.ldconfig.call.patch0000664000175000017500000000267512511411356016462 0ustar nielsenrnielsenrFrom b139e03ac2f72e644e547c7ee9b1514383af4d97 Mon Sep 17 00:00:00 2001 From: Andrei Dinu Date: Wed, 30 Jan 2013 15:22:04 +0200 Subject: [PATCH] When /etc/ld.so.cache is writeable by user running bitbake then it creates invalid cache (in my case libstdc++.so cannot be found after building zlib(-native) and I have to call touch */libstdc++.so && /sbin/ldconfig to fix it. So remove ldconfig call from make install-libs Patch authored by Martin Jansa. Upstream-Status: Inappropriate [disable feature] Signed-off-by: Scott Garman Signed-off-by: Andrei Dinu --- lib/Makefile.elf-lib | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/Makefile.elf-lib b/lib/Makefile.elf-lib index 78479d3..4a4a5ac 100644 --- a/lib/Makefile.elf-lib +++ b/lib/Makefile.elf-lib @@ -50,8 +50,6 @@ install-shlibs install:: $(ELF_LIB) installdirs-elf-lib $(DEP_INSTALL_SYMLINK) $(E) " SYMLINK $(libdir)/$(ELF_IMAGE).so" $(Q) $(INSTALL_SYMLINK) $(ELF_INSTALL_DIR)/$(ELF_SONAME) \ $(libdir)/$(ELF_IMAGE).so $(DESTDIR) - $(E) " LDCONFIG" - $(Q) -$(LDCONFIG) install-strip: install $(E) " STRIP-LIB $(ELF_INSTALL_DIR)/$(ELF_LIB)" @@ -67,7 +65,6 @@ uninstall-shlibs uninstall:: $(RM) -f $(DESTDIR)$(ELF_INSTALL_DIR)/$(ELF_LIB) \ $(DESTDIR)$(ELF_INSTALL_DIR)/$(ELF_SONAME) \ $(DESTDIR)$(libdir)/$(ELF_IMAGE).so - -$(LDCONFIG) clean:: $(RM) -rf elfshared -- 1.7.9.5 ./0005-misc-create_inode.c-copy-regular-file.patch0000664000175000017500000001317512511411356022165 0ustar nielsenrnielsenrFrom 2973c74afaa532f3f72639b463322b2523519c20 Mon Sep 17 00:00:00 2001 From: Robert Yang Date: Mon, 23 Dec 2013 03:28:12 -0500 Subject: [PATCH 05/11] misc/create_inode.c: copy regular file The do_write_internal() is used for copying file from native fs to target, most of the code are from debugfs/debugfs.c, the debugfs/debugfs.c will be modified to use this function. Upstream-Status: Backport Signed-off-by: Robert Yang Reviewed-by: Darren Hart --- misc/create_inode.c | 183 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) diff --git a/misc/create_inode.c b/misc/create_inode.c index f845103..98f4a93 100644 --- a/misc/create_inode.c +++ b/misc/create_inode.c @@ -8,6 +8,16 @@ # endif #endif +/* 64KiB is the minimium blksize to best minimize system call overhead. */ +#ifndef IO_BUFSIZE +#define IO_BUFSIZE 64*1024 +#endif + +/* Block size for `st_blocks' */ +#ifndef S_BLKSIZE +#define S_BLKSIZE 512 +#endif + /* Make a special file which is block, character and fifo */ errcode_t do_mknod_internal(ext2_ino_t cwd, const char *name, struct stat *st) { @@ -127,9 +137,182 @@ errcode_t do_mkdir_internal(ext2_ino_t cwd, const char *name, struct stat *st) { } +static errcode_t copy_file(int fd, ext2_ino_t newfile, int bufsize, int make_holes) +{ + ext2_file_t e2_file; + errcode_t retval; + int got; + unsigned int written; + char *buf; + char *ptr; + char *zero_buf; + int cmp; + + retval = ext2fs_file_open(current_fs, newfile, + EXT2_FILE_WRITE, &e2_file); + if (retval) + return retval; + + retval = ext2fs_get_mem(bufsize, &buf); + if (retval) { + com_err("copy_file", retval, "can't allocate buffer\n"); + return retval; + } + + /* This is used for checking whether the whole block is zero */ + retval = ext2fs_get_memzero(bufsize, &zero_buf); + if (retval) { + com_err("copy_file", retval, "can't allocate buffer\n"); + ext2fs_free_mem(&buf); + return retval; + } + + while (1) { + got = read(fd, buf, bufsize); + if (got == 0) + break; + if (got < 0) { + retval = errno; + goto fail; + } + ptr = buf; + + /* Sparse copy */ + if (make_holes) { + /* Check whether all is zero */ + cmp = memcmp(ptr, zero_buf, got); + if (cmp == 0) { + /* The whole block is zero, make a hole */ + retval = ext2fs_file_lseek(e2_file, got, EXT2_SEEK_CUR, NULL); + if (retval) + goto fail; + got = 0; + } + } + + /* Normal copy */ + while (got > 0) { + retval = ext2fs_file_write(e2_file, ptr, + got, &written); + if (retval) + goto fail; + + got -= written; + ptr += written; + } + } + ext2fs_free_mem(&buf); + ext2fs_free_mem(&zero_buf); + retval = ext2fs_file_close(e2_file); + return retval; + +fail: + ext2fs_free_mem(&buf); + ext2fs_free_mem(&zero_buf); + (void) ext2fs_file_close(e2_file); + return retval; +} + /* Copy the native file to the fs */ errcode_t do_write_internal(ext2_ino_t cwd, const char *src, const char *dest) { + int fd; + struct stat statbuf; + ext2_ino_t newfile; + errcode_t retval; + struct ext2_inode inode; + int bufsize = IO_BUFSIZE; + int make_holes = 0; + + fd = open(src, O_RDONLY); + if (fd < 0) { + com_err(src, errno, 0); + return errno; + } + if (fstat(fd, &statbuf) < 0) { + com_err(src, errno, 0); + close(fd); + return errno; + } + + retval = ext2fs_namei(current_fs, root, cwd, dest, &newfile); + if (retval == 0) { + com_err(__func__, 0, "The file '%s' already exists\n", dest); + close(fd); + return retval; + } + + retval = ext2fs_new_inode(current_fs, cwd, 010755, 0, &newfile); + if (retval) { + com_err(__func__, retval, 0); + close(fd); + return retval; + } +#ifdef DEBUGFS + printf("Allocated inode: %u\n", newfile); +#endif + retval = ext2fs_link(current_fs, cwd, dest, newfile, + EXT2_FT_REG_FILE); + if (retval == EXT2_ET_DIR_NO_SPACE) { + retval = ext2fs_expand_dir(current_fs, cwd); + if (retval) { + com_err(__func__, retval, "while expanding directory"); + close(fd); + return retval; + } + retval = ext2fs_link(current_fs, cwd, dest, newfile, + EXT2_FT_REG_FILE); + } + if (retval) { + com_err(dest, retval, 0); + close(fd); + return retval; + } + if (ext2fs_test_inode_bitmap2(current_fs->inode_map, newfile)) + com_err(__func__, 0, "Warning: inode already set"); + ext2fs_inode_alloc_stats2(current_fs, newfile, +1, 0); + memset(&inode, 0, sizeof(inode)); + inode.i_mode = (statbuf.st_mode & ~LINUX_S_IFMT) | LINUX_S_IFREG; + inode.i_atime = inode.i_ctime = inode.i_mtime = + current_fs->now ? current_fs->now : time(0); + inode.i_links_count = 1; + inode.i_size = statbuf.st_size; + if (current_fs->super->s_feature_incompat & + EXT3_FEATURE_INCOMPAT_EXTENTS) { + int i; + struct ext3_extent_header *eh; + + eh = (struct ext3_extent_header *) &inode.i_block[0]; + eh->eh_depth = 0; + eh->eh_entries = 0; + eh->eh_magic = ext2fs_cpu_to_le16(EXT3_EXT_MAGIC); + i = (sizeof(inode.i_block) - sizeof(*eh)) / + sizeof(struct ext3_extent); + eh->eh_max = ext2fs_cpu_to_le16(i); + inode.i_flags |= EXT4_EXTENTS_FL; + } + + if ((retval = ext2fs_write_new_inode(current_fs, newfile, &inode))) { + com_err(__func__, retval, "while creating inode %u", newfile); + close(fd); + return retval; + } + if (LINUX_S_ISREG(inode.i_mode)) { + if (statbuf.st_blocks < statbuf.st_size / S_BLKSIZE) { + make_holes = 1; + /* + * Use I/O blocksize as buffer size when + * copying sparse files. + */ + bufsize = statbuf.st_blksize; + } + retval = copy_file(fd, newfile, bufsize, make_holes); + if (retval) + com_err("copy_file", retval, 0); + } + close(fd); + + return 0; } /* Copy files from source_dir to fs */ -- 1.7.10.4 ./0001-mke2fs-add-the-ability-to-copy-files-from-a-given-di.patch0000664000175000017500000000566512511411356024544 0ustar nielsenrnielsenrFrom c98fec004f077e566b9dfa20b25e3b86cb462a2e Mon Sep 17 00:00:00 2001 From: Robert Yang Date: Tue, 24 Dec 2013 01:41:08 -0500 Subject: [PATCH 01/11] mke2fs: add the ability to copy files from a given directory We will add a -d option which will be used for adding the files from a given directory to the filesystem, it is similiar to genext2fs, but genext2fs doesn't fully support ext4. * We already have the basic operations in debugfs: - Copy regular file - Create directory - Create symlink - Create special file We will move these operations into create_inode.h and create_inode.c, then let both mke2fs and debugfs use them. * What we need to do are: - Copy the given directory recursively, this will be done by the populate_fs() - Set the owner, mode and other informations - Handle the hard links TODO: - The libext2fs can't create the socket file (S_IFSOCK), do we have a plan to support it ? Upstream-Status: Backport Signed-off-by: Robert Yang Reviewed-by: Darren Hart --- misc/create_inode.c | 26 ++++++++++++++++++++++++++ misc/create_inode.h | 17 +++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 misc/create_inode.c create mode 100644 misc/create_inode.h diff --git a/misc/create_inode.c b/misc/create_inode.c new file mode 100644 index 0000000..46aaa60 --- /dev/null +++ b/misc/create_inode.c @@ -0,0 +1,26 @@ +#include "create_inode.h" + +/* Make a special file which is block, character and fifo */ +errcode_t do_mknod_internal(ext2_ino_t cwd, const char *name, struct stat *st) +{ +} + +/* Make a symlink name -> target */ +errcode_t do_symlink_internal(ext2_ino_t cwd, const char *name, char *target) +{ +} + +/* Make a directory in the fs */ +errcode_t do_mkdir_internal(ext2_ino_t cwd, const char *name, struct stat *st) +{ +} + +/* Copy the native file to the fs */ +errcode_t do_write_internal(ext2_ino_t cwd, const char *src, const char *dest) +{ +} + +/* Copy files from source_dir to fs */ +errcode_t populate_fs(ext2_ino_t parent_ino, const char *source_dir) +{ +} diff --git a/misc/create_inode.h b/misc/create_inode.h new file mode 100644 index 0000000..9fc97fa --- /dev/null +++ b/misc/create_inode.h @@ -0,0 +1,17 @@ +#include +#include +#include +#include "et/com_err.h" +#include "e2p/e2p.h" +#include "ext2fs/ext2fs.h" +#include "nls-enable.h" + +ext2_filsys current_fs; +ext2_ino_t root; + +/* For populating the filesystem */ +extern errcode_t populate_fs(ext2_ino_t parent_ino, const char *source_dir); +extern errcode_t do_mknod_internal(ext2_ino_t cwd, const char *name, struct stat *st); +extern errcode_t do_symlink_internal(ext2_ino_t cwd, const char *name, char *target); +extern errcode_t do_mkdir_internal(ext2_ino_t cwd, const char *name, struct stat *st); +extern errcode_t do_write_internal(ext2_ino_t cwd, const char *src, const char *dest); -- 1.7.10.4 ./0001-e2fsprogs-fix-cross-compilation-problem.patch0000664000175000017500000000306412511411356022635 0ustar nielsenrnielsenrUpstream-Status: Pending Subject: e2fsprogs: fix cross compilation problem The checking of types in parse-types.sh doesn't make much sense in a cross-compilation environment, because the generated binary is executed on build machine. So even if asm_types.h has got correct statements for types, it's possible that the generated binary will report an error. Because these types are for the target machine. Signed-off-by: Chen Qi --- config/parse-types.sh | 6 ++++-- configure.in | 6 +++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/config/parse-types.sh b/config/parse-types.sh index 5076f6c..24d2a99 100755 --- a/config/parse-types.sh +++ b/config/parse-types.sh @@ -118,8 +118,10 @@ if ./asm_types then true else - echo "Problem detected with asm_types.h" - echo "" > asm_types.h + if [ "${CROSS_COMPILE}" != "1" ]; then + echo "Problem detected with asm_types.h" + echo "" > asm_types.h + fi fi rm asm_types.c asm_types diff --git a/configure.in b/configure.in index 68adf0d..ed1697b 100644 --- a/configure.in +++ b/configure.in @@ -953,7 +953,11 @@ AC_SUBST(SIZEOF_LONG) AC_SUBST(SIZEOF_LONG_LONG) AC_SUBST(SIZEOF_OFF_T) AC_C_BIGENDIAN -BUILD_CC="$BUILD_CC" CPP="$CPP" /bin/sh $ac_aux_dir/parse-types.sh +if test $cross_compiling = no; then + BUILD_CC="$BUILD_CC" CPP="$CPP" /bin/sh $ac_aux_dir/parse-types.sh +else + CROSS_COMPILE="1" BUILD_CC="$BUILD_CC" CPP="$CPP" /bin/sh $ac_aux_dir/parse-types.sh +fi ASM_TYPES_HEADER=./asm_types.h AC_SUBST_FILE(ASM_TYPES_HEADER) dnl -- 1.7.9.5 ./misc-mke2fs.c-return-error-when-failed-to-populate-fs.patch0000664000175000017500000000175212511411356024525 0ustar nielsenrnielsenrFrom e4ffd6fe975888d306b5f700ba54af18b59f6759 Mon Sep 17 00:00:00 2001 From: Robert Yang Date: Thu, 20 Mar 2014 11:10:21 +0800 Subject: [PATCH] misc/mke2fs.c: return error when failed to populate filesystem We need return retval when "mke2fs -d" failed, otherwise the "$?" would be 0 which is misleading. Upstream-Status Submitted Signed-off-by: Robert Yang --- misc/mke2fs.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/misc/mke2fs.c b/misc/mke2fs.c index a63f0b7..846190e 100644 --- a/misc/mke2fs.c +++ b/misc/mke2fs.c @@ -2745,10 +2745,11 @@ no_journal: current_fs = fs; root = EXT2_ROOT_INO; retval = populate_fs(root, root_dir); - if (retval) + if (retval) { fprintf(stderr, "%s", - _("\nError while populating file system")); - else if (!quiet) + _("\nError while populating file system\n")); + return retval; + } else if (!quiet) printf("%s", _("done\n")); } -- 1.8.3.1 ./0006-misc-create_inode.c-create-directory.patch0000664000175000017500000000324612511411356022103 0ustar nielsenrnielsenrFrom c8d1c43be24489036137f8fdebcfccc208f7cc8b Mon Sep 17 00:00:00 2001 From: Robert Yang Date: Mon, 23 Dec 2013 03:34:14 -0500 Subject: [PATCH 06/11] misc/create_inode.c: create directory The do_mkdir_internal() is used for making dir on the target fs, most of the code are from debugfs/debugfs.c, the debugfs/debugfs.c will be modified to use this function. Upstream-Status: Backport Signed-off-by: Robert Yang Reviewed-by: Darren Hart --- misc/create_inode.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/misc/create_inode.c b/misc/create_inode.c index 98f4a93..6a8c92a 100644 --- a/misc/create_inode.c +++ b/misc/create_inode.c @@ -135,6 +135,37 @@ try_again: /* Make a directory in the fs */ errcode_t do_mkdir_internal(ext2_ino_t cwd, const char *name, struct stat *st) { + char *cp; + ext2_ino_t parent_ino, ino; + errcode_t retval; + struct ext2_inode inode; + + + cp = strrchr(name, '/'); + if (cp) { + *cp = 0; + if ((retval = ext2fs_namei(current_fs, root, cwd, name, &parent_ino))){ + com_err(name, retval, 0); + return retval; + } + name = cp+1; + } else + parent_ino = cwd; + +try_again: + retval = ext2fs_mkdir(current_fs, parent_ino, 0, name); + if (retval == EXT2_ET_DIR_NO_SPACE) { + retval = ext2fs_expand_dir(current_fs, parent_ino); + if (retval) { + com_err(__func__, retval, "while expanding directory"); + return retval; + } + goto try_again; + } + if (retval) { + com_err("ext2fs_mkdir", retval, 0); + return retval; + } } static errcode_t copy_file(int fd, ext2_ino_t newfile, int bufsize, int make_holes) -- 1.7.10.4 ./0007-misc-create_inode.c-set-owner-mode-time-for-the-inod.patch0000664000175000017500000000430712511411356024730 0ustar nielsenrnielsenrFrom 2b1f6e6b386703a5d7e60b7d8b72746f3d31a8bc Mon Sep 17 00:00:00 2001 From: Robert Yang Date: Mon, 23 Dec 2013 03:39:56 -0500 Subject: [PATCH 07/11] misc/create_inode.c: set owner/mode/time for the inode Set the uid, gid, mode and time for inode. Upstream-Status: Backport Signed-off-by: Robert Yang Reviewed-by: Darren Hart --- misc/create_inode.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/misc/create_inode.c b/misc/create_inode.c index 6a8c92a..aad7354 100644 --- a/misc/create_inode.c +++ b/misc/create_inode.c @@ -18,6 +18,40 @@ #define S_BLKSIZE 512 #endif +/* Fill the uid, gid, mode and time for the inode */ +static void fill_inode(struct ext2_inode *inode, struct stat *st) +{ + if (st != NULL) { + inode->i_uid = st->st_uid; + inode->i_gid = st->st_gid; + inode->i_mode |= st->st_mode; + inode->i_atime = st->st_atime; + inode->i_mtime = st->st_mtime; + inode->i_ctime = st->st_ctime; + } +} + +/* Set the uid, gid, mode and time for the inode */ +errcode_t set_inode_extra(ext2_ino_t cwd, ext2_ino_t ino, struct stat *st) +{ + errcode_t retval; + struct ext2_inode inode; + + retval = ext2fs_read_inode(current_fs, ino, &inode); + if (retval) { + com_err(__func__, retval, "while reading inode %u", ino); + return retval; + } + + fill_inode(&inode, st); + + retval = ext2fs_write_inode(current_fs, ino, &inode); + if (retval) { + com_err(__func__, retval, "while writing inode %u", ino); + return retval; + } +} + /* Make a special file which is block, character and fifo */ errcode_t do_mknod_internal(ext2_ino_t cwd, const char *name, struct stat *st) { @@ -435,6 +469,17 @@ errcode_t populate_fs(ext2_ino_t parent_ino, const char *source_dir) com_err(__func__, 0, _("ignoring entry \"%s\""), name); } + + if ((retval = ext2fs_namei(current_fs, root, parent_ino, name, &ino))){ + com_err(name, retval, 0); + return retval; + } + + if ((retval = set_inode_extra(parent_ino, ino, &st))) { + com_err(__func__, retval, + _("while setting inode for \"%s\""), name); + return retval; + } } closedir(dh); return retval; -- 1.7.10.4