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