Commit 7c3d167f authored by Romain Francoise's avatar Romain Francoise
Browse files

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'.
parent a5e9740d
2012-12-16 Romain Francoise <romain@orebokech.com>
* configure.ac (acl): New option.
(HAVE_POSIX_ACL): Test for POSIX ACL support. This is typically
provided by libacl on GNU/Linux.
2012-12-14 Paul Eggert <eggert@cs.ucla.edu>
Fix permissions bugs with setgid directories etc. (Bug#13125)
......
......@@ -184,6 +184,7 @@ OPTION_DEFAULT_ON([dbus],[don't compile with D-Bus support])
OPTION_DEFAULT_ON([gconf],[don't compile with GConf support])
OPTION_DEFAULT_ON([gsettings],[don't compile with GSettings support])
OPTION_DEFAULT_ON([selinux],[don't compile with SELinux support])
OPTION_DEFAULT_ON([acl],[don't compile with ACL support])
OPTION_DEFAULT_ON([gnutls],[don't use -lgnutls for SSL/TLS support])
OPTION_DEFAULT_ON([inotify],[don't compile with inotify (file-watch) support])
......@@ -2197,6 +2198,23 @@ if test "$ac_cv_func_inotify_init1" = yes; then
AC_DEFINE(HAVE_INOTIFY, 1, [Define to 1 to use inotify.])
fi
dnl POSIX ACL support: provided by libacl on GNU/Linux, by libc on FreeBSD.
HAVE_POSIX_ACL=no
LIBACL_LIBS=
if test "${with_acl}" = "yes"; then
AC_CHECK_LIB([acl], [acl_set_file], HAVE_POSIX_ACL=yes, HAVE_POSIX_ACL=no)
if test "$HAVE_POSIX_ACL" = yes; then
AC_DEFINE(HAVE_POSIX_ACL, 1, [Define to 1 if using POSIX ACL support.])
LIBACL_LIBS=-lacl
else
AC_CHECK_FUNC(acl_set_file, HAVE_POSIX_ACL=yes, HAVE_POSIX_ACL=no)
if test "$HAVE_POSIX_ACL" = yes; then
AC_DEFINE(HAVE_POSIX_ACL, 1, [Define to 1 if using POSIX ACL support.])
fi
fi
fi
AC_SUBST(LIBACL_LIBS)
dnl Do not put whitespace before the #include statements below.
dnl Older compilers (eg sunos4 cc) choke on it.
HAVE_XAW3D=no
......
2012-12-16 Romain Francoise <romain@orebokech.com>
* 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'.
2012-12-14 Paul Eggert <eggert@cs.ucla.edu>
Fix permissions bugs with setgid directories etc. (Bug#13125)
......
......@@ -1352,6 +1352,36 @@ not support SELinux, or if Emacs was not compiled with SELinux
support, then the return value is @code{(nil nil nil nil)}.
@end defun
@cindex access control list
@cindex ACL entries
If Emacs has been compiled with @dfn{ACL} (access control list)
support, you can use the function @code{file-acl} to retrieve a file's
ACL entries. The format is platform-specific; on GNU/Linux and BSD,
Emacs uses the POSIX ACL interface. For the function
@code{set-file-acl}, see @ref{Changing Files}.
@defun file-acl filename
This function returns the ACL entries of the file @var{filename}.
The return value is a string containing the textual representation of
the ACL entries, like the following:
@example
@group
user::rw-
group::r--
group:gnu:rwx
mask::rwx
other::r--
@end group
@end example
If the file does not exist or is inaccessible, or if Emacs was unable to
determine the ACL entries, then the return value is @code{nil}. The
latter can happen for local files if Emacs was not compiled with ACL
support, or for remote files if the file handler returns nil for the
file's ACL entries.
@end defun
@node Locating Files
@subsection How to Locate Files in Standard Places
@cindex locate file in path
......@@ -1541,9 +1571,10 @@ non-@code{nil}, we attempt to copy the user and group ownership of the
file. This works only on some operating systems, and only if you have
the correct permissions to do so.
If the optional argument @var{preserve-selinux} is non-@code{nil}, and
Emacs has been compiled with SELinux support, this function attempts
to copy the file's SELinux context (@pxref{File Attributes}).
If the optional argument @var{preserve-extended-attributes} is
non-@code{nil}, and Emacs has been built with the appropriate support,
this function attempts to copy the file's extended attributes, such as
its SELinux context and ACL entries (@pxref{File Attributes}).
@end deffn
@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
SELinux support.
@end defun
@defun set-file-acl filename acl-string
This function sets the ACL entries of the file @var{filename} to
@var{acl-string}. @xref{File Attributes}, for a brief description of
ACLs. The @var{acl-string} argument should be a string containing the
textual representation of the desired ACL entries.
@end defun
@node File Names
@section File Names
@cindex file names
......
......@@ -22,6 +22,12 @@ so we will look at it and add it to the manual.
* Installation Changes in Emacs 24.4
** Emacs can be compiled with POSIX ACL support.
This happens by default if a suitable support library is found at
build time, like libacl on GNU/Linux. To prevent this, use the
configure option `--without-acl'.
* Startup Changes in Emacs 24.4
* Changes in Emacs 24.4
......@@ -33,6 +39,14 @@ if there is one.
This unfinished feature was introduced by accident in Emacs 23.1;
simply disabling Transient Mark mode does the same thing.
** ACL support has been added.
+++
*** Emacs preserves the ACL entries of files when backing up.
+++
*** New functions `file-acl' and `set-file-acl' get and set the ACL
entries of a file. On GNU/Linux the POSIX ACL interface is used via
libacl.
* Editing Changes in Emacs 24.4
** New commands `toggle-frame-maximized' and `cycle-frame-maximized',
......@@ -149,6 +163,12 @@ special-forms any more.
VAR was bound to nil which was not tremendously useful and just lead to
spurious warnings about an unused var.
** The return value of `backup-buffer' has changed.
The second argument is no longer an SELinux context, instead it is an
alist of extended attributes as returned by the new function
`file-extended-attributes'. The attributes can be applied to another
file using `set-file-extended-attributes'.
* Lisp changes in Emacs 24.4
** Support for filesystem notifications.
......@@ -186,6 +206,10 @@ used in place of the 9th element of `file-attributes'.
** New functions `group-gid' and `group-real-gid'.
** The 6th argument to `copy-file' has been renamed to
`preserve-extended-attributes' as it now handles both SELinux context
and ACL entries.
* Changes in Emacs 24.4 on non-free operating systems
+++
......
2012-12-16 Romain Francoise <romain@orebokech.com>
* 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.
2012-12-16 Timo Myyrä <timo.myyra@gmail.com>
* battery.el (battery-bsd-apm): New function.
......
......@@ -3879,6 +3879,27 @@ Interactively, confirmation is required unless you supply a prefix argument."
;; the one at the old location.
(vc-find-file-hook))
(defun file-extended-attributes (filename)
"Return an alist of extended attributes of file FILENAME.
Extended attributes are platform-specific metadata about the file,
such as SELinux context, list of ACL entries, etc."
`((acl . ,(file-acl filename))
(selinux-context . ,(file-selinux-context filename))))
(defun set-file-extended-attributes (filename attributes)
"Set extended attributes of file FILENAME to ATTRIBUTES.
ATTRIBUTES must be an alist of file attributes as returned by
`file-extended-attributes'."
(dolist (elt attributes)
(let ((attr (car elt))
(val (cdr elt)))
(cond ((eq attr 'acl)
(set-file-acl filename val))
((eq attr 'selinux-context)
(set-file-selinux-context filename val))))))
(defun backup-buffer ()
"Make a backup of the disk file visited by the current buffer, if appropriate.
This 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
no longer accessible under its old name.
The value is non-nil after a backup was made by renaming.
It has the form (MODES SELINUXCONTEXT BACKUPNAME).
It has the form (MODES EXTENDED-ATTRIBUTES BACKUPNAME).
MODES is the result of `file-modes' on the original
file; this means that the caller, after saving the buffer, should change
the modes of the new file to agree with the old modes.
SELINUXCONTEXT is the result of `file-selinux-context' on the original
file; this means that the caller, after saving the buffer, should change
the SELinux context of the new file to agree with the old context.
EXTENDED-ATTRIBUTES is the result of `file-extended-attributes'
on the original file; this means that the caller, after saving
the buffer, should change the extended attributes of the new file
to agree with the old attributes.
BACKUPNAME is the backup file name, which is the old file renamed."
(if (and make-backup-files (not backup-inhibited)
(not buffer-backed-up)
......@@ -3923,7 +3945,8 @@ BACKUPNAME is the backup file name, which is the old file renamed."
(y-or-n-p (format "Delete excess backup versions of %s? "
real-file-name)))))
(modes (file-modes buffer-file-name))
(context (file-selinux-context buffer-file-name)))
(extended-attributes
(file-extended-attributes buffer-file-name)))
;; Actually write the back up file.
(condition-case ()
(if (or file-precious-flag
......@@ -3943,10 +3966,13 @@ BACKUPNAME is the backup file name, which is the old file renamed."
(<= (nth 2 attr) backup-by-copying-when-privileged-mismatch)))
(not (file-ownership-preserved-p
real-file-name t))))))
(backup-buffer-copy real-file-name backupname modes context)
(backup-buffer-copy real-file-name
backupname modes
extended-attributes)
;; rename-file should delete old backup.
(rename-file real-file-name backupname t)
(setq setmodes (list modes context backupname)))
(setq setmodes (list modes extended-attributes
backupname)))
(file-error
;; If trouble writing the backup, write it in
;; .emacs.d/%backup%.
......@@ -3954,7 +3980,8 @@ BACKUPNAME is the backup file name, which is the old file renamed."
(message "Cannot write backup file; backing up in %s"
backupname)
(sleep-for 1)
(backup-buffer-copy real-file-name backupname modes context)))
(backup-buffer-copy real-file-name backupname
modes extended-attributes)))
(setq buffer-backed-up t)
;; Now delete the old versions, if desired.
(if delete-old-versions
......@@ -3966,7 +3993,7 @@ BACKUPNAME is the backup file name, which is the old file renamed."
setmodes)
(file-error nil))))))
(defun backup-buffer-copy (from-name to-name modes context)
(defun backup-buffer-copy (from-name to-name modes extended-attributes)
(let ((umask (default-file-modes)))
(unwind-protect
(progn
......@@ -3994,8 +4021,8 @@ BACKUPNAME is the backup file name, which is the old file renamed."
(set-default-file-modes umask)))
(and modes
(set-file-modes to-name (logand modes #o1777)))
(and context
(set-file-selinux-context to-name context)))
(and extended-attributes
(set-file-extended-attributes to-name extended-attributes)))
(defvar file-name-version-regexp
"\\(?:~\\|\\.~[-[:alnum:]:#@^._]+\\(?:~[[:digit:]]+\\)?~\\)"
......@@ -4593,7 +4620,8 @@ Before and after saving the buffer, this function runs
(condition-case ()
(progn
(set-file-modes buffer-file-name (car setmodes))
(set-file-selinux-context buffer-file-name (nth 1 setmodes)))
(set-file-extended-attributes buffer-file-name
(nth 1 setmodes)))
(error nil))))
;; If the auto-save file was recent before this command,
;; delete it now.
......@@ -4606,7 +4634,8 @@ Before and after saving the buffer, this function runs
;; This does the "real job" of writing a buffer into its visited file
;; and making a backup file. This is what is normally done
;; but inhibited if one of write-file-functions returns non-nil.
;; It returns a value (MODES SELINUXCONTEXT BACKUPNAME), like backup-buffer.
;; It returns a value (MODES EXTENDED-ATTRIBUTES BACKUPNAME), like
;; backup-buffer.
(defun basic-save-buffer-1 ()
(prog1
(if save-buffer-coding-system
......@@ -4618,7 +4647,8 @@ Before and after saving the buffer, this function runs
(setq buffer-file-coding-system-explicit
(cons last-coding-system-used nil)))))
;; This returns a value (MODES SELINUXCONTEXT BACKUPNAME), like backup-buffer.
;; This returns a value (MODES EXTENDED-ATTRIBUTES BACKUPNAME), like
;; backup-buffer.
(defun basic-save-buffer-2 ()
(let (tempsetmodes setmodes)
(if (not (file-writable-p buffer-file-name))
......@@ -4693,7 +4723,7 @@ Before and after saving the buffer, this function runs
(setq setmodes (or setmodes
(list (or (file-modes buffer-file-name)
(logand ?\666 umask))
(file-selinux-context buffer-file-name)
(file-extended-attributes buffer-file-name)
buffer-file-name)))
;; We succeeded in writing the temp file,
;; so rename it.
......@@ -4705,10 +4735,10 @@ Before and after saving the buffer, this function runs
(cond ((and tempsetmodes (not setmodes))
;; Change the mode back, after writing.
(setq setmodes (list (file-modes buffer-file-name)
(file-selinux-context buffer-file-name)
(file-extended-attributes buffer-file-name)
buffer-file-name))
(set-file-modes buffer-file-name (logior (car setmodes) 128))
(set-file-selinux-context buffer-file-name (nth 1 setmodes)))))
(set-file-extended-attributes buffer-file-name (nth 1 setmodes)))))
(let (success)
(unwind-protect
(progn
......
2012-12-16 Romain Francoise <romain@orebokech.com>
* 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.
2012-12-15 Paul Eggert <eggert@cs.ucla.edu>
* fileio.c (internal_delete_file): Use bool for boolean.
......
......@@ -292,6 +292,8 @@ LIBSELINUX_LIBS = @LIBSELINUX_LIBS@
LIBGNUTLS_LIBS = @LIBGNUTLS_LIBS@
LIBGNUTLS_CFLAGS = @LIBGNUTLS_CFLAGS@
LIBACL_LIBS = @LIBACL_LIBS@
LIB_PTHREAD_SIGMASK = @LIB_PTHREAD_SIGMASK@
INTERVALS_H = dispextern.h intervals.h composite.h
......@@ -406,7 +408,7 @@ LIBES = $(LIBS) $(W32_LIBS) $(LIBX_BASE) $(LIBIMAGE) \
$(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) \
$(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \
$(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \
$(LIBGNUTLS_LIBS) $(LIB_PTHREAD) $(LIB_PTHREAD_SIGMASK) \
$(LIBACL_LIBS) $(LIBGNUTLS_LIBS) $(LIB_PTHREAD) $(LIB_PTHREAD_SIGMASK) \
$(LIB_GCC) $(LIB_MATH) $(LIB_STANDARD) $(LIB_GCC)
all: emacs$(EXEEXT) $(OTHER_FILES)
......
......@@ -36,6 +36,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <selinux/context.h>
#endif
#ifdef HAVE_POSIX_ACL
#include <sys/acl.h>
#endif
#include <c-ctype.h>
#include "lisp.h"
......@@ -236,6 +240,8 @@ static Lisp_Object Qset_file_modes;
static Lisp_Object Qset_file_times;
static Lisp_Object Qfile_selinux_context;
static Lisp_Object Qset_file_selinux_context;
static Lisp_Object Qfile_acl;
static Lisp_Object Qset_file_acl;
static Lisp_Object Qfile_newer_than_file_p;
Lisp_Object Qinsert_file_contents;
Lisp_Object Qwrite_region;
......@@ -1895,9 +1901,10 @@ A prefix arg makes KEEP-TIME non-nil.
If PRESERVE-UID-GID is non-nil, we try to transfer the
uid and gid of FILE to NEWNAME.
If PRESERVE-SELINUX-CONTEXT is non-nil and SELinux is enabled
on the system, we copy the SELinux context of FILE to NEWNAME. */)
(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)
If PRESERVE-EXTENDED-ATTRIBUTES is non-nil, we try to copy additional
attributes of FILE to NEWNAME, such as its SELinux context and ACL
entries (depending on how Emacs was built). */)
(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)
{
int ifd, ofd;
int n;
......@@ -1911,6 +1918,9 @@ on the system, we copy the SELinux context of FILE to NEWNAME. */)
security_context_t con;
int conlength = 0;
#endif
#ifdef HAVE_POSIX_ACL
acl_t acl = NULL;
#endif
encoded_file = encoded_newname = Qnil;
GCPRO4 (file, newname, encoded_file, encoded_newname);
......@@ -1933,7 +1943,7 @@ on the system, we copy the SELinux context of FILE to NEWNAME. */)
if (!NILP (handler))
RETURN_UNGCPRO (call7 (handler, Qcopy_file, file, newname,
ok_if_already_exists, keep_time, preserve_uid_gid,
preserve_selinux_context));
preserve_extended_attributes));
encoded_file = ENCODE_FILE (file);
encoded_newname = ENCODE_FILE (newname);
......@@ -1986,14 +1996,23 @@ on the system, we copy the SELinux context of FILE to NEWNAME. */)
if (fstat (ifd, &st) != 0)
report_file_error ("Input file status", Fcons (file, Qnil));
#if HAVE_LIBSELINUX
if (!NILP (preserve_selinux_context) && is_selinux_enabled ())
if (!NILP (preserve_extended_attributes))
{
conlength = fgetfilecon (ifd, &con);
if (conlength == -1)
report_file_error ("Doing fgetfilecon", Fcons (file, Qnil));
}
#if HAVE_LIBSELINUX
if (is_selinux_enabled ())
{
conlength = fgetfilecon (ifd, &con);
if (conlength == -1)
report_file_error ("Doing fgetfilecon", Fcons (file, Qnil));
}
#endif
#ifdef HAVE_POSIX_ACL
acl = acl_get_fd (ifd);
if (acl == NULL && errno != ENOTSUP)
report_file_error ("Getting ACL", Fcons (file, Qnil));
#endif
}
if (out_st.st_mode != 0
&& 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. */)
}
#endif
#ifdef HAVE_POSIX_ACL
if (acl != NULL)
{
bool fail = acl_set_fd (ofd, acl) != 0;
if (fail && errno != ENOTSUP)
report_file_error ("Setting ACL", Fcons (newname, Qnil));
acl_free (acl);
}
#endif
if (!NILP (keep_time))
{
EMACS_TIME atime = get_stat_atime (&st);
......@@ -2961,6 +2991,106 @@ compiled with SELinux support. */)
return Qnil;
}
DEFUN ("file-acl", Ffile_acl, Sfile_acl, 1, 1, 0,
doc: /* Return ACL entries of file named FILENAME, as a string.
Return nil if file does not exist or is not accessible, or if Emacs
was unable to determine the ACL entries. The latter can happen for
local files if Emacs was not compiled with ACL support, or for remote
files if the file handler returns nil for the file's ACL entries. */)
(Lisp_Object filename)
{
Lisp_Object absname;
Lisp_Object handler;
#ifdef HAVE_POSIX_ACL
acl_t acl;
Lisp_Object acl_string;
char *str;
#endif
absname = expand_and_dir_to_file (filename,
BVAR (current_buffer, directory));
/* If the file name has special constructs in it,
call the corresponding file handler. */
handler = Ffind_file_name_handler (absname, Qfile_acl);
if (!NILP (handler))
return call2 (handler, Qfile_acl, absname);
#ifdef HAVE_POSIX_ACL
absname = ENCODE_FILE (absname);
acl = acl_get_file (SSDATA (absname), ACL_TYPE_ACCESS);
if (acl == NULL)
return Qnil;
str = acl_to_text (acl, NULL);
if (str == NULL)
{
acl_free (acl);
return Qnil;
}
acl_string = build_string (str);
acl_free (str);
acl_free (acl);
return acl_string;
#endif
return Qnil;
}
DEFUN ("set-file-acl", Fset_file_acl, Sset_file_acl,
2, 2, 0,
doc: /* Set ACL of file named FILENAME to ACL-STRING.
ACL-STRING should contain the textual representation of the ACL
entries in a format suitable for the platform.
Setting ACL for local files requires Emacs to be built with ACL
support. */)
(Lisp_Object filename, Lisp_Object acl_string)
{
Lisp_Object absname;
Lisp_Object handler;
#ifdef HAVE_POSIX_ACL
Lisp_Object encoded_absname;
acl_t acl;
bool fail;
#endif
absname = Fexpand_file_name (filename, BVAR (current_buffer, directory));
/* If the file name has special constructs in it,
call the corresponding file handler. */
handler = Ffind_file_name_handler (absname, Qset_file_acl);
if (!NILP (handler))
return call3 (handler, Qset_file_acl, absname, acl_string);
#ifdef HAVE_POSIX_ACL
if (STRINGP (acl_string))
{
acl = acl_from_text (SSDATA (acl_string));
if (acl == NULL)
{
report_file_error ("Converting ACL", Fcons (absname, Qnil));
return Qnil;
}
encoded_absname = ENCODE_FILE (absname);
fail = (acl_set_file (SSDATA (encoded_absname), ACL_TYPE_ACCESS,
acl)
!= 0);
if (fail && errno != ENOTSUP)
report_file_error ("Setting ACL", Fcons (absname, Qnil));
acl_free (acl);
}
#endif
return Qnil;
}
DEFUN ("file-modes", Ffile_modes, Sfile_modes, 1, 1, 0,
doc: /* Return mode bits of file named FILENAME, as an integer.
Return nil, if file does not exist or is not accessible. */)
......@@ -5630,6 +5760,8 @@ syms_of_fileio (void)
DEFSYM (Qset_file_times, "set-file-times");
DEFSYM (Qfile_selinux_context, "file-selinux-context");
DEFSYM (Qset_file_selinux_context, "set-file-selinux-context");
DEFSYM (Qfile_acl, "file-acl");
DEFSYM (Qset_file_acl, "set-file-acl");
DEFSYM (Qfile_newer_than_file_p, "file-newer-than-file-p");
DEFSYM (Qinsert_file_contents, "insert-file-contents");
DEFSYM (Qwrite_region, "write-region");
......@@ -5849,6 +5981,8 @@ This includes interactive calls to `delete-file' and
defsubr (&Sset_file_modes);
defsubr (&Sset_file_times);
defsubr (&Sfile_selinux_context);
defsubr (&Sfile_acl);
defsubr (&Sset_file_acl);
defsubr (&Sset_file_selinux_context);
defsubr (&Sset_default_file_modes);
defsubr (&Sdefault_file_modes);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment