xattr.c (2361f738b67ab7f1152187fa3d321a09b7c95c09) | xattr.c (38f38657444d15e1a8574eae80ed3de9f501737a) |
---|---|
1/* 2 File: fs/xattr.c 3 4 Extended attribute handling. 5 6 Copyright (C) 2001 by Andreas Gruenbacher <a.gruenbacher@computer.org> 7 Copyright (C) 2001 SGI - Silicon Graphics, Inc <linux-xfs@oss.sgi.com> 8 Copyright (c) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com> --- 777 unchanged lines hidden (view full) --- 786 return handler->set(dentry, name, NULL, 0, 787 XATTR_REPLACE, handler->flags); 788} 789 790EXPORT_SYMBOL(generic_getxattr); 791EXPORT_SYMBOL(generic_listxattr); 792EXPORT_SYMBOL(generic_setxattr); 793EXPORT_SYMBOL(generic_removexattr); | 1/* 2 File: fs/xattr.c 3 4 Extended attribute handling. 5 6 Copyright (C) 2001 by Andreas Gruenbacher <a.gruenbacher@computer.org> 7 Copyright (C) 2001 SGI - Silicon Graphics, Inc <linux-xfs@oss.sgi.com> 8 Copyright (c) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com> --- 777 unchanged lines hidden (view full) --- 786 return handler->set(dentry, name, NULL, 0, 787 XATTR_REPLACE, handler->flags); 788} 789 790EXPORT_SYMBOL(generic_getxattr); 791EXPORT_SYMBOL(generic_listxattr); 792EXPORT_SYMBOL(generic_setxattr); 793EXPORT_SYMBOL(generic_removexattr); |
794 795/* 796 * Allocate new xattr and copy in the value; but leave the name to callers. 797 */ 798struct simple_xattr *simple_xattr_alloc(const void *value, size_t size) 799{ 800 struct simple_xattr *new_xattr; 801 size_t len; 802 803 /* wrap around? */ 804 len = sizeof(*new_xattr) + size; 805 if (len <= sizeof(*new_xattr)) 806 return NULL; 807 808 new_xattr = kmalloc(len, GFP_KERNEL); 809 if (!new_xattr) 810 return NULL; 811 812 new_xattr->size = size; 813 memcpy(new_xattr->value, value, size); 814 return new_xattr; 815} 816 817/* 818 * xattr GET operation for in-memory/pseudo filesystems 819 */ 820int simple_xattr_get(struct simple_xattrs *xattrs, const char *name, 821 void *buffer, size_t size) 822{ 823 struct simple_xattr *xattr; 824 int ret = -ENODATA; 825 826 spin_lock(&xattrs->lock); 827 list_for_each_entry(xattr, &xattrs->head, list) { 828 if (strcmp(name, xattr->name)) 829 continue; 830 831 ret = xattr->size; 832 if (buffer) { 833 if (size < xattr->size) 834 ret = -ERANGE; 835 else 836 memcpy(buffer, xattr->value, xattr->size); 837 } 838 break; 839 } 840 spin_unlock(&xattrs->lock); 841 return ret; 842} 843 844static int __simple_xattr_set(struct simple_xattrs *xattrs, const char *name, 845 const void *value, size_t size, int flags) 846{ 847 struct simple_xattr *xattr; 848 struct simple_xattr *new_xattr = NULL; 849 int err = 0; 850 851 /* value == NULL means remove */ 852 if (value) { 853 new_xattr = simple_xattr_alloc(value, size); 854 if (!new_xattr) 855 return -ENOMEM; 856 857 new_xattr->name = kstrdup(name, GFP_KERNEL); 858 if (!new_xattr->name) { 859 kfree(new_xattr); 860 return -ENOMEM; 861 } 862 } 863 864 spin_lock(&xattrs->lock); 865 list_for_each_entry(xattr, &xattrs->head, list) { 866 if (!strcmp(name, xattr->name)) { 867 if (flags & XATTR_CREATE) { 868 xattr = new_xattr; 869 err = -EEXIST; 870 } else if (new_xattr) { 871 list_replace(&xattr->list, &new_xattr->list); 872 } else { 873 list_del(&xattr->list); 874 } 875 goto out; 876 } 877 } 878 if (flags & XATTR_REPLACE) { 879 xattr = new_xattr; 880 err = -ENODATA; 881 } else { 882 list_add(&new_xattr->list, &xattrs->head); 883 xattr = NULL; 884 } 885out: 886 spin_unlock(&xattrs->lock); 887 if (xattr) { 888 kfree(xattr->name); 889 kfree(xattr); 890 } 891 return err; 892 893} 894 895/* 896 * xattr SET operation for in-memory/pseudo filesystems 897 */ 898int simple_xattr_set(struct simple_xattrs *xattrs, const char *name, 899 const void *value, size_t size, int flags) 900{ 901 if (size == 0) 902 value = ""; /* empty EA, do not remove */ 903 return __simple_xattr_set(xattrs, name, value, size, flags); 904} 905 906/* 907 * xattr REMOVE operation for in-memory/pseudo filesystems 908 */ 909int simple_xattr_remove(struct simple_xattrs *xattrs, const char *name) 910{ 911 return __simple_xattr_set(xattrs, name, NULL, 0, XATTR_REPLACE); 912} 913 914static bool xattr_is_trusted(const char *name) 915{ 916 return !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN); 917} 918 919/* 920 * xattr LIST operation for in-memory/pseudo filesystems 921 */ 922ssize_t simple_xattr_list(struct simple_xattrs *xattrs, char *buffer, 923 size_t size) 924{ 925 bool trusted = capable(CAP_SYS_ADMIN); 926 struct simple_xattr *xattr; 927 size_t used = 0; 928 929 spin_lock(&xattrs->lock); 930 list_for_each_entry(xattr, &xattrs->head, list) { 931 size_t len; 932 933 /* skip "trusted." attributes for unprivileged callers */ 934 if (!trusted && xattr_is_trusted(xattr->name)) 935 continue; 936 937 len = strlen(xattr->name) + 1; 938 used += len; 939 if (buffer) { 940 if (size < used) { 941 used = -ERANGE; 942 break; 943 } 944 memcpy(buffer, xattr->name, len); 945 buffer += len; 946 } 947 } 948 spin_unlock(&xattrs->lock); 949 950 return used; 951} 952 953void simple_xattr_list_add(struct simple_xattrs *xattrs, 954 struct simple_xattr *new_xattr) 955{ 956 spin_lock(&xattrs->lock); 957 list_add(&new_xattr->list, &xattrs->head); 958 spin_unlock(&xattrs->lock); 959} |
|