]> git.saurik.com Git - apple/xnu.git/blame - bsd/vfs/vfs_xattr.c
xnu-792.6.22.tar.gz
[apple/xnu.git] / bsd / vfs / vfs_xattr.c
CommitLineData
91447636
A
1/*
2 * Copyright (c) 2004-2005 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
23#include <sys/param.h>
24
25#include <sys/fcntl.h>
26#include <sys/fsevents.h>
27#include <sys/kernel.h>
28#include <sys/kauth.h>
29#include <sys/malloc.h>
30#include <sys/namei.h>
31#include <sys/proc_internal.h>
32#include <sys/stat.h>
33#include <sys/uio.h>
34#include <sys/utfconv.h>
35#include <sys/vnode.h>
36#include <sys/vnode_internal.h>
37
38#include <sys/xattr.h>
39
40#include <architecture/byte_order.h>
41#include <vm/vm_kern.h>
42
43/*
44 * Default xattr support routines.
45 */
46static int default_getxattr(vnode_t vp, const char *name, uio_t uio, size_t *size,
47 int options, vfs_context_t context);
48
49static int default_setxattr(vnode_t vp, const char *name, uio_t uio,
50 int options, vfs_context_t context);
51
52static int default_removexattr(vnode_t vp, const char *name, int options, vfs_context_t context);
53
54static int default_listxattr(vnode_t vp, uio_t uio, size_t *size, int options,
55 vfs_context_t context);
56
57
58
59/*
60 * Retrieve the data of an extended attribute.
61 */
62int
63vn_getxattr(vnode_t vp, const char *name, uio_t uio, size_t *size,
64 int options, vfs_context_t context)
65{
66 int error;
67
68 if (!(vp->v_type == VREG || vp->v_type == VDIR || vp->v_type == VLNK)) {
69 return (EPERM);
70 }
71 if ((error = xattr_validatename(name))) {
72 return (error);
73 }
74 if (!(options & XATTR_NOSECURITY) && (error = vnode_authorize(vp, NULL, KAUTH_VNODE_READ_EXTATTRIBUTES, context)))
75 goto out;
76
77 /* The offset can only be non-zero for resource forks. */
78 if (uio != NULL && uio_offset(uio) != 0 &&
79 bcmp(name, XATTR_RESOURCEFORK_NAME, sizeof(XATTR_RESOURCEFORK_NAME)) != 0) {
80 error = EINVAL;
81 goto out;
82 }
83
84 error = VNOP_GETXATTR(vp, name, uio, size, options, context);
85 if (error == ENOTSUP) {
86 /*
87 * A filesystem may keep some EAs natively and return ENOTSUP for others.
88 * SMB returns ENOTSUP for finderinfo and resource forks.
89 */
90 error = default_getxattr(vp, name, uio, size, options, context);
91 }
92out:
93 return (error);
94}
95
96/*
97 * Set the data of an extended attribute.
98 */
99int
100vn_setxattr(vnode_t vp, const char *name, uio_t uio, int options, vfs_context_t context)
101{
102 int error;
103
104 if (!(vp->v_type == VREG || vp->v_type == VDIR || vp->v_type == VLNK)) {
105 return (EPERM);
106 }
107 if ((options & (XATTR_REPLACE|XATTR_CREATE)) == (XATTR_REPLACE|XATTR_CREATE)) {
108 return (EINVAL);
109 }
110 if ((error = xattr_validatename(name))) {
111 return (error);
112 }
113 if (!(options & XATTR_NOSECURITY) && (error = vnode_authorize(vp, NULL, KAUTH_VNODE_WRITE_EXTATTRIBUTES, context)))
114 goto out;
115
116 /* The offset can only be non-zero for resource forks. */
117 if (uio_offset(uio) != 0 &&
118 bcmp(name, XATTR_RESOURCEFORK_NAME, sizeof(XATTR_RESOURCEFORK_NAME)) != 0 ) {
119 error = EINVAL;
120 goto out;
121 }
122
123 error = VNOP_SETXATTR(vp, name, uio, options, context);
124#ifdef DUAL_EAS
125 /*
126 * An EJUSTRETURN is from a filesystem which keeps this xattr
127 * natively as well as in a dot-underscore file. In this case the
128 * EJUSTRETURN means the filesytem has done nothing, but identifies the
129 * EA as one which may be represented natively and/or in a DU, and
130 * since XATTR_CREATE or XATTR_REPLACE was specified, only up here in
131 * in vn_setxattr can we do the getxattrs needed to ascertain whether
132 * the XATTR_{CREATE,REPLACE} should yield an error.
133 */
134 if (error == EJUSTRETURN) {
135 int native = 0, dufile = 0;
136 size_t sz; /* not used */
137
138 native = VNOP_GETXATTR(vp, name, NULL, &sz, 0, context) ? 0 : 1;
139 dufile = default_getxattr(vp, name, NULL, &sz, 0, context) ? 0 : 1;
140 if (options & XATTR_CREATE && (native || dufile)) {
141 error = EEXIST;
142 goto out;
143 }
144 if (options & XATTR_REPLACE && !(native || dufile)) {
145 error = ENOATTR;
146 goto out;
147 }
148 /*
149 * Having determined no CREATE/REPLACE error should result, we
150 * zero those bits, so both backing stores get written to.
151 */
152 options &= ~(XATTR_CREATE | XATTR_REPLACE);
153 error = VNOP_SETXATTR(vp, name, uio, options, context);
154 /* the mainline path here is to have error==ENOTSUP ... */
155 }
156#endif /* DUAL_EAS */
157 if (error == ENOTSUP) {
158 /*
159 * A filesystem may keep some EAs natively and return ENOTSUP for others.
160 * SMB returns ENOTSUP for finderinfo and resource forks.
161 */
162 error = default_setxattr(vp, name, uio, options, context);
163 }
164out:
165 return (error);
166}
167
168/*
169 * Remove an extended attribute.
170 */
171int
172vn_removexattr(vnode_t vp, const char * name, int options, vfs_context_t context)
173{
174 int error;
175
176 if (!(vp->v_type == VREG || vp->v_type == VDIR || vp->v_type == VLNK)) {
177 return (EPERM);
178 }
179 if ((error = xattr_validatename(name))) {
180 return (error);
181 }
182 if (!(options & XATTR_NOSECURITY) && (error = vnode_authorize(vp, NULL, KAUTH_VNODE_WRITE_EXTATTRIBUTES, context)))
183 goto out;
184 error = VNOP_REMOVEXATTR(vp, name, options, context);
185 if (error == ENOTSUP) {
186 /*
187 * A filesystem may keep some EAs natively and return ENOTSUP for others.
188 * SMB returns ENOTSUP for finderinfo and resource forks.
189 */
190 error = default_removexattr(vp, name, options, context);
191#ifdef DUAL_EAS
192 } else if (error == EJUSTRETURN) {
193 /*
194 * EJUSTRETURN is from a filesystem which keeps this xattr natively as well
195 * as in a dot-underscore file. EJUSTRETURN means the filesytem did remove
196 * a native xattr, so failure to find it in a DU file during
197 * default_removexattr should not be considered an error.
198 */
199 error = default_removexattr(vp, name, options, context);
200 if (error == ENOATTR)
201 error = 0;
202#endif /* DUAL_EAS */
203 }
204out:
205 return (error);
206}
207
208/*
209 * Retrieve the list of extended attribute names.
210 */
211int
212vn_listxattr(vnode_t vp, uio_t uio, size_t *size, int options, vfs_context_t context)
213{
214 int error;
215
216 if (!(vp->v_type == VREG || vp->v_type == VDIR || vp->v_type == VLNK)) {
217 return (EPERM);
218 }
219 if (!(options & XATTR_NOSECURITY) && (error = vnode_authorize(vp, NULL, KAUTH_VNODE_READ_EXTATTRIBUTES, context)))
220 goto out;
221
222 error = VNOP_LISTXATTR(vp, uio, size, options, context);
223 if (error == ENOTSUP) {
224 /*
225 * A filesystem may keep some but not all EAs natively, in which case
226 * the native EA names will have been uiomove-d out (or *size updated)
227 * and the default_listxattr here will finish the job. Note SMB takes
228 * advantage of this for its finder-info and resource forks.
229 */
230 error = default_listxattr(vp, uio, size, options, context);
231 }
232out:
233 return (error);
234}
235
236int
237xattr_validatename(const char *name)
238{
239 int namelen;
240
241 if (name == NULL || name[0] == '\0') {
242 return (EINVAL);
243 }
244 namelen = strlen(name);
245 if (namelen > XATTR_MAXNAMELEN) {
246 return (ENAMETOOLONG);
247 }
248 if (utf8_validatestr(name, namelen) != 0) {
249 return (EINVAL);
250 }
251 return (0);
252}
253
254
255/*
256 * Determine whether an EA is a protected system attribute.
257 */
258int
259xattr_protected(const char *attrname)
260{
261 return(!strncmp(attrname, "com.apple.system.", 17));
262}
263
264
265/*
266 * Default Implementation (Non-native EA)
267 */
268
269
270/*
271 Typical "._" AppleDouble Header File layout:
272 ------------------------------------------------------------
273 MAGIC 0x00051607
274 VERSION 0x00020000
275 FILLER 0
276 COUNT 2
277 .-- AD ENTRY[0] Finder Info Entry (must be first)
278 .--+-- AD ENTRY[1] Resource Fork Entry (must be last)
279 | '-> FINDER INFO
280 | ///////////// Fixed Size Data (32 bytes)
281 | EXT ATTR HDR
282 | /////////////
283 | ATTR ENTRY[0] --.
284 | ATTR ENTRY[1] --+--.
285 | ATTR ENTRY[2] --+--+--.
286 | ... | | |
287 | ATTR ENTRY[N] --+--+--+--.
288 | ATTR DATA 0 <-' | | |
289 | //////////// | | |
290 | ATTR DATA 1 <----' | |
291 | ///////////// | |
292 | ATTR DATA 2 <-------' |
293 | ///////////// |
294 | ... |
295 | ATTR DATA N <----------'
296 | /////////////
297 | Attribute Free Space
298 |
299 '----> RESOURCE FORK
300 ///////////// Variable Sized Data
301 /////////////
302 /////////////
303 /////////////
304 /////////////
305 /////////////
306 ...
307 /////////////
308
309 ------------------------------------------------------------
310
311 NOTE: The EXT ATTR HDR, ATTR ENTRY's and ATTR DATA's are
312 stored as part of the Finder Info. The length in the Finder
313 Info AppleDouble entry includes the length of the extended
314 attribute header, attribute entries, and attribute data.
315*/
316
317
318/*
319 * On Disk Data Structures
320 *
321 * Note: Motorola 68K alignment and big-endian.
322 *
323 * See RFC 1740 for additional information about the AppleDouble file format.
324 *
325 */
326
327#define ADH_MAGIC 0x00051607
328#define ADH_VERSION 0x00020000
329#define ADH_MACOSX "Mac OS X "
330
331/*
332 * AppleDouble Entry ID's
333 */
334#define AD_DATA 1 /* Data fork */
335#define AD_RESOURCE 2 /* Resource fork */
336