qemu/hw/9pfs/9p-xattr.c
<<
>>
Prefs
   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
  20static 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
  32ssize_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
  43ssize_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 */
  66ssize_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        }
 107next_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
 117err_out:
 118    g_free(orig_value_start);
 119    return size;
 120}
 121
 122int 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
 134int 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
 146XattrOperations *mapped_xattr_ops[] = {
 147    &mapped_user_xattr,
 148    &mapped_pacl_xattr,
 149    &mapped_dacl_xattr,
 150    NULL,
 151};
 152
 153XattrOperations *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 */
 160XattrOperations *none_xattr_ops[] = {
 161    &passthrough_user_xattr,
 162    &none_acl_xattr,
 163    NULL,
 164};
 165