]> git.saurik.com Git - apple/libc.git/blob - sys/statx_np.c
Libc-391.tar.gz
[apple/libc.git] / sys / statx_np.c
1 /*
2 * Copyright (c) 2004 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 #include <sys/types.h>
24 #include <sys/acl.h>
25 #include <sys/stat.h>
26 #include <errno.h>
27 #include <stdlib.h>
28 #include <sys/syscall.h>
29 #include <unistd.h>
30 #include <fcntl.h>
31
32 #include <string.h>
33 #include <stdio.h>
34
35 #define ACL_MIN_SIZE_HEURISTIC (sizeof(struct kauth_filesec) + 16 * sizeof(struct kauth_ace))
36
37 static int statx_syscall(void *obj, struct stat *sb, void *fsacl, size_t *fsacl_size);
38 static int fstatx_syscall(void *obj, struct stat *sb, void *fsacl, size_t *fsacl_size);
39 static int lstatx_syscall(void *obj, struct stat *sb, void *fsacl, size_t *fsacl_size);
40
41 static int statx1(void *obj,
42 int (* stat_syscall)(void *obj, struct stat *sb, void *fsacl, size_t *fsacl_size),
43 struct stat *sb, filesec_t fsec);
44
45 /*
46 * Stat interfaces.
47 */
48 int
49 statx_np(const char *path, struct stat *sb, filesec_t fsec)
50 {
51 if (fsec == NULL)
52 return(stat(path, sb));
53 return(statx1((void *)&path, statx_syscall, sb, fsec));
54 }
55
56 int
57 fstatx_np(int fd, struct stat *sb, filesec_t fsec)
58 {
59 if (fsec == NULL)
60 return(fstat(fd, sb));
61 return(statx1((void *)&fd, fstatx_syscall, sb, fsec));
62 }
63
64 int
65 lstatx_np(const char *path, struct stat *sb, filesec_t fsec)
66 {
67 if (fsec == NULL)
68 return(lstat(path, sb));
69 return(statx1((void *)&path, lstatx_syscall, sb, fsec));
70 }
71
72 /*
73 * Stat syscalls
74 */
75 static int
76 statx_syscall(void *obj, struct stat *sb, void *fsacl, size_t *fsacl_size)
77 {
78 const char *path = *(const char **)obj;
79
80 return(syscall(SYS_stat_extended, path, sb, fsacl, fsacl_size));
81 }
82
83 static int
84 fstatx_syscall(void *obj, struct stat *sb, void *fsacl, size_t *fsacl_size)
85 {
86 int fd = *(int *)obj;
87 return(syscall(SYS_fstat_extended, fd, sb, fsacl, fsacl_size));
88 }
89
90 static int
91 lstatx_syscall(void *obj, struct stat *sb, void *fsacl, size_t *fsacl_size)
92 {
93 const char *path = *(const char **)obj;
94 return(syscall(SYS_lstat_extended, path, sb, fsacl, fsacl_size));
95 }
96
97 /*
98 * Stat internals
99 */
100 static int
101 statx1(void *obj,
102 int (* stat_syscall)(void *obj, struct stat *sb, void *fsacl, size_t *fsacl_size),
103 struct stat *sb, filesec_t fsec)
104 {
105 struct kauth_filesec *fsacl, *ofsacl;
106 size_t fsacl_size, buffer_size;
107 int error;
108
109 fsacl = NULL;
110 error = 0;
111
112 /*
113 * Allocate an initial buffer.
114 */
115 if ((fsacl = malloc(ACL_MIN_SIZE_HEURISTIC)) == NULL) {
116 error = ENOMEM;
117 goto out;
118 }
119 buffer_size = ACL_MIN_SIZE_HEURISTIC;
120
121 /*
122 * Loop until we have the ACL.
123 */
124 for (;;) {
125 fsacl_size = buffer_size;
126 if ((error = stat_syscall(obj, sb, fsacl, &fsacl_size)) != 0)
127 goto out;
128
129 /*
130 * No error, did we get the ACL?
131 */
132 if (fsacl_size <= buffer_size)
133 break;
134
135 /* no, use supplied buffer size plus some padding */
136 ofsacl = fsacl;
137 fsacl = realloc(fsacl, fsacl_size + sizeof(struct kauth_ace) * 2);
138 if (fsacl == NULL) {
139 fsacl = ofsacl;
140 errno = ENOMEM;
141 goto out;
142 }
143 buffer_size = fsacl_size;
144 }
145
146 /* populate filesec with values from stat */
147 filesec_set_property(fsec, FILESEC_OWNER, &(sb->st_uid));
148 filesec_set_property(fsec, FILESEC_GROUP, &(sb->st_gid));
149 filesec_set_property(fsec, FILESEC_MODE, &(sb->st_mode));
150
151 /* if we got a kauth_filesec, take values from there too */
152 if (fsacl_size >= sizeof(struct kauth_filesec)) {
153 filesec_set_property(fsec, FILESEC_UUID, &fsacl->fsec_owner);
154 filesec_set_property(fsec, FILESEC_GRPUUID, &fsacl->fsec_group);
155
156 /* check to see whether there's actually an ACL here */
157 if (fsacl->fsec_acl.acl_entrycount != KAUTH_FILESEC_NOACL) {
158 filesec_set_property(fsec, FILESEC_ACL_ALLOCSIZE, &fsacl_size);
159 filesec_set_property(fsec, FILESEC_ACL_RAW, &fsacl);
160 fsacl = NULL; /* avoid freeing it below */
161 } else {
162 filesec_set_property(fsec, FILESEC_ACL_ALLOCSIZE, NULL);
163 filesec_set_property(fsec, FILESEC_ACL_RAW, NULL);
164 }
165 } else {
166 filesec_set_property(fsec, FILESEC_UUID, NULL);
167 filesec_set_property(fsec, FILESEC_GRPUUID, NULL);
168 filesec_set_property(fsec, FILESEC_ACL_ALLOCSIZE, NULL);
169 filesec_set_property(fsec, FILESEC_ACL_RAW, NULL);
170 }
171 out:
172 if (fsacl != NULL)
173 free(fsacl);
174 return(error);
175 }