From: Ross Burton Date: Thu, 10 Jul 2014 16:44:38 +0000 (+0100) Subject: misc: copy extended attributes in populate_fs X-Git-Tag: v1.43-WIP-2015-05-18~268^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c84da2eed09acee1cc9d2912bed71e9bb5788c8e;p=thirdparty%2Fe2fsprogs.git misc: copy extended attributes in populate_fs When creating a file system using a source directory, also copy any extended attributes that have been set. [ Add configure tests for Linux-specific xattr syscalls and add fallback when compiling on non-Linux systems. --tytso ] Signed-off-by: Ross Burton Reviewed-by: Darrick J. Wong Signed-off-by: Theodore Ts'o --- diff --git a/configure b/configure index d8f6debce..6c503aaf7 100755 --- a/configure +++ b/configure @@ -12404,7 +12404,7 @@ fi done fi -for ac_header in dirent.h errno.h execinfo.h getopt.h malloc.h mntent.h paths.h semaphore.h setjmp.h signal.h stdarg.h stdint.h stdlib.h termios.h termio.h unistd.h utime.h linux/falloc.h linux/fd.h linux/major.h linux/loop.h net/if_dl.h netinet/in.h sys/disklabel.h sys/disk.h sys/file.h sys/ioctl.h sys/mkdev.h sys/mman.h sys/mount.h sys/prctl.h sys/resource.h sys/select.h sys/socket.h sys/sockio.h sys/stat.h sys/syscall.h sys/sysmacros.h sys/time.h sys/types.h sys/un.h sys/wait.h +for ac_header in dirent.h errno.h execinfo.h getopt.h malloc.h mntent.h paths.h semaphore.h setjmp.h signal.h stdarg.h stdint.h stdlib.h termios.h termio.h unistd.h utime.h attr/xattr.h linux/falloc.h linux/fd.h linux/major.h linux/loop.h net/if_dl.h netinet/in.h sys/disklabel.h sys/disk.h sys/file.h sys/ioctl.h sys/mkdev.h sys/mman.h sys/mount.h sys/prctl.h sys/resource.h sys/select.h sys/socket.h sys/sockio.h sys/stat.h sys/syscall.h sys/sysmacros.h sys/time.h sys/types.h sys/un.h sys/wait.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" @@ -13071,7 +13071,7 @@ if test "$ac_res" != no; then : fi fi -for ac_func in __secure_getenv backtrace blkid_probe_get_topology blkid_probe_enable_partitions chflags fadvise64 fallocate fallocate64 fchown fdatasync fstat64 ftruncate64 futimes getcwd getdtablesize getmntinfo getpwuid_r getrlimit getrusage jrand48 llseek lseek64 mallinfo mbstowcs memalign mempcpy mmap msync nanosleep open64 pathconf posix_fadvise posix_fadvise64 posix_memalign prctl secure_getenv setmntent setresgid setresuid snprintf srandom stpcpy strcasecmp strdup strnlen strptime strtoull sync_file_range sysconf usleep utime valloc +for ac_func in __secure_getenv backtrace blkid_probe_get_topology blkid_probe_enable_partitions chflags fadvise64 fallocate fallocate64 fchown fdatasync fstat64 ftruncate64 futimes getcwd getdtablesize getmntinfo getpwuid_r getrlimit getrusage jrand48 llistxattr llseek lseek64 mallinfo mbstowcs memalign mempcpy mmap msync nanosleep open64 pathconf posix_fadvise posix_fadvise64 posix_memalign prctl secure_getenv setmntent setresgid setresuid snprintf srandom stpcpy strcasecmp strdup strnlen strptime strtoull sync_file_range sysconf usleep utime valloc do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" diff --git a/configure.in b/configure.in index 79c8dc266..67e545313 100644 --- a/configure.in +++ b/configure.in @@ -920,6 +920,7 @@ AC_CHECK_HEADERS(m4_flatten([ termio.h unistd.h utime.h + attr/xattr.h linux/falloc.h linux/fd.h linux/major.h @@ -1098,6 +1099,7 @@ AC_CHECK_FUNCS(m4_flatten([ getrlimit getrusage jrand48 + llistxattr llseek lseek64 mallinfo diff --git a/lib/config.h.in b/lib/config.h.in index 3ed71fa0e..12a609a45 100644 --- a/lib/config.h.in +++ b/lib/config.h.in @@ -70,6 +70,9 @@ /* Define to 1 if you have the `asprintf' function. */ #undef HAVE_ASPRINTF +/* Define to 1 if you have the header file. */ +#undef HAVE_ATTR_XATTR_H + /* Define to 1 if you have the `backtrace' function. */ #undef HAVE_BACKTRACE @@ -244,6 +247,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_MAJOR_H +/* Define to 1 if you have the `llistxattr' function. */ +#undef HAVE_LLISTXATTR + /* Define to 1 if you have the `llseek' function. */ #undef HAVE_LLSEEK diff --git a/misc/create_inode.c b/misc/create_inode.c index 92086d275..4d567199a 100644 --- a/misc/create_inode.c +++ b/misc/create_inode.c @@ -12,6 +12,9 @@ #include #include #include /* for PATH_MAX */ +#ifdef HAVE_ATTR_XATTR_H +#include +#endif #include "create_inode.h" @@ -103,6 +106,94 @@ static errcode_t set_inode_extra(ext2_filsys fs, ext2_ino_t cwd, return retval; } +static errcode_t set_inode_xattr(ext2_filsys fs, ext2_ino_t ino, const char *filename) +{ +#ifdef HAVE_LLISTXATTR + errcode_t retval, close_retval; + struct ext2_inode inode; + struct ext2_xattr_handle *handle; + ssize_t size, value_size; + char *list; + int i; + + size = llistxattr(filename, NULL, 0); + if (size == -1) { + com_err(__func__, errno, "llistxattr failed on %s", filename); + return errno; + } else if (size == 0) { + return 0; + } + + retval = ext2fs_xattrs_open(fs, ino, &handle); + if (retval) { + if (retval == EXT2_ET_MISSING_EA_FEATURE) + return 0; + com_err(__func__, retval, "while opening inode %u", ino); + return retval; + } + + retval = ext2fs_get_mem(size, &list); + if (retval) { + com_err(__func__, retval, "whilst allocating memory"); + goto out; + } + + size = llistxattr(filename, list, size); + if (size == -1) { + com_err(__func__, errno, "llistxattr failed on %s", filename); + retval = errno; + goto out; + } + + for (i = 0; i < size; i += strlen(&list[i]) + 1) { + const char *name = &list[i]; + char *value; + + value_size = getxattr(filename, name, NULL, 0); + if (value_size == -1) { + com_err(__func__, errno, "getxattr failed on %s", + filename); + retval = errno; + break; + } + + retval = ext2fs_get_mem(value_size, &value); + if (retval) { + com_err(__func__, retval, "whilst allocating memory"); + break; + } + + value_size = getxattr(filename, name, value, value_size); + if (value_size == -1) { + ext2fs_free_mem(&value); + com_err(__func__, errno, "getxattr failed on %s", + filename); + retval = errno; + break; + } + + retval = ext2fs_xattr_set(handle, name, value, value_size); + ext2fs_free_mem(&value); + if (retval) { + com_err(__func__, retval, + "while writing xattr %u", ino); + break; + } + + } + out: + ext2fs_free_mem(&list); + close_retval = ext2fs_xattrs_close(&handle); + if (close_retval) { + com_err(__func__, retval, "while closing inode %u", ino); + retval = retval ? retval : close_retval; + } + return retval; +#else /* HAVE_LLISTXATTR */ + return 0; +#endif /* HAVE_LLISTXATTR */ +} + /* Make a special files (block and character devices), fifo's, and sockets */ errcode_t do_mknod_internal(ext2_filsys fs, ext2_ino_t cwd, const char *name, struct stat *st) @@ -620,6 +711,13 @@ static errcode_t __populate_fs(ext2_filsys fs, ext2_ino_t parent_ino, goto out; } + retval = set_inode_xattr(fs, ino, name); + if (retval) { + com_err(__func__, retval, + _("while setting xattrs for \"%s\""), name); + goto out; + } + /* Save the hardlink ino */ if (save_inode) { /*