diff options
author | Andreas Gruenbacher <agruen@suse.de> | 2010-10-27 02:53:42 +0200 |
---|---|---|
committer | Andreas Gruenbacher <agruen@suse.de> | 2010-10-27 02:53:42 +0200 |
commit | 76d0e43140e83602ecca0073f2ee5515c3a9613b (patch) | |
tree | d00898bcd03371cde4b75d3f3b9a150e37efd973 /src | |
parent | 28113637f563534c5b4e1a462c39069b837d31d9 (diff) | |
download | patch-76d0e43140e83602ecca0073f2ee5515c3a9613b.tar.gz |
Preserve extended attributes of patched files when possible
* src/patch.c (main): Set all file attributes of the temporary output
file before renaming it over the final output file (possibly replacing
the input file). Pass the input file name to set_file_attributes().
* src/util.c (set_file_attributes): When enabled (USE_XATTR), also
copy extended attributes including attributes which define
permissions.
(copy_attr_error, copy_attr_quote, copy_attr_free, copy_attr_check,
copy_attr): Helper functions for copying extended attributes.
* m4/xattr.m4 (gl_FUNC_XATTR): Import from coreutils.
* src/Makefile.am (patch_LDADD): Add $(LIB_XATTR) here.
* bootstrap.conf: Use the gnulib verror module.
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/patch.c | 9 | ||||
-rw-r--r-- | src/util.c | 70 | ||||
-rw-r--r-- | src/util.h | 4 |
4 files changed, 76 insertions, 10 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index c1a1f9c..c119cfb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -31,7 +31,8 @@ patch_SOURCES = \ version.h AM_CPPFLAGS = -I$(top_builddir)/lib -I$(top_srcdir)/lib -patch_LDADD = $(LDADD) $(top_builddir)/lib/libpatch.a $(LIB_CLOCK_GETTIME) +patch_LDADD = $(LDADD) $(top_builddir)/lib/libpatch.a $(LIB_CLOCK_GETTIME) \ + $(LIB_XATTR) if ENABLE_MERGE patch_SOURCES += merge.c diff --git a/src/patch.c b/src/patch.c index 6d37581..77be499 100644 --- a/src/patch.c +++ b/src/patch.c @@ -476,9 +476,6 @@ main (int argc, char **argv) mode_t mode = file_type | ((new_mode ? new_mode : instat.st_mode) & S_IRWXUGO); - move_file (TMPOUTNAME, &TMPOUTNAME_needs_removal, &outst, - outname, mode, backup); - if ((set_time | set_utc) && new_time.tv_sec != -1) { struct timespec old_time = pch_timestamp (reverse); @@ -500,7 +497,11 @@ main (int argc, char **argv) } if (! inerrno) - set_file_attributes (outname, attr, &instat, mode, &new_time); + set_file_attributes (TMPOUTNAME, attr, inname, &instat, + mode, &new_time); + + move_file (TMPOUTNAME, &TMPOUTNAME_needs_removal, &outst, + outname, mode, backup); if (pch_rename ()) { @@ -42,6 +42,13 @@ #include <full-write.h> #include <tempname.h> +#ifdef USE_XATTR +# include <attr/error_context.h> +# include <attr/libattr.h> +# include <stdarg.h> +# include "verror.h" +#endif + static void makedirs (char const *); typedef struct @@ -123,9 +130,64 @@ contains_slash (const char *s) return false; } +#ifdef USE_XATTR + +static void +copy_attr_error (struct error_context *ctx, char const *fmt, ...) +{ + int err = errno; + va_list ap; + + /* use verror module to print error message */ + va_start (ap, fmt); + verror (0, err, fmt, ap); + va_end (ap); +} + +static char const * +copy_attr_quote (struct error_context *ctx, char const *str) +{ + return quotearg (str); +} + +static void +copy_attr_free (struct error_context *ctx, char const *str) +{ +} + +static int +copy_attr_check (const char *name, struct error_context *ctx) +{ + int action = attr_copy_action (name, ctx); + return action == 0 || action == ATTR_ACTION_PERMISSIONS; +} + +static int +copy_attr (char const *src_path, char const *dst_path) +{ + struct error_context ctx = + { + .error = copy_attr_error, + .quote = copy_attr_quote, + .quote_free = copy_attr_free + }; + return attr_copy_file (src_path, dst_path, copy_attr_check, &ctx); +} + +#else /* USE_XATTR */ + +static int +copy_attr (char const *src_path, char const *dst_path) +{ + return 0; +} + +#endif + void set_file_attributes (char const *to, enum file_attributes attr, - struct stat *st, mode_t mode, struct timespec *new_time) + char const *from, struct stat *st, mode_t mode, + struct timespec *new_time) { if (attr & FA_TIMES) { @@ -170,6 +232,9 @@ set_file_attributes (char const *to, enum file_attributes attr, S_ISLNK (st->st_mode) ? "symbolic link" : "file", quotearg (to)); } + if (copy_attr (from, to)) + fatal_exit (0); + /* FIXME: There may be other attributes to preserve. */ if (attr & FA_MODE) { #if 0 && defined HAVE_LCHMOD @@ -184,7 +249,6 @@ set_file_attributes (char const *to, enum file_attributes attr, S_ISLNK (st->st_mode) ? "symbolic link" : "file", quotearg (to)); } - /* FIXME: There may be other attributes to preserve. */ } static void @@ -196,7 +260,7 @@ create_backup_copy (char const *from, char const *to, struct stat *st, to_dir_known_to_exist); if (remember_backup) insert_file (&backup_st); - set_file_attributes (to, FA_TIMES | FA_IDS | FA_MODE, st, st->st_mode, NULL); + set_file_attributes (to, FA_TIMES | FA_IDS | FA_MODE, from, st, st->st_mode, NULL); } void @@ -70,8 +70,8 @@ enum file_attributes { FA_MODE = 4 }; -void set_file_attributes (char const *, enum file_attributes, struct stat *, - mode_t, struct timespec *); +void set_file_attributes (char const *, enum file_attributes, char const *, + struct stat *, mode_t, struct timespec *); static inline char const * skip_spaces (char const *str) |