1 /* 2 * 9p xattr callback 3 * 4 * Copyright IBM, Corp. 2010 5 * 6 * Authors: 7 * Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> 8 * 9 * This work is licensed under the terms of the GNU GPL, version 2. See 10 * the COPYING file in the top-level directory. 11 * 12 */ 13 14 #include "9p.h" 15 #include "fsdev/file-op-9p.h" 16 #include "9p-xattr.h" 17 18 19 static XattrOperations *get_xattr_operations(XattrOperations **h, 20 const char *name) 21 { 22 XattrOperations *xops; 23 for (xops = *(h)++; xops != NULL; xops = *(h)++) { 24 if (!strncmp(name, xops->name, strlen(xops->name))) { 25 return xops; 26 } 27 } 28 return NULL; 29 } 30 31 ssize_t v9fs_get_xattr(FsContext *ctx, const char *path, 32 const char *name, void *value, size_t size) 33 { 34 XattrOperations *xops = get_xattr_operations(ctx->xops, name); 35 if (xops) { 36 return xops->getxattr(ctx, path, name, value, size); 37 } 38 errno = EOPNOTSUPP; 39 return -1; 40 } 41 42 ssize_t pt_listxattr(FsContext *ctx, const char *path, 43 char *name, void *value, size_t size) 44 { 45 int name_size = strlen(name) + 1; 46 if (!value) { 47 return name_size; 48 } 49 50 if (size < name_size) { 51 errno = ERANGE; 52 return -1; 53 } 54 55 /* no need for strncpy: name_size is strlen(name)+1 */ 56 memcpy(value, name, name_size); 57 return name_size; 58 } 59 60 61 /* 62 * Get the list and pass to each layer to find out whether 63 * to send the data or not 64 */ 65 ssize_t v9fs_list_xattr(FsContext *ctx, const char *path, 66 void *value, size_t vsize) 67 { 68 ssize_t size = 0; 69 char *buffer; 70 void *ovalue = value; 71 XattrOperations *xops; 72 char *orig_value, *orig_value_start; 73 ssize_t xattr_len, parsed_len = 0, attr_len; 74 75 /* Get the actual len */ 76 buffer = rpath(ctx, path); 77 xattr_len = llistxattr(buffer, value, 0); 78 if (xattr_len <= 0) { 79 g_free(buffer); 80 return xattr_len; 81 } 82 83 /* Now fetch the xattr and find the actual size */ 84 orig_value = g_malloc(xattr_len); 85 xattr_len = llistxattr(buffer, orig_value, xattr_len); 86 g_free(buffer); 87 88 /* store the orig pointer */ 89 orig_value_start = orig_value; 90 while (xattr_len > parsed_len) { 91 xops = get_xattr_operations(ctx->xops, orig_value); 92 if (!xops) { 93 goto next_entry; 94 } 95 96 if (!value) { 97 size += xops->listxattr(ctx, path, orig_value, value, vsize); 98 } else { 99 size = xops->listxattr(ctx, path, orig_value, value, vsize); 100 if (size < 0) { 101 goto err_out; 102 } 103 value += size; 104 vsize -= size; 105 } 106 next_entry: 107 /* Got the next entry */ 108 attr_len = strlen(orig_value) + 1; 109 parsed_len += attr_len; 110 orig_value += attr_len; 111 } 112 if (value) { 113 size = value - ovalue; 114 } 115 116 err_out: 117 g_free(orig_value_start); 118 return size; 119 } 120 121 int v9fs_set_xattr(FsContext *ctx, const char *path, const char *name, 122 void *value, size_t size, int flags) 123 { 124 XattrOperations *xops = get_xattr_operations(ctx->xops, name); 125 if (xops) { 126 return xops->setxattr(ctx, path, name, value, size, flags); 127 } 128 errno = EOPNOTSUPP; 129 return -1; 130 131 } 132 133 int v9fs_remove_xattr(FsContext *ctx, 134 const char *path, const char *name) 135 { 136 XattrOperations *xops = get_xattr_operations(ctx->xops, name); 137 if (xops) { 138 return xops->removexattr(ctx, path, name); 139 } 140 errno = EOPNOTSUPP; 141 return -1; 142 143 } 144 145 XattrOperations *mapped_xattr_ops[] = { 146 &mapped_user_xattr, 147 &mapped_pacl_xattr, 148 &mapped_dacl_xattr, 149 NULL, 150 }; 151 152 XattrOperations *passthrough_xattr_ops[] = { 153 &passthrough_user_xattr, 154 &passthrough_acl_xattr, 155 NULL, 156 }; 157 158 /* for .user none model should be same as passthrough */ 159 XattrOperations *none_xattr_ops[] = { 160 &passthrough_user_xattr, 161 &none_acl_xattr, 162 NULL, 163 }; 164