]> git.saurik.com Git - apple/libc.git/blame - sys/statx_np.c
Libc-391.tar.gz
[apple/libc.git] / sys / statx_np.c
CommitLineData
3d9156a7
A
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
37static int statx_syscall(void *obj, struct stat *sb, void *fsacl, size_t *fsacl_size);
38static int fstatx_syscall(void *obj, struct stat *sb, void *fsacl, size_t *fsacl_size);
39static int lstatx_syscall(void *obj, struct stat *sb, void *fsacl, size_t *fsacl_size);
40
41static 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 */
48int
49statx_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
56int
57fstatx_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
64int
65lstatx_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 */
75static int
76statx_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
83static int
84fstatx_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
90static int
91lstatx_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 */
100static int
101statx1(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 }
171out:
172 if (fsacl != NULL)
173 free(fsacl);
174 return(error);
175}