diff options
Diffstat (limited to 'fs/xfs/xfs_attr.c')
| -rw-r--r-- | fs/xfs/xfs_attr.c | 608 |
1 files changed, 92 insertions, 516 deletions
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index df151a859186..78de80e3caa2 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c | |||
| @@ -16,8 +16,6 @@ | |||
| 16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| 17 | */ | 17 | */ |
| 18 | 18 | ||
| 19 | #include <linux/capability.h> | ||
| 20 | |||
| 21 | #include "xfs.h" | 19 | #include "xfs.h" |
| 22 | #include "xfs_fs.h" | 20 | #include "xfs_fs.h" |
| 23 | #include "xfs_types.h" | 21 | #include "xfs_types.h" |
| @@ -57,11 +55,6 @@ | |||
| 57 | * Provide the external interfaces to manage attribute lists. | 55 | * Provide the external interfaces to manage attribute lists. |
| 58 | */ | 56 | */ |
| 59 | 57 | ||
| 60 | #define ATTR_SYSCOUNT 2 | ||
| 61 | static struct attrnames posix_acl_access; | ||
| 62 | static struct attrnames posix_acl_default; | ||
| 63 | static struct attrnames *attr_system_names[ATTR_SYSCOUNT]; | ||
| 64 | |||
| 65 | /*======================================================================== | 58 | /*======================================================================== |
| 66 | * Function prototypes for the kernel. | 59 | * Function prototypes for the kernel. |
| 67 | *========================================================================*/ | 60 | *========================================================================*/ |
| @@ -116,6 +109,17 @@ xfs_attr_name_to_xname( | |||
| 116 | return 0; | 109 | return 0; |
| 117 | } | 110 | } |
| 118 | 111 | ||
| 112 | STATIC int | ||
| 113 | xfs_inode_hasattr( | ||
| 114 | struct xfs_inode *ip) | ||
| 115 | { | ||
| 116 | if (!XFS_IFORK_Q(ip) || | ||
| 117 | (ip->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS && | ||
| 118 | ip->i_d.di_anextents == 0)) | ||
| 119 | return 0; | ||
| 120 | return 1; | ||
| 121 | } | ||
| 122 | |||
| 119 | /*======================================================================== | 123 | /*======================================================================== |
| 120 | * Overall external interface routines. | 124 | * Overall external interface routines. |
| 121 | *========================================================================*/ | 125 | *========================================================================*/ |
| @@ -127,10 +131,8 @@ xfs_attr_fetch(xfs_inode_t *ip, struct xfs_name *name, | |||
| 127 | xfs_da_args_t args; | 131 | xfs_da_args_t args; |
| 128 | int error; | 132 | int error; |
| 129 | 133 | ||
| 130 | if ((XFS_IFORK_Q(ip) == 0) || | 134 | if (!xfs_inode_hasattr(ip)) |
| 131 | (ip->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS && | 135 | return ENOATTR; |
| 132 | ip->i_d.di_anextents == 0)) | ||
| 133 | return(ENOATTR); | ||
| 134 | 136 | ||
| 135 | /* | 137 | /* |
| 136 | * Fill in the arg structure for this request. | 138 | * Fill in the arg structure for this request. |
| @@ -148,11 +150,7 @@ xfs_attr_fetch(xfs_inode_t *ip, struct xfs_name *name, | |||
| 148 | /* | 150 | /* |
| 149 | * Decide on what work routines to call based on the inode size. | 151 | * Decide on what work routines to call based on the inode size. |
| 150 | */ | 152 | */ |
| 151 | if (XFS_IFORK_Q(ip) == 0 || | 153 | if (ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) { |
| 152 | (ip->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS && | ||
| 153 | ip->i_d.di_anextents == 0)) { | ||
| 154 | error = XFS_ERROR(ENOATTR); | ||
| 155 | } else if (ip->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) { | ||
| 156 | error = xfs_attr_shortform_getvalue(&args); | 154 | error = xfs_attr_shortform_getvalue(&args); |
| 157 | } else if (xfs_bmap_one_block(ip, XFS_ATTR_FORK)) { | 155 | } else if (xfs_bmap_one_block(ip, XFS_ATTR_FORK)) { |
| 158 | error = xfs_attr_leaf_get(&args); | 156 | error = xfs_attr_leaf_get(&args); |
| @@ -241,8 +239,7 @@ xfs_attr_set_int(xfs_inode_t *dp, struct xfs_name *name, | |||
| 241 | args.firstblock = &firstblock; | 239 | args.firstblock = &firstblock; |
| 242 | args.flist = &flist; | 240 | args.flist = &flist; |
| 243 | args.whichfork = XFS_ATTR_FORK; | 241 | args.whichfork = XFS_ATTR_FORK; |
| 244 | args.addname = 1; | 242 | args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT; |
| 245 | args.oknoent = 1; | ||
| 246 | 243 | ||
| 247 | /* | 244 | /* |
| 248 | * Determine space new attribute will use, and if it would be | 245 | * Determine space new attribute will use, and if it would be |
| @@ -529,9 +526,7 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags) | |||
| 529 | /* | 526 | /* |
| 530 | * Decide on what work routines to call based on the inode size. | 527 | * Decide on what work routines to call based on the inode size. |
| 531 | */ | 528 | */ |
| 532 | if (XFS_IFORK_Q(dp) == 0 || | 529 | if (!xfs_inode_hasattr(dp)) { |
| 533 | (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS && | ||
| 534 | dp->i_d.di_anextents == 0)) { | ||
| 535 | error = XFS_ERROR(ENOATTR); | 530 | error = XFS_ERROR(ENOATTR); |
| 536 | goto out; | 531 | goto out; |
| 537 | } | 532 | } |
| @@ -601,29 +596,33 @@ xfs_attr_remove( | |||
| 601 | return error; | 596 | return error; |
| 602 | 597 | ||
| 603 | xfs_ilock(dp, XFS_ILOCK_SHARED); | 598 | xfs_ilock(dp, XFS_ILOCK_SHARED); |
| 604 | if (XFS_IFORK_Q(dp) == 0 || | 599 | if (!xfs_inode_hasattr(dp)) { |
| 605 | (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS && | ||
| 606 | dp->i_d.di_anextents == 0)) { | ||
| 607 | xfs_iunlock(dp, XFS_ILOCK_SHARED); | 600 | xfs_iunlock(dp, XFS_ILOCK_SHARED); |
| 608 | return(XFS_ERROR(ENOATTR)); | 601 | return XFS_ERROR(ENOATTR); |
| 609 | } | 602 | } |
| 610 | xfs_iunlock(dp, XFS_ILOCK_SHARED); | 603 | xfs_iunlock(dp, XFS_ILOCK_SHARED); |
| 611 | 604 | ||
| 612 | return xfs_attr_remove_int(dp, &xname, flags); | 605 | return xfs_attr_remove_int(dp, &xname, flags); |
| 613 | } | 606 | } |
| 614 | 607 | ||
| 615 | STATIC int | 608 | int |
| 616 | xfs_attr_list_int(xfs_attr_list_context_t *context) | 609 | xfs_attr_list_int(xfs_attr_list_context_t *context) |
| 617 | { | 610 | { |
| 618 | int error; | 611 | int error; |
| 619 | xfs_inode_t *dp = context->dp; | 612 | xfs_inode_t *dp = context->dp; |
| 620 | 613 | ||
| 614 | XFS_STATS_INC(xs_attr_list); | ||
| 615 | |||
| 616 | if (XFS_FORCED_SHUTDOWN(dp->i_mount)) | ||
| 617 | return EIO; | ||
| 618 | |||
| 619 | xfs_ilock(dp, XFS_ILOCK_SHARED); | ||
| 620 | xfs_attr_trace_l_c("syscall start", context); | ||
| 621 | |||
| 621 | /* | 622 | /* |
| 622 | * Decide on what work routines to call based on the inode size. | 623 | * Decide on what work routines to call based on the inode size. |
| 623 | */ | 624 | */ |
| 624 | if (XFS_IFORK_Q(dp) == 0 || | 625 | if (!xfs_inode_hasattr(dp)) { |
| 625 | (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS && | ||
| 626 | dp->i_d.di_anextents == 0)) { | ||
| 627 | error = 0; | 626 | error = 0; |
| 628 | } else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) { | 627 | } else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) { |
| 629 | error = xfs_attr_shortform_list(context); | 628 | error = xfs_attr_shortform_list(context); |
| @@ -632,6 +631,10 @@ xfs_attr_list_int(xfs_attr_list_context_t *context) | |||
| 632 | } else { | 631 | } else { |
| 633 | error = xfs_attr_node_list(context); | 632 | error = xfs_attr_node_list(context); |
| 634 | } | 633 | } |
| 634 | |||
| 635 | xfs_iunlock(dp, XFS_ILOCK_SHARED); | ||
| 636 | xfs_attr_trace_l_c("syscall end", context); | ||
| 637 | |||
| 635 | return error; | 638 | return error; |
| 636 | } | 639 | } |
| 637 | 640 | ||
| @@ -648,74 +651,50 @@ xfs_attr_list_int(xfs_attr_list_context_t *context) | |||
| 648 | */ | 651 | */ |
| 649 | /*ARGSUSED*/ | 652 | /*ARGSUSED*/ |
| 650 | STATIC int | 653 | STATIC int |
| 651 | xfs_attr_put_listent(xfs_attr_list_context_t *context, attrnames_t *namesp, | 654 | xfs_attr_put_listent(xfs_attr_list_context_t *context, int flags, |
| 652 | char *name, int namelen, | 655 | char *name, int namelen, |
| 653 | int valuelen, char *value) | 656 | int valuelen, char *value) |
| 654 | { | 657 | { |
| 658 | struct attrlist *alist = (struct attrlist *)context->alist; | ||
| 655 | attrlist_ent_t *aep; | 659 | attrlist_ent_t *aep; |
| 656 | int arraytop; | 660 | int arraytop; |
| 657 | 661 | ||
| 658 | ASSERT(!(context->flags & ATTR_KERNOVAL)); | 662 | ASSERT(!(context->flags & ATTR_KERNOVAL)); |
| 659 | ASSERT(context->count >= 0); | 663 | ASSERT(context->count >= 0); |
| 660 | ASSERT(context->count < (ATTR_MAX_VALUELEN/8)); | 664 | ASSERT(context->count < (ATTR_MAX_VALUELEN/8)); |
| 661 | ASSERT(context->firstu >= sizeof(*context->alist)); | 665 | ASSERT(context->firstu >= sizeof(*alist)); |
| 662 | ASSERT(context->firstu <= context->bufsize); | 666 | ASSERT(context->firstu <= context->bufsize); |
| 663 | 667 | ||
| 664 | arraytop = sizeof(*context->alist) + | 668 | /* |
| 665 | context->count * sizeof(context->alist->al_offset[0]); | 669 | * Only list entries in the right namespace. |
| 670 | */ | ||
| 671 | if (((context->flags & ATTR_SECURE) == 0) != | ||
| 672 | ((flags & XFS_ATTR_SECURE) == 0)) | ||
| 673 | return 0; | ||
| 674 | if (((context->flags & ATTR_ROOT) == 0) != | ||
| 675 | ((flags & XFS_ATTR_ROOT) == 0)) | ||
| 676 | return 0; | ||
| 677 | |||
| 678 | arraytop = sizeof(*alist) + | ||
| 679 | context->count * sizeof(alist->al_offset[0]); | ||
| 666 | context->firstu -= ATTR_ENTSIZE(namelen); | 680 | context->firstu -= ATTR_ENTSIZE(namelen); |
| 667 | if (context->firstu < arraytop) { | 681 | if (context->firstu < arraytop) { |
| 668 | xfs_attr_trace_l_c("buffer full", context); | 682 | xfs_attr_trace_l_c("buffer full", context); |
| 669 | context->alist->al_more = 1; | 683 | alist->al_more = 1; |
| 670 | context->seen_enough = 1; | 684 | context->seen_enough = 1; |
| 671 | return 1; | 685 | return 1; |
| 672 | } | 686 | } |
| 673 | 687 | ||
| 674 | aep = (attrlist_ent_t *)&(((char *)context->alist)[ context->firstu ]); | 688 | aep = (attrlist_ent_t *)&context->alist[context->firstu]; |
| 675 | aep->a_valuelen = valuelen; | 689 | aep->a_valuelen = valuelen; |
| 676 | memcpy(aep->a_name, name, namelen); | 690 | memcpy(aep->a_name, name, namelen); |
| 677 | aep->a_name[ namelen ] = 0; | 691 | aep->a_name[namelen] = 0; |
| 678 | context->alist->al_offset[ context->count++ ] = context->firstu; | 692 | alist->al_offset[context->count++] = context->firstu; |
| 679 | context->alist->al_count = context->count; | 693 | alist->al_count = context->count; |
| 680 | xfs_attr_trace_l_c("add", context); | 694 | xfs_attr_trace_l_c("add", context); |
| 681 | return 0; | 695 | return 0; |
| 682 | } | 696 | } |
| 683 | 697 | ||
| 684 | STATIC int | ||
| 685 | xfs_attr_kern_list(xfs_attr_list_context_t *context, attrnames_t *namesp, | ||
| 686 | char *name, int namelen, | ||
| 687 | int valuelen, char *value) | ||
| 688 | { | ||
| 689 | char *offset; | ||
| 690 | int arraytop; | ||
| 691 | |||
| 692 | ASSERT(context->count >= 0); | ||
| 693 | |||
| 694 | arraytop = context->count + namesp->attr_namelen + namelen + 1; | ||
| 695 | if (arraytop > context->firstu) { | ||
| 696 | context->count = -1; /* insufficient space */ | ||
| 697 | return 1; | ||
| 698 | } | ||
| 699 | offset = (char *)context->alist + context->count; | ||
| 700 | strncpy(offset, namesp->attr_name, namesp->attr_namelen); | ||
| 701 | offset += namesp->attr_namelen; | ||
| 702 | strncpy(offset, name, namelen); /* real name */ | ||
| 703 | offset += namelen; | ||
| 704 | *offset = '\0'; | ||
| 705 | context->count += namesp->attr_namelen + namelen + 1; | ||
| 706 | return 0; | ||
| 707 | } | ||
| 708 | |||
| 709 | /*ARGSUSED*/ | ||
| 710 | STATIC int | ||
| 711 | xfs_attr_kern_list_sizes(xfs_attr_list_context_t *context, attrnames_t *namesp, | ||
| 712 | char *name, int namelen, | ||
| 713 | int valuelen, char *value) | ||
| 714 | { | ||
| 715 | context->count += namesp->attr_namelen + namelen + 1; | ||
| 716 | return 0; | ||
| 717 | } | ||
| 718 | |||
| 719 | /* | 698 | /* |
| 720 | * Generate a list of extended attribute names and optionally | 699 | * Generate a list of extended attribute names and optionally |
| 721 | * also value lengths. Positive return value follows the XFS | 700 | * also value lengths. Positive return value follows the XFS |
| @@ -732,10 +711,9 @@ xfs_attr_list( | |||
| 732 | attrlist_cursor_kern_t *cursor) | 711 | attrlist_cursor_kern_t *cursor) |
| 733 | { | 712 | { |
| 734 | xfs_attr_list_context_t context; | 713 | xfs_attr_list_context_t context; |
| 714 | struct attrlist *alist; | ||
| 735 | int error; | 715 | int error; |
| 736 | 716 | ||
| 737 | XFS_STATS_INC(xs_attr_list); | ||
| 738 | |||
| 739 | /* | 717 | /* |
| 740 | * Validate the cursor. | 718 | * Validate the cursor. |
| 741 | */ | 719 | */ |
| @@ -756,52 +734,23 @@ xfs_attr_list( | |||
| 756 | /* | 734 | /* |
| 757 | * Initialize the output buffer. | 735 | * Initialize the output buffer. |
| 758 | */ | 736 | */ |
| 737 | memset(&context, 0, sizeof(context)); | ||
| 759 | context.dp = dp; | 738 | context.dp = dp; |
| 760 | context.cursor = cursor; | 739 | context.cursor = cursor; |
| 761 | context.count = 0; | ||
| 762 | context.dupcnt = 0; | ||
| 763 | context.resynch = 1; | 740 | context.resynch = 1; |
| 764 | context.flags = flags; | 741 | context.flags = flags; |
| 765 | context.seen_enough = 0; | 742 | context.alist = buffer; |
| 766 | context.alist = (attrlist_t *)buffer; | 743 | context.bufsize = (bufsize & ~(sizeof(int)-1)); /* align */ |
| 767 | context.put_value = 0; | 744 | context.firstu = context.bufsize; |
| 768 | 745 | context.put_listent = xfs_attr_put_listent; | |
| 769 | if (flags & ATTR_KERNAMELS) { | ||
| 770 | context.bufsize = bufsize; | ||
| 771 | context.firstu = context.bufsize; | ||
| 772 | if (flags & ATTR_KERNOVAL) | ||
| 773 | context.put_listent = xfs_attr_kern_list_sizes; | ||
| 774 | else | ||
| 775 | context.put_listent = xfs_attr_kern_list; | ||
| 776 | } else { | ||
| 777 | context.bufsize = (bufsize & ~(sizeof(int)-1)); /* align */ | ||
| 778 | context.firstu = context.bufsize; | ||
| 779 | context.alist->al_count = 0; | ||
| 780 | context.alist->al_more = 0; | ||
| 781 | context.alist->al_offset[0] = context.bufsize; | ||
| 782 | context.put_listent = xfs_attr_put_listent; | ||
| 783 | } | ||
| 784 | 746 | ||
| 785 | if (XFS_FORCED_SHUTDOWN(dp->i_mount)) | 747 | alist = (struct attrlist *)context.alist; |
| 786 | return EIO; | 748 | alist->al_count = 0; |
| 787 | 749 | alist->al_more = 0; | |
| 788 | xfs_ilock(dp, XFS_ILOCK_SHARED); | 750 | alist->al_offset[0] = context.bufsize; |
| 789 | xfs_attr_trace_l_c("syscall start", &context); | ||
| 790 | 751 | ||
| 791 | error = xfs_attr_list_int(&context); | 752 | error = xfs_attr_list_int(&context); |
| 792 | 753 | ASSERT(error >= 0); | |
| 793 | xfs_iunlock(dp, XFS_ILOCK_SHARED); | ||
| 794 | xfs_attr_trace_l_c("syscall end", &context); | ||
| 795 | |||
| 796 | if (context.flags & (ATTR_KERNOVAL|ATTR_KERNAMELS)) { | ||
| 797 | /* must return negated buffer size or the error */ | ||
| 798 | if (context.count < 0) | ||
| 799 | error = XFS_ERROR(ERANGE); | ||
| 800 | else | ||
| 801 | error = -context.count; | ||
| 802 | } else | ||
| 803 | ASSERT(error >= 0); | ||
| 804 | |||
| 805 | return error; | 754 | return error; |
| 806 | } | 755 | } |
| 807 | 756 | ||
| @@ -816,12 +765,10 @@ xfs_attr_inactive(xfs_inode_t *dp) | |||
| 816 | ASSERT(! XFS_NOT_DQATTACHED(mp, dp)); | 765 | ASSERT(! XFS_NOT_DQATTACHED(mp, dp)); |
| 817 | 766 | ||
| 818 | xfs_ilock(dp, XFS_ILOCK_SHARED); | 767 | xfs_ilock(dp, XFS_ILOCK_SHARED); |
| 819 | if ((XFS_IFORK_Q(dp) == 0) || | 768 | if (!xfs_inode_hasattr(dp) || |
| 820 | (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) || | 769 | dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) { |
| 821 | (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS && | ||
| 822 | dp->i_d.di_anextents == 0)) { | ||
| 823 | xfs_iunlock(dp, XFS_ILOCK_SHARED); | 770 | xfs_iunlock(dp, XFS_ILOCK_SHARED); |
| 824 | return(0); | 771 | return 0; |
| 825 | } | 772 | } |
| 826 | xfs_iunlock(dp, XFS_ILOCK_SHARED); | 773 | xfs_iunlock(dp, XFS_ILOCK_SHARED); |
| 827 | 774 | ||
| @@ -854,10 +801,8 @@ xfs_attr_inactive(xfs_inode_t *dp) | |||
| 854 | /* | 801 | /* |
| 855 | * Decide on what work routines to call based on the inode size. | 802 | * Decide on what work routines to call based on the inode size. |
| 856 | */ | 803 | */ |
| 857 | if ((XFS_IFORK_Q(dp) == 0) || | 804 | if (!xfs_inode_hasattr(dp) || |
| 858 | (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) || | 805 | dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) { |
| 859 | (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS && | ||
| 860 | dp->i_d.di_anextents == 0)) { | ||
| 861 | error = 0; | 806 | error = 0; |
| 862 | goto out; | 807 | goto out; |
| 863 | } | 808 | } |
| @@ -974,7 +919,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) | |||
| 974 | xfs_da_brelse(args->trans, bp); | 919 | xfs_da_brelse(args->trans, bp); |
| 975 | return(retval); | 920 | return(retval); |
| 976 | } | 921 | } |
| 977 | args->rename = 1; /* an atomic rename */ | 922 | args->op_flags |= XFS_DA_OP_RENAME; /* an atomic rename */ |
| 978 | args->blkno2 = args->blkno; /* set 2nd entry info*/ | 923 | args->blkno2 = args->blkno; /* set 2nd entry info*/ |
| 979 | args->index2 = args->index; | 924 | args->index2 = args->index; |
| 980 | args->rmtblkno2 = args->rmtblkno; | 925 | args->rmtblkno2 = args->rmtblkno; |
| @@ -1054,7 +999,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) | |||
| 1054 | * so that one disappears and one appears atomically. Then we | 999 | * so that one disappears and one appears atomically. Then we |
| 1055 | * must remove the "old" attribute/value pair. | 1000 | * must remove the "old" attribute/value pair. |
| 1056 | */ | 1001 | */ |
| 1057 | if (args->rename) { | 1002 | if (args->op_flags & XFS_DA_OP_RENAME) { |
| 1058 | /* | 1003 | /* |
| 1059 | * In a separate transaction, set the incomplete flag on the | 1004 | * In a separate transaction, set the incomplete flag on the |
| 1060 | * "old" attr and clear the incomplete flag on the "new" attr. | 1005 | * "old" attr and clear the incomplete flag on the "new" attr. |
| @@ -1307,7 +1252,7 @@ restart: | |||
| 1307 | } else if (retval == EEXIST) { | 1252 | } else if (retval == EEXIST) { |
| 1308 | if (args->flags & ATTR_CREATE) | 1253 | if (args->flags & ATTR_CREATE) |
| 1309 | goto out; | 1254 | goto out; |
| 1310 | args->rename = 1; /* atomic rename op */ | 1255 | args->op_flags |= XFS_DA_OP_RENAME; /* atomic rename op */ |
| 1311 | args->blkno2 = args->blkno; /* set 2nd entry info*/ | 1256 | args->blkno2 = args->blkno; /* set 2nd entry info*/ |
| 1312 | args->index2 = args->index; | 1257 | args->index2 = args->index; |
| 1313 | args->rmtblkno2 = args->rmtblkno; | 1258 | args->rmtblkno2 = args->rmtblkno; |
| @@ -1425,7 +1370,7 @@ restart: | |||
| 1425 | * so that one disappears and one appears atomically. Then we | 1370 | * so that one disappears and one appears atomically. Then we |
| 1426 | * must remove the "old" attribute/value pair. | 1371 | * must remove the "old" attribute/value pair. |
| 1427 | */ | 1372 | */ |
| 1428 | if (args->rename) { | 1373 | if (args->op_flags & XFS_DA_OP_RENAME) { |
| 1429 | /* | 1374 | /* |
| 1430 | * In a separate transaction, set the incomplete flag on the | 1375 | * In a separate transaction, set the incomplete flag on the |
| 1431 | * "old" attr and clear the incomplete flag on the "new" attr. | 1376 | * "old" attr and clear the incomplete flag on the "new" attr. |
| @@ -2300,23 +2245,7 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args) | |||
| 2300 | void | 2245 | void |
| 2301 | xfs_attr_trace_l_c(char *where, struct xfs_attr_list_context *context) | 2246 | xfs_attr_trace_l_c(char *where, struct xfs_attr_list_context *context) |
| 2302 | { | 2247 | { |
| 2303 | xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_C, where, | 2248 | xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_C, where, context, |
| 2304 | (__psunsigned_t)context->dp, | ||
| 2305 | (__psunsigned_t)context->cursor->hashval, | ||
| 2306 | (__psunsigned_t)context->cursor->blkno, | ||
| 2307 | (__psunsigned_t)context->cursor->offset, | ||
| 2308 | (__psunsigned_t)context->alist, | ||
| 2309 | (__psunsigned_t)context->bufsize, | ||
| 2310 | (__psunsigned_t)context->count, | ||
| 2311 | (__psunsigned_t)context->firstu, | ||
| 2312 | (__psunsigned_t) | ||
| 2313 | ((context->count > 0) && | ||
| 2314 | !(context->flags & (ATTR_KERNAMELS|ATTR_KERNOVAL))) | ||
| 2315 | ? (ATTR_ENTRY(context->alist, | ||
| 2316 | context->count-1)->a_valuelen) | ||
| 2317 | : 0, | ||
| 2318 | (__psunsigned_t)context->dupcnt, | ||
| 2319 | (__psunsigned_t)context->flags, | ||
| 2320 | (__psunsigned_t)NULL, | 2249 | (__psunsigned_t)NULL, |
| 2321 | (__psunsigned_t)NULL, | 2250 | (__psunsigned_t)NULL, |
| 2322 | (__psunsigned_t)NULL); | 2251 | (__psunsigned_t)NULL); |
| @@ -2329,23 +2258,7 @@ void | |||
| 2329 | xfs_attr_trace_l_cn(char *where, struct xfs_attr_list_context *context, | 2258 | xfs_attr_trace_l_cn(char *where, struct xfs_attr_list_context *context, |
| 2330 | struct xfs_da_intnode *node) | 2259 | struct xfs_da_intnode *node) |
| 2331 | { | 2260 | { |
| 2332 | xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_CN, where, | 2261 | xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_CN, where, context, |
| 2333 | (__psunsigned_t)context->dp, | ||
| 2334 | (__psunsigned_t)context->cursor->hashval, | ||
| 2335 | (__psunsigned_t)context->cursor->blkno, | ||
| 2336 | (__psunsigned_t)context->cursor->offset, | ||
| 2337 | (__psunsigned_t)context->alist, | ||
| 2338 | (__psunsigned_t)context->bufsize, | ||
| 2339 | (__psunsigned_t)context->count, | ||
| 2340 | (__psunsigned_t)context->firstu, | ||
| 2341 | (__psunsigned_t) | ||
| 2342 | ((context->count > 0) && | ||
| 2343 | !(context->flags & (ATTR_KERNAMELS|ATTR_KERNOVAL))) | ||
| 2344 | ? (ATTR_ENTRY(context->alist, | ||
| 2345 | context->count-1)->a_valuelen) | ||
| 2346 | : 0, | ||
| 2347 | (__psunsigned_t)context->dupcnt, | ||
| 2348 | (__psunsigned_t)context->flags, | ||
| 2349 | (__psunsigned_t)be16_to_cpu(node->hdr.count), | 2262 | (__psunsigned_t)be16_to_cpu(node->hdr.count), |
| 2350 | (__psunsigned_t)be32_to_cpu(node->btree[0].hashval), | 2263 | (__psunsigned_t)be32_to_cpu(node->btree[0].hashval), |
| 2351 | (__psunsigned_t)be32_to_cpu(node->btree[ | 2264 | (__psunsigned_t)be32_to_cpu(node->btree[ |
| @@ -2359,23 +2272,7 @@ void | |||
| 2359 | xfs_attr_trace_l_cb(char *where, struct xfs_attr_list_context *context, | 2272 | xfs_attr_trace_l_cb(char *where, struct xfs_attr_list_context *context, |
| 2360 | struct xfs_da_node_entry *btree) | 2273 | struct xfs_da_node_entry *btree) |
| 2361 | { | 2274 | { |
| 2362 | xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_CB, where, | 2275 | xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_CB, where, context, |
| 2363 | (__psunsigned_t)context->dp, | ||
| 2364 | (__psunsigned_t)context->cursor->hashval, | ||
| 2365 | (__psunsigned_t)context->cursor->blkno, | ||
| 2366 | (__psunsigned_t)context->cursor->offset, | ||
| 2367 | (__psunsigned_t)context->alist, | ||
| 2368 | (__psunsigned_t)context->bufsize, | ||
| 2369 | (__psunsigned_t)context->count, | ||
| 2370 | (__psunsigned_t)context->firstu, | ||
| 2371 | (__psunsigned_t) | ||
| 2372 | ((context->count > 0) && | ||
| 2373 | !(context->flags & (ATTR_KERNAMELS|ATTR_KERNOVAL))) | ||
| 2374 | ? (ATTR_ENTRY(context->alist, | ||
| 2375 | context->count-1)->a_valuelen) | ||
| 2376 | : 0, | ||
| 2377 | (__psunsigned_t)context->dupcnt, | ||
| 2378 | (__psunsigned_t)context->flags, | ||
| 2379 | (__psunsigned_t)be32_to_cpu(btree->hashval), | 2276 | (__psunsigned_t)be32_to_cpu(btree->hashval), |
| 2380 | (__psunsigned_t)be32_to_cpu(btree->before), | 2277 | (__psunsigned_t)be32_to_cpu(btree->before), |
| 2381 | (__psunsigned_t)NULL); | 2278 | (__psunsigned_t)NULL); |
| @@ -2388,23 +2285,7 @@ void | |||
| 2388 | xfs_attr_trace_l_cl(char *where, struct xfs_attr_list_context *context, | 2285 | xfs_attr_trace_l_cl(char *where, struct xfs_attr_list_context *context, |
| 2389 | struct xfs_attr_leafblock *leaf) | 2286 | struct xfs_attr_leafblock *leaf) |
| 2390 | { | 2287 | { |
| 2391 | xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_CL, where, | 2288 | xfs_attr_trace_enter(XFS_ATTR_KTRACE_L_CL, where, context, |
| 2392 | (__psunsigned_t)context->dp, | ||
| 2393 | (__psunsigned_t)context->cursor->hashval, | ||
| 2394 | (__psunsigned_t)context->cursor->blkno, | ||
| 2395 | (__psunsigned_t)context->cursor->offset, | ||
| 2396 | (__psunsigned_t)context->alist, | ||
| 2397 | (__psunsigned_t)context->bufsize, | ||
| 2398 | (__psunsigned_t)context->count, | ||
| 2399 | (__psunsigned_t)context->firstu, | ||
| 2400 | (__psunsigned_t) | ||
| 2401 | ((context->count > 0) && | ||
| 2402 | !(context->flags & (ATTR_KERNAMELS|ATTR_KERNOVAL))) | ||
| 2403 | ? (ATTR_ENTRY(context->alist, | ||
| 2404 | context->count-1)->a_valuelen) | ||
| 2405 | : 0, | ||
| 2406 | (__psunsigned_t)context->dupcnt, | ||
| 2407 | (__psunsigned_t)context->flags, | ||
| 2408 | (__psunsigned_t)be16_to_cpu(leaf->hdr.count), | 2289 | (__psunsigned_t)be16_to_cpu(leaf->hdr.count), |
| 2409 | (__psunsigned_t)be32_to_cpu(leaf->entries[0].hashval), | 2290 | (__psunsigned_t)be32_to_cpu(leaf->entries[0].hashval), |
| 2410 | (__psunsigned_t)be32_to_cpu(leaf->entries[ | 2291 | (__psunsigned_t)be32_to_cpu(leaf->entries[ |
| @@ -2417,329 +2298,24 @@ xfs_attr_trace_l_cl(char *where, struct xfs_attr_list_context *context, | |||
| 2417 | */ | 2298 | */ |
| 2418 | void | 2299 | void |
| 2419 | xfs_attr_trace_enter(int type, char *where, | 2300 | xfs_attr_trace_enter(int type, char *where, |
| 2420 | __psunsigned_t a2, __psunsigned_t a3, | 2301 | struct xfs_attr_list_context *context, |
| 2421 | __psunsigned_t a4, __psunsigned_t a5, | 2302 | __psunsigned_t a13, __psunsigned_t a14, |
| 2422 | __psunsigned_t a6, __psunsigned_t a7, | 2303 | __psunsigned_t a15) |
| 2423 | __psunsigned_t a8, __psunsigned_t a9, | ||
| 2424 | __psunsigned_t a10, __psunsigned_t a11, | ||
| 2425 | __psunsigned_t a12, __psunsigned_t a13, | ||
| 2426 | __psunsigned_t a14, __psunsigned_t a15) | ||
| 2427 | { | 2304 | { |
| 2428 | ASSERT(xfs_attr_trace_buf); | 2305 | ASSERT(xfs_attr_trace_buf); |
| 2429 | ktrace_enter(xfs_attr_trace_buf, (void *)((__psunsigned_t)type), | 2306 | ktrace_enter(xfs_attr_trace_buf, (void *)((__psunsigned_t)type), |
| 2430 | (void *)where, | 2307 | (void *)((__psunsigned_t)where), |
| 2431 | (void *)a2, (void *)a3, (void *)a4, | 2308 | (void *)((__psunsigned_t)context->dp), |
| 2432 | (void *)a5, (void *)a6, (void *)a7, | 2309 | (void *)((__psunsigned_t)context->cursor->hashval), |
| 2433 | (void *)a8, (void *)a9, (void *)a10, | 2310 | (void *)((__psunsigned_t)context->cursor->blkno), |
| 2434 | (void *)a11, (void *)a12, (void *)a13, | 2311 | (void *)((__psunsigned_t)context->cursor->offset), |
| 2435 | (void *)a14, (void *)a15); | 2312 | (void *)((__psunsigned_t)context->alist), |
| 2313 | (void *)((__psunsigned_t)context->bufsize), | ||
| 2314 | (void *)((__psunsigned_t)context->count), | ||
| 2315 | (void *)((__psunsigned_t)context->firstu), | ||
| 2316 | NULL, | ||
| 2317 | (void *)((__psunsigned_t)context->dupcnt), | ||
| 2318 | (void *)((__psunsigned_t)context->flags), | ||
| 2319 | (void *)a13, (void *)a14, (void *)a15); | ||
| 2436 | } | 2320 | } |
| 2437 | #endif /* XFS_ATTR_TRACE */ | 2321 | #endif /* XFS_ATTR_TRACE */ |
| 2438 | |||
| 2439 | |||
| 2440 | /*======================================================================== | ||
| 2441 | * System (pseudo) namespace attribute interface routines. | ||
| 2442 | *========================================================================*/ | ||
| 2443 | |||
| 2444 | STATIC int | ||
| 2445 | posix_acl_access_set( | ||
| 2446 | bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags) | ||
| 2447 | { | ||
| 2448 | return xfs_acl_vset(vp, data, size, _ACL_TYPE_ACCESS); | ||
| 2449 | } | ||
| 2450 | |||
| 2451 | STATIC int | ||
| 2452 | posix_acl_access_remove( | ||
| 2453 | bhv_vnode_t *vp, char *name, int xflags) | ||
| 2454 | { | ||
| 2455 | return xfs_acl_vremove(vp, _ACL_TYPE_ACCESS); | ||
| 2456 | } | ||
| 2457 | |||
| 2458 | STATIC int | ||
| 2459 | posix_acl_access_get( | ||
| 2460 | bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags) | ||
| 2461 | { | ||
| 2462 | return xfs_acl_vget(vp, data, size, _ACL_TYPE_ACCESS); | ||
| 2463 | } | ||
| 2464 | |||
| 2465 | STATIC int | ||
| 2466 | posix_acl_access_exists( | ||
| 2467 | bhv_vnode_t *vp) | ||
| 2468 | { | ||
| 2469 | return xfs_acl_vhasacl_access(vp); | ||
| 2470 | } | ||
| 2471 | |||
| 2472 | STATIC int | ||
| 2473 | posix_acl_default_set( | ||
| 2474 | bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags) | ||
| 2475 | { | ||
| 2476 | return xfs_acl_vset(vp, data, size, _ACL_TYPE_DEFAULT); | ||
| 2477 | } | ||
| 2478 | |||
| 2479 | STATIC int | ||
| 2480 | posix_acl_default_get( | ||
| 2481 | bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags) | ||
| 2482 | { | ||
| 2483 | return xfs_acl_vget(vp, data, size, _ACL_TYPE_DEFAULT); | ||
| 2484 | } | ||
| 2485 | |||
| 2486 | STATIC int | ||
| 2487 | posix_acl_default_remove( | ||
| 2488 | bhv_vnode_t *vp, char *name, int xflags) | ||
| 2489 | { | ||
| 2490 | return xfs_acl_vremove(vp, _ACL_TYPE_DEFAULT); | ||
| 2491 | } | ||
| 2492 | |||
| 2493 | STATIC int | ||
| 2494 | posix_acl_default_exists( | ||
| 2495 | bhv_vnode_t *vp) | ||
| 2496 | { | ||
| 2497 | return xfs_acl_vhasacl_default(vp); | ||
| 2498 | } | ||
| 2499 | |||
| 2500 | static struct attrnames posix_acl_access = { | ||
| 2501 | .attr_name = "posix_acl_access", | ||
| 2502 | .attr_namelen = sizeof("posix_acl_access") - 1, | ||
| 2503 | .attr_get = posix_acl_access_get, | ||
| 2504 | .attr_set = posix_acl_access_set, | ||
| 2505 | .attr_remove = posix_acl_access_remove, | ||
| 2506 | .attr_exists = posix_acl_access_exists, | ||
| 2507 | }; | ||
| 2508 | |||
| 2509 | static struct attrnames posix_acl_default = { | ||
| 2510 | .attr_name = "posix_acl_default", | ||
| 2511 | .attr_namelen = sizeof("posix_acl_default") - 1, | ||
| 2512 | .attr_get = posix_acl_default_get, | ||
| 2513 | .attr_set = posix_acl_default_set, | ||
| 2514 | .attr_remove = posix_acl_default_remove, | ||
| 2515 | .attr_exists = posix_acl_default_exists, | ||
| 2516 | }; | ||
| 2517 | |||
| 2518 | static struct attrnames *attr_system_names[] = | ||
| 2519 | { &posix_acl_access, &posix_acl_default }; | ||
| 2520 | |||
| 2521 | |||
| 2522 | /*======================================================================== | ||
| 2523 | * Namespace-prefix-style attribute name interface routines. | ||
| 2524 | *========================================================================*/ | ||
| 2525 | |||
| 2526 | STATIC int | ||
| 2527 | attr_generic_set( | ||
| 2528 | bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags) | ||
| 2529 | { | ||
| 2530 | return -xfs_attr_set(xfs_vtoi(vp), name, data, size, xflags); | ||
| 2531 | } | ||
| 2532 | |||
| 2533 | STATIC int | ||
| 2534 | attr_generic_get( | ||
| 2535 | bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags) | ||
| 2536 | { | ||
| 2537 | int error, asize = size; | ||
| 2538 | |||
| 2539 | error = xfs_attr_get(xfs_vtoi(vp), name, data, &asize, xflags); | ||
| 2540 | if (!error) | ||
| 2541 | return asize; | ||
| 2542 | return -error; | ||
| 2543 | } | ||
| 2544 | |||
| 2545 | STATIC int | ||
| 2546 | attr_generic_remove( | ||
| 2547 | bhv_vnode_t *vp, char *name, int xflags) | ||
| 2548 | { | ||
| 2549 | return -xfs_attr_remove(xfs_vtoi(vp), name, xflags); | ||
| 2550 | } | ||
| 2551 | |||
| 2552 | STATIC int | ||
| 2553 | attr_generic_listadd( | ||
| 2554 | attrnames_t *prefix, | ||
| 2555 | attrnames_t *namesp, | ||
| 2556 | void *data, | ||
| 2557 | size_t size, | ||
| 2558 | ssize_t *result) | ||
| 2559 | { | ||
| 2560 | char *p = data + *result; | ||
| 2561 | |||
| 2562 | *result += prefix->attr_namelen; | ||
| 2563 | *result += namesp->attr_namelen + 1; | ||
| 2564 | if (!size) | ||
| 2565 | return 0; | ||
| 2566 | if (*result > size) | ||
| 2567 | return -ERANGE; | ||
| 2568 | strcpy(p, prefix->attr_name); | ||
| 2569 | p += prefix->attr_namelen; | ||
| 2570 | strcpy(p, namesp->attr_name); | ||
| 2571 | p += namesp->attr_namelen + 1; | ||
| 2572 | return 0; | ||
| 2573 | } | ||
| 2574 | |||
| 2575 | STATIC int | ||
| 2576 | attr_system_list( | ||
| 2577 | bhv_vnode_t *vp, | ||
| 2578 | void *data, | ||
| 2579 | size_t size, | ||
| 2580 | ssize_t *result) | ||
| 2581 | { | ||
| 2582 | attrnames_t *namesp; | ||
| 2583 | int i, error = 0; | ||
| 2584 | |||
| 2585 | for (i = 0; i < ATTR_SYSCOUNT; i++) { | ||
| 2586 | namesp = attr_system_names[i]; | ||
| 2587 | if (!namesp->attr_exists || !namesp->attr_exists(vp)) | ||
| 2588 | continue; | ||
| 2589 | error = attr_generic_listadd(&attr_system, namesp, | ||
| 2590 | data, size, result); | ||
| 2591 | if (error) | ||
| 2592 | break; | ||
| 2593 | } | ||
| 2594 | return error; | ||
| 2595 | } | ||
| 2596 | |||
| 2597 | int | ||
| 2598 | attr_generic_list( | ||
| 2599 | bhv_vnode_t *vp, void *data, size_t size, int xflags, ssize_t *result) | ||
| 2600 | { | ||
| 2601 | attrlist_cursor_kern_t cursor = { 0 }; | ||
| 2602 | int error; | ||
| 2603 | |||
| 2604 | error = xfs_attr_list(xfs_vtoi(vp), data, size, xflags, &cursor); | ||
| 2605 | if (error > 0) | ||
| 2606 | return -error; | ||
| 2607 | *result = -error; | ||
| 2608 | return attr_system_list(vp, data, size, result); | ||
| 2609 | } | ||
| 2610 | |||
| 2611 | attrnames_t * | ||
| 2612 | attr_lookup_namespace( | ||
| 2613 | char *name, | ||
| 2614 | struct attrnames **names, | ||
| 2615 | int nnames) | ||
| 2616 | { | ||
| 2617 | int i; | ||
| 2618 | |||
| 2619 | for (i = 0; i < nnames; i++) | ||
| 2620 | if (!strncmp(name, names[i]->attr_name, names[i]->attr_namelen)) | ||
| 2621 | return names[i]; | ||
| 2622 | return NULL; | ||
| 2623 | } | ||
| 2624 | |||
| 2625 | /* | ||
| 2626 | * Some checks to prevent people abusing EAs to get over quota: | ||
| 2627 | * - Don't allow modifying user EAs on devices/symlinks; | ||
| 2628 | * - Don't allow modifying user EAs if sticky bit set; | ||
| 2629 | */ | ||
| 2630 | STATIC int | ||
| 2631 | attr_user_capable( | ||
| 2632 | bhv_vnode_t *vp, | ||
| 2633 | cred_t *cred) | ||
| 2634 | { | ||
| 2635 | struct inode *inode = vn_to_inode(vp); | ||
| 2636 | |||
| 2637 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) | ||
| 2638 | return -EPERM; | ||
| 2639 | if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode) && | ||
| 2640 | !capable(CAP_SYS_ADMIN)) | ||
| 2641 | return -EPERM; | ||
| 2642 | if (S_ISDIR(inode->i_mode) && (inode->i_mode & S_ISVTX) && | ||
| 2643 | (current_fsuid(cred) != inode->i_uid) && !capable(CAP_FOWNER)) | ||
| 2644 | return -EPERM; | ||
| 2645 | return 0; | ||
| 2646 | } | ||
| 2647 | |||
| 2648 | STATIC int | ||
| 2649 | attr_trusted_capable( | ||
| 2650 | bhv_vnode_t *vp, | ||
| 2651 | cred_t *cred) | ||
| 2652 | { | ||
| 2653 | struct inode *inode = vn_to_inode(vp); | ||
| 2654 | |||
| 2655 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) | ||
| 2656 | return -EPERM; | ||
| 2657 | if (!capable(CAP_SYS_ADMIN)) | ||
| 2658 | return -EPERM; | ||
| 2659 | return 0; | ||
| 2660 | } | ||
| 2661 | |||
| 2662 | STATIC int | ||
| 2663 | attr_system_set( | ||
| 2664 | bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags) | ||
| 2665 | { | ||
| 2666 | attrnames_t *namesp; | ||
| 2667 | int error; | ||
| 2668 | |||
| 2669 | if (xflags & ATTR_CREATE) | ||
| 2670 | return -EINVAL; | ||
| 2671 | |||
| 2672 | namesp = attr_lookup_namespace(name, attr_system_names, ATTR_SYSCOUNT); | ||
| 2673 | if (!namesp) | ||
| 2674 | return -EOPNOTSUPP; | ||
| 2675 | error = namesp->attr_set(vp, name, data, size, xflags); | ||
| 2676 | if (!error) | ||
| 2677 | error = vn_revalidate(vp); | ||
| 2678 | return error; | ||
| 2679 | } | ||
| 2680 | |||
| 2681 | STATIC int | ||
| 2682 | attr_system_get( | ||
| 2683 | bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags) | ||
| 2684 | { | ||
| 2685 | attrnames_t *namesp; | ||
| 2686 | |||
| 2687 | namesp = attr_lookup_namespace(name, attr_system_names, ATTR_SYSCOUNT); | ||
| 2688 | if (!namesp) | ||
| 2689 | return -EOPNOTSUPP; | ||
| 2690 | return namesp->attr_get(vp, name, data, size, xflags); | ||
| 2691 | } | ||
| 2692 | |||
| 2693 | STATIC int | ||
| 2694 | attr_system_remove( | ||
| 2695 | bhv_vnode_t *vp, char *name, int xflags) | ||
| 2696 | { | ||
| 2697 | attrnames_t *namesp; | ||
| 2698 | |||
| 2699 | namesp = attr_lookup_namespace(name, attr_system_names, ATTR_SYSCOUNT); | ||
| 2700 | if (!namesp) | ||
| 2701 | return -EOPNOTSUPP; | ||
| 2702 | return namesp->attr_remove(vp, name, xflags); | ||
| 2703 | } | ||
| 2704 | |||
| 2705 | struct attrnames attr_system = { | ||
| 2706 | .attr_name = "system.", | ||
| 2707 | .attr_namelen = sizeof("system.") - 1, | ||
| 2708 | .attr_flag = ATTR_SYSTEM, | ||
| 2709 | .attr_get = attr_system_get, | ||
| 2710 | .attr_set = attr_system_set, | ||
| 2711 | .attr_remove = attr_system_remove, | ||
| 2712 | .attr_capable = (attrcapable_t)fs_noerr, | ||
| 2713 | }; | ||
| 2714 | |||
| 2715 | struct attrnames attr_trusted = { | ||
| 2716 | .attr_name = "trusted.", | ||
| 2717 | .attr_namelen = sizeof("trusted.") - 1, | ||
| 2718 | .attr_flag = ATTR_ROOT, | ||
| 2719 | .attr_get = attr_generic_get, | ||
| 2720 | .attr_set = attr_generic_set, | ||
| 2721 | .attr_remove = attr_generic_remove, | ||
| 2722 | .attr_capable = attr_trusted_capable, | ||
| 2723 | }; | ||
| 2724 | |||
| 2725 | struct attrnames attr_secure = { | ||
| 2726 | .attr_name = "security.", | ||
| 2727 | .attr_namelen = sizeof("security.") - 1, | ||
| 2728 | .attr_flag = ATTR_SECURE, | ||
| 2729 | .attr_get = attr_generic_get, | ||
| 2730 | .attr_set = attr_generic_set, | ||
| 2731 | .attr_remove = attr_generic_remove, | ||
| 2732 | .attr_capable = (attrcapable_t)fs_noerr, | ||
| 2733 | }; | ||
| 2734 | |||
| 2735 | struct attrnames attr_user = { | ||
| 2736 | .attr_name = "user.", | ||
| 2737 | .attr_namelen = sizeof("user.") - 1, | ||
| 2738 | .attr_get = attr_generic_get, | ||
| 2739 | .attr_set = attr_generic_set, | ||
| 2740 | .attr_remove = attr_generic_remove, | ||
| 2741 | .attr_capable = attr_user_capable, | ||
| 2742 | }; | ||
| 2743 | |||
| 2744 | struct attrnames *attr_namespaces[] = | ||
| 2745 | { &attr_system, &attr_trusted, &attr_secure, &attr_user }; | ||
