[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [qemu-xen master] 9pfs: fix readdir() for 9p2000.u



commit e90997dc8f8272378b259a0080a0062597e72c10
Author:     Jan Dakinevich <jan.dakinevich@xxxxxxxxx>
AuthorDate: Wed Sep 20 08:48:51 2017 +0200
Commit:     Michael Roth <mdroth@xxxxxxxxxxxxxxxxxx>
CommitDate: Fri Sep 22 18:23:05 2017 -0500

    9pfs: fix readdir() for 9p2000.u
    
    If the client is using 9p2000.u, the following occurs:
    
    $ cd ${virtfs_shared_dir}
    $ mkdir -p a/b/c
    $ ls a/b
    ls: cannot access 'a/b/a': No such file or directory
    ls: cannot access 'a/b/b': No such file or directory
    a  b  c
    
    instead of the expected:
    
    $ ls a/b
    c
    
    This is a regression introduced by commit f57f5878578a;
    local_name_to_path() now resolves ".." and "." in paths,
    and v9fs_do_readdir_with_stat()->stat_to_v9stat() then
    copies the basename of the resulting path to the response.
    With the example above, this means that "." and ".." are
    turned into "b" and "a" respectively...
    
    stat_to_v9stat() currently assumes it is passed a full
    canonicalized path and uses it to do two different things:
    1) to pass it to v9fs_co_readlink() in case the file is a symbolic
       link
    2) to set the name field of the V9fsStat structure to the basename
       part of the given path
    
    It only has two users: v9fs_stat() and v9fs_do_readdir_with_stat().
    
    v9fs_stat() really needs 1) and 2) to be performed since it starts
    with the full canonicalized path stored in the fid. It is different
    for v9fs_do_readdir_with_stat() though because the name we want to
    put into the V9fsStat structure is the d_name field of the dirent
    actually (ie, we want to keep the "." and ".." special names). So,
    we only need 1) in this case.
    
    This patch hence adds a basename argument to stat_to_v9stat(), to
    be used to set the name field of the V9fsStat structure, and moves
    the basename logic to v9fs_stat().
    
    Signed-off-by: Jan Dakinevich <jan.dakinevich@xxxxxxxxx>
    (groug, renamed old name argument to path and updated changelog)
    Signed-off-by: Greg Kurz <groug@xxxxxxxx>
    
    (cherry picked from commit 6069537f4336a59054afda91a6545d3648c64619)
    Signed-off-by: Michael Roth <mdroth@xxxxxxxxxxxxxxxxxx>
---
 hw/9pfs/9p.c | 22 +++++++++-------------
 1 file changed, 9 insertions(+), 13 deletions(-)

diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index 333dbb6..6d68db0 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -803,12 +803,12 @@ static uint32_t stat_to_v9mode(const struct stat *stbuf)
     return mode;
 }
 
-static int coroutine_fn stat_to_v9stat(V9fsPDU *pdu, V9fsPath *name,
+static int coroutine_fn stat_to_v9stat(V9fsPDU *pdu, V9fsPath *path,
+                                       const char *basename,
                                        const struct stat *stbuf,
                                        V9fsStat *v9stat)
 {
     int err;
-    const char *str;
 
     memset(v9stat, 0, sizeof(*v9stat));
 
@@ -829,7 +829,7 @@ static int coroutine_fn stat_to_v9stat(V9fsPDU *pdu, 
V9fsPath *name,
     v9fs_string_free(&v9stat->extension);
 
     if (v9stat->mode & P9_STAT_MODE_SYMLINK) {
-        err = v9fs_co_readlink(pdu, name, &v9stat->extension);
+        err = v9fs_co_readlink(pdu, path, &v9stat->extension);
         if (err < 0) {
             return err;
         }
@@ -842,14 +842,7 @@ static int coroutine_fn stat_to_v9stat(V9fsPDU *pdu, 
V9fsPath *name,
                 "HARDLINKCOUNT", (unsigned long)stbuf->st_nlink);
     }
 
-    str = strrchr(name->data, '/');
-    if (str) {
-        str += 1;
-    } else {
-        str = name->data;
-    }
-
-    v9fs_string_sprintf(&v9stat->name, "%s", str);
+    v9fs_string_sprintf(&v9stat->name, "%s", basename);
 
     v9stat->size = 61 +
         v9fs_string_size(&v9stat->name) +
@@ -1058,6 +1051,7 @@ static void coroutine_fn v9fs_stat(void *opaque)
     struct stat stbuf;
     V9fsFidState *fidp;
     V9fsPDU *pdu = opaque;
+    char *basename;
 
     err = pdu_unmarshal(pdu, offset, "d", &fid);
     if (err < 0) {
@@ -1074,7 +1068,9 @@ static void coroutine_fn v9fs_stat(void *opaque)
     if (err < 0) {
         goto out;
     }
-    err = stat_to_v9stat(pdu, &fidp->path, &stbuf, &v9stat);
+    basename = g_path_get_basename(fidp->path.data);
+    err = stat_to_v9stat(pdu, &fidp->path, basename, &stbuf, &v9stat);
+    g_free(basename);
     if (err < 0) {
         goto out;
     }
@@ -1750,7 +1746,7 @@ static int coroutine_fn v9fs_do_readdir_with_stat(V9fsPDU 
*pdu,
         if (err < 0) {
             break;
         }
-        err = stat_to_v9stat(pdu, &path, &stbuf, &v9stat);
+        err = stat_to_v9stat(pdu, &path, dent->d_name, &stbuf, &v9stat);
         if (err < 0) {
             break;
         }
--
generated by git-patchbot for /home/xen/git/qemu-xen.git#master

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
https://lists.xenproject.org/xen-changelog

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.