1 /* Copy POSIX 1003.1e draft 17 (abandoned) ACLs between files. */
3 /* Copyright (C) 2002 Andreas Gruenbacher <agruen@suse.de>, SuSE Linux AG.
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #if defined (HAVE_CONFIG_H)
23 #if defined(HAVE_LIBACL_LIBACL_H)
27 #include <sys/types.h>
33 #if defined(HAVE_SYS_ACL_H)
37 #if defined(HAVE_ACL_LIBACL_H)
38 #include <acl/libacl.h>
41 #define ERROR_CONTEXT_MACROS
42 #ifdef HAVE_ATTR_ERROR_CONTEXT_H
43 #include <attr/error_context.h>
45 #include "error_context.h"
52 #if !defined(HAVE_ACL_FREE)
61 #if !defined(HAVE_ACL_ENTRIES)
63 acl_entries(acl_t acl)
65 # if defined(HAVE_ACL_GET_ENTRY)
66 /* POSIX 1003.1e draft 17 (abandoned) compatible version. */
70 int entries = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry);
72 while (acl_get_entry(acl, ACL_NEXT_ENTRY, &entry) > 0)
82 #if !defined(HAVE_ACL_FROM_MODE) && defined(HAVE_ACL_FROM_TEXT)
83 # define HAVE_ACL_FROM_MODE
85 acl_from_mode(mode_t mode)
87 char acl_text[] = "u::---,g::---,o::---";
90 if (mode & S_IRUSR) acl_text[ 3] = 'r';
91 if (mode & S_IWUSR) acl_text[ 4] = 'w';
92 if (mode & S_IXUSR) acl_text[ 5] = 'x';
93 if (mode & S_IRGRP) acl_text[10] = 'r';
94 if (mode & S_IWGRP) acl_text[11] = 'w';
95 if (mode & S_IXGRP) acl_text[12] = 'x';
96 if (mode & S_IROTH) acl_text[17] = 'r';
97 if (mode & S_IWOTH) acl_text[18] = 'w';
98 if (mode & S_IXOTH) acl_text[19] = 'x';
100 return acl_from_text (acl_text);
104 /* Set the access control list of path to the permissions defined by mode. */
106 set_acl_fd (char const *path, int fd, mode_t mode, struct error_context *ctx)
109 #if defined(HAVE_ACL_FROM_MODE) && defined(HAVE_ACL_SET_FD)
110 /* POSIX 1003.1e draft 17 (abandoned) specific version. */
111 acl_t acl = acl_from_mode (mode);
117 if (acl_set_fd (fd, acl) != 0) {
119 if (errno == ENOTSUP || errno == ENOSYS) {
120 (void) acl_free (acl);
123 const char *qpath = quote (ctx, path);
124 error (ctx, _("setting permissions for %s"), qpath);
125 quote_free (ctx, qpath);
128 (void) acl_free (acl);
133 ret = fchmod (fd, mode);
135 const char *qpath = quote (ctx, path);
136 error (ctx, _("setting permissions for %s"), qpath);
137 quote_free (ctx, qpath);
142 /* Copy the permissions of src_path to dst_path. This includes the
143 file mode permission bits and ACLs. File ownership is not copied.
146 perm_copy_fd (const char *src_path, int src_fd,
147 const char *dst_path, int dst_fd,
148 struct error_context *ctx)
150 #if defined(HAVE_ACL_GET_FD) && defined(HAVE_ACL_SET_FD)
156 ret = fstat(src_fd, &st);
158 const char *qpath = quote (ctx, src_path);
159 error (ctx, "%s", qpath);
160 quote_free (ctx, qpath);
163 #if defined(HAVE_ACL_GET_FD) && defined(HAVE_ACL_SET_FD)
164 /* POSIX 1003.1e draft 17 (abandoned) specific version. */
165 acl = acl_get_fd (src_fd);
168 if (errno == ENOSYS || errno == ENOTSUP)
169 ret = set_acl_fd (dst_path, dst_fd, st.st_mode, ctx);
171 const char *qpath = quote (ctx, src_path);
172 error (ctx, "%s", qpath);
173 quote_free (ctx, qpath);
178 if (acl_set_fd (dst_fd, acl) != 0) {
179 int saved_errno = errno;
180 __apply_mask_to_mode(&st.st_mode, acl);
181 ret = fchmod (dst_fd, st.st_mode);
182 if ((errno != ENOSYS && errno != ENOTSUP) ||
183 acl_entries (acl) != 3) {
184 const char *qpath = quote (ctx, dst_path);
186 error (ctx, _("preserving permissions for %s"), qpath);
187 quote_free (ctx, qpath);
191 (void) acl_free (acl);
194 /* POSIX.1 version. */
195 ret = fchmod (dst_fd, st.st_mode);
197 const char *qpath = quote (ctx, dst_path);
198 error (ctx, _("setting permissions for %s"), qpath);
199 quote_free (ctx, qpath);