summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--ChangeLog12
-rw-r--r--bootstrap.conf1
-rw-r--r--configure.ac2
-rw-r--r--m4/.gitignore116
-rw-r--r--m4/xattr.m444
-rw-r--r--src/Makefile.am3
-rw-r--r--src/patch.c9
-rw-r--r--src/util.c70
-rw-r--r--src/util.h4
10 files changed, 251 insertions, 11 deletions
diff --git a/.gitignore b/.gitignore
index 4c2012b..1d3147f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,7 +15,6 @@
/config.status
/configure
/lib
-/m4
/patch-*.tar.bz2
/patch-*.tar.bz2.sig
/patch-*.tar.gz
diff --git a/ChangeLog b/ChangeLog
index 2a0084a..2519200 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,6 +4,18 @@
be set when FA_MODE is specified.
(create_backup_copy): Update accordingly.
+ * 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.
+
2010-10-26 Andreas Gruenbacher <agruen@suse.de>
* configure.ac: Remove obsolete checks for mktemp.
diff --git a/bootstrap.conf b/bootstrap.conf
index 260164d..688fde0 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -56,6 +56,7 @@ time
unistd
unlink
utimens
+verror
xalloc
"
diff --git a/configure.ac b/configure.ac
index 8912210..82e0a52 100644
--- a/configure.ac
+++ b/configure.ac
@@ -49,6 +49,8 @@ gl_INIT
AC_TYPE_MODE_T
AC_TYPE_OFF_T
+gl_FUNC_XATTR
+
AC_CHECK_FUNCS(geteuid getuid raise sigaction sigprocmask sigsetmask)
AC_FUNC_SETMODE_DOS
diff --git a/m4/.gitignore b/m4/.gitignore
new file mode 100644
index 0000000..057a6a6
--- /dev/null
+++ b/m4/.gitignore
@@ -0,0 +1,116 @@
+00gnulib.m4
+alloca.m4
+argmatch.m4
+backupfile.m4
+bison.m4
+canonicalize.m4
+clock_time.m4
+codeset.m4
+d-ino.m4
+dirent-safer.m4
+dirent_h.m4
+dirfd.m4
+dirname.m4
+dos.m4
+double-slash-root.m4
+dup2.m4
+eealloc.m4
+environ.m4
+errno_h.m4
+error.m4
+extensions.m4
+fcntl-o.m4
+fcntl.m4
+fcntl_h.m4
+float_h.m4
+fseek.m4
+fseeko.m4
+ftell.m4
+ftello.m4
+getdate.m4
+getdtablesize.m4
+getopt.m4
+gettime.m4
+gettimeofday.m4
+glibc21.m4
+gnulib-cache.m4
+gnulib-common.m4
+gnulib-comp.m4
+gnulib-tool.m4
+hash.m4
+include_next.m4
+inline.m4
+intmax_t.m4
+inttypes_h.m4
+lchmod.m4
+localcharset.m4
+locale-fr.m4
+locale-ja.m4
+locale-zh.m4
+longlong.m4
+lseek.m4
+lstat.m4
+malloc.m4
+malloca.m4
+mbrtowc.m4
+mbsinit.m4
+mbstate_t.m4
+memchr.m4
+minmax.m4
+mkdir.m4
+mktime.m4
+mmap-anon.m4
+multiarch.m4
+onceonly.m4
+pathmax.m4
+printf.m4
+quote.m4
+quotearg.m4
+readlink.m4
+realloc.m4
+rename.m4
+rmdir.m4
+safe-read.m4
+safe-write.m4
+setenv.m4
+size_max.m4
+ssize_t.m4
+stat-time.m4
+stat.m4
+stdarg.m4
+stdbool.m4
+stddef_h.m4
+stdint.m4
+stdint_h.m4
+stdio_h.m4
+stdlib_h.m4
+strerror.m4
+string_h.m4
+strndup.m4
+strnlen.m4
+symlink.m4
+sys_stat_h.m4
+sys_time_h.m4
+tempname.m4
+time_h.m4
+time_r.m4
+timespec.m4
+tm_gmtoff.m4
+unistd-safer.m4
+unistd_h.m4
+unlink.m4
+utimbuf.m4
+utimens.m4
+utimes.m4
+vasnprintf.m4
+vasprintf.m4
+warn-on-use.m4
+wchar_h.m4
+wchar_t.m4
+wctype_h.m4
+wint_t.m4
+write.m4
+xalloc.m4
+xsize.m4
+xstrndup.m4
+xvasprintf.m4
diff --git a/m4/xattr.m4 b/m4/xattr.m4
new file mode 100644
index 0000000..80fddbd
--- /dev/null
+++ b/m4/xattr.m4
@@ -0,0 +1,44 @@
+# xattr.m4 - check for Extended Attributes (Linux)
+# serial 3
+
+# Copyright (C) 2003, 2008-2010 Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# Originally written by Andreas Gruenbacher.
+# http://www.suse.de/~agruen/coreutils/5.91/coreutils-xattr.diff
+
+AC_DEFUN([gl_FUNC_XATTR],
+[
+ AC_ARG_ENABLE([xattr],
+ AC_HELP_STRING([--disable-xattr],
+ [do not support extended attributes]),
+ [use_xattr=$enableval], [use_xattr=yes])
+
+ LIB_XATTR=
+ AC_SUBST([LIB_XATTR])
+
+ if test "$use_xattr" = "yes"; then
+ AC_CHECK_HEADERS([attr/error_context.h attr/libattr.h])
+ use_xattr=no
+ if test $ac_cv_header_attr_libattr_h = yes \
+ && test $ac_cv_header_attr_error_context_h = yes; then
+ xattr_saved_LIBS=$LIBS
+ AC_SEARCH_LIBS([attr_copy_file], [attr],
+ [test "$ac_cv_search_attr_copy_file" = "none required" ||
+ LIB_XATTR=$ac_cv_search_attr_copy_file])
+ AC_CHECK_FUNCS([attr_copy_file])
+ LIBS=$xattr_saved_LIBS
+ if test $ac_cv_func_attr_copy_file = yes; then
+ use_xattr=yes
+ fi
+ fi
+ if test $use_xattr = no; then
+ AC_MSG_WARN([libattr development library was not found or not usable.])
+ AC_MSG_WARN([AC_PACKAGE_NAME will be built without xattr support.])
+ fi
+ fi
+ AC_DEFINE_UNQUOTED([USE_XATTR], [`test $use_xattr != yes; echo $?`],
+ [Define if you want extended attribute support.])
+])
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 ())
{
diff --git a/src/util.c b/src/util.c
index 22b19d0..2f9c2f6 100644
--- a/src/util.c
+++ b/src/util.c
@@ -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
diff --git a/src/util.h b/src/util.h
index 521d098..6ab09f0 100644
--- a/src/util.h
+++ b/src/util.h
@@ -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)