diff mbox

[09/13] hw/9pfs: File ownership and others

Message ID 1320094412-19091-10-git-send-email-mohan@in.ibm.com
State New
Headers show

Commit Message

Mohan Kumar M Oct. 31, 2011, 8:53 p.m. UTC
From: "M. Mohan Kumar" <mohan@in.ibm.com>

Add file ownership interfaces like chmod/chown, utime update, rename,
remove and truncating files for proxy FS

Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
---
 hw/9pfs/proxy.h               |    6 ++
 hw/9pfs/virtfs-proxy-helper.c |   61 ++++++++++++++++++-
 hw/9pfs/virtio-9p-proxy.c     |  134 +++++++++++++++++++++++++++++++++++++----
 3 files changed, 188 insertions(+), 13 deletions(-)
diff mbox

Patch

diff --git a/hw/9pfs/proxy.h b/hw/9pfs/proxy.h
index 5a13b5f..557a8f4 100644
--- a/hw/9pfs/proxy.h
+++ b/hw/9pfs/proxy.h
@@ -24,6 +24,12 @@  enum {
     T_LSTAT,
     T_READLINK,
     T_STATFS,
+    T_CHMOD,
+    T_CHOWN,
+    T_TRUNCATE,
+    T_UTIME,
+    T_RENAME,
+    T_REMOVE,
 };
 
 #endif
diff --git a/hw/9pfs/virtfs-proxy-helper.c b/hw/9pfs/virtfs-proxy-helper.c
index 9fa4a30..845e3c6 100644
--- a/hw/9pfs/virtfs-proxy-helper.c
+++ b/hw/9pfs/virtfs-proxy-helper.c
@@ -423,7 +423,9 @@  static int process_requests(int sock)
     int valid_fd;
     V9fsString oldpath, path;
     char *response = NULL;
-    int size;
+    int size, mode, uid, gid;
+    struct timespec spec[2];
+    uint64_t offset;
 
     iovec.iov_base = g_malloc(BUFF_SZ);
     iovec.iov_len = BUFF_SZ;
@@ -473,6 +475,57 @@  static int process_requests(int sock)
             }
             v9fs_string_free(&path);
             break;
+        case T_CHMOD:
+            v9fs_unmarshal(&iovec, 1, 0, "sd", &path, &mode);
+            retval = chmod(path.data, mode);
+            if (retval < 0) {
+                retval = -errno;
+            }
+            v9fs_string_free(&path);
+            break;
+        case T_CHOWN:
+            v9fs_unmarshal(&iovec, 1, 0, "sdd", &path, &uid, &gid);
+            retval = lchown(path.data, uid, gid);
+            if (retval < 0) {
+                retval = -errno;
+            }
+            v9fs_string_free(&path);
+            break;
+        case T_TRUNCATE:
+            v9fs_unmarshal(&iovec, 1, 0, "sq", &path, &offset);
+            retval = truncate(path.data, offset);
+            if (retval < 0) {
+                retval = -errno;
+            }
+            v9fs_string_free(&path);
+            break;
+        case T_UTIME:
+            v9fs_unmarshal(&iovec, 1, 0, "sqqqq", &path,
+                            &spec[0].tv_sec, &spec[0].tv_nsec,
+                            &spec[1].tv_sec, &spec[1].tv_nsec);
+            retval = utimensat(AT_FDCWD, path.data, spec, AT_SYMLINK_NOFOLLOW);
+            if (retval < 0) {
+                retval = -errno;
+            }
+            v9fs_string_free(&path);
+            break;
+        case T_RENAME:
+            v9fs_unmarshal(&iovec, 1, 0, "ss", &oldpath, &path);
+            retval = rename(oldpath.data, path.data);
+            if (retval < 0) {
+                retval = -errno;
+            }
+            v9fs_string_free(&oldpath);
+            v9fs_string_free(&path);
+            break;
+        case T_REMOVE:
+            v9fs_unmarshal(&iovec, 1, 0, "s", &path);
+            retval = remove(path.data);
+            if (retval < 0) {
+                retval = -errno;
+            }
+            v9fs_string_free(&path);
+            break;
         default:
             goto error;
             break;
@@ -486,6 +539,12 @@  static int process_requests(int sock)
         case T_MKDIR:
         case T_SYMLINK:
         case T_LINK:
+        case T_CHMOD:
+        case T_CHOWN:
+        case T_TRUNCATE:
+        case T_UTIME:
+        case T_RENAME:
+        case T_REMOVE:
              sendfd(sock, retval, valid_fd);
             break;
         case T_LSTAT:
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index 1328e59..47419dd 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -102,6 +102,8 @@  static int v9fs_request(V9fsProxy *proxy, int type,
     struct iovec *iovec = NULL;
     dev_t rdev;
     int msg_size, size;
+    struct timespec spec[2];
+    uint64_t offset;
 
     qemu_mutex_lock(&proxy->mutex);
 
@@ -199,6 +201,63 @@  static int v9fs_request(V9fsProxy *proxy, int type,
         v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
         header.size += sizeof(header);
         break;
+    case T_CHMOD:
+        path = va_arg(ap, V9fsString *);
+        mode = va_arg(ap, int);
+        header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "sd",
+                        path, mode);
+        header.type = T_CHMOD;
+        v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+        header.size += sizeof(header);
+        break;
+    case T_CHOWN:
+        path = va_arg(ap, V9fsString *);
+        uid = va_arg(ap, int);
+        gid = va_arg(ap, int);
+        header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "sdd",
+                        path, uid, gid);
+        header.type = T_CHOWN;
+        v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+        header.size += sizeof(header);
+        break;
+    case T_TRUNCATE:
+        path = va_arg(ap, V9fsString *);
+        offset = va_arg(ap, uint64_t);
+        header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "sq",
+                        path, offset);
+        header.type = T_TRUNCATE;
+        v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+        header.size += sizeof(header);
+        break;
+    case T_UTIME:
+        path = va_arg(ap, V9fsString *);
+        spec[0].tv_sec = va_arg(ap, long);
+        spec[0].tv_nsec = va_arg(ap, long);
+        spec[1].tv_sec = va_arg(ap, long);
+        spec[1].tv_nsec = va_arg(ap, long);
+        header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "sqqqq",
+                        path, spec[0].tv_sec, spec[1].tv_nsec,
+                        spec[1].tv_sec, spec[1].tv_nsec);
+        header.type = T_UTIME;
+        v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+        header.size += sizeof(header);
+        break;
+    case T_RENAME:
+        oldpath = va_arg(ap, V9fsString *);
+        path = va_arg(ap, V9fsString *);
+        header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "ss",
+                        oldpath, path);
+        header.type = T_RENAME;
+        v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+        header.size += sizeof(header);
+        break;
+    case T_REMOVE:
+        path = va_arg(ap, V9fsString *);
+        header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "s", path);
+        header.type = T_REMOVE;
+        v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+        header.size += sizeof(header);
+        break;
     default:
         fprintf(stderr, "Invalid type %d\n", type);
         goto close_error;
@@ -221,6 +280,12 @@  static int v9fs_request(V9fsProxy *proxy, int type,
     case T_MKDIR:
     case T_SYMLINK:
     case T_LINK:
+    case T_CHMOD:
+    case T_CHOWN:
+    case T_RENAME:
+    case T_TRUNCATE:
+    case T_UTIME:
+    case T_REMOVE:
         retval = v9fs_receivefd(proxy->sockfd, &sock_error);
         if (sock_error) {
             goto close_error;
@@ -386,8 +451,13 @@  static ssize_t proxy_pwritev(FsContext *ctx, V9fsFidOpenState *fs,
 
 static int proxy_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    retval = v9fs_request(fs_ctx->private, T_CHMOD, NULL, "sd",
+                    fs_path, credp->fc_mode);
+    if (retval < 0) {
+        errno = -retval;
+    }
+    return retval;
 }
 
 static int proxy_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
@@ -499,34 +569,74 @@  static int proxy_link(FsContext *ctx, V9fsPath *oldpath,
 
 static int proxy_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+
+    retval = v9fs_request(ctx->private, T_TRUNCATE, NULL, "sq", fs_path, size);
+    if (retval < 0) {
+        errno = -retval;
+        return -1;
+    }
+    return 0;
 }
 
 static int proxy_rename(FsContext *ctx, const char *oldpath,
                         const char *newpath)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    V9fsString oldname, newname;
+
+    v9fs_string_init(&oldname);
+    v9fs_string_init(&newname);
+
+    v9fs_string_sprintf(&oldname, "%s", oldpath);
+    v9fs_string_sprintf(&newname, "%s", newpath);
+    retval = v9fs_request(ctx->private, T_RENAME, NULL, "ss",
+                    &oldname, &newname);
+    if (retval < 0) {
+        errno = -retval;
+    }
+    v9fs_string_free(&oldname);
+    v9fs_string_free(&newname);
+    return retval;
 }
 
 static int proxy_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    retval = v9fs_request(fs_ctx->private, T_CHOWN, NULL, "sdd",
+                    fs_path, credp->fc_uid, credp->fc_gid);
+    if (retval < 0) {
+        errno = -retval;
+    }
+    return retval;
 }
 
 static int proxy_utimensat(FsContext *s, V9fsPath *fs_path,
                            const struct timespec *buf)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    retval = v9fs_request(s->private, T_UTIME, NULL, "sqqqq",
+                    fs_path,
+                    buf[0].tv_sec, buf[0].tv_nsec,
+                    buf[1].tv_sec, buf[1].tv_nsec);
+    if (retval < 0) {
+        errno = -retval;
+    }
+    return retval;
 }
 
 static int proxy_remove(FsContext *ctx, const char *path)
 {
-    errno = EOPNOTSUPP;
-    return -1;
+    int retval;
+    V9fsString name;
+    v9fs_string_init(&name);
+    v9fs_string_sprintf(&name, "%s", path);
+    retval = v9fs_request(ctx->private, T_REMOVE, NULL, "s", &name);
+    if (retval < 0) {
+        errno = -retval;
+    }
+    v9fs_string_free(&name);
+    return retval;
 }
 
 static int proxy_fsync(FsContext *ctx, V9fsFidOpenState *fs, int datasync)