aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRomain Francoise2012-12-16 19:22:27 +0100
committerRomain Francoise2012-12-16 19:22:27 +0100
commit7c3d167f48d6262ee4e5512aa50a07ee96bc1509 (patch)
tree9d4c24c1c97ae0cb1763e51d6ab8e808283fb09b
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'.
-rw-r--r--ChangeLog6
-rw-r--r--configure.ac18
-rw-r--r--doc/lispref/ChangeLog7
-rw-r--r--doc/lispref/files.texi44
-rw-r--r--etc/NEWS24
-rw-r--r--lisp/ChangeLog10
-rw-r--r--lisp/files.el64
-rw-r--r--src/ChangeLog11
-rw-r--r--src/Makefile.in4
-rw-r--r--src/fileio.c154
10 files changed, 311 insertions, 31 deletions
diff --git a/ChangeLog b/ChangeLog
index f60ac180f6b..9f56370dc3c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
12012-12-16 Romain Francoise <romain@orebokech.com>
2
3 * configure.ac (acl): New option.
4 (HAVE_POSIX_ACL): Test for POSIX ACL support. This is typically
5 provided by libacl on GNU/Linux.
6
12012-12-14 Paul Eggert <eggert@cs.ucla.edu> 72012-12-14 Paul Eggert <eggert@cs.ucla.edu>
2 8
3 Fix permissions bugs with setgid directories etc. (Bug#13125) 9 Fix permissions bugs with setgid directories etc. (Bug#13125)
diff --git a/configure.ac b/configure.ac
index 1a7f78326eb..3c8be79e24c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -184,6 +184,7 @@ OPTION_DEFAULT_ON([dbus],[don't compile with D-Bus support])
184OPTION_DEFAULT_ON([gconf],[don't compile with GConf support]) 184OPTION_DEFAULT_ON([gconf],[don't compile with GConf support])
185OPTION_DEFAULT_ON([gsettings],[don't compile with GSettings support]) 185OPTION_DEFAULT_ON([gsettings],[don't compile with GSettings support])
186OPTION_DEFAULT_ON([selinux],[don't compile with SELinux support]) 186OPTION_DEFAULT_ON([selinux],[don't compile with SELinux support])
187OPTION_DEFAULT_ON([acl],[don't compile with ACL support])
187OPTION_DEFAULT_ON([gnutls],[don't use -lgnutls for SSL/TLS support]) 188OPTION_DEFAULT_ON([gnutls],[don't use -lgnutls for SSL/TLS support])
188OPTION_DEFAULT_ON([inotify],[don't compile with inotify (file-watch) support]) 189OPTION_DEFAULT_ON([inotify],[don't compile with inotify (file-watch) support])
189 190
@@ -2197,6 +2198,23 @@ if test "$ac_cv_func_inotify_init1" = yes; then
2197 AC_DEFINE(HAVE_INOTIFY, 1, [Define to 1 to use inotify.]) 2198 AC_DEFINE(HAVE_INOTIFY, 1, [Define to 1 to use inotify.])
2198fi 2199fi
2199 2200
2201dnl POSIX ACL support: provided by libacl on GNU/Linux, by libc on FreeBSD.
2202HAVE_POSIX_ACL=no
2203LIBACL_LIBS=
2204if test "${with_acl}" = "yes"; then
2205 AC_CHECK_LIB([acl], [acl_set_file], HAVE_POSIX_ACL=yes, HAVE_POSIX_ACL=no)
2206 if test "$HAVE_POSIX_ACL" = yes; then
2207 AC_DEFINE(HAVE_POSIX_ACL, 1, [Define to 1 if using POSIX ACL support.])
2208 LIBACL_LIBS=-lacl
2209 else
2210 AC_CHECK_FUNC(acl_set_file, HAVE_POSIX_ACL=yes, HAVE_POSIX_ACL=no)
2211 if test "$HAVE_POSIX_ACL" = yes; then
2212 AC_DEFINE(HAVE_POSIX_ACL, 1, [Define to 1 if using POSIX ACL support.])
2213 fi
2214 fi
2215fi
2216AC_SUBST(LIBACL_LIBS)
2217
2200dnl Do not put whitespace before the #include statements below. 2218dnl Do not put whitespace before the #include statements below.
2201dnl Older compilers (eg sunos4 cc) choke on it. 2219dnl Older compilers (eg sunos4 cc) choke on it.
2202HAVE_XAW3D=no 2220HAVE_XAW3D=no
diff --git a/doc/lispref/ChangeLog b/doc/lispref/ChangeLog
index 8a99f8c9c40..922147844bd 100644
--- a/doc/lispref/ChangeLog
+++ b/doc/lispref/ChangeLog
@@ -1,3 +1,10 @@
12012-12-16 Romain Francoise <romain@orebokech.com>
2
3 * files.texi (File Attributes): Document ACL support and new
4 `file-acl' function.
5 (Changing Files): Mention argument name change of `copy-file' and
6 document new function `set-file-acl'.
7
12012-12-14 Paul Eggert <eggert@cs.ucla.edu> 82012-12-14 Paul Eggert <eggert@cs.ucla.edu>
2 9
3 Fix permissions bugs with setgid directories etc. (Bug#13125) 10 Fix permissions bugs with setgid directories etc. (Bug#13125)
diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi
index c0c2221a394..93bee961929 100644
--- a/doc/lispref/files.texi
+++ b/doc/lispref/files.texi
@@ -1352,6 +1352,36 @@ not support SELinux, or if Emacs was not compiled with SELinux
1352support, then the return value is @code{(nil nil nil nil)}. 1352support, then the return value is @code{(nil nil nil nil)}.
1353@end defun 1353@end defun
1354 1354
1355@cindex access control list
1356@cindex ACL entries
1357 If Emacs has been compiled with @dfn{ACL} (access control list)
1358support, you can use the function @code{file-acl} to retrieve a file's
1359ACL entries. The format is platform-specific; on GNU/Linux and BSD,
1360Emacs uses the POSIX ACL interface. For the function
1361@code{set-file-acl}, see @ref{Changing Files}.
1362
1363@defun file-acl filename
1364This function returns the ACL entries of the file @var{filename}.
1365The return value is a string containing the textual representation of
1366the ACL entries, like the following:
1367
1368@example
1369@group
1370user::rw-
1371group::r--
1372group:gnu:rwx
1373mask::rwx
1374other::r--
1375@end group
1376@end example
1377
1378If the file does not exist or is inaccessible, or if Emacs was unable to
1379determine the ACL entries, then the return value is @code{nil}. The
1380latter can happen for local files if Emacs was not compiled with ACL
1381support, or for remote files if the file handler returns nil for the
1382file's ACL entries.
1383@end defun
1384
1355@node Locating Files 1385@node Locating Files
1356@subsection How to Locate Files in Standard Places 1386@subsection How to Locate Files in Standard Places
1357@cindex locate file in path 1387@cindex locate file in path
@@ -1541,9 +1571,10 @@ non-@code{nil}, we attempt to copy the user and group ownership of the
1541file. This works only on some operating systems, and only if you have 1571file. This works only on some operating systems, and only if you have
1542the correct permissions to do so. 1572the correct permissions to do so.
1543 1573
1544If the optional argument @var{preserve-selinux} is non-@code{nil}, and 1574If the optional argument @var{preserve-extended-attributes} is
1545Emacs has been compiled with SELinux support, this function attempts 1575non-@code{nil}, and Emacs has been built with the appropriate support,
1546to copy the file's SELinux context (@pxref{File Attributes}). 1576this function attempts to copy the file's extended attributes, such as
1577its SELinux context and ACL entries (@pxref{File Attributes}).
1547@end deffn 1578@end deffn
1548 1579
1549@deffn Command make-symbolic-link filename newname &optional ok-if-exists 1580@deffn Command make-symbolic-link filename newname &optional ok-if-exists
@@ -1684,6 +1715,13 @@ nothing if SELinux is disabled, or if Emacs was compiled without
1684SELinux support. 1715SELinux support.
1685@end defun 1716@end defun
1686 1717
1718@defun set-file-acl filename acl-string
1719This function sets the ACL entries of the file @var{filename} to
1720@var{acl-string}. @xref{File Attributes}, for a brief description of
1721ACLs. The @var{acl-string} argument should be a string containing the
1722textual representation of the desired ACL entries.
1723@end defun
1724
1687@node File Names 1725@node File Names
1688@section File Names 1726@section File Names
1689@cindex file names 1727@cindex file names
diff --git a/etc/NEWS b/etc/NEWS
index 0063aedb0db..1c82b760946 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -22,6 +22,12 @@ so we will look at it and add it to the manual.
22 22
23 23
24* Installation Changes in Emacs 24.4 24* Installation Changes in Emacs 24.4
25
26** Emacs can be compiled with POSIX ACL support.
27This happens by default if a suitable support library is found at
28build time, like libacl on GNU/Linux. To prevent this, use the
29configure option `--without-acl'.
30
25* Startup Changes in Emacs 24.4 31* Startup Changes in Emacs 24.4
26* Changes in Emacs 24.4 32* Changes in Emacs 24.4
27 33
@@ -33,6 +39,14 @@ if there is one.
33This unfinished feature was introduced by accident in Emacs 23.1; 39This unfinished feature was introduced by accident in Emacs 23.1;
34simply disabling Transient Mark mode does the same thing. 40simply disabling Transient Mark mode does the same thing.
35 41
42** ACL support has been added.
43+++
44*** Emacs preserves the ACL entries of files when backing up.
45+++
46*** New functions `file-acl' and `set-file-acl' get and set the ACL
47entries of a file. On GNU/Linux the POSIX ACL interface is used via
48libacl.
49
36* Editing Changes in Emacs 24.4 50* Editing Changes in Emacs 24.4
37 51
38** New commands `toggle-frame-maximized' and `cycle-frame-maximized', 52** New commands `toggle-frame-maximized' and `cycle-frame-maximized',
@@ -149,6 +163,12 @@ special-forms any more.
149VAR was bound to nil which was not tremendously useful and just lead to 163VAR was bound to nil which was not tremendously useful and just lead to
150spurious warnings about an unused var. 164spurious warnings about an unused var.
151 165
166** The return value of `backup-buffer' has changed.
167The second argument is no longer an SELinux context, instead it is an
168alist of extended attributes as returned by the new function
169`file-extended-attributes'. The attributes can be applied to another
170file using `set-file-extended-attributes'.
171
152* Lisp changes in Emacs 24.4 172* Lisp changes in Emacs 24.4
153 173
154** Support for filesystem notifications. 174** Support for filesystem notifications.
@@ -186,6 +206,10 @@ used in place of the 9th element of `file-attributes'.
186 206
187** New functions `group-gid' and `group-real-gid'. 207** New functions `group-gid' and `group-real-gid'.
188 208
209** The 6th argument to `copy-file' has been renamed to
210`preserve-extended-attributes' as it now handles both SELinux context
211and ACL entries.
212
189* Changes in Emacs 24.4 on non-free operating systems 213* Changes in Emacs 24.4 on non-free operating systems
190 214
191+++ 215+++
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index e56b44ba525..0d65baebee2 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,13 @@
12012-12-16 Romain Francoise <romain@orebokech.com>
2
3 * files.el (file-extended-attributes)
4 (set-file-extended-attributes): New functions.
5 (backup-buffer): Use them to handle both SELinux context and ACL
6 entries.
7 (backup-buffer-copy): Work with an alist of extended attributes,
8 rather than an SELinux context.
9 (basic-save-buffer-2): Ditto.
10
12012-12-16 Timo Myyrä <timo.myyra@gmail.com> 112012-12-16 Timo Myyrä <timo.myyra@gmail.com>
2 12
3 * battery.el (battery-bsd-apm): New function. 13 * battery.el (battery-bsd-apm): New function.
diff --git a/lisp/files.el b/lisp/files.el
index 7974f73a248..3f29468e2d1 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -3879,6 +3879,27 @@ Interactively, confirmation is required unless you supply a prefix argument."
3879 ;; the one at the old location. 3879 ;; the one at the old location.
3880 (vc-find-file-hook)) 3880 (vc-find-file-hook))
3881 3881
3882(defun file-extended-attributes (filename)
3883 "Return an alist of extended attributes of file FILENAME.
3884
3885Extended attributes are platform-specific metadata about the file,
3886such as SELinux context, list of ACL entries, etc."
3887 `((acl . ,(file-acl filename))
3888 (selinux-context . ,(file-selinux-context filename))))
3889
3890(defun set-file-extended-attributes (filename attributes)
3891 "Set extended attributes of file FILENAME to ATTRIBUTES.
3892
3893ATTRIBUTES must be an alist of file attributes as returned by
3894`file-extended-attributes'."
3895 (dolist (elt attributes)
3896 (let ((attr (car elt))
3897 (val (cdr elt)))
3898 (cond ((eq attr 'acl)
3899 (set-file-acl filename val))
3900 ((eq attr 'selinux-context)
3901 (set-file-selinux-context filename val))))))
3902
3882(defun backup-buffer () 3903(defun backup-buffer ()
3883 "Make a backup of the disk file visited by the current buffer, if appropriate. 3904 "Make a backup of the disk file visited by the current buffer, if appropriate.
3884This is normally done before saving the buffer the first time. 3905This is normally done before saving the buffer the first time.
@@ -3888,13 +3909,14 @@ variable `make-backup-files'. If it's done by renaming, then the file is
3888no longer accessible under its old name. 3909no longer accessible under its old name.
3889 3910
3890The value is non-nil after a backup was made by renaming. 3911The value is non-nil after a backup was made by renaming.
3891It has the form (MODES SELINUXCONTEXT BACKUPNAME). 3912It has the form (MODES EXTENDED-ATTRIBUTES BACKUPNAME).
3892MODES is the result of `file-modes' on the original 3913MODES is the result of `file-modes' on the original
3893file; this means that the caller, after saving the buffer, should change 3914file; this means that the caller, after saving the buffer, should change
3894the modes of the new file to agree with the old modes. 3915the modes of the new file to agree with the old modes.
3895SELINUXCONTEXT is the result of `file-selinux-context' on the original 3916EXTENDED-ATTRIBUTES is the result of `file-extended-attributes'
3896file; this means that the caller, after saving the buffer, should change 3917on the original file; this means that the caller, after saving
3897the SELinux context of the new file to agree with the old context. 3918the buffer, should change the extended attributes of the new file
3919to agree with the old attributes.
3898BACKUPNAME is the backup file name, which is the old file renamed." 3920BACKUPNAME is the backup file name, which is the old file renamed."
3899 (if (and make-backup-files (not backup-inhibited) 3921 (if (and make-backup-files (not backup-inhibited)
3900 (not buffer-backed-up) 3922 (not buffer-backed-up)
@@ -3923,7 +3945,8 @@ BACKUPNAME is the backup file name, which is the old file renamed."
3923 (y-or-n-p (format "Delete excess backup versions of %s? " 3945 (y-or-n-p (format "Delete excess backup versions of %s? "
3924 real-file-name))))) 3946 real-file-name)))))
3925 (modes (file-modes buffer-file-name)) 3947 (modes (file-modes buffer-file-name))
3926 (context (file-selinux-context buffer-file-name))) 3948 (extended-attributes
3949 (file-extended-attributes buffer-file-name)))
3927 ;; Actually write the back up file. 3950 ;; Actually write the back up file.
3928 (condition-case () 3951 (condition-case ()
3929 (if (or file-precious-flag 3952 (if (or file-precious-flag
@@ -3943,10 +3966,13 @@ BACKUPNAME is the backup file name, which is the old file renamed."
3943 (<= (nth 2 attr) backup-by-copying-when-privileged-mismatch))) 3966 (<= (nth 2 attr) backup-by-copying-when-privileged-mismatch)))
3944 (not (file-ownership-preserved-p 3967 (not (file-ownership-preserved-p
3945 real-file-name t)))))) 3968 real-file-name t))))))
3946 (backup-buffer-copy real-file-name backupname modes context) 3969 (backup-buffer-copy real-file-name
3970 backupname modes
3971 extended-attributes)
3947 ;; rename-file should delete old backup. 3972 ;; rename-file should delete old backup.
3948 (rename-file real-file-name backupname t) 3973 (rename-file real-file-name backupname t)
3949 (setq setmodes (list modes context backupname))) 3974 (setq setmodes (list modes extended-attributes
3975 backupname)))
3950 (file-error 3976 (file-error
3951 ;; If trouble writing the backup, write it in 3977 ;; If trouble writing the backup, write it in
3952 ;; .emacs.d/%backup%. 3978 ;; .emacs.d/%backup%.
@@ -3954,7 +3980,8 @@ BACKUPNAME is the backup file name, which is the old file renamed."
3954 (message "Cannot write backup file; backing up in %s" 3980 (message "Cannot write backup file; backing up in %s"
3955 backupname) 3981 backupname)
3956 (sleep-for 1) 3982 (sleep-for 1)
3957 (backup-buffer-copy real-file-name backupname modes context))) 3983 (backup-buffer-copy real-file-name backupname
3984 modes extended-attributes)))
3958 (setq buffer-backed-up t) 3985 (setq buffer-backed-up t)
3959 ;; Now delete the old versions, if desired. 3986 ;; Now delete the old versions, if desired.
3960 (if delete-old-versions 3987 (if delete-old-versions
@@ -3966,7 +3993,7 @@ BACKUPNAME is the backup file name, which is the old file renamed."
3966 setmodes) 3993 setmodes)
3967 (file-error nil)))))) 3994 (file-error nil))))))
3968 3995
3969(defun backup-buffer-copy (from-name to-name modes context) 3996(defun backup-buffer-copy (from-name to-name modes extended-attributes)
3970 (let ((umask (default-file-modes))) 3997 (let ((umask (default-file-modes)))
3971 (unwind-protect 3998 (unwind-protect
3972 (progn 3999 (progn
@@ -3994,8 +4021,8 @@ BACKUPNAME is the backup file name, which is the old file renamed."
3994 (set-default-file-modes umask))) 4021 (set-default-file-modes umask)))
3995 (and modes 4022 (and modes
3996 (set-file-modes to-name (logand modes #o1777))) 4023 (set-file-modes to-name (logand modes #o1777)))
3997 (and context 4024 (and extended-attributes
3998 (set-file-selinux-context to-name context))) 4025 (set-file-extended-attributes to-name extended-attributes)))
3999 4026
4000(defvar file-name-version-regexp 4027(defvar file-name-version-regexp
4001 "\\(?:~\\|\\.~[-[:alnum:]:#@^._]+\\(?:~[[:digit:]]+\\)?~\\)" 4028 "\\(?:~\\|\\.~[-[:alnum:]:#@^._]+\\(?:~[[:digit:]]+\\)?~\\)"
@@ -4593,7 +4620,8 @@ Before and after saving the buffer, this function runs
4593 (condition-case () 4620 (condition-case ()
4594 (progn 4621 (progn
4595 (set-file-modes buffer-file-name (car setmodes)) 4622 (set-file-modes buffer-file-name (car setmodes))
4596 (set-file-selinux-context buffer-file-name (nth 1 setmodes))) 4623 (set-file-extended-attributes buffer-file-name
4624 (nth 1 setmodes)))
4597 (error nil)))) 4625 (error nil))))
4598 ;; If the auto-save file was recent before this command, 4626 ;; If the auto-save file was recent before this command,
4599 ;; delete it now. 4627 ;; delete it now.
@@ -4606,7 +4634,8 @@ Before and after saving the buffer, this function runs
4606;; This does the "real job" of writing a buffer into its visited file 4634;; This does the "real job" of writing a buffer into its visited file
4607;; and making a backup file. This is what is normally done 4635;; and making a backup file. This is what is normally done
4608;; but inhibited if one of write-file-functions returns non-nil. 4636;; but inhibited if one of write-file-functions returns non-nil.
4609;; It returns a value (MODES SELINUXCONTEXT BACKUPNAME), like backup-buffer. 4637;; It returns a value (MODES EXTENDED-ATTRIBUTES BACKUPNAME), like
4638;; backup-buffer.
4610(defun basic-save-buffer-1 () 4639(defun basic-save-buffer-1 ()
4611 (prog1 4640 (prog1
4612 (if save-buffer-coding-system 4641 (if save-buffer-coding-system
@@ -4618,7 +4647,8 @@ Before and after saving the buffer, this function runs
4618 (setq buffer-file-coding-system-explicit 4647 (setq buffer-file-coding-system-explicit
4619 (cons last-coding-system-used nil))))) 4648 (cons last-coding-system-used nil)))))
4620 4649
4621;; This returns a value (MODES SELINUXCONTEXT BACKUPNAME), like backup-buffer. 4650;; This returns a value (MODES EXTENDED-ATTRIBUTES BACKUPNAME), like
4651;; backup-buffer.
4622(defun basic-save-buffer-2 () 4652(defun basic-save-buffer-2 ()
4623 (let (tempsetmodes setmodes) 4653 (let (tempsetmodes setmodes)
4624 (if (not (file-writable-p buffer-file-name)) 4654 (if (not (file-writable-p buffer-file-name))
@@ -4693,7 +4723,7 @@ Before and after saving the buffer, this function runs
4693 (setq setmodes (or setmodes 4723 (setq setmodes (or setmodes
4694 (list (or (file-modes buffer-file-name) 4724 (list (or (file-modes buffer-file-name)
4695 (logand ?\666 umask)) 4725 (logand ?\666 umask))
4696 (file-selinux-context buffer-file-name) 4726 (file-extended-attributes buffer-file-name)
4697 buffer-file-name))) 4727 buffer-file-name)))
4698 ;; We succeeded in writing the temp file, 4728 ;; We succeeded in writing the temp file,
4699 ;; so rename it. 4729 ;; so rename it.
@@ -4705,10 +4735,10 @@ Before and after saving the buffer, this function runs
4705 (cond ((and tempsetmodes (not setmodes)) 4735 (cond ((and tempsetmodes (not setmodes))
4706 ;; Change the mode back, after writing. 4736 ;; Change the mode back, after writing.
4707 (setq setmodes (list (file-modes buffer-file-name) 4737 (setq setmodes (list (file-modes buffer-file-name)
4708 (file-selinux-context buffer-file-name) 4738 (file-extended-attributes buffer-file-name)
4709 buffer-file-name)) 4739 buffer-file-name))
4710 (set-file-modes buffer-file-name (logior (car setmodes) 128)) 4740 (set-file-modes buffer-file-name (logior (car setmodes) 128))
4711 (set-file-selinux-context buffer-file-name (nth 1 setmodes))))) 4741 (set-file-extended-attributes buffer-file-name (nth 1 setmodes)))))
4712 (let (success) 4742 (let (success)
4713 (unwind-protect 4743 (unwind-protect
4714 (progn 4744 (progn
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);