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