1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21: #include <config.h>
22:
23: #include "acl.h"
24:
25: #include "acl-internal.h"
26:
27:
28:
29:
30:
31:
32: int
33: chmod_or_fchmod (const char *name, int desc, mode_t mode)
34: {
35: if (HAVE_FCHMOD && desc != -1)
36: return fchmod (desc, mode);
37: else
38: return chmod (name, mode);
39: }
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50: int
51: copy_acl (const char *src_name, int source_desc, const char *dst_name,
52: int dest_desc, mode_t mode)
53: {
54: int ret;
55:
56: #if USE_ACL && HAVE_ACL_GET_FILE && HAVE_ACL_SET_FILE && HAVE_ACL_FREE
57:
58:
59: acl_t acl;
60: if (HAVE_ACL_GET_FD && source_desc != -1)
61: acl = acl_get_fd (source_desc);
62: else
63: acl = acl_get_file (src_name, ACL_TYPE_ACCESS);
64: if (acl == NULL)
65: {
66: if (ACL_NOT_WELL_SUPPORTED (errno))
67: return set_acl (dst_name, dest_desc, mode);
68: else
69: {
70: error (0, errno, "%s", quote (src_name));
71: return -1;
72: }
73: }
74:
75: if (HAVE_ACL_SET_FD && dest_desc != -1)
76: ret = acl_set_fd (dest_desc, acl);
77: else
78: ret = acl_set_file (dst_name, ACL_TYPE_ACCESS, acl);
79: if (ret != 0)
80: {
81: int saved_errno = errno;
82:
83: if (ACL_NOT_WELL_SUPPORTED (errno))
84: {
85: int n = acl_entries (acl);
86:
87: acl_free (acl);
88: if (n == 3)
89: {
90: if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0)
91: saved_errno = errno;
92: else
93: return 0;
94: }
95: else
96: chmod_or_fchmod (dst_name, dest_desc, mode);
97: }
98: else
99: {
100: acl_free (acl);
101: chmod_or_fchmod (dst_name, dest_desc, mode);
102: }
103: error (0, saved_errno, _("preserving permissions for %s"),
104: quote (dst_name));
105: return -1;
106: }
107: else
108: acl_free (acl);
109:
110: if (mode & (S_ISUID | S_ISGID | S_ISVTX))
111: {
112:
113:
114:
115: if (chmod_or_fchmod (dst_name, dest_desc, mode) != 0)
116: {
117: error (0, errno, _("preserving permissions for %s"),
118: quote (dst_name));
119: return -1;
120: }
121: }
122:
123: if (S_ISDIR (mode))
124: {
125: acl = acl_get_file (src_name, ACL_TYPE_DEFAULT);
126: if (acl == NULL)
127: {
128: error (0, errno, "%s", quote (src_name));
129: return -1;
130: }
131:
132: if (acl_set_file (dst_name, ACL_TYPE_DEFAULT, acl))
133: {
134: error (0, errno, _("preserving permissions for %s"),
135: quote (dst_name));
136: acl_free (acl);
137: return -1;
138: }
139: else
140: acl_free (acl);
141: }
142: return 0;
143: #else
144: ret = chmod_or_fchmod (dst_name, dest_desc, mode);
145: if (ret != 0)
146: error (0, errno, _("preserving permissions for %s"), quote (dst_name));
147: return ret;
148: #endif
149: }
150:
151:
152:
153:
154:
155:
156:
157:
158:
159: int
160: set_acl (char const *name, int desc, mode_t mode)
161: {
162: #if USE_ACL && HAVE_ACL_SET_FILE && HAVE_ACL_FREE
163:
164:
165:
166:
167:
168:
169:
170: # ifndef HAVE_ACL_FROM_TEXT
171: # error Must have acl_from_text (see POSIX 1003.1e draft 17).
172: # endif
173: # ifndef HAVE_ACL_DELETE_DEF_FILE
174: # error Must have acl_delete_def_file (see POSIX 1003.1e draft 17).
175: # endif
176:
177: acl_t acl;
178: int ret;
179:
180: if (HAVE_ACL_FROM_MODE)
181: {
182: acl = acl_from_mode (mode);
183: if (!acl)
184: {
185: error (0, errno, "%s", quote (name));
186: return -1;
187: }
188: }
189: else
190: {
191: char acl_text[] = "u::---,g::---,o::---";
192:
193: if (mode & S_IRUSR) acl_text[ 3] = 'r';
194: if (mode & S_IWUSR) acl_text[ 4] = 'w';
195: if (mode & S_IXUSR) acl_text[ 5] = 'x';
196: if (mode & S_IRGRP) acl_text[10] = 'r';
197: if (mode & S_IWGRP) acl_text[11] = 'w';
198: if (mode & S_IXGRP) acl_text[12] = 'x';
199: if (mode & S_IROTH) acl_text[17] = 'r';
200: if (mode & S_IWOTH) acl_text[18] = 'w';
201: if (mode & S_IXOTH) acl_text[19] = 'x';
202:
203: acl = acl_from_text (acl_text);
204: if (!acl)
205: {
206: error (0, errno, "%s", quote (name));
207: return -1;
208: }
209: }
210: if (HAVE_ACL_SET_FD && desc != -1)
211: ret = acl_set_fd (desc, acl);
212: else
213: ret = acl_set_file (name, ACL_TYPE_ACCESS, acl);
214: if (ret != 0)
215: {
216: int saved_errno = errno;
217: acl_free (acl);
218:
219: if (ACL_NOT_WELL_SUPPORTED (errno))
220: {
221: if (chmod_or_fchmod (name, desc, mode) != 0)
222: saved_errno = errno;
223: else
224: return 0;
225: }
226: error (0, saved_errno, _("setting permissions for %s"), quote (name));
227: return -1;
228: }
229: else
230: acl_free (acl);
231:
232: if (S_ISDIR (mode) && acl_delete_def_file (name))
233: {
234: error (0, errno, _("setting permissions for %s"), quote (name));
235: return -1;
236: }
237:
238: if (mode & (S_ISUID | S_ISGID | S_ISVTX))
239: {
240:
241:
242:
243: if (chmod_or_fchmod (name, desc, mode))
244: {
245: error (0, errno, _("preserving permissions for %s"), quote (name));
246: return -1;
247: }
248: }
249: return 0;
250: #else
251: int ret = chmod_or_fchmod (name, desc, mode);
252: if (ret)
253: error (0, errno, _("setting permissions for %s"), quote (name));
254: return ret;
255: #endif
256: }