]> git.saurik.com Git - apple/libc.git/blame - gen/filesec.c
Libc-498.1.5.tar.gz
[apple/libc.git] / gen / filesec.c
CommitLineData
3d9156a7
A
1/*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24#include <sys/types.h>
25#include <sys/acl.h>
26#include <stdlib.h>
27#include <fcntl.h>
28#include <strings.h>
29#include <errno.h>
30#include <uuid/uuid.h>
31
eb1cde05
A
32/*
33 * Versions of copy_int/copy_ext that retain native endianity.
34 */
35extern ssize_t acl_copy_ext_native(void *buf_p, acl_t acl, ssize_t size);
36extern acl_t acl_copy_int_native(const void *buf_p);
3d9156a7
A
37
38struct _filesec {
39 int fs_valid;
40#define FS_VALID_UID (1<<0)
41#define FS_VALID_GID (1<<1)
42#define FS_VALID_UUID (1<<2)
43#define FS_VALID_GRPUUID (1<<3)
44#define FS_VALID_MODE (1<<4)
45#define FS_VALID_ACL (1<<5)
46 uid_t fs_uid;
47 gid_t fs_gid;
48 uuid_t fs_uuid;
49 uuid_t fs_grpuuid;
50 mode_t fs_mode;
51 size_t fs_aclsize;
52 void *fs_aclbuf;
53};
54
55#define FS_ISVALID(_fsec, _bit) ((_fsec)->fs_valid & (_bit))
56#define FS_CLEAR(_fsec, _bit) ((_fsec)->fs_valid &= ~(_bit))
57#define FS_SET(_fsec, _bit) ((_fsec)->fs_valid |= (_bit))
58
59static void filesec_discard_aclbuf(struct _filesec *fsec);
60
61filesec_t
62filesec_init(void)
63{
64 struct _filesec *fsp;
65
66 fsp = malloc(sizeof(*fsp));
67 if (fsp != NULL)
68 fsp->fs_valid = 0;
69 return(fsp);
70}
71
72filesec_t
73filesec_dup(filesec_t fsec)
74{
75 struct _filesec *fsp;
76
77 fsp = malloc(sizeof(*fsp));
78 if (fsp != NULL) {
79 *fsp = *fsec;
80 if (FS_ISVALID(fsec, FS_VALID_ACL)) {
81 if (fsec->fs_aclbuf != _FILESEC_REMOVE_ACL) {
82 fsp->fs_aclbuf = malloc(fsec->fs_aclsize);
83 if (fsp->fs_aclbuf == NULL) {
84 free(fsp);
85 return(NULL);
86 }
87 bcopy(fsec->fs_aclbuf, fsp->fs_aclbuf, fsec->fs_aclsize);
88 }
89 }
90 }
91 return(fsp);
92}
93
94void
95filesec_free(filesec_t fsec)
96{
97 filesec_discard_aclbuf(fsec);
98 free(fsec);
99}
100
101int
102filesec_get_property(filesec_t fsec, filesec_property_t property, void *propptr)
103{
104 int error;
105
106 error = 0;
107 switch(property) {
108 case FILESEC_OWNER:
109 if (!FS_ISVALID(fsec, FS_VALID_UID)) {
110 error = ENOENT;
111 break;
112 }
113 if (propptr != NULL)
114 *(uid_t *)propptr = fsec->fs_uid;
115 break;
116 case FILESEC_GROUP:
117 if (!FS_ISVALID(fsec, FS_VALID_GID)) {
118 error = ENOENT;
119 break;
120 }
121 if (propptr != NULL)
122 *(gid_t *)propptr = fsec->fs_gid;
123 break;
124 case FILESEC_UUID:
125 if (!FS_ISVALID(fsec, FS_VALID_UUID)) {
126 error = ENOENT;
127 break;
128 }
129 if (propptr != NULL)
130 uuid_copy(*(uuid_t *)propptr, fsec->fs_uuid);
131 break;
132 case FILESEC_GRPUUID:
133 if (!FS_ISVALID(fsec, FS_VALID_GRPUUID)) {
134 error = ENOENT;
135 break;
136 }
137 if (propptr != NULL)
138 uuid_copy(*(uuid_t *)propptr, fsec->fs_grpuuid);
139 break;
140 case FILESEC_MODE:
141 if (!FS_ISVALID(fsec, FS_VALID_MODE)) {
142 error = ENOENT;
143 break;
144 }
145 if (propptr != NULL)
146 *(mode_t *)propptr = fsec->fs_mode;
147 break;
148 case FILESEC_ACL:
149 if (!FS_ISVALID(fsec, FS_VALID_ACL)) {
150 error = ENOENT;
151 break;
152 }
153 if (propptr != NULL) {
154 if (fsec->fs_aclbuf == _FILESEC_REMOVE_ACL) {
155 *(acl_t *)propptr = _FILESEC_REMOVE_ACL;
156 } else {
eb1cde05 157 *(acl_t *)propptr = acl_copy_int_native(fsec->fs_aclbuf);
3d9156a7
A
158 if (*(acl_t *)propptr == NULL)
159 error = errno;
160 }
161 }
162 break;
163 case FILESEC_ACL_RAW:
164 if (!FS_ISVALID(fsec, FS_VALID_ACL)) {
165 error = ENOENT;
166 break;
167 }
168 if (propptr != NULL)
169 *(void **)propptr = fsec->fs_aclbuf;
170 break;
171 case FILESEC_ACL_ALLOCSIZE:
172 if (!FS_ISVALID(fsec, FS_VALID_ACL)) {
173 error = ENOENT;
174 break;
175 }
176 if (propptr != NULL)
177 *(size_t *)propptr = fsec->fs_aclsize;
178 break;
179 default:
180 error = EINVAL;
181 break;
182 }
183 if (error) {
184 errno = error;
185 return(-1);
186 }
187 return(0);
188}
189
190int
191filesec_set_property(filesec_t fsec, filesec_property_t property, const void *propptr)
192{
193 void *aclbuf;
194 ssize_t aclsize, copysize;
195 acl_t acl;
196 int error;
197
198 error = 0;
199 switch(property) {
200 case FILESEC_OWNER:
201 if (propptr == _FILESEC_UNSET_PROPERTY) {
202 FS_CLEAR(fsec, FS_VALID_UID);
203 } else {
204 fsec->fs_uid = *(uid_t *)propptr;
205 FS_SET(fsec, FS_VALID_UID);
206 }
207 break;
208 case FILESEC_GROUP:
209 if (propptr == _FILESEC_UNSET_PROPERTY) {
210 FS_CLEAR(fsec, FS_VALID_GID);
211 } else {
212 fsec->fs_gid = *(gid_t *)propptr;
213 FS_SET(fsec, FS_VALID_GID);
214 }
215 break;
216 case FILESEC_UUID:
217 if (propptr == _FILESEC_UNSET_PROPERTY) {
218 FS_CLEAR(fsec, FS_VALID_UUID);
219 } else {
220 uuid_copy(fsec->fs_uuid, *(uuid_t *)propptr);
221 FS_SET(fsec, FS_VALID_UUID);
222 }
223 break;
224 case FILESEC_GRPUUID:
225 if (propptr == _FILESEC_UNSET_PROPERTY) {
226 FS_CLEAR(fsec, FS_VALID_GRPUUID);
227 } else {
228 uuid_copy(fsec->fs_grpuuid, *(uuid_t *)propptr);
229 FS_SET(fsec, FS_VALID_GRPUUID);
230 }
231 break;
232 case FILESEC_MODE:
233 if (propptr == _FILESEC_UNSET_PROPERTY) {
234 FS_CLEAR(fsec, FS_VALID_MODE);
235 } else {
236 fsec->fs_mode = *(mode_t *)propptr;
237 FS_SET(fsec, FS_VALID_MODE);
238 }
239 break;
240 case FILESEC_ACL:
241 if (propptr == _FILESEC_UNSET_PROPERTY) {
242 filesec_discard_aclbuf(fsec);
243 FS_CLEAR(fsec, FS_VALID_ACL);
244 } else if (propptr == _FILESEC_REMOVE_ACL) {
245 filesec_discard_aclbuf(fsec);
246 fsec->fs_aclbuf = _FILESEC_REMOVE_ACL;
247 fsec->fs_aclsize = 0;
248 FS_SET(fsec, FS_VALID_ACL);
249 } else {
250 acl = *(acl_t *)propptr;
251 aclsize = acl_size(acl);
252 if (aclsize < 0) {
253 error = errno;
254 break;
255 }
256 if ((aclbuf = malloc(aclsize)) == NULL) {
257 error = errno;
258 break;
259 }
eb1cde05 260 copysize = acl_copy_ext_native(aclbuf, acl, aclsize);
3d9156a7
A
261 if (copysize < 0) {
262 free(aclbuf);
263 error = EINVAL;
264 break;
265 }
266 filesec_discard_aclbuf(fsec);
267 fsec->fs_aclbuf = aclbuf;
268 fsec->fs_aclsize = aclsize;
269 FS_SET(fsec, FS_VALID_ACL);
270 }
271 break;
272 case FILESEC_ACL_RAW:
273 filesec_discard_aclbuf(fsec);
274 if ((propptr != NULL) && (*(void **)propptr != NULL)) {
275 fsec->fs_aclbuf = *(void **)propptr;
276 FS_SET(fsec, FS_VALID_ACL);
277 }
278 break;
279 case FILESEC_ACL_ALLOCSIZE:
280 if (propptr != NULL) {
281 fsec->fs_aclsize = *(size_t *)propptr;
282 } else {
283 error = EINVAL;
284 }
285 break;
286 default:
287 error = EINVAL;
288 break;
289 }
290 if (error != 0) {
291 errno = error;
292 return (-1);
293 }
294 return (0);
295}
296
297int
298filesec_query_property(filesec_t fsec, filesec_property_t property, int *validptr)
299{
300 int valid, error;
301
302 error = 0;
303 switch(property) {
304 case FILESEC_OWNER:
305 valid = FS_ISVALID(fsec, FS_VALID_UID);
306 break;
307 case FILESEC_GROUP:
308 valid = FS_ISVALID(fsec, FS_VALID_GID);
309 break;
310 case FILESEC_UUID:
311 valid = FS_ISVALID(fsec, FS_VALID_UUID);
312 break;
313 case FILESEC_GRPUUID:
314 valid = FS_ISVALID(fsec, FS_VALID_GRPUUID);
315 break;
316 case FILESEC_MODE:
317 valid = FS_ISVALID(fsec, FS_VALID_MODE);
318 break;
319 case FILESEC_ACL:
320 case FILESEC_ACL_RAW:
321 case FILESEC_ACL_ALLOCSIZE:
322 valid = FS_ISVALID(fsec, FS_VALID_ACL);
323 break;
324 default:
325 error = EINVAL;
326 break;
327 }
328
329 if (error != 0) {
330 errno = error;
331 return(-1);
332 }
333 *validptr = valid;
334 return(0);
335}
336
337static void
338filesec_discard_aclbuf(struct _filesec *fsec)
339{
340 if (FS_ISVALID(fsec, FS_VALID_ACL)) {
341 if (fsec->fs_aclbuf != _FILESEC_REMOVE_ACL)
342 free(fsec->fs_aclbuf);
343 fsec->fs_aclbuf = NULL;
344 fsec->fs_aclsize = 0;
345 FS_CLEAR(fsec, FS_VALID_ACL);
346 }
347}