hw/9pfs: use g_strdup_printf() instead of PATH_MAX limitation
When path is truncated by PATH_MAX limitation, it causes QEMU to access
incorrect file. So use original full path instead of PATH_MAX within
9pfs (need check/process ENOMEM for related memory allocation).
The related test:
- Environments (for qemu-devel):
- Host is under fedora17 desktop with ext4fs:
qemu-system-x86_64 -hda test.img -m 1024 \
-net nic,vlan=4,model=virtio,macaddr=00:16:35:AF:94:04 \
-net tap,vlan=4,ifname=tap4,script=no,downscript=no \
-device virtio-9p-pci,id=fs0,fsdev=fsdev0,mount_tag=hostshare \
-fsdev local,security_model=passthrough,id=fsdev0,\
path=/upstream/vm/data/share/1234567890abcdefghijklmnopqrstuvwxyz\
ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890acdefghijklmnopqrstuvwxyz\
ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890/111111111111111111111111111\
1111111111111111111111111111111111111111111111111111222222222222\
2222222222222222222222222222222222222222222222222222222222222222\
2222222222222222222222222222222222233333333333333333333333333333\
3333333333333333333333333333333333
- Guest is ubuntu12 server with 9pfs.
mount -t 9p -o trans=virtio,version=9p2000.L hostshare /share
- Limitations:
full path limitation is PATH_MAX (4096B include nul) under Linux.
file/dir node name maximized length is 256 (include nul) under ext4.
- Special test:
Under host, modify the file: "/upstream/vm/data/share/1234567890abcdefg\
hijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890acdefghijklmno\
pqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890/111111111111111111111\
111111111111111111111111111111111111111111111111111111111122222222222\
222222222222222222222222222222222222222222222222222222222222222222222\
222222222222222222222222222222233333333333333333333333333333333333333\
3333333333333333333333333/4444444444444444444444444444444444444444444\
444444444444444444444444444444444444444444444444444444444444444444444\
444444444444444444444444444444444444444444444444444444444444444444444\
444444444444444444444444444444444444444/55555555555555555555555555555\
555555555555555555555555555555555555555555555555555555555555555555555\
555555555555555555555555555555555555555555555555555555555555555555555\
555555555555555555555555555555555555555555555555555555555555555555555\
55555555/666666666666666666666666666666666666666666666666666666666666\
666666666666666666666666666666666666666666666666666666666666666666666\
666666666666666666666666666666666666666666666666666666666666666666666\
666666666666666666666/77777777777777777777777777777777777777777777777\
777777777777777777777777777777777777777777777777777777777777777777777\
777777777777777777777777777777777777777777777777777777777777777777777\
77777777777777777777777777777777777777777777777777777777777/888888888\
888888888888888888888888888888888888888888888888888888888888888888888\
888888888888888888888888888888888888888888888888888888888888888888888\
888888888888888888888888888888888888888888888888888888888888888888888\
888888888/99999999999999999999999999999999999999999999999999999999999\
999999999999999999999999999999999999999999999999999999999999999999999\
999999999999999999999999999999999999999999999999999999999999999999999\
99999999999999999999999999999999999999999/000000000000000000000000000\
000000000000000000000000000000000000000000000000000000000000000000000\
000000000000000000000000000000000000000000000000000000000000000000000\
000000000000000000000000000000000000000000000000/aaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbb\
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ccccccccc\
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc\
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc\
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc\
cccccccccc/dddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\
ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\
ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\
dddddddddddddddddddddd/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\
eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\
eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\
eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee/fffffffffffffff\
fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\
fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff/gggggggggg\
ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg\
ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg\
ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg\
ggggggggggggggggggggggg/iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii\
iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii\
iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii\
iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii/jjjjjjjjjjjjj\
jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj\
jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj/ppppppppppppppppppppp\
ppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp\
ppppppppppppppppppppppppppppppppppppppp/test1234567890file.log"
(need enter dir firstly, then modify file, or can not open it).
Under guest, still allow modify "test1234567890file.log" (will generate
"test123456" file with contents).
After apply this patch, can not open "test1234567890file.log" under guest
(permission denied).
- Common test:
All are still OK after apply this path.
"mkdir -p", "create/open file/dir", "modify file/dir", "rm file/dir".
change various mount point paths under host and/or guest.
Signed-off-by: Chen Gang <gang.chen.5i5j@gmail.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c
index dc615a4..56b302c 100644
--- a/hw/9pfs/virtio-9p-local.c
+++ b/hw/9pfs/virtio-9p-local.c
@@ -42,18 +42,18 @@
#define VIRTFS_META_DIR ".virtfs_metadata"
-static const char *local_mapped_attr_path(FsContext *ctx,
- const char *path, char *buffer)
+static char *local_mapped_attr_path(FsContext *ctx, const char *path)
{
char *dir_name;
char *tmp_path = g_strdup(path);
char *base_name = basename(tmp_path);
+ char *buffer;
/* NULL terminate the directory */
dir_name = tmp_path;
*(base_name - 1) = '\0';
- snprintf(buffer, PATH_MAX, "%s/%s/%s/%s",
+ buffer = g_strdup_printf("%s/%s/%s/%s",
ctx->fs_root, dir_name, VIRTFS_META_DIR, base_name);
g_free(tmp_path);
return buffer;
@@ -92,10 +92,11 @@
{
FILE *fp;
char buf[ATTR_MAX];
- char attr_path[PATH_MAX];
+ char *attr_path;
- local_mapped_attr_path(ctx, path, attr_path);
+ attr_path = local_mapped_attr_path(ctx, path);
fp = local_fopen(attr_path, "r");
+ g_free(attr_path);
if (!fp) {
return;
}
@@ -118,12 +119,13 @@
static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
{
int err;
- char buffer[PATH_MAX];
+ char *buffer;
char *path = fs_path->data;
- err = lstat(rpath(fs_ctx, path, buffer), stbuf);
+ buffer = rpath(fs_ctx, path);
+ err = lstat(buffer, stbuf);
if (err) {
- return err;
+ goto err_out;
}
if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
/* Actual credentials are part of extended attrs */
@@ -131,41 +133,42 @@
gid_t tmp_gid;
mode_t tmp_mode;
dev_t tmp_dev;
- if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.uid", &tmp_uid,
- sizeof(uid_t)) > 0) {
+ if (getxattr(buffer, "user.virtfs.uid", &tmp_uid, sizeof(uid_t)) > 0) {
stbuf->st_uid = tmp_uid;
}
- if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.gid", &tmp_gid,
- sizeof(gid_t)) > 0) {
+ if (getxattr(buffer, "user.virtfs.gid", &tmp_gid, sizeof(gid_t)) > 0) {
stbuf->st_gid = tmp_gid;
}
- if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.mode",
+ if (getxattr(buffer, "user.virtfs.mode",
&tmp_mode, sizeof(mode_t)) > 0) {
stbuf->st_mode = tmp_mode;
}
- if (getxattr(rpath(fs_ctx, path, buffer), "user.virtfs.rdev", &tmp_dev,
- sizeof(dev_t)) > 0) {
+ if (getxattr(buffer, "user.virtfs.rdev", &tmp_dev, sizeof(dev_t)) > 0) {
stbuf->st_rdev = tmp_dev;
}
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
local_mapped_file_attr(fs_ctx, path, stbuf);
}
+
+err_out:
+ g_free(buffer);
return err;
}
static int local_create_mapped_attr_dir(FsContext *ctx, const char *path)
{
int err;
- char attr_dir[PATH_MAX];
+ char *attr_dir;
char *tmp_path = g_strdup(path);
- snprintf(attr_dir, PATH_MAX, "%s/%s/%s",
+ attr_dir = g_strdup_printf("%s/%s/%s",
ctx->fs_root, dirname(tmp_path), VIRTFS_META_DIR);
err = mkdir(attr_dir, 0700);
if (err < 0 && errno == EEXIST) {
err = 0;
}
+ g_free(attr_dir);
g_free(tmp_path);
return err;
}
@@ -176,10 +179,11 @@
FILE *fp;
int ret = 0;
char buf[ATTR_MAX];
- char attr_path[PATH_MAX];
+ char *attr_path;
int uid = -1, gid = -1, mode = -1, rdev = -1;
- fp = local_fopen(local_mapped_attr_path(ctx, path, attr_path), "r");
+ attr_path = local_mapped_attr_path(ctx, path);
+ fp = local_fopen(attr_path, "r");
if (!fp) {
goto create_map_file;
}
@@ -241,6 +245,7 @@
fclose(fp);
err_out:
+ g_free(attr_path);
return ret;
}
@@ -282,36 +287,43 @@
static int local_post_create_passthrough(FsContext *fs_ctx, const char *path,
FsCred *credp)
{
- char buffer[PATH_MAX];
+ char *buffer;
- if (lchown(rpath(fs_ctx, path, buffer), credp->fc_uid,
- credp->fc_gid) < 0) {
+ buffer = rpath(fs_ctx, path);
+ if (lchown(buffer, credp->fc_uid, credp->fc_gid) < 0) {
/*
* If we fail to change ownership and if we are
* using security model none. Ignore the error
*/
if ((fs_ctx->export_flags & V9FS_SEC_MASK) != V9FS_SM_NONE) {
- return -1;
+ goto err;
}
}
- if (chmod(rpath(fs_ctx, path, buffer), credp->fc_mode & 07777) < 0) {
- return -1;
+ if (chmod(buffer, credp->fc_mode & 07777) < 0) {
+ goto err;
}
+
+ g_free(buffer);
return 0;
+err:
+ g_free(buffer);
+ return -1;
}
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 *buffer;
char *path = fs_path->data;
if ((fs_ctx->export_flags & V9FS_SM_MAPPED) ||
(fs_ctx->export_flags & V9FS_SM_MAPPED_FILE)) {
int fd;
- fd = open(rpath(fs_ctx, path, buffer), O_RDONLY | O_NOFOLLOW);
+ buffer = rpath(fs_ctx, path);
+ fd = open(buffer, O_RDONLY | O_NOFOLLOW);
+ g_free(buffer);
if (fd == -1) {
return -1;
}
@@ -322,7 +334,9 @@
return tsize;
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
(fs_ctx->export_flags & V9FS_SM_NONE)) {
- tsize = readlink(rpath(fs_ctx, path, buffer), buf, bufsz);
+ buffer = rpath(fs_ctx, path);
+ tsize = readlink(buffer, buf, bufsz);
+ g_free(buffer);
}
return tsize;
}
@@ -340,20 +354,24 @@
static int local_open(FsContext *ctx, V9fsPath *fs_path,
int flags, V9fsFidOpenState *fs)
{
- char buffer[PATH_MAX];
+ char *buffer;
char *path = fs_path->data;
- fs->fd = open(rpath(ctx, path, buffer), flags | O_NOFOLLOW);
+ buffer = rpath(ctx, path);
+ fs->fd = open(buffer, flags | O_NOFOLLOW);
+ g_free(buffer);
return fs->fd;
}
static int local_opendir(FsContext *ctx,
V9fsPath *fs_path, V9fsFidOpenState *fs)
{
- char buffer[PATH_MAX];
+ char *buffer;
char *path = fs_path->data;
- fs->dir = opendir(rpath(ctx, path, buffer));
+ buffer = rpath(ctx, path);
+ fs->dir = opendir(buffer);
+ g_free(buffer);
if (!fs->dir) {
return -1;
}
@@ -441,18 +459,23 @@
static int local_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
{
- char buffer[PATH_MAX];
+ char *buffer;
+ int ret = -1;
char *path = fs_path->data;
if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
- return local_set_xattr(rpath(fs_ctx, path, buffer), credp);
+ buffer = rpath(fs_ctx, path);
+ ret = local_set_xattr(buffer, credp);
+ g_free(buffer);
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
return local_set_mapped_file_attr(fs_ctx, path, credp);
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
(fs_ctx->export_flags & V9FS_SM_NONE)) {
- return chmod(rpath(fs_ctx, path, buffer), credp->fc_mode);
+ buffer = rpath(fs_ctx, path);
+ ret = chmod(buffer, credp->fc_mode);
+ g_free(buffer);
}
- return -1;
+ return ret;
}
static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
@@ -462,7 +485,7 @@
int err = -1;
int serrno = 0;
V9fsString fullname;
- char buffer[PATH_MAX];
+ char *buffer;
v9fs_string_init(&fullname);
v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
@@ -470,21 +493,23 @@
/* Determine the security model */
if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
- err = mknod(rpath(fs_ctx, path, buffer),
- SM_LOCAL_MODE_BITS|S_IFREG, 0);
+ buffer = rpath(fs_ctx, path);
+ err = mknod(buffer, SM_LOCAL_MODE_BITS|S_IFREG, 0);
if (err == -1) {
+ g_free(buffer);
goto out;
}
- err = local_set_xattr(rpath(fs_ctx, path, buffer), credp);
+ err = local_set_xattr(buffer, credp);
if (err == -1) {
serrno = errno;
goto err_end;
}
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
- err = mknod(rpath(fs_ctx, path, buffer),
- SM_LOCAL_MODE_BITS|S_IFREG, 0);
+ buffer = rpath(fs_ctx, path);
+ err = mknod(buffer, SM_LOCAL_MODE_BITS|S_IFREG, 0);
if (err == -1) {
+ g_free(buffer);
goto out;
}
err = local_set_mapped_file_attr(fs_ctx, path, credp);
@@ -494,9 +519,10 @@
}
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
(fs_ctx->export_flags & V9FS_SM_NONE)) {
- err = mknod(rpath(fs_ctx, path, buffer), credp->fc_mode,
- credp->fc_rdev);
+ buffer = rpath(fs_ctx, path);
+ err = mknod(buffer, credp->fc_mode, credp->fc_rdev);
if (err == -1) {
+ g_free(buffer);
goto out;
}
err = local_post_create_passthrough(fs_ctx, path, credp);
@@ -508,8 +534,9 @@
goto out;
err_end:
- remove(rpath(fs_ctx, path, buffer));
+ remove(buffer);
errno = serrno;
+ g_free(buffer);
out:
v9fs_string_free(&fullname);
return err;
@@ -522,7 +549,7 @@
int err = -1;
int serrno = 0;
V9fsString fullname;
- char buffer[PATH_MAX];
+ char *buffer;
v9fs_string_init(&fullname);
v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
@@ -530,19 +557,23 @@
/* Determine the security model */
if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
- err = mkdir(rpath(fs_ctx, path, buffer), SM_LOCAL_DIR_MODE_BITS);
+ buffer = rpath(fs_ctx, path);
+ err = mkdir(buffer, SM_LOCAL_DIR_MODE_BITS);
if (err == -1) {
+ g_free(buffer);
goto out;
}
credp->fc_mode = credp->fc_mode|S_IFDIR;
- err = local_set_xattr(rpath(fs_ctx, path, buffer), credp);
+ err = local_set_xattr(buffer, credp);
if (err == -1) {
serrno = errno;
goto err_end;
}
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
- err = mkdir(rpath(fs_ctx, path, buffer), SM_LOCAL_DIR_MODE_BITS);
+ buffer = rpath(fs_ctx, path);
+ err = mkdir(buffer, SM_LOCAL_DIR_MODE_BITS);
if (err == -1) {
+ g_free(buffer);
goto out;
}
credp->fc_mode = credp->fc_mode|S_IFDIR;
@@ -553,8 +584,10 @@
}
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
(fs_ctx->export_flags & V9FS_SM_NONE)) {
- err = mkdir(rpath(fs_ctx, path, buffer), credp->fc_mode);
+ buffer = rpath(fs_ctx, path);
+ err = mkdir(buffer, credp->fc_mode);
if (err == -1) {
+ g_free(buffer);
goto out;
}
err = local_post_create_passthrough(fs_ctx, path, credp);
@@ -566,8 +599,9 @@
goto out;
err_end:
- remove(rpath(fs_ctx, path, buffer));
+ remove(buffer);
errno = serrno;
+ g_free(buffer);
out:
v9fs_string_free(&fullname);
return err;
@@ -626,7 +660,7 @@
int err = -1;
int serrno = 0;
V9fsString fullname;
- char buffer[PATH_MAX];
+ char *buffer;
/*
* Mark all the open to not follow symlinks
@@ -639,21 +673,25 @@
/* Determine the security model */
if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
- fd = open(rpath(fs_ctx, path, buffer), flags, SM_LOCAL_MODE_BITS);
+ buffer = rpath(fs_ctx, path);
+ fd = open(buffer, flags, SM_LOCAL_MODE_BITS);
if (fd == -1) {
+ g_free(buffer);
err = fd;
goto out;
}
credp->fc_mode = credp->fc_mode|S_IFREG;
/* Set cleint credentials in xattr */
- err = local_set_xattr(rpath(fs_ctx, path, buffer), credp);
+ err = local_set_xattr(buffer, credp);
if (err == -1) {
serrno = errno;
goto err_end;
}
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
- fd = open(rpath(fs_ctx, path, buffer), flags, SM_LOCAL_MODE_BITS);
+ buffer = rpath(fs_ctx, path);
+ fd = open(buffer, flags, SM_LOCAL_MODE_BITS);
if (fd == -1) {
+ g_free(buffer);
err = fd;
goto out;
}
@@ -666,8 +704,10 @@
}
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
(fs_ctx->export_flags & V9FS_SM_NONE)) {
- fd = open(rpath(fs_ctx, path, buffer), flags, credp->fc_mode);
+ buffer = rpath(fs_ctx, path);
+ fd = open(buffer, flags, credp->fc_mode);
if (fd == -1) {
+ g_free(buffer);
err = fd;
goto out;
}
@@ -683,8 +723,9 @@
err_end:
close(fd);
- remove(rpath(fs_ctx, path, buffer));
+ remove(buffer);
errno = serrno;
+ g_free(buffer);
out:
v9fs_string_free(&fullname);
return err;
@@ -698,7 +739,7 @@
int serrno = 0;
char *newpath;
V9fsString fullname;
- char buffer[PATH_MAX];
+ char *buffer;
v9fs_string_init(&fullname);
v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
@@ -708,10 +749,10 @@
if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
int fd;
ssize_t oldpath_size, write_size;
- fd = open(rpath(fs_ctx, newpath, buffer),
- O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW,
- SM_LOCAL_MODE_BITS);
+ buffer = rpath(fs_ctx, newpath);
+ fd = open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, SM_LOCAL_MODE_BITS);
if (fd == -1) {
+ g_free(buffer);
err = fd;
goto out;
}
@@ -730,7 +771,7 @@
close(fd);
/* Set cleint credentials in symlink's xattr */
credp->fc_mode = credp->fc_mode|S_IFLNK;
- err = local_set_xattr(rpath(fs_ctx, newpath, buffer), credp);
+ err = local_set_xattr(buffer, credp);
if (err == -1) {
serrno = errno;
goto err_end;
@@ -738,10 +779,10 @@
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
int fd;
ssize_t oldpath_size, write_size;
- fd = open(rpath(fs_ctx, newpath, buffer),
- O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW,
- SM_LOCAL_MODE_BITS);
+ buffer = rpath(fs_ctx, newpath);
+ fd = open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, SM_LOCAL_MODE_BITS);
if (fd == -1) {
+ g_free(buffer);
err = fd;
goto out;
}
@@ -767,12 +808,13 @@
}
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
(fs_ctx->export_flags & V9FS_SM_NONE)) {
- err = symlink(oldpath, rpath(fs_ctx, newpath, buffer));
+ buffer = rpath(fs_ctx, newpath);
+ err = symlink(oldpath, buffer);
if (err) {
+ g_free(buffer);
goto out;
}
- err = lchown(rpath(fs_ctx, newpath, buffer), credp->fc_uid,
- credp->fc_gid);
+ err = lchown(buffer, credp->fc_uid, credp->fc_gid);
if (err == -1) {
/*
* If we fail to change ownership and if we are
@@ -788,8 +830,9 @@
goto out;
err_end:
- remove(rpath(fs_ctx, newpath, buffer));
+ remove(buffer);
errno = serrno;
+ g_free(buffer);
out:
v9fs_string_free(&fullname);
return err;
@@ -800,13 +843,16 @@
{
int ret;
V9fsString newpath;
- char buffer[PATH_MAX], buffer1[PATH_MAX];
+ char *buffer, *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));
+ buffer = rpath(ctx, oldpath->data);
+ buffer1 = rpath(ctx, newpath.data);
+ ret = link(buffer, buffer1);
+ g_free(buffer);
+ g_free(buffer1);
/* now link the virtfs_metadata files */
if (!ret && (ctx->export_flags & V9FS_SM_MAPPED_FILE)) {
@@ -815,8 +861,11 @@
if (ret < 0) {
goto err_out;
}
- ret = link(local_mapped_attr_path(ctx, oldpath->data, buffer),
- local_mapped_attr_path(ctx, newpath.data, buffer1));
+ buffer = local_mapped_attr_path(ctx, oldpath->data);
+ buffer1 = local_mapped_attr_path(ctx, newpath.data);
+ ret = link(buffer, buffer1);
+ g_free(buffer);
+ g_free(buffer1);
if (ret < 0 && errno != ENOENT) {
goto err_out;
}
@@ -828,17 +877,21 @@
static int local_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
{
- char buffer[PATH_MAX];
+ char *buffer;
+ int ret;
char *path = fs_path->data;
- return truncate(rpath(ctx, path, buffer), size);
+ buffer = rpath(ctx, path);
+ ret = truncate(buffer, size);
+ g_free(buffer);
+ return ret;
}
static int local_rename(FsContext *ctx, const char *oldpath,
const char *newpath)
{
int err;
- char buffer[PATH_MAX], buffer1[PATH_MAX];
+ char *buffer, *buffer1;
if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
err = local_create_mapped_attr_dir(ctx, newpath);
@@ -846,50 +899,69 @@
return err;
}
/* rename the .virtfs_metadata files */
- err = rename(local_mapped_attr_path(ctx, oldpath, buffer),
- local_mapped_attr_path(ctx, newpath, buffer1));
+ buffer = local_mapped_attr_path(ctx, oldpath);
+ buffer1 = local_mapped_attr_path(ctx, newpath);
+ err = rename(buffer, buffer1);
+ g_free(buffer);
+ g_free(buffer1);
if (err < 0 && errno != ENOENT) {
return err;
}
}
- return rename(rpath(ctx, oldpath, buffer), rpath(ctx, newpath, buffer1));
+
+ buffer = rpath(ctx, oldpath);
+ buffer1 = rpath(ctx, newpath);
+ err = rename(buffer, buffer1);
+ g_free(buffer);
+ g_free(buffer1);
+ return err;
}
static int local_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
{
- char buffer[PATH_MAX];
+ char *buffer;
+ int ret = -1;
char *path = fs_path->data;
if ((credp->fc_uid == -1 && credp->fc_gid == -1) ||
(fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
(fs_ctx->export_flags & V9FS_SM_NONE)) {
- return lchown(rpath(fs_ctx, path, buffer),
- credp->fc_uid, credp->fc_gid);
+ buffer = rpath(fs_ctx, path);
+ ret = lchown(buffer, credp->fc_uid, credp->fc_gid);
+ g_free(buffer);
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
- return local_set_xattr(rpath(fs_ctx, path, buffer), credp);
+ buffer = rpath(fs_ctx, path);
+ ret = local_set_xattr(buffer, credp);
+ g_free(buffer);
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
return local_set_mapped_file_attr(fs_ctx, path, credp);
}
- return -1;
+ return ret;
}
static int local_utimensat(FsContext *s, V9fsPath *fs_path,
const struct timespec *buf)
{
- char buffer[PATH_MAX];
+ char *buffer;
+ int ret;
char *path = fs_path->data;
- return qemu_utimens(rpath(s, path, buffer), buf);
+ buffer = rpath(s, path);
+ ret = qemu_utimens(buffer, buf);
+ g_free(buffer);
+ return ret;
}
static int local_remove(FsContext *ctx, const char *path)
{
int err;
struct stat stbuf;
- char buffer[PATH_MAX];
+ char *buffer;
if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
- err = lstat(rpath(ctx, path, buffer), &stbuf);
+ buffer = rpath(ctx, path);
+ err = lstat(buffer, &stbuf);
+ g_free(buffer);
if (err) {
goto err_out;
}
@@ -898,9 +970,10 @@
* directory
*/
if (S_ISDIR(stbuf.st_mode)) {
- snprintf(buffer, ARRAY_SIZE(buffer), "%s/%s/%s",
- ctx->fs_root, path, VIRTFS_META_DIR);
+ buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root,
+ path, VIRTFS_META_DIR);
err = remove(buffer);
+ g_free(buffer);
if (err < 0 && errno != ENOENT) {
/*
* We didn't had the .virtfs_metadata file. May be file created
@@ -913,7 +986,9 @@
* Now remove the name from parent directory
* .virtfs_metadata directory
*/
- err = remove(local_mapped_attr_path(ctx, path, buffer));
+ buffer = local_mapped_attr_path(ctx, path);
+ err = remove(buffer);
+ g_free(buffer);
if (err < 0 && errno != ENOENT) {
/*
* We didn't had the .virtfs_metadata file. May be file created
@@ -922,7 +997,10 @@
goto err_out;
}
}
- return remove(rpath(ctx, path, buffer));
+
+ buffer = rpath(ctx, path);
+ err = remove(buffer);
+ g_free(buffer);
err_out:
return err;
}
@@ -947,10 +1025,14 @@
static int local_statfs(FsContext *s, V9fsPath *fs_path, struct statfs *stbuf)
{
- char buffer[PATH_MAX];
+ char *buffer;
+ int ret;
char *path = fs_path->data;
- return statfs(rpath(s, path, buffer), stbuf);
+ buffer = rpath(s, path);
+ ret = statfs(buffer, stbuf);
+ g_free(buffer);
+ return ret;
}
static ssize_t local_lgetxattr(FsContext *ctx, V9fsPath *fs_path,
@@ -1023,7 +1105,7 @@
{
int ret;
V9fsString fullname;
- char buffer[PATH_MAX];
+ char *buffer;
v9fs_string_init(&fullname);
@@ -1034,9 +1116,10 @@
* If directory remove .virtfs_metadata contained in the
* directory
*/
- snprintf(buffer, ARRAY_SIZE(buffer), "%s/%s/%s", ctx->fs_root,
- fullname.data, VIRTFS_META_DIR);
+ buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root,
+ fullname.data, VIRTFS_META_DIR);
ret = remove(buffer);
+ g_free(buffer);
if (ret < 0 && errno != ENOENT) {
/*
* We didn't had the .virtfs_metadata file. May be file created
@@ -1049,7 +1132,9 @@
* Now remove the name from parent directory
* .virtfs_metadata directory.
*/
- ret = remove(local_mapped_attr_path(ctx, fullname.data, buffer));
+ buffer = local_mapped_attr_path(ctx, fullname.data);
+ ret = remove(buffer);
+ g_free(buffer);
if (ret < 0 && errno != ENOENT) {
/*
* We didn't had the .virtfs_metadata file. May be file created
@@ -1059,7 +1144,9 @@
}
}
/* Remove the name finally */
- ret = remove(rpath(ctx, fullname.data, buffer));
+ buffer = rpath(ctx, fullname.data);
+ ret = remove(buffer);
+ g_free(buffer);
err_out:
v9fs_string_free(&fullname);