1267ae092SWei Liu /* 2267ae092SWei Liu * 9p xattr callback 3267ae092SWei Liu * 4267ae092SWei Liu * Copyright IBM, Corp. 2010 5267ae092SWei Liu * 6267ae092SWei Liu * Authors: 7267ae092SWei Liu * Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> 8267ae092SWei Liu * 9267ae092SWei Liu * This work is licensed under the terms of the GNU GPL, version 2. See 10267ae092SWei Liu * the COPYING file in the top-level directory. 11267ae092SWei Liu * 12267ae092SWei Liu */ 13267ae092SWei Liu 14fbc04127SPeter Maydell #include "qemu/osdep.h" 15ebe74f8bSWei Liu #include "9p.h" 16267ae092SWei Liu #include "fsdev/file-op-9p.h" 17267ae092SWei Liu #include "9p-xattr.h" 18267ae092SWei Liu 19267ae092SWei Liu 20267ae092SWei Liu static XattrOperations *get_xattr_operations(XattrOperations **h, 21267ae092SWei Liu const char *name) 22267ae092SWei Liu { 23267ae092SWei Liu XattrOperations *xops; 24267ae092SWei Liu for (xops = *(h)++; xops != NULL; xops = *(h)++) { 25267ae092SWei Liu if (!strncmp(name, xops->name, strlen(xops->name))) { 26267ae092SWei Liu return xops; 27267ae092SWei Liu } 28267ae092SWei Liu } 29267ae092SWei Liu return NULL; 30267ae092SWei Liu } 31267ae092SWei Liu 32267ae092SWei Liu ssize_t v9fs_get_xattr(FsContext *ctx, const char *path, 33267ae092SWei Liu const char *name, void *value, size_t size) 34267ae092SWei Liu { 35267ae092SWei Liu XattrOperations *xops = get_xattr_operations(ctx->xops, name); 36267ae092SWei Liu if (xops) { 37267ae092SWei Liu return xops->getxattr(ctx, path, name, value, size); 38267ae092SWei Liu } 39267ae092SWei Liu errno = EOPNOTSUPP; 40267ae092SWei Liu return -1; 41267ae092SWei Liu } 42267ae092SWei Liu 43267ae092SWei Liu ssize_t pt_listxattr(FsContext *ctx, const char *path, 44267ae092SWei Liu char *name, void *value, size_t size) 45267ae092SWei Liu { 46267ae092SWei Liu int name_size = strlen(name) + 1; 47267ae092SWei Liu if (!value) { 48267ae092SWei Liu return name_size; 49267ae092SWei Liu } 50267ae092SWei Liu 51267ae092SWei Liu if (size < name_size) { 52267ae092SWei Liu errno = ERANGE; 53267ae092SWei Liu return -1; 54267ae092SWei Liu } 55267ae092SWei Liu 56267ae092SWei Liu /* no need for strncpy: name_size is strlen(name)+1 */ 57267ae092SWei Liu memcpy(value, name, name_size); 58267ae092SWei Liu return name_size; 59267ae092SWei Liu } 60267ae092SWei Liu 61267ae092SWei Liu 62267ae092SWei Liu /* 63267ae092SWei Liu * Get the list and pass to each layer to find out whether 64267ae092SWei Liu * to send the data or not 65267ae092SWei Liu */ 66267ae092SWei Liu ssize_t v9fs_list_xattr(FsContext *ctx, const char *path, 67267ae092SWei Liu void *value, size_t vsize) 68267ae092SWei Liu { 69267ae092SWei Liu ssize_t size = 0; 70267ae092SWei Liu char *buffer; 71267ae092SWei Liu void *ovalue = value; 72267ae092SWei Liu XattrOperations *xops; 73267ae092SWei Liu char *orig_value, *orig_value_start; 74267ae092SWei Liu ssize_t xattr_len, parsed_len = 0, attr_len; 75267ae092SWei Liu 76267ae092SWei Liu /* Get the actual len */ 77267ae092SWei Liu buffer = rpath(ctx, path); 78267ae092SWei Liu xattr_len = llistxattr(buffer, value, 0); 79267ae092SWei Liu if (xattr_len <= 0) { 80267ae092SWei Liu g_free(buffer); 81267ae092SWei Liu return xattr_len; 82267ae092SWei Liu } 83267ae092SWei Liu 84267ae092SWei Liu /* Now fetch the xattr and find the actual size */ 85267ae092SWei Liu orig_value = g_malloc(xattr_len); 86267ae092SWei Liu xattr_len = llistxattr(buffer, orig_value, xattr_len); 87267ae092SWei Liu g_free(buffer); 88267ae092SWei Liu 89267ae092SWei Liu /* store the orig pointer */ 90267ae092SWei Liu orig_value_start = orig_value; 91267ae092SWei Liu while (xattr_len > parsed_len) { 92267ae092SWei Liu xops = get_xattr_operations(ctx->xops, orig_value); 93267ae092SWei Liu if (!xops) { 94267ae092SWei Liu goto next_entry; 95267ae092SWei Liu } 96267ae092SWei Liu 97267ae092SWei Liu if (!value) { 98267ae092SWei Liu size += xops->listxattr(ctx, path, orig_value, value, vsize); 99267ae092SWei Liu } else { 100267ae092SWei Liu size = xops->listxattr(ctx, path, orig_value, value, vsize); 101267ae092SWei Liu if (size < 0) { 102267ae092SWei Liu goto err_out; 103267ae092SWei Liu } 104267ae092SWei Liu value += size; 105267ae092SWei Liu vsize -= size; 106267ae092SWei Liu } 107267ae092SWei Liu next_entry: 108267ae092SWei Liu /* Got the next entry */ 109267ae092SWei Liu attr_len = strlen(orig_value) + 1; 110267ae092SWei Liu parsed_len += attr_len; 111267ae092SWei Liu orig_value += attr_len; 112267ae092SWei Liu } 113267ae092SWei Liu if (value) { 114267ae092SWei Liu size = value - ovalue; 115267ae092SWei Liu } 116267ae092SWei Liu 117267ae092SWei Liu err_out: 118267ae092SWei Liu g_free(orig_value_start); 119267ae092SWei Liu return size; 120267ae092SWei Liu } 121267ae092SWei Liu 122267ae092SWei Liu int v9fs_set_xattr(FsContext *ctx, const char *path, const char *name, 123267ae092SWei Liu void *value, size_t size, int flags) 124267ae092SWei Liu { 125267ae092SWei Liu XattrOperations *xops = get_xattr_operations(ctx->xops, name); 126267ae092SWei Liu if (xops) { 127267ae092SWei Liu return xops->setxattr(ctx, path, name, value, size, flags); 128267ae092SWei Liu } 129267ae092SWei Liu errno = EOPNOTSUPP; 130267ae092SWei Liu return -1; 131267ae092SWei Liu 132267ae092SWei Liu } 133267ae092SWei Liu 134267ae092SWei Liu int v9fs_remove_xattr(FsContext *ctx, 135267ae092SWei Liu const char *path, const char *name) 136267ae092SWei Liu { 137267ae092SWei Liu XattrOperations *xops = get_xattr_operations(ctx->xops, name); 138267ae092SWei Liu if (xops) { 139267ae092SWei Liu return xops->removexattr(ctx, path, name); 140267ae092SWei Liu } 141267ae092SWei Liu errno = EOPNOTSUPP; 142267ae092SWei Liu return -1; 143267ae092SWei Liu 144267ae092SWei Liu } 145267ae092SWei Liu 146*56fc494bSGreg Kurz ssize_t pt_getxattr(FsContext *ctx, const char *path, const char *name, 147*56fc494bSGreg Kurz void *value, size_t size) 148*56fc494bSGreg Kurz { 149*56fc494bSGreg Kurz char *buffer; 150*56fc494bSGreg Kurz ssize_t ret; 151*56fc494bSGreg Kurz 152*56fc494bSGreg Kurz buffer = rpath(ctx, path); 153*56fc494bSGreg Kurz ret = lgetxattr(buffer, name, value, size); 154*56fc494bSGreg Kurz g_free(buffer); 155*56fc494bSGreg Kurz return ret; 156*56fc494bSGreg Kurz } 157*56fc494bSGreg Kurz 158*56fc494bSGreg Kurz int pt_setxattr(FsContext *ctx, const char *path, const char *name, void *value, 159*56fc494bSGreg Kurz size_t size, int flags) 160*56fc494bSGreg Kurz { 161*56fc494bSGreg Kurz char *buffer; 162*56fc494bSGreg Kurz int ret; 163*56fc494bSGreg Kurz 164*56fc494bSGreg Kurz buffer = rpath(ctx, path); 165*56fc494bSGreg Kurz ret = lsetxattr(buffer, name, value, size, flags); 166*56fc494bSGreg Kurz g_free(buffer); 167*56fc494bSGreg Kurz return ret; 168*56fc494bSGreg Kurz } 169*56fc494bSGreg Kurz 170*56fc494bSGreg Kurz int pt_removexattr(FsContext *ctx, const char *path, const char *name) 171*56fc494bSGreg Kurz { 172*56fc494bSGreg Kurz char *buffer; 173*56fc494bSGreg Kurz int ret; 174*56fc494bSGreg Kurz 175*56fc494bSGreg Kurz buffer = rpath(ctx, path); 176*56fc494bSGreg Kurz ret = lremovexattr(path, name); 177*56fc494bSGreg Kurz g_free(buffer); 178*56fc494bSGreg Kurz return ret; 179*56fc494bSGreg Kurz } 180*56fc494bSGreg Kurz 181*56fc494bSGreg Kurz ssize_t notsup_getxattr(FsContext *ctx, const char *path, const char *name, 182*56fc494bSGreg Kurz void *value, size_t size) 183*56fc494bSGreg Kurz { 184*56fc494bSGreg Kurz errno = ENOTSUP; 185*56fc494bSGreg Kurz return -1; 186*56fc494bSGreg Kurz } 187*56fc494bSGreg Kurz 188*56fc494bSGreg Kurz int notsup_setxattr(FsContext *ctx, const char *path, const char *name, 189*56fc494bSGreg Kurz void *value, size_t size, int flags) 190*56fc494bSGreg Kurz { 191*56fc494bSGreg Kurz errno = ENOTSUP; 192*56fc494bSGreg Kurz return -1; 193*56fc494bSGreg Kurz } 194*56fc494bSGreg Kurz 195*56fc494bSGreg Kurz ssize_t notsup_listxattr(FsContext *ctx, const char *path, char *name, 196*56fc494bSGreg Kurz void *value, size_t size) 197*56fc494bSGreg Kurz { 198*56fc494bSGreg Kurz return 0; 199*56fc494bSGreg Kurz } 200*56fc494bSGreg Kurz 201*56fc494bSGreg Kurz int notsup_removexattr(FsContext *ctx, const char *path, const char *name) 202*56fc494bSGreg Kurz { 203*56fc494bSGreg Kurz errno = ENOTSUP; 204*56fc494bSGreg Kurz return -1; 205*56fc494bSGreg Kurz } 206*56fc494bSGreg Kurz 207267ae092SWei Liu XattrOperations *mapped_xattr_ops[] = { 208267ae092SWei Liu &mapped_user_xattr, 209267ae092SWei Liu &mapped_pacl_xattr, 210267ae092SWei Liu &mapped_dacl_xattr, 211267ae092SWei Liu NULL, 212267ae092SWei Liu }; 213267ae092SWei Liu 214267ae092SWei Liu XattrOperations *passthrough_xattr_ops[] = { 215267ae092SWei Liu &passthrough_user_xattr, 216267ae092SWei Liu &passthrough_acl_xattr, 217267ae092SWei Liu NULL, 218267ae092SWei Liu }; 219267ae092SWei Liu 220267ae092SWei Liu /* for .user none model should be same as passthrough */ 221267ae092SWei Liu XattrOperations *none_xattr_ops[] = { 222267ae092SWei Liu &passthrough_user_xattr, 223267ae092SWei Liu &none_acl_xattr, 224267ae092SWei Liu NULL, 225267ae092SWei Liu }; 226