 70fc55ebe4
			
		
	
	
		70fc55ebe4
		
	
	
	
	
		
			
			Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Signed-off-by: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com>
		
			
				
	
	
		
			157 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			157 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Virtio 9p  xattr callback
 | |
|  *
 | |
|  * Copyright IBM, Corp. 2010
 | |
|  *
 | |
|  * Authors:
 | |
|  * Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
 | |
|  *
 | |
|  * This work is licensed under the terms of the GNU GPL, version 2.  See
 | |
|  * the COPYING file in the top-level directory.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| #include "virtio.h"
 | |
| #include "virtio-9p.h"
 | |
| #include "file-op-9p.h"
 | |
| #include "virtio-9p-xattr.h"
 | |
| 
 | |
| 
 | |
| static XattrOperations *get_xattr_operations(XattrOperations **h,
 | |
|                                              const char *name)
 | |
| {
 | |
|     XattrOperations *xops;
 | |
|     for (xops = *(h)++; xops != NULL; xops = *(h)++) {
 | |
|         if (!strncmp(name, xops->name, strlen(xops->name))) {
 | |
|             return xops;
 | |
|         }
 | |
|     }
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| ssize_t v9fs_get_xattr(FsContext *ctx, const char *path,
 | |
|                        const char *name, void *value, size_t size)
 | |
| {
 | |
|     XattrOperations *xops = get_xattr_operations(ctx->xops, name);
 | |
|     if (xops) {
 | |
|         return xops->getxattr(ctx, path, name, value, size);
 | |
|     }
 | |
|     errno = -EOPNOTSUPP;
 | |
|     return -1;
 | |
| }
 | |
| 
 | |
| ssize_t pt_listxattr(FsContext *ctx, const char *path,
 | |
|                      char *name, void *value, size_t size)
 | |
| {
 | |
|     int name_size = strlen(name) + 1;
 | |
|     if (!value) {
 | |
|         return name_size;
 | |
|     }
 | |
| 
 | |
|     if (size < name_size) {
 | |
|         errno = ERANGE;
 | |
|         return -1;
 | |
|     }
 | |
| 
 | |
|     strncpy(value, name, name_size);
 | |
|     return name_size;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Get the list and pass to each layer to find out whether
 | |
|  * to send the data or not
 | |
|  */
 | |
| ssize_t v9fs_list_xattr(FsContext *ctx, const char *path,
 | |
|                         void *value, size_t vsize)
 | |
| {
 | |
|     ssize_t size = 0;
 | |
|     void *ovalue = value;
 | |
|     XattrOperations *xops;
 | |
|     char *orig_value, *orig_value_start;
 | |
|     ssize_t xattr_len, parsed_len = 0, attr_len;
 | |
| 
 | |
|     /* Get the actual len */
 | |
|     xattr_len = llistxattr(rpath(ctx, path), value, 0);
 | |
| 
 | |
|     /* Now fetch the xattr and find the actual size */
 | |
|     orig_value = qemu_malloc(xattr_len);
 | |
|     xattr_len = llistxattr(rpath(ctx, path), orig_value, xattr_len);
 | |
| 
 | |
|     /* store the orig pointer */
 | |
|     orig_value_start = orig_value;
 | |
|     while (xattr_len > parsed_len) {
 | |
|         xops = get_xattr_operations(ctx->xops, orig_value);
 | |
|         if (!xops) {
 | |
|             goto next_entry;
 | |
|         }
 | |
| 
 | |
|         if (!value) {
 | |
|             size += xops->listxattr(ctx, path, orig_value, value, vsize);
 | |
|         } else {
 | |
|             size = xops->listxattr(ctx, path, orig_value, value, vsize);
 | |
|             if (size < 0) {
 | |
|                 goto err_out;
 | |
|             }
 | |
|             value += size;
 | |
|             vsize -= size;
 | |
|         }
 | |
| next_entry:
 | |
|         /* Got the next entry */
 | |
|         attr_len = strlen(orig_value) + 1;
 | |
|         parsed_len += attr_len;
 | |
|         orig_value += attr_len;
 | |
|     }
 | |
|     if (value) {
 | |
|         size = value - ovalue;
 | |
|     }
 | |
| 
 | |
| err_out:
 | |
|     qemu_free(orig_value_start);
 | |
|     return size;
 | |
| }
 | |
| 
 | |
| int v9fs_set_xattr(FsContext *ctx, const char *path, const char *name,
 | |
|                    void *value, size_t size, int flags)
 | |
| {
 | |
|     XattrOperations *xops = get_xattr_operations(ctx->xops, name);
 | |
|     if (xops) {
 | |
|         return xops->setxattr(ctx, path, name, value, size, flags);
 | |
|     }
 | |
|     errno = -EOPNOTSUPP;
 | |
|     return -1;
 | |
| 
 | |
| }
 | |
| 
 | |
| int v9fs_remove_xattr(FsContext *ctx,
 | |
|                       const char *path, const char *name)
 | |
| {
 | |
|     XattrOperations *xops = get_xattr_operations(ctx->xops, name);
 | |
|     if (xops) {
 | |
|         return xops->removexattr(ctx, path, name);
 | |
|     }
 | |
|     errno = -EOPNOTSUPP;
 | |
|     return -1;
 | |
| 
 | |
| }
 | |
| 
 | |
| XattrOperations *mapped_xattr_ops[] = {
 | |
|     &mapped_user_xattr,
 | |
|     &mapped_pacl_xattr,
 | |
|     &mapped_dacl_xattr,
 | |
|     NULL,
 | |
| };
 | |
| 
 | |
| XattrOperations *passthrough_xattr_ops[] = {
 | |
|     &passthrough_user_xattr,
 | |
|     &passthrough_acl_xattr,
 | |
|     NULL,
 | |
| };
 | |
| 
 | |
| /* for .user none model should be same as passthrough */
 | |
| XattrOperations *none_xattr_ops[] = {
 | |
|     &passthrough_user_xattr,
 | |
|     &none_acl_xattr,
 | |
|     NULL,
 | |
| };
 |