From patchwork Fri Apr 15 09:05:57 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mohan Kumar M X-Patchwork-Id: 91346 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id ACED41007EE for ; Fri, 15 Apr 2011 19:06:40 +1000 (EST) Received: from localhost ([::1]:46883 helo=lists2.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QAez7-0005U0-AX for incoming@patchwork.ozlabs.org; Fri, 15 Apr 2011 05:06:37 -0400 Received: from eggs.gnu.org ([140.186.70.92]:52605) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QAeyn-0005Sf-Cc for qemu-devel@nongnu.org; Fri, 15 Apr 2011 05:06:22 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QAeyj-00052v-G6 for qemu-devel@nongnu.org; Fri, 15 Apr 2011 05:06:17 -0400 Received: from e28smtp01.in.ibm.com ([122.248.162.1]:59101) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QAeyh-00051i-1w for qemu-devel@nongnu.org; Fri, 15 Apr 2011 05:06:13 -0400 Received: from d28relay03.in.ibm.com (d28relay03.in.ibm.com [9.184.220.60]) by e28smtp01.in.ibm.com (8.14.4/8.13.1) with ESMTP id p3F95wmm014750 for ; Fri, 15 Apr 2011 14:35:58 +0530 Received: from d28av02.in.ibm.com (d28av02.in.ibm.com [9.184.220.64]) by d28relay03.in.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id p3F95w2n3592424 for ; Fri, 15 Apr 2011 14:35:58 +0530 Received: from d28av02.in.ibm.com (loopback [127.0.0.1]) by d28av02.in.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id p3F95vhA030271 for ; Fri, 15 Apr 2011 19:05:57 +1000 Received: from explorer.in.ibm.com ([9.124.35.30]) by d28av02.in.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id p3F95vcM030265 for ; Fri, 15 Apr 2011 19:05:57 +1000 From: "M. Mohan Kumar" To: qemu-devel@nongnu.org Date: Fri, 15 Apr 2011 14:35:57 +0530 Message-Id: <1302858357-11309-1-git-send-email-mohan@in.ibm.com> X-Mailer: git-send-email 1.7.4 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) X-Received-From: 122.248.162.1 Subject: [Qemu-devel] [PATCH] virtio-9p: Make rpath function thread safe X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 --- 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