summaryrefslogtreecommitdiff
path: root/hw/9pfs/virtio-9p-local.c
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2011-09-09 15:14:18 +0530
committerAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2011-09-22 21:38:52 +0530
commit2289be19aecc290263ef1f3c1f4a0e9ea32aaad6 (patch)
treef9049e0b36dce4289995e8d3519b20255c4a4b7f /hw/9pfs/virtio-9p-local.c
parent02cb7f3a256517cbf3136caff2863fbafc57b540 (diff)
downloadqemu-2289be19aecc290263ef1f3c1f4a0e9ea32aaad6.tar.gz
hw/9pfs: Move fid pathname tracking to seperate data type.
This enables us to add handles to track fids later. The V9fsPath added is similar to V9fsString except that the size include the NULL byte also. Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Diffstat (limited to 'hw/9pfs/virtio-9p-local.c')
-rw-r--r--hw/9pfs/virtio-9p-local.c205
1 files changed, 165 insertions, 40 deletions
diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c
index 61cbf8db14..55f62f9570 100644
--- a/hw/9pfs/virtio-9p-local.c
+++ b/hw/9pfs/virtio-9p-local.c
@@ -22,10 +22,12 @@
#include <attr/xattr.h>
-static int local_lstat(FsContext *fs_ctx, const char *path, struct stat *stbuf)
+static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
{
int err;
char buffer[PATH_MAX];
+ char *path = fs_path->data;
+
err = lstat(rpath(fs_ctx, path, buffer), stbuf);
if (err) {
return err;
@@ -59,6 +61,7 @@ static int local_lstat(FsContext *fs_ctx, const char *path, struct stat *stbuf)
static int local_set_xattr(const char *path, FsCred *credp)
{
int err;
+
if (credp->fc_uid != -1) {
err = setxattr(path, "user.virtfs.uid", &credp->fc_uid, sizeof(uid_t),
0);
@@ -91,9 +94,10 @@ static int local_set_xattr(const char *path, FsCred *credp)
}
static int local_post_create_passthrough(FsContext *fs_ctx, const char *path,
- FsCred *credp)
+ FsCred *credp)
{
char buffer[PATH_MAX];
+
if (chmod(rpath(fs_ctx, path, buffer), credp->fc_mode & 07777) < 0) {
return -1;
}
@@ -110,11 +114,13 @@ static int local_post_create_passthrough(FsContext *fs_ctx, const char *path,
return 0;
}
-static ssize_t local_readlink(FsContext *fs_ctx, const char *path,
- char *buf, size_t bufsz)
+static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
+ char *buf, size_t bufsz)
{
ssize_t tsize = -1;
char buffer[PATH_MAX];
+ char *path = fs_path->data;
+
if (fs_ctx->fs_sm == SM_MAPPED) {
int fd;
fd = open(rpath(fs_ctx, path, buffer), O_RDONLY);
@@ -143,15 +149,19 @@ static int local_closedir(FsContext *ctx, DIR *dir)
return closedir(dir);
}
-static int local_open(FsContext *ctx, const char *path, int flags)
+static int local_open(FsContext *ctx, V9fsPath *fs_path, int flags)
{
char buffer[PATH_MAX];
+ char *path = fs_path->data;
+
return open(rpath(ctx, path, buffer), flags);
}
-static DIR *local_opendir(FsContext *ctx, const char *path)
+static DIR *local_opendir(FsContext *ctx, V9fsPath *fs_path)
{
char buffer[PATH_MAX];
+ char *path = fs_path->data;
+
return opendir(rpath(ctx, path, buffer));
}
@@ -166,7 +176,7 @@ static off_t local_telldir(FsContext *ctx, DIR *dir)
}
static int local_readdir_r(FsContext *ctx, DIR *dir, struct dirent *entry,
- struct dirent **result)
+ struct dirent **result)
{
return readdir_r(dir, entry, result);
}
@@ -192,7 +202,7 @@ static ssize_t local_preadv(FsContext *ctx, int fd, const struct iovec *iov,
}
static ssize_t local_pwritev(FsContext *ctx, int fd, const struct iovec *iov,
- int iovcnt, off_t offset)
+ int iovcnt, off_t offset)
{
#ifdef CONFIG_PREADV
return pwritev(fd, iov, iovcnt, offset);
@@ -206,9 +216,11 @@ static ssize_t local_pwritev(FsContext *ctx, int fd, const struct iovec *iov,
#endif
}
-static int local_chmod(FsContext *fs_ctx, const char *path, FsCred *credp)
+static int local_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
{
char buffer[PATH_MAX];
+ char *path = fs_path->data;
+
if (fs_ctx->fs_sm == SM_MAPPED) {
return local_set_xattr(rpath(fs_ctx, path, buffer), credp);
} else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
@@ -218,18 +230,25 @@ static int local_chmod(FsContext *fs_ctx, const char *path, FsCred *credp)
return -1;
}
-static int local_mknod(FsContext *fs_ctx, const char *path, FsCred *credp)
+static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
+ const char *name, FsCred *credp)
{
+ char *path;
int err = -1;
int serrno = 0;
+ V9fsString fullname;
char buffer[PATH_MAX];
+ v9fs_string_init(&fullname);
+ v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
+ path = fullname.data;
+
/* Determine the security model */
if (fs_ctx->fs_sm == SM_MAPPED) {
err = mknod(rpath(fs_ctx, path, buffer),
SM_LOCAL_MODE_BITS|S_IFREG, 0);
if (err == -1) {
- return err;
+ goto out;
}
local_set_xattr(rpath(fs_ctx, path, buffer), credp);
if (err == -1) {
@@ -241,7 +260,7 @@ static int local_mknod(FsContext *fs_ctx, const char *path, FsCred *credp)
err = mknod(rpath(fs_ctx, path, buffer), credp->fc_mode,
credp->fc_rdev);
if (err == -1) {
- return err;
+ goto out;
}
err = local_post_create_passthrough(fs_ctx, path, credp);
if (err == -1) {
@@ -249,25 +268,34 @@ static int local_mknod(FsContext *fs_ctx, const char *path, FsCred *credp)
goto err_end;
}
}
- return err;
+ goto out;
err_end:
remove(rpath(fs_ctx, path, buffer));
errno = serrno;
+out:
+ v9fs_string_free(&fullname);
return err;
}
-static int local_mkdir(FsContext *fs_ctx, const char *path, FsCred *credp)
+static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
+ const char *name, FsCred *credp)
{
+ char *path;
int err = -1;
int serrno = 0;
+ V9fsString fullname;
char buffer[PATH_MAX];
+ v9fs_string_init(&fullname);
+ v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
+ path = fullname.data;
+
/* Determine the security model */
if (fs_ctx->fs_sm == SM_MAPPED) {
err = mkdir(rpath(fs_ctx, path, buffer), SM_LOCAL_DIR_MODE_BITS);
if (err == -1) {
- return err;
+ goto out;
}
credp->fc_mode = credp->fc_mode|S_IFDIR;
err = local_set_xattr(rpath(fs_ctx, path, buffer), credp);
@@ -279,7 +307,7 @@ static int local_mkdir(FsContext *fs_ctx, const char *path, FsCred *credp)
(fs_ctx->fs_sm == SM_NONE)) {
err = mkdir(rpath(fs_ctx, path, buffer), credp->fc_mode);
if (err == -1) {
- return err;
+ goto out;
}
err = local_post_create_passthrough(fs_ctx, path, credp);
if (err == -1) {
@@ -287,11 +315,13 @@ static int local_mkdir(FsContext *fs_ctx, const char *path, FsCred *credp)
goto err_end;
}
}
- return err;
+ goto out;
err_end:
remove(rpath(fs_ctx, path, buffer));
errno = serrno;
+out:
+ v9fs_string_free(&fullname);
return err;
}
@@ -325,19 +355,26 @@ static int local_fstat(FsContext *fs_ctx, int fd, struct stat *stbuf)
return err;
}
-static int local_open2(FsContext *fs_ctx, const char *path, int flags,
- FsCred *credp)
+static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
+ int flags, FsCred *credp)
{
+ char *path;
int fd = -1;
int err = -1;
int serrno = 0;
+ V9fsString fullname;
char buffer[PATH_MAX];
+ v9fs_string_init(&fullname);
+ v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
+ path = fullname.data;
+
/* Determine the security model */
if (fs_ctx->fs_sm == SM_MAPPED) {
fd = open(rpath(fs_ctx, path, buffer), flags, SM_LOCAL_MODE_BITS);
if (fd == -1) {
- return fd;
+ err = fd;
+ goto out;
}
credp->fc_mode = credp->fc_mode|S_IFREG;
/* Set cleint credentials in xattr */
@@ -350,7 +387,8 @@ static int local_open2(FsContext *fs_ctx, const char *path, int flags,
(fs_ctx->fs_sm == SM_NONE)) {
fd = open(rpath(fs_ctx, path, buffer), flags, credp->fc_mode);
if (fd == -1) {
- return fd;
+ err = fd;
+ goto out;
}
err = local_post_create_passthrough(fs_ctx, path, credp);
if (err == -1) {
@@ -358,23 +396,32 @@ static int local_open2(FsContext *fs_ctx, const char *path, int flags,
goto err_end;
}
}
- return fd;
+ err = fd;
+ goto out;
err_end:
close(fd);
remove(rpath(fs_ctx, path, buffer));
errno = serrno;
+out:
+ v9fs_string_free(&fullname);
return err;
}
static int local_symlink(FsContext *fs_ctx, const char *oldpath,
- const char *newpath, FsCred *credp)
+ V9fsPath *dir_path, const char *name, FsCred *credp)
{
int err = -1;
int serrno = 0;
+ char *newpath;
+ V9fsString fullname;
char buffer[PATH_MAX];
+ v9fs_string_init(&fullname);
+ v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
+ newpath = fullname.data;
+
/* Determine the security model */
if (fs_ctx->fs_sm == SM_MAPPED) {
int fd;
@@ -382,7 +429,8 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
fd = open(rpath(fs_ctx, newpath, buffer), O_CREAT|O_EXCL|O_RDWR,
SM_LOCAL_MODE_BITS);
if (fd == -1) {
- return fd;
+ err = fd;
+ goto out;
}
/* Write the oldpath (target) to the file. */
oldpath_size = strlen(oldpath);
@@ -408,10 +456,10 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
(fs_ctx->fs_sm == SM_NONE)) {
err = symlink(oldpath, rpath(fs_ctx, newpath, buffer));
if (err) {
- return err;
+ goto out;
}
err = lchown(rpath(fs_ctx, newpath, buffer), credp->fc_uid,
- credp->fc_gid);
+ credp->fc_gid);
if (err == -1) {
/*
* If we fail to change ownership and if we are
@@ -424,24 +472,37 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
err = 0;
}
}
- return err;
+ goto out;
err_end:
remove(rpath(fs_ctx, newpath, buffer));
errno = serrno;
+out:
+ v9fs_string_free(&fullname);
return err;
}
-static int local_link(FsContext *ctx, const char *oldpath, const char *newpath)
+static int local_link(FsContext *ctx, V9fsPath *oldpath,
+ V9fsPath *dirpath, const char *name)
{
+ int ret;
+ V9fsString newpath;
char buffer[PATH_MAX], buffer1[PATH_MAX];
- return link(rpath(ctx, oldpath, buffer), rpath(ctx, newpath, buffer1));
+ v9fs_string_init(&newpath);
+ v9fs_string_sprintf(&newpath, "%s/%s", dirpath->data, name);
+
+ ret = link(rpath(ctx, oldpath->data, buffer),
+ rpath(ctx, newpath.data, buffer1));
+ v9fs_string_free(&newpath);
+ return ret;
}
-static int local_truncate(FsContext *ctx, const char *path, off_t size)
+static int local_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
{
char buffer[PATH_MAX];
+ char *path = fs_path->data;
+
return truncate(rpath(ctx, path, buffer), size);
}
@@ -453,9 +514,11 @@ static int local_rename(FsContext *ctx, const char *oldpath,
return rename(rpath(ctx, oldpath, buffer), rpath(ctx, newpath, buffer1));
}
-static int local_chown(FsContext *fs_ctx, const char *path, FsCred *credp)
+static int local_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
{
char buffer[PATH_MAX];
+ char *path = fs_path->data;
+
if ((credp->fc_uid == -1 && credp->fc_gid == -1) ||
(fs_ctx->fs_sm == SM_PASSTHROUGH)) {
return lchown(rpath(fs_ctx, path, buffer), credp->fc_uid,
@@ -470,12 +533,14 @@ static int local_chown(FsContext *fs_ctx, const char *path, FsCred *credp)
return -1;
}
-static int local_utimensat(FsContext *s, const char *path,
+static int local_utimensat(FsContext *s, V9fsPath *fs_path,
const struct timespec *buf)
{
char buffer[PATH_MAX];
+ char *path = fs_path->data;
+
return qemu_utimensat(AT_FDCWD, rpath(s, path, buffer), buf,
- AT_SYMLINK_NOFOLLOW);
+ AT_SYMLINK_NOFOLLOW);
}
static int local_remove(FsContext *ctx, const char *path)
@@ -493,36 +558,93 @@ 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 *s, V9fsPath *fs_path, struct statfs *stbuf)
{
char buffer[PATH_MAX];
- return statfs(rpath(s, path, buffer), stbuf);
+ char *path = fs_path->data;
+
+ return statfs(rpath(s, path, buffer), stbuf);
}
-static ssize_t local_lgetxattr(FsContext *ctx, const char *path,
+static ssize_t local_lgetxattr(FsContext *ctx, V9fsPath *fs_path,
const char *name, void *value, size_t size)
{
+ char *path = fs_path->data;
+
return v9fs_get_xattr(ctx, path, name, value, size);
}
-static ssize_t local_llistxattr(FsContext *ctx, const char *path,
+static ssize_t local_llistxattr(FsContext *ctx, V9fsPath *fs_path,
void *value, size_t size)
{
+ char *path = fs_path->data;
+
return v9fs_list_xattr(ctx, path, value, size);
}
-static int local_lsetxattr(FsContext *ctx, const char *path, const char *name,
+static int local_lsetxattr(FsContext *ctx, V9fsPath *fs_path, const char *name,
void *value, size_t size, int flags)
{
+ char *path = fs_path->data;
+
return v9fs_set_xattr(ctx, path, name, value, size, flags);
}
-static int local_lremovexattr(FsContext *ctx,
- const char *path, const char *name)
+static int local_lremovexattr(FsContext *ctx, V9fsPath *fs_path,
+ const char *name)
{
+ char *path = fs_path->data;
+
return v9fs_remove_xattr(ctx, path, name);
}
+static int local_name_to_path(FsContext *ctx, V9fsPath *dir_path,
+ const char *name, V9fsPath *target)
+{
+ if (dir_path) {
+ v9fs_string_sprintf((V9fsString *)target, "%s/%s",
+ dir_path->data, name);
+ } else {
+ v9fs_string_sprintf((V9fsString *)target, "%s", name);
+ }
+ /* Bump the size for including terminating NULL */
+ target->size++;
+ return 0;
+}
+
+static int local_renameat(FsContext *ctx, V9fsPath *olddir,
+ const char *old_name, V9fsPath *newdir,
+ const char *new_name)
+{
+ int ret;
+ V9fsString old_full_name, new_full_name;
+
+ v9fs_string_init(&old_full_name);
+ v9fs_string_init(&new_full_name);
+
+ v9fs_string_sprintf(&old_full_name, "%s/%s", olddir->data, old_name);
+ v9fs_string_sprintf(&new_full_name, "%s/%s", newdir->data, new_name);
+
+ ret = local_rename(ctx, old_full_name.data, new_full_name.data);
+ v9fs_string_free(&old_full_name);
+ v9fs_string_free(&new_full_name);
+ return ret;
+}
+
+static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
+ const char *name, int flags)
+{
+ int ret;
+ V9fsString fullname;
+ char buffer[PATH_MAX];
+ v9fs_string_init(&fullname);
+
+ v9fs_string_sprintf(&fullname, "%s/%s", dir->data, name);
+ ret = remove(rpath(ctx, fullname.data, buffer));
+ v9fs_string_free(&fullname);
+
+ return ret;
+}
FileOperations local_ops = {
.lstat = local_lstat,
@@ -555,4 +677,7 @@ FileOperations local_ops = {
.llistxattr = local_llistxattr,
.lsetxattr = local_lsetxattr,
.lremovexattr = local_lremovexattr,
+ .name_to_path = local_name_to_path,
+ .renameat = local_renameat,
+ .unlinkat = local_unlinkat,
};