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#include "9p-util.h"
  19#include "9p-local.h"
  20
  21
  22static XattrOperations *get_xattr_operations(XattrOperations **h,
  23                                             const char *name)
  24{
  25    XattrOperations *xops;
  26    for (xops = *(h)++; xops != NULL; xops = *(h)++) {
  27        if (!strncmp(name, xops->name, strlen(xops->name))) {
  28            return xops;
  29        }
  30    }
  31    return NULL;
  32}
  33
  34ssize_t v9fs_get_xattr(FsContext *ctx, const char *path,
  35                       const char *name, void *value, size_t size)
  36{
  37    XattrOperations *xops = get_xattr_operations(ctx->xops, name);
  38    if (xops) {
  39        return xops->getxattr(ctx, path, name, value, size);
  40    }
  41    errno = EOPNOTSUPP;
  42    return -1;
  43}
  44
  45ssize_t pt_listxattr(FsContext *ctx, const char *path,
  46                     char *name, void *value, size_t size)
  47{
  48    int name_size = strlen(name) + 1;
  49    if (!value) {
  50        return name_size;
  51    }
  52
  53    if (size < name_size) {
  54        errno = ERANGE;
  55        return -1;
  56    }
  57
  58    /* no need for strncpy: name_size is strlen(name)+1 */
  59    memcpy(value, name, name_size);
  60    return name_size;
  61}
  62
  63/*
  64 * Get the list and pass to each layer to find out whether
  65 * to send the data or not
  66 */
  67ssize_t v9fs_list_xattr(FsContext *ctx, const char *path,
  68                        void *value, size_t vsize)
  69{
  70    ssize_t size = 0;
  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    char *dirpath, *name;
  76    int dirfd;
  77
  78    /* Get the actual len */
  79    dirpath = g_path_get_dirname(path);
  80    dirfd = local_opendir_nofollow(ctx, dirpath);
  81    g_free(dirpath);
  82    if (dirfd == -1) {
  83        return -1;
  84    }
  85
  86    name = g_path_get_basename(path);
  87    xattr_len = flistxattrat_nofollow(dirfd, name, value, 0);
  88    if (xattr_len <= 0) {
  89        g_free(name);
  90        close_preserve_errno(dirfd);
  91        return xattr_len;
  92    }
  93
  94    /* Now fetch the xattr and find the actual size */
  95    orig_value = g_malloc(xattr_len);
  96    xattr_len = flistxattrat_nofollow(dirfd, name, orig_value, xattr_len);
  97    g_free(name);
  98    close_preserve_errno(dirfd);
  99    if (xattr_len < 0) {
 100        g_free(orig_value);
 101        return -1;
 102    }
 103
 104    /* store the orig pointer */
 105    orig_value_start = orig_value;
 106    while (xattr_len > parsed_len) {
 107        xops = get_xattr_operations(ctx->xops, orig_value);
 108        if (!xops) {
 109            goto next_entry;
 110        }
 111
 112        if (!value) {
 113            size += xops->listxattr(ctx, path, orig_value, value, vsize);
 114        } else {
 115            size = xops->listxattr(ctx, path, orig_value, value, vsize);
 116            if (size < 0) {
 117                goto err_out;
 118            }
 119            value += size;
 120            vsize -= size;
 121        }
 122next_entry:
 123        /* Got the next entry */
 124        attr_len = strlen(orig_value) + 1;
 125        parsed_len += attr_len;
 126        orig_value += attr_len;
 127    }
 128    if (value) {
 129        size = value - ovalue;
 130    }
 131
 132err_out:
 133    g_free(orig_value_start);
 134    return size;
 135}
 136
 137int v9fs_set_xattr(FsContext *ctx, const char *path, const char *name,
 138                   void *value, size_t size, int flags)
 139{
 140    XattrOperations *xops = get_xattr_operations(ctx->xops, name);
 141    if (xops) {
 142        return xops->setxattr(ctx, path, name, value, size, flags);
 143    }
 144    errno = EOPNOTSUPP;
 145    return -1;
 146
 147}
 148
 149int v9fs_remove_xattr(FsContext *ctx,
 150                      const char *path, const char *name)
 151{
 152    XattrOperations *xops = get_xattr_operations(ctx->xops, name);
 153    if (xops) {
 154        return xops->removexattr(ctx, path, name);
 155    }
 156    errno = EOPNOTSUPP;
 157    return -1;
 158
 159}
 160
 161ssize_t local_getxattr_nofollow(FsContext *ctx, const char *path,
 162                                const char *name, void *value, size_t size)
 163{
 164    char *dirpath = g_path_get_dirname(path);
 165    char *filename = g_path_get_basename(path);
 166    int dirfd;
 167    ssize_t ret = -1;
 168
 169    dirfd = local_opendir_nofollow(ctx, dirpath);
 170    if (dirfd == -1) {
 171        goto out;
 172    }
 173
 174    ret = fgetxattrat_nofollow(dirfd, filename, name, value, size);
 175    close_preserve_errno(dirfd);
 176out:
 177    g_free(dirpath);
 178    g_free(filename);
 179    return ret;
 180}
 181
 182ssize_t pt_getxattr(FsContext *ctx, const char *path, const char *name,
 183                    void *value, size_t size)
 184{
 185    return local_getxattr_nofollow(ctx, path, name, value, size);
 186}
 187
 188ssize_t local_setxattr_nofollow(FsContext *ctx, const char *path,
 189                                const char *name, void *value, size_t size,
 190                                int flags)
 191{
 192    char *dirpath = g_path_get_dirname(path);
 193    char *filename = g_path_get_basename(path);
 194    int dirfd;
 195    ssize_t ret = -1;
 196
 197    dirfd = local_opendir_nofollow(ctx, dirpath);
 198    if (dirfd == -1) {
 199        goto out;
 200    }
 201
 202    ret = fsetxattrat_nofollow(dirfd, filename, name, value, size, flags);
 203    close_preserve_errno(dirfd);
 204out:
 205    g_free(dirpath);
 206    g_free(filename);
 207    return ret;
 208}
 209
 210int pt_setxattr(FsContext *ctx, const char *path, const char *name, void *value,
 211                size_t size, int flags)
 212{
 213    return local_setxattr_nofollow(ctx, path, name, value, size, flags);
 214}
 215
 216ssize_t local_removexattr_nofollow(FsContext *ctx, const char *path,
 217                                   const char *name)
 218{
 219    char *dirpath = g_path_get_dirname(path);
 220    char *filename = g_path_get_basename(path);
 221    int dirfd;
 222    ssize_t ret = -1;
 223
 224    dirfd = local_opendir_nofollow(ctx, dirpath);
 225    if (dirfd == -1) {
 226        goto out;
 227    }
 228
 229    ret = fremovexattrat_nofollow(dirfd, filename, name);
 230    close_preserve_errno(dirfd);
 231out:
 232    g_free(dirpath);
 233    g_free(filename);
 234    return ret;
 235}
 236
 237int pt_removexattr(FsContext *ctx, const char *path, const char *name)
 238{
 239    return local_removexattr_nofollow(ctx, path, name);
 240}
 241
 242ssize_t notsup_getxattr(FsContext *ctx, const char *path, const char *name,
 243                        void *value, size_t size)
 244{
 245    errno = ENOTSUP;
 246    return -1;
 247}
 248
 249int notsup_setxattr(FsContext *ctx, const char *path, const char *name,
 250                    void *value, size_t size, int flags)
 251{
 252    errno = ENOTSUP;
 253    return -1;
 254}
 255
 256ssize_t notsup_listxattr(FsContext *ctx, const char *path, char *name,
 257                         void *value, size_t size)
 258{
 259    return 0;
 260}
 261
 262int notsup_removexattr(FsContext *ctx, const char *path, const char *name)
 263{
 264    errno = ENOTSUP;
 265    return -1;
 266}
 267
 268XattrOperations *mapped_xattr_ops[] = {
 269    &mapped_user_xattr,
 270    &mapped_pacl_xattr,
 271    &mapped_dacl_xattr,
 272    NULL,
 273};
 274
 275XattrOperations *passthrough_xattr_ops[] = {
 276    &passthrough_user_xattr,
 277    &passthrough_acl_xattr,
 278    NULL,
 279};
 280
 281/* for .user none model should be same as passthrough */
 282XattrOperations *none_xattr_ops[] = {
 283    &passthrough_user_xattr,
 284    &none_acl_xattr,
 285    NULL,
 286};
 287