qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH] virtio-9p: Make rpath function thread safe


From: M. Mohan Kumar
Subject: [Qemu-devel] [PATCH] virtio-9p: Make rpath function thread safe
Date: Fri, 15 Apr 2011 14:35:57 +0530

Use dynamically allocated memory to return concatenated path
(fs_root and file path) instead of a static buffer. Caller has to free
the memory.

Signed-off-by: M. Mohan Kumar <address@hidden>
---
This patch depends on my chroot patchset.
http://patchwork.ozlabs.org/patch/89033/

 hw/9pfs/virtio-9p-local.c |  551 ++++++++++++++++++++++++++-------------------
 hw/file-op-9p.h           |   10 +-
 2 files changed, 322 insertions(+), 239 deletions(-)

diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c
index fa5c88f..abe3987 100644
--- a/hw/9pfs/virtio-9p-local.c
+++ b/hw/9pfs/virtio-9p-local.c
@@ -109,15 +109,42 @@ static int get_dirfd(FsContext *fs_ctx, const char *path)
     return fd;
 }
 
+static int passthrough_lstat(FsContext *fs_ctx, const char *path,
+                struct stat *stbuf)
+{
+    int pfd, retval, serrno = 0;
+    char *tmp_path;
+
+    pfd = get_dirfd(fs_ctx, path);
+    if (pfd < 0) {
+        return -1;
+    }
+    tmp_path = qemu_strdup(path);
+    retval = fstatat(pfd, basename(tmp_path), stbuf, AT_SYMLINK_NOFOLLOW);
+    serrno = retval < 0 ? errno : 0;
+    close(pfd);
+    qemu_free(tmp_path);
+    errno = serrno ? serrno : errno;
+    return retval;
+}
+
 static int local_lstat(FsContext *fs_ctx, const char *path, struct stat *stbuf)
 {
-    int err;
+    int err, serrno = 0;
+    char *full_path;
 
+    if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
+        return passthrough_lstat(fs_ctx, path, stbuf);
+    }
+    full_path = rpath(fs_ctx, path);
+    err = lstat(full_path, stbuf);
+    if (err < 0) {
+        serrno = errno;
+        qemu_free(full_path);
+        errno = serrno;
+        return err;
+    }
     if (fs_ctx->fs_sm == SM_MAPPED) {
-        err =  lstat(rpath(fs_ctx, path), stbuf);
-        if (err) {
-            return err;
-        }
         /* Actual credentials are part of extended attrs */
         uid_t tmp_uid;
         gid_t tmp_gid;
@@ -137,29 +164,10 @@ static int local_lstat(FsContext *fs_ctx, const char 
*path, struct stat *stbuf)
         }
         if (getxattr(rpath(fs_ctx, path), "user.virtfs.rdev", &tmp_dev,
                         sizeof(dev_t)) > 0) {
-                stbuf->st_rdev = tmp_dev;
-        }
-    } else if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
-        int pfd, serrno = 0;
-        char *tmp_path;
-
-        pfd = get_dirfd(fs_ctx, path);
-        if (pfd < 0) {
-            return -1;
-        }
-        tmp_path = qemu_strdup(path);
-        err = fstatat(pfd, basename(tmp_path), stbuf, AT_SYMLINK_NOFOLLOW);
-        if (err < 0) {
-            serrno = errno;
-        }
-        close(pfd);
-        qemu_free(tmp_path);
-        if (err < 0) {
-            errno = serrno;
+            stbuf->st_rdev = tmp_dev;
         }
-    } else {
-        err =  lstat(rpath(fs_ctx, path), stbuf);
     }
+    qemu_free(full_path);
     return err;
 }
 
@@ -197,54 +205,62 @@ static int local_set_xattr(const char *path, FsCred 
*credp)
     return 0;
 }
 
-static int local_post_create_none(FsContext *fs_ctx, const char *path,
-        FsCred *credp)
+static void local_post_create_none(const char *path, FsCred *credp)
 {
-    int retval;
-    if (chmod(rpath(fs_ctx, path), credp->fc_mode & 07777) < 0) {
+    chmod(path, credp->fc_mode & 07777);
+    lchown(path, credp->fc_uid, credp->fc_gid);
+}
+
+static ssize_t passthrough_readlink(FsContext *fs_ctx, const char *path,
+        char *buf, size_t bufsz)
+{
+    int pfd, serrno = 0, tsize;
+    char *tmp_path;
+    pfd = get_dirfd(fs_ctx, path);
+    if (pfd < 0) {
         return -1;
     }
-    retval = lchown(rpath(fs_ctx, path), credp->fc_uid, credp->fc_gid);
-    return 0;
+
+    tmp_path = qemu_strdup(path);
+    tsize = readlinkat(pfd, basename(tmp_path), buf, bufsz);
+    serrno = tsize < 0 ? errno : 0;
+    close(pfd);
+    qemu_free(tmp_path);
+    errno = serrno ? serrno : errno;
+    return tsize;
 }
 
 static ssize_t local_readlink(FsContext *fs_ctx, const char *path,
         char *buf, size_t bufsz)
 {
-    ssize_t tsize = -1;
+    ssize_t tsize = -1, serrno = 0;
+    char *full_path;
+
+    if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
+        return passthrough_readlink(fs_ctx, path, buf, bufsz);
+    }
+    full_path = rpath(fs_ctx, path);
     if (fs_ctx->fs_sm == SM_MAPPED) {
         int fd;
-        fd = open(rpath(fs_ctx, path), O_RDONLY);
-        if (fd == -1) {
-            return -1;
+        fd = open(full_path, O_RDONLY);
+        if (fd < 0) {
+            serrno = errno;
+            goto err_end;
         }
         do {
             tsize = read(fd, (void *)buf, bufsz);
         } while (tsize == -1 && errno == EINTR);
+        serrno = tsize < 0 ? errno : serrno;
         close(fd);
-        return tsize;
     } else if (fs_ctx->fs_sm == SM_NONE) {
         tsize = readlink(rpath(fs_ctx, path), buf, bufsz);
-    } else if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
-        int pfd, serrno = 0;
-        char *tmp_path;
-        pfd = get_dirfd(fs_ctx, path);
-        if (pfd < 0) {
-            return -1;
-        }
-
-        tmp_path = qemu_strdup(path);
-        tsize = readlinkat(pfd, basename(tmp_path), buf, bufsz);
-        if (tsize < 0) {
-            serrno = errno;
-        }
-        close(pfd);
-        qemu_free(tmp_path);
-        if (tsize < 0) {
-            errno = serrno;
-        }
     }
+    qemu_free(full_path);
     return tsize;
+err_end:
+    qemu_free(full_path);
+    errno = serrno;
+    return -1;
 }
 
 static int local_close(FsContext *ctx, int fd)
@@ -259,15 +275,25 @@ static int local_closedir(FsContext *ctx, DIR *dir)
 
 static int local_open(FsContext *fs_ctx, const char *path, int flags)
 {
+    char *full_path;
+    int fd, serrno = 0;
     if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
         return passthrough_request(fs_ctx, NULL, path, flags, NULL, T_OPEN);
-    } else {
-        return open(rpath(fs_ctx, path), flags);
     }
+    full_path = rpath(fs_ctx, path);
+    fd = open(full_path, flags);
+    serrno = fd < 0 ? errno : 0;
+    qemu_free(full_path);
+    errno = serrno ? serrno : errno;
+    return fd;
 }
 
 static DIR *local_opendir(FsContext *fs_ctx, const char *path)
 {
+    char *full_path;
+    int serrno = 0;
+    DIR *retval;
+
     if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
         int fd;
         fd = passthrough_request(fs_ctx, NULL, path, O_DIRECTORY, NULL, 
T_OPEN);
@@ -275,32 +301,36 @@ static DIR *local_opendir(FsContext *fs_ctx, const char 
*path)
             return NULL;
         }
         return fdopendir(fd);
-    } else {
-        return opendir(rpath(fs_ctx, path));
     }
+    full_path = rpath(fs_ctx, path);
+    retval = opendir(full_path);
+    serrno = retval == NULL ? errno : 0;
+    qemu_free(full_path);
+    errno = serrno ? serrno : errno;
+    return retval;
 }
 
-static void local_rewinddir(FsContext *ctx, DIR *dir)
+static void local_rewinddir(FsContext *fs_ctx, DIR *dir)
 {
     return rewinddir(dir);
 }
 
-static off_t local_telldir(FsContext *ctx, DIR *dir)
+static off_t local_telldir(FsContext *fs_ctx, DIR *dir)
 {
     return telldir(dir);
 }
 
-static struct dirent *local_readdir(FsContext *ctx, DIR *dir)
+static struct dirent *local_readdir(FsContext *fs_ctx, DIR *dir)
 {
     return readdir(dir);
 }
 
-static void local_seekdir(FsContext *ctx, DIR *dir, off_t off)
+static void local_seekdir(FsContext *fs_ctx, DIR *dir, off_t off)
 {
     return seekdir(dir, off);
 }
 
-static ssize_t local_preadv(FsContext *ctx, int fd, const struct iovec *iov,
+static ssize_t local_preadv(FsContext *fs_ctx, int fd, const struct iovec *iov,
                             int iovcnt, off_t offset)
 {
 #ifdef CONFIG_PREADV
@@ -315,7 +345,7 @@ static ssize_t local_preadv(FsContext *ctx, int fd, const 
struct iovec *iov,
 #endif
 }
 
-static ssize_t local_pwritev(FsContext *ctx, int fd, const struct iovec *iov,
+static ssize_t local_pwritev(FsContext *fs_ctx, int fd, const struct iovec 
*iov,
                             int iovcnt, off_t offset)
 {
 #ifdef CONFIG_PREADV
@@ -332,87 +362,102 @@ static ssize_t local_pwritev(FsContext *ctx, int fd, 
const struct iovec *iov,
 
 static int local_chmod(FsContext *fs_ctx, const char *path, FsCred *credp)
 {
-    if (fs_ctx->fs_sm == SM_MAPPED) {
-        return local_set_xattr(rpath(fs_ctx, path), credp);
-    } else if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
+    char *full_path;
+    int serrno = 0, retval;
+
+    if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
         return passthrough_request(fs_ctx, NULL, path, 0, credp, T_CHMOD);
-    } else if (fs_ctx->fs_sm == SM_NONE) {
-        return chmod(rpath(fs_ctx, path), credp->fc_mode);
     }
-    return -1;
+
+    full_path = rpath(fs_ctx, path);
+    if (fs_ctx->fs_sm == SM_MAPPED) {
+        retval = local_set_xattr(full_path, credp);
+    } else {
+        retval = chmod(full_path, credp->fc_mode);
+    }
+    serrno = retval < 0 ? errno : 0;
+    qemu_free(full_path);
+    errno = serrno ? serrno : errno;
+    return retval;
 }
 
 static int local_mknod(FsContext *fs_ctx, const char *path, FsCred *credp)
 {
-    int err = -1;
-    int serrno = 0;
+    int err = -1, serrno = 0;
+    char *full_path;
 
+    if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
+        return passthrough_request(fs_ctx, NULL, path, 0, credp, T_MKNOD);
+    }
+
+    full_path = rpath(fs_ctx, path);
     /* Determine the security model */
     if (fs_ctx->fs_sm == SM_MAPPED) {
-        err = mknod(rpath(fs_ctx, path), SM_LOCAL_MODE_BITS|S_IFREG, 0);
-        if (err == -1) {
-            return err;
-        }
-        local_set_xattr(rpath(fs_ctx, path), credp);
-        if (err == -1) {
+        err = mknod(full_path, SM_LOCAL_MODE_BITS|S_IFREG, 0);
+        if (err < 0) {
             serrno = errno;
             goto err_end;
         }
-    } else if (fs_ctx->fs_sm == SM_NONE) {
-        err = mknod(rpath(fs_ctx, path), credp->fc_mode, credp->fc_rdev);
-        if (err == -1) {
-            return err;
+        err = local_set_xattr(full_path, credp);
+        if (err < 0) {
+            serrno = errno;
+            goto err_rm;
         }
-        err = local_post_create_none(fs_ctx, path, credp);
-        if (err == -1) {
+    } else if (fs_ctx->fs_sm == SM_NONE) {
+        err = mknod(full_path, credp->fc_mode, credp->fc_rdev);
+        if (err < 0) {
             serrno = errno;
             goto err_end;
         }
-    } else if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
-        err = passthrough_request(fs_ctx, NULL, path, 0, credp, T_MKNOD);
+        local_post_create_none(full_path, credp);
     }
+    qemu_free(full_path);
     return err;
-
+err_rm:
+    remove(full_path);
 err_end:
-    remove(rpath(fs_ctx, path));
+    qemu_free(full_path);
     errno = serrno;
     return err;
 }
 
 static int local_mkdir(FsContext *fs_ctx, const char *path, FsCred *credp)
 {
-    int err = -1;
-    int serrno = 0;
+    int err = -1, serrno = 0;
+    char *full_path;
+
+    if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
+        return passthrough_request(fs_ctx, NULL, path, 0, credp, T_MKDIR);
+    }
 
+    full_path = rpath(fs_ctx, path);
     /* Determine the security model */
     if (fs_ctx->fs_sm == SM_MAPPED) {
-        err = mkdir(rpath(fs_ctx, path), SM_LOCAL_DIR_MODE_BITS);
-        if (err == -1) {
-            return err;
+        err = mkdir(full_path, SM_LOCAL_DIR_MODE_BITS);
+        if (err < 0) {
+            serrno = errno;
+            goto err_end;
         }
         credp->fc_mode = credp->fc_mode|S_IFDIR;
-        err = local_set_xattr(rpath(fs_ctx, path), credp);
-        if (err == -1) {
+        err = local_set_xattr(full_path, credp);
+        if (err < 0) {
             serrno = errno;
-            goto err_end;
+            goto err_rm;
         }
     } else if (fs_ctx->fs_sm == SM_NONE) {
-        err = mkdir(rpath(fs_ctx, path), credp->fc_mode);
-        if (err == -1) {
-            return err;
-        }
-        err = local_post_create_none(fs_ctx, path, credp);
-        if (err == -1) {
+        err = mkdir(full_path, credp->fc_mode);
+        if (err < 0) {
             serrno = errno;
             goto err_end;
         }
-    } else if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
-        err = passthrough_request(fs_ctx, NULL, path, 0, credp, T_MKDIR);
+        local_post_create_none(full_path, credp);
     }
+    qemu_free(full_path);
     return err;
-
+err_rm:
+    remove(full_path);
 err_end:
-    remove(rpath(fs_ctx, path));
+    qemu_free(full_path);
     errno = serrno;
     return err;
 }
@@ -450,60 +495,68 @@ static int local_fstat(FsContext *fs_ctx, int fd, struct 
stat *stbuf)
 static int local_open2(FsContext *fs_ctx, const char *path, int flags,
         FsCred *credp)
 {
-    int fd = -1;
-    int err = -1;
-    int serrno = 0;
+    int fd = -1, err = -1, serrno = 0;
+    char *full_path;
+
+    if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
+        return passthrough_request(fs_ctx, NULL, path, flags, credp, T_CREATE);
+    }
 
+    full_path = rpath(fs_ctx, path);
     /* Determine the security model */
     if (fs_ctx->fs_sm == SM_MAPPED) {
-        fd = open(rpath(fs_ctx, path), flags, SM_LOCAL_MODE_BITS);
-        if (fd == -1) {
-            return fd;
+        fd = open(full_path, flags, SM_LOCAL_MODE_BITS);
+        if (fd < 0) {
+            serrno = errno;
+            goto err_end;
         }
         credp->fc_mode = credp->fc_mode|S_IFREG;
-        /* Set cleint credentials in xattr */
-        err = local_set_xattr(rpath(fs_ctx, path), credp);
-        if (err == -1) {
+        /* Set client credentials in xattr */
+        err = local_set_xattr(full_path, credp);
+        if (err < 0) {
             serrno = errno;
-            goto err_end;
+            goto err_rm;
         }
     } else if (fs_ctx->fs_sm == SM_NONE) {
-        fd = open(rpath(fs_ctx, path), flags, credp->fc_mode);
-        if (fd == -1) {
-            return fd;
-        }
-        err = local_post_create_none(fs_ctx, path, credp);
-        if (err == -1) {
+        fd = open(full_path, flags, credp->fc_mode);
+        if (fd < 0) {
             serrno = errno;
             goto err_end;
         }
-    } else if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
-        fd = passthrough_request(fs_ctx, NULL, path, flags, credp, T_CREATE);
+        local_post_create_none(full_path, credp);
     }
+    qemu_free(full_path);
     return fd;
-
+err_rm:
+    remove(full_path);
 err_end:
     close(fd);
-    remove(rpath(fs_ctx, path));
+    qemu_free(full_path);
     errno = serrno;
     return err;
 }
 
-
 static int local_symlink(FsContext *fs_ctx, const char *oldpath,
         const char *newpath, FsCred *credp)
 {
-    int err = -1;
-    int serrno = 0;
+    int err = -1, serrno = 0;
+    char *full_newpath;
+
+    if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
+        err = passthrough_request(fs_ctx, oldpath, newpath, 0, credp,
+                        T_SYMLINK);
+    }
+
+    full_newpath = rpath(fs_ctx, newpath);
 
     /* Determine the security model */
     if (fs_ctx->fs_sm == SM_MAPPED) {
         int fd;
         ssize_t oldpath_size, write_size;
-        fd = open(rpath(fs_ctx, newpath), O_CREAT|O_EXCL|O_RDWR,
-                SM_LOCAL_MODE_BITS);
-        if (fd == -1) {
-            return fd;
+        fd = open(full_newpath, O_CREAT|O_EXCL|O_RDWR, SM_LOCAL_MODE_BITS);
+        if (fd < 0) {
+            errno = serrno;
+            goto err_end;
         }
         /* Write the oldpath (target) to the file. */
         oldpath_size = strlen(oldpath);
@@ -515,31 +568,30 @@ static int local_symlink(FsContext *fs_ctx, const char 
*oldpath,
             serrno = errno;
             close(fd);
             err = -1;
-            goto err_end;
+            goto err_rm;
         }
         close(fd);
-        /* Set cleint credentials in symlink's xattr */
+        /* Set client credentials in symlink's xattr */
         credp->fc_mode = credp->fc_mode|S_IFLNK;
         err = local_set_xattr(rpath(fs_ctx, newpath), credp);
-        if (err == -1) {
+        if (err < 0) {
             serrno = errno;
             goto err_end;
         }
     } else if (fs_ctx->fs_sm == SM_NONE) {
-        err = symlink(oldpath, rpath(fs_ctx, newpath));
-        if (err) {
-            return err;
+        err = symlink(oldpath, full_newpath);
+        if (err < 0) {
+            errno = serrno;
+            goto err_end;
         }
-        err = lchown(rpath(fs_ctx, newpath), credp->fc_uid, credp->fc_gid);
-        err = 0;
-    } else if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
-        err = passthrough_request(fs_ctx, oldpath, newpath, 0, credp,
-                        T_SYMLINK);
+        (void)lchown(full_newpath, credp->fc_uid, credp->fc_gid);
     }
+    qemu_free(full_newpath);
     return err;
-
+err_rm:
+    remove(full_newpath);
 err_end:
-    remove(rpath(fs_ctx, newpath));
+    qemu_free(full_newpath);
     errno = serrno;
     return err;
 }
@@ -548,119 +600,149 @@ static int local_link(FsContext *fs_ctx, const char 
*oldpath,
                 const char *newpath)
 {
     int err, serrno = 0;
-    char *tmp;
+    char *full_oldpath, *full_newpath;
 
     if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
         return passthrough_request(fs_ctx, oldpath, newpath, 0, NULL, T_LINK);
     }
 
-    tmp = qemu_strdup(rpath(fs_ctx, oldpath));
-    err = link(tmp, rpath(fs_ctx, newpath));
-    if (err == -1) {
-        serrno = errno;
-    }
-    qemu_free(tmp);
-    if (err == -1) {
-        errno = serrno;
-    }
+    full_oldpath = rpath(fs_ctx, oldpath);
+    full_newpath = rpath(fs_ctx, newpath);
+    err = link(full_oldpath, full_newpath);
+    serrno = err < 0 ? errno : 0;
+    qemu_free(full_oldpath);
+    qemu_free(full_newpath);
+    errno = serrno ? serrno : errno;
     return err;
 }
 
-static int local_truncate(FsContext *ctx, const char *path, off_t size)
+static int passthrough_truncate(FsContext *fs_ctx, const char *path, off_t 
size)
 {
-    if (ctx->fs_sm == SM_PASSTHROUGH) {
-        int fd, retval, serrno;
-        fd = passthrough_request(ctx, NULL, path, O_RDWR, NULL, T_OPEN);
-        if (fd < 0) {
-            errno = -fd;
-            return -1;
-        }
-        retval = ftruncate(fd, size);
-        if (retval < 0) {
-            serrno = errno;
-        }
-        close(fd);
-        if (retval < 0) {
-            errno = serrno;
-        }
-        return retval;
-    } else {
-        return truncate(rpath(ctx, path), size);
+    int fd, retval, serrno;
+    fd = passthrough_request(fs_ctx, NULL, path, O_RDWR, NULL, T_OPEN);
+    if (fd < 0) {
+        errno = -fd;
+        return -1;
     }
+    retval = ftruncate(fd, size);
+    serrno = retval < 0 ? errno : 0;
+    close(fd);
+    errno = serrno ? serrno : errno;
+    return retval;
 }
 
-static int local_rename(FsContext *ctx, const char *oldpath,
+static int local_truncate(FsContext *fs_ctx, const char *path, off_t size)
+{
+    int serrno, retval;
+    char *full_path;
+
+    if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
+        return passthrough_truncate(fs_ctx, path, size);
+    }
+
+    full_path = rpath(fs_ctx, path);
+    retval = truncate(full_path, size);
+    serrno = retval < 0 ? errno : 0;
+    qemu_free(full_path);
+    errno = serrno ? serrno : errno;
+    return retval;
+}
+
+static int local_rename(FsContext *fs_ctx, const char *oldpath,
                         const char *newpath)
 {
     int err, serrno;
-    char *tmp;
+    char *full_oldpath, *full_newpath;
 
-    if (ctx->fs_sm == SM_PASSTHROUGH) {
-        return passthrough_request(ctx, oldpath, newpath, 0, NULL, T_RENAME);
+    if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
+        return passthrough_request(fs_ctx, oldpath, newpath, 0, NULL, 
T_RENAME);
     }
 
-    tmp = qemu_strdup(rpath(ctx, oldpath));
-    err = rename(tmp, rpath(ctx, newpath));
-    if (err == -1) {
-        serrno = errno;
-    }
-    qemu_free(tmp);
-    if (err == -1) {
-        errno = serrno;
-    }
+    full_oldpath = rpath(fs_ctx, oldpath);
+    full_newpath = rpath(fs_ctx, newpath);
+    err = rename(full_oldpath, full_newpath);
+    serrno = err < 0 ? errno : 0;
+    qemu_free(full_oldpath);
+    qemu_free(full_newpath);
+    errno = serrno ? serrno : errno;
     return err;
 }
 
 static int local_chown(FsContext *fs_ctx, const char *path, FsCred *credp)
 {
-    if (fs_ctx->fs_sm != SM_PASSTHROUGH &&
-            (credp->fc_uid == -1 && credp->fc_gid == -1)) {
-        return lchown(rpath(fs_ctx, path), credp->fc_uid, credp->fc_gid);
-    } else if (fs_ctx->fs_sm == SM_MAPPED) {
-        return local_set_xattr(rpath(fs_ctx, path), credp);
-    } else if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
+    int retval, serrno;
+    char *full_path;
+
+    if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
         return passthrough_request(fs_ctx, NULL, path, 0, credp, T_CHOWN);
-    } else if (fs_ctx->fs_sm == SM_NONE) {
-        return lchown(rpath(fs_ctx, path), credp->fc_uid, credp->fc_gid);
     }
-    return -1;
+    full_path = rpath(fs_ctx, path);
+    if (credp->fc_uid == -1 && credp->fc_gid == -1) {
+        retval = lchown(full_path, credp->fc_uid, credp->fc_gid);
+    } else if (fs_ctx->fs_sm == SM_MAPPED) {
+        retval = local_set_xattr(full_path, credp);
+    } else {
+        retval = lchown(full_path, credp->fc_uid, credp->fc_gid);
+    }
+    serrno = retval < 0 ? errno : 0;
+    qemu_free(full_path);
+    errno = serrno ? serrno : 0;
+    return retval;
+}
+
+static int passthrough_utimensat(FsContext *fs_ctx, const char *path,
+                const struct timespec *buf)
+{
+    int fd, retval, serrno = 0;
+    fd = passthrough_request(fs_ctx, NULL, path, O_RDONLY | O_NONBLOCK |
+                                O_NOFOLLOW, NULL, T_OPEN);
+    if (fd < 0) {
+        errno = -fd;
+        return -1;
+    }
+    retval = futimens(fd, buf);
+    if (retval < 0) {
+        serrno = errno;
+    }
+    close(fd);
+    errno = serrno ? serrno : errno;
+    return retval;
 }
 
 static int local_utimensat(FsContext *fs_ctx, const char *path,
                 const struct timespec *buf)
 {
+    char *full_path;
+    int serrno, retval;
+
     if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
-        int fd, retval, serrno = 0;
-        fd = passthrough_request(fs_ctx, NULL, path,
-                        O_RDONLY | O_NONBLOCK | O_NOFOLLOW, NULL, T_OPEN);
-        if (fd < 0) {
-            errno = -fd;
-            return -1;
-        }
-        retval = futimens(fd, buf);
-        if (retval < 0) {
-            serrno = errno;
-        }
-        close(fd);
-        if (retval < 0) {
-            errno = serrno;
-        }
-        return retval;
-    } else {
-        return utimensat(AT_FDCWD, rpath(fs_ctx, path), buf,
-                        AT_SYMLINK_NOFOLLOW);
+        return passthrough_utimensat(fs_ctx, path, buf);
     }
+    full_path = rpath(fs_ctx, path);
+    retval = utimensat(AT_FDCWD, full_path, buf, AT_SYMLINK_NOFOLLOW);
+    serrno = retval < 0 ? errno : 0;
+    qemu_free(full_path);
+    errno = serrno ? serrno : errno;
+    return retval;
 }
 
-static int local_remove(FsContext *ctx, const char *path)
+static int local_remove(FsContext *fs_ctx, const char *path)
 {
-    if (ctx->fs_sm == SM_PASSTHROUGH) {
-        return passthrough_request(ctx, NULL, path, 0, NULL, T_REMOVE);
+    int serrno, retval;
+    char *full_path;
+
+    if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
+        return passthrough_request(fs_ctx, NULL, path, 0, NULL, T_REMOVE);
     }
-    return remove(rpath(ctx, path));
+    full_path = rpath(fs_ctx, path);
+    retval = remove(full_path);
+    serrno = retval < 0 ? errno : 0;
+    qemu_free(full_path);
+    errno = serrno ? serrno : errno;
+    return retval;
 }
 
-static int local_fsync(FsContext *ctx, int fd, int datasync)
+static int local_fsync(FsContext *fs_ctx, int fd, int datasync)
 {
     if (datasync) {
         return qemu_fdatasync(fd);
@@ -669,36 +751,37 @@ static int local_fsync(FsContext *ctx, int fd, int 
datasync)
     }
 }
 
-static int local_statfs(FsContext *s, const char *path, struct statfs *stbuf)
+static int local_statfs(FsContext *fs_ctx, const char *path,
+                struct statfs *stbuf)
 {
-   return statfs(rpath(s, path), stbuf);
+   return statfs(fs_ctx->fs_root, stbuf);
 }
 
-static ssize_t local_lgetxattr(FsContext *ctx, const char *path,
+static ssize_t local_lgetxattr(FsContext *fs_ctx, const char *path,
                                const char *name, void *value, size_t size)
 {
-    return v9fs_get_xattr(ctx, path, name, value, size);
+    return v9fs_get_xattr(fs_ctx, path, name, value, size);
 }
 
-static ssize_t local_llistxattr(FsContext *ctx, const char *path,
+static ssize_t local_llistxattr(FsContext *fs_ctx, const char *path,
                                 void *value, size_t size)
 {
-    return v9fs_list_xattr(ctx, path, value, size);
+    return v9fs_list_xattr(fs_ctx, path, value, size);
 }
 
-static int local_lsetxattr(FsContext *ctx, const char *path, const char *name,
-                           void *value, size_t size, int flags)
+static int local_lsetxattr(FsContext *fs_ctx, const char *path,
+                const char *name, void *value, size_t size, int flags)
 {
-    return v9fs_set_xattr(ctx, path, name, value, size, flags);
+    return v9fs_set_xattr(fs_ctx, path, name, value, size, flags);
 }
 
-static int local_lremovexattr(FsContext *ctx,
+static int local_lremovexattr(FsContext *fs_ctx,
                               const char *path, const char *name)
 {
-    return v9fs_remove_xattr(ctx, path, name);
+    return v9fs_remove_xattr(fs_ctx, path, name);
 }
 
-static int local_syncfs(FsContext *ctx, int fd)
+static int local_syncfs(FsContext *fs_ctx, int fd)
 {
     /*
      * We should be doing per file system sync here.
diff --git a/hw/file-op-9p.h b/hw/file-op-9p.h
index 6b2e16a..3ea4f53 100644
--- a/hw/file-op-9p.h
+++ b/hw/file-op-9p.h
@@ -102,11 +102,11 @@ typedef struct FileOperations
     void *opaque;
 } FileOperations;
 
-static inline const char *rpath(FsContext *ctx, const char *path)
+static inline char *rpath(FsContext *ctx, const char *path)
 {
-    /* FIXME: so wrong... */
-    static char buffer[4096];
-    snprintf(buffer, sizeof(buffer), "%s/%s", ctx->fs_root, path);
-    return buffer;
+    char *fullpath;
+    fullpath = qemu_malloc(strlen(path) + strlen(ctx->fs_root) + 2);
+    sprintf(fullpath, "%s/%s", ctx->fs_root, path);
+    return fullpath;
 }
 #endif
-- 
1.7.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]