]>
Commit | Line | Data |
---|---|---|
ab2dbccc | 1 | /* sec_acl.cc: Sun compatible ACL functions. |
c0d1968a | 2 | |
bc837d22 CF |
3 | Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, |
4 | 2011, 2012 Red Hat, Inc. | |
c0d1968a CV |
5 | |
6 | Written by Corinna Vinschen <corinna@vinschen.de> | |
7 | ||
8 | This file is part of Cygwin. | |
9 | ||
10 | This software is a copyrighted work licensed under the terms of the | |
11 | Cygwin license. Please consult the file "CYGWIN_LICENSE" for | |
12 | details. */ | |
13 | ||
14 | #include "winsup.h" | |
c0d1968a | 15 | #include <stdlib.h> |
c0d1968a CV |
16 | #include <sys/acl.h> |
17 | #include <ctype.h> | |
c0d1968a | 18 | #include "cygerrno.h" |
6b91b8d5 | 19 | #include "security.h" |
c0d1968a | 20 | #include "path.h" |
7ac61736 | 21 | #include "fhandler.h" |
c0d1968a | 22 | #include "dtable.h" |
c0d1968a | 23 | #include "cygheap.h" |
1754539e | 24 | #include "ntdll.h" |
d6ffc075 | 25 | #include "pwdgrp.h" |
4e8f539f | 26 | #include "tls_pbuf.h" |
c0d1968a CV |
27 | |
28 | static int | |
62cd433e | 29 | searchace (__aclent32_t *aclp, int nentries, int type, __uid32_t id = ILLEGAL_UID) |
c0d1968a CV |
30 | { |
31 | int i; | |
32 | ||
33 | for (i = 0; i < nentries; ++i) | |
62cd433e | 34 | if ((aclp[i].a_type == type && (id == ILLEGAL_UID || aclp[i].a_id == id)) |
c0d1968a CV |
35 | || !aclp[i].a_type) |
36 | return i; | |
37 | return -1; | |
38 | } | |
39 | ||
e3d1d515 | 40 | int |
eea4e482 | 41 | setacl (HANDLE handle, path_conv &pc, int nentries, __aclent32_t *aclbufp, |
6bcc8fd7 | 42 | bool &writable) |
c0d1968a | 43 | { |
12069cf3 | 44 | security_descriptor sd_ret; |
4e8f539f | 45 | tmp_pathbuf tp; |
c0d1968a | 46 | |
67a93078 | 47 | if (get_file_sd (handle, pc, sd_ret, false)) |
eea4e482 | 48 | return -1; |
c0d1968a | 49 | |
1838d97b CV |
50 | NTSTATUS status; |
51 | BOOLEAN dummy; | |
c0d1968a CV |
52 | |
53 | /* Get owner SID. */ | |
62cd433e | 54 | PSID owner_sid; |
1838d97b CV |
55 | status = RtlGetOwnerSecurityDescriptor (sd_ret, &owner_sid, &dummy); |
56 | if (!NT_SUCCESS (status)) | |
c0d1968a | 57 | { |
1838d97b | 58 | __seterrno_from_nt_status (status); |
c0d1968a CV |
59 | return -1; |
60 | } | |
d551169a | 61 | cygsid owner (owner_sid); |
c0d1968a CV |
62 | |
63 | /* Get group SID. */ | |
62cd433e | 64 | PSID group_sid; |
1838d97b CV |
65 | status = RtlGetGroupSecurityDescriptor (sd_ret, &group_sid, &dummy); |
66 | if (!NT_SUCCESS (status)) | |
c0d1968a | 67 | { |
1838d97b | 68 | __seterrno_from_nt_status (status); |
c0d1968a CV |
69 | return -1; |
70 | } | |
d551169a | 71 | cygsid group (group_sid); |
c0d1968a CV |
72 | |
73 | /* Initialize local security descriptor. */ | |
74 | SECURITY_DESCRIPTOR sd; | |
1754539e | 75 | RtlCreateSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION); |
fd04c2f0 CV |
76 | status = RtlSetOwnerSecurityDescriptor (&sd, owner, FALSE); |
77 | if (!NT_SUCCESS (status)) | |
c0d1968a | 78 | { |
fd04c2f0 | 79 | __seterrno_from_nt_status (status); |
c0d1968a CV |
80 | return -1; |
81 | } | |
fd04c2f0 CV |
82 | status = RtlSetGroupSecurityDescriptor (&sd, group, FALSE); |
83 | if (!NT_SUCCESS (status)) | |
c0d1968a | 84 | { |
fd04c2f0 | 85 | __seterrno_from_nt_status (status); |
c0d1968a CV |
86 | return -1; |
87 | } | |
88 | ||
89 | /* Fill access control list. */ | |
4e8f539f | 90 | PACL acl = (PACL) tp.w_get (); |
c0d1968a CV |
91 | size_t acl_len = sizeof (ACL); |
92 | int ace_off = 0; | |
93 | ||
d551169a | 94 | cygsid sid; |
c0d1968a | 95 | struct passwd *pw; |
57196405 | 96 | struct __group32 *gr; |
c0d1968a CV |
97 | int pos; |
98 | ||
1754539e | 99 | RtlCreateAcl (acl, ACL_MAXIMUM_SIZE, ACL_REVISION); |
6bcc8fd7 CV |
100 | |
101 | writable = false; | |
102 | ||
c0d1968a CV |
103 | for (int i = 0; i < nentries; ++i) |
104 | { | |
62cd433e CV |
105 | DWORD allow; |
106 | /* Owner has more standard rights set. */ | |
107 | if ((aclbufp[i].a_type & ~ACL_DEFAULT) == USER_OBJ) | |
5f9ca0d2 CV |
108 | allow = STANDARD_RIGHTS_ALL |
109 | | (pc.fs_is_samba () | |
110 | ? 0 : (FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES)); | |
62cd433e | 111 | else |
5f9ca0d2 CV |
112 | allow = STANDARD_RIGHTS_READ |
113 | | (pc.fs_is_samba () ? 0 : FILE_READ_ATTRIBUTES); | |
c0d1968a CV |
114 | if (aclbufp[i].a_perm & S_IROTH) |
115 | allow |= FILE_GENERIC_READ; | |
116 | if (aclbufp[i].a_perm & S_IWOTH) | |
6bcc8fd7 | 117 | { |
5f9ca0d2 | 118 | allow |= FILE_GENERIC_WRITE; |
6bcc8fd7 CV |
119 | writable = true; |
120 | } | |
c0d1968a | 121 | if (aclbufp[i].a_perm & S_IXOTH) |
5f9ca0d2 | 122 | allow |= FILE_GENERIC_EXECUTE & ~FILE_READ_ATTRIBUTES; |
3a157c0d | 123 | if ((aclbufp[i].a_perm & (S_IWOTH | S_IXOTH)) == (S_IWOTH | S_IXOTH)) |
1ff9f4b9 | 124 | allow |= FILE_DELETE_CHILD; |
c0d1968a CV |
125 | /* Set inherit property. */ |
126 | DWORD inheritance = (aclbufp[i].a_type & ACL_DEFAULT) | |
b42441d3 CV |
127 | ? (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE |
128 | | INHERIT_ONLY_ACE) | |
654bad37 | 129 | : NO_INHERITANCE; |
c0d1968a CV |
130 | /* |
131 | * If a specific acl contains a corresponding default entry with | |
132 | * identical permissions, only one Windows ACE with proper | |
133 | * inheritance bits is created. | |
134 | */ | |
135 | if (!(aclbufp[i].a_type & ACL_DEFAULT) | |
ab2dbccc | 136 | && aclbufp[i].a_type & (USER|GROUP|OTHER_OBJ) |
9a751621 | 137 | && (pos = searchace (aclbufp + i + 1, nentries - i - 1, |
c0d1968a CV |
138 | aclbufp[i].a_type | ACL_DEFAULT, |
139 | (aclbufp[i].a_type & (USER|GROUP)) | |
62cd433e | 140 | ? aclbufp[i].a_id : ILLEGAL_UID)) >= 0 |
bb090650 | 141 | && aclbufp[i].a_perm == aclbufp[i + 1 + pos].a_perm) |
c0d1968a | 142 | { |
b42441d3 | 143 | inheritance = CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE; |
9a751621 | 144 | /* This invalidates the corresponding default entry. */ |
bb090650 | 145 | aclbufp[i + 1 + pos].a_type = USER|GROUP|ACL_DEFAULT; |
c0d1968a CV |
146 | } |
147 | switch (aclbufp[i].a_type) | |
148 | { | |
149 | case USER_OBJ: | |
c0d1968a | 150 | if (!add_access_allowed_ace (acl, ace_off++, allow, |
d551169a | 151 | owner, acl_len, inheritance)) |
c0d1968a CV |
152 | return -1; |
153 | break; | |
ab2dbccc | 154 | case DEF_USER_OBJ: |
ab2dbccc CV |
155 | if (!add_access_allowed_ace (acl, ace_off++, allow, |
156 | well_known_creator_owner_sid, acl_len, inheritance)) | |
157 | return -1; | |
158 | break; | |
c0d1968a CV |
159 | case USER: |
160 | case DEF_USER: | |
d6ffc075 | 161 | if (!(pw = internal_getpwuid (aclbufp[i].a_id)) |
c1410a8d CV |
162 | || !sid.getfrompw (pw)) |
163 | { | |
164 | set_errno (EINVAL); | |
165 | return -1; | |
166 | } | |
167 | if (!add_access_allowed_ace (acl, ace_off++, allow, | |
168 | sid, acl_len, inheritance)) | |
c0d1968a CV |
169 | return -1; |
170 | break; | |
171 | case GROUP_OBJ: | |
c0d1968a | 172 | if (!add_access_allowed_ace (acl, ace_off++, allow, |
62cd433e | 173 | group, acl_len, inheritance)) |
c0d1968a CV |
174 | return -1; |
175 | break; | |
ab2dbccc CV |
176 | case DEF_GROUP_OBJ: |
177 | if (!add_access_allowed_ace (acl, ace_off++, allow, | |
178 | well_known_creator_group_sid, acl_len, inheritance)) | |
179 | return -1; | |
180 | break; | |
c0d1968a CV |
181 | case GROUP: |
182 | case DEF_GROUP: | |
d6ffc075 | 183 | if (!(gr = internal_getgrgid (aclbufp[i].a_id)) |
c1410a8d CV |
184 | || !sid.getfromgr (gr)) |
185 | { | |
186 | set_errno (EINVAL); | |
187 | return -1; | |
188 | } | |
189 | if (!add_access_allowed_ace (acl, ace_off++, allow, | |
190 | sid, acl_len, inheritance)) | |
c0d1968a CV |
191 | return -1; |
192 | break; | |
193 | case OTHER_OBJ: | |
194 | case DEF_OTHER_OBJ: | |
195 | if (!add_access_allowed_ace (acl, ace_off++, allow, | |
2b0a111f CV |
196 | well_known_world_sid, |
197 | acl_len, inheritance)) | |
c0d1968a CV |
198 | return -1; |
199 | break; | |
200 | } | |
201 | } | |
202 | /* Set AclSize to computed value. */ | |
203 | acl->AclSize = acl_len; | |
204 | debug_printf ("ACL-Size: %d", acl_len); | |
205 | /* Create DACL for local security descriptor. */ | |
fd04c2f0 CV |
206 | status = RtlSetDaclSecurityDescriptor (&sd, TRUE, acl, FALSE); |
207 | if (!NT_SUCCESS (status)) | |
c0d1968a | 208 | { |
fd04c2f0 | 209 | __seterrno_from_nt_status (status); |
c0d1968a CV |
210 | return -1; |
211 | } | |
12069cf3 CV |
212 | /* Make self relative security descriptor in sd_ret. */ |
213 | DWORD sd_size = 0; | |
5735d5f6 | 214 | RtlAbsoluteToSelfRelativeSD (&sd, sd_ret, &sd_size); |
c0d1968a CV |
215 | if (sd_size <= 0) |
216 | { | |
217 | __seterrno (); | |
218 | return -1; | |
219 | } | |
fb69e3ed CV |
220 | if (!sd_ret.realloc (sd_size)) |
221 | { | |
222 | set_errno (ENOMEM); | |
223 | return -1; | |
224 | } | |
5735d5f6 CV |
225 | status = RtlAbsoluteToSelfRelativeSD (&sd, sd_ret, &sd_size); |
226 | if (!NT_SUCCESS (status)) | |
c0d1968a | 227 | { |
5735d5f6 | 228 | __seterrno_from_nt_status (status); |
c0d1968a CV |
229 | return -1; |
230 | } | |
12069cf3 | 231 | debug_printf ("Created SD-Size: %d", sd_ret.size ()); |
2d647173 | 232 | return set_file_sd (handle, pc, sd_ret, false); |
c0d1968a CV |
233 | } |
234 | ||
19f20901 CV |
235 | /* Temporary access denied bits */ |
236 | #define DENY_R 040000 | |
237 | #define DENY_W 020000 | |
238 | #define DENY_X 010000 | |
239 | ||
c0d1968a | 240 | static void |
62cd433e | 241 | getace (__aclent32_t &acl, int type, int id, DWORD win_ace_mask, |
9a751621 | 242 | DWORD win_ace_type) |
c0d1968a CV |
243 | { |
244 | acl.a_type = type; | |
245 | acl.a_id = id; | |
246 | ||
3db69078 | 247 | if ((win_ace_mask & FILE_READ_BITS) && !(acl.a_perm & (S_IROTH | DENY_R))) |
7b9e380f CF |
248 | { |
249 | if (win_ace_type == ACCESS_ALLOWED_ACE_TYPE) | |
250 | acl.a_perm |= S_IROTH; | |
251 | else if (win_ace_type == ACCESS_DENIED_ACE_TYPE) | |
252 | acl.a_perm |= DENY_R; | |
253 | } | |
c0d1968a | 254 | |
3db69078 | 255 | if ((win_ace_mask & FILE_WRITE_BITS) && !(acl.a_perm & (S_IWOTH | DENY_W))) |
7b9e380f CF |
256 | { |
257 | if (win_ace_type == ACCESS_ALLOWED_ACE_TYPE) | |
258 | acl.a_perm |= S_IWOTH; | |
259 | else if (win_ace_type == ACCESS_DENIED_ACE_TYPE) | |
260 | acl.a_perm |= DENY_W; | |
261 | } | |
c0d1968a | 262 | |
3db69078 | 263 | if ((win_ace_mask & FILE_EXEC_BITS) && !(acl.a_perm & (S_IXOTH | DENY_X))) |
7b9e380f CF |
264 | { |
265 | if (win_ace_type == ACCESS_ALLOWED_ACE_TYPE) | |
266 | acl.a_perm |= S_IXOTH; | |
267 | else if (win_ace_type == ACCESS_DENIED_ACE_TYPE) | |
268 | acl.a_perm |= DENY_X; | |
269 | } | |
c0d1968a CV |
270 | } |
271 | ||
e3d1d515 | 272 | int |
eea4e482 | 273 | getacl (HANDLE handle, path_conv &pc, int nentries, __aclent32_t *aclbufp) |
c0d1968a | 274 | { |
12069cf3 | 275 | security_descriptor sd; |
c0d1968a | 276 | |
67a93078 | 277 | if (get_file_sd (handle, pc, sd, false)) |
eea4e482 | 278 | return -1; |
c0d1968a | 279 | |
62cd433e CV |
280 | cygpsid owner_sid; |
281 | cygpsid group_sid; | |
1838d97b CV |
282 | NTSTATUS status; |
283 | BOOLEAN dummy; | |
a8d7ae61 | 284 | __uid32_t uid; |
57196405 | 285 | __gid32_t gid; |
c0d1968a | 286 | |
1838d97b CV |
287 | status = RtlGetOwnerSecurityDescriptor (sd, (PSID *) &owner_sid, &dummy); |
288 | if (!NT_SUCCESS (status)) | |
c0d1968a | 289 | { |
1838d97b | 290 | __seterrno_from_nt_status (status); |
c0d1968a CV |
291 | return -1; |
292 | } | |
62cd433e | 293 | uid = owner_sid.get_uid (); |
c0d1968a | 294 | |
1838d97b CV |
295 | status = RtlGetGroupSecurityDescriptor (sd, (PSID *) &group_sid, &dummy); |
296 | if (!NT_SUCCESS (status)) | |
c0d1968a | 297 | { |
1838d97b | 298 | __seterrno_from_nt_status (status); |
c0d1968a CV |
299 | return -1; |
300 | } | |
62cd433e | 301 | gid = group_sid.get_gid (); |
c0d1968a | 302 | |
62cd433e CV |
303 | __aclent32_t lacl[MAX_ACL_ENTRIES]; |
304 | memset (&lacl, 0, MAX_ACL_ENTRIES * sizeof (__aclent32_t)); | |
c0d1968a CV |
305 | lacl[0].a_type = USER_OBJ; |
306 | lacl[0].a_id = uid; | |
307 | lacl[1].a_type = GROUP_OBJ; | |
308 | lacl[1].a_id = gid; | |
309 | lacl[2].a_type = OTHER_OBJ; | |
19f20901 CV |
310 | lacl[2].a_id = ILLEGAL_GID; |
311 | lacl[3].a_type = CLASS_OBJ; | |
312 | lacl[3].a_id = ILLEGAL_GID; | |
313 | lacl[3].a_perm = S_IROTH | S_IWOTH | S_IXOTH; | |
c0d1968a CV |
314 | |
315 | PACL acl; | |
1838d97b | 316 | BOOLEAN acl_exists; |
c0d1968a | 317 | |
1838d97b CV |
318 | status = RtlGetDaclSecurityDescriptor (sd, &acl_exists, &acl, &dummy); |
319 | if (!NT_SUCCESS (status)) | |
c0d1968a | 320 | { |
1838d97b | 321 | __seterrno_from_nt_status (status); |
c0d1968a CV |
322 | return -1; |
323 | } | |
324 | ||
19f20901 | 325 | int pos, i, types_def = 0; |
c0d1968a CV |
326 | |
327 | if (!acl_exists || !acl) | |
19f20901 CV |
328 | for (pos = 0; pos < 3; ++pos) /* Don't change CLASS_OBJ entry */ |
329 | lacl[pos].a_perm = S_IROTH | S_IWOTH | S_IXOTH; | |
330 | else | |
c0d1968a | 331 | { |
19f20901 CV |
332 | for (i = 0; i < acl->AceCount; ++i) |
333 | { | |
334 | ACCESS_ALLOWED_ACE *ace; | |
6d147411 | 335 | |
1754539e | 336 | if (!NT_SUCCESS (RtlGetAce (acl, i, (PVOID *) &ace))) |
19f20901 | 337 | continue; |
c0d1968a | 338 | |
62cd433e | 339 | cygpsid ace_sid ((PSID) &ace->SidStart); |
19f20901 CV |
340 | int id; |
341 | int type = 0; | |
c0d1968a | 342 | |
19f20901 CV |
343 | if (ace_sid == well_known_world_sid) |
344 | { | |
345 | type = OTHER_OBJ; | |
346 | id = ILLEGAL_GID; | |
347 | } | |
348 | else if (ace_sid == group_sid) | |
349 | { | |
350 | type = GROUP_OBJ; | |
351 | id = gid; | |
352 | } | |
353 | else if (ace_sid == owner_sid) | |
c0d1968a | 354 | { |
19f20901 CV |
355 | type = USER_OBJ; |
356 | id = uid; | |
357 | } | |
ab2dbccc CV |
358 | else if (ace_sid == well_known_creator_group_sid) |
359 | { | |
360 | type = GROUP_OBJ | ACL_DEFAULT; | |
e445b7c3 | 361 | types_def |= type; |
ab2dbccc CV |
362 | id = ILLEGAL_GID; |
363 | } | |
364 | else if (ace_sid == well_known_creator_owner_sid) | |
365 | { | |
366 | type = USER_OBJ | ACL_DEFAULT; | |
e445b7c3 | 367 | types_def |= type; |
ab2dbccc CV |
368 | id = ILLEGAL_GID; |
369 | } | |
19f20901 | 370 | else |
2e008fb9 | 371 | id = ace_sid.get_id (true, &type); |
62cd433e | 372 | |
19f20901 CV |
373 | if (!type) |
374 | continue; | |
b42441d3 | 375 | if (!(ace->Header.AceFlags & INHERIT_ONLY_ACE || type & ACL_DEFAULT)) |
19f20901 CV |
376 | { |
377 | if ((pos = searchace (lacl, MAX_ACL_ENTRIES, type, id)) >= 0) | |
378 | getace (lacl[pos], type, id, ace->Mask, ace->Header.AceType); | |
379 | } | |
b42441d3 CV |
380 | if ((ace->Header.AceFlags |
381 | & (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE)) | |
eea4e482 | 382 | && pc.isdir ()) |
19f20901 | 383 | { |
ab2dbccc CV |
384 | if (type == USER_OBJ) |
385 | type = USER; | |
386 | else if (type == GROUP_OBJ) | |
387 | type = GROUP; | |
19f20901 CV |
388 | type |= ACL_DEFAULT; |
389 | types_def |= type; | |
390 | if ((pos = searchace (lacl, MAX_ACL_ENTRIES, type, id)) >= 0) | |
391 | getace (lacl[pos], type, id, ace->Mask, ace->Header.AceType); | |
392 | } | |
c0d1968a | 393 | } |
e445b7c3 | 394 | if (types_def && (pos = searchace (lacl, MAX_ACL_ENTRIES, 0)) >= 0) |
c0d1968a | 395 | { |
e445b7c3 CV |
396 | /* Ensure that the default acl contains at |
397 | least DEF_(USER|GROUP|OTHER)_OBJ entries. */ | |
398 | if (!(types_def & USER_OBJ)) | |
399 | { | |
400 | lacl[pos].a_type = DEF_USER_OBJ; | |
401 | lacl[pos].a_id = uid; | |
402 | lacl[pos].a_perm = lacl[0].a_perm; | |
403 | pos++; | |
404 | } | |
405 | if (!(types_def & GROUP_OBJ) && pos < MAX_ACL_ENTRIES) | |
406 | { | |
407 | lacl[pos].a_type = DEF_GROUP_OBJ; | |
408 | lacl[pos].a_id = gid; | |
409 | lacl[pos].a_perm = lacl[1].a_perm; | |
410 | pos++; | |
411 | } | |
412 | if (!(types_def & OTHER_OBJ) && pos < MAX_ACL_ENTRIES) | |
413 | { | |
414 | lacl[pos].a_type = DEF_OTHER_OBJ; | |
415 | lacl[pos].a_id = ILLEGAL_GID; | |
416 | lacl[pos].a_perm = lacl[2].a_perm; | |
417 | pos++; | |
418 | } | |
419 | /* Include DEF_CLASS_OBJ if any named default ace exists. */ | |
420 | if ((types_def & (USER|GROUP)) && pos < MAX_ACL_ENTRIES) | |
421 | { | |
422 | lacl[pos].a_type = DEF_CLASS_OBJ; | |
423 | lacl[pos].a_id = ILLEGAL_GID; | |
424 | lacl[pos].a_perm = S_IROTH | S_IWOTH | S_IXOTH; | |
425 | } | |
c0d1968a CV |
426 | } |
427 | } | |
428 | if ((pos = searchace (lacl, MAX_ACL_ENTRIES, 0)) < 0) | |
429 | pos = MAX_ACL_ENTRIES; | |
19f20901 | 430 | if (aclbufp) { |
62cd433e | 431 | if (owner_sid == group_sid) |
19f20901 CV |
432 | lacl[0].a_perm = lacl[1].a_perm; |
433 | if (pos > nentries) | |
f1da8a06 | 434 | { |
9a751621 | 435 | set_errno (ENOSPC); |
f1da8a06 CV |
436 | return -1; |
437 | } | |
62cd433e | 438 | memcpy (aclbufp, lacl, pos * sizeof (__aclent32_t)); |
19f20901 CV |
439 | for (i = 0; i < pos; ++i) |
440 | aclbufp[i].a_perm &= ~(DENY_R | DENY_W | DENY_X); | |
62cd433e | 441 | aclsort32 (pos, 0, aclbufp); |
19f20901 | 442 | } |
b9aa8149 | 443 | syscall_printf ("%R = getacl(%S)", pos, pc.get_nt_native_path ()); |
c0d1968a CV |
444 | return pos; |
445 | } | |
446 | ||
f7382efe CV |
447 | extern "C" int |
448 | acl32 (const char *path, int cmd, int nentries, __aclent32_t *aclbufp) | |
c0d1968a | 449 | { |
e3d1d515 | 450 | int res = -1; |
f7382efe CV |
451 | |
452 | fhandler_base *fh = build_fh_name (path, PC_SYM_FOLLOW | PC_KEEP_HANDLE, | |
5a0d1edb | 453 | stat_suffixes); |
60ecc3d6 CV |
454 | if (!fh || !fh->exists ()) |
455 | set_errno (ENOENT); | |
456 | else if (fh->error ()) | |
c0d1968a | 457 | { |
e3d1d515 CV |
458 | debug_printf ("got %d error from build_fh_name", fh->error ()); |
459 | set_errno (fh->error ()); | |
c0d1968a | 460 | } |
e3d1d515 CV |
461 | else |
462 | res = fh->facl (cmd, nentries, aclbufp); | |
e84c7766 CV |
463 | |
464 | delete fh; | |
b9aa8149 | 465 | syscall_printf ("%R = acl(%s)", res, path); |
e3d1d515 | 466 | return res; |
c0d1968a CV |
467 | } |
468 | ||
c367dfd0 | 469 | extern "C" int |
62cd433e | 470 | lacl32 (const char *path, int cmd, int nentries, __aclent32_t *aclbufp) |
c0d1968a | 471 | { |
f7382efe CV |
472 | /* This call was an accident. Make it absolutely clear. */ |
473 | set_errno (ENOSYS); | |
474 | return -1; | |
c0d1968a CV |
475 | } |
476 | ||
c367dfd0 | 477 | extern "C" int |
62cd433e | 478 | facl32 (int fd, int cmd, int nentries, __aclent32_t *aclbufp) |
c0d1968a | 479 | { |
df63bd49 CF |
480 | cygheap_fdget cfd (fd); |
481 | if (cfd < 0) | |
c0d1968a CV |
482 | { |
483 | syscall_printf ("-1 = facl (%d)", fd); | |
c0d1968a CV |
484 | return -1; |
485 | } | |
e3d1d515 | 486 | int res = cfd->facl (cmd, nentries, aclbufp); |
b9aa8149 | 487 | syscall_printf ("%R = facl(%s) )", res, cfd->get_name ()); |
e3d1d515 | 488 | return res; |
c0d1968a CV |
489 | } |
490 | ||
c367dfd0 | 491 | extern "C" int |
62cd433e | 492 | aclcheck32 (__aclent32_t *aclbufp, int nentries, int *which) |
c0d1968a | 493 | { |
2e008fb9 CF |
494 | bool has_user_obj = false; |
495 | bool has_group_obj = false; | |
496 | bool has_other_obj = false; | |
497 | bool has_class_obj = false; | |
498 | bool has_ug_objs = false; | |
499 | bool has_def_user_obj = false; | |
500 | bool has_def_group_obj = false; | |
501 | bool has_def_other_obj = false; | |
502 | bool has_def_class_obj = false; | |
503 | bool has_def_ug_objs = false; | |
c0d1968a CV |
504 | int pos2; |
505 | ||
506 | for (int pos = 0; pos < nentries; ++pos) | |
507 | switch (aclbufp[pos].a_type) | |
508 | { | |
509 | case USER_OBJ: | |
510 | if (has_user_obj) | |
511 | { | |
512 | if (which) | |
513 | *which = pos; | |
514 | return USER_ERROR; | |
515 | } | |
2e008fb9 | 516 | has_user_obj = true; |
c0d1968a CV |
517 | break; |
518 | case GROUP_OBJ: | |
519 | if (has_group_obj) | |
520 | { | |
521 | if (which) | |
522 | *which = pos; | |
523 | return GRP_ERROR; | |
524 | } | |
2e008fb9 | 525 | has_group_obj = true; |
c0d1968a CV |
526 | break; |
527 | case OTHER_OBJ: | |
528 | if (has_other_obj) | |
529 | { | |
530 | if (which) | |
531 | *which = pos; | |
532 | return OTHER_ERROR; | |
533 | } | |
2e008fb9 | 534 | has_other_obj = true; |
c0d1968a CV |
535 | break; |
536 | case CLASS_OBJ: | |
537 | if (has_class_obj) | |
538 | { | |
539 | if (which) | |
540 | *which = pos; | |
541 | return CLASS_ERROR; | |
542 | } | |
2e008fb9 | 543 | has_class_obj = true; |
c0d1968a CV |
544 | break; |
545 | case USER: | |
546 | case GROUP: | |
547 | if ((pos2 = searchace (aclbufp + pos + 1, nentries - pos - 1, | |
548 | aclbufp[pos].a_type, aclbufp[pos].a_id)) >= 0) | |
549 | { | |
550 | if (which) | |
551 | *which = pos2; | |
552 | return DUPLICATE_ERROR; | |
553 | } | |
2e008fb9 | 554 | has_ug_objs = true; |
c0d1968a CV |
555 | break; |
556 | case DEF_USER_OBJ: | |
557 | if (has_def_user_obj) | |
558 | { | |
559 | if (which) | |
560 | *which = pos; | |
561 | return USER_ERROR; | |
562 | } | |
2e008fb9 | 563 | has_def_user_obj = true; |
c0d1968a CV |
564 | break; |
565 | case DEF_GROUP_OBJ: | |
566 | if (has_def_group_obj) | |
567 | { | |
568 | if (which) | |
569 | *which = pos; | |
570 | return GRP_ERROR; | |
571 | } | |
2e008fb9 | 572 | has_def_group_obj = true; |
c0d1968a CV |
573 | break; |
574 | case DEF_OTHER_OBJ: | |
575 | if (has_def_other_obj) | |
576 | { | |
577 | if (which) | |
578 | *which = pos; | |
579 | return OTHER_ERROR; | |
580 | } | |
2e008fb9 | 581 | has_def_other_obj = true; |
c0d1968a CV |
582 | break; |
583 | case DEF_CLASS_OBJ: | |
584 | if (has_def_class_obj) | |
585 | { | |
586 | if (which) | |
587 | *which = pos; | |
588 | return CLASS_ERROR; | |
589 | } | |
2e008fb9 | 590 | has_def_class_obj = true; |
c0d1968a CV |
591 | break; |
592 | case DEF_USER: | |
593 | case DEF_GROUP: | |
594 | if ((pos2 = searchace (aclbufp + pos + 1, nentries - pos - 1, | |
595 | aclbufp[pos].a_type, aclbufp[pos].a_id)) >= 0) | |
596 | { | |
597 | if (which) | |
598 | *which = pos2; | |
599 | return DUPLICATE_ERROR; | |
600 | } | |
2e008fb9 | 601 | has_def_ug_objs = true; |
c0d1968a CV |
602 | break; |
603 | default: | |
604 | return ENTRY_ERROR; | |
605 | } | |
606 | if (!has_user_obj | |
607 | || !has_group_obj | |
608 | || !has_other_obj | |
609 | #if 0 | |
610 | /* These checks are not ok yet since CLASS_OBJ isn't fully implemented. */ | |
611 | || (has_ug_objs && !has_class_obj) | |
612 | || (has_def_ug_objs && !has_def_class_obj) | |
613 | #endif | |
614 | ) | |
615 | { | |
616 | if (which) | |
617 | *which = -1; | |
618 | return MISS_ERROR; | |
619 | } | |
620 | return 0; | |
621 | } | |
622 | ||
c367dfd0 CF |
623 | static int |
624 | acecmp (const void *a1, const void *a2) | |
c0d1968a | 625 | { |
62cd433e | 626 | #define ace(i) ((const __aclent32_t *) a##i) |
c90e1cf1 | 627 | int ret = ace (1)->a_type - ace (2)->a_type; |
c0d1968a | 628 | if (!ret) |
c90e1cf1 | 629 | ret = ace (1)->a_id - ace (2)->a_id; |
c0d1968a CV |
630 | return ret; |
631 | #undef ace | |
632 | } | |
633 | ||
c367dfd0 | 634 | extern "C" int |
62cd433e | 635 | aclsort32 (int nentries, int, __aclent32_t *aclbufp) |
c0d1968a | 636 | { |
62cd433e | 637 | if (aclcheck32 (aclbufp, nentries, NULL)) |
c0d1968a CV |
638 | return -1; |
639 | if (!aclbufp || nentries < 1) | |
640 | { | |
641 | set_errno (EINVAL); | |
642 | return -1; | |
643 | } | |
62cd433e | 644 | qsort ((void *) aclbufp, nentries, sizeof (__aclent32_t), acecmp); |
c0d1968a CV |
645 | return 0; |
646 | } | |
647 | ||
c367dfd0 | 648 | extern "C" int |
62cd433e | 649 | acltomode32 (__aclent32_t *aclbufp, int nentries, mode_t *modep) |
c0d1968a CV |
650 | { |
651 | int pos; | |
652 | ||
653 | if (!aclbufp || nentries < 1 || !modep) | |
654 | { | |
655 | set_errno (EINVAL); | |
656 | return -1; | |
657 | } | |
658 | *modep = 0; | |
19f20901 CV |
659 | if ((pos = searchace (aclbufp, nentries, USER_OBJ)) < 0 |
660 | || !aclbufp[pos].a_type) | |
c0d1968a CV |
661 | { |
662 | set_errno (EINVAL); | |
663 | return -1; | |
664 | } | |
19f20901 CV |
665 | *modep |= (aclbufp[pos].a_perm & S_IRWXO) << 6; |
666 | if ((pos = searchace (aclbufp, nentries, GROUP_OBJ)) < 0 | |
667 | || !aclbufp[pos].a_type) | |
c0d1968a CV |
668 | { |
669 | set_errno (EINVAL); | |
670 | return -1; | |
671 | } | |
19f20901 CV |
672 | *modep |= (aclbufp[pos].a_perm & S_IRWXO) << 3; |
673 | int cpos; | |
674 | if ((cpos = searchace (aclbufp, nentries, CLASS_OBJ)) >= 0 | |
675 | && aclbufp[cpos].a_type == CLASS_OBJ) | |
676 | *modep |= ((aclbufp[pos].a_perm & S_IRWXO) & aclbufp[cpos].a_perm) << 3; | |
677 | if ((pos = searchace (aclbufp, nentries, OTHER_OBJ)) < 0 | |
678 | || !aclbufp[pos].a_type) | |
c0d1968a CV |
679 | { |
680 | set_errno (EINVAL); | |
681 | return -1; | |
682 | } | |
19f20901 | 683 | *modep |= aclbufp[pos].a_perm & S_IRWXO; |
c0d1968a CV |
684 | return 0; |
685 | } | |
686 | ||
c367dfd0 | 687 | extern "C" int |
62cd433e | 688 | aclfrommode32 (__aclent32_t *aclbufp, int nentries, mode_t *modep) |
c0d1968a CV |
689 | { |
690 | int pos; | |
691 | ||
692 | if (!aclbufp || nentries < 1 || !modep) | |
693 | { | |
694 | set_errno (EINVAL); | |
695 | return -1; | |
696 | } | |
19f20901 CV |
697 | if ((pos = searchace (aclbufp, nentries, USER_OBJ)) < 0 |
698 | || !aclbufp[pos].a_type) | |
c0d1968a CV |
699 | { |
700 | set_errno (EINVAL); | |
701 | return -1; | |
702 | } | |
19f20901 CV |
703 | aclbufp[pos].a_perm = (*modep & S_IRWXU) >> 6; |
704 | if ((pos = searchace (aclbufp, nentries, GROUP_OBJ)) < 0 | |
705 | || !aclbufp[pos].a_type) | |
c0d1968a CV |
706 | { |
707 | set_errno (EINVAL); | |
708 | return -1; | |
709 | } | |
19f20901 CV |
710 | aclbufp[pos].a_perm = (*modep & S_IRWXG) >> 3; |
711 | if ((pos = searchace (aclbufp, nentries, CLASS_OBJ)) >= 0 | |
712 | && aclbufp[pos].a_type == CLASS_OBJ) | |
713 | aclbufp[pos].a_perm = (*modep & S_IRWXG) >> 3; | |
714 | if ((pos = searchace (aclbufp, nentries, OTHER_OBJ)) < 0 | |
715 | || !aclbufp[pos].a_type) | |
c0d1968a CV |
716 | { |
717 | set_errno (EINVAL); | |
718 | return -1; | |
719 | } | |
19f20901 | 720 | aclbufp[pos].a_perm = (*modep & S_IRWXO); |
c0d1968a CV |
721 | return 0; |
722 | } | |
723 | ||
c367dfd0 | 724 | extern "C" int |
62cd433e | 725 | acltopbits32 (__aclent32_t *aclbufp, int nentries, mode_t *pbitsp) |
c0d1968a | 726 | { |
62cd433e | 727 | return acltomode32 (aclbufp, nentries, pbitsp); |
c0d1968a CV |
728 | } |
729 | ||
c367dfd0 | 730 | extern "C" int |
62cd433e | 731 | aclfrompbits32 (__aclent32_t *aclbufp, int nentries, mode_t *pbitsp) |
c0d1968a | 732 | { |
62cd433e | 733 | return aclfrommode32 (aclbufp, nentries, pbitsp); |
c0d1968a CV |
734 | } |
735 | ||
736 | static char * | |
737 | permtostr (mode_t perm) | |
738 | { | |
739 | static char pbuf[4]; | |
740 | ||
19f20901 CV |
741 | pbuf[0] = (perm & S_IROTH) ? 'r' : '-'; |
742 | pbuf[1] = (perm & S_IWOTH) ? 'w' : '-'; | |
743 | pbuf[2] = (perm & S_IXOTH) ? 'x' : '-'; | |
c0d1968a CV |
744 | pbuf[3] = '\0'; |
745 | return pbuf; | |
746 | } | |
747 | ||
c367dfd0 | 748 | extern "C" char * |
62cd433e | 749 | acltotext32 (__aclent32_t *aclbufp, int aclcnt) |
c0d1968a CV |
750 | { |
751 | if (!aclbufp || aclcnt < 1 || aclcnt > MAX_ACL_ENTRIES | |
62cd433e | 752 | || aclcheck32 (aclbufp, aclcnt, NULL)) |
c0d1968a CV |
753 | { |
754 | set_errno (EINVAL); | |
755 | return NULL; | |
756 | } | |
757 | char buf[32000]; | |
758 | buf[0] = '\0'; | |
2e008fb9 | 759 | bool first = true; |
c0d1968a CV |
760 | |
761 | for (int pos = 0; pos < aclcnt; ++pos) | |
762 | { | |
763 | if (!first) | |
764 | strcat (buf, ","); | |
2e008fb9 | 765 | first = false; |
c0d1968a CV |
766 | if (aclbufp[pos].a_type & ACL_DEFAULT) |
767 | strcat (buf, "default"); | |
62e9d4b9 | 768 | switch (aclbufp[pos].a_type & ~ACL_DEFAULT) |
c0d1968a CV |
769 | { |
770 | case USER_OBJ: | |
771 | __small_sprintf (buf + strlen (buf), "user::%s", | |
772 | permtostr (aclbufp[pos].a_perm)); | |
773 | break; | |
774 | case USER: | |
775 | __small_sprintf (buf + strlen (buf), "user:%d:%s", | |
776 | aclbufp[pos].a_id, permtostr (aclbufp[pos].a_perm)); | |
777 | break; | |
778 | case GROUP_OBJ: | |
779 | __small_sprintf (buf + strlen (buf), "group::%s", | |
780 | permtostr (aclbufp[pos].a_perm)); | |
781 | break; | |
782 | case GROUP: | |
783 | __small_sprintf (buf + strlen (buf), "group:%d:%s", | |
784 | aclbufp[pos].a_id, permtostr (aclbufp[pos].a_perm)); | |
785 | break; | |
786 | case CLASS_OBJ: | |
787 | __small_sprintf (buf + strlen (buf), "mask::%s", | |
788 | permtostr (aclbufp[pos].a_perm)); | |
789 | break; | |
790 | case OTHER_OBJ: | |
791 | __small_sprintf (buf + strlen (buf), "other::%s", | |
792 | permtostr (aclbufp[pos].a_perm)); | |
793 | break; | |
794 | default: | |
795 | set_errno (EINVAL); | |
796 | return NULL; | |
797 | } | |
798 | } | |
799 | return strdup (buf); | |
800 | } | |
801 | ||
802 | static mode_t | |
803 | permfromstr (char *perm) | |
804 | { | |
805 | mode_t mode = 0; | |
806 | ||
807 | if (strlen (perm) != 3) | |
808 | return 01000; | |
809 | if (perm[0] == 'r') | |
19f20901 | 810 | mode |= S_IROTH; |
c0d1968a CV |
811 | else if (perm[0] != '-') |
812 | return 01000; | |
813 | if (perm[1] == 'w') | |
19f20901 | 814 | mode |= S_IWOTH; |
c0d1968a CV |
815 | else if (perm[1] != '-') |
816 | return 01000; | |
817 | if (perm[2] == 'x') | |
19f20901 | 818 | mode |= S_IXOTH; |
c0d1968a CV |
819 | else if (perm[2] != '-') |
820 | return 01000; | |
821 | return mode; | |
822 | } | |
823 | ||
c367dfd0 | 824 | extern "C" __aclent32_t * |
62cd433e | 825 | aclfromtext32 (char *acltextp, int *) |
c0d1968a CV |
826 | { |
827 | if (!acltextp) | |
828 | { | |
829 | set_errno (EINVAL); | |
830 | return NULL; | |
831 | } | |
832 | char buf[strlen (acltextp) + 1]; | |
62cd433e | 833 | __aclent32_t lacl[MAX_ACL_ENTRIES]; |
c0d1968a CV |
834 | memset (lacl, 0, sizeof lacl); |
835 | int pos = 0; | |
836 | strcpy (buf, acltextp); | |
837 | char *lasts; | |
838 | for (char *c = strtok_r (buf, ",", &lasts); | |
839 | c; | |
840 | c = strtok_r (NULL, ",", &lasts)) | |
841 | { | |
842 | if (!strncmp (c, "default", 7)) | |
843 | { | |
844 | lacl[pos].a_type |= ACL_DEFAULT; | |
845 | c += 7; | |
846 | } | |
847 | if (!strncmp (c, "user:", 5)) | |
848 | { | |
849 | if (c[5] == ':') | |
850 | lacl[pos].a_type |= USER_OBJ; | |
851 | else | |
852 | { | |
853 | lacl[pos].a_type |= USER; | |
854 | c += 5; | |
855 | if (isalpha (*c)) | |
856 | { | |
d6ffc075 | 857 | struct passwd *pw = internal_getpwnam (c); |
c0d1968a CV |
858 | if (!pw) |
859 | { | |
860 | set_errno (EINVAL); | |
861 | return NULL; | |
862 | } | |
863 | lacl[pos].a_id = pw->pw_uid; | |
f71f133b | 864 | c = strchrnul (c, ':'); |
c0d1968a CV |
865 | } |
866 | else if (isdigit (*c)) | |
867 | lacl[pos].a_id = strtol (c, &c, 10); | |
62cd433e | 868 | if (*c != ':') |
c0d1968a CV |
869 | { |
870 | set_errno (EINVAL); | |
871 | return NULL; | |
872 | } | |
873 | } | |
874 | } | |
875 | else if (!strncmp (c, "group:", 6)) | |
876 | { | |
877 | if (c[5] == ':') | |
878 | lacl[pos].a_type |= GROUP_OBJ; | |
879 | else | |
880 | { | |
881 | lacl[pos].a_type |= GROUP; | |
882 | c += 5; | |
883 | if (isalpha (*c)) | |
884 | { | |
d6ffc075 | 885 | struct __group32 *gr = internal_getgrnam (c); |
c0d1968a CV |
886 | if (!gr) |
887 | { | |
888 | set_errno (EINVAL); | |
889 | return NULL; | |
890 | } | |
891 | lacl[pos].a_id = gr->gr_gid; | |
f71f133b | 892 | c = strchrnul (c, ':'); |
c0d1968a CV |
893 | } |
894 | else if (isdigit (*c)) | |
895 | lacl[pos].a_id = strtol (c, &c, 10); | |
62cd433e | 896 | if (*c != ':') |
c0d1968a CV |
897 | { |
898 | set_errno (EINVAL); | |
899 | return NULL; | |
900 | } | |
901 | } | |
902 | } | |
903 | else if (!strncmp (c, "mask:", 5)) | |
904 | { | |
905 | if (c[5] == ':') | |
906 | lacl[pos].a_type |= CLASS_OBJ; | |
907 | else | |
908 | { | |
909 | set_errno (EINVAL); | |
910 | return NULL; | |
911 | } | |
912 | } | |
913 | else if (!strncmp (c, "other:", 6)) | |
914 | { | |
915 | if (c[5] == ':') | |
916 | lacl[pos].a_type |= OTHER_OBJ; | |
917 | else | |
918 | { | |
919 | set_errno (EINVAL); | |
920 | return NULL; | |
921 | } | |
922 | } | |
923 | if ((lacl[pos].a_perm = permfromstr (c)) == 01000) | |
924 | { | |
925 | set_errno (EINVAL); | |
926 | return NULL; | |
927 | } | |
928 | ++pos; | |
929 | } | |
62cd433e | 930 | __aclent32_t *aclp = (__aclent32_t *) malloc (pos * sizeof (__aclent32_t)); |
c0d1968a | 931 | if (aclp) |
62cd433e | 932 | memcpy (aclp, lacl, pos * sizeof (__aclent32_t)); |
c0d1968a CV |
933 | return aclp; |
934 | } | |
935 | ||
62cd433e CV |
936 | /* __aclent16_t and __aclent32_t have same size and same member offsets */ |
937 | static __aclent32_t * | |
938 | acl16to32 (__aclent16_t *aclbufp, int nentries) | |
939 | { | |
940 | __aclent32_t *aclbufp32 = (__aclent32_t *) aclbufp; | |
941 | if (aclbufp32) | |
942 | for (int i = 0; i < nentries; i++) | |
943 | aclbufp32[i].a_id &= USHRT_MAX; | |
944 | return aclbufp32; | |
945 | } | |
946 | ||
c367dfd0 | 947 | extern "C" int |
62cd433e CV |
948 | acl (const char *path, int cmd, int nentries, __aclent16_t *aclbufp) |
949 | { | |
950 | return acl32 (path, cmd, nentries, acl16to32 (aclbufp, nentries)); | |
951 | } | |
952 | ||
c367dfd0 | 953 | extern "C" int |
62cd433e CV |
954 | facl (int fd, int cmd, int nentries, __aclent16_t *aclbufp) |
955 | { | |
956 | return facl32 (fd, cmd, nentries, acl16to32 (aclbufp, nentries)); | |
957 | } | |
958 | ||
c367dfd0 | 959 | extern "C" int |
62cd433e CV |
960 | lacl (const char *path, int cmd, int nentries, __aclent16_t *aclbufp) |
961 | { | |
f7382efe CV |
962 | /* This call was an accident. Make it absolutely clear. */ |
963 | set_errno (ENOSYS); | |
964 | return -1; | |
62cd433e CV |
965 | } |
966 | ||
c367dfd0 | 967 | extern "C" int |
62cd433e CV |
968 | aclcheck (__aclent16_t *aclbufp, int nentries, int *which) |
969 | { | |
970 | return aclcheck32 (acl16to32 (aclbufp, nentries), nentries, which); | |
971 | } | |
972 | ||
c367dfd0 | 973 | extern "C" int |
62cd433e CV |
974 | aclsort (int nentries, int i, __aclent16_t *aclbufp) |
975 | { | |
976 | return aclsort32 (nentries, i, acl16to32 (aclbufp, nentries)); | |
977 | } | |
978 | ||
979 | ||
c367dfd0 | 980 | extern "C" int |
62cd433e CV |
981 | acltomode (__aclent16_t *aclbufp, int nentries, mode_t *modep) |
982 | { | |
983 | return acltomode32 (acl16to32 (aclbufp, nentries), nentries, modep); | |
984 | } | |
985 | ||
c367dfd0 | 986 | extern "C" int |
62cd433e CV |
987 | aclfrommode (__aclent16_t *aclbufp, int nentries, mode_t *modep) |
988 | { | |
989 | return aclfrommode32 ((__aclent32_t *)aclbufp, nentries, modep); | |
990 | } | |
991 | ||
c367dfd0 | 992 | extern "C" int |
62cd433e CV |
993 | acltopbits (__aclent16_t *aclbufp, int nentries, mode_t *pbitsp) |
994 | { | |
995 | return acltopbits32 (acl16to32 (aclbufp, nentries), nentries, pbitsp); | |
996 | } | |
997 | ||
c367dfd0 | 998 | extern "C" int |
62cd433e CV |
999 | aclfrompbits (__aclent16_t *aclbufp, int nentries, mode_t *pbitsp) |
1000 | { | |
1001 | return aclfrompbits32 ((__aclent32_t *)aclbufp, nentries, pbitsp); | |
1002 | } | |
1003 | ||
c367dfd0 | 1004 | extern "C" char * |
62cd433e CV |
1005 | acltotext (__aclent16_t *aclbufp, int aclcnt) |
1006 | { | |
1007 | return acltotext32 (acl16to32 (aclbufp, aclcnt), aclcnt); | |
1008 | } | |
1009 | ||
c367dfd0 | 1010 | extern "C" __aclent16_t * |
62cd433e CV |
1011 | aclfromtext (char *acltextp, int * aclcnt) |
1012 | { | |
1013 | return (__aclent16_t *) aclfromtext32 (acltextp, aclcnt); | |
1014 | } |