sim-card
/
qemu
Archived
10
0
Fork 0

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>
This commit is contained in:
Aneesh Kumar K.V 2011-09-09 15:14:18 +05:30
parent 02cb7f3a25
commit 2289be19ae
9 changed files with 552 additions and 303 deletions

View File

@ -57,43 +57,53 @@ typedef struct FsContext
struct xattr_operations **xops; struct xattr_operations **xops;
} FsContext; } FsContext;
typedef struct V9fsPath {
int16_t size;
char *data;
} V9fsPath;
void cred_init(FsCred *); void cred_init(FsCred *);
typedef struct FileOperations typedef struct FileOperations
{ {
int (*lstat)(FsContext *, const char *, struct stat *); int (*lstat)(FsContext *, V9fsPath *, struct stat *);
ssize_t (*readlink)(FsContext *, const char *, char *, size_t); ssize_t (*readlink)(FsContext *, V9fsPath *, char *, size_t);
int (*chmod)(FsContext *, const char *, FsCred *); int (*chmod)(FsContext *, V9fsPath *, FsCred *);
int (*chown)(FsContext *, const char *, FsCred *); int (*chown)(FsContext *, V9fsPath *, FsCred *);
int (*mknod)(FsContext *, const char *, FsCred *); int (*mknod)(FsContext *, V9fsPath *, const char *, FsCred *);
int (*utimensat)(FsContext *, const char *, const struct timespec *); int (*utimensat)(FsContext *, V9fsPath *, const struct timespec *);
int (*remove)(FsContext *, const char *); int (*remove)(FsContext *, const char *);
int (*symlink)(FsContext *, const char *, const char *, FsCred *); int (*symlink)(FsContext *, const char *, V9fsPath *,
int (*link)(FsContext *, const char *, const char *); const char *, FsCred *);
int (*link)(FsContext *, V9fsPath *, V9fsPath *, const char *);
int (*setuid)(FsContext *, uid_t); int (*setuid)(FsContext *, uid_t);
int (*close)(FsContext *, int); int (*close)(FsContext *, int);
int (*closedir)(FsContext *, DIR *); int (*closedir)(FsContext *, DIR *);
DIR *(*opendir)(FsContext *, const char *); DIR *(*opendir)(FsContext *, V9fsPath *);
int (*open)(FsContext *, const char *, int); int (*open)(FsContext *, V9fsPath *, int);
int (*open2)(FsContext *, const char *, int, FsCred *); int (*open2)(FsContext *, V9fsPath *, const char *, int, FsCred *);
void (*rewinddir)(FsContext *, DIR *); void (*rewinddir)(FsContext *, DIR *);
off_t (*telldir)(FsContext *, DIR *); off_t (*telldir)(FsContext *, DIR *);
int (*readdir_r)(FsContext *, DIR *, struct dirent *, struct dirent **); int (*readdir_r)(FsContext *, DIR *, struct dirent *, struct dirent **);
void (*seekdir)(FsContext *, DIR *, off_t); void (*seekdir)(FsContext *, DIR *, off_t);
ssize_t (*preadv)(FsContext *, int, const struct iovec *, int, off_t); ssize_t (*preadv)(FsContext *, int, const struct iovec *, int, off_t);
ssize_t (*pwritev)(FsContext *, int, const struct iovec *, int, off_t); ssize_t (*pwritev)(FsContext *, int, const struct iovec *, int, off_t);
int (*mkdir)(FsContext *, const char *, FsCred *); int (*mkdir)(FsContext *, V9fsPath *, const char *, FsCred *);
int (*fstat)(FsContext *, int, struct stat *); int (*fstat)(FsContext *, int, struct stat *);
int (*rename)(FsContext *, const char *, const char *); int (*rename)(FsContext *, const char *, const char *);
int (*truncate)(FsContext *, const char *, off_t); int (*truncate)(FsContext *, V9fsPath *, off_t);
int (*fsync)(FsContext *, int, int); int (*fsync)(FsContext *, int, int);
int (*statfs)(FsContext *s, const char *path, struct statfs *stbuf); int (*statfs)(FsContext *s, V9fsPath *path, struct statfs *stbuf);
ssize_t (*lgetxattr)(FsContext *, const char *, ssize_t (*lgetxattr)(FsContext *, V9fsPath *,
const char *, void *, size_t); const char *, void *, size_t);
ssize_t (*llistxattr)(FsContext *, const char *, void *, size_t); ssize_t (*llistxattr)(FsContext *, V9fsPath *, void *, size_t);
int (*lsetxattr)(FsContext *, const char *, int (*lsetxattr)(FsContext *, V9fsPath *,
const char *, void *, size_t, int); const char *, void *, size_t, int);
int (*lremovexattr)(FsContext *, const char *, const char *); int (*lremovexattr)(FsContext *, V9fsPath *, const char *);
int (*name_to_path)(FsContext *, V9fsPath *, const char *, V9fsPath *);
int (*renameat)(FsContext *ctx, V9fsPath *olddir, const char *old_name,
V9fsPath *newdir, const char *new_name);
int (*unlinkat)(FsContext *ctx, V9fsPath *dir, const char *name, int flags);
void *opaque; void *opaque;
} FileOperations; } FileOperations;

View File

@ -70,29 +70,31 @@ int v9fs_co_mkdir(V9fsState *s, V9fsFidState *fidp, V9fsString *name,
{ {
int err; int err;
FsCred cred; FsCred cred;
V9fsString fullname; V9fsPath path;
cred_init(&cred); cred_init(&cred);
cred.fc_mode = mode; cred.fc_mode = mode;
cred.fc_uid = uid; cred.fc_uid = uid;
cred.fc_gid = gid; cred.fc_gid = gid;
v9fs_string_init(&fullname);
qemu_co_rwlock_rdlock(&s->rename_lock); qemu_co_rwlock_rdlock(&s->rename_lock);
v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name->data);
v9fs_co_run_in_worker( v9fs_co_run_in_worker(
{ {
err = s->ops->mkdir(&s->ctx, fullname.data, &cred); err = s->ops->mkdir(&s->ctx, &fidp->path, name->data, &cred);
if (err < 0) { if (err < 0) {
err = -errno; err = -errno;
} else { } else {
err = s->ops->lstat(&s->ctx, fullname.data, stbuf); v9fs_path_init(&path);
if (err < 0) { err = v9fs_name_to_path(s, &fidp->path, name->data, &path);
err = -errno; if (!err) {
err = s->ops->lstat(&s->ctx, &path, stbuf);
if (err < 0) {
err = -errno;
}
} }
v9fs_path_free(&path);
} }
}); });
qemu_co_rwlock_unlock(&s->rename_lock); qemu_co_rwlock_unlock(&s->rename_lock);
v9fs_string_free(&fullname);
return err; return err;
} }
@ -103,7 +105,7 @@ int v9fs_co_opendir(V9fsState *s, V9fsFidState *fidp)
qemu_co_rwlock_rdlock(&s->rename_lock); qemu_co_rwlock_rdlock(&s->rename_lock);
v9fs_co_run_in_worker( v9fs_co_run_in_worker(
{ {
fidp->fs.dir = s->ops->opendir(&s->ctx, fidp->path.data); fidp->fs.dir = s->ops->opendir(&s->ctx, &fidp->path);
if (!fidp->fs.dir) { if (!fidp->fs.dir) {
err = -errno; err = -errno;
} else { } else {

View File

@ -17,14 +17,14 @@
#include "qemu-coroutine.h" #include "qemu-coroutine.h"
#include "virtio-9p-coth.h" #include "virtio-9p-coth.h"
int v9fs_co_lstat(V9fsState *s, V9fsString *path, struct stat *stbuf) int v9fs_co_lstat(V9fsState *s, V9fsPath *path, struct stat *stbuf)
{ {
int err; int err;
qemu_co_rwlock_rdlock(&s->rename_lock); qemu_co_rwlock_rdlock(&s->rename_lock);
v9fs_co_run_in_worker( v9fs_co_run_in_worker(
{ {
err = s->ops->lstat(&s->ctx, path->data, stbuf); err = s->ops->lstat(&s->ctx, path, stbuf);
if (err < 0) { if (err < 0) {
err = -errno; err = -errno;
} }
@ -54,7 +54,7 @@ int v9fs_co_open(V9fsState *s, V9fsFidState *fidp, int flags)
qemu_co_rwlock_rdlock(&s->rename_lock); qemu_co_rwlock_rdlock(&s->rename_lock);
v9fs_co_run_in_worker( v9fs_co_run_in_worker(
{ {
fidp->fs.fd = s->ops->open(&s->ctx, fidp->path.data, flags); fidp->fs.fd = s->ops->open(&s->ctx, &fidp->path, flags);
if (fidp->fs.fd == -1) { if (fidp->fs.fd == -1) {
err = -errno; err = -errno;
} else { } else {
@ -76,33 +76,40 @@ int v9fs_co_open2(V9fsState *s, V9fsFidState *fidp, V9fsString *name, gid_t gid,
{ {
int err; int err;
FsCred cred; FsCred cred;
V9fsString fullname; V9fsPath path;
cred_init(&cred); cred_init(&cred);
cred.fc_mode = mode & 07777; cred.fc_mode = mode & 07777;
cred.fc_uid = fidp->uid; cred.fc_uid = fidp->uid;
cred.fc_gid = gid; cred.fc_gid = gid;
v9fs_string_init(&fullname);
/* /*
* Hold the directory fid lock so that directory path name * Hold the directory fid lock so that directory path name
* don't change. Read lock is fine because this fid cannot * don't change. Read lock is fine because this fid cannot
* be used by any other operation. * be used by any other operation.
*/ */
qemu_co_rwlock_rdlock(&s->rename_lock); qemu_co_rwlock_rdlock(&s->rename_lock);
v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name->data);
v9fs_co_run_in_worker( v9fs_co_run_in_worker(
{ {
fidp->fs.fd = s->ops->open2(&s->ctx, fullname.data, flags, &cred); fidp->fs.fd = s->ops->open2(&s->ctx, &fidp->path,
name->data, flags, &cred);
if (fidp->fs.fd == -1) { if (fidp->fs.fd == -1) {
err = -errno; err = -errno;
} else { } else {
err = s->ops->lstat(&s->ctx, fullname.data, stbuf); v9fs_path_init(&path);
if (err < 0) { err = v9fs_name_to_path(s, &fidp->path, name->data, &path);
err = -errno; if (!err) {
err = s->ops->close(&s->ctx, fidp->fs.fd); err = s->ops->lstat(&s->ctx, &path, stbuf);
if (err < 0) {
err = -errno;
s->ops->close(&s->ctx, fidp->fs.fd);
} else {
v9fs_path_copy(&fidp->path, &path);
}
} else { } else {
v9fs_string_copy(&fidp->path, &fullname); s->ops->close(&s->ctx, fidp->fs.fd);
} }
v9fs_path_free(&path);
} }
}); });
qemu_co_rwlock_unlock(&s->rename_lock); qemu_co_rwlock_unlock(&s->rename_lock);
@ -112,7 +119,6 @@ int v9fs_co_open2(V9fsState *s, V9fsFidState *fidp, V9fsString *name, gid_t gid,
v9fs_reclaim_fd(s); v9fs_reclaim_fd(s);
} }
} }
v9fs_string_free(&fullname);
return err; return err;
} }
@ -149,14 +155,16 @@ int v9fs_co_fsync(V9fsState *s, V9fsFidState *fidp, int datasync)
return err; return err;
} }
int v9fs_co_link(V9fsState *s, V9fsString *oldpath, V9fsString *newpath) int v9fs_co_link(V9fsState *s, V9fsFidState *oldfid,
V9fsFidState *newdirfid, V9fsString *name)
{ {
int err; int err;
qemu_co_rwlock_rdlock(&s->rename_lock); qemu_co_rwlock_rdlock(&s->rename_lock);
v9fs_co_run_in_worker( v9fs_co_run_in_worker(
{ {
err = s->ops->link(&s->ctx, oldpath->data, newpath->data); err = s->ops->link(&s->ctx, &oldfid->path,
&newdirfid->path, name->data);
if (err < 0) { if (err < 0) {
err = -errno; err = -errno;
} }

View File

@ -17,7 +17,7 @@
#include "qemu-coroutine.h" #include "qemu-coroutine.h"
#include "virtio-9p-coth.h" #include "virtio-9p-coth.h"
int v9fs_co_readlink(V9fsState *s, V9fsString *path, V9fsString *buf) int v9fs_co_readlink(V9fsState *s, V9fsPath *path, V9fsString *buf)
{ {
int err; int err;
ssize_t len; ssize_t len;
@ -27,7 +27,7 @@ int v9fs_co_readlink(V9fsState *s, V9fsString *path, V9fsString *buf)
v9fs_co_run_in_worker( v9fs_co_run_in_worker(
{ {
len = s->ops->readlink(&s->ctx, path->data, len = s->ops->readlink(&s->ctx, path,
buf->data, PATH_MAX - 1); buf->data, PATH_MAX - 1);
if (len > -1) { if (len > -1) {
buf->size = len; buf->size = len;
@ -46,14 +46,14 @@ int v9fs_co_readlink(V9fsState *s, V9fsString *path, V9fsString *buf)
return err; return err;
} }
int v9fs_co_statfs(V9fsState *s, V9fsString *path, struct statfs *stbuf) int v9fs_co_statfs(V9fsState *s, V9fsPath *path, struct statfs *stbuf)
{ {
int err; int err;
qemu_co_rwlock_rdlock(&s->rename_lock); qemu_co_rwlock_rdlock(&s->rename_lock);
v9fs_co_run_in_worker( v9fs_co_run_in_worker(
{ {
err = s->ops->statfs(&s->ctx, path->data, stbuf); err = s->ops->statfs(&s->ctx, path, stbuf);
if (err < 0) { if (err < 0) {
err = -errno; err = -errno;
} }
@ -62,7 +62,7 @@ int v9fs_co_statfs(V9fsState *s, V9fsString *path, struct statfs *stbuf)
return err; return err;
} }
int v9fs_co_chmod(V9fsState *s, V9fsString *path, mode_t mode) int v9fs_co_chmod(V9fsState *s, V9fsPath *path, mode_t mode)
{ {
int err; int err;
FsCred cred; FsCred cred;
@ -72,7 +72,7 @@ int v9fs_co_chmod(V9fsState *s, V9fsString *path, mode_t mode)
qemu_co_rwlock_rdlock(&s->rename_lock); qemu_co_rwlock_rdlock(&s->rename_lock);
v9fs_co_run_in_worker( v9fs_co_run_in_worker(
{ {
err = s->ops->chmod(&s->ctx, path->data, &cred); err = s->ops->chmod(&s->ctx, path, &cred);
if (err < 0) { if (err < 0) {
err = -errno; err = -errno;
} }
@ -81,7 +81,7 @@ int v9fs_co_chmod(V9fsState *s, V9fsString *path, mode_t mode)
return err; return err;
} }
int v9fs_co_utimensat(V9fsState *s, V9fsString *path, int v9fs_co_utimensat(V9fsState *s, V9fsPath *path,
struct timespec times[2]) struct timespec times[2])
{ {
int err; int err;
@ -89,7 +89,7 @@ int v9fs_co_utimensat(V9fsState *s, V9fsString *path,
qemu_co_rwlock_rdlock(&s->rename_lock); qemu_co_rwlock_rdlock(&s->rename_lock);
v9fs_co_run_in_worker( v9fs_co_run_in_worker(
{ {
err = s->ops->utimensat(&s->ctx, path->data, times); err = s->ops->utimensat(&s->ctx, path, times);
if (err < 0) { if (err < 0) {
err = -errno; err = -errno;
} }
@ -98,7 +98,7 @@ int v9fs_co_utimensat(V9fsState *s, V9fsString *path,
return err; return err;
} }
int v9fs_co_chown(V9fsState *s, V9fsString *path, uid_t uid, gid_t gid) int v9fs_co_chown(V9fsState *s, V9fsPath *path, uid_t uid, gid_t gid)
{ {
int err; int err;
FsCred cred; FsCred cred;
@ -109,7 +109,7 @@ int v9fs_co_chown(V9fsState *s, V9fsString *path, uid_t uid, gid_t gid)
qemu_co_rwlock_rdlock(&s->rename_lock); qemu_co_rwlock_rdlock(&s->rename_lock);
v9fs_co_run_in_worker( v9fs_co_run_in_worker(
{ {
err = s->ops->chown(&s->ctx, path->data, &cred); err = s->ops->chown(&s->ctx, path, &cred);
if (err < 0) { if (err < 0) {
err = -errno; err = -errno;
} }
@ -118,14 +118,14 @@ int v9fs_co_chown(V9fsState *s, V9fsString *path, uid_t uid, gid_t gid)
return err; return err;
} }
int v9fs_co_truncate(V9fsState *s, V9fsString *path, off_t size) int v9fs_co_truncate(V9fsState *s, V9fsPath *path, off_t size)
{ {
int err; int err;
qemu_co_rwlock_rdlock(&s->rename_lock); qemu_co_rwlock_rdlock(&s->rename_lock);
v9fs_co_run_in_worker( v9fs_co_run_in_worker(
{ {
err = s->ops->truncate(&s->ctx, path->data, size); err = s->ops->truncate(&s->ctx, path, size);
if (err < 0) { if (err < 0) {
err = -errno; err = -errno;
} }
@ -138,35 +138,38 @@ int v9fs_co_mknod(V9fsState *s, V9fsFidState *fidp, V9fsString *name, uid_t uid,
gid_t gid, dev_t dev, mode_t mode, struct stat *stbuf) gid_t gid, dev_t dev, mode_t mode, struct stat *stbuf)
{ {
int err; int err;
V9fsPath path;
FsCred cred; FsCred cred;
V9fsString fullname;
cred_init(&cred); cred_init(&cred);
cred.fc_uid = uid; cred.fc_uid = uid;
cred.fc_gid = gid; cred.fc_gid = gid;
cred.fc_mode = mode; cred.fc_mode = mode;
cred.fc_rdev = dev; cred.fc_rdev = dev;
v9fs_string_init(&fullname);
qemu_co_rwlock_rdlock(&s->rename_lock); qemu_co_rwlock_rdlock(&s->rename_lock);
v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name->data);
v9fs_co_run_in_worker( v9fs_co_run_in_worker(
{ {
err = s->ops->mknod(&s->ctx, fullname.data, &cred); err = s->ops->mknod(&s->ctx, &fidp->path, name->data, &cred);
if (err < 0) { if (err < 0) {
err = -errno; err = -errno;
} else { } else {
err = s->ops->lstat(&s->ctx, fullname.data, stbuf); v9fs_path_init(&path);
if (err < 0) { err = v9fs_name_to_path(s, &fidp->path, name->data, &path);
err = -errno; if (!err) {
err = s->ops->lstat(&s->ctx, &path, stbuf);
if (err < 0) {
err = -errno;
}
} }
v9fs_path_free(&path);
} }
}); });
qemu_co_rwlock_unlock(&s->rename_lock); qemu_co_rwlock_unlock(&s->rename_lock);
v9fs_string_free(&fullname);
return err; return err;
} }
int v9fs_co_remove(V9fsState *s, V9fsString *path) /* Only works with path name based fid */
int v9fs_co_remove(V9fsState *s, V9fsPath *path)
{ {
int err; int err;
@ -182,7 +185,24 @@ int v9fs_co_remove(V9fsState *s, V9fsString *path)
return err; return err;
} }
int v9fs_co_rename(V9fsState *s, V9fsString *oldpath, V9fsString *newpath) int v9fs_co_unlinkat(V9fsState *s, V9fsPath *path, V9fsString *name, int flags)
{
int err;
qemu_co_rwlock_rdlock(&s->rename_lock);
v9fs_co_run_in_worker(
{
err = s->ops->unlinkat(&s->ctx, path, name->data, flags);
if (err < 0) {
err = -errno;
}
});
qemu_co_rwlock_unlock(&s->rename_lock);
return err;
}
/* Only work with path name based fid */
int v9fs_co_rename(V9fsState *s, V9fsPath *oldpath, V9fsPath *newpath)
{ {
int err; int err;
@ -196,34 +216,68 @@ int v9fs_co_rename(V9fsState *s, V9fsString *oldpath, V9fsString *newpath)
return err; return err;
} }
int v9fs_co_renameat(V9fsState *s, V9fsPath *olddirpath, V9fsString *oldname,
V9fsPath *newdirpath, V9fsString *newname)
{
int err;
v9fs_co_run_in_worker(
{
err = s->ops->renameat(&s->ctx, olddirpath, oldname->data,
newdirpath, newname->data);
if (err < 0) {
err = -errno;
}
});
return err;
}
int v9fs_co_symlink(V9fsState *s, V9fsFidState *dfidp, V9fsString *name, int v9fs_co_symlink(V9fsState *s, V9fsFidState *dfidp, V9fsString *name,
const char *oldpath, gid_t gid, struct stat *stbuf) const char *oldpath, gid_t gid, struct stat *stbuf)
{ {
int err; int err;
FsCred cred; FsCred cred;
V9fsString fullname; V9fsPath path;
cred_init(&cred); cred_init(&cred);
cred.fc_uid = dfidp->uid; cred.fc_uid = dfidp->uid;
cred.fc_gid = gid; cred.fc_gid = gid;
cred.fc_mode = 0777; cred.fc_mode = 0777;
v9fs_string_init(&fullname);
qemu_co_rwlock_rdlock(&s->rename_lock); qemu_co_rwlock_rdlock(&s->rename_lock);
v9fs_string_sprintf(&fullname, "%s/%s", dfidp->path.data, name->data);
v9fs_co_run_in_worker( v9fs_co_run_in_worker(
{ {
err = s->ops->symlink(&s->ctx, oldpath, fullname.data, &cred); err = s->ops->symlink(&s->ctx, oldpath, &dfidp->path,
name->data, &cred);
if (err < 0) { if (err < 0) {
err = -errno; err = -errno;
} else { } else {
err = s->ops->lstat(&s->ctx, fullname.data, stbuf); v9fs_path_init(&path);
if (err < 0) { err = v9fs_name_to_path(s, &dfidp->path, name->data, &path);
err = -errno; if (!err) {
err = s->ops->lstat(&s->ctx, &path, stbuf);
if (err < 0) {
err = -errno;
}
} }
v9fs_path_free(&path);
} }
}); });
qemu_co_rwlock_unlock(&s->rename_lock); qemu_co_rwlock_unlock(&s->rename_lock);
v9fs_string_free(&fullname); return err;
}
/*
* For path name based fid we don't block. So we can
* directly call the fs driver ops.
*/
int v9fs_co_name_to_path(V9fsState *s, V9fsPath *dirpath,
const char *name, V9fsPath *path)
{
int err;
err = s->ops->name_to_path(&s->ctx, dirpath, name, path);
if (err < 0) {
err = -errno;
}
return err; return err;
} }

View File

@ -17,14 +17,14 @@
#include "qemu-coroutine.h" #include "qemu-coroutine.h"
#include "virtio-9p-coth.h" #include "virtio-9p-coth.h"
int v9fs_co_llistxattr(V9fsState *s, V9fsString *path, void *value, size_t size) int v9fs_co_llistxattr(V9fsState *s, V9fsPath *path, void *value, size_t size)
{ {
int err; int err;
qemu_co_rwlock_rdlock(&s->rename_lock); qemu_co_rwlock_rdlock(&s->rename_lock);
v9fs_co_run_in_worker( v9fs_co_run_in_worker(
{ {
err = s->ops->llistxattr(&s->ctx, path->data, value, size); err = s->ops->llistxattr(&s->ctx, path, value, size);
if (err < 0) { if (err < 0) {
err = -errno; err = -errno;
} }
@ -33,7 +33,7 @@ int v9fs_co_llistxattr(V9fsState *s, V9fsString *path, void *value, size_t size)
return err; return err;
} }
int v9fs_co_lgetxattr(V9fsState *s, V9fsString *path, int v9fs_co_lgetxattr(V9fsState *s, V9fsPath *path,
V9fsString *xattr_name, V9fsString *xattr_name,
void *value, size_t size) void *value, size_t size)
{ {
@ -42,7 +42,7 @@ int v9fs_co_lgetxattr(V9fsState *s, V9fsString *path,
qemu_co_rwlock_rdlock(&s->rename_lock); qemu_co_rwlock_rdlock(&s->rename_lock);
v9fs_co_run_in_worker( v9fs_co_run_in_worker(
{ {
err = s->ops->lgetxattr(&s->ctx, path->data, err = s->ops->lgetxattr(&s->ctx, path,
xattr_name->data, xattr_name->data,
value, size); value, size);
if (err < 0) { if (err < 0) {
@ -53,7 +53,7 @@ int v9fs_co_lgetxattr(V9fsState *s, V9fsString *path,
return err; return err;
} }
int v9fs_co_lsetxattr(V9fsState *s, V9fsString *path, int v9fs_co_lsetxattr(V9fsState *s, V9fsPath *path,
V9fsString *xattr_name, void *value, V9fsString *xattr_name, void *value,
size_t size, int flags) size_t size, int flags)
{ {
@ -62,7 +62,7 @@ int v9fs_co_lsetxattr(V9fsState *s, V9fsString *path,
qemu_co_rwlock_rdlock(&s->rename_lock); qemu_co_rwlock_rdlock(&s->rename_lock);
v9fs_co_run_in_worker( v9fs_co_run_in_worker(
{ {
err = s->ops->lsetxattr(&s->ctx, path->data, err = s->ops->lsetxattr(&s->ctx, path,
xattr_name->data, value, xattr_name->data, value,
size, flags); size, flags);
if (err < 0) { if (err < 0) {
@ -73,7 +73,7 @@ int v9fs_co_lsetxattr(V9fsState *s, V9fsString *path,
return err; return err;
} }
int v9fs_co_lremovexattr(V9fsState *s, V9fsString *path, int v9fs_co_lremovexattr(V9fsState *s, V9fsPath *path,
V9fsString *xattr_name) V9fsString *xattr_name)
{ {
int err; int err;
@ -81,8 +81,7 @@ int v9fs_co_lremovexattr(V9fsState *s, V9fsString *path,
qemu_co_rwlock_rdlock(&s->rename_lock); qemu_co_rwlock_rdlock(&s->rename_lock);
v9fs_co_run_in_worker( v9fs_co_run_in_worker(
{ {
err = s->ops->lremovexattr(&s->ctx, path->data, err = s->ops->lremovexattr(&s->ctx, path, xattr_name->data);
xattr_name->data);
if (err < 0) { if (err < 0) {
err = -errno; err = -errno;
} }

View File

@ -56,43 +56,49 @@ typedef struct V9fsThPool {
extern void co_run_in_worker_bh(void *); extern void co_run_in_worker_bh(void *);
extern int v9fs_init_worker_threads(void); extern int v9fs_init_worker_threads(void);
extern int v9fs_co_readlink(V9fsState *, V9fsString *, V9fsString *); extern int v9fs_co_readlink(V9fsState *, V9fsPath *, V9fsString *);
extern int v9fs_co_readdir_r(V9fsState *, V9fsFidState *, extern int v9fs_co_readdir_r(V9fsState *, V9fsFidState *,
struct dirent *, struct dirent **result); struct dirent *, struct dirent **result);
extern off_t v9fs_co_telldir(V9fsState *, V9fsFidState *); extern off_t v9fs_co_telldir(V9fsState *, V9fsFidState *);
extern void v9fs_co_seekdir(V9fsState *, V9fsFidState *, off_t); extern void v9fs_co_seekdir(V9fsState *, V9fsFidState *, off_t);
extern void v9fs_co_rewinddir(V9fsState *, V9fsFidState *); extern void v9fs_co_rewinddir(V9fsState *, V9fsFidState *);
extern int v9fs_co_statfs(V9fsState *, V9fsString *, struct statfs *); extern int v9fs_co_statfs(V9fsState *, V9fsPath *, struct statfs *);
extern int v9fs_co_lstat(V9fsState *, V9fsString *, struct stat *); extern int v9fs_co_lstat(V9fsState *, V9fsPath *, struct stat *);
extern int v9fs_co_chmod(V9fsState *, V9fsString *, mode_t); extern int v9fs_co_chmod(V9fsState *, V9fsPath *, mode_t);
extern int v9fs_co_utimensat(V9fsState *, V9fsString *, struct timespec [2]); extern int v9fs_co_utimensat(V9fsState *, V9fsPath *, struct timespec [2]);
extern int v9fs_co_chown(V9fsState *, V9fsString *, uid_t, gid_t); extern int v9fs_co_chown(V9fsState *, V9fsPath *, uid_t, gid_t);
extern int v9fs_co_truncate(V9fsState *, V9fsString *, off_t); extern int v9fs_co_truncate(V9fsState *, V9fsPath *, off_t);
extern int v9fs_co_llistxattr(V9fsState *, V9fsString *, void *, size_t); extern int v9fs_co_llistxattr(V9fsState *, V9fsPath *, void *, size_t);
extern int v9fs_co_lgetxattr(V9fsState *, V9fsString *, extern int v9fs_co_lgetxattr(V9fsState *, V9fsPath *,
V9fsString *, void *, size_t); V9fsString *, void *, size_t);
extern int v9fs_co_mknod(V9fsState *, V9fsFidState *, V9fsString *, uid_t, extern int v9fs_co_mknod(V9fsState *, V9fsFidState *, V9fsString *, uid_t,
gid_t, dev_t, mode_t, struct stat *); gid_t, dev_t, mode_t, struct stat *);
extern int v9fs_co_mkdir(V9fsState *, V9fsFidState *, V9fsString *, extern int v9fs_co_mkdir(V9fsState *, V9fsFidState *, V9fsString *,
mode_t, uid_t, gid_t, struct stat *); mode_t, uid_t, gid_t, struct stat *);
extern int v9fs_co_remove(V9fsState *, V9fsString *); extern int v9fs_co_remove(V9fsState *, V9fsPath *);
extern int v9fs_co_rename(V9fsState *, V9fsString *, V9fsString *); extern int v9fs_co_rename(V9fsState *, V9fsPath *, V9fsPath *);
extern int v9fs_co_unlinkat(V9fsState *, V9fsPath *, V9fsString *, int flags);
extern int v9fs_co_renameat(V9fsState *, V9fsPath *, V9fsString *,
V9fsPath *, V9fsString *);
extern int v9fs_co_fstat(V9fsState *, int, struct stat *); extern int v9fs_co_fstat(V9fsState *, int, struct stat *);
extern int v9fs_co_opendir(V9fsState *, V9fsFidState *); extern int v9fs_co_opendir(V9fsState *, V9fsFidState *);
extern int v9fs_co_open(V9fsState *, V9fsFidState *, int); extern int v9fs_co_open(V9fsState *, V9fsFidState *, int);
extern int v9fs_co_open2(V9fsState *, V9fsFidState *, V9fsString *, extern int v9fs_co_open2(V9fsState *, V9fsFidState *, V9fsString *,
gid_t, int, int, struct stat *); gid_t, int, int, struct stat *);
extern int v9fs_co_lsetxattr(V9fsState *, V9fsString *, V9fsString *, extern int v9fs_co_lsetxattr(V9fsState *, V9fsPath *, V9fsString *,
void *, size_t, int); void *, size_t, int);
extern int v9fs_co_lremovexattr(V9fsState *, V9fsString *, V9fsString *); extern int v9fs_co_lremovexattr(V9fsState *, V9fsPath *, V9fsString *);
extern int v9fs_co_closedir(V9fsState *, DIR *); extern int v9fs_co_closedir(V9fsState *, DIR *);
extern int v9fs_co_close(V9fsState *, int); extern int v9fs_co_close(V9fsState *, int);
extern int v9fs_co_fsync(V9fsState *, V9fsFidState *, int); extern int v9fs_co_fsync(V9fsState *, V9fsFidState *, int);
extern int v9fs_co_symlink(V9fsState *, V9fsFidState *, V9fsString *, extern int v9fs_co_symlink(V9fsState *, V9fsFidState *, V9fsString *,
const char *, gid_t, struct stat *); const char *, gid_t, struct stat *);
extern int v9fs_co_link(V9fsState *, V9fsString *, V9fsString *); extern int v9fs_co_link(V9fsState *, V9fsFidState *,
V9fsFidState *, V9fsString *);
extern int v9fs_co_pwritev(V9fsState *, V9fsFidState *, extern int v9fs_co_pwritev(V9fsState *, V9fsFidState *,
struct iovec *, int, int64_t); struct iovec *, int, int64_t);
extern int v9fs_co_preadv(V9fsState *, V9fsFidState *, extern int v9fs_co_preadv(V9fsState *, V9fsFidState *,
struct iovec *, int, int64_t); struct iovec *, int, int64_t);
extern int v9fs_co_name_to_path(V9fsState *, V9fsPath *,
const char *, V9fsPath *);
#endif #endif

View File

@ -22,10 +22,12 @@
#include <attr/xattr.h> #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; int err;
char buffer[PATH_MAX]; char buffer[PATH_MAX];
char *path = fs_path->data;
err = lstat(rpath(fs_ctx, path, buffer), stbuf); err = lstat(rpath(fs_ctx, path, buffer), stbuf);
if (err) { if (err) {
return 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) static int local_set_xattr(const char *path, FsCred *credp)
{ {
int err; int err;
if (credp->fc_uid != -1) { if (credp->fc_uid != -1) {
err = setxattr(path, "user.virtfs.uid", &credp->fc_uid, sizeof(uid_t), err = setxattr(path, "user.virtfs.uid", &credp->fc_uid, sizeof(uid_t),
0); 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, static int local_post_create_passthrough(FsContext *fs_ctx, const char *path,
FsCred *credp) FsCred *credp)
{ {
char buffer[PATH_MAX]; char buffer[PATH_MAX];
if (chmod(rpath(fs_ctx, path, buffer), credp->fc_mode & 07777) < 0) { if (chmod(rpath(fs_ctx, path, buffer), credp->fc_mode & 07777) < 0) {
return -1; return -1;
} }
@ -110,11 +114,13 @@ static int local_post_create_passthrough(FsContext *fs_ctx, const char *path,
return 0; return 0;
} }
static ssize_t local_readlink(FsContext *fs_ctx, const char *path, static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
char *buf, size_t bufsz) char *buf, size_t bufsz)
{ {
ssize_t tsize = -1; ssize_t tsize = -1;
char buffer[PATH_MAX]; char buffer[PATH_MAX];
char *path = fs_path->data;
if (fs_ctx->fs_sm == SM_MAPPED) { if (fs_ctx->fs_sm == SM_MAPPED) {
int fd; int fd;
fd = open(rpath(fs_ctx, path, buffer), O_RDONLY); fd = open(rpath(fs_ctx, path, buffer), O_RDONLY);
@ -143,15 +149,19 @@ static int local_closedir(FsContext *ctx, DIR *dir)
return closedir(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 buffer[PATH_MAX];
char *path = fs_path->data;
return open(rpath(ctx, path, buffer), flags); 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 buffer[PATH_MAX];
char *path = fs_path->data;
return opendir(rpath(ctx, path, buffer)); 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, static int local_readdir_r(FsContext *ctx, DIR *dir, struct dirent *entry,
struct dirent **result) struct dirent **result)
{ {
return readdir_r(dir, entry, 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, 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 #ifdef CONFIG_PREADV
return pwritev(fd, iov, iovcnt, offset); return pwritev(fd, iov, iovcnt, offset);
@ -206,9 +216,11 @@ static ssize_t local_pwritev(FsContext *ctx, int fd, const struct iovec *iov,
#endif #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 buffer[PATH_MAX];
char *path = fs_path->data;
if (fs_ctx->fs_sm == SM_MAPPED) { if (fs_ctx->fs_sm == SM_MAPPED) {
return local_set_xattr(rpath(fs_ctx, path, buffer), credp); return local_set_xattr(rpath(fs_ctx, path, buffer), credp);
} else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) || } 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; 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 err = -1;
int serrno = 0; int serrno = 0;
V9fsString fullname;
char buffer[PATH_MAX]; 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 */ /* Determine the security model */
if (fs_ctx->fs_sm == SM_MAPPED) { if (fs_ctx->fs_sm == SM_MAPPED) {
err = mknod(rpath(fs_ctx, path, buffer), err = mknod(rpath(fs_ctx, path, buffer),
SM_LOCAL_MODE_BITS|S_IFREG, 0); SM_LOCAL_MODE_BITS|S_IFREG, 0);
if (err == -1) { if (err == -1) {
return err; goto out;
} }
local_set_xattr(rpath(fs_ctx, path, buffer), credp); local_set_xattr(rpath(fs_ctx, path, buffer), credp);
if (err == -1) { 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, err = mknod(rpath(fs_ctx, path, buffer), credp->fc_mode,
credp->fc_rdev); credp->fc_rdev);
if (err == -1) { if (err == -1) {
return err; goto out;
} }
err = local_post_create_passthrough(fs_ctx, path, credp); err = local_post_create_passthrough(fs_ctx, path, credp);
if (err == -1) { if (err == -1) {
@ -249,25 +268,34 @@ static int local_mknod(FsContext *fs_ctx, const char *path, FsCred *credp)
goto err_end; goto err_end;
} }
} }
return err; goto out;
err_end: err_end:
remove(rpath(fs_ctx, path, buffer)); remove(rpath(fs_ctx, path, buffer));
errno = serrno; errno = serrno;
out:
v9fs_string_free(&fullname);
return err; 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 err = -1;
int serrno = 0; int serrno = 0;
V9fsString fullname;
char buffer[PATH_MAX]; 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 */ /* Determine the security model */
if (fs_ctx->fs_sm == SM_MAPPED) { if (fs_ctx->fs_sm == SM_MAPPED) {
err = mkdir(rpath(fs_ctx, path, buffer), SM_LOCAL_DIR_MODE_BITS); err = mkdir(rpath(fs_ctx, path, buffer), SM_LOCAL_DIR_MODE_BITS);
if (err == -1) { if (err == -1) {
return err; goto out;
} }
credp->fc_mode = credp->fc_mode|S_IFDIR; credp->fc_mode = credp->fc_mode|S_IFDIR;
err = local_set_xattr(rpath(fs_ctx, path, buffer), credp); 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)) { (fs_ctx->fs_sm == SM_NONE)) {
err = mkdir(rpath(fs_ctx, path, buffer), credp->fc_mode); err = mkdir(rpath(fs_ctx, path, buffer), credp->fc_mode);
if (err == -1) { if (err == -1) {
return err; goto out;
} }
err = local_post_create_passthrough(fs_ctx, path, credp); err = local_post_create_passthrough(fs_ctx, path, credp);
if (err == -1) { if (err == -1) {
@ -287,11 +315,13 @@ static int local_mkdir(FsContext *fs_ctx, const char *path, FsCred *credp)
goto err_end; goto err_end;
} }
} }
return err; goto out;
err_end: err_end:
remove(rpath(fs_ctx, path, buffer)); remove(rpath(fs_ctx, path, buffer));
errno = serrno; errno = serrno;
out:
v9fs_string_free(&fullname);
return err; return err;
} }
@ -325,19 +355,26 @@ static int local_fstat(FsContext *fs_ctx, int fd, struct stat *stbuf)
return err; return err;
} }
static int local_open2(FsContext *fs_ctx, const char *path, int flags, static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
FsCred *credp) int flags, FsCred *credp)
{ {
char *path;
int fd = -1; int fd = -1;
int err = -1; int err = -1;
int serrno = 0; int serrno = 0;
V9fsString fullname;
char buffer[PATH_MAX]; 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 */ /* Determine the security model */
if (fs_ctx->fs_sm == SM_MAPPED) { if (fs_ctx->fs_sm == SM_MAPPED) {
fd = open(rpath(fs_ctx, path, buffer), flags, SM_LOCAL_MODE_BITS); fd = open(rpath(fs_ctx, path, buffer), flags, SM_LOCAL_MODE_BITS);
if (fd == -1) { if (fd == -1) {
return fd; err = fd;
goto out;
} }
credp->fc_mode = credp->fc_mode|S_IFREG; credp->fc_mode = credp->fc_mode|S_IFREG;
/* Set cleint credentials in xattr */ /* 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)) { (fs_ctx->fs_sm == SM_NONE)) {
fd = open(rpath(fs_ctx, path, buffer), flags, credp->fc_mode); fd = open(rpath(fs_ctx, path, buffer), flags, credp->fc_mode);
if (fd == -1) { if (fd == -1) {
return fd; err = fd;
goto out;
} }
err = local_post_create_passthrough(fs_ctx, path, credp); err = local_post_create_passthrough(fs_ctx, path, credp);
if (err == -1) { if (err == -1) {
@ -358,23 +396,32 @@ static int local_open2(FsContext *fs_ctx, const char *path, int flags,
goto err_end; goto err_end;
} }
} }
return fd; err = fd;
goto out;
err_end: err_end:
close(fd); close(fd);
remove(rpath(fs_ctx, path, buffer)); remove(rpath(fs_ctx, path, buffer));
errno = serrno; errno = serrno;
out:
v9fs_string_free(&fullname);
return err; return err;
} }
static int local_symlink(FsContext *fs_ctx, const char *oldpath, 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 err = -1;
int serrno = 0; int serrno = 0;
char *newpath;
V9fsString fullname;
char buffer[PATH_MAX]; 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 */ /* Determine the security model */
if (fs_ctx->fs_sm == SM_MAPPED) { if (fs_ctx->fs_sm == SM_MAPPED) {
int fd; 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, fd = open(rpath(fs_ctx, newpath, buffer), O_CREAT|O_EXCL|O_RDWR,
SM_LOCAL_MODE_BITS); SM_LOCAL_MODE_BITS);
if (fd == -1) { if (fd == -1) {
return fd; err = fd;
goto out;
} }
/* Write the oldpath (target) to the file. */ /* Write the oldpath (target) to the file. */
oldpath_size = strlen(oldpath); oldpath_size = strlen(oldpath);
@ -408,10 +456,10 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
(fs_ctx->fs_sm == SM_NONE)) { (fs_ctx->fs_sm == SM_NONE)) {
err = symlink(oldpath, rpath(fs_ctx, newpath, buffer)); err = symlink(oldpath, rpath(fs_ctx, newpath, buffer));
if (err) { if (err) {
return err; goto out;
} }
err = lchown(rpath(fs_ctx, newpath, buffer), credp->fc_uid, err = lchown(rpath(fs_ctx, newpath, buffer), credp->fc_uid,
credp->fc_gid); credp->fc_gid);
if (err == -1) { if (err == -1) {
/* /*
* If we fail to change ownership and if we are * 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; err = 0;
} }
} }
return err; goto out;
err_end: err_end:
remove(rpath(fs_ctx, newpath, buffer)); remove(rpath(fs_ctx, newpath, buffer));
errno = serrno; errno = serrno;
out:
v9fs_string_free(&fullname);
return err; 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]; 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 buffer[PATH_MAX];
char *path = fs_path->data;
return truncate(rpath(ctx, path, buffer), size); 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)); 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 buffer[PATH_MAX];
char *path = fs_path->data;
if ((credp->fc_uid == -1 && credp->fc_gid == -1) || if ((credp->fc_uid == -1 && credp->fc_gid == -1) ||
(fs_ctx->fs_sm == SM_PASSTHROUGH)) { (fs_ctx->fs_sm == SM_PASSTHROUGH)) {
return lchown(rpath(fs_ctx, path, buffer), credp->fc_uid, 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; return -1;
} }
static int local_utimensat(FsContext *s, const char *path, static int local_utimensat(FsContext *s, V9fsPath *fs_path,
const struct timespec *buf) const struct timespec *buf)
{ {
char buffer[PATH_MAX]; char buffer[PATH_MAX];
char *path = fs_path->data;
return qemu_utimensat(AT_FDCWD, rpath(s, path, buffer), buf, 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) 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]; 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) const char *name, void *value, size_t size)
{ {
char *path = fs_path->data;
return v9fs_get_xattr(ctx, path, name, value, size); 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) void *value, size_t size)
{ {
char *path = fs_path->data;
return v9fs_list_xattr(ctx, path, value, size); 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) void *value, size_t size, int flags)
{ {
char *path = fs_path->data;
return v9fs_set_xattr(ctx, path, name, value, size, flags); return v9fs_set_xattr(ctx, path, name, value, size, flags);
} }
static int local_lremovexattr(FsContext *ctx, static int local_lremovexattr(FsContext *ctx, V9fsPath *fs_path,
const char *path, const char *name) const char *name)
{ {
char *path = fs_path->data;
return v9fs_remove_xattr(ctx, path, name); 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 = { FileOperations local_ops = {
.lstat = local_lstat, .lstat = local_lstat,
@ -555,4 +677,7 @@ FileOperations local_ops = {
.llistxattr = local_llistxattr, .llistxattr = local_llistxattr,
.lsetxattr = local_lsetxattr, .lsetxattr = local_lsetxattr,
.lremovexattr = local_lremovexattr, .lremovexattr = local_lremovexattr,
.name_to_path = local_name_to_path,
.renameat = local_renameat,
.unlinkat = local_unlinkat,
}; };

View File

@ -214,16 +214,48 @@ void v9fs_string_copy(V9fsString *lhs, V9fsString *rhs)
v9fs_string_sprintf(lhs, "%s", rhs->data); v9fs_string_sprintf(lhs, "%s", rhs->data);
} }
void v9fs_path_init(V9fsPath *path)
{
path->data = NULL;
path->size = 0;
}
void v9fs_path_free(V9fsPath *path)
{
g_free(path->data);
path->data = NULL;
path->size = 0;
}
void v9fs_path_copy(V9fsPath *lhs, V9fsPath *rhs)
{
v9fs_path_free(lhs);
lhs->data = g_malloc(rhs->size);
memcpy(lhs->data, rhs->data, rhs->size);
lhs->size = rhs->size;
}
int v9fs_name_to_path(V9fsState *s, V9fsPath *dirpath,
const char *name, V9fsPath *path)
{
int err;
err = s->ops->name_to_path(&s->ctx, dirpath, name, path);
if (err < 0) {
err = -errno;
}
return err;
}
/* /*
* Return TRUE if s1 is an ancestor of s2. * Return TRUE if s1 is an ancestor of s2.
* *
* E.g. "a/b" is an ancestor of "a/b/c" but not of "a/bc/d". * E.g. "a/b" is an ancestor of "a/b/c" but not of "a/bc/d".
* As a special case, We treat s1 as ancestor of s2 if they are same! * As a special case, We treat s1 as ancestor of s2 if they are same!
*/ */
static int v9fs_path_is_ancestor(V9fsString *s1, V9fsString *s2) static int v9fs_path_is_ancestor(V9fsPath *s1, V9fsPath *s2)
{ {
if (!strncmp(s1->data, s2->data, s1->size)) { if (!strncmp(s1->data, s2->data, s1->size - 1)) {
if (s2->data[s1->size] == '\0' || s2->data[s1->size] == '/') { if (s2->data[s1->size - 1] == '\0' || s2->data[s1->size - 1] == '/') {
return 1; return 1;
} }
} }
@ -368,7 +400,7 @@ static int free_fid(V9fsState *s, V9fsFidState *fidp)
} else if (fidp->fid_type == P9_FID_XATTR) { } else if (fidp->fid_type == P9_FID_XATTR) {
retval = v9fs_xattr_fid_clunk(s, fidp); retval = v9fs_xattr_fid_clunk(s, fidp);
} }
v9fs_string_free(&fidp->path); v9fs_path_free(&fidp->path);
g_free(fidp); g_free(fidp);
return retval; return retval;
} }
@ -484,14 +516,17 @@ void v9fs_reclaim_fd(V9fsState *s)
} }
} }
static int v9fs_mark_fids_unreclaim(V9fsState *s, V9fsString *str) static int v9fs_mark_fids_unreclaim(V9fsState *s, V9fsPath *path)
{ {
int err; int err;
V9fsFidState *fidp, head_fid; V9fsFidState *fidp, head_fid;
head_fid.next = s->fid_list; head_fid.next = s->fid_list;
for (fidp = s->fid_list; fidp; fidp = fidp->next) { for (fidp = s->fid_list; fidp; fidp = fidp->next) {
if (!strcmp(fidp->path.data, str->data)) { if (fidp->path.size != path->size) {
continue;
}
if (!memcmp(fidp->path.data, path->data, path->size)) {
/* Mark the fid non reclaimable. */ /* Mark the fid non reclaimable. */
fidp->flags |= FID_NON_RECLAIMABLE; fidp->flags |= FID_NON_RECLAIMABLE;
@ -998,7 +1033,7 @@ static uint32_t stat_to_v9mode(const struct stat *stbuf)
return mode; return mode;
} }
static int stat_to_v9stat(V9fsState *s, V9fsString *name, static int stat_to_v9stat(V9fsState *s, V9fsPath *name,
const struct stat *stbuf, const struct stat *stbuf,
V9fsStat *v9stat) V9fsStat *v9stat)
{ {
@ -1150,13 +1185,16 @@ static void print_sg(struct iovec *sg, int cnt)
printf("}\n"); printf("}\n");
} }
static void v9fs_fix_path(V9fsString *dst, V9fsString *src, int len) /* Will call this only for path name based fid */
static void v9fs_fix_path(V9fsPath *dst, V9fsPath *src, int len)
{ {
V9fsString str; V9fsPath str;
v9fs_string_init(&str); v9fs_path_init(&str);
v9fs_string_copy(&str, dst); v9fs_path_copy(&str, dst);
v9fs_string_sprintf(dst, "%s%s", src->data, str.data+len); v9fs_string_sprintf((V9fsString *)dst, "%s%s", src->data, str.data+len);
v9fs_string_free(&str); v9fs_path_free(&str);
/* +1 to include terminating NULL */
dst->size++;
} }
static void v9fs_version(void *opaque) static void v9fs_version(void *opaque)
@ -1202,7 +1240,12 @@ static void v9fs_attach(void *opaque)
goto out_nofid; goto out_nofid;
} }
fidp->uid = n_uname; fidp->uid = n_uname;
v9fs_string_sprintf(&fidp->path, "%s", "/"); err = v9fs_co_name_to_path(s, NULL, "/", &fidp->path);
if (err < 0) {
err = -EINVAL;
clunk_fid(s, fid);
goto out;
}
err = fid_to_qid(s, fidp, &qid); err = fid_to_qid(s, fidp, &qid);
if (err < 0) { if (err < 0) {
err = -EINVAL; err = -EINVAL;
@ -1400,7 +1443,7 @@ static void v9fs_walk(void *opaque)
int name_idx; int name_idx;
V9fsQID *qids = NULL; V9fsQID *qids = NULL;
int i, err = 0; int i, err = 0;
V9fsString path; V9fsPath dpath, path;
uint16_t nwnames; uint16_t nwnames;
struct stat stbuf; struct stat stbuf;
size_t offset = 7; size_t offset = 7;
@ -1420,7 +1463,6 @@ static void v9fs_walk(void *opaque)
for (i = 0; i < nwnames; i++) { for (i = 0; i < nwnames; i++) {
offset += pdu_unmarshal(pdu, offset, "s", &wnames[i]); offset += pdu_unmarshal(pdu, offset, "s", &wnames[i]);
} }
} else if (nwnames > P9_MAXWELEM) { } else if (nwnames > P9_MAXWELEM) {
err = -EINVAL; err = -EINVAL;
goto out_nofid; goto out_nofid;
@ -1430,22 +1472,29 @@ static void v9fs_walk(void *opaque)
err = -ENOENT; err = -ENOENT;
goto out_nofid; goto out_nofid;
} }
v9fs_path_init(&dpath);
v9fs_path_init(&path);
/*
* Both dpath and path initially poin to fidp.
* Needed to handle request with nwnames == 0
*/
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(s, &dpath, wnames[name_idx].data, &path);
if (err < 0) {
goto out;
}
err = v9fs_co_lstat(s, &path, &stbuf);
if (err < 0) {
goto out;
}
stat_to_qid(&stbuf, &qids[name_idx]);
v9fs_path_copy(&dpath, &path);
}
if (fid == newfid) { if (fid == newfid) {
BUG_ON(fidp->fid_type != P9_FID_NONE); BUG_ON(fidp->fid_type != P9_FID_NONE);
v9fs_string_init(&path); v9fs_path_copy(&fidp->path, &path);
for (name_idx = 0; name_idx < nwnames; name_idx++) {
v9fs_string_sprintf(&path, "%s/%s",
fidp->path.data, wnames[name_idx].data);
v9fs_string_copy(&fidp->path, &path);
err = v9fs_co_lstat(s, &fidp->path, &stbuf);
if (err < 0) {
v9fs_string_free(&path);
goto out;
}
stat_to_qid(&stbuf, &qids[name_idx]);
}
v9fs_string_free(&path);
} else { } else {
newfidp = alloc_fid(s, newfid); newfidp = alloc_fid(s, newfid);
if (newfidp == NULL) { if (newfidp == NULL) {
@ -1453,21 +1502,7 @@ static void v9fs_walk(void *opaque)
goto out; goto out;
} }
newfidp->uid = fidp->uid; newfidp->uid = fidp->uid;
v9fs_string_init(&path); v9fs_path_copy(&newfidp->path, &path);
v9fs_string_copy(&newfidp->path, &fidp->path);
for (name_idx = 0; name_idx < nwnames; name_idx++) {
v9fs_string_sprintf(&path, "%s/%s", newfidp->path.data,
wnames[name_idx].data);
v9fs_string_copy(&newfidp->path, &path);
err = v9fs_co_lstat(s, &newfidp->path, &stbuf);
if (err < 0) {
clunk_fid(s, newfidp->fid);
v9fs_string_free(&path);
goto out;
}
stat_to_qid(&stbuf, &qids[name_idx]);
}
v9fs_string_free(&path);
} }
err = v9fs_walk_marshal(pdu, nwnames, qids); err = v9fs_walk_marshal(pdu, nwnames, qids);
out: out:
@ -1475,6 +1510,8 @@ out:
if (newfidp) { if (newfidp) {
put_fid(s, newfidp); put_fid(s, newfidp);
} }
v9fs_path_free(&dpath);
v9fs_path_free(&path);
out_nofid: out_nofid:
complete_pdu(s, pdu, err); complete_pdu(s, pdu, err);
if (nwnames && nwnames <= P9_MAXWELEM) { if (nwnames && nwnames <= P9_MAXWELEM) {
@ -1484,9 +1521,10 @@ out_nofid:
g_free(wnames); g_free(wnames);
g_free(qids); g_free(qids);
} }
return;
} }
static int32_t get_iounit(V9fsState *s, V9fsString *name) static int32_t get_iounit(V9fsState *s, V9fsPath *path)
{ {
struct statfs stbuf; struct statfs stbuf;
int32_t iounit = 0; int32_t iounit = 0;
@ -1495,7 +1533,7 @@ static int32_t get_iounit(V9fsState *s, V9fsString *name)
* iounit should be multiples of f_bsize (host filesystem block size * iounit should be multiples of f_bsize (host filesystem block size
* and as well as less than (client msize - P9_IOHDRSZ)) * and as well as less than (client msize - P9_IOHDRSZ))
*/ */
if (!v9fs_co_statfs(s, name, &stbuf)) { if (!v9fs_co_statfs(s, path, &stbuf)) {
iounit = stbuf.f_bsize; iounit = stbuf.f_bsize;
iounit *= (s->msize - P9_IOHDRSZ)/stbuf.f_bsize; iounit *= (s->msize - P9_IOHDRSZ)/stbuf.f_bsize;
} }
@ -1705,7 +1743,7 @@ static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu,
static int v9fs_do_readdir_with_stat(V9fsState *s, V9fsPDU *pdu, static int v9fs_do_readdir_with_stat(V9fsState *s, V9fsPDU *pdu,
V9fsFidState *fidp, int32_t max_count) V9fsFidState *fidp, int32_t max_count)
{ {
V9fsString name; V9fsPath path;
V9fsStat v9stat; V9fsStat v9stat;
int len, err = 0; int len, err = 0;
int32_t count = 0; int32_t count = 0;
@ -1722,17 +1760,20 @@ static int v9fs_do_readdir_with_stat(V9fsState *s, V9fsPDU *pdu,
dent = g_malloc(sizeof(struct dirent)); dent = g_malloc(sizeof(struct dirent));
while (1) { while (1) {
v9fs_string_init(&name); v9fs_path_init(&path);
err = v9fs_co_readdir_r(s, fidp, dent, &result); err = v9fs_co_readdir_r(s, fidp, dent, &result);
if (err || !result) { if (err || !result) {
break; break;
} }
v9fs_string_sprintf(&name, "%s/%s", fidp->path.data, dent->d_name); err = v9fs_co_name_to_path(s, &fidp->path, dent->d_name, &path);
err = v9fs_co_lstat(s, &name, &stbuf);
if (err < 0) { if (err < 0) {
goto out; goto out;
} }
err = stat_to_v9stat(s, &name, &stbuf, &v9stat); err = v9fs_co_lstat(s, &path, &stbuf);
if (err < 0) {
goto out;
}
err = stat_to_v9stat(s, &path, &stbuf, &v9stat);
if (err < 0) { if (err < 0) {
goto out; goto out;
} }
@ -1742,18 +1783,18 @@ static int v9fs_do_readdir_with_stat(V9fsState *s, V9fsPDU *pdu,
/* Ran out of buffer. Set dir back to old position and return */ /* Ran out of buffer. Set dir back to old position and return */
v9fs_co_seekdir(s, fidp, saved_dir_pos); v9fs_co_seekdir(s, fidp, saved_dir_pos);
v9fs_stat_free(&v9stat); v9fs_stat_free(&v9stat);
v9fs_string_free(&name); v9fs_path_free(&path);
g_free(dent); g_free(dent);
return count; return count;
} }
count += len; count += len;
v9fs_stat_free(&v9stat); v9fs_stat_free(&v9stat);
v9fs_string_free(&name); v9fs_path_free(&path);
saved_dir_pos = dent->d_off; saved_dir_pos = dent->d_off;
} }
out: out:
g_free(dent); g_free(dent);
v9fs_string_free(&name); v9fs_path_free(&path);
if (err < 0) { if (err < 0) {
return err; return err;
} }
@ -2062,14 +2103,14 @@ static void v9fs_create(void *opaque)
V9fsQID qid; V9fsQID qid;
int32_t perm; int32_t perm;
int8_t mode; int8_t mode;
V9fsPath path;
struct stat stbuf; struct stat stbuf;
V9fsString name; V9fsString name;
V9fsString extension; V9fsString extension;
V9fsString fullname;
int iounit; int iounit;
V9fsPDU *pdu = opaque; V9fsPDU *pdu = opaque;
v9fs_string_init(&fullname); v9fs_path_init(&path);
pdu_unmarshal(pdu, offset, "dsdbs", &fid, &name, pdu_unmarshal(pdu, offset, "dsdbs", &fid, &name,
&perm, &mode, &extension); &perm, &mode, &extension);
@ -2079,23 +2120,17 @@ static void v9fs_create(void *opaque)
err = -EINVAL; err = -EINVAL;
goto out_nofid; goto out_nofid;
} }
v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
err = v9fs_co_lstat(pdu->s, &fullname, &stbuf);
if (!err) {
err = -EEXIST;
goto out;
} else if (err != -ENOENT) {
goto out;
}
if (perm & P9_STAT_MODE_DIR) { if (perm & P9_STAT_MODE_DIR) {
err = v9fs_co_mkdir(pdu->s, fidp, &name, perm & 0777, err = v9fs_co_mkdir(pdu->s, fidp, &name, perm & 0777,
fidp->uid, -1, &stbuf); fidp->uid, -1, &stbuf);
if (err < 0) { if (err < 0) {
goto out; goto out;
} }
v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data); err = v9fs_co_name_to_path(pdu->s, &fidp->path, name.data, &path);
v9fs_string_copy(&fidp->path, &fullname); if (err < 0) {
goto out;
}
v9fs_path_copy(&fidp->path, &path);
err = v9fs_co_opendir(pdu->s, fidp); err = v9fs_co_opendir(pdu->s, fidp);
if (err < 0) { if (err < 0) {
goto out; goto out;
@ -2107,23 +2142,29 @@ static void v9fs_create(void *opaque)
if (err < 0) { if (err < 0) {
goto out; goto out;
} }
v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data); err = v9fs_co_name_to_path(pdu->s, &fidp->path, name.data, &path);
v9fs_string_copy(&fidp->path, &fullname);
} else if (perm & P9_STAT_MODE_LINK) {
int32_t nfid = atoi(extension.data);
V9fsFidState *nfidp = get_fid(pdu->s, nfid);
if (nfidp == NULL) {
err = -EINVAL;
goto out;
}
v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data);
err = v9fs_co_link(pdu->s, &nfidp->path, &fullname);
put_fid(pdu->s, nfidp);
if (err < 0) { if (err < 0) {
goto out; goto out;
} }
v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data); v9fs_path_copy(&fidp->path, &path);
v9fs_string_copy(&fidp->path, &fullname); } else if (perm & P9_STAT_MODE_LINK) {
int32_t ofid = atoi(extension.data);
V9fsFidState *ofidp = get_fid(pdu->s, ofid);
if (ofidp == NULL) {
err = -EINVAL;
goto out;
}
err = v9fs_co_link(pdu->s, ofidp, fidp, &name);
put_fid(pdu->s, ofidp);
if (err < 0) {
goto out;
}
err = v9fs_co_name_to_path(pdu->s, &fidp->path, name.data, &path);
if (err < 0) {
fidp->fid_type = P9_FID_NONE;
goto out;
}
v9fs_path_copy(&fidp->path, &path);
err = v9fs_co_lstat(pdu->s, &fidp->path, &stbuf); err = v9fs_co_lstat(pdu->s, &fidp->path, &stbuf);
if (err < 0) { if (err < 0) {
fidp->fid_type = P9_FID_NONE; fidp->fid_type = P9_FID_NONE;
@ -2157,24 +2198,33 @@ static void v9fs_create(void *opaque)
if (err < 0) { if (err < 0) {
goto out; goto out;
} }
v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data); err = v9fs_co_name_to_path(pdu->s, &fidp->path, name.data, &path);
v9fs_string_copy(&fidp->path, &fullname); if (err < 0) {
goto out;
}
v9fs_path_copy(&fidp->path, &path);
} else if (perm & P9_STAT_MODE_NAMED_PIPE) { } else if (perm & P9_STAT_MODE_NAMED_PIPE) {
err = v9fs_co_mknod(pdu->s, fidp, &name, fidp->uid, -1, err = v9fs_co_mknod(pdu->s, fidp, &name, fidp->uid, -1,
0, S_IFIFO | (perm & 0777), &stbuf); 0, S_IFIFO | (perm & 0777), &stbuf);
if (err < 0) { if (err < 0) {
goto out; goto out;
} }
v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data); err = v9fs_co_name_to_path(pdu->s, &fidp->path, name.data, &path);
v9fs_string_copy(&fidp->path, &fullname); if (err < 0) {
goto out;
}
v9fs_path_copy(&fidp->path, &path);
} else if (perm & P9_STAT_MODE_SOCKET) { } else if (perm & P9_STAT_MODE_SOCKET) {
err = v9fs_co_mknod(pdu->s, fidp, &name, fidp->uid, -1, err = v9fs_co_mknod(pdu->s, fidp, &name, fidp->uid, -1,
0, S_IFSOCK | (perm & 0777), &stbuf); 0, S_IFSOCK | (perm & 0777), &stbuf);
if (err < 0) { if (err < 0) {
goto out; goto out;
} }
v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data); err = v9fs_co_name_to_path(pdu->s, &fidp->path, name.data, &path);
v9fs_string_copy(&fidp->path, &fullname); if (err < 0) {
goto out;
}
v9fs_path_copy(&fidp->path, &path);
} else { } else {
err = v9fs_co_open2(pdu->s, fidp, &name, -1, err = v9fs_co_open2(pdu->s, fidp, &name, -1,
omode_to_uflags(mode)|O_CREAT, perm, &stbuf); omode_to_uflags(mode)|O_CREAT, perm, &stbuf);
@ -2201,7 +2251,7 @@ out_nofid:
complete_pdu(pdu->s, pdu, err); complete_pdu(pdu->s, pdu, err);
v9fs_string_free(&name); v9fs_string_free(&name);
v9fs_string_free(&extension); v9fs_string_free(&extension);
v9fs_string_free(&fullname); v9fs_path_free(&path);
} }
static void v9fs_symlink(void *opaque) static void v9fs_symlink(void *opaque)
@ -2254,12 +2304,10 @@ static void v9fs_link(void *opaque)
V9fsState *s = pdu->s; V9fsState *s = pdu->s;
int32_t dfid, oldfid; int32_t dfid, oldfid;
V9fsFidState *dfidp, *oldfidp; V9fsFidState *dfidp, *oldfidp;
V9fsString name, fullname; V9fsString name;;
size_t offset = 7; size_t offset = 7;
int err = 0; int err = 0;
v9fs_string_init(&fullname);
pdu_unmarshal(pdu, offset, "dds", &dfid, &oldfid, &name); pdu_unmarshal(pdu, offset, "dds", &dfid, &oldfid, &name);
dfidp = get_fid(s, dfid); dfidp = get_fid(s, dfid);
@ -2273,14 +2321,10 @@ static void v9fs_link(void *opaque)
err = -ENOENT; err = -ENOENT;
goto out; goto out;
} }
err = v9fs_co_link(s, oldfidp, dfidp, &name);
v9fs_string_sprintf(&fullname, "%s/%s", dfidp->path.data, name.data);
err = v9fs_co_link(s, &oldfidp->path, &fullname);
if (!err) { if (!err) {
err = offset; err = offset;
} }
v9fs_string_free(&fullname);
out: out:
put_fid(s, dfidp); put_fid(s, dfidp);
out_nofid: out_nofid:
@ -2329,9 +2373,9 @@ static void v9fs_unlinkat(void *opaque)
V9fsString name; V9fsString name;
int32_t dfid, flags; int32_t dfid, flags;
size_t offset = 7; size_t offset = 7;
V9fsPath path;
V9fsFidState *dfidp; V9fsFidState *dfidp;
V9fsPDU *pdu = opaque; V9fsPDU *pdu = opaque;
V9fsString full_name;
pdu_unmarshal(pdu, offset, "dsd", &dfid, &name, &flags); pdu_unmarshal(pdu, offset, "dsd", &dfid, &name, &flags);
@ -2340,36 +2384,44 @@ static void v9fs_unlinkat(void *opaque)
err = -EINVAL; err = -EINVAL;
goto out_nofid; goto out_nofid;
} }
v9fs_string_init(&full_name);
v9fs_string_sprintf(&full_name, "%s/%s", dfidp->path.data, name.data);
/* /*
* IF the file is unlinked, we cannot reopen * IF the file is unlinked, we cannot reopen
* the file later. So don't reclaim fd * the file later. So don't reclaim fd
*/ */
err = v9fs_mark_fids_unreclaim(pdu->s, &full_name); v9fs_path_init(&path);
err = v9fs_co_name_to_path(pdu->s, &dfidp->path, name.data, &path);
if (err < 0) { if (err < 0) {
goto out_err; goto out_err;
} }
err = v9fs_co_remove(pdu->s, &full_name); err = v9fs_mark_fids_unreclaim(pdu->s, &path);
if (err < 0) {
goto out_err;
}
err = v9fs_co_unlinkat(pdu->s, &dfidp->path, &name, flags);
if (!err) { if (!err) {
err = offset; err = offset;
} }
out_err: out_err:
put_fid(pdu->s, dfidp); put_fid(pdu->s, dfidp);
v9fs_string_free(&full_name); v9fs_path_free(&path);
out_nofid: out_nofid:
complete_pdu(pdu->s, pdu, err); complete_pdu(pdu->s, pdu, err);
v9fs_string_free(&name); v9fs_string_free(&name);
} }
/* Only works with path name based fid */
static int v9fs_complete_rename(V9fsState *s, V9fsFidState *fidp, static int v9fs_complete_rename(V9fsState *s, V9fsFidState *fidp,
int32_t newdirfid, V9fsString *name) int32_t newdirfid, V9fsString *name)
{ {
char *end; char *end;
int err = 0; int err = 0;
V9fsPath new_path;
V9fsFidState *tfidp;
V9fsFidState *dirfidp = NULL; V9fsFidState *dirfidp = NULL;
char *old_name, *new_name; char *old_name, *new_name;
v9fs_path_init(&new_path);
if (newdirfid != -1) { if (newdirfid != -1) {
dirfidp = get_fid(s, newdirfid); dirfidp = get_fid(s, newdirfid);
if (dirfidp == NULL) { if (dirfidp == NULL) {
@ -2377,12 +2429,7 @@ static int v9fs_complete_rename(V9fsState *s, V9fsFidState *fidp,
goto out_nofid; goto out_nofid;
} }
BUG_ON(dirfidp->fid_type != P9_FID_NONE); BUG_ON(dirfidp->fid_type != P9_FID_NONE);
v9fs_co_name_to_path(s, &dirfidp->path, name->data, &new_path);
new_name = g_malloc0(dirfidp->path.size + name->size + 2);
strcpy(new_name, dirfidp->path.data);
strcat(new_name, "/");
strcat(new_name + dirfidp->path.size, name->data);
} else { } else {
old_name = fidp->path.data; old_name = fidp->path.data;
end = strrchr(old_name, '/'); end = strrchr(old_name, '/');
@ -2392,44 +2439,30 @@ static int v9fs_complete_rename(V9fsState *s, V9fsFidState *fidp,
end = old_name; end = old_name;
} }
new_name = g_malloc0(end - old_name + name->size + 1); new_name = g_malloc0(end - old_name + name->size + 1);
strncat(new_name, old_name, end - old_name); strncat(new_name, old_name, end - old_name);
strncat(new_name + (end - old_name), name->data, name->size); strncat(new_name + (end - old_name), name->data, name->size);
v9fs_co_name_to_path(s, NULL, new_name, &new_path);
g_free(new_name);
} }
err = v9fs_co_rename(s, &fidp->path, &new_path);
v9fs_string_free(name); if (err < 0) {
name->data = new_name; goto out;
name->size = strlen(new_name); }
/*
if (strcmp(new_name, fidp->path.data) != 0) { * Fixup fid's pointing to the old name to
err = v9fs_co_rename(s, &fidp->path, name); * start pointing to the new name
if (err < 0) { */
goto out; for (tfidp = s->fid_list; tfidp; tfidp = tfidp->next) {
if (v9fs_path_is_ancestor(&fidp->path, &tfidp->path)) {
/* replace the name */
v9fs_fix_path(&tfidp->path, &new_path, strlen(fidp->path.data));
} }
V9fsFidState *tfidp;
/*
* Fixup fid's pointing to the old name to
* start pointing to the new name
*/
for (tfidp = s->fid_list; tfidp; tfidp = tfidp->next) {
if (fidp == tfidp) {
/*
* we replace name of this fid towards the end
* so that our below strcmp will work
*/
continue;
}
if (v9fs_path_is_ancestor(&fidp->path, &tfidp->path)) {
/* replace the name */
v9fs_fix_path(&tfidp->path, name, strlen(fidp->path.data));
}
}
v9fs_string_copy(&fidp->path, name);
} }
out: out:
if (dirfidp) { if (dirfidp) {
put_fid(s, dirfidp); put_fid(s, dirfidp);
} }
v9fs_path_free(&new_path);
out_nofid: out_nofid:
return err; return err;
} }
@ -2466,12 +2499,38 @@ out_nofid:
v9fs_string_free(&name); v9fs_string_free(&name);
} }
static void v9fs_fix_fid_paths(V9fsState *s, V9fsPath *olddir,
V9fsString *old_name, V9fsPath *newdir,
V9fsString *new_name)
{
V9fsFidState *tfidp;
V9fsPath oldpath, newpath;
v9fs_path_init(&oldpath);
v9fs_path_init(&newpath);
v9fs_co_name_to_path(s, olddir, old_name->data, &oldpath);
v9fs_co_name_to_path(s, newdir, new_name->data, &newpath);
/*
* Fixup fid's pointing to the old name to
* start pointing to the new name
*/
for (tfidp = s->fid_list; tfidp; tfidp = tfidp->next) {
if (v9fs_path_is_ancestor(&oldpath, &tfidp->path)) {
/* replace the name */
v9fs_fix_path(&tfidp->path, &newpath, strlen(oldpath.data));
}
}
v9fs_path_free(&oldpath);
v9fs_path_free(&newpath);
}
static int v9fs_complete_renameat(V9fsState *s, int32_t olddirfid, static int v9fs_complete_renameat(V9fsState *s, int32_t olddirfid,
V9fsString *old_name, int32_t newdirfid, V9fsString *old_name, int32_t newdirfid,
V9fsString *new_name) V9fsString *new_name)
{ {
int err = 0; int err = 0;
V9fsString old_full_name, new_full_name;
V9fsFidState *newdirfidp = NULL, *olddirfidp = NULL; V9fsFidState *newdirfidp = NULL, *olddirfidp = NULL;
olddirfidp = get_fid(s, olddirfid); olddirfidp = get_fid(s, olddirfid);
@ -2479,41 +2538,24 @@ static int v9fs_complete_renameat(V9fsState *s, int32_t olddirfid,
err = -ENOENT; err = -ENOENT;
goto out; goto out;
} }
v9fs_string_init(&old_full_name);
v9fs_string_init(&new_full_name);
v9fs_string_sprintf(&old_full_name, "%s/%s",
olddirfidp->path.data, old_name->data);
if (newdirfid != -1) { if (newdirfid != -1) {
newdirfidp = get_fid(s, newdirfid); newdirfidp = get_fid(s, newdirfid);
if (newdirfidp == NULL) { if (newdirfidp == NULL) {
err = -ENOENT; err = -ENOENT;
goto out; goto out;
} }
v9fs_string_sprintf(&new_full_name, "%s/%s",
newdirfidp->path.data, new_name->data);
} else { } else {
v9fs_string_sprintf(&new_full_name, "%s/%s", newdirfidp = get_fid(s, olddirfid);
olddirfidp->path.data, new_name->data);
} }
if (strcmp(old_full_name.data, new_full_name.data) != 0) { err = v9fs_co_renameat(s, &olddirfidp->path, old_name,
V9fsFidState *tfidp; &newdirfidp->path, new_name);
err = v9fs_co_rename(s, &old_full_name, &new_full_name); if (err < 0) {
if (err < 0) { goto out;
goto out;
}
/*
* Fixup fid's pointing to the old name to
* start pointing to the new name
*/
for (tfidp = s->fid_list; tfidp; tfidp = tfidp->next) {
if (v9fs_path_is_ancestor(&old_full_name, &tfidp->path)) {
/* replace the name */
v9fs_fix_path(&tfidp->path, &new_full_name, old_full_name.size);
}
}
} }
/* Only for path based fid we need to do the below fixup */
v9fs_fix_fid_paths(s, &olddirfidp->path, old_name,
&newdirfidp->path, new_name);
out: out:
if (olddirfidp) { if (olddirfidp) {
put_fid(s, olddirfidp); put_fid(s, olddirfidp);
@ -2521,8 +2563,6 @@ out:
if (newdirfidp) { if (newdirfidp) {
put_fid(s, newdirfidp); put_fid(s, newdirfidp);
} }
v9fs_string_free(&old_full_name);
v9fs_string_free(&new_full_name);
return err; return err;
} }
@ -2899,7 +2939,7 @@ static void v9fs_xattrwalk(void *opaque)
err = -EINVAL; err = -EINVAL;
goto out; goto out;
} }
v9fs_string_copy(&xattr_fidp->path, &file_fidp->path); v9fs_path_copy(&xattr_fidp->path, &file_fidp->path);
if (name.data[0] == 0) { if (name.data[0] == 0) {
/* /*
* listxattr request. Get the size first * listxattr request. Get the size first

View File

@ -206,7 +206,7 @@ struct V9fsFidState
{ {
int fid_type; int fid_type;
int32_t fid; int32_t fid;
V9fsString path; V9fsPath path;
union { union {
int fd; int fd;
DIR *dir; DIR *dir;
@ -396,4 +396,9 @@ extern void v9fs_string_free(V9fsString *str);
extern void v9fs_string_null(V9fsString *str); extern void v9fs_string_null(V9fsString *str);
extern void v9fs_string_sprintf(V9fsString *str, const char *fmt, ...); extern void v9fs_string_sprintf(V9fsString *str, const char *fmt, ...);
extern void v9fs_string_copy(V9fsString *lhs, V9fsString *rhs); extern void v9fs_string_copy(V9fsString *lhs, V9fsString *rhs);
extern void v9fs_path_init(V9fsPath *path);
extern void v9fs_path_free(V9fsPath *path);
extern void v9fs_path_copy(V9fsPath *lhs, V9fsPath *rhs);
extern int v9fs_name_to_path(V9fsState *s, V9fsPath *dirpath,
const char *name, V9fsPath *path);
#endif #endif