1 1.41 riastrad /* $NetBSD: vfs_xattr.c,v 1.41 2024/12/07 02:27:38 riastradh Exp $ */ 2 1.2 thorpej 3 1.2 thorpej /*- 4 1.17 ad * Copyright (c) 2005, 2008 The NetBSD Foundation, Inc. 5 1.2 thorpej * All rights reserved. 6 1.2 thorpej * 7 1.2 thorpej * This code is derived from software contributed to The NetBSD Foundation 8 1.2 thorpej * by Jason R. Thorpe. 9 1.2 thorpej * 10 1.2 thorpej * Redistribution and use in source and binary forms, with or without 11 1.2 thorpej * modification, are permitted provided that the following conditions 12 1.2 thorpej * are met: 13 1.2 thorpej * 1. Redistributions of source code must retain the above copyright 14 1.2 thorpej * notice, this list of conditions and the following disclaimer. 15 1.2 thorpej * 2. Redistributions in binary form must reproduce the above copyright 16 1.2 thorpej * notice, this list of conditions and the following disclaimer in the 17 1.2 thorpej * documentation and/or other materials provided with the distribution. 18 1.2 thorpej * 19 1.2 thorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.2 thorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.2 thorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.2 thorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.2 thorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.2 thorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.2 thorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.2 thorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.2 thorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.2 thorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.2 thorpej * POSSIBILITY OF SUCH DAMAGE. 30 1.2 thorpej */ 31 1.1 thorpej 32 1.1 thorpej /* 33 1.1 thorpej * Copyright (c) 1989, 1993 34 1.1 thorpej * The Regents of the University of California. All rights reserved. 35 1.1 thorpej * (c) UNIX System Laboratories, Inc. 36 1.1 thorpej * All or some portions of this file are derived from material licensed 37 1.1 thorpej * to the University of California by American Telephone and Telegraph 38 1.1 thorpej * Co. or Unix System Laboratories, Inc. and are reproduced herein with 39 1.1 thorpej * the permission of UNIX System Laboratories, Inc. 40 1.1 thorpej * 41 1.1 thorpej * Redistribution and use in source and binary forms, with or without 42 1.1 thorpej * modification, are permitted provided that the following conditions 43 1.1 thorpej * are met: 44 1.1 thorpej * 1. Redistributions of source code must retain the above copyright 45 1.1 thorpej * notice, this list of conditions and the following disclaimer. 46 1.1 thorpej * 2. Redistributions in binary form must reproduce the above copyright 47 1.1 thorpej * notice, this list of conditions and the following disclaimer in the 48 1.1 thorpej * documentation and/or other materials provided with the distribution. 49 1.1 thorpej * 3. Neither the name of the University nor the names of its contributors 50 1.1 thorpej * may be used to endorse or promote products derived from this software 51 1.1 thorpej * without specific prior written permission. 52 1.1 thorpej * 53 1.1 thorpej * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 54 1.1 thorpej * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 55 1.1 thorpej * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 56 1.1 thorpej * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 57 1.1 thorpej * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 58 1.1 thorpej * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 59 1.1 thorpej * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 60 1.1 thorpej * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 61 1.1 thorpej * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 62 1.1 thorpej * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 63 1.1 thorpej * SUCH DAMAGE. 64 1.1 thorpej */ 65 1.1 thorpej 66 1.1 thorpej /* 67 1.1 thorpej * VFS extended attribute support. 68 1.1 thorpej */ 69 1.1 thorpej 70 1.1 thorpej #include <sys/cdefs.h> 71 1.41 riastrad __KERNEL_RCSID(0, "$NetBSD: vfs_xattr.c,v 1.41 2024/12/07 02:27:38 riastradh Exp $"); 72 1.1 thorpej 73 1.1 thorpej #include <sys/param.h> 74 1.40 riastrad #include <sys/types.h> 75 1.40 riastrad 76 1.40 riastrad #include <sys/extattr.h> 77 1.40 riastrad #include <sys/file.h> 78 1.1 thorpej #include <sys/filedesc.h> 79 1.40 riastrad #include <sys/kauth.h> 80 1.1 thorpej #include <sys/kernel.h> 81 1.40 riastrad #include <sys/ktrace.h> 82 1.1 thorpej #include <sys/mount.h> 83 1.40 riastrad #include <sys/namei.h> 84 1.1 thorpej #include <sys/proc.h> 85 1.41 riastrad #include <sys/sdt.h> 86 1.40 riastrad #include <sys/syscallargs.h> 87 1.40 riastrad #include <sys/sysctl.h> 88 1.40 riastrad #include <sys/systm.h> 89 1.1 thorpej #include <sys/uio.h> 90 1.40 riastrad #include <sys/vnode.h> 91 1.2 thorpej #include <sys/xattr.h> 92 1.1 thorpej 93 1.30 elad #include <miscfs/genfs/genfs.h> 94 1.30 elad 95 1.36 christos static void 96 1.36 christos ktr_xattr_name(const char *str) 97 1.36 christos { 98 1.36 christos ktrkuser("xattr-name", (void *)__UNCONST(str), strlen(str)); 99 1.36 christos } 100 1.36 christos 101 1.36 christos static void 102 1.36 christos ktr_xattr_val(const void *data, size_t cnt) 103 1.36 christos { 104 1.36 christos ktruser("xattr-val", __UNCONST(data), cnt, 0); 105 1.36 christos } 106 1.36 christos 107 1.1 thorpej /* 108 1.3 thorpej * Credential check based on process requesting service, and per-attribute 109 1.3 thorpej * permissions. 110 1.3 thorpej * 111 1.3 thorpej * NOTE: Vnode must be locked. 112 1.3 thorpej */ 113 1.3 thorpej int 114 1.35 christos extattr_check_cred(struct vnode *vp, int attrspace, kauth_cred_t cred, 115 1.30 elad int access) 116 1.3 thorpej { 117 1.3 thorpej 118 1.3 thorpej if (cred == NOCRED) 119 1.38 riastrad return 0; 120 1.3 thorpej 121 1.30 elad return kauth_authorize_vnode(cred, kauth_extattr_action(access), vp, 122 1.35 christos NULL, genfs_can_extattr(vp, cred, access, attrspace)); 123 1.3 thorpej } 124 1.3 thorpej 125 1.3 thorpej /* 126 1.3 thorpej * Default vfs_extattrctl routine for file systems that do not support 127 1.3 thorpej * it. 128 1.3 thorpej */ 129 1.3 thorpej /*ARGSUSED*/ 130 1.3 thorpej int 131 1.9 yamt vfs_stdextattrctl(struct mount *mp, int cmt, struct vnode *vp, 132 1.13 pooka int attrnamespace, const char *attrname) 133 1.3 thorpej { 134 1.3 thorpej 135 1.3 thorpej if (vp != NULL) 136 1.22 hannken VOP_UNLOCK(vp); 137 1.41 riastrad return SET_ERROR(EOPNOTSUPP); 138 1.3 thorpej } 139 1.3 thorpej 140 1.3 thorpej /* 141 1.2 thorpej * Push extended attribute configuration information into the file 142 1.2 thorpej * system. 143 1.1 thorpej * 144 1.1 thorpej * NOTE: Not all file systems that support extended attributes will 145 1.1 thorpej * require the use of this system call. 146 1.1 thorpej */ 147 1.1 thorpej int 148 1.40 riastrad sys_extattrctl(struct lwp *l, const struct sys_extattrctl_args *uap, 149 1.40 riastrad register_t *retval) 150 1.1 thorpej { 151 1.15 dsl /* { 152 1.1 thorpej syscallarg(const char *) path; 153 1.1 thorpej syscallarg(int) cmd; 154 1.1 thorpej syscallarg(const char *) filename; 155 1.1 thorpej syscallarg(int) attrnamespace; 156 1.1 thorpej syscallarg(const char *) attrname; 157 1.15 dsl } */ 158 1.20 dholland struct vnode *path_vp, *file_vp; 159 1.23 dholland struct pathbuf *file_pb; 160 1.20 dholland struct nameidata file_nd; 161 1.1 thorpej char attrname[EXTATTR_MAXNAMELEN]; 162 1.1 thorpej int error; 163 1.1 thorpej 164 1.1 thorpej if (SCARG(uap, attrname) != NULL) { 165 1.1 thorpej error = copyinstr(SCARG(uap, attrname), attrname, 166 1.1 thorpej sizeof(attrname), NULL); 167 1.1 thorpej if (error) 168 1.38 riastrad return error; 169 1.1 thorpej } 170 1.1 thorpej 171 1.38 riastrad error = namei_simple_user(SCARG(uap, path), NSM_FOLLOW_NOEMULROOT, 172 1.38 riastrad &path_vp); 173 1.38 riastrad if (error) 174 1.38 riastrad return error; 175 1.21 pooka 176 1.20 dholland file_vp = NULL; 177 1.1 thorpej if (SCARG(uap, filename) != NULL) { 178 1.23 dholland error = pathbuf_copyin(SCARG(uap, filename), &file_pb); 179 1.23 dholland if (error) { 180 1.23 dholland vrele(path_vp); 181 1.38 riastrad return error; 182 1.23 dholland } 183 1.23 dholland NDINIT(&file_nd, LOOKUP, FOLLOW | LOCKLEAF, file_pb); 184 1.20 dholland error = namei(&file_nd); 185 1.21 pooka if (error) { 186 1.23 dholland pathbuf_destroy(file_pb); 187 1.21 pooka vrele(path_vp); 188 1.38 riastrad return error; 189 1.21 pooka } 190 1.20 dholland file_vp = file_nd.ni_vp; 191 1.23 dholland pathbuf_destroy(file_pb); 192 1.1 thorpej } 193 1.1 thorpej 194 1.20 dholland error = VFS_EXTATTRCTL(path_vp->v_mount, SCARG(uap, cmd), file_vp, 195 1.1 thorpej SCARG(uap, attrnamespace), 196 1.13 pooka SCARG(uap, attrname) != NULL ? attrname : NULL); 197 1.1 thorpej 198 1.20 dholland if (file_vp != NULL) 199 1.20 dholland vrele(file_vp); 200 1.20 dholland vrele(path_vp); 201 1.1 thorpej 202 1.38 riastrad return error; 203 1.1 thorpej } 204 1.1 thorpej 205 1.1 thorpej /***************************************************************************** 206 1.1 thorpej * Internal routines to manipulate file system extended attributes: 207 1.1 thorpej * - set 208 1.1 thorpej * - get 209 1.1 thorpej * - delete 210 1.1 thorpej * - list 211 1.1 thorpej *****************************************************************************/ 212 1.1 thorpej 213 1.1 thorpej /* 214 1.1 thorpej * extattr_set_vp: 215 1.1 thorpej * 216 1.1 thorpej * Set a named extended attribute on a file or directory. 217 1.1 thorpej */ 218 1.1 thorpej static int 219 1.1 thorpej extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname, 220 1.24 manu const void *data, size_t nbytes, struct lwp *l, register_t *retval, 221 1.24 manu int flag) 222 1.1 thorpej { 223 1.1 thorpej struct uio auio; 224 1.1 thorpej struct iovec aiov; 225 1.1 thorpej ssize_t cnt; 226 1.1 thorpej int error; 227 1.1 thorpej 228 1.1 thorpej vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 229 1.1 thorpej 230 1.24 manu if (flag) { 231 1.24 manu size_t attrlen; 232 1.24 manu 233 1.24 manu error = VOP_GETEXTATTR(vp, attrnamespace, attrname, NULL, 234 1.38 riastrad &attrlen, l->l_cred); 235 1.24 manu 236 1.24 manu switch (error) { 237 1.31 manu case ENODATA: 238 1.39 bouyer case ENOATTR: 239 1.24 manu if (flag & XATTR_REPLACE) 240 1.24 manu goto done; 241 1.24 manu break; 242 1.24 manu case 0: 243 1.24 manu if (flag & XATTR_CREATE) { 244 1.41 riastrad error = SET_ERROR(EEXIST); 245 1.24 manu goto done; 246 1.24 manu } 247 1.24 manu break; 248 1.24 manu default: 249 1.24 manu goto done; 250 1.24 manu break; 251 1.24 manu } 252 1.24 manu } 253 1.24 manu 254 1.1 thorpej aiov.iov_base = __UNCONST(data); /* XXXUNCONST kills const */ 255 1.1 thorpej aiov.iov_len = nbytes; 256 1.1 thorpej auio.uio_iov = &aiov; 257 1.1 thorpej auio.uio_iovcnt = 1; 258 1.1 thorpej auio.uio_offset = 0; 259 1.1 thorpej if (nbytes > INT_MAX) { 260 1.41 riastrad error = SET_ERROR(EINVAL); 261 1.1 thorpej goto done; 262 1.1 thorpej } 263 1.1 thorpej auio.uio_resid = nbytes; 264 1.1 thorpej auio.uio_rw = UIO_WRITE; 265 1.5 yamt KASSERT(l == curlwp); 266 1.5 yamt auio.uio_vmspace = l->l_proc->p_vmspace; 267 1.1 thorpej cnt = nbytes; 268 1.1 thorpej 269 1.36 christos ktr_xattr_name(attrname); 270 1.36 christos ktr_xattr_val(data, nbytes); 271 1.28 manu 272 1.13 pooka error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio, l->l_cred); 273 1.1 thorpej cnt -= auio.uio_resid; 274 1.1 thorpej retval[0] = cnt; 275 1.1 thorpej 276 1.40 riastrad done: 277 1.22 hannken VOP_UNLOCK(vp); 278 1.38 riastrad return error; 279 1.1 thorpej } 280 1.1 thorpej 281 1.1 thorpej /* 282 1.1 thorpej * extattr_get_vp: 283 1.1 thorpej * 284 1.1 thorpej * Get a named extended attribute on a file or directory. 285 1.1 thorpej */ 286 1.1 thorpej static int 287 1.1 thorpej extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname, 288 1.4 christos void *data, size_t nbytes, struct lwp *l, register_t *retval) 289 1.1 thorpej { 290 1.1 thorpej struct uio auio, *auiop; 291 1.1 thorpej struct iovec aiov; 292 1.1 thorpej ssize_t cnt; 293 1.1 thorpej size_t size, *sizep; 294 1.1 thorpej int error; 295 1.1 thorpej 296 1.1 thorpej vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 297 1.1 thorpej 298 1.1 thorpej /* 299 1.1 thorpej * Slightly unusual semantics: if the user provides a NULL data 300 1.1 thorpej * pointer, they don't want to receive the data, just the maximum 301 1.1 thorpej * read length. 302 1.1 thorpej */ 303 1.1 thorpej auiop = NULL; 304 1.1 thorpej sizep = NULL; 305 1.1 thorpej cnt = 0; 306 1.1 thorpej if (data != NULL) { 307 1.1 thorpej aiov.iov_base = data; 308 1.1 thorpej aiov.iov_len = nbytes; 309 1.1 thorpej auio.uio_iov = &aiov; 310 1.37 riastrad auio.uio_iovcnt = 1; 311 1.1 thorpej auio.uio_offset = 0; 312 1.1 thorpej if (nbytes > INT_MAX) { 313 1.41 riastrad error = SET_ERROR(EINVAL); 314 1.1 thorpej goto done; 315 1.1 thorpej } 316 1.1 thorpej auio.uio_resid = nbytes; 317 1.1 thorpej auio.uio_rw = UIO_READ; 318 1.5 yamt KASSERT(l == curlwp); 319 1.5 yamt auio.uio_vmspace = l->l_proc->p_vmspace; 320 1.1 thorpej auiop = &auio; 321 1.1 thorpej cnt = nbytes; 322 1.1 thorpej } else 323 1.1 thorpej sizep = &size; 324 1.1 thorpej 325 1.36 christos ktr_xattr_name(attrname); 326 1.28 manu 327 1.1 thorpej error = VOP_GETEXTATTR(vp, attrnamespace, attrname, auiop, sizep, 328 1.13 pooka l->l_cred); 329 1.1 thorpej 330 1.1 thorpej if (auiop != NULL) { 331 1.1 thorpej cnt -= auio.uio_resid; 332 1.1 thorpej retval[0] = cnt; 333 1.28 manu 334 1.36 christos ktr_xattr_val(data, cnt); 335 1.1 thorpej } else 336 1.1 thorpej retval[0] = size; 337 1.1 thorpej 338 1.40 riastrad done: 339 1.22 hannken VOP_UNLOCK(vp); 340 1.38 riastrad return error; 341 1.1 thorpej } 342 1.1 thorpej 343 1.1 thorpej /* 344 1.1 thorpej * extattr_delete_vp: 345 1.1 thorpej * 346 1.1 thorpej * Delete a named extended attribute on a file or directory. 347 1.1 thorpej */ 348 1.1 thorpej static int 349 1.1 thorpej extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname, 350 1.4 christos struct lwp *l) 351 1.1 thorpej { 352 1.1 thorpej int error; 353 1.1 thorpej 354 1.1 thorpej vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 355 1.1 thorpej 356 1.36 christos ktr_xattr_name(attrname); 357 1.28 manu 358 1.13 pooka error = VOP_DELETEEXTATTR(vp, attrnamespace, attrname, l->l_cred); 359 1.1 thorpej if (error == EOPNOTSUPP) 360 1.1 thorpej error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL, 361 1.13 pooka l->l_cred); 362 1.1 thorpej 363 1.22 hannken VOP_UNLOCK(vp); 364 1.38 riastrad return error; 365 1.1 thorpej } 366 1.1 thorpej 367 1.1 thorpej /* 368 1.1 thorpej * extattr_list_vp: 369 1.1 thorpej * 370 1.1 thorpej * Retrieve a list of extended attributes on a file or directory. 371 1.1 thorpej */ 372 1.1 thorpej static int 373 1.1 thorpej extattr_list_vp(struct vnode *vp, int attrnamespace, void *data, size_t nbytes, 374 1.27 manu int flag, struct lwp *l, register_t *retval) 375 1.1 thorpej { 376 1.1 thorpej struct uio auio, *auiop; 377 1.1 thorpej size_t size, *sizep; 378 1.1 thorpej struct iovec aiov; 379 1.1 thorpej ssize_t cnt; 380 1.1 thorpej int error; 381 1.1 thorpej 382 1.1 thorpej vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 383 1.1 thorpej 384 1.1 thorpej auiop = NULL; 385 1.1 thorpej sizep = NULL; 386 1.1 thorpej cnt = 0; 387 1.1 thorpej if (data != NULL) { 388 1.1 thorpej aiov.iov_base = data; 389 1.1 thorpej aiov.iov_len = nbytes; 390 1.1 thorpej auio.uio_iov = &aiov; 391 1.37 riastrad auio.uio_iovcnt = 1; 392 1.1 thorpej auio.uio_offset = 0; 393 1.1 thorpej if (nbytes > INT_MAX) { 394 1.41 riastrad error = SET_ERROR(EINVAL); 395 1.1 thorpej goto done; 396 1.1 thorpej } 397 1.1 thorpej auio.uio_resid = nbytes; 398 1.1 thorpej auio.uio_rw = UIO_READ; 399 1.5 yamt KASSERT(l == curlwp); 400 1.5 yamt auio.uio_vmspace = l->l_proc->p_vmspace; 401 1.1 thorpej auiop = &auio; 402 1.1 thorpej cnt = nbytes; 403 1.1 thorpej } else 404 1.1 thorpej sizep = &size; 405 1.1 thorpej 406 1.38 riastrad error = VOP_LISTEXTATTR(vp, attrnamespace, auiop, sizep, flag, 407 1.38 riastrad l->l_cred); 408 1.1 thorpej 409 1.1 thorpej if (auiop != NULL) { 410 1.1 thorpej cnt -= auio.uio_resid; 411 1.1 thorpej retval[0] = cnt; 412 1.28 manu 413 1.34 christos ktruser("xattr-list", data, cnt, 0); 414 1.1 thorpej } else 415 1.1 thorpej retval[0] = size; 416 1.1 thorpej 417 1.40 riastrad done: 418 1.22 hannken VOP_UNLOCK(vp); 419 1.38 riastrad return error; 420 1.1 thorpej } 421 1.1 thorpej 422 1.1 thorpej /***************************************************************************** 423 1.1 thorpej * BSD <sys/extattr.h> API for file system extended attributes 424 1.1 thorpej *****************************************************************************/ 425 1.1 thorpej 426 1.1 thorpej int 427 1.38 riastrad sys_extattr_set_fd(struct lwp *l, const struct sys_extattr_set_fd_args *uap, 428 1.38 riastrad register_t *retval) 429 1.1 thorpej { 430 1.15 dsl /* { 431 1.1 thorpej syscallarg(int) fd; 432 1.1 thorpej syscallarg(int) attrnamespace; 433 1.1 thorpej syscallarg(const char *) attrname; 434 1.1 thorpej syscallarg(const void *) data; 435 1.1 thorpej syscallarg(size_t) nbytes; 436 1.15 dsl } */ 437 1.1 thorpej struct file *fp; 438 1.1 thorpej struct vnode *vp; 439 1.1 thorpej char attrname[EXTATTR_MAXNAMELEN]; 440 1.1 thorpej int error; 441 1.1 thorpej 442 1.1 thorpej error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname), 443 1.1 thorpej NULL); 444 1.1 thorpej if (error) 445 1.38 riastrad return error; 446 1.1 thorpej 447 1.19 ad error = fd_getvnode(SCARG(uap, fd), &fp); 448 1.1 thorpej if (error) 449 1.38 riastrad return error; 450 1.33 matt vp = fp->f_vnode; 451 1.1 thorpej 452 1.1 thorpej error = extattr_set_vp(vp, SCARG(uap, attrnamespace), attrname, 453 1.24 manu SCARG(uap, data), SCARG(uap, nbytes), l, retval, 0); 454 1.1 thorpej 455 1.17 ad fd_putfile(SCARG(uap, fd)); 456 1.38 riastrad return error; 457 1.1 thorpej } 458 1.1 thorpej 459 1.1 thorpej int 460 1.38 riastrad sys_extattr_set_file(struct lwp *l, 461 1.38 riastrad const struct sys_extattr_set_file_args *uap, 462 1.38 riastrad register_t *retval) 463 1.1 thorpej { 464 1.15 dsl /* { 465 1.1 thorpej syscallarg(const char *) path; 466 1.1 thorpej syscallarg(int) attrnamespace; 467 1.1 thorpej syscallarg(const char *) attrname; 468 1.1 thorpej syscallarg(const void *) data; 469 1.1 thorpej syscallarg(size_t) nbytes; 470 1.15 dsl } */ 471 1.20 dholland struct vnode *vp; 472 1.1 thorpej char attrname[EXTATTR_MAXNAMELEN]; 473 1.1 thorpej int error; 474 1.1 thorpej 475 1.1 thorpej error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname), 476 1.1 thorpej NULL); 477 1.1 thorpej if (error) 478 1.38 riastrad return error; 479 1.1 thorpej 480 1.38 riastrad error = namei_simple_user(SCARG(uap, path), NSM_FOLLOW_NOEMULROOT, 481 1.38 riastrad &vp); 482 1.1 thorpej if (error) 483 1.38 riastrad return error; 484 1.1 thorpej 485 1.20 dholland error = extattr_set_vp(vp, SCARG(uap, attrnamespace), attrname, 486 1.24 manu SCARG(uap, data), SCARG(uap, nbytes), l, retval, 0); 487 1.1 thorpej 488 1.20 dholland vrele(vp); 489 1.38 riastrad return error; 490 1.1 thorpej } 491 1.1 thorpej 492 1.1 thorpej int 493 1.38 riastrad sys_extattr_set_link(struct lwp *l, 494 1.38 riastrad const struct sys_extattr_set_link_args *uap, 495 1.38 riastrad register_t *retval) 496 1.1 thorpej { 497 1.15 dsl /* { 498 1.1 thorpej syscallarg(const char *) path; 499 1.1 thorpej syscallarg(int) attrnamespace; 500 1.1 thorpej syscallarg(const char *) attrname; 501 1.1 thorpej syscallarg(const void *) data; 502 1.1 thorpej syscallarg(size_t) nbytes; 503 1.15 dsl } */ 504 1.20 dholland struct vnode *vp; 505 1.1 thorpej char attrname[EXTATTR_MAXNAMELEN]; 506 1.1 thorpej int error; 507 1.1 thorpej 508 1.1 thorpej error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname), 509 1.1 thorpej NULL); 510 1.1 thorpej if (error) 511 1.38 riastrad return error; 512 1.1 thorpej 513 1.38 riastrad error = namei_simple_user(SCARG(uap, path), NSM_NOFOLLOW_NOEMULROOT, 514 1.38 riastrad &vp); 515 1.1 thorpej if (error) 516 1.38 riastrad return error; 517 1.1 thorpej 518 1.20 dholland error = extattr_set_vp(vp, SCARG(uap, attrnamespace), attrname, 519 1.24 manu SCARG(uap, data), SCARG(uap, nbytes), l, retval, 0); 520 1.1 thorpej 521 1.20 dholland vrele(vp); 522 1.38 riastrad return error; 523 1.1 thorpej } 524 1.1 thorpej 525 1.1 thorpej int 526 1.38 riastrad sys_extattr_get_fd(struct lwp *l, 527 1.38 riastrad const struct sys_extattr_get_fd_args *uap, 528 1.38 riastrad register_t *retval) 529 1.1 thorpej { 530 1.15 dsl /* { 531 1.1 thorpej syscallarg(int) fd; 532 1.1 thorpej syscallarg(int) attrnamespace; 533 1.1 thorpej syscallarg(const char *) attrname; 534 1.1 thorpej syscallarg(void *) data; 535 1.1 thorpej syscallarg(size_t) nbytes; 536 1.15 dsl } */ 537 1.1 thorpej struct file *fp; 538 1.1 thorpej struct vnode *vp; 539 1.1 thorpej char attrname[EXTATTR_MAXNAMELEN]; 540 1.1 thorpej int error; 541 1.1 thorpej 542 1.1 thorpej error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname), 543 1.1 thorpej NULL); 544 1.1 thorpej if (error) 545 1.38 riastrad return error; 546 1.1 thorpej 547 1.19 ad error = fd_getvnode(SCARG(uap, fd), &fp); 548 1.1 thorpej if (error) 549 1.38 riastrad return error; 550 1.33 matt vp = fp->f_vnode; 551 1.1 thorpej 552 1.1 thorpej error = extattr_get_vp(vp, SCARG(uap, attrnamespace), attrname, 553 1.4 christos SCARG(uap, data), SCARG(uap, nbytes), l, retval); 554 1.1 thorpej 555 1.17 ad fd_putfile(SCARG(uap, fd)); 556 1.38 riastrad return error; 557 1.1 thorpej } 558 1.1 thorpej 559 1.1 thorpej int 560 1.38 riastrad sys_extattr_get_file(struct lwp *l, 561 1.38 riastrad const struct sys_extattr_get_file_args *uap, 562 1.38 riastrad register_t *retval) 563 1.1 thorpej { 564 1.15 dsl /* { 565 1.1 thorpej syscallarg(const char *) path; 566 1.1 thorpej syscallarg(int) attrnamespace; 567 1.1 thorpej syscallarg(const char *) attrname; 568 1.1 thorpej syscallarg(void *) data; 569 1.1 thorpej syscallarg(size_t) nbytes; 570 1.15 dsl } */ 571 1.20 dholland struct vnode *vp; 572 1.1 thorpej char attrname[EXTATTR_MAXNAMELEN]; 573 1.1 thorpej int error; 574 1.1 thorpej 575 1.1 thorpej error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname), 576 1.1 thorpej NULL); 577 1.1 thorpej if (error) 578 1.38 riastrad return error; 579 1.1 thorpej 580 1.38 riastrad error = namei_simple_user(SCARG(uap, path), NSM_FOLLOW_NOEMULROOT, 581 1.38 riastrad &vp); 582 1.1 thorpej if (error) 583 1.38 riastrad return error; 584 1.1 thorpej 585 1.20 dholland error = extattr_get_vp(vp, SCARG(uap, attrnamespace), attrname, 586 1.4 christos SCARG(uap, data), SCARG(uap, nbytes), l, retval); 587 1.1 thorpej 588 1.20 dholland vrele(vp); 589 1.38 riastrad return error; 590 1.1 thorpej } 591 1.1 thorpej 592 1.1 thorpej int 593 1.38 riastrad sys_extattr_get_link(struct lwp *l, 594 1.38 riastrad const struct sys_extattr_get_link_args *uap, 595 1.38 riastrad register_t *retval) 596 1.1 thorpej { 597 1.15 dsl /* { 598 1.1 thorpej syscallarg(const char *) path; 599 1.1 thorpej syscallarg(int) attrnamespace; 600 1.1 thorpej syscallarg(const char *) attrname; 601 1.1 thorpej syscallarg(void *) data; 602 1.1 thorpej syscallarg(size_t) nbytes; 603 1.15 dsl } */ 604 1.20 dholland struct vnode *vp; 605 1.1 thorpej char attrname[EXTATTR_MAXNAMELEN]; 606 1.1 thorpej int error; 607 1.1 thorpej 608 1.1 thorpej error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname), 609 1.1 thorpej NULL); 610 1.1 thorpej if (error) 611 1.38 riastrad return error; 612 1.1 thorpej 613 1.38 riastrad error = namei_simple_user(SCARG(uap, path), NSM_NOFOLLOW_NOEMULROOT, 614 1.38 riastrad &vp); 615 1.1 thorpej if (error) 616 1.38 riastrad return error; 617 1.1 thorpej 618 1.20 dholland error = extattr_get_vp(vp, SCARG(uap, attrnamespace), attrname, 619 1.4 christos SCARG(uap, data), SCARG(uap, nbytes), l, retval); 620 1.1 thorpej 621 1.20 dholland vrele(vp); 622 1.38 riastrad return error; 623 1.1 thorpej } 624 1.1 thorpej 625 1.1 thorpej int 626 1.38 riastrad sys_extattr_delete_fd(struct lwp *l, 627 1.38 riastrad const struct sys_extattr_delete_fd_args *uap, 628 1.38 riastrad register_t *retval) 629 1.1 thorpej { 630 1.15 dsl /* { 631 1.1 thorpej syscallarg(int) fd; 632 1.1 thorpej syscallarg(int) attrnamespace; 633 1.1 thorpej syscallarg(const char *) attrname; 634 1.15 dsl } */ 635 1.1 thorpej struct file *fp; 636 1.1 thorpej struct vnode *vp; 637 1.1 thorpej char attrname[EXTATTR_MAXNAMELEN]; 638 1.1 thorpej int error; 639 1.1 thorpej 640 1.1 thorpej error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname), 641 1.1 thorpej NULL); 642 1.1 thorpej if (error) 643 1.38 riastrad return error; 644 1.1 thorpej 645 1.19 ad error = fd_getvnode(SCARG(uap, fd), &fp); 646 1.1 thorpej if (error) 647 1.38 riastrad return error; 648 1.33 matt vp = fp->f_vnode; 649 1.1 thorpej 650 1.4 christos error = extattr_delete_vp(vp, SCARG(uap, attrnamespace), attrname, l); 651 1.1 thorpej 652 1.17 ad fd_putfile(SCARG(uap, fd)); 653 1.38 riastrad return error; 654 1.1 thorpej } 655 1.1 thorpej 656 1.1 thorpej int 657 1.38 riastrad sys_extattr_delete_file(struct lwp *l, 658 1.38 riastrad const struct sys_extattr_delete_file_args *uap, 659 1.38 riastrad register_t *retval) 660 1.1 thorpej { 661 1.15 dsl /* { 662 1.1 thorpej syscallarg(const char *) path; 663 1.1 thorpej syscallarg(int) attrnamespace; 664 1.1 thorpej syscallarg(const char *) attrname; 665 1.15 dsl } */ 666 1.20 dholland struct vnode *vp; 667 1.1 thorpej char attrname[EXTATTR_MAXNAMELEN]; 668 1.1 thorpej int error; 669 1.1 thorpej 670 1.1 thorpej error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname), 671 1.1 thorpej NULL); 672 1.1 thorpej if (error) 673 1.38 riastrad return error; 674 1.1 thorpej 675 1.38 riastrad error = namei_simple_user(SCARG(uap, path), NSM_FOLLOW_NOEMULROOT, 676 1.38 riastrad &vp); 677 1.1 thorpej if (error) 678 1.38 riastrad return error; 679 1.1 thorpej 680 1.20 dholland error = extattr_delete_vp(vp, SCARG(uap, attrnamespace), attrname, l); 681 1.1 thorpej 682 1.20 dholland vrele(vp); 683 1.38 riastrad return error; 684 1.1 thorpej } 685 1.1 thorpej 686 1.1 thorpej int 687 1.38 riastrad sys_extattr_delete_link(struct lwp *l, 688 1.38 riastrad const struct sys_extattr_delete_link_args *uap, 689 1.38 riastrad register_t *retval) 690 1.1 thorpej { 691 1.15 dsl /* { 692 1.1 thorpej syscallarg(const char *) path; 693 1.1 thorpej syscallarg(int) attrnamespace; 694 1.1 thorpej syscallarg(const char *) attrname; 695 1.15 dsl } */ 696 1.20 dholland struct vnode *vp; 697 1.1 thorpej char attrname[EXTATTR_MAXNAMELEN]; 698 1.1 thorpej int error; 699 1.1 thorpej 700 1.1 thorpej error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname), 701 1.1 thorpej NULL); 702 1.1 thorpej if (error) 703 1.38 riastrad return error; 704 1.1 thorpej 705 1.38 riastrad error = namei_simple_user(SCARG(uap, path), NSM_NOFOLLOW_NOEMULROOT, 706 1.38 riastrad &vp); 707 1.1 thorpej if (error) 708 1.38 riastrad return error; 709 1.1 thorpej 710 1.20 dholland error = extattr_delete_vp(vp, SCARG(uap, attrnamespace), attrname, l); 711 1.1 thorpej 712 1.20 dholland vrele(vp); 713 1.38 riastrad return error; 714 1.1 thorpej } 715 1.1 thorpej 716 1.1 thorpej int 717 1.38 riastrad sys_extattr_list_fd(struct lwp *l, 718 1.38 riastrad const struct sys_extattr_list_fd_args *uap, 719 1.38 riastrad register_t *retval) 720 1.1 thorpej { 721 1.15 dsl /* { 722 1.1 thorpej syscallarg(int) fd; 723 1.1 thorpej syscallarg(int) attrnamespace; 724 1.1 thorpej syscallarg(void *) data; 725 1.1 thorpej syscallarg(size_t) nbytes; 726 1.15 dsl } */ 727 1.1 thorpej struct file *fp; 728 1.1 thorpej struct vnode *vp; 729 1.1 thorpej int error; 730 1.1 thorpej 731 1.19 ad error = fd_getvnode(SCARG(uap, fd), &fp); 732 1.1 thorpej if (error) 733 1.38 riastrad return error; 734 1.33 matt vp = fp->f_vnode; 735 1.1 thorpej 736 1.1 thorpej error = extattr_list_vp(vp, SCARG(uap, attrnamespace), 737 1.27 manu SCARG(uap, data), SCARG(uap, nbytes), 738 1.27 manu EXTATTR_LIST_LENPREFIX, l, retval); 739 1.1 thorpej 740 1.17 ad fd_putfile(SCARG(uap, fd)); 741 1.38 riastrad return error; 742 1.1 thorpej } 743 1.1 thorpej 744 1.1 thorpej int 745 1.38 riastrad sys_extattr_list_file(struct lwp *l, 746 1.38 riastrad const struct sys_extattr_list_file_args *uap, 747 1.38 riastrad register_t *retval) 748 1.1 thorpej { 749 1.15 dsl /* { 750 1.1 thorpej syscallarg(const char *) path; 751 1.1 thorpej syscallarg(int) attrnamespace; 752 1.1 thorpej syscallarg(void *) data; 753 1.1 thorpej syscallarg(size_t) nbytes; 754 1.15 dsl } */ 755 1.20 dholland struct vnode *vp; 756 1.1 thorpej int error; 757 1.1 thorpej 758 1.38 riastrad error = namei_simple_user(SCARG(uap, path), NSM_FOLLOW_NOEMULROOT, 759 1.38 riastrad &vp); 760 1.1 thorpej if (error) 761 1.38 riastrad return error; 762 1.1 thorpej 763 1.20 dholland error = extattr_list_vp(vp, SCARG(uap, attrnamespace), 764 1.27 manu SCARG(uap, data), SCARG(uap, nbytes), 765 1.27 manu EXTATTR_LIST_LENPREFIX, l, retval); 766 1.1 thorpej 767 1.20 dholland vrele(vp); 768 1.38 riastrad return error; 769 1.1 thorpej } 770 1.1 thorpej 771 1.1 thorpej int 772 1.38 riastrad sys_extattr_list_link(struct lwp *l, 773 1.38 riastrad const struct sys_extattr_list_link_args *uap, 774 1.38 riastrad register_t *retval) 775 1.1 thorpej { 776 1.15 dsl /* { 777 1.1 thorpej syscallarg(const char *) path; 778 1.1 thorpej syscallarg(int) attrnamespace; 779 1.1 thorpej syscallarg(void *) data; 780 1.1 thorpej syscallarg(size_t) nbytes; 781 1.15 dsl } */ 782 1.20 dholland struct vnode *vp; 783 1.1 thorpej int error; 784 1.1 thorpej 785 1.38 riastrad error = namei_simple_user(SCARG(uap, path), NSM_NOFOLLOW_NOEMULROOT, 786 1.38 riastrad &vp); 787 1.1 thorpej if (error) 788 1.38 riastrad return error; 789 1.1 thorpej 790 1.20 dholland error = extattr_list_vp(vp, SCARG(uap, attrnamespace), 791 1.27 manu SCARG(uap, data), SCARG(uap, nbytes), 792 1.27 manu EXTATTR_LIST_LENPREFIX, l, retval); 793 1.1 thorpej 794 1.20 dholland vrele(vp); 795 1.38 riastrad return error; 796 1.1 thorpej } 797 1.2 thorpej 798 1.2 thorpej /***************************************************************************** 799 1.2 thorpej * Linux-compatible <sys/xattr.h> API for file system extended attributes 800 1.2 thorpej *****************************************************************************/ 801 1.2 thorpej 802 1.24 manu #define MATCH_NS(ns, key) (strncmp(ns, key, sizeof(ns) - 1) == 0) 803 1.24 manu static int 804 1.38 riastrad xattr_native(const char *key) 805 1.38 riastrad { 806 1.38 riastrad 807 1.24 manu if (MATCH_NS("system.", key)) 808 1.24 manu return EXTATTR_NAMESPACE_SYSTEM; 809 1.24 manu else if (MATCH_NS("user.", key)) 810 1.24 manu return EXTATTR_NAMESPACE_USER; 811 1.24 manu else if (MATCH_NS("security.", key)) 812 1.24 manu return EXTATTR_NAMESPACE_SYSTEM; 813 1.24 manu else if (MATCH_NS("trusted.", key)) 814 1.24 manu return EXTATTR_NAMESPACE_SYSTEM; 815 1.38 riastrad else 816 1.24 manu return EXTATTR_NAMESPACE_USER; 817 1.24 manu } 818 1.24 manu #undef MATCH_NS 819 1.24 manu 820 1.41 riastrad #define XATTR_ERRNO(e) ((e) == EOPNOTSUPP ? SET_ERROR(ENOTSUP) : (e)) 821 1.29 drochner 822 1.2 thorpej int 823 1.38 riastrad sys_setxattr(struct lwp *l, 824 1.38 riastrad const struct sys_setxattr_args *uap, 825 1.38 riastrad register_t *retval) 826 1.2 thorpej { 827 1.15 dsl /* { 828 1.2 thorpej syscallarg(const char *) path; 829 1.2 thorpej syscallarg(const char *) name; 830 1.2 thorpej syscallarg(void *) value; 831 1.2 thorpej syscallarg(size_t) size; 832 1.2 thorpej syscallarg(int) flags; 833 1.15 dsl } */ 834 1.20 dholland struct vnode *vp; 835 1.2 thorpej char attrname[XATTR_NAME_MAX]; 836 1.32 matt int attrnamespace; 837 1.24 manu register_t attrlen; 838 1.2 thorpej int error; 839 1.2 thorpej 840 1.2 thorpej error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname), 841 1.2 thorpej NULL); 842 1.2 thorpej if (error) 843 1.24 manu goto out; 844 1.2 thorpej 845 1.20 dholland error = namei_simple_user(SCARG(uap, path), 846 1.38 riastrad NSM_FOLLOW_NOEMULROOT, &vp); 847 1.2 thorpej if (error) 848 1.26 manu goto out; 849 1.2 thorpej 850 1.32 matt attrnamespace = xattr_native(attrname); 851 1.2 thorpej 852 1.32 matt error = extattr_set_vp(vp, attrnamespace, 853 1.38 riastrad attrname, SCARG(uap, value), SCARG(uap, size), l, 854 1.24 manu &attrlen, SCARG(uap, flags)); 855 1.2 thorpej 856 1.20 dholland vrele(vp); 857 1.24 manu out: 858 1.38 riastrad *retval = (error == 0 ? 0 : -1); 859 1.38 riastrad return XATTR_ERRNO(error); 860 1.2 thorpej } 861 1.2 thorpej 862 1.2 thorpej int 863 1.38 riastrad sys_lsetxattr(struct lwp *l, 864 1.38 riastrad const struct sys_lsetxattr_args *uap, 865 1.38 riastrad register_t *retval) 866 1.2 thorpej { 867 1.15 dsl /* { 868 1.2 thorpej syscallarg(const char *) path; 869 1.2 thorpej syscallarg(const char *) name; 870 1.2 thorpej syscallarg(void *) value; 871 1.2 thorpej syscallarg(size_t) size; 872 1.2 thorpej syscallarg(int) flags; 873 1.15 dsl } */ 874 1.20 dholland struct vnode *vp; 875 1.2 thorpej char attrname[XATTR_NAME_MAX]; 876 1.32 matt int attrnamespace; 877 1.24 manu register_t attrlen; 878 1.2 thorpej int error; 879 1.2 thorpej 880 1.2 thorpej error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname), 881 1.2 thorpej NULL); 882 1.2 thorpej if (error) 883 1.24 manu goto out; 884 1.2 thorpej 885 1.38 riastrad error = namei_simple_user(SCARG(uap, path), NSM_NOFOLLOW_NOEMULROOT, 886 1.38 riastrad &vp); 887 1.2 thorpej if (error) 888 1.26 manu goto out; 889 1.2 thorpej 890 1.32 matt attrnamespace = xattr_native(attrname); 891 1.2 thorpej 892 1.32 matt error = extattr_set_vp(vp, attrnamespace, 893 1.24 manu attrname, SCARG(uap, value), SCARG(uap, size), l, 894 1.24 manu &attrlen, SCARG(uap, flags)); 895 1.2 thorpej 896 1.20 dholland vrele(vp); 897 1.24 manu out: 898 1.38 riastrad *retval = (error == 0 ? 0 : -1); 899 1.38 riastrad return XATTR_ERRNO(error); 900 1.2 thorpej } 901 1.2 thorpej 902 1.2 thorpej int 903 1.38 riastrad sys_fsetxattr(struct lwp *l, 904 1.38 riastrad const struct sys_fsetxattr_args *uap, 905 1.38 riastrad register_t *retval) 906 1.2 thorpej { 907 1.15 dsl /* { 908 1.2 thorpej syscallarg(int) fd; 909 1.2 thorpej syscallarg(const char *) name; 910 1.2 thorpej syscallarg(void *) value; 911 1.2 thorpej syscallarg(size_t) size; 912 1.2 thorpej syscallarg(int) flags; 913 1.15 dsl } */ 914 1.2 thorpej struct file *fp; 915 1.2 thorpej struct vnode *vp; 916 1.2 thorpej char attrname[XATTR_NAME_MAX]; 917 1.32 matt int attrnamespace; 918 1.24 manu register_t attrlen; 919 1.2 thorpej int error; 920 1.2 thorpej 921 1.2 thorpej error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname), 922 1.2 thorpej NULL); 923 1.2 thorpej if (error) 924 1.24 manu goto out; 925 1.2 thorpej 926 1.19 ad error = fd_getvnode(SCARG(uap, fd), &fp); 927 1.2 thorpej if (error) 928 1.24 manu goto out; 929 1.33 matt vp = fp->f_vnode; 930 1.2 thorpej 931 1.32 matt attrnamespace = xattr_native(attrname); 932 1.2 thorpej 933 1.32 matt error = extattr_set_vp(vp, attrnamespace, 934 1.24 manu attrname, SCARG(uap, value), SCARG(uap, size), l, 935 1.24 manu &attrlen, SCARG(uap, flags)); 936 1.2 thorpej 937 1.17 ad fd_putfile(SCARG(uap, fd)); 938 1.24 manu out: 939 1.38 riastrad *retval = (error == 0 ? 0 : -1); 940 1.38 riastrad return XATTR_ERRNO(error); 941 1.2 thorpej } 942 1.2 thorpej 943 1.2 thorpej int 944 1.38 riastrad sys_getxattr(struct lwp *l, 945 1.38 riastrad const struct sys_getxattr_args *uap, 946 1.38 riastrad register_t *retval) 947 1.2 thorpej { 948 1.15 dsl /* { 949 1.2 thorpej syscallarg(const char *) path; 950 1.2 thorpej syscallarg(const char *) name; 951 1.2 thorpej syscallarg(void *) value; 952 1.2 thorpej syscallarg(size_t) size; 953 1.15 dsl } */ 954 1.20 dholland struct vnode *vp; 955 1.2 thorpej char attrname[XATTR_NAME_MAX]; 956 1.32 matt int attrnamespace; 957 1.2 thorpej int error; 958 1.2 thorpej 959 1.2 thorpej error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname), 960 1.2 thorpej NULL); 961 1.2 thorpej if (error) 962 1.38 riastrad return error; 963 1.2 thorpej 964 1.38 riastrad error = namei_simple_user(SCARG(uap, path), NSM_FOLLOW_NOEMULROOT, 965 1.38 riastrad &vp); 966 1.2 thorpej if (error) 967 1.38 riastrad return error; 968 1.2 thorpej 969 1.32 matt attrnamespace = xattr_native(attrname); 970 1.24 manu 971 1.32 matt error = extattr_get_vp(vp, attrnamespace, 972 1.4 christos attrname, SCARG(uap, value), SCARG(uap, size), l, retval); 973 1.2 thorpej 974 1.20 dholland vrele(vp); 975 1.38 riastrad return XATTR_ERRNO(error); 976 1.2 thorpej } 977 1.2 thorpej 978 1.2 thorpej int 979 1.38 riastrad sys_lgetxattr(struct lwp *l, 980 1.38 riastrad const struct sys_lgetxattr_args *uap, 981 1.38 riastrad register_t *retval) 982 1.2 thorpej { 983 1.15 dsl /* { 984 1.2 thorpej syscallarg(const char *) path; 985 1.2 thorpej syscallarg(const char *) name; 986 1.2 thorpej syscallarg(void *) value; 987 1.2 thorpej syscallarg(size_t) size; 988 1.15 dsl } */ 989 1.20 dholland struct vnode *vp; 990 1.2 thorpej char attrname[XATTR_NAME_MAX]; 991 1.32 matt int attrnamespace; 992 1.2 thorpej int error; 993 1.2 thorpej 994 1.2 thorpej error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname), 995 1.2 thorpej NULL); 996 1.2 thorpej if (error) 997 1.38 riastrad return error; 998 1.2 thorpej 999 1.38 riastrad error = namei_simple_user(SCARG(uap, path), NSM_NOFOLLOW_NOEMULROOT, 1000 1.38 riastrad &vp); 1001 1.2 thorpej if (error) 1002 1.38 riastrad return error; 1003 1.2 thorpej 1004 1.32 matt attrnamespace = xattr_native(attrname); 1005 1.24 manu 1006 1.32 matt error = extattr_get_vp(vp, attrnamespace, 1007 1.4 christos attrname, SCARG(uap, value), SCARG(uap, size), l, retval); 1008 1.2 thorpej 1009 1.20 dholland vrele(vp); 1010 1.38 riastrad return XATTR_ERRNO(error); 1011 1.2 thorpej } 1012 1.2 thorpej 1013 1.2 thorpej int 1014 1.38 riastrad sys_fgetxattr(struct lwp *l, 1015 1.38 riastrad const struct sys_fgetxattr_args *uap, 1016 1.38 riastrad register_t *retval) 1017 1.2 thorpej { 1018 1.15 dsl /* { 1019 1.2 thorpej syscallarg(int) fd; 1020 1.2 thorpej syscallarg(const char *) name; 1021 1.2 thorpej syscallarg(void *) value; 1022 1.2 thorpej syscallarg(size_t) size; 1023 1.15 dsl } */ 1024 1.2 thorpej struct file *fp; 1025 1.2 thorpej struct vnode *vp; 1026 1.2 thorpej char attrname[XATTR_NAME_MAX]; 1027 1.32 matt int attrnamespace; 1028 1.2 thorpej int error; 1029 1.2 thorpej 1030 1.2 thorpej error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname), 1031 1.2 thorpej NULL); 1032 1.2 thorpej if (error) 1033 1.38 riastrad return error; 1034 1.2 thorpej 1035 1.19 ad error = fd_getvnode(SCARG(uap, fd), &fp); 1036 1.2 thorpej if (error) 1037 1.38 riastrad return error; 1038 1.33 matt vp = fp->f_vnode; 1039 1.2 thorpej 1040 1.32 matt attrnamespace = xattr_native(attrname); 1041 1.24 manu 1042 1.32 matt error = extattr_get_vp(vp, attrnamespace, 1043 1.4 christos attrname, SCARG(uap, value), SCARG(uap, size), l, retval); 1044 1.2 thorpej 1045 1.17 ad fd_putfile(SCARG(uap, fd)); 1046 1.38 riastrad return XATTR_ERRNO(error); 1047 1.2 thorpej } 1048 1.2 thorpej 1049 1.2 thorpej int 1050 1.38 riastrad sys_listxattr(struct lwp *l, 1051 1.38 riastrad const struct sys_listxattr_args *uap, 1052 1.38 riastrad register_t *retval) 1053 1.2 thorpej { 1054 1.15 dsl /* { 1055 1.2 thorpej syscallarg(const char *) path; 1056 1.2 thorpej syscallarg(char *) list; 1057 1.2 thorpej syscallarg(size_t) size; 1058 1.15 dsl } */ 1059 1.20 dholland struct vnode *vp; 1060 1.24 manu char *list; 1061 1.24 manu size_t size; 1062 1.24 manu register_t listsize_usr, listsize_sys; 1063 1.2 thorpej int error; 1064 1.2 thorpej 1065 1.38 riastrad error = namei_simple_user(SCARG(uap, path), NSM_FOLLOW_NOEMULROOT, 1066 1.38 riastrad &vp); 1067 1.2 thorpej if (error) 1068 1.38 riastrad return error; 1069 1.2 thorpej 1070 1.24 manu list = SCARG(uap, list); 1071 1.24 manu size = SCARG(uap, size); 1072 1.24 manu 1073 1.20 dholland error = extattr_list_vp(vp, EXTATTR_NAMESPACE_USER, 1074 1.27 manu list, size, 0, l, &listsize_usr); 1075 1.24 manu if (error) 1076 1.24 manu goto out; 1077 1.24 manu 1078 1.24 manu if (list) 1079 1.24 manu list += listsize_usr; 1080 1.24 manu if (size) 1081 1.24 manu size -= listsize_usr; 1082 1.2 thorpej 1083 1.24 manu error = extattr_list_vp(vp, EXTATTR_NAMESPACE_SYSTEM, 1084 1.27 manu list, size, 0, l, &listsize_sys); 1085 1.25 manu switch (error) { 1086 1.25 manu case EPERM: 1087 1.25 manu error = 0; /* Ignore and just skip system EA */ 1088 1.25 manu listsize_sys = 0; 1089 1.25 manu break; 1090 1.25 manu case 0: 1091 1.25 manu break; 1092 1.38 riastrad default: 1093 1.24 manu goto out; 1094 1.25 manu break; 1095 1.25 manu } 1096 1.24 manu 1097 1.38 riastrad *retval = listsize_usr + listsize_sys; 1098 1.24 manu out: 1099 1.20 dholland vrele(vp); 1100 1.38 riastrad return XATTR_ERRNO(error); 1101 1.2 thorpej } 1102 1.2 thorpej 1103 1.2 thorpej int 1104 1.38 riastrad sys_llistxattr(struct lwp *l, 1105 1.38 riastrad const struct sys_llistxattr_args *uap, 1106 1.38 riastrad register_t *retval) 1107 1.2 thorpej { 1108 1.15 dsl /* { 1109 1.2 thorpej syscallarg(const char *) path; 1110 1.2 thorpej syscallarg(char *) list; 1111 1.2 thorpej syscallarg(size_t) size; 1112 1.15 dsl } */ 1113 1.20 dholland struct vnode *vp; 1114 1.24 manu char *list; 1115 1.24 manu size_t size; 1116 1.24 manu register_t listsize_usr, listsize_sys; 1117 1.2 thorpej int error; 1118 1.2 thorpej 1119 1.38 riastrad error = namei_simple_user(SCARG(uap, path), NSM_NOFOLLOW_NOEMULROOT, 1120 1.38 riastrad &vp); 1121 1.2 thorpej if (error) 1122 1.38 riastrad return error; 1123 1.2 thorpej 1124 1.24 manu list = SCARG(uap, list); 1125 1.24 manu size = SCARG(uap, size); 1126 1.24 manu 1127 1.20 dholland error = extattr_list_vp(vp, EXTATTR_NAMESPACE_USER, 1128 1.27 manu list, size, 0, l, &listsize_usr); 1129 1.24 manu if (error) 1130 1.24 manu goto out; 1131 1.24 manu if (list) 1132 1.24 manu list += listsize_usr; 1133 1.24 manu if (size) 1134 1.24 manu size -= listsize_usr; 1135 1.2 thorpej 1136 1.24 manu error = extattr_list_vp(vp, EXTATTR_NAMESPACE_SYSTEM, 1137 1.27 manu list, size, 0, l, &listsize_sys); 1138 1.25 manu switch (error) { 1139 1.25 manu case EPERM: 1140 1.25 manu error = 0; /* Ignore and just skip system EA */ 1141 1.25 manu listsize_sys = 0; 1142 1.25 manu break; 1143 1.25 manu case 0: 1144 1.25 manu break; 1145 1.38 riastrad default: 1146 1.24 manu goto out; 1147 1.25 manu break; 1148 1.25 manu } 1149 1.24 manu 1150 1.38 riastrad *retval = listsize_usr + listsize_sys; 1151 1.24 manu out: 1152 1.20 dholland vrele(vp); 1153 1.38 riastrad return XATTR_ERRNO(error); 1154 1.2 thorpej } 1155 1.2 thorpej 1156 1.2 thorpej int 1157 1.38 riastrad sys_flistxattr(struct lwp *l, 1158 1.38 riastrad const struct sys_flistxattr_args *uap, 1159 1.38 riastrad register_t *retval) 1160 1.2 thorpej { 1161 1.15 dsl /* { 1162 1.2 thorpej syscallarg(int) fd; 1163 1.2 thorpej syscallarg(char *) list; 1164 1.2 thorpej syscallarg(size_t) size; 1165 1.15 dsl } */ 1166 1.2 thorpej struct file *fp; 1167 1.2 thorpej struct vnode *vp; 1168 1.24 manu char *list; 1169 1.24 manu size_t size; 1170 1.24 manu register_t listsize_usr, listsize_sys; 1171 1.2 thorpej int error; 1172 1.2 thorpej 1173 1.19 ad error = fd_getvnode(SCARG(uap, fd), &fp); 1174 1.2 thorpej if (error) 1175 1.38 riastrad return error; 1176 1.33 matt vp = fp->f_vnode; 1177 1.2 thorpej 1178 1.24 manu list = SCARG(uap, list); 1179 1.24 manu size = SCARG(uap, size); 1180 1.24 manu 1181 1.2 thorpej error = extattr_list_vp(vp, EXTATTR_NAMESPACE_USER, 1182 1.27 manu list, size, 0, l, &listsize_usr); 1183 1.24 manu if (error) 1184 1.24 manu goto out; 1185 1.24 manu 1186 1.24 manu if (list) 1187 1.24 manu list += listsize_usr; 1188 1.24 manu if (size) 1189 1.24 manu size -= listsize_usr; 1190 1.24 manu 1191 1.24 manu error = extattr_list_vp(vp, EXTATTR_NAMESPACE_SYSTEM, 1192 1.27 manu list, size, 0, l, &listsize_sys); 1193 1.25 manu switch (error) { 1194 1.25 manu case EPERM: 1195 1.25 manu error = 0; /* Ignore and just skip system EA */ 1196 1.25 manu listsize_sys = 0; 1197 1.25 manu break; 1198 1.25 manu case 0: 1199 1.25 manu break; 1200 1.38 riastrad default: 1201 1.24 manu goto out; 1202 1.25 manu break; 1203 1.25 manu } 1204 1.24 manu 1205 1.38 riastrad *retval = listsize_usr + listsize_sys; 1206 1.24 manu out: 1207 1.17 ad fd_putfile(SCARG(uap, fd)); 1208 1.38 riastrad return XATTR_ERRNO(error); 1209 1.2 thorpej } 1210 1.2 thorpej 1211 1.2 thorpej int 1212 1.38 riastrad sys_removexattr(struct lwp *l, 1213 1.38 riastrad const struct sys_removexattr_args *uap, 1214 1.38 riastrad register_t *retval) 1215 1.2 thorpej { 1216 1.15 dsl /* { 1217 1.2 thorpej syscallarg(const char *) path; 1218 1.2 thorpej syscallarg(const char *) name; 1219 1.15 dsl } */ 1220 1.20 dholland struct vnode *vp; 1221 1.2 thorpej char attrname[XATTR_NAME_MAX]; 1222 1.32 matt int attrnamespace; 1223 1.2 thorpej int error; 1224 1.2 thorpej 1225 1.2 thorpej error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname), 1226 1.2 thorpej NULL); 1227 1.2 thorpej if (error) 1228 1.38 riastrad return error; 1229 1.2 thorpej 1230 1.38 riastrad error = namei_simple_user(SCARG(uap, path), NSM_FOLLOW_NOEMULROOT, 1231 1.38 riastrad &vp); 1232 1.2 thorpej if (error) 1233 1.38 riastrad return error; 1234 1.2 thorpej 1235 1.32 matt attrnamespace = xattr_native(attrname); 1236 1.24 manu 1237 1.32 matt error = extattr_delete_vp(vp, attrnamespace, attrname, l); 1238 1.2 thorpej 1239 1.20 dholland vrele(vp); 1240 1.38 riastrad return XATTR_ERRNO(error); 1241 1.2 thorpej } 1242 1.2 thorpej 1243 1.2 thorpej int 1244 1.38 riastrad sys_lremovexattr(struct lwp *l, 1245 1.38 riastrad const struct sys_lremovexattr_args *uap, 1246 1.38 riastrad register_t *retval) 1247 1.2 thorpej { 1248 1.15 dsl /* { 1249 1.2 thorpej syscallarg(const char *) path; 1250 1.2 thorpej syscallarg(const char *) name; 1251 1.15 dsl } */ 1252 1.20 dholland struct vnode *vp; 1253 1.2 thorpej char attrname[XATTR_NAME_MAX]; 1254 1.32 matt int attrnamespace; 1255 1.2 thorpej int error; 1256 1.2 thorpej 1257 1.2 thorpej error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname), 1258 1.2 thorpej NULL); 1259 1.2 thorpej if (error) 1260 1.38 riastrad return error; 1261 1.2 thorpej 1262 1.38 riastrad error = namei_simple_user(SCARG(uap, path), NSM_NOFOLLOW_NOEMULROOT, 1263 1.38 riastrad &vp); 1264 1.2 thorpej if (error) 1265 1.38 riastrad return error; 1266 1.2 thorpej 1267 1.32 matt attrnamespace = xattr_native(attrname); 1268 1.24 manu 1269 1.32 matt error = extattr_delete_vp(vp, attrnamespace, attrname, l); 1270 1.2 thorpej 1271 1.20 dholland vrele(vp); 1272 1.38 riastrad return XATTR_ERRNO(error); 1273 1.2 thorpej } 1274 1.2 thorpej 1275 1.2 thorpej int 1276 1.38 riastrad sys_fremovexattr(struct lwp *l, 1277 1.38 riastrad const struct sys_fremovexattr_args *uap, 1278 1.38 riastrad register_t *retval) 1279 1.2 thorpej { 1280 1.15 dsl /* { 1281 1.2 thorpej syscallarg(int) fd; 1282 1.2 thorpej syscallarg(const char *) name; 1283 1.15 dsl } */ 1284 1.2 thorpej struct file *fp; 1285 1.2 thorpej struct vnode *vp; 1286 1.2 thorpej char attrname[XATTR_NAME_MAX]; 1287 1.32 matt int attrnamespace; 1288 1.2 thorpej int error; 1289 1.2 thorpej 1290 1.2 thorpej error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname), 1291 1.2 thorpej NULL); 1292 1.2 thorpej if (error) 1293 1.38 riastrad return error; 1294 1.2 thorpej 1295 1.19 ad error = fd_getvnode(SCARG(uap, fd), &fp); 1296 1.2 thorpej if (error) 1297 1.38 riastrad return error; 1298 1.33 matt vp = fp->f_vnode; 1299 1.2 thorpej 1300 1.32 matt attrnamespace = xattr_native(attrname); 1301 1.24 manu 1302 1.32 matt error = extattr_delete_vp(vp, attrnamespace, attrname, l); 1303 1.2 thorpej 1304 1.17 ad fd_putfile(SCARG(uap, fd)); 1305 1.38 riastrad return XATTR_ERRNO(error); 1306 1.2 thorpej } 1307