aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRomain Francoise2012-12-16 19:22:27 +0100
committerRomain Francoise2012-12-16 19:22:27 +0100
commit7c3d167f48d6262ee4e5512aa50a07ee96bc1509 (patch)
tree9d4c24c1c97ae0cb1763e51d6ab8e808283fb09b /src
parenta5e9740d8ecfd471ecbc1f02980b83b003c1a469 (diff)
downloademacs-7c3d167f48d6262ee4e5512aa50a07ee96bc1509.tar.gz
emacs-7c3d167f48d6262ee4e5512aa50a07ee96bc1509.zip
Add support for preserving ACL entries of files.
* configure.ac (acl): New option. (HAVE_POSIX_ACL): Test for POSIX ACL support. This is typically provided by libacl on GNU/Linux. * fileio.c (Ffile_acl, Fset_file_acl): New functions. (Fcopy_file): Change last arg to `preserve_extended_attributes' and copy ACL entries of file in addition to SELinux context if set. (syms_of_fileio): Add `file-acl' and `set-file-acl'. * Makefile.in (LIBACL_LIBS): New macro. (LIBES): Use it. * files.el (file-extended-attributes) (set-file-extended-attributes): New functions. (backup-buffer): Use them to handle both SELinux context and ACL entries. (backup-buffer-copy): Work with an alist of extended attributes, rather than an SELinux context. (basic-save-buffer-2): Ditto. * files.texi (File Attributes): Document ACL support and new `file-acl' function. (Changing Files): Mention argument name change of `copy-file' and document new function `set-file-acl'.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog11
-rw-r--r--src/Makefile.in4
-rw-r--r--src/fileio.c154
3 files changed, 158 insertions, 11 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 54dcfca6fd5..3cf105c8003 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,14 @@
12012-12-16 Romain Francoise <romain@orebokech.com>
2
3 * fileio.c (Ffile_acl, Fset_file_acl): New functions.
4 (Fcopy_file): Change last arg to `preserve_extended_attributes'
5 and copy ACL entries of file in addition to SELinux context if
6 set.
7 (syms_of_fileio): Add `file-acl' and `set-file-acl'.
8
9 * Makefile.in (LIBACL_LIBS): New macro.
10 (LIBES): Use it.
11
12012-12-15 Paul Eggert <eggert@cs.ucla.edu> 122012-12-15 Paul Eggert <eggert@cs.ucla.edu>
2 13
3 * fileio.c (internal_delete_file): Use bool for boolean. 14 * fileio.c (internal_delete_file): Use bool for boolean.
diff --git a/src/Makefile.in b/src/Makefile.in
index 5f5fdfdc5eb..0e91eaecb17 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -292,6 +292,8 @@ LIBSELINUX_LIBS = @LIBSELINUX_LIBS@
292LIBGNUTLS_LIBS = @LIBGNUTLS_LIBS@ 292LIBGNUTLS_LIBS = @LIBGNUTLS_LIBS@
293LIBGNUTLS_CFLAGS = @LIBGNUTLS_CFLAGS@ 293LIBGNUTLS_CFLAGS = @LIBGNUTLS_CFLAGS@
294 294
295LIBACL_LIBS = @LIBACL_LIBS@
296
295LIB_PTHREAD_SIGMASK = @LIB_PTHREAD_SIGMASK@ 297LIB_PTHREAD_SIGMASK = @LIB_PTHREAD_SIGMASK@
296 298
297INTERVALS_H = dispextern.h intervals.h composite.h 299INTERVALS_H = dispextern.h intervals.h composite.h
@@ -406,7 +408,7 @@ LIBES = $(LIBS) $(W32_LIBS) $(LIBX_BASE) $(LIBIMAGE) \
406 $(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) \ 408 $(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) \
407 $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \ 409 $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \
408 $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \ 410 $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \
409 $(LIBGNUTLS_LIBS) $(LIB_PTHREAD) $(LIB_PTHREAD_SIGMASK) \ 411 $(LIBACL_LIBS) $(LIBGNUTLS_LIBS) $(LIB_PTHREAD) $(LIB_PTHREAD_SIGMASK) \
410 $(LIB_GCC) $(LIB_MATH) $(LIB_STANDARD) $(LIB_GCC) 412 $(LIB_GCC) $(LIB_MATH) $(LIB_STANDARD) $(LIB_GCC)
411 413
412all: emacs$(EXEEXT) $(OTHER_FILES) 414all: emacs$(EXEEXT) $(OTHER_FILES)
diff --git a/src/fileio.c b/src/fileio.c
index 90626c4af0e..f1cfe0eb625 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -36,6 +36,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
36#include <selinux/context.h> 36#include <selinux/context.h>
37#endif 37#endif
38 38
39#ifdef HAVE_POSIX_ACL
40#include <sys/acl.h>
41#endif
42
39#include <c-ctype.h> 43#include <c-ctype.h>
40 44
41#include "lisp.h" 45#include "lisp.h"
@@ -236,6 +240,8 @@ static Lisp_Object Qset_file_modes;
236static Lisp_Object Qset_file_times; 240static Lisp_Object Qset_file_times;
237static Lisp_Object Qfile_selinux_context; 241static Lisp_Object Qfile_selinux_context;
238static Lisp_Object Qset_file_selinux_context; 242static Lisp_Object Qset_file_selinux_context;
243static Lisp_Object Qfile_acl;
244static Lisp_Object Qset_file_acl;
239static Lisp_Object Qfile_newer_than_file_p; 245static Lisp_Object Qfile_newer_than_file_p;
240Lisp_Object Qinsert_file_contents; 246Lisp_Object Qinsert_file_contents;
241Lisp_Object Qwrite_region; 247Lisp_Object Qwrite_region;
@@ -1895,9 +1901,10 @@ A prefix arg makes KEEP-TIME non-nil.
1895If PRESERVE-UID-GID is non-nil, we try to transfer the 1901If PRESERVE-UID-GID is non-nil, we try to transfer the
1896uid and gid of FILE to NEWNAME. 1902uid and gid of FILE to NEWNAME.
1897 1903
1898If PRESERVE-SELINUX-CONTEXT is non-nil and SELinux is enabled 1904If PRESERVE-EXTENDED-ATTRIBUTES is non-nil, we try to copy additional
1899on the system, we copy the SELinux context of FILE to NEWNAME. */) 1905attributes of FILE to NEWNAME, such as its SELinux context and ACL
1900 (Lisp_Object file, Lisp_Object newname, Lisp_Object ok_if_already_exists, Lisp_Object keep_time, Lisp_Object preserve_uid_gid, Lisp_Object preserve_selinux_context) 1906entries (depending on how Emacs was built). */)
1907 (Lisp_Object file, Lisp_Object newname, Lisp_Object ok_if_already_exists, Lisp_Object keep_time, Lisp_Object preserve_uid_gid, Lisp_Object preserve_extended_attributes)
1901{ 1908{
1902 int ifd, ofd; 1909 int ifd, ofd;
1903 int n; 1910 int n;
@@ -1911,6 +1918,9 @@ on the system, we copy the SELinux context of FILE to NEWNAME. */)
1911 security_context_t con; 1918 security_context_t con;
1912 int conlength = 0; 1919 int conlength = 0;
1913#endif 1920#endif
1921#ifdef HAVE_POSIX_ACL
1922 acl_t acl = NULL;
1923#endif
1914 1924
1915 encoded_file = encoded_newname = Qnil; 1925 encoded_file = encoded_newname = Qnil;
1916 GCPRO4 (file, newname, encoded_file, encoded_newname); 1926 GCPRO4 (file, newname, encoded_file, encoded_newname);
@@ -1933,7 +1943,7 @@ on the system, we copy the SELinux context of FILE to NEWNAME. */)
1933 if (!NILP (handler)) 1943 if (!NILP (handler))
1934 RETURN_UNGCPRO (call7 (handler, Qcopy_file, file, newname, 1944 RETURN_UNGCPRO (call7 (handler, Qcopy_file, file, newname,
1935 ok_if_already_exists, keep_time, preserve_uid_gid, 1945 ok_if_already_exists, keep_time, preserve_uid_gid,
1936 preserve_selinux_context)); 1946 preserve_extended_attributes));
1937 1947
1938 encoded_file = ENCODE_FILE (file); 1948 encoded_file = ENCODE_FILE (file);
1939 encoded_newname = ENCODE_FILE (newname); 1949 encoded_newname = ENCODE_FILE (newname);
@@ -1986,14 +1996,23 @@ on the system, we copy the SELinux context of FILE to NEWNAME. */)
1986 if (fstat (ifd, &st) != 0) 1996 if (fstat (ifd, &st) != 0)
1987 report_file_error ("Input file status", Fcons (file, Qnil)); 1997 report_file_error ("Input file status", Fcons (file, Qnil));
1988 1998
1989#if HAVE_LIBSELINUX 1999 if (!NILP (preserve_extended_attributes))
1990 if (!NILP (preserve_selinux_context) && is_selinux_enabled ())
1991 { 2000 {
1992 conlength = fgetfilecon (ifd, &con); 2001#if HAVE_LIBSELINUX
1993 if (conlength == -1) 2002 if (is_selinux_enabled ())
1994 report_file_error ("Doing fgetfilecon", Fcons (file, Qnil)); 2003 {
1995 } 2004 conlength = fgetfilecon (ifd, &con);
2005 if (conlength == -1)
2006 report_file_error ("Doing fgetfilecon", Fcons (file, Qnil));
2007 }
2008#endif
2009
2010#ifdef HAVE_POSIX_ACL
2011 acl = acl_get_fd (ifd);
2012 if (acl == NULL && errno != ENOTSUP)
2013 report_file_error ("Getting ACL", Fcons (file, Qnil));
1996#endif 2014#endif
2015 }
1997 2016
1998 if (out_st.st_mode != 0 2017 if (out_st.st_mode != 0
1999 && st.st_dev == out_st.st_dev && st.st_ino == out_st.st_ino) 2018 && st.st_dev == out_st.st_dev && st.st_ino == out_st.st_ino)
@@ -2075,6 +2094,17 @@ on the system, we copy the SELinux context of FILE to NEWNAME. */)
2075 } 2094 }
2076#endif 2095#endif
2077 2096
2097#ifdef HAVE_POSIX_ACL
2098 if (acl != NULL)
2099 {
2100 bool fail = acl_set_fd (ofd, acl) != 0;
2101 if (fail && errno != ENOTSUP)
2102 report_file_error ("Setting ACL", Fcons (newname, Qnil));
2103
2104 acl_free (acl);
2105 }
2106#endif
2107
2078 if (!NILP (keep_time)) 2108 if (!NILP (keep_time))
2079 { 2109 {
2080 EMACS_TIME atime = get_stat_atime (&st); 2110 EMACS_TIME atime = get_stat_atime (&st);
@@ -2961,6 +2991,106 @@ compiled with SELinux support. */)
2961 return Qnil; 2991 return Qnil;
2962} 2992}
2963 2993
2994DEFUN ("file-acl", Ffile_acl, Sfile_acl, 1, 1, 0,
2995 doc: /* Return ACL entries of file named FILENAME, as a string.
2996Return nil if file does not exist or is not accessible, or if Emacs
2997was unable to determine the ACL entries. The latter can happen for
2998local files if Emacs was not compiled with ACL support, or for remote
2999files if the file handler returns nil for the file's ACL entries. */)
3000 (Lisp_Object filename)
3001{
3002 Lisp_Object absname;
3003 Lisp_Object handler;
3004#ifdef HAVE_POSIX_ACL
3005 acl_t acl;
3006 Lisp_Object acl_string;
3007 char *str;
3008#endif
3009
3010 absname = expand_and_dir_to_file (filename,
3011 BVAR (current_buffer, directory));
3012
3013 /* If the file name has special constructs in it,
3014 call the corresponding file handler. */
3015 handler = Ffind_file_name_handler (absname, Qfile_acl);
3016 if (!NILP (handler))
3017 return call2 (handler, Qfile_acl, absname);
3018
3019#ifdef HAVE_POSIX_ACL
3020 absname = ENCODE_FILE (absname);
3021
3022 acl = acl_get_file (SSDATA (absname), ACL_TYPE_ACCESS);
3023 if (acl == NULL)
3024 return Qnil;
3025
3026 str = acl_to_text (acl, NULL);
3027 if (str == NULL)
3028 {
3029 acl_free (acl);
3030 return Qnil;
3031 }
3032
3033 acl_string = build_string (str);
3034 acl_free (str);
3035 acl_free (acl);
3036
3037 return acl_string;
3038#endif
3039
3040 return Qnil;
3041}
3042
3043DEFUN ("set-file-acl", Fset_file_acl, Sset_file_acl,
3044 2, 2, 0,
3045 doc: /* Set ACL of file named FILENAME to ACL-STRING.
3046ACL-STRING should contain the textual representation of the ACL
3047entries in a format suitable for the platform.
3048
3049Setting ACL for local files requires Emacs to be built with ACL
3050support. */)
3051 (Lisp_Object filename, Lisp_Object acl_string)
3052{
3053 Lisp_Object absname;
3054 Lisp_Object handler;
3055#ifdef HAVE_POSIX_ACL
3056 Lisp_Object encoded_absname;
3057 acl_t acl;
3058 bool fail;
3059#endif
3060
3061 absname = Fexpand_file_name (filename, BVAR (current_buffer, directory));
3062
3063 /* If the file name has special constructs in it,
3064 call the corresponding file handler. */
3065 handler = Ffind_file_name_handler (absname, Qset_file_acl);
3066 if (!NILP (handler))
3067 return call3 (handler, Qset_file_acl, absname, acl_string);
3068
3069#ifdef HAVE_POSIX_ACL
3070 if (STRINGP (acl_string))
3071 {
3072 acl = acl_from_text (SSDATA (acl_string));
3073 if (acl == NULL)
3074 {
3075 report_file_error ("Converting ACL", Fcons (absname, Qnil));
3076 return Qnil;
3077 }
3078
3079 encoded_absname = ENCODE_FILE (absname);
3080
3081 fail = (acl_set_file (SSDATA (encoded_absname), ACL_TYPE_ACCESS,
3082 acl)
3083 != 0);
3084 if (fail && errno != ENOTSUP)
3085 report_file_error ("Setting ACL", Fcons (absname, Qnil));
3086
3087 acl_free (acl);
3088 }
3089#endif
3090
3091 return Qnil;
3092}
3093
2964DEFUN ("file-modes", Ffile_modes, Sfile_modes, 1, 1, 0, 3094DEFUN ("file-modes", Ffile_modes, Sfile_modes, 1, 1, 0,
2965 doc: /* Return mode bits of file named FILENAME, as an integer. 3095 doc: /* Return mode bits of file named FILENAME, as an integer.
2966Return nil, if file does not exist or is not accessible. */) 3096Return nil, if file does not exist or is not accessible. */)
@@ -5630,6 +5760,8 @@ syms_of_fileio (void)
5630 DEFSYM (Qset_file_times, "set-file-times"); 5760 DEFSYM (Qset_file_times, "set-file-times");
5631 DEFSYM (Qfile_selinux_context, "file-selinux-context"); 5761 DEFSYM (Qfile_selinux_context, "file-selinux-context");
5632 DEFSYM (Qset_file_selinux_context, "set-file-selinux-context"); 5762 DEFSYM (Qset_file_selinux_context, "set-file-selinux-context");
5763 DEFSYM (Qfile_acl, "file-acl");
5764 DEFSYM (Qset_file_acl, "set-file-acl");
5633 DEFSYM (Qfile_newer_than_file_p, "file-newer-than-file-p"); 5765 DEFSYM (Qfile_newer_than_file_p, "file-newer-than-file-p");
5634 DEFSYM (Qinsert_file_contents, "insert-file-contents"); 5766 DEFSYM (Qinsert_file_contents, "insert-file-contents");
5635 DEFSYM (Qwrite_region, "write-region"); 5767 DEFSYM (Qwrite_region, "write-region");
@@ -5849,6 +5981,8 @@ This includes interactive calls to `delete-file' and
5849 defsubr (&Sset_file_modes); 5981 defsubr (&Sset_file_modes);
5850 defsubr (&Sset_file_times); 5982 defsubr (&Sset_file_times);
5851 defsubr (&Sfile_selinux_context); 5983 defsubr (&Sfile_selinux_context);
5984 defsubr (&Sfile_acl);
5985 defsubr (&Sset_file_acl);
5852 defsubr (&Sset_file_selinux_context); 5986 defsubr (&Sset_file_selinux_context);
5853 defsubr (&Sset_default_file_modes); 5987 defsubr (&Sset_default_file_modes);
5854 defsubr (&Sdefault_file_modes); 5988 defsubr (&Sdefault_file_modes);