9pfs: enable 9pfs on Windows and Macos
authorSooyoung Ha <yoosah.ha@samsung.com>
Wed, 2 Nov 2016 08:33:34 +0000 (17:33 +0900)
committerSooyoung Ha <yoosah.ha@samsung.com>
Tue, 22 Nov 2016 13:45:41 +0000 (22:45 +0900)
I modify the maru defined codes of 9pfs for applying qemu 2.7 upgrade.

Change-Id: I83abb46d97f07443f1337659f12da8afa1d8eb15
Signed-off-by: Sooyoung Ha <yoosah.ha@samsung.com>
hw/9pfs/9p-local-maru.c
hw/9pfs/9p-maru.c

index d2f4931..7605f1d 100644 (file)
@@ -1,11 +1,12 @@
 /*
  * Virtio 9p backend for Maru
- * Based on hw/9pfs/virtio-9p-local.c:
+ * Based on hw/9pfs/9p-local.c:
  *
- * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Contact:
  *  Sooyoung Ha <yoosah.ha@samsung.com>
+ *  SeokYeon Hwang <syeon.hwang@samsung.com>
  *  YeongKyoon Lee <yeongkyoon.lee@samsung.com>
  *
  * This program is free software; you can redistribute it and/or
@@ -29,9 +30,9 @@
 
 #include "qemu/osdep.h"
 #include "9p.h"
-#include "fsdev/qemu-fsdev.h"   /* local_ops */
 #ifndef CONFIG_WIN32
 #include "9p-xattr.h"
+#include "fsdev/qemu-fsdev.h"   /* local_ops */
 #include <arpa/inet.h>
 #include <pwd.h>
 #include <grp.h>
@@ -571,12 +572,12 @@ static struct dirent *local_readdir(FsContext *ctx, V9fsFidOpenState *fs)
     struct dirent *entry;
 
 again:
-#ifndef CONFIG_WIN32
     entry = readdir(fs->dir.stream);
     if (!entry) {
         return NULL;
     }
 
+#ifndef CONFIG_WIN32
     if (ctx->export_flags & V9FS_SM_MAPPED) {
         entry->d_type = DT_UNKNOWN;
     } else if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
@@ -587,13 +588,8 @@ again:
         entry->d_type = DT_UNKNOWN;
     }
 #else
-    int ret = errno;
-    *result = readdir(fs->dir.stream);
-    ret = (ret == errno ? 0 : errno);
-    entry = *result;
     if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
-        if (!ret && *result != NULL &&
-                !strcmp(entry->d_name, VIRTFS_META_DIR)) {
+        if (!strcmp(entry->d_name, VIRTFS_META_DIR)) {
             /* skp the meta data directory */
             goto again;
         }
index dcc0f2b..ebe4987 100644 (file)
@@ -1,11 +1,12 @@
 /*
  * Virtio 9p backend for Maru
- * Based on hw/9pfs/virtio-9p.c:
+ * Based on hw/9pfs/9p.c:
  *
- * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Contact:
  *  Sooyoung Ha <yoosah.ha@samsung.com>
+ *  SeokYeon Hwang <syeon.hwang@samsung.com>
  *  YeongKyoon Lee <yeongkyoon.lee@samsung.com>
  *
  * This program is free software; you can redistribute it and/or
@@ -29,7 +30,6 @@
 
 #include "qemu/osdep.h"
 #include "hw/virtio/virtio.h"
-#include "hw/i386/pc.h"
 #include "qapi/error.h"
 #include "qemu/error-report.h"
 #include "qemu/iov.h"
@@ -348,6 +348,9 @@ static V9fsFidState *alloc_fid(V9fsState *s, int32_t fid)
     f->next = s->fid_list;
     s->fid_list = f;
 
+    v9fs_readdir_init(&f->fs.dir);
+    v9fs_readdir_init(&f->fs_reclaim.dir);
+
     return f;
 }
 
@@ -1107,6 +1110,7 @@ static void v9fs_attach(void *opaque)
         goto out;
     }
     err += offset;
+    memcpy(&s->root_qid, &qid, sizeof(qid));
     trace_v9fs_attach_return(pdu->tag, pdu->id,
                              qid.type, qid.version, qid.path);
     /*
@@ -1366,6 +1370,23 @@ static int v9fs_walk_marshal(V9fsPDU *pdu, uint16_t nwnames, V9fsQID *qids)
     return offset;
 }
 
+static bool name_is_illegal(const char *name)
+{
+#ifndef CONFIG_WIN32
+    return !*name || strchr(name, '/') != NULL;
+#else
+    return !*name || strchr(name, '\\') != NULL;
+#endif
+}
+
+static bool not_same_qid(const V9fsQID *qid1, const V9fsQID *qid2)
+{
+    return
+        qid1->type != qid2->type ||
+        qid1->version != qid2->version ||
+        qid1->path != qid2->path;
+}
+
 static void v9fs_walk(void *opaque)
 {
     TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__);
@@ -1382,6 +1403,7 @@ static void v9fs_walk(void *opaque)
     V9fsFidState *newfidp = NULL;
     V9fsPDU *pdu = opaque;
     V9fsState *s = pdu->s;
+    V9fsQID qid;
 
     err = pdu_unmarshal(pdu, offset, "ddw", &fid, &newfid, &nwnames);
     if (err < 0) {
@@ -1402,6 +1424,10 @@ static void v9fs_walk(void *opaque)
                 ERR("[%d][ >> %s]\n", __LINE__, __func__);
                 goto out_nofid;
             }
+            if (name_is_illegal(wnames[i].data)) {
+                err = -ENOENT;
+                goto out_nofid;
+            }
             offset += err;
         }
     } else if (nwnames > P9_MAXWELEM) {
@@ -1415,6 +1441,12 @@ static void v9fs_walk(void *opaque)
         err = -ENOENT;
         goto out_nofid;
     }
+
+    err = fid_to_qid(pdu, fidp, &qid);
+    if (err < 0) {
+        goto out;
+    }
+
     v9fs_path_init(&dpath);
     v9fs_path_init(&path);
     /*
@@ -1424,17 +1456,23 @@ static void v9fs_walk(void *opaque)
     v9fs_path_copy(&dpath, &fidp->path);
     v9fs_path_copy(&path, &fidp->path);
     for (name_idx = 0; name_idx < nwnames; name_idx++) {
-        err = v9fs_co_name_to_path(pdu, &dpath, wnames[name_idx].data, &path);
-        if (err < 0) {
-            ERR("[%d][ >> %s]\n", __LINE__, __func__);
-            goto out;
-        }
-        err = v9fs_co_lstat(pdu, &path, &stbuf);
-        if (err < 0) {
-            goto out;
+        if (not_same_qid(&pdu->s->root_qid, &qid) ||
+            strcmp("..", wnames[name_idx].data)) {
+            err = v9fs_co_name_to_path(pdu, &dpath, wnames[name_idx].data,
+                                       &path);
+            if (err < 0) {
+                ERR("[%d][ >> %s]\n", __LINE__, __func__);
+                goto out;
+            }
+
+            err = v9fs_co_lstat(pdu, &path, &stbuf);
+            if (err < 0) {
+                goto out;
+            }
+            stat_to_qid(&stbuf, &qid);
+            v9fs_path_copy(&dpath, &path);
         }
-        stat_to_qid(&stbuf, &qids[name_idx]);
-        v9fs_path_copy(&dpath, &path);
+        memcpy(&qids[name_idx], &qid, sizeof(qid));
     }
     if (fid == newfid) {
         BUG_ON(fidp->fid_type != P9_FID_NONE);
@@ -1612,6 +1650,16 @@ static void v9fs_lcreate(void *opaque)
     }
     trace_v9fs_lcreate(pdu->tag, pdu->id, dfid, flags, mode, gid);
 
+    if (name_is_illegal(name.data)) {
+        err = -ENOENT;
+        goto out_nofid;
+    }
+
+    if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
+        err = -EEXIST;
+        goto out_nofid;
+    }
+
     fidp = get_fid(pdu, dfid);
     if (fidp == NULL) {
         ERR("[%d][ >> %s]\n", __LINE__, __func__);
@@ -1773,8 +1821,6 @@ static int v9fs_do_readdir_with_stat(V9fsPDU *pdu,
         return saved_dir_pos;
     }
 
-    dent = g_malloc(sizeof(struct dirent));
-
     while (1) {
         v9fs_path_init(&path);
 
@@ -1788,17 +1834,17 @@ static int v9fs_do_readdir_with_stat(V9fsPDU *pdu,
         err = v9fs_co_name_to_path(pdu, &fidp->path, dent->d_name, &path);
         if (err < 0) {
             ERR("[%d][ >> %s]\n", __LINE__, __func__);
-            goto out;
+            break;
         }
         err = v9fs_co_lstat(pdu, &path, &stbuf);
         if (err < 0) {
             ERR("[%d][ >> %s]\n", __LINE__, __func__);
-            goto out;
+            break;
         }
         err = stat_to_v9stat(pdu, &path, &stbuf, &v9stat);
         if (err < 0) {
             ERR("[%d][ >> %s]\n", __LINE__, __func__);
-            goto out;
+            break;
         }
         /* 11 = 7 + 4 (7 = start offset, 4 = space for storing count) */
         len = pdu_marshal(pdu, 11 + count, "S", &v9stat);
@@ -1810,7 +1856,6 @@ static int v9fs_do_readdir_with_stat(V9fsPDU *pdu,
             v9fs_co_seekdir(pdu, fidp, saved_dir_pos);
             v9fs_stat_free(&v9stat);
             v9fs_path_free(&path);
-            g_free(dent);
             return count;
         }
         count += len;
@@ -1822,8 +1867,6 @@ static int v9fs_do_readdir_with_stat(V9fsPDU *pdu,
         saved_dir_pos = v9fs_co_telldir(pdu, fidp);
 #endif
     }
-out:
-    g_free(dent);
 
     v9fs_readdir_unlock(&fidp->fs.dir);
 
@@ -1986,8 +2029,6 @@ static int v9fs_do_readdir(V9fsPDU *pdu,
         return saved_dir_pos;
     }
 
-    dent = g_malloc(sizeof(struct dirent));
-
     while (1) {
         v9fs_readdir_lock(&fidp->fs.dir);
 
@@ -1999,10 +2040,11 @@ static int v9fs_do_readdir(V9fsPDU *pdu,
         v9fs_string_init(&name);
         v9fs_string_sprintf(&name, "%s", dent->d_name);
         if ((count + v9fs_readdir_data_size(&name)) > max_count) {
+            v9fs_readdir_unlock(&fidp->fs.dir);
+
             /* Ran out of buffer. Set dir back to old position and return */
             v9fs_co_seekdir(pdu, fidp, saved_dir_pos);
             v9fs_string_free(&name);
-            g_free(dent);
             return count;
         }
         /*
@@ -2039,7 +2081,6 @@ static int v9fs_do_readdir(V9fsPDU *pdu,
         if (len < 0) {
             v9fs_co_seekdir(pdu, fidp, saved_dir_pos);
             v9fs_string_free(&name);
-            g_free(dent);
             return len;
         }
         count += len;
@@ -2050,7 +2091,6 @@ static int v9fs_do_readdir(V9fsPDU *pdu,
         saved_dir_pos = d_offset;
 #endif
     }
-    g_free(dent);
 
     v9fs_readdir_unlock(&fidp->fs.dir);
 
@@ -2286,6 +2326,16 @@ static void v9fs_create(void *opaque)
     }
     trace_v9fs_create(pdu->tag, pdu->id, fid, name.data, perm, mode);
 
+    if (name_is_illegal(name.data)) {
+        err = -ENOENT;
+        goto out_nofid;
+    }
+
+    if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
+        err = -EEXIST;
+        goto out_nofid;
+    }
+
     fidp = get_fid(pdu, fid);
     if (fidp == NULL) {
         ERR("[%d][ >> %s]\n", __LINE__, __func__);
@@ -2473,6 +2523,16 @@ static void v9fs_symlink(void *opaque)
     }
     trace_v9fs_symlink(pdu->tag, pdu->id, dfid, name.data, symname.data, gid);
 
+    if (name_is_illegal(name.data)) {
+        err = -ENOENT;
+        goto out_nofid;
+    }
+
+    if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
+        err = -EEXIST;
+        goto out_nofid;
+    }
+
     dfidp = get_fid(pdu, dfid);
     if (dfidp == NULL) {
         err = -EINVAL;
@@ -2553,6 +2613,16 @@ static void v9fs_link(void *opaque)
     }
     trace_v9fs_link(pdu->tag, pdu->id, dfid, oldfid, name.data);
 
+    if (name_is_illegal(name.data)) {
+        err = -ENOENT;
+        goto out_nofid;
+    }
+
+    if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
+        err = -EEXIST;
+        goto out_nofid;
+    }
+
     dfidp = get_fid(pdu, dfid);
     if (dfidp == NULL) {
         err = -ENOENT;
@@ -2637,6 +2707,22 @@ static void v9fs_unlinkat(void *opaque)
     if (err < 0) {
         goto out_nofid;
     }
+
+    if (name_is_illegal(name.data)) {
+        err = -ENOENT;
+        goto out_nofid;
+    }
+
+    if (!strcmp(".", name.data)) {
+        err = -EINVAL;
+        goto out_nofid;
+    }
+
+    if (!strcmp("..", name.data)) {
+        err = -ENOTEMPTY;
+        goto out_nofid;
+    }
+
     dfidp = get_fid(pdu, dfid);
     if (dfidp == NULL) {
         err = -EINVAL;
@@ -2744,6 +2830,17 @@ static void v9fs_rename(void *opaque)
     if (err < 0) {
         goto out_nofid;
     }
+
+    if (name_is_illegal(name.data)) {
+        err = -ENOENT;
+        goto out_nofid;
+    }
+
+    if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
+        err = -EISDIR;
+        goto out_nofid;
+    }
+
     fidp = get_fid(pdu, fid);
     if (fidp == NULL) {
         err = -ENOENT;
@@ -2858,6 +2955,17 @@ static void v9fs_renameat(void *opaque)
         goto out_err;
     }
 
+    if (name_is_illegal(old_name.data) || name_is_illegal(new_name.data)) {
+        err = -ENOENT;
+        goto out_err;
+    }
+
+    if (!strcmp(".", old_name.data) || !strcmp("..", old_name.data) ||
+        !strcmp(".", new_name.data) || !strcmp("..", new_name.data)) {
+        err = -EISDIR;
+        goto out_err;
+    }
+
     v9fs_path_write_lock(s);
     err = v9fs_complete_renameat(pdu, olddirfid,
                                  &old_name, newdirfid, &new_name);
@@ -3085,6 +3193,16 @@ static void v9fs_mknod(void *opaque)
     }
     trace_v9fs_mknod(pdu->tag, pdu->id, fid, mode, major, minor);
 
+    if (name_is_illegal(name.data)) {
+        err = -ENOENT;
+        goto out_nofid;
+    }
+
+    if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
+        err = -EEXIST;
+        goto out_nofid;
+    }
+
     fidp = get_fid(pdu, fid);
     if (fidp == NULL) {
         err = -ENOENT;
@@ -3243,6 +3361,16 @@ static void v9fs_mkdir(void *opaque)
     }
     trace_v9fs_mkdir(pdu->tag, pdu->id, fid, name.data, mode, gid);
 
+    if (name_is_illegal(name.data)) {
+        err = -ENOENT;
+        goto out_nofid;
+    }
+
+    if (!strcmp(".", name.data) || !strcmp("..", name.data)) {
+        err = -EEXIST;
+        goto out_nofid;
+    }
+
     fidp = get_fid(pdu, fid);
     if (fidp == NULL) {
         err = -ENOENT;