Message ID | 1460447520-12499-1-git-send-email-michael@fritscher.net (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Tue, 12 Apr 2016 09:52:00 +0200 Michael Fritscher <michael@fritscher.net> wrote: > It was tested on Windows & Linux hosts, on the later no obvious regressions could be found. The guest was a Knoppix 7.6.0 live cd. > > This is WIP and a RFC - it isn't meant to be upstreamed yet. The error_printf are only for debugging and will be deleted in the final patch. > > There are some comments with "mifritscher" - I'm not quite sure how to handle these problems (e.g. on mingw, this in 32 bit, while on Linux this is 16 bit and so on). Additionally, some places from which I suspect problems are marked with a #warning. > > Changes against v1: > * fixed open (added binary flag) -> read/write is fine now, file > creation was fixed as well > * added inode calculation using own crude hash algorithm > * fixed xattr returning -1 + EOPNOTSUP -> fixes e.g. executing files > * fixed unlinkat / remove für directories by trying rmdir as well > * prepend 777 mode on files (for executing) > > What does work: > * reading/writing "big" files (5MB, verified with md5sum) > * creating files > * executing files > * mkdir > * rm / rmdir > * cp files > * running gcc > * cp first 250 files & directories from /etc > * tar it from and to the 9p mount > * create a 100 MB swap file and do a mkswap on it > > What does not work: > * swapon - no real surprise (doesn't work on Linux as well - with the same error message) ;-) (swapon returns -1 EINVAL) > * link / symlink (there is no real aequivalent for this on windows) > * mknod (dito) > * chown (dito - prepend success for compatibility) > > State of v1: > What works: > * mount > * stat > * chdir > * readdir (aka ls) > * read of small files (<10k) > * overwrite > > What does not work: > * create new files (in 90% problems with path handling (old path occurs) > * read / probably write big files > > > Signed-off-by: Michael Fritscher <michael@fritscher.net> > --- > On https://github.com/mifritscher/qemu/tree/9pfs_windows is a git tree with the patch. > > I gave a shot at xattr (try to include xattr stuff) but it ended up even more #ifdefs. So I gave up at this. > Now I'm waiting on comments etc. If there are no big objections, I'll remove the debug output and make a patch which is meant for upstreaming. > > Thanks to everybody which helped me! > Hi Michael ! Impressive work ! :) Since this is a big patch, it will take probably some time for me to review. I'll comment on easy stuff first, and probably send more emails when I get time to go deeper. Anyway, this is a new feature and it won't go upstream until 2.6 is out. Cheers. -- Greg
Hi Michael, I have some more comments that should end up in a preliminary patch. Cheers. -- Greg On Tue, 12 Apr 2016 09:52:00 +0200 Michael Fritscher <michael@fritscher.net> wrote: > It was tested on Windows & Linux hosts, on the later no obvious regressions could be found. The guest was a Knoppix 7.6.0 live cd. > > This is WIP and a RFC - it isn't meant to be upstreamed yet. The error_printf are only for debugging and will be deleted in the final patch. > > There are some comments with "mifritscher" - I'm not quite sure how to handle these problems (e.g. on mingw, this in 32 bit, while on Linux this is 16 bit and so on). Additionally, some places from which I suspect problems are marked with a #warning. > > Changes against v1: > * fixed open (added binary flag) -> read/write is fine now, file > creation was fixed as well > * added inode calculation using own crude hash algorithm > * fixed xattr returning -1 + EOPNOTSUP -> fixes e.g. executing files > * fixed unlinkat / remove für directories by trying rmdir as well > * prepend 777 mode on files (for executing) > > What does work: > * reading/writing "big" files (5MB, verified with md5sum) > * creating files > * executing files > * mkdir > * rm / rmdir > * cp files > * running gcc > * cp first 250 files & directories from /etc > * tar it from and to the 9p mount > * create a 100 MB swap file and do a mkswap on it > > What does not work: > * swapon - no real surprise (doesn't work on Linux as well - with the same error message) ;-) (swapon returns -1 EINVAL) > * link / symlink (there is no real aequivalent for this on windows) > * mknod (dito) > * chown (dito - prepend success for compatibility) > > State of v1: > What works: > * mount > * stat > * chdir > * readdir (aka ls) > * read of small files (<10k) > * overwrite > > What does not work: > * create new files (in 90% problems with path handling (old path occurs) > * read / probably write big files > > > Signed-off-by: Michael Fritscher <michael@fritscher.net> > --- > On https://github.com/mifritscher/qemu/tree/9pfs_windows is a git tree with the patch. > > I gave a shot at xattr (try to include xattr stuff) but it ended up even more #ifdefs. So I gave up at this. > Now I'm waiting on comments etc. If there are no big objections, I'll remove the debug output and make a patch which is meant for upstreaming. > > Thanks to everybody which helped me! > > Makefile.objs | 1 + > configure | 15 ++- > fsdev/9p-iov-marshal.c | 2 + > fsdev/9p-marshal.c | 4 +- > fsdev/file-op-9p.h | 35 ++++- > fsdev/qemu-fsdev.c | 2 + > hw/9pfs/9p-local.c | 326 +++++++++++++++++++++++++++++++++++++++++---- > hw/9pfs/9p-synth.c | 10 +- > hw/9pfs/9p.c | 102 +++++++++++++- > hw/9pfs/9p.h | 70 +++++++++- > hw/9pfs/Makefile.objs | 7 +- > hw/9pfs/codir.c | 31 +++++ > hw/9pfs/cofile.c | 15 +++ > hw/9pfs/cofs.c | 15 +++ > hw/9pfs/coxattr.c | 6 + > hw/9pfs/virtio-9p-device.c | 4 +- > 16 files changed, 600 insertions(+), 45 deletions(-) > > diff --git a/Makefile.objs b/Makefile.objs > index 8f705f6..6fd02bc 100644 > --- a/Makefile.objs > +++ b/Makefile.objs > @@ -48,6 +48,7 @@ common-obj-$(CONFIG_WIN32) += os-win32.o > common-obj-$(CONFIG_POSIX) += os-posix.o > > common-obj-$(CONFIG_LINUX) += fsdev/ > +common-obj-$(CONFIG_WIN32) += fsdev/ > > common-obj-y += migration/ > common-obj-y += qemu-char.o #aio.o > diff --git a/configure b/configure > index 5db29f0..a4797c3 100755 > --- a/configure > +++ b/configure > @@ -4566,12 +4566,21 @@ if test "$want_tools" = "yes" ; then > fi > if test "$softmmu" = yes ; then > if test "$virtfs" != no ; then > - if test "$cap" = yes && test "$linux" = yes && test "$attr" = yes ; then > + if test "$linux" = yes ; then > + if test "$cap" = yes && test "$attr" = yes ; then > + virtfs=yes > + tools="$tools fsdev/virtfs-proxy-helper\$(EXESUF)" > + else > + if test "$virtfs" = yes; then > + error_exit "VirtFS requires libcap-devel and libattr-devel on Linux" > + fi > + virtfs=no > + fi > + elif test "$mingw32" = yes; then > virtfs=yes > - tools="$tools fsdev/virtfs-proxy-helper\$(EXESUF)" > else > if test "$virtfs" = yes; then > - error_exit "VirtFS is supported only on Linux and requires libcap-devel and libattr-devel" > + error_exit "VirtFS is only supported on Linux or Windows" > fi > virtfs=no > fi > diff --git a/fsdev/9p-iov-marshal.c b/fsdev/9p-iov-marshal.c > index fb40bdf..1a292c6 100644 > --- a/fsdev/9p-iov-marshal.c > +++ b/fsdev/9p-iov-marshal.c > @@ -15,7 +15,9 @@ > #include <glib.h> > #include <glib/gprintf.h> > #include <utime.h> > +#ifndef _WIN32 > #include <sys/uio.h> > +#endif > > #include "9p-iov-marshal.h" > #include "qemu/bswap.h" > diff --git a/fsdev/9p-marshal.c b/fsdev/9p-marshal.c > index 183d366..081cb88 100644 > --- a/fsdev/9p-marshal.c > +++ b/fsdev/9p-marshal.c > @@ -16,7 +16,9 @@ > #include <glib/gprintf.h> > #include <dirent.h> > #include <utime.h> > -#include <sys/uio.h> > +#ifndef WIN32 > + #include <sys/uio.h> > +#endif > > #include "9p-marshal.h" > > diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h > index b8c2602..446c6a5 100644 > --- a/fsdev/file-op-9p.h > +++ b/fsdev/file-op-9p.h > @@ -14,12 +14,43 @@ > #define _FILEOP_H > #include <dirent.h> > #include <utime.h> > -#include <sys/uio.h> > -#include <sys/vfs.h> > +#ifndef _WIN32 > + #include <sys/uio.h> > + #include <sys/vfs.h> This should be included by include/sysemu/os-posix.h, and you just need to add a forward declaration for struct statfs before struct FileOperations somewhere below. > +#endif > > #define SM_LOCAL_MODE_BITS 0600 > #define SM_LOCAL_DIR_MODE_BITS 0700 > > +#ifdef _WIN32 > +typedef uint32_t uid_t; > +typedef uint32_t gid_t; > + > +/* from http://man7.org/linux/man-pages/man2/statfs.2.html */ > +typedef uint32_t __fsword_t; > +typedef uint32_t fsblkcnt_t; > +typedef uint32_t fsfilcnt_t; > + > +/* from linux/include/uapi/asm-generic/posix_types.h */ > +typedef struct { > + long __val[2]; > +} fsid_t; > + > +struct statfs { > + __fsword_t f_type; > + __fsword_t f_bsize; > + fsblkcnt_t f_blocks; > + fsblkcnt_t f_bfree; > + fsblkcnt_t f_bavail; > + fsfilcnt_t f_files; > + fsfilcnt_t f_ffree; > + fsid_t f_fsid; > + __fsword_t f_namelen; > + __fsword_t f_frsize; > + __fsword_t f_flags; > +}; All this block belongs to include/sysemu/os-win32.h. > +#endif > +
More comments. On Tue, 12 Apr 2016 09:52:00 +0200 Michael Fritscher <michael@fritscher.net> wrote: > It was tested on Windows & Linux hosts, on the later no obvious regressions could be found. The guest was a Knoppix 7.6.0 live cd. > > This is WIP and a RFC - it isn't meant to be upstreamed yet. The error_printf are only for debugging and will be deleted in the final patch. > > There are some comments with "mifritscher" - I'm not quite sure how to handle these problems (e.g. on mingw, this in 32 bit, while on Linux this is 16 bit and so on). Additionally, some places from which I suspect problems are marked with a #warning. > > Changes against v1: > * fixed open (added binary flag) -> read/write is fine now, file > creation was fixed as well > * added inode calculation using own crude hash algorithm > * fixed xattr returning -1 + EOPNOTSUP -> fixes e.g. executing files > * fixed unlinkat / remove für directories by trying rmdir as well > * prepend 777 mode on files (for executing) > > What does work: > * reading/writing "big" files (5MB, verified with md5sum) > * creating files > * executing files > * mkdir > * rm / rmdir > * cp files > * running gcc > * cp first 250 files & directories from /etc > * tar it from and to the 9p mount > * create a 100 MB swap file and do a mkswap on it > > What does not work: > * swapon - no real surprise (doesn't work on Linux as well - with the same error message) ;-) (swapon returns -1 EINVAL) > * link / symlink (there is no real aequivalent for this on windows) > * mknod (dito) > * chown (dito - prepend success for compatibility) > > State of v1: > What works: > * mount > * stat > * chdir > * readdir (aka ls) > * read of small files (<10k) > * overwrite > > What does not work: > * create new files (in 90% problems with path handling (old path occurs) > * read / probably write big files > > > Signed-off-by: Michael Fritscher <michael@fritscher.net> > --- > On https://github.com/mifritscher/qemu/tree/9pfs_windows is a git tree with the patch. > > I gave a shot at xattr (try to include xattr stuff) but it ended up even more #ifdefs. So I gave up at this. > Now I'm waiting on comments etc. If there are no big objections, I'll remove the debug output and make a patch which is meant for upstreaming. > > Thanks to everybody which helped me! > > Makefile.objs | 1 + > configure | 15 ++- > fsdev/9p-iov-marshal.c | 2 + > fsdev/9p-marshal.c | 4 +- > fsdev/file-op-9p.h | 35 ++++- > fsdev/qemu-fsdev.c | 2 + > hw/9pfs/9p-local.c | 326 +++++++++++++++++++++++++++++++++++++++++---- > hw/9pfs/9p-synth.c | 10 +- > hw/9pfs/9p.c | 102 +++++++++++++- > hw/9pfs/9p.h | 70 +++++++++- > hw/9pfs/Makefile.objs | 7 +- > hw/9pfs/codir.c | 31 +++++ > hw/9pfs/cofile.c | 15 +++ > hw/9pfs/cofs.c | 15 +++ > hw/9pfs/coxattr.c | 6 + > hw/9pfs/virtio-9p-device.c | 4 +- > 16 files changed, 600 insertions(+), 45 deletions(-) > > diff --git a/Makefile.objs b/Makefile.objs > index 8f705f6..6fd02bc 100644 > --- a/Makefile.objs > +++ b/Makefile.objs > @@ -48,6 +48,7 @@ common-obj-$(CONFIG_WIN32) += os-win32.o > common-obj-$(CONFIG_POSIX) += os-posix.o > > common-obj-$(CONFIG_LINUX) += fsdev/ > +common-obj-$(CONFIG_WIN32) += fsdev/ > > common-obj-y += migration/ > common-obj-y += qemu-char.o #aio.o > diff --git a/configure b/configure > index 5db29f0..a4797c3 100755 > --- a/configure > +++ b/configure > @@ -4566,12 +4566,21 @@ if test "$want_tools" = "yes" ; then > fi > if test "$softmmu" = yes ; then > if test "$virtfs" != no ; then > - if test "$cap" = yes && test "$linux" = yes && test "$attr" = yes ; then > + if test "$linux" = yes ; then > + if test "$cap" = yes && test "$attr" = yes ; then > + virtfs=yes > + tools="$tools fsdev/virtfs-proxy-helper\$(EXESUF)" > + else > + if test "$virtfs" = yes; then > + error_exit "VirtFS requires libcap-devel and libattr-devel on Linux" > + fi > + virtfs=no > + fi > + elif test "$mingw32" = yes; then > virtfs=yes > - tools="$tools fsdev/virtfs-proxy-helper\$(EXESUF)" > else > if test "$virtfs" = yes; then > - error_exit "VirtFS is supported only on Linux and requires libcap-devel and libattr-devel" > + error_exit "VirtFS is only supported on Linux or Windows" > fi > virtfs=no > fi > diff --git a/fsdev/9p-iov-marshal.c b/fsdev/9p-iov-marshal.c > index fb40bdf..1a292c6 100644 > --- a/fsdev/9p-iov-marshal.c > +++ b/fsdev/9p-iov-marshal.c > @@ -15,7 +15,9 @@ > #include <glib.h> > #include <glib/gprintf.h> > #include <utime.h> > +#ifndef _WIN32 > #include <sys/uio.h> > +#endif > > #include "9p-iov-marshal.h" > #include "qemu/bswap.h" > diff --git a/fsdev/9p-marshal.c b/fsdev/9p-marshal.c > index 183d366..081cb88 100644 > --- a/fsdev/9p-marshal.c > +++ b/fsdev/9p-marshal.c > @@ -16,7 +16,9 @@ > #include <glib/gprintf.h> > #include <dirent.h> > #include <utime.h> > -#include <sys/uio.h> > +#ifndef WIN32 > + #include <sys/uio.h> > +#endif > > #include "9p-marshal.h" > > diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h > index b8c2602..446c6a5 100644 > --- a/fsdev/file-op-9p.h > +++ b/fsdev/file-op-9p.h > @@ -14,12 +14,43 @@ > #define _FILEOP_H > #include <dirent.h> > #include <utime.h> > -#include <sys/uio.h> > -#include <sys/vfs.h> > +#ifndef _WIN32 > + #include <sys/uio.h> > + #include <sys/vfs.h> > +#endif > > #define SM_LOCAL_MODE_BITS 0600 > #define SM_LOCAL_DIR_MODE_BITS 0700 > > +#ifdef _WIN32 > +typedef uint32_t uid_t; > +typedef uint32_t gid_t; > + > +/* from http://man7.org/linux/man-pages/man2/statfs.2.html */ > +typedef uint32_t __fsword_t; > +typedef uint32_t fsblkcnt_t; > +typedef uint32_t fsfilcnt_t; > + > +/* from linux/include/uapi/asm-generic/posix_types.h */ > +typedef struct { > + long __val[2]; > +} fsid_t; > + > +struct statfs { > + __fsword_t f_type; > + __fsword_t f_bsize; > + fsblkcnt_t f_blocks; > + fsblkcnt_t f_bfree; > + fsblkcnt_t f_bavail; > + fsfilcnt_t f_files; > + fsfilcnt_t f_ffree; > + fsid_t f_fsid; > + __fsword_t f_namelen; > + __fsword_t f_frsize; > + __fsword_t f_flags; > +}; > +#endif > + > typedef struct FsCred > { > uid_t fc_uid; > diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c > index bf7f0b0..384d72e 100644 > --- a/fsdev/qemu-fsdev.c > +++ b/fsdev/qemu-fsdev.c > @@ -26,7 +26,9 @@ static FsDriverTable FsDrivers[] = { > { .name = "handle", .ops = &handle_ops}, > #endif > { .name = "synth", .ops = &synth_ops}, > +#ifndef WIN32 > { .name = "proxy", .ops = &proxy_ops}, > +#endif > }; > > int qemu_fsdev_add(QemuOpts *opts) > diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c > index 16f45f4..710ab5f 100644 > --- a/hw/9pfs/9p-local.c > +++ b/hw/9pfs/9p-local.c > @@ -12,23 +12,174 @@ > */ > > #include "qemu/osdep.h" > +/* mifritscher: after killing the debug printf, kill this as well! */ > +#include "qemu/error-report.h" > #include "9p.h" > -#include "9p-xattr.h" > +#ifdef _WIN32 > +/* idea from http://mingw-users.1079350.n2.nabble.com/Undefined-reference-to-quot-lstat-quot-and-quot-S-ISLNK-quot-td5450984.html */ > +# define lstat(path, buffer) stat(path, buffer) > + > +# define mkdir(path, mode) mkdir(path) Maybe these definitions can go to include/sysemu/os-win32.h ? > +# define getxattr(buffer, name, pointer, length) 0 > + > +/* pretend success */ > +static int setxattr(const char *path, const char *name, > + const void *value, size_t size, int flags) > +{ > + return 0; > +} > + > +static ssize_t fgetxattr(int fd, const char *name, > + void *value, size_t size) > +{ > + return 0; > +} > + and these xattr definitions to include/qemu/xattr.h ? > +# define lchown(buffer, uid, gid) 0 > +# define readlink(buffer, buf, bufsz) 0 > +# define mknod(buffer, mode, u) 0 > +# define link(buffer, buffer1) 0 > +# define symlink(buffer, buffer1) 0 > + > +static ssize_t v9fs_get_xattr(FsContext *ctx, const char *path, > + const char *name, void *value, size_t size) > +{ > + errno = 95; /* EOPNOTSUP - wrong definition in mingw(130); */ This is ENOTSUP actually. > + return -1; > +} > + > +static ssize_t v9fs_list_xattr(FsContext *ctx, const char *path, > + void *value, size_t vsize) > +{ > + errno = 95; /* EOPNOTSUP - wrong definition in mingw(130); */ > + return -1; > +} > + > +static int v9fs_set_xattr(FsContext *ctx, const char *path, > + const char *name, void *value, size_t size, > + int flags) > +{ > + errno = 95; /* EOPNOTSUP - wrong definition in mingw(130); */ > + return -1; > +} > + > +static int v9fs_remove_xattr(FsContext *ctx, const char *path, > + const char *name) > +{ > + errno = 95; /* EOPNOTSUP - wrong definition in mingw(130); */ > + return -1; > +} > + > +static int readdir_r(DIR *dirp, struct dirent *entry, > + struct dirent **result) > +{ > + struct dirent *temp; > + errno = 0; > + temp = readdir(dirp); readdir() isn't expected to be thread safe... I believe we need some locking here. Also this function should probably be in os-win32.c. > + if (temp == 0) { > + error_printf("readdir_r: End of directory reached -> returning NULL\n"); > + *result = 0; > + } else { > + /* Copy it from the stack to the buffer got from the caller */ > + memcpy(entry, temp, sizeof(struct dirent)); > + error_printf("readdir_r: Name: %hu %s\n", > + temp->d_namlen, temp->d_name); > + error_printf("readdir_r: Name: %hu %s\n", > + entry->d_namlen, entry->d_name); > + *result = entry; > + } > + return errno; > +} > + > +/* Can be done better... */ > +static int statfs(const char *file, struct statfs *buf) > +{ > + memset(buf, 0, sizeof(struct statfs)); > + buf->f_type = 0x01021997; /* V9FS_MAGIC */ > + buf->f_bsize = 4096; > + buf->f_blocks = 4000000; > + buf->f_bfree = 3000000; > + buf->f_bavail = 2999000; > + buf->f_files = 1000000; > + buf->f_ffree = 800000; > + buf->f_namelen = NAME_MAX; > + return 0; > +} > + > +/* a crude hash function (needed for fake inodes) */ > +static ino_t hash(const char *path) > +{ > + ino_t result = (ino_t)41021998; > + int len = strlen(path); > + if (!len) { > + return result; > + } > + > + /* Q&D canolizement of the path */ > + if (path[len - 1] == '\\' || path[len - 1] == '/') { > + len--; > + } > + if (!len) { > + return result; > + } > + > + if (path[len - 1] == '.') { > + if (len == 1) { > + return result; > + } > + len--; > + if (path[len - 1] == '\\' || path[len - 1] == '/') { > + len--; > + /* .. -> kill last part */ > + } else if (path[len - 1] == '.') { > + len--; > + while (len) { > + if (path[len - 1] == '\\' || path[len - 1] == '/') { > + len--; > + break; > + } > + len--; > + } > + } > + } > + > + if (!len) { > + return result; > + } > + > + for (int i = 0; i < len; i++) { > + result += path[i] << (i % 7); > + result += path[i] << ((i + 11) % 17); > + result += path[i] << ((i + 19) % 23); > + } > + > + return result; > +} > + > +#else > +# include "9p-xattr.h" > +#endif I'd prefer the missing xattr bits to be added to win32... and if we really need different implementations, then maybe add 9p-xattr-posix.c and 9p-xattr-win32.c... > #include "fsdev/qemu-fsdev.h" /* local_ops */ > +#ifndef _WIN32 > #include <arpa/inet.h> > #include <pwd.h> > #include <grp.h> > #include <sys/socket.h> > #include <sys/un.h> > #include "qemu/xattr.h" > +#endif > #include "qemu/cutils.h" > #include "qemu/error-report.h" > #include <libgen.h> > -#include <linux/fs.h> > +#ifndef _WIN32 > + #include <linux/fs.h> > +#endif > #ifdef CONFIG_LINUX_MAGIC_H > #include <linux/magic.h> > #endif > +#ifndef _WIN32 > #include <sys/ioctl.h> > +#endif > > #ifndef XFS_SUPER_MAGIC > #define XFS_SUPER_MAGIC 0x58465342 > @@ -76,7 +227,7 @@ static FILE *local_fopen(const char *path, const char *mode) > } else { > return NULL; > } > - fd = open(path, flags, o_mode); > + fd = open(path, flags | O_BINARY, o_mode); Why is this needed ? > if (fd == -1) { > return NULL; > } > @@ -124,10 +275,20 @@ static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf) > char *path = fs_path->data; > > buffer = rpath(fs_ctx, path); > - err = lstat(buffer, stbuf); > + error_printf("\nrpath %s + %s -> %s\n\n", fs_ctx->fs_root, path, buffer); > + err = lstat(buffer, stbuf); > if (err) { > goto err_out; > } > +#ifdef _WIN32 > + /* This way, all files are executable > + (MingW seems to do 777 on dirs, but 666 on files) */ > + stbuf->st_mode |= S_IXUSR | S_IXGRP | S_IXOTH; > + > + /* Under WIN32 (MingW), st_ino seems to be always 2, > + which leads to confusion */ > + stbuf->st_ino = hash(path); > +#endif > if (fs_ctx->export_flags & V9FS_SM_MAPPED) { > /* Actual credentials are part of extended attrs */ > uid_t tmp_uid; > @@ -162,7 +323,7 @@ static int local_create_mapped_attr_dir(FsContext *ctx, const char *path) > char *attr_dir; > char *tmp_path = g_strdup(path); > > - attr_dir = g_strdup_printf("%s/%s/%s", > + attr_dir = g_strdup_printf(DELIMITER_IN_PATH2, > ctx->fs_root, dirname(tmp_path), VIRTFS_META_DIR); > > err = mkdir(attr_dir, 0700); > @@ -223,7 +384,8 @@ update_map_file: > if (credp->fc_gid != -1) { > gid = credp->fc_gid; > } > - if (credp->fc_mode != -1) { > + /* mifritscher: is normally unsigned... */ > + if ((int16_t)(credp->fc_mode) != -1) { > mode = credp->fc_mode; > } > if (credp->fc_rdev != -1) { > @@ -268,7 +430,8 @@ static int local_set_xattr(const char *path, FsCred *credp) > return err; > } > } > - if (credp->fc_mode != -1) { > + /* mifritscher: is normally unsigned... */ > + if ((int16_t)(credp->fc_mode) != -1) { > uint32_t tmp_mode = cpu_to_le32(credp->fc_mode); > err = setxattr(path, "user.virtfs.mode", &tmp_mode, sizeof(mode_t), 0); > if (err) { > @@ -323,7 +486,7 @@ static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path, > (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE)) { > int fd; > buffer = rpath(fs_ctx, path); > - fd = open(buffer, O_RDONLY | O_NOFOLLOW); > + fd = open(buffer, O_RDONLY | O_NOFOLLOW | O_BINARY); > g_free(buffer); > if (fd == -1) { > return -1; > @@ -358,7 +521,8 @@ static int local_open(FsContext *ctx, V9fsPath *fs_path, > char *path = fs_path->data; > > buffer = rpath(ctx, path); > - fs->fd = open(buffer, flags | O_NOFOLLOW); > + error_printf("File which should be opened: %s\n", buffer); > + fs->fd = open(buffer, flags | O_NOFOLLOW | O_BINARY); I see you add O_BINARY on all open() call sites ? Does this mean we need a helper ? > g_free(buffer); > return fs->fd; > } > @@ -370,6 +534,7 @@ static int local_opendir(FsContext *ctx, > char *path = fs_path->data; > > buffer = rpath(ctx, path); > + error_printf("Directory (opendir) which should be opened: %s\n", buffer); > fs->dir = opendir(buffer); > g_free(buffer); > if (!fs->dir) { > @@ -395,17 +560,36 @@ static int local_readdir_r(FsContext *ctx, V9fsFidOpenState *fs, > int ret; > > again: > +#ifdef _WIN32 > + error_printf("local_readdir_r: Directory which should be read:%s\n", > + fs->dir->dd_name); > +#endif > ret = readdir_r(fs->dir, entry, result); > if (ctx->export_flags & V9FS_SM_MAPPED) { > +#ifndef _WIN32 > entry->d_type = DT_UNKNOWN; > +#endif > } else if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { > if (!ret && *result != NULL && > !strcmp(entry->d_name, VIRTFS_META_DIR)) { > /* skp the meta data directory */ > goto again; > } > +#ifndef _WIN32 > entry->d_type = DT_UNKNOWN; > +#endif > } > + if (*result == NULL) { > + error_printf("local_readdir_r: End of directory -> returning NULL\n"); > + } else { > +#ifdef _WIN32 > + error_printf("local_readdir_r: Name: %hu %s\n", > + entry->d_namlen, entry->d_name); > +#else > + error_printf("local_readdir_r: Name: %s\n", entry->d_name); > +#endif > + } > + error_printf("local_readdir_r: return %d\n", ret); > return ret; > } > > @@ -418,10 +602,15 @@ static ssize_t local_preadv(FsContext *ctx, V9fsFidOpenState *fs, > const struct iovec *iov, > int iovcnt, off_t offset) > { > + error_printf("local_preadv: #iov: %u, addr: %p, #bytes: %u, offset: %llu\n", > + iovcnt, iov->iov_base, iov->iov_len, offset); > #ifdef CONFIG_PREADV > + error_printf("local_preadv: using preadv\n"); > return preadv(fs->fd, iov, iovcnt, offset); > #else > + error_printf("local_preadv: not using preadv\n"); > int err = lseek(fs->fd, offset, SEEK_SET); > + error_printf("local_preadv: lseek returned %d\n", err); > if (err == -1) { > return err; > } else { > @@ -491,7 +680,7 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path, > char *buffer = NULL; > > v9fs_string_init(&fullname); > - v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); > + v9fs_string_sprintf(&fullname, DELIMITER_IN_PATH, dir_path->data, name); > path = fullname.data; > > /* Determine the security model */ > @@ -552,7 +741,7 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path, > char *buffer = NULL; > > v9fs_string_init(&fullname); > - v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); > + v9fs_string_sprintf(&fullname, DELIMITER_IN_PATH, dir_path->data, name); > path = fullname.data; > > /* Determine the security model */ > @@ -610,7 +799,14 @@ static int local_fstat(FsContext *fs_ctx, int fid_type, > int err, fd; > > if (fid_type == P9_FID_DIR) { > + /* Don't know if that's right... > + (on WIN32/mingw, DIR has no fd entry) */ > +#ifdef _WIN32 > + #warning "Could cause problems!" > + fd = fs->fd; > +#else > fd = dirfd(fs->dir); > +#endif > } else { > fd = fs->fd; > } > @@ -619,6 +815,13 @@ static int local_fstat(FsContext *fs_ctx, int fid_type, > if (err) { > return err; > } > +#ifdef _WIN32 > + /* This way, all files are executable > + (MingW seems to do 777 on dirs, but 666 on files) */ > + stbuf->st_mode |= S_IXUSR | S_IXGRP | S_IXOTH; > + > + /* mifritscher: TODO: fake inode? */ > +#endif > if (fs_ctx->export_flags & V9FS_SM_MAPPED) { > /* Actual credentials are part of extended attrs */ > uid_t tmp_uid; > @@ -661,13 +864,16 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name, > flags |= O_NOFOLLOW; > > v9fs_string_init(&fullname); > - v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); > + v9fs_string_sprintf(&fullname, DELIMITER_IN_PATH, dir_path->data, name); > path = fullname.data; > > + error_printf("local_open2: got %s %s\n", dir_path->data, name); > + error_printf("local_open2: full path: %s\n", path); > + > /* Determine the security model */ > if (fs_ctx->export_flags & V9FS_SM_MAPPED) { > buffer = rpath(fs_ctx, path); > - fd = open(buffer, flags, SM_LOCAL_MODE_BITS); > + fd = open(buffer, flags | O_BINARY, SM_LOCAL_MODE_BITS); > if (fd == -1) { > err = fd; > goto out; > @@ -681,7 +887,7 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name, > } > } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { > buffer = rpath(fs_ctx, path); > - fd = open(buffer, flags, SM_LOCAL_MODE_BITS); > + fd = open(buffer, flags | O_BINARY, SM_LOCAL_MODE_BITS); > if (fd == -1) { > err = fd; > goto out; > @@ -696,12 +902,17 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name, > } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || > (fs_ctx->export_flags & V9FS_SM_NONE)) { > buffer = rpath(fs_ctx, path); > - fd = open(buffer, flags, credp->fc_mode); > + error_printf("local_open2: File which should be opened (open2): %s\n", > + buffer); > + fd = open(buffer, flags | O_BINARY, credp->fc_mode); > + error_printf("local_open2: open returned %d\n", fd); > if (fd == -1) { > err = fd; > goto out; > } > err = local_post_create_passthrough(fs_ctx, path, credp); > + error_printf("local_open2: local_post_create_passthrough returned %u\n", > + err); > if (err == -1) { > serrno = errno; > goto err_end; > @@ -732,7 +943,7 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath, > char *buffer = NULL; > > v9fs_string_init(&fullname); > - v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); > + v9fs_string_sprintf(&fullname, DELIMITER_IN_PATH, dir_path->data, name); > newpath = fullname.data; > > /* Determine the security model */ > @@ -740,7 +951,9 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath, > int fd; > ssize_t oldpath_size, write_size; > buffer = rpath(fs_ctx, newpath); > - fd = open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, SM_LOCAL_MODE_BITS); > + fd = open(buffer, > + O_CREAT | O_EXCL | O_RDWR | O_NOFOLLOW | O_BINARY, > + SM_LOCAL_MODE_BITS); > if (fd == -1) { > err = fd; > goto out; > @@ -758,8 +971,10 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath, > goto err_end; > } > close(fd); > - /* Set cleint credentials in symlink's xattr */ > + /* Set client credentials in symlink's xattr */ > +#ifndef _WIN32 > credp->fc_mode = credp->fc_mode|S_IFLNK; > +#endif > err = local_set_xattr(buffer, credp); > if (err == -1) { > serrno = errno; > @@ -769,7 +984,9 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath, > int fd; > ssize_t oldpath_size, write_size; > buffer = rpath(fs_ctx, newpath); > - fd = open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, SM_LOCAL_MODE_BITS); > + fd = open(buffer, > + O_CREAT | O_EXCL | O_RDWR | O_NOFOLLOW | O_BINARY, > + SM_LOCAL_MODE_BITS); > if (fd == -1) { > err = fd; > goto out; > @@ -788,7 +1005,9 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath, > } > close(fd); > /* Set cleint credentials in symlink's xattr */ > +#ifndef _WIN32 > credp->fc_mode = credp->fc_mode|S_IFLNK; > +#endif > err = local_set_mapped_file_attr(fs_ctx, newpath, credp); > if (err == -1) { > serrno = errno; > @@ -833,7 +1052,7 @@ static int local_link(FsContext *ctx, V9fsPath *oldpath, > char *buffer, *buffer1; > > v9fs_string_init(&newpath); > - v9fs_string_sprintf(&newpath, "%s/%s", dirpath->data, name); > + v9fs_string_sprintf(&newpath, DELIMITER_IN_PATH, dirpath->data, name); > > buffer = rpath(ctx, oldpath->data); > buffer1 = rpath(ctx, newpath.data); > @@ -934,7 +1153,12 @@ static int local_utimensat(FsContext *s, V9fsPath *fs_path, > char *path = fs_path->data; > > buffer = rpath(s, path); > +#ifdef _WIN32 > + #warning "Could cause problems!" > + ret = 0; > +#else > ret = qemu_utimens(buffer, buf); > +#endif > g_free(buffer); > return ret; > } > @@ -949,6 +1173,7 @@ static int local_remove(FsContext *ctx, const char *path) > buffer = rpath(ctx, path); > err = lstat(buffer, &stbuf); > g_free(buffer); > + error_printf("local_remove: stat %d %d\n", err, errno); > if (err) { > goto err_out; > } > @@ -957,10 +1182,12 @@ static int local_remove(FsContext *ctx, const char *path) > * directory > */ > if (S_ISDIR(stbuf.st_mode)) { > - buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root, > + buffer = g_strdup_printf(DELIMITER_IN_PATH2, ctx->fs_root, > path, VIRTFS_META_DIR); > err = remove(buffer); > g_free(buffer); > + error_printf("local_remove: .virtfs_metdata remove %d %d\n", > + err, errno); > if (err < 0 && errno != ENOENT) { > /* > * We didn't had the .virtfs_metadata file. May be file created > @@ -976,6 +1203,8 @@ static int local_remove(FsContext *ctx, const char *path) > buffer = local_mapped_attr_path(ctx, path); > err = remove(buffer); > g_free(buffer); > + error_printf("local_remove: local_mapped_attr_path remove %d %d\n", > + err, errno); > if (err < 0 && errno != ENOENT) { > /* > * We didn't had the .virtfs_metadata file. May be file created > @@ -986,7 +1215,14 @@ static int local_remove(FsContext *ctx, const char *path) > } > > buffer = rpath(ctx, path); > - err = remove(buffer); > + /* mifritscher: posix remove can delete directories as well, windows not */ > + if (S_ISDIR(stbuf.st_mode)) { > + err = rmdir(buffer); > + } else { > + err = remove(buffer); > + } > + error_printf("local_remove: final remove %d %d\n", > + err, errno); > g_free(buffer); > err_out: > return err; > @@ -998,7 +1234,12 @@ static int local_fsync(FsContext *ctx, int fid_type, > int fd; > > if (fid_type == P9_FID_DIR) { > +#ifdef _WIN32 > + #warning "Could cause problems!" > + fd = fs->fd; > +#else > fd = dirfd(fs->dir); > +#endif > } else { > fd = fs->fd; > } > @@ -1058,10 +1299,14 @@ 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", > + v9fs_string_sprintf((V9fsString *)target, DELIMITER_IN_PATH, > dir_path->data, name); > + error_printf("local_name_to_path: "); > + error_printf(DELIMITER_IN_PATH, dir_path->data, name); > + error_printf("\n"); > } else { > v9fs_string_sprintf((V9fsString *)target, "%s", name); > + error_printf("local_name_to_path: %s\n", name); > } > /* Bump the size for including terminating NULL */ > target->size++; > @@ -1078,8 +1323,10 @@ static int local_renameat(FsContext *ctx, V9fsPath *olddir, > 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); > + v9fs_string_sprintf(&old_full_name, > + DELIMITER_IN_PATH, olddir->data, old_name); > + v9fs_string_sprintf(&new_full_name, > + DELIMITER_IN_PATH, newdir->data, new_name); > > ret = local_rename(ctx, old_full_name.data, new_full_name.data); > v9fs_string_free(&old_full_name); > @@ -1096,17 +1343,19 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir, > > v9fs_string_init(&fullname); > > - v9fs_string_sprintf(&fullname, "%s/%s", dir->data, name); > + v9fs_string_sprintf(&fullname, DELIMITER_IN_PATH, dir->data, name); > if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { > if (flags == AT_REMOVEDIR) { > /* > * If directory remove .virtfs_metadata contained in the > * directory > */ > - buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root, > + buffer = g_strdup_printf(DELIMITER_IN_PATH2, ctx->fs_root, > fullname.data, VIRTFS_META_DIR); > ret = remove(buffer); > g_free(buffer); > + error_printf("local_unlinkat: .virtfs_metadata %d %d\n", > + ret, errno); > if (ret < 0 && errno != ENOENT) { > /* > * We didn't had the .virtfs_metadata file. May be file created > @@ -1121,6 +1370,8 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir, > */ > buffer = local_mapped_attr_path(ctx, fullname.data); > ret = remove(buffer); > + error_printf("local_unlinkat: local_mapped_attr_path %d %d\n", > + ret, errno); > g_free(buffer); > if (ret < 0 && errno != ENOENT) { > /* > @@ -1133,6 +1384,19 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir, > /* Remove the name finally */ > buffer = rpath(ctx, fullname.data); > ret = remove(buffer); > + error_printf("local_unlinkat: final |%s| %d %d\n", buffer, ret, errno); > + /* extension for MingW: remove or Windows can't handle directories... */ > +#ifdef _WIN32 > + /* mifritscher: Try to delete it as directory > + (AT_REMOVEDIR doesn't seem to be set in this case > + (testcase: rmdir from Linux)) */ > + if (ret < 0) { > + ret = rmdir(buffer); > + error_printf("local_unlinkat: final rmdir |%s| %d %d\n", > + buffer, ret, errno); > + > + } > +#endif > g_free(buffer); > > err_out: > @@ -1140,6 +1404,7 @@ err_out: > return ret; > } > > +#ifndef _WIN32 > static int local_ioc_getversion(FsContext *ctx, V9fsPath *path, > mode_t st_mode, uint64_t *st_gen) > { > @@ -1167,12 +1432,18 @@ static int local_ioc_getversion(FsContext *ctx, V9fsPath *path, > return -1; > #endif > } > +#endif > > static int local_init(FsContext *ctx) > { > int err = 0; > +#ifdef FS_IOC_GETVERSION > struct statfs stbuf; > +#endif > > +#ifdef _WIN32 > + ctx->xops = 0; > +#else > if (ctx->export_flags & V9FS_SM_PASSTHROUGH) { > ctx->xops = passthrough_xattr_ops; > } else if (ctx->export_flags & V9FS_SM_MAPPED) { > @@ -1186,6 +1457,7 @@ static int local_init(FsContext *ctx) > */ > ctx->xops = passthrough_xattr_ops; > } > +#endif > ctx->export_flags |= V9FS_PATHNAME_FSCONTEXT; > #ifdef FS_IOC_GETVERSION > /* > diff --git a/hw/9pfs/9p-synth.c b/hw/9pfs/9p-synth.c > index f1475df..8355722 100644 > --- a/hw/9pfs/9p-synth.c > +++ b/hw/9pfs/9p-synth.c > @@ -15,7 +15,9 @@ > #include "qemu/osdep.h" > #include "hw/virtio/virtio.h" > #include "9p.h" > -#include "9p-xattr.h" > +#ifndef _WIN32 > + #include "9p-xattr.h" > +#endif > #include "fsdev/qemu-fsdev.h" > #include "9p-synth.h" > #include "qemu/rcu.h" > @@ -152,8 +154,10 @@ static void v9fs_synth_fill_statbuf(V9fsSynthNode *node, struct stat *stbuf) > stbuf->st_gid = 0; > stbuf->st_rdev = 0; > stbuf->st_size = 0; > +#ifndef _WIN32 > stbuf->st_blksize = 0; > stbuf->st_blocks = 0; > +#endif > stbuf->st_atime = 0; > stbuf->st_mtime = 0; > stbuf->st_ctime = 0; > @@ -222,7 +226,11 @@ static void v9fs_synth_direntry(V9fsSynthNode *node, > { > strcpy(entry->d_name, node->name); > entry->d_ino = node->attr->inode; > +#ifdef _WIN32 > + #warning "Can cause problems!" > +#else > entry->d_off = off + 1; > +#endif > } > > static int v9fs_synth_get_dentry(V9fsSynthNode *dir, struct dirent *entry, > diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c > index f5e3012..7980f33 100644 > --- a/hw/9pfs/9p.c > +++ b/hw/9pfs/9p.c > @@ -20,7 +20,21 @@ > #include "qemu/sockets.h" > #include "virtio-9p.h" > #include "fsdev/qemu-fsdev.h" > -#include "9p-xattr.h" > +#ifdef _WIN32 > +/* taken from linux/kdev_t.h */ > +# define MINORBITS 20 > +# define MINORMASK ((1U << MINORBITS) - 1) > + > +# define major(dev) ((unsigned int) ((dev) >> MINORBITS)) > +# define minor(dev) ((unsigned int) ((dev) & MINORMASK)) > +# define makedev(ma, mi) (((ma) << MINORBITS) | (mi)) > + > +/* taken from linux/include/linux/stat.h */ > +# define UTIME_NOW ((1l << 30) - 1l) > +# define UTIME_OMIT ((1l << 30) - 2l) > +#else > +# include "9p-xattr.h" > +#endif > #include "coth.h" > #include "trace.h" > #include "migration/migration.h" > @@ -576,9 +590,11 @@ static void stat_to_qid(const struct stat *stbuf, V9fsQID *qidp) > if (S_ISDIR(stbuf->st_mode)) { > qidp->type |= P9_QID_TYPE_DIR; > } > - if (S_ISLNK(stbuf->st_mode)) { > - qidp->type |= P9_QID_TYPE_SYMLINK; > - } > + #ifndef _WIN32 > + if (S_ISLNK(stbuf->st_mode)) { > + qidp->type |= P9_QID_TYPE_SYMLINK; > + } > + #endif > } > > static int fid_to_qid(V9fsPDU *pdu, V9fsFidState *fidp, V9fsQID *qidp) > @@ -677,12 +693,15 @@ static mode_t v9mode_to_mode(uint32_t mode, V9fsString *extension) > ret |= S_IFDIR; > } > > +#ifndef _WIN32 > if (mode & P9_STAT_MODE_SYMLINK) { > ret |= S_IFLNK; > } > if (mode & P9_STAT_MODE_SOCKET) { > ret |= S_IFSOCK; > } > +#endif > + > if (mode & P9_STAT_MODE_NAMED_PIPE) { > ret |= S_IFIFO; > } > @@ -698,6 +717,7 @@ static mode_t v9mode_to_mode(uint32_t mode, V9fsString *extension) > ret |= S_IFREG; > } > > +#ifndef _WIN32 > if (mode & P9_STAT_MODE_SETUID) { > ret |= S_ISUID; > } > @@ -707,6 +727,7 @@ static mode_t v9mode_to_mode(uint32_t mode, V9fsString *extension) > if (mode & P9_STAT_MODE_SETVTX) { > ret |= S_ISVTX; > } > +#endif > > return ret; > } > @@ -762,6 +783,7 @@ static uint32_t stat_to_v9mode(const struct stat *stbuf) > mode |= P9_STAT_MODE_DIR; > } > > +#ifndef _WIN32 > if (S_ISLNK(stbuf->st_mode)) { > mode |= P9_STAT_MODE_SYMLINK; > } > @@ -769,6 +791,7 @@ static uint32_t stat_to_v9mode(const struct stat *stbuf) > if (S_ISSOCK(stbuf->st_mode)) { > mode |= P9_STAT_MODE_SOCKET; > } > +#endif > > if (S_ISFIFO(stbuf->st_mode)) { > mode |= P9_STAT_MODE_NAMED_PIPE; > @@ -778,6 +801,7 @@ static uint32_t stat_to_v9mode(const struct stat *stbuf) > mode |= P9_STAT_MODE_DEVICE; > } > > +#ifndef _WIN32 > if (stbuf->st_mode & S_ISUID) { > mode |= P9_STAT_MODE_SETUID; > } > @@ -789,6 +813,7 @@ static uint32_t stat_to_v9mode(const struct stat *stbuf) > if (stbuf->st_mode & S_ISVTX) { > mode |= P9_STAT_MODE_SETVTX; > } > +#endif > > return mode; > } > @@ -881,14 +906,34 @@ static void stat_to_v9stat_dotl(V9fsState *s, const struct stat *stbuf, > v9lstat->st_gid = stbuf->st_gid; > v9lstat->st_rdev = stbuf->st_rdev; > v9lstat->st_size = stbuf->st_size; > +#ifdef _WIN32 > + /* Blksize is the optimal EA-block, > + while blocks always refers to 512 blocks > + */ > + v9lstat->st_blksize = 4096; > + v9lstat->st_blocks = ((stbuf->st_size + 1) / 512) + 1; > +#else > v9lstat->st_blksize = stbuf->st_blksize; > v9lstat->st_blocks = stbuf->st_blocks; > +#endif > v9lstat->st_atime_sec = stbuf->st_atime; > +#ifdef _WIN32 > + v9lstat->st_atime_nsec = 0; > +#else > v9lstat->st_atime_nsec = stbuf->st_atim.tv_nsec; > +#endif > v9lstat->st_mtime_sec = stbuf->st_mtime; > +#ifdef _WIN32 > + v9lstat->st_mtime_nsec = 0; > +#else > v9lstat->st_mtime_nsec = stbuf->st_mtim.tv_nsec; > +#endif > v9lstat->st_ctime_sec = stbuf->st_ctime; > +#ifdef _WIN32 > + v9lstat->st_ctime_nsec = 0; > +#else > v9lstat->st_ctime_nsec = stbuf->st_ctim.tv_nsec; > +#endif > /* Currently we only support BASIC fields in stat */ > v9lstat->st_result_mask = P9_STATS_BASIC; > > @@ -1639,7 +1684,10 @@ static int v9fs_do_readdir_with_stat(V9fsPDU *pdu, > v9fs_path_init(&path); > err = v9fs_co_readdir_r(pdu, fidp, dent, &result); > if (err || !result) { > + error_printf("v9fs_do_readdir_with_stat: exiting...\n"); > break; > + } else { > + error_printf("v9fs_do_readdir_with_stat: continue\n"); > } > err = v9fs_co_name_to_path(pdu, &fidp->path, dent->d_name, &path); > if (err < 0) { > @@ -1666,7 +1714,12 @@ static int v9fs_do_readdir_with_stat(V9fsPDU *pdu, > count += len; > v9fs_stat_free(&v9stat); > v9fs_path_free(&path); > +#ifdef _WIN32 > + #warning "Probably right, but could make problems!" > + saved_dir_pos = v9fs_co_telldir(pdu, fidp); > +#else > saved_dir_pos = dent->d_off; > +#endif > } > out: > g_free(dent); > @@ -1806,6 +1859,9 @@ static int v9fs_do_readdir(V9fsPDU *pdu, > int32_t count = 0; > off_t saved_dir_pos; > struct dirent *dent, *result; > +#ifdef _WIN32 > + uint8_t type = 0; /* DT_UNKNOWN */ > +#endif > > /* save the directory position */ > saved_dir_pos = v9fs_co_telldir(pdu, fidp); > @@ -1818,15 +1874,27 @@ static int v9fs_do_readdir(V9fsPDU *pdu, > while (1) { > err = v9fs_co_readdir_r(pdu, fidp, dent, &result); > if (err || !result) { > + error_printf("v9fs_do_readdir: exiting...\n"); > break; > + } else { > + error_printf("v9fs_do_readdir: continue\n"); > } > v9fs_string_init(&name); > + if (!dent->d_name) { > + error_printf("\ndent->d_name is NULL!\n"); > + break; > + } else { > + error_printf("v9fs_do_readdir: entry is named %s, strlen %u\n", > + dent->d_name, strlen(dent->d_name)); > + } > v9fs_string_sprintf(&name, "%s", dent->d_name); > if ((count + v9fs_readdir_data_size(&name)) > max_count) { > /* Ran out of buffer. Set dir back to old position and return */ > v9fs_co_seekdir(pdu, fidp, saved_dir_pos); > v9fs_string_free(&name); > g_free(dent); > + error_printf("v9fs_do_readdir: RAN OUT OF BUFFER return %d\n\n", > + count); > return count; > } > /* > @@ -1841,9 +1909,16 @@ static int v9fs_do_readdir(V9fsPDU *pdu, > qid.version = 0; > > /* 11 = 7 + 4 (7 = start offset, 4 = space for storing count) */ > +#ifdef _WIN32 > + #warning "Probably right, but could make problems!" > + len = pdu_marshal(pdu, 11 + count, "Qqbs", > + &qid, v9fs_co_telldir(pdu, fidp), > + type, &name); > +#else > len = pdu_marshal(pdu, 11 + count, "Qqbs", > &qid, dent->d_off, > dent->d_type, &name); > +#endif > if (len < 0) { > v9fs_co_seekdir(pdu, fidp, saved_dir_pos); > v9fs_string_free(&name); > @@ -1852,12 +1927,18 @@ static int v9fs_do_readdir(V9fsPDU *pdu, > } > count += len; > v9fs_string_free(&name); > +#ifdef _WIN32 > + #warning "Probably right, but could make problems!" > + saved_dir_pos = v9fs_co_telldir(pdu, fidp); > +#else > saved_dir_pos = dent->d_off; > +#endif > } > g_free(dent); > if (err < 0) { > return err; > } > + error_printf("v9fs_do_readdir: return %d\n\n", count); > return count; > } > > @@ -1878,6 +1959,8 @@ static void v9fs_readdir(void *opaque) > goto out_nofid; > } > trace_v9fs_readdir(pdu->tag, pdu->id, fid, initial_offset, max_count); > + error_printf("v9fs_readdir initial: %llu max count: %u\n", > + initial_offset, max_count); > > fidp = get_fid(pdu, fid); > if (fidp == NULL) { > @@ -1904,10 +1987,13 @@ static void v9fs_readdir(void *opaque) > } > retval += count + offset; > trace_v9fs_readdir_return(pdu->tag, pdu->id, count, retval); > + error_printf("v9fs_readdir: count: %d retval: %d\n\n", count, retval); > out: > put_fid(pdu, fidp); > out_nofid: > pdu_complete(pdu, retval); > + > + error_printf("v9fs_readdir: return\n"); > } > > static int v9fs_xattr_write(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp, > @@ -2166,8 +2252,12 @@ static void v9fs_create(void *opaque) > } > v9fs_path_copy(&fidp->path, &path); > } else if (perm & P9_STAT_MODE_SOCKET) { > +#ifdef _WIN32 > + err = -1; > +#else > err = v9fs_co_mknod(pdu, fidp, &name, fidp->uid, -1, > 0, S_IFSOCK | (perm & 0777), &stbuf); > +#endif > if (err < 0) { > goto out; > } > @@ -3338,7 +3428,7 @@ int v9fs_device_realize_common(V9fsState *s, Error **errp) > * call back to do that. Since we are in the init path, we don't > * use co-routines here. > */ > - if (s->ops->name_to_path(&s->ctx, NULL, "/", &path) < 0) { > + if (s->ops->name_to_path(&s->ctx, NULL, DELIMITER_STRING, &path) < 0) { > error_setg(errp, > "error in converting name to path %s", strerror(errno)); > goto out; > @@ -3370,6 +3460,7 @@ void v9fs_device_unrealize_common(V9fsState *s, Error **errp) > > static void __attribute__((__constructor__)) v9fs_set_fd_limit(void) > { > +#ifndef _WIN32 > struct rlimit rlim; > if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) { > error_report("Failed to get the resource limit"); > @@ -3377,4 +3468,5 @@ static void __attribute__((__constructor__)) v9fs_set_fd_limit(void) > } > open_fd_hw = rlim.rlim_cur - MIN(400, rlim.rlim_cur/3); > open_fd_rc = rlim.rlim_cur/2; > +#endif > } > diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h > index 1a19418..7bc8863 100644 > --- a/hw/9pfs/9p.h > +++ b/hw/9pfs/9p.h > @@ -3,7 +3,29 @@ > > #include <dirent.h> > #include <utime.h> > -#include <sys/resource.h> > +#ifdef _WIN32 > +/* Bad workaround, from http://octave.org/doxygen/3.4/fcntl_8h.html */ > +# define O_NOCTTY 0 > +# define O_NDELAY 0 > +# define O_NONBLOCK O_NDELAY > +# define O_DSYNC 0 > +# define O_DIRECT 0 > +# define O_DIRECTORY 0 > +# define O_NOFOLLOW 0 > +# define O_NOATIME 0 > +# define O_SYNC 0 > +# define O_ASYNC 0 > + > +# define FASYNC 0 > + > +# define AT_REMOVEDIR 1 > + > +# define NAME_MAX 260 > + > +#else > +# include <sys/resource.h> > +#endif > + > #include <glib.h> > #include "standard-headers/linux/virtio_9p.h" > #include "hw/virtio/virtio.h" > @@ -12,6 +34,10 @@ > #include "qemu/thread.h" > #include "qemu/coroutine.h" > > +#define DELIMITER_STRING "/" > +#define DELIMITER_IN_PATH "%s/%s" > +#define DELIMITER_IN_PATH2 "%s/%s/%s" > + Is this really needed (will there be different values for win32) ? If yes, I guess DELEMITER_STRING should be defined in a host arch specific header ? And anyway, this should be pushed to a separate patch. > enum { > P9_TLERROR = 6, > P9_RLERROR, > @@ -108,9 +134,49 @@ enum p9_proto_version { > > #define FID_REFERENCED 0x1 > #define FID_NON_RECLAIMABLE 0x2 > + > +/* combines the host's root dir and the path to a complete host path */ > static inline char *rpath(FsContext *ctx, const char *path) > { > - return g_strdup_printf("%s/%s", ctx->fs_root, path); > + char *result; > + result = g_strdup_printf(DELIMITER_IN_PATH, ctx->fs_root, path); > +#ifdef _WIN32 > + int input = 0; > + int output = 0; > + while (result[input]) { > + /* error_printf("<-%d %c\n", input, result[input]); */ > + if (result[input] == '/') { > + result[output] = '\\'; > + /* remove duplicate \... */ Why do we need to remove duplicate \ ? > + if (output > 0 && result[output - 1] == '\\') { > + /* error_printf("remove duplicate \\\n"); */ > + output--; > + } else { > + result[output] = '\\'; > + } > + /* error_printf(" %c\n", result[output]); */ > + } else { > + result[output] = result[input]; > + } > + /* error_printf("->%d %c\n\n", output, result[output]); */ > + input++; > + output++; > + } > + /* Kill last \ (but leave it if the char before is a : ...) Why kill last \ ? > + So: > + C:\ -> C:\ > + C:\blah\ -> C:\blah > + b\ -> b > + blah\ -> blah */ > + if (output > 1 && result[output - 1] == '\\' > + && (output == 1 || result[output - 2] != ':')) { > + /* error_printf("Killed last \\\n"); */ > + result[output - 1] = '\0'; > + } else { > + result[output] = '\0'; > + } > +#endif I understand we need to convert / to \, but I don't see why we should remove duplicates... and anyway, this should be moved to a fixup helper. > + return result; > } > > /* > diff --git a/hw/9pfs/Makefile.objs b/hw/9pfs/Makefile.objs > index da0ae0c..6f6ed19 100644 > --- a/hw/9pfs/Makefile.objs > +++ b/hw/9pfs/Makefile.objs > @@ -1,9 +1,10 @@ > common-obj-y = 9p.o > -common-obj-y += 9p-local.o 9p-xattr.o > -common-obj-y += 9p-xattr-user.o 9p-posix-acl.o > +common-obj-$(CONFIG_LINUX) += 9p-local.o 9p-xattr.o > +common-obj-$(CONFIG_LINUX) += 9p-xattr-user.o 9p-posix-acl.o > +common-obj-$(CONFIG_WIN32) += 9p-local.o > common-obj-y += coth.o cofs.o codir.o cofile.o > common-obj-y += coxattr.o 9p-synth.o > common-obj-$(CONFIG_OPEN_BY_HANDLE) += 9p-handle.o > -common-obj-y += 9p-proxy.o > +common-obj-$(CONFIG_POSIX) += 9p-proxy.o > > obj-y += virtio-9p-device.o > diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c > index 91df7f7..399bd8a 100644 > --- a/hw/9pfs/codir.c > +++ b/hw/9pfs/codir.c > @@ -17,6 +17,8 @@ > #include "qemu/thread.h" > #include "qemu/coroutine.h" > #include "coth.h" > +/* mifritscher: after killing the debug printf, kill this as well! */ > +#include "qemu/error-report.h" > > int v9fs_co_readdir_r(V9fsPDU *pdu, V9fsFidState *fidp, struct dirent *dent, > struct dirent **result) > @@ -37,6 +39,12 @@ int v9fs_co_readdir_r(V9fsPDU *pdu, V9fsFidState *fidp, struct dirent *dent, > err = 0; > } > }); > +#ifdef _WIN32 > + error_printf("v9fs_co_readdir_r: %s %d %p\n", > + (&fidp->fs)->dir->dd_name, err, *result); > +#else > + error_printf("v9fs_co_readdir_r: %d %p\n", err, *result); > +#endif > return err; > } > > @@ -55,6 +63,12 @@ off_t v9fs_co_telldir(V9fsPDU *pdu, V9fsFidState *fidp) > err = -errno; > } > }); > +#ifdef _WIN32 > + error_printf("v9fs_co_telldir_r: %s %lld\n", > + (&fidp->fs)->dir->dd_name, err); > +#else > + error_printf("v9fs_co_telldir_r: %ld\n", err); > +#endif > return err; > } > > @@ -68,6 +82,11 @@ void v9fs_co_seekdir(V9fsPDU *pdu, V9fsFidState *fidp, off_t offset) > { > s->ops->seekdir(&s->ctx, &fidp->fs, offset); > }); > +#ifdef _WIN32 > + error_printf("v9fs_co_seekdir: %s\n", (&fidp->fs)->dir->dd_name); > +#else > + error_printf("v9fs_co_seekdir\n"); > +#endif > } > > void v9fs_co_rewinddir(V9fsPDU *pdu, V9fsFidState *fidp) > @@ -80,6 +99,11 @@ void v9fs_co_rewinddir(V9fsPDU *pdu, V9fsFidState *fidp) > { > s->ops->rewinddir(&s->ctx, &fidp->fs); > }); > +#ifdef _WIN32 > + error_printf("v9fs_co_rewinddir: %s\n", (&fidp->fs)->dir->dd_name); > +#else > + error_printf("v9fs_co_rewinddir\n"); > +#endif > } > > int v9fs_co_mkdir(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name, > @@ -116,6 +140,7 @@ int v9fs_co_mkdir(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name, > } > }); > v9fs_path_unlock(s); > + error_printf("v9fs_co_mkdir: %d\n", err); > return err; > } > > @@ -144,6 +169,11 @@ int v9fs_co_opendir(V9fsPDU *pdu, V9fsFidState *fidp) > v9fs_reclaim_fd(pdu); > } > } > +#ifdef _WIN32 > + error_printf("v9fs_co_opendir: %s %d\n", (&fidp->fs)->dir->dd_name, err); > +#else > + error_printf("v9fs_co_opendir: %d\n", err); > +#endif > return err; > } > > @@ -165,5 +195,6 @@ int v9fs_co_closedir(V9fsPDU *pdu, V9fsFidOpenState *fs) > if (!err) { > total_open_fd--; > } > + error_printf("v9fs_co_closedir: %d\n", err); > return err; > } > diff --git a/hw/9pfs/cofile.c b/hw/9pfs/cofile.c > index 293483e..a9c1a10 100644 > --- a/hw/9pfs/cofile.c > +++ b/hw/9pfs/cofile.c > @@ -17,6 +17,8 @@ > #include "qemu/thread.h" > #include "qemu/coroutine.h" > #include "coth.h" > +/* mifritscher: after killing the debug printf, kill this as well! */ > +#include "qemu/error-report.h" > > int v9fs_co_st_gen(V9fsPDU *pdu, V9fsPath *path, mode_t st_mode, > V9fsStatDotl *v9stat) > @@ -39,6 +41,7 @@ int v9fs_co_st_gen(V9fsPDU *pdu, V9fsPath *path, mode_t st_mode, > }); > v9fs_path_unlock(s); > } > + error_printf("v9fs_co_st_gen: %d\n", err); > return err; > } > > @@ -59,6 +62,7 @@ int v9fs_co_lstat(V9fsPDU *pdu, V9fsPath *path, struct stat *stbuf) > } > }); > v9fs_path_unlock(s); > + error_printf("v9fs_co_lstat: %d\n", err); > return err; > } > > @@ -91,6 +95,7 @@ int v9fs_co_fstat(V9fsPDU *pdu, V9fsFidState *fidp, struct stat *stbuf) > err = 0; > } > } > + error_printf("v9fs_co_fstat: %s %d\n", (&fidp->path)->data, err); > return err; > } > > @@ -119,6 +124,7 @@ int v9fs_co_open(V9fsPDU *pdu, V9fsFidState *fidp, int flags) > v9fs_reclaim_fd(pdu); > } > } > + error_printf("v9fs_co_open: %s %d\n", (&fidp->path)->data, err); > return err; > } > > @@ -147,13 +153,17 @@ int v9fs_co_open2(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name, gid_t gid, > { > err = s->ops->open2(&s->ctx, &fidp->path, > name->data, flags, &cred, &fidp->fs); > + error_printf("v9fs_co_open2: open returned %d\n", err); > if (err < 0) { > err = -errno; > } else { > v9fs_path_init(&path); > err = v9fs_name_to_path(s, &fidp->path, name->data, &path); > + error_printf("v9fs_co_open2: v9fs_name_to_path returned %d\n", > + err); > if (!err) { > err = s->ops->lstat(&s->ctx, &path, stbuf); > + error_printf("v9fs_co_open2: lstat returned %d\n", err); > if (err < 0) { > err = -errno; > s->ops->close(&s->ctx, &fidp->fs); > @@ -173,6 +183,7 @@ int v9fs_co_open2(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name, gid_t gid, > v9fs_reclaim_fd(pdu); > } > } > + error_printf("v9fs_co_open2: %s %d\n", (&fidp->path)->data, err); > return err; > } > > @@ -194,6 +205,7 @@ int v9fs_co_close(V9fsPDU *pdu, V9fsFidOpenState *fs) > if (!err) { > total_open_fd--; > } > + error_printf("v9fs_co_close: %d\n", err); > return err; > } > > @@ -234,6 +246,7 @@ int v9fs_co_link(V9fsPDU *pdu, V9fsFidState *oldfid, > } > }); > v9fs_path_unlock(s); > + error_printf("v9fs_co_link: %d\n", err); > return err; > } > > @@ -253,6 +266,7 @@ int v9fs_co_pwritev(V9fsPDU *pdu, V9fsFidState *fidp, > err = -errno; > } > }); > + error_printf("v9fs_co_pwritev: %s %d\n", (&fidp->path)->data, err); > return err; > } > > @@ -272,5 +286,6 @@ int v9fs_co_preadv(V9fsPDU *pdu, V9fsFidState *fidp, > err = -errno; > } > }); > + error_printf("v9fs_co_preadv: %s %d\n", (&fidp->path)->data, err); > return err; > } > diff --git a/hw/9pfs/cofs.c b/hw/9pfs/cofs.c > index 18c81cb..a3a42bf 100644 > --- a/hw/9pfs/cofs.c > +++ b/hw/9pfs/cofs.c > @@ -17,6 +17,8 @@ > #include "qemu/thread.h" > #include "qemu/coroutine.h" > #include "coth.h" > +/* mifritscher: after killing the debug printf, kill this as well! */ > +#include "qemu/error-report.h" > > static ssize_t __readlink(V9fsState *s, V9fsPath *path, V9fsString *buf) > { > @@ -67,6 +69,7 @@ int v9fs_co_readlink(V9fsPDU *pdu, V9fsPath *path, V9fsString *buf) > } > }); > v9fs_path_unlock(s); > + error_printf("v9fs_co_readlink: %d\n", err); > return err; > } > > @@ -87,6 +90,7 @@ int v9fs_co_statfs(V9fsPDU *pdu, V9fsPath *path, struct statfs *stbuf) > } > }); > v9fs_path_unlock(s); > + error_printf("v9fs_co_statfs: %d\n", err); > return err; > } > > @@ -110,6 +114,7 @@ int v9fs_co_chmod(V9fsPDU *pdu, V9fsPath *path, mode_t mode) > } > }); > v9fs_path_unlock(s); > + error_printf("v9fs_co_chmod: %d\n", err); > return err; > } > > @@ -131,6 +136,7 @@ int v9fs_co_utimensat(V9fsPDU *pdu, V9fsPath *path, > } > }); > v9fs_path_unlock(s); > + error_printf("v9fs_co_utimensat: %d\n", err); > return err; > } > > @@ -155,6 +161,7 @@ int v9fs_co_chown(V9fsPDU *pdu, V9fsPath *path, uid_t uid, gid_t gid) > } > }); > v9fs_path_unlock(s); > + error_printf("v9fs_co_chown: %d\n", err); > return err; > } > > @@ -175,6 +182,7 @@ int v9fs_co_truncate(V9fsPDU *pdu, V9fsPath *path, off_t size) > } > }); > v9fs_path_unlock(s); > + error_printf("v9fs_co_truncate: %d\n", err); > return err; > } > > @@ -213,6 +221,7 @@ int v9fs_co_mknod(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name, uid_t uid, > } > }); > v9fs_path_unlock(s); > + error_printf("v9fs_co_mknod: %d\n", err); > return err; > } > > @@ -234,6 +243,7 @@ int v9fs_co_remove(V9fsPDU *pdu, V9fsPath *path) > } > }); > v9fs_path_unlock(s); > + error_printf("v9fs_co_remove: %d\n", err); > return err; > } > > @@ -254,6 +264,7 @@ int v9fs_co_unlinkat(V9fsPDU *pdu, V9fsPath *path, V9fsString *name, int flags) > } > }); > v9fs_path_unlock(s); > + error_printf("v9fs_co_unlinkat: %d\n", err); > return err; > } > > @@ -273,6 +284,7 @@ int v9fs_co_rename(V9fsPDU *pdu, V9fsPath *oldpath, V9fsPath *newpath) > err = -errno; > } > }); > + error_printf("v9fs_co_rename: %d\n", err); > return err; > } > > @@ -293,6 +305,7 @@ int v9fs_co_renameat(V9fsPDU *pdu, V9fsPath *olddirpath, V9fsString *oldname, > err = -errno; > } > }); > + error_printf("v9fs_co_renameat: %d\n", err); > return err; > } > > @@ -331,6 +344,7 @@ int v9fs_co_symlink(V9fsPDU *pdu, V9fsFidState *dfidp, V9fsString *name, > } > }); > v9fs_path_unlock(s); > + error_printf("v9fs_co_symlink: %d\n", err); > return err; > } > > @@ -361,5 +375,6 @@ int v9fs_co_name_to_path(V9fsPDU *pdu, V9fsPath *dirpath, > } > }); > } > + error_printf("v9fs_co_name_to_path: %d\n", err); > return err; > } > diff --git a/hw/9pfs/coxattr.c b/hw/9pfs/coxattr.c > index 6ad96ea..49fbd5e 100644 > --- a/hw/9pfs/coxattr.c > +++ b/hw/9pfs/coxattr.c > @@ -17,6 +17,8 @@ > #include "qemu/thread.h" > #include "qemu/coroutine.h" > #include "coth.h" > +/* mifritscher: after killing the debug printf, kill this as well! */ > +#include "qemu/error-report.h" > > int v9fs_co_llistxattr(V9fsPDU *pdu, V9fsPath *path, void *value, size_t size) > { > @@ -35,6 +37,7 @@ int v9fs_co_llistxattr(V9fsPDU *pdu, V9fsPath *path, void *value, size_t size) > } > }); > v9fs_path_unlock(s); > + error_printf("v9fs_co_llistxattr: %d\n", err); > return err; > } > > @@ -59,6 +62,7 @@ int v9fs_co_lgetxattr(V9fsPDU *pdu, V9fsPath *path, > } > }); > v9fs_path_unlock(s); > + error_printf("v9fs_co_lgetxattr: %d\n", err); > return err; > } > > @@ -83,6 +87,7 @@ int v9fs_co_lsetxattr(V9fsPDU *pdu, V9fsPath *path, > } > }); > v9fs_path_unlock(s); > + error_printf("v9fs_co_lsetxattr: %d\n", err); > return err; > } > > @@ -104,5 +109,6 @@ int v9fs_co_lremovexattr(V9fsPDU *pdu, V9fsPath *path, > } > }); > v9fs_path_unlock(s); > + error_printf("v9fs_co_lremovexattr: %d\n", err); > return err; > } > diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c > index a38850e..59d0a50 100644 > --- a/hw/9pfs/virtio-9p-device.c > +++ b/hw/9pfs/virtio-9p-device.c > @@ -17,7 +17,9 @@ > #include "qemu/sockets.h" > #include "virtio-9p.h" > #include "fsdev/qemu-fsdev.h" > -#include "9p-xattr.h" > +#ifndef WIN32 > + #include "9p-xattr.h" > +#endif > #include "coth.h" > #include "hw/virtio/virtio-access.h" > #include "qemu/iov.h"
Hello Greg, I commented your comments :-) To summerize: * I didn't know where to put the win32 specific functions/wrappers - thanks showing me the locations! * Binary mode is needed by Windows - else newlines are screwed up. * Windows is way more picky than Linux regarding paths. * Which looking mechanism should I use? Best regards, Michael P.S. is there a nice tool to edit / split patchfiles? > More comments. > > On Tue, 12 Apr 2016 09:52:00 +0200 > Michael Fritscher <michael@fritscher.net> wrote: > >> It was tested on Windows & Linux hosts, on the later no obvious >> regressions could be found. The guest was a Knoppix 7.6.0 live cd. >> >> This is WIP and a RFC - it isn't meant to be upstreamed yet. The >> error_printf are only for debugging and will be deleted in the final >> patch. >> >> There are some comments with "mifritscher" - I'm not quite sure how to >> handle these problems (e.g. on mingw, this in 32 bit, while on Linux >> this is 16 bit and so on). Additionally, some places from which I >> suspect problems are marked with a #warning. >> >> Changes against v1: >> * fixed open (added binary flag) -> read/write is fine now, file >> creation was fixed as well >> * added inode calculation using own crude hash algorithm >> * fixed xattr returning -1 + EOPNOTSUP -> fixes e.g. executing files >> * fixed unlinkat / remove für directories by trying rmdir as well >> * prepend 777 mode on files (for executing) >> >> What does work: >> * reading/writing "big" files (5MB, verified with md5sum) >> * creating files >> * executing files >> * mkdir >> * rm / rmdir >> * cp files >> * running gcc >> * cp first 250 files & directories from /etc >> * tar it from and to the 9p mount >> * create a 100 MB swap file and do a mkswap on it >> >> What does not work: >> * swapon - no real surprise (doesn't work on Linux as well - with the >> same error message) ;-) (swapon returns -1 EINVAL) >> * link / symlink (there is no real aequivalent for this on windows) >> * mknod (dito) >> * chown (dito - prepend success for compatibility) >> >> State of v1: >> What works: >> * mount >> * stat >> * chdir >> * readdir (aka ls) >> * read of small files (<10k) >> * overwrite >> >> What does not work: >> * create new files (in 90% problems with path handling (old path >> occurs) >> * read / probably write big files >> >> >> Signed-off-by: Michael Fritscher <michael@fritscher.net> >> --- >> On https://github.com/mifritscher/qemu/tree/9pfs_windows is a git tree >> with the patch. >> >> I gave a shot at xattr (try to include xattr stuff) but it ended up even >> more #ifdefs. So I gave up at this. >> Now I'm waiting on comments etc. If there are no big objections, I'll >> remove the debug output and make a patch which is meant for upstreaming. >> >> Thanks to everybody which helped me! >> >> Makefile.objs | 1 + >> configure | 15 ++- >> fsdev/9p-iov-marshal.c | 2 + >> fsdev/9p-marshal.c | 4 +- >> fsdev/file-op-9p.h | 35 ++++- >> fsdev/qemu-fsdev.c | 2 + >> hw/9pfs/9p-local.c | 326 >> +++++++++++++++++++++++++++++++++++++++++---- >> hw/9pfs/9p-synth.c | 10 +- >> hw/9pfs/9p.c | 102 +++++++++++++- >> hw/9pfs/9p.h | 70 +++++++++- >> hw/9pfs/Makefile.objs | 7 +- >> hw/9pfs/codir.c | 31 +++++ >> hw/9pfs/cofile.c | 15 +++ >> hw/9pfs/cofs.c | 15 +++ >> hw/9pfs/coxattr.c | 6 + >> hw/9pfs/virtio-9p-device.c | 4 +- >> 16 files changed, 600 insertions(+), 45 deletions(-) >> >> diff --git a/Makefile.objs b/Makefile.objs >> index 8f705f6..6fd02bc 100644 >> --- a/Makefile.objs >> +++ b/Makefile.objs >> @@ -48,6 +48,7 @@ common-obj-$(CONFIG_WIN32) += os-win32.o >> common-obj-$(CONFIG_POSIX) += os-posix.o >> >> common-obj-$(CONFIG_LINUX) += fsdev/ >> +common-obj-$(CONFIG_WIN32) += fsdev/ >> >> common-obj-y += migration/ >> common-obj-y += qemu-char.o #aio.o >> diff --git a/configure b/configure >> index 5db29f0..a4797c3 100755 >> --- a/configure >> +++ b/configure >> @@ -4566,12 +4566,21 @@ if test "$want_tools" = "yes" ; then >> fi >> if test "$softmmu" = yes ; then >> if test "$virtfs" != no ; then >> - if test "$cap" = yes && test "$linux" = yes && test "$attr" = yes ; >> then >> + if test "$linux" = yes ; then >> + if test "$cap" = yes && test "$attr" = yes ; then >> + virtfs=yes >> + tools="$tools fsdev/virtfs-proxy-helper\$(EXESUF)" >> + else >> + if test "$virtfs" = yes; then >> + error_exit "VirtFS requires libcap-devel and libattr-devel on >> Linux" >> + fi >> + virtfs=no >> + fi >> + elif test "$mingw32" = yes; then >> virtfs=yes >> - tools="$tools fsdev/virtfs-proxy-helper\$(EXESUF)" >> else >> if test "$virtfs" = yes; then >> - error_exit "VirtFS is supported only on Linux and requires >> libcap-devel and libattr-devel" >> + error_exit "VirtFS is only supported on Linux or Windows" >> fi >> virtfs=no >> fi >> diff --git a/fsdev/9p-iov-marshal.c b/fsdev/9p-iov-marshal.c >> index fb40bdf..1a292c6 100644 >> --- a/fsdev/9p-iov-marshal.c >> +++ b/fsdev/9p-iov-marshal.c >> @@ -15,7 +15,9 @@ >> #include <glib.h> >> #include <glib/gprintf.h> >> #include <utime.h> >> +#ifndef _WIN32 >> #include <sys/uio.h> >> +#endif >> >> #include "9p-iov-marshal.h" >> #include "qemu/bswap.h" >> diff --git a/fsdev/9p-marshal.c b/fsdev/9p-marshal.c >> index 183d366..081cb88 100644 >> --- a/fsdev/9p-marshal.c >> +++ b/fsdev/9p-marshal.c >> @@ -16,7 +16,9 @@ >> #include <glib/gprintf.h> >> #include <dirent.h> >> #include <utime.h> >> -#include <sys/uio.h> >> +#ifndef WIN32 >> + #include <sys/uio.h> >> +#endif >> >> #include "9p-marshal.h" >> >> diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h >> index b8c2602..446c6a5 100644 >> --- a/fsdev/file-op-9p.h >> +++ b/fsdev/file-op-9p.h >> @@ -14,12 +14,43 @@ >> #define _FILEOP_H >> #include <dirent.h> >> #include <utime.h> >> -#include <sys/uio.h> >> -#include <sys/vfs.h> >> +#ifndef _WIN32 >> + #include <sys/uio.h> >> + #include <sys/vfs.h> >> +#endif >> >> #define SM_LOCAL_MODE_BITS 0600 >> #define SM_LOCAL_DIR_MODE_BITS 0700 >> >> +#ifdef _WIN32 >> +typedef uint32_t uid_t; >> +typedef uint32_t gid_t; >> + >> +/* from http://man7.org/linux/man-pages/man2/statfs.2.html */ >> +typedef uint32_t __fsword_t; >> +typedef uint32_t fsblkcnt_t; >> +typedef uint32_t fsfilcnt_t; >> + >> +/* from linux/include/uapi/asm-generic/posix_types.h */ >> +typedef struct { >> + long __val[2]; >> +} fsid_t; >> + >> +struct statfs { >> + __fsword_t f_type; >> + __fsword_t f_bsize; >> + fsblkcnt_t f_blocks; >> + fsblkcnt_t f_bfree; >> + fsblkcnt_t f_bavail; >> + fsfilcnt_t f_files; >> + fsfilcnt_t f_ffree; >> + fsid_t f_fsid; >> + __fsword_t f_namelen; >> + __fsword_t f_frsize; >> + __fsword_t f_flags; >> +}; >> +#endif >> + >> typedef struct FsCred >> { >> uid_t fc_uid; >> diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c >> index bf7f0b0..384d72e 100644 >> --- a/fsdev/qemu-fsdev.c >> +++ b/fsdev/qemu-fsdev.c >> @@ -26,7 +26,9 @@ static FsDriverTable FsDrivers[] = { >> { .name = "handle", .ops = &handle_ops}, >> #endif >> { .name = "synth", .ops = &synth_ops}, >> +#ifndef WIN32 >> { .name = "proxy", .ops = &proxy_ops}, >> +#endif >> }; >> >> int qemu_fsdev_add(QemuOpts *opts) >> diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c >> index 16f45f4..710ab5f 100644 >> --- a/hw/9pfs/9p-local.c >> +++ b/hw/9pfs/9p-local.c >> @@ -12,23 +12,174 @@ >> */ >> >> #include "qemu/osdep.h" >> +/* mifritscher: after killing the debug printf, kill this as well! */ >> +#include "qemu/error-report.h" >> #include "9p.h" >> -#include "9p-xattr.h" >> +#ifdef _WIN32 >> +/* idea from >> http://mingw-users.1079350.n2.nabble.com/Undefined-reference-to-quot-lstat-quot-and-quot-S-ISLNK-quot-td5450984.html >> */ >> +# define lstat(path, buffer) stat(path, buffer) >> + >> +# define mkdir(path, mode) mkdir(path) > > Maybe these definitions can go to include/sysemu/os-win32.h ? I didn't know that we have this file - in fact, I wanted to provoke a reaction on this how to handle this properly ;-) Yes, good idea. > >> +# define getxattr(buffer, name, pointer, length) 0 >> + >> +/* pretend success */ >> +static int setxattr(const char *path, const char *name, >> + const void *value, size_t size, int flags) >> +{ >> + return 0; >> +} >> + >> +static ssize_t fgetxattr(int fd, const char *name, >> + void *value, size_t size) >> +{ >> + return 0; >> +} >> + > > and these xattr definitions to include/qemu/xattr.h ? Yes - or perhaps a xattr-win32.h (I think there was some problem including xattr.h) > >> +# define lchown(buffer, uid, gid) 0 >> +# define readlink(buffer, buf, bufsz) 0 >> +# define mknod(buffer, mode, u) 0 >> +# define link(buffer, buffer1) 0 >> +# define symlink(buffer, buffer1) 0 >> + >> +static ssize_t v9fs_get_xattr(FsContext *ctx, const char *path, >> + const char *name, void *value, size_t >> size) >> +{ >> + errno = 95; /* EOPNOTSUP - wrong definition in mingw(130); */ > > This is ENOTSUP actually. Aahhh - thanks :-) > >> + return -1; >> +} >> + >> +static ssize_t v9fs_list_xattr(FsContext *ctx, const char *path, >> + void *value, size_t vsize) >> +{ >> + errno = 95; /* EOPNOTSUP - wrong definition in mingw(130); */ >> + return -1; >> +} >> + >> +static int v9fs_set_xattr(FsContext *ctx, const char *path, >> + const char *name, void *value, size_t size, >> + int flags) >> +{ >> + errno = 95; /* EOPNOTSUP - wrong definition in mingw(130); */ >> + return -1; >> +} >> + >> +static int v9fs_remove_xattr(FsContext *ctx, const char *path, >> + const char *name) >> +{ >> + errno = 95; /* EOPNOTSUP - wrong definition in mingw(130); */ >> + return -1; >> +} >> + >> +static int readdir_r(DIR *dirp, struct dirent *entry, >> + struct dirent **result) >> +{ >> + struct dirent *temp; >> + errno = 0; >> + temp = readdir(dirp); > > readdir() isn't expected to be thread safe... I believe we need some > locking here. > > Also this function should probably be in os-win32.c. @locking: Yes, I stumbled over that. Which locking mechanism do you prefer? @os-win32.c: Yes :-) > >> + if (temp == 0) { >> + error_printf("readdir_r: End of directory reached -> returning >> NULL\n"); >> + *result = 0; >> + } else { >> + /* Copy it from the stack to the buffer got from the caller */ >> + memcpy(entry, temp, sizeof(struct dirent)); >> + error_printf("readdir_r: Name: %hu %s\n", >> + temp->d_namlen, temp->d_name); >> + error_printf("readdir_r: Name: %hu %s\n", >> + entry->d_namlen, entry->d_name); >> + *result = entry; >> + } >> + return errno; >> +} >> + >> +/* Can be done better... */ >> +static int statfs(const char *file, struct statfs *buf) >> +{ >> + memset(buf, 0, sizeof(struct statfs)); >> + buf->f_type = 0x01021997; /* V9FS_MAGIC */ >> + buf->f_bsize = 4096; >> + buf->f_blocks = 4000000; >> + buf->f_bfree = 3000000; >> + buf->f_bavail = 2999000; >> + buf->f_files = 1000000; >> + buf->f_ffree = 800000; >> + buf->f_namelen = NAME_MAX; >> + return 0; >> +} >> + >> +/* a crude hash function (needed for fake inodes) */ >> +static ino_t hash(const char *path) >> +{ >> + ino_t result = (ino_t)41021998; >> + int len = strlen(path); >> + if (!len) { >> + return result; >> + } >> + >> + /* Q&D canolizement of the path */ >> + if (path[len - 1] == '\\' || path[len - 1] == '/') { >> + len--; >> + } >> + if (!len) { >> + return result; >> + } >> + >> + if (path[len - 1] == '.') { >> + if (len == 1) { >> + return result; >> + } >> + len--; >> + if (path[len - 1] == '\\' || path[len - 1] == '/') { >> + len--; >> + /* .. -> kill last part */ >> + } else if (path[len - 1] == '.') { >> + len--; >> + while (len) { >> + if (path[len - 1] == '\\' || path[len - 1] == '/') { >> + len--; >> + break; >> + } >> + len--; >> + } >> + } >> + } >> + >> + if (!len) { >> + return result; >> + } >> + >> + for (int i = 0; i < len; i++) { >> + result += path[i] << (i % 7); >> + result += path[i] << ((i + 11) % 17); >> + result += path[i] << ((i + 19) % 23); >> + } >> + >> + return result; >> +} >> + >> +#else >> +# include "9p-xattr.h" >> +#endif > > I'd prefer the missing xattr bits to be added to win32... and > if we really need different implementations, then maybe add > 9p-xattr-posix.c and 9p-xattr-win32.c... Yes. > >> #include "fsdev/qemu-fsdev.h" /* local_ops */ >> +#ifndef _WIN32 >> #include <arpa/inet.h> >> #include <pwd.h> >> #include <grp.h> >> #include <sys/socket.h> >> #include <sys/un.h> >> #include "qemu/xattr.h" >> +#endif >> #include "qemu/cutils.h" >> #include "qemu/error-report.h" >> #include <libgen.h> >> -#include <linux/fs.h> >> +#ifndef _WIN32 >> + #include <linux/fs.h> >> +#endif >> #ifdef CONFIG_LINUX_MAGIC_H >> #include <linux/magic.h> >> #endif >> +#ifndef _WIN32 >> #include <sys/ioctl.h> >> +#endif >> >> #ifndef XFS_SUPER_MAGIC >> #define XFS_SUPER_MAGIC 0x58465342 >> @@ -76,7 +227,7 @@ static FILE *local_fopen(const char *path, const char >> *mode) >> } else { >> return NULL; >> } >> - fd = open(path, flags, o_mode); >> + fd = open(path, flags | O_BINARY, o_mode); > > Why is this needed ? Because on Windows, the files are opened in textmode - which screws up line endings. Stephan Weil told me that this flag is ignored on other OSes, which open files in binary mode by default. > >> if (fd == -1) { >> return NULL; >> } >> @@ -124,10 +275,20 @@ static int local_lstat(FsContext *fs_ctx, V9fsPath >> *fs_path, struct stat *stbuf) >> char *path = fs_path->data; >> >> buffer = rpath(fs_ctx, path); >> - err = lstat(buffer, stbuf); >> + error_printf("\nrpath %s + %s -> %s\n\n", fs_ctx->fs_root, path, >> buffer); >> + err = lstat(buffer, stbuf); >> if (err) { >> goto err_out; >> } >> +#ifdef _WIN32 >> + /* This way, all files are executable >> + (MingW seems to do 777 on dirs, but 666 on files) */ >> + stbuf->st_mode |= S_IXUSR | S_IXGRP | S_IXOTH; >> + >> + /* Under WIN32 (MingW), st_ino seems to be always 2, >> + which leads to confusion */ >> + stbuf->st_ino = hash(path); >> +#endif >> if (fs_ctx->export_flags & V9FS_SM_MAPPED) { >> /* Actual credentials are part of extended attrs */ >> uid_t tmp_uid; >> @@ -162,7 +323,7 @@ static int local_create_mapped_attr_dir(FsContext >> *ctx, const char *path) >> char *attr_dir; >> char *tmp_path = g_strdup(path); >> >> - attr_dir = g_strdup_printf("%s/%s/%s", >> + attr_dir = g_strdup_printf(DELIMITER_IN_PATH2, >> ctx->fs_root, dirname(tmp_path), VIRTFS_META_DIR); >> >> err = mkdir(attr_dir, 0700); >> @@ -223,7 +384,8 @@ update_map_file: >> if (credp->fc_gid != -1) { >> gid = credp->fc_gid; >> } >> - if (credp->fc_mode != -1) { >> + /* mifritscher: is normally unsigned... */ >> + if ((int16_t)(credp->fc_mode) != -1) { >> mode = credp->fc_mode; >> } >> if (credp->fc_rdev != -1) { >> @@ -268,7 +430,8 @@ static int local_set_xattr(const char *path, FsCred >> *credp) >> return err; >> } >> } >> - if (credp->fc_mode != -1) { >> + /* mifritscher: is normally unsigned... */ >> + if ((int16_t)(credp->fc_mode) != -1) { >> uint32_t tmp_mode = cpu_to_le32(credp->fc_mode); >> err = setxattr(path, "user.virtfs.mode", &tmp_mode, >> sizeof(mode_t), 0); >> if (err) { >> @@ -323,7 +486,7 @@ static ssize_t local_readlink(FsContext *fs_ctx, >> V9fsPath *fs_path, >> (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE)) { >> int fd; >> buffer = rpath(fs_ctx, path); >> - fd = open(buffer, O_RDONLY | O_NOFOLLOW); >> + fd = open(buffer, O_RDONLY | O_NOFOLLOW | O_BINARY); >> g_free(buffer); >> if (fd == -1) { >> return -1; >> @@ -358,7 +521,8 @@ static int local_open(FsContext *ctx, V9fsPath >> *fs_path, >> char *path = fs_path->data; >> >> buffer = rpath(ctx, path); >> - fs->fd = open(buffer, flags | O_NOFOLLOW); >> + error_printf("File which should be opened: %s\n", buffer); >> + fs->fd = open(buffer, flags | O_NOFOLLOW | O_BINARY); > > I see you add O_BINARY on all open() call sites ? Does this mean we > need a helper ? I could make a helper function if you want, which wraps open() and adds O_BINARY to the flag. Where should I add this helper? > >> g_free(buffer); >> return fs->fd; >> } >> @@ -370,6 +534,7 @@ static int local_opendir(FsContext *ctx, >> char *path = fs_path->data; >> >> buffer = rpath(ctx, path); >> + error_printf("Directory (opendir) which should be opened: %s\n", >> buffer); >> fs->dir = opendir(buffer); >> g_free(buffer); >> if (!fs->dir) { >> @@ -395,17 +560,36 @@ static int local_readdir_r(FsContext *ctx, >> V9fsFidOpenState *fs, >> int ret; >> >> again: >> +#ifdef _WIN32 >> + error_printf("local_readdir_r: Directory which should be >> read:%s\n", >> + fs->dir->dd_name); >> +#endif >> ret = readdir_r(fs->dir, entry, result); >> if (ctx->export_flags & V9FS_SM_MAPPED) { >> +#ifndef _WIN32 >> entry->d_type = DT_UNKNOWN; >> +#endif >> } else if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { >> if (!ret && *result != NULL && >> !strcmp(entry->d_name, VIRTFS_META_DIR)) { >> /* skp the meta data directory */ >> goto again; >> } >> +#ifndef _WIN32 >> entry->d_type = DT_UNKNOWN; >> +#endif >> } >> + if (*result == NULL) { >> + error_printf("local_readdir_r: End of directory -> returning >> NULL\n"); >> + } else { >> +#ifdef _WIN32 >> + error_printf("local_readdir_r: Name: %hu %s\n", >> + entry->d_namlen, entry->d_name); >> +#else >> + error_printf("local_readdir_r: Name: %s\n", entry->d_name); >> +#endif >> + } >> + error_printf("local_readdir_r: return %d\n", ret); >> return ret; >> } >> >> @@ -418,10 +602,15 @@ static ssize_t local_preadv(FsContext *ctx, >> V9fsFidOpenState *fs, >> const struct iovec *iov, >> int iovcnt, off_t offset) >> { >> + error_printf("local_preadv: #iov: %u, addr: %p, #bytes: %u, offset: >> %llu\n", >> + iovcnt, iov->iov_base, iov->iov_len, offset); >> #ifdef CONFIG_PREADV >> + error_printf("local_preadv: using preadv\n"); >> return preadv(fs->fd, iov, iovcnt, offset); >> #else >> + error_printf("local_preadv: not using preadv\n"); >> int err = lseek(fs->fd, offset, SEEK_SET); >> + error_printf("local_preadv: lseek returned %d\n", err); >> if (err == -1) { >> return err; >> } else { >> @@ -491,7 +680,7 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath >> *dir_path, >> char *buffer = NULL; >> >> v9fs_string_init(&fullname); >> - v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); >> + v9fs_string_sprintf(&fullname, DELIMITER_IN_PATH, dir_path->data, >> name); >> path = fullname.data; >> >> /* Determine the security model */ >> @@ -552,7 +741,7 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath >> *dir_path, >> char *buffer = NULL; >> >> v9fs_string_init(&fullname); >> - v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); >> + v9fs_string_sprintf(&fullname, DELIMITER_IN_PATH, dir_path->data, >> name); >> path = fullname.data; >> >> /* Determine the security model */ >> @@ -610,7 +799,14 @@ static int local_fstat(FsContext *fs_ctx, int >> fid_type, >> int err, fd; >> >> if (fid_type == P9_FID_DIR) { >> + /* Don't know if that's right... >> + (on WIN32/mingw, DIR has no fd entry) */ >> +#ifdef _WIN32 >> + #warning "Could cause problems!" >> + fd = fs->fd; >> +#else >> fd = dirfd(fs->dir); >> +#endif >> } else { >> fd = fs->fd; >> } >> @@ -619,6 +815,13 @@ static int local_fstat(FsContext *fs_ctx, int >> fid_type, >> if (err) { >> return err; >> } >> +#ifdef _WIN32 >> + /* This way, all files are executable >> + (MingW seems to do 777 on dirs, but 666 on files) */ >> + stbuf->st_mode |= S_IXUSR | S_IXGRP | S_IXOTH; >> + >> + /* mifritscher: TODO: fake inode? */ >> +#endif >> if (fs_ctx->export_flags & V9FS_SM_MAPPED) { >> /* Actual credentials are part of extended attrs */ >> uid_t tmp_uid; >> @@ -661,13 +864,16 @@ static int local_open2(FsContext *fs_ctx, V9fsPath >> *dir_path, const char *name, >> flags |= O_NOFOLLOW; >> >> v9fs_string_init(&fullname); >> - v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); >> + v9fs_string_sprintf(&fullname, DELIMITER_IN_PATH, dir_path->data, >> name); >> path = fullname.data; >> >> + error_printf("local_open2: got %s %s\n", dir_path->data, name); >> + error_printf("local_open2: full path: %s\n", path); >> + >> /* Determine the security model */ >> if (fs_ctx->export_flags & V9FS_SM_MAPPED) { >> buffer = rpath(fs_ctx, path); >> - fd = open(buffer, flags, SM_LOCAL_MODE_BITS); >> + fd = open(buffer, flags | O_BINARY, SM_LOCAL_MODE_BITS); >> if (fd == -1) { >> err = fd; >> goto out; >> @@ -681,7 +887,7 @@ static int local_open2(FsContext *fs_ctx, V9fsPath >> *dir_path, const char *name, >> } >> } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { >> buffer = rpath(fs_ctx, path); >> - fd = open(buffer, flags, SM_LOCAL_MODE_BITS); >> + fd = open(buffer, flags | O_BINARY, SM_LOCAL_MODE_BITS); >> if (fd == -1) { >> err = fd; >> goto out; >> @@ -696,12 +902,17 @@ static int local_open2(FsContext *fs_ctx, V9fsPath >> *dir_path, const char *name, >> } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || >> (fs_ctx->export_flags & V9FS_SM_NONE)) { >> buffer = rpath(fs_ctx, path); >> - fd = open(buffer, flags, credp->fc_mode); >> + error_printf("local_open2: File which should be opened (open2): >> %s\n", >> + buffer); >> + fd = open(buffer, flags | O_BINARY, credp->fc_mode); >> + error_printf("local_open2: open returned %d\n", fd); >> if (fd == -1) { >> err = fd; >> goto out; >> } >> err = local_post_create_passthrough(fs_ctx, path, credp); >> + error_printf("local_open2: local_post_create_passthrough >> returned %u\n", >> + err); >> if (err == -1) { >> serrno = errno; >> goto err_end; >> @@ -732,7 +943,7 @@ static int local_symlink(FsContext *fs_ctx, const >> char *oldpath, >> char *buffer = NULL; >> >> v9fs_string_init(&fullname); >> - v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); >> + v9fs_string_sprintf(&fullname, DELIMITER_IN_PATH, dir_path->data, >> name); >> newpath = fullname.data; >> >> /* Determine the security model */ >> @@ -740,7 +951,9 @@ static int local_symlink(FsContext *fs_ctx, const >> char *oldpath, >> int fd; >> ssize_t oldpath_size, write_size; >> buffer = rpath(fs_ctx, newpath); >> - fd = open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, >> SM_LOCAL_MODE_BITS); >> + fd = open(buffer, >> + O_CREAT | O_EXCL | O_RDWR | O_NOFOLLOW | O_BINARY, >> + SM_LOCAL_MODE_BITS); >> if (fd == -1) { >> err = fd; >> goto out; >> @@ -758,8 +971,10 @@ static int local_symlink(FsContext *fs_ctx, const >> char *oldpath, >> goto err_end; >> } >> close(fd); >> - /* Set cleint credentials in symlink's xattr */ >> + /* Set client credentials in symlink's xattr */ >> +#ifndef _WIN32 >> credp->fc_mode = credp->fc_mode|S_IFLNK; >> +#endif >> err = local_set_xattr(buffer, credp); >> if (err == -1) { >> serrno = errno; >> @@ -769,7 +984,9 @@ static int local_symlink(FsContext *fs_ctx, const >> char *oldpath, >> int fd; >> ssize_t oldpath_size, write_size; >> buffer = rpath(fs_ctx, newpath); >> - fd = open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, >> SM_LOCAL_MODE_BITS); >> + fd = open(buffer, >> + O_CREAT | O_EXCL | O_RDWR | O_NOFOLLOW | O_BINARY, >> + SM_LOCAL_MODE_BITS); >> if (fd == -1) { >> err = fd; >> goto out; >> @@ -788,7 +1005,9 @@ static int local_symlink(FsContext *fs_ctx, const >> char *oldpath, >> } >> close(fd); >> /* Set cleint credentials in symlink's xattr */ >> +#ifndef _WIN32 >> credp->fc_mode = credp->fc_mode|S_IFLNK; >> +#endif >> err = local_set_mapped_file_attr(fs_ctx, newpath, credp); >> if (err == -1) { >> serrno = errno; >> @@ -833,7 +1052,7 @@ static int local_link(FsContext *ctx, V9fsPath >> *oldpath, >> char *buffer, *buffer1; >> >> v9fs_string_init(&newpath); >> - v9fs_string_sprintf(&newpath, "%s/%s", dirpath->data, name); >> + v9fs_string_sprintf(&newpath, DELIMITER_IN_PATH, dirpath->data, >> name); >> >> buffer = rpath(ctx, oldpath->data); >> buffer1 = rpath(ctx, newpath.data); >> @@ -934,7 +1153,12 @@ static int local_utimensat(FsContext *s, V9fsPath >> *fs_path, >> char *path = fs_path->data; >> >> buffer = rpath(s, path); >> +#ifdef _WIN32 >> + #warning "Could cause problems!" >> + ret = 0; >> +#else >> ret = qemu_utimens(buffer, buf); >> +#endif >> g_free(buffer); >> return ret; >> } >> @@ -949,6 +1173,7 @@ static int local_remove(FsContext *ctx, const char >> *path) >> buffer = rpath(ctx, path); >> err = lstat(buffer, &stbuf); >> g_free(buffer); >> + error_printf("local_remove: stat %d %d\n", err, errno); >> if (err) { >> goto err_out; >> } >> @@ -957,10 +1182,12 @@ static int local_remove(FsContext *ctx, const >> char *path) >> * directory >> */ >> if (S_ISDIR(stbuf.st_mode)) { >> - buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root, >> + buffer = g_strdup_printf(DELIMITER_IN_PATH2, ctx->fs_root, >> path, VIRTFS_META_DIR); >> err = remove(buffer); >> g_free(buffer); >> + error_printf("local_remove: .virtfs_metdata remove %d >> %d\n", >> + err, errno); >> if (err < 0 && errno != ENOENT) { >> /* >> * We didn't had the .virtfs_metadata file. May be file >> created >> @@ -976,6 +1203,8 @@ static int local_remove(FsContext *ctx, const char >> *path) >> buffer = local_mapped_attr_path(ctx, path); >> err = remove(buffer); >> g_free(buffer); >> + error_printf("local_remove: local_mapped_attr_path remove %d >> %d\n", >> + err, errno); >> if (err < 0 && errno != ENOENT) { >> /* >> * We didn't had the .virtfs_metadata file. May be file >> created >> @@ -986,7 +1215,14 @@ static int local_remove(FsContext *ctx, const char >> *path) >> } >> >> buffer = rpath(ctx, path); >> - err = remove(buffer); >> + /* mifritscher: posix remove can delete directories as well, >> windows not */ >> + if (S_ISDIR(stbuf.st_mode)) { >> + err = rmdir(buffer); >> + } else { >> + err = remove(buffer); >> + } >> + error_printf("local_remove: final remove %d %d\n", >> + err, errno); >> g_free(buffer); >> err_out: >> return err; >> @@ -998,7 +1234,12 @@ static int local_fsync(FsContext *ctx, int >> fid_type, >> int fd; >> >> if (fid_type == P9_FID_DIR) { >> +#ifdef _WIN32 >> + #warning "Could cause problems!" >> + fd = fs->fd; >> +#else >> fd = dirfd(fs->dir); >> +#endif >> } else { >> fd = fs->fd; >> } >> @@ -1058,10 +1299,14 @@ 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", >> + v9fs_string_sprintf((V9fsString *)target, DELIMITER_IN_PATH, >> dir_path->data, name); >> + error_printf("local_name_to_path: "); >> + error_printf(DELIMITER_IN_PATH, dir_path->data, name); >> + error_printf("\n"); >> } else { >> v9fs_string_sprintf((V9fsString *)target, "%s", name); >> + error_printf("local_name_to_path: %s\n", name); >> } >> /* Bump the size for including terminating NULL */ >> target->size++; >> @@ -1078,8 +1323,10 @@ static int local_renameat(FsContext *ctx, >> V9fsPath *olddir, >> 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); >> + v9fs_string_sprintf(&old_full_name, >> + DELIMITER_IN_PATH, olddir->data, old_name); >> + v9fs_string_sprintf(&new_full_name, >> + DELIMITER_IN_PATH, newdir->data, new_name); >> >> ret = local_rename(ctx, old_full_name.data, new_full_name.data); >> v9fs_string_free(&old_full_name); >> @@ -1096,17 +1343,19 @@ static int local_unlinkat(FsContext *ctx, >> V9fsPath *dir, >> >> v9fs_string_init(&fullname); >> >> - v9fs_string_sprintf(&fullname, "%s/%s", dir->data, name); >> + v9fs_string_sprintf(&fullname, DELIMITER_IN_PATH, dir->data, name); >> if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { >> if (flags == AT_REMOVEDIR) { >> /* >> * If directory remove .virtfs_metadata contained in the >> * directory >> */ >> - buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root, >> + buffer = g_strdup_printf(DELIMITER_IN_PATH2, ctx->fs_root, >> fullname.data, VIRTFS_META_DIR); >> ret = remove(buffer); >> g_free(buffer); >> + error_printf("local_unlinkat: .virtfs_metadata %d %d\n", >> + ret, errno); >> if (ret < 0 && errno != ENOENT) { >> /* >> * We didn't had the .virtfs_metadata file. May be file >> created >> @@ -1121,6 +1370,8 @@ static int local_unlinkat(FsContext *ctx, V9fsPath >> *dir, >> */ >> buffer = local_mapped_attr_path(ctx, fullname.data); >> ret = remove(buffer); >> + error_printf("local_unlinkat: local_mapped_attr_path %d %d\n", >> + ret, errno); >> g_free(buffer); >> if (ret < 0 && errno != ENOENT) { >> /* >> @@ -1133,6 +1384,19 @@ static int local_unlinkat(FsContext *ctx, >> V9fsPath *dir, >> /* Remove the name finally */ >> buffer = rpath(ctx, fullname.data); >> ret = remove(buffer); >> + error_printf("local_unlinkat: final |%s| %d %d\n", buffer, ret, >> errno); >> + /* extension for MingW: remove or Windows can't handle >> directories... */ >> +#ifdef _WIN32 >> + /* mifritscher: Try to delete it as directory >> + (AT_REMOVEDIR doesn't seem to be set in this case >> + (testcase: rmdir from Linux)) */ >> + if (ret < 0) { >> + ret = rmdir(buffer); >> + error_printf("local_unlinkat: final rmdir |%s| %d %d\n", >> + buffer, ret, errno); >> + >> + } >> +#endif >> g_free(buffer); >> >> err_out: >> @@ -1140,6 +1404,7 @@ err_out: >> return ret; >> } >> >> +#ifndef _WIN32 >> static int local_ioc_getversion(FsContext *ctx, V9fsPath *path, >> mode_t st_mode, uint64_t *st_gen) >> { >> @@ -1167,12 +1432,18 @@ static int local_ioc_getversion(FsContext *ctx, >> V9fsPath *path, >> return -1; >> #endif >> } >> +#endif >> >> static int local_init(FsContext *ctx) >> { >> int err = 0; >> +#ifdef FS_IOC_GETVERSION >> struct statfs stbuf; >> +#endif >> >> +#ifdef _WIN32 >> + ctx->xops = 0; >> +#else >> if (ctx->export_flags & V9FS_SM_PASSTHROUGH) { >> ctx->xops = passthrough_xattr_ops; >> } else if (ctx->export_flags & V9FS_SM_MAPPED) { >> @@ -1186,6 +1457,7 @@ static int local_init(FsContext *ctx) >> */ >> ctx->xops = passthrough_xattr_ops; >> } >> +#endif >> ctx->export_flags |= V9FS_PATHNAME_FSCONTEXT; >> #ifdef FS_IOC_GETVERSION >> /* >> diff --git a/hw/9pfs/9p-synth.c b/hw/9pfs/9p-synth.c >> index f1475df..8355722 100644 >> --- a/hw/9pfs/9p-synth.c >> +++ b/hw/9pfs/9p-synth.c >> @@ -15,7 +15,9 @@ >> #include "qemu/osdep.h" >> #include "hw/virtio/virtio.h" >> #include "9p.h" >> -#include "9p-xattr.h" >> +#ifndef _WIN32 >> + #include "9p-xattr.h" >> +#endif >> #include "fsdev/qemu-fsdev.h" >> #include "9p-synth.h" >> #include "qemu/rcu.h" >> @@ -152,8 +154,10 @@ static void v9fs_synth_fill_statbuf(V9fsSynthNode >> *node, struct stat *stbuf) >> stbuf->st_gid = 0; >> stbuf->st_rdev = 0; >> stbuf->st_size = 0; >> +#ifndef _WIN32 >> stbuf->st_blksize = 0; >> stbuf->st_blocks = 0; >> +#endif >> stbuf->st_atime = 0; >> stbuf->st_mtime = 0; >> stbuf->st_ctime = 0; >> @@ -222,7 +226,11 @@ static void v9fs_synth_direntry(V9fsSynthNode >> *node, >> { >> strcpy(entry->d_name, node->name); >> entry->d_ino = node->attr->inode; >> +#ifdef _WIN32 >> + #warning "Can cause problems!" >> +#else >> entry->d_off = off + 1; >> +#endif >> } >> >> static int v9fs_synth_get_dentry(V9fsSynthNode *dir, struct dirent >> *entry, >> diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c >> index f5e3012..7980f33 100644 >> --- a/hw/9pfs/9p.c >> +++ b/hw/9pfs/9p.c >> @@ -20,7 +20,21 @@ >> #include "qemu/sockets.h" >> #include "virtio-9p.h" >> #include "fsdev/qemu-fsdev.h" >> -#include "9p-xattr.h" >> +#ifdef _WIN32 >> +/* taken from linux/kdev_t.h */ >> +# define MINORBITS 20 >> +# define MINORMASK ((1U << MINORBITS) - 1) >> + >> +# define major(dev) ((unsigned int) ((dev) >> MINORBITS)) >> +# define minor(dev) ((unsigned int) ((dev) & MINORMASK)) >> +# define makedev(ma, mi) (((ma) << MINORBITS) | (mi)) >> + >> +/* taken from linux/include/linux/stat.h */ >> +# define UTIME_NOW ((1l << 30) - 1l) >> +# define UTIME_OMIT ((1l << 30) - 2l) >> +#else >> +# include "9p-xattr.h" >> +#endif >> #include "coth.h" >> #include "trace.h" >> #include "migration/migration.h" >> @@ -576,9 +590,11 @@ static void stat_to_qid(const struct stat *stbuf, >> V9fsQID *qidp) >> if (S_ISDIR(stbuf->st_mode)) { >> qidp->type |= P9_QID_TYPE_DIR; >> } >> - if (S_ISLNK(stbuf->st_mode)) { >> - qidp->type |= P9_QID_TYPE_SYMLINK; >> - } >> + #ifndef _WIN32 >> + if (S_ISLNK(stbuf->st_mode)) { >> + qidp->type |= P9_QID_TYPE_SYMLINK; >> + } >> + #endif >> } >> >> static int fid_to_qid(V9fsPDU *pdu, V9fsFidState *fidp, V9fsQID *qidp) >> @@ -677,12 +693,15 @@ static mode_t v9mode_to_mode(uint32_t mode, >> V9fsString *extension) >> ret |= S_IFDIR; >> } >> >> +#ifndef _WIN32 >> if (mode & P9_STAT_MODE_SYMLINK) { >> ret |= S_IFLNK; >> } >> if (mode & P9_STAT_MODE_SOCKET) { >> ret |= S_IFSOCK; >> } >> +#endif >> + >> if (mode & P9_STAT_MODE_NAMED_PIPE) { >> ret |= S_IFIFO; >> } >> @@ -698,6 +717,7 @@ static mode_t v9mode_to_mode(uint32_t mode, >> V9fsString *extension) >> ret |= S_IFREG; >> } >> >> +#ifndef _WIN32 >> if (mode & P9_STAT_MODE_SETUID) { >> ret |= S_ISUID; >> } >> @@ -707,6 +727,7 @@ static mode_t v9mode_to_mode(uint32_t mode, >> V9fsString *extension) >> if (mode & P9_STAT_MODE_SETVTX) { >> ret |= S_ISVTX; >> } >> +#endif >> >> return ret; >> } >> @@ -762,6 +783,7 @@ static uint32_t stat_to_v9mode(const struct stat >> *stbuf) >> mode |= P9_STAT_MODE_DIR; >> } >> >> +#ifndef _WIN32 >> if (S_ISLNK(stbuf->st_mode)) { >> mode |= P9_STAT_MODE_SYMLINK; >> } >> @@ -769,6 +791,7 @@ static uint32_t stat_to_v9mode(const struct stat >> *stbuf) >> if (S_ISSOCK(stbuf->st_mode)) { >> mode |= P9_STAT_MODE_SOCKET; >> } >> +#endif >> >> if (S_ISFIFO(stbuf->st_mode)) { >> mode |= P9_STAT_MODE_NAMED_PIPE; >> @@ -778,6 +801,7 @@ static uint32_t stat_to_v9mode(const struct stat >> *stbuf) >> mode |= P9_STAT_MODE_DEVICE; >> } >> >> +#ifndef _WIN32 >> if (stbuf->st_mode & S_ISUID) { >> mode |= P9_STAT_MODE_SETUID; >> } >> @@ -789,6 +813,7 @@ static uint32_t stat_to_v9mode(const struct stat >> *stbuf) >> if (stbuf->st_mode & S_ISVTX) { >> mode |= P9_STAT_MODE_SETVTX; >> } >> +#endif >> >> return mode; >> } >> @@ -881,14 +906,34 @@ static void stat_to_v9stat_dotl(V9fsState *s, >> const struct stat *stbuf, >> v9lstat->st_gid = stbuf->st_gid; >> v9lstat->st_rdev = stbuf->st_rdev; >> v9lstat->st_size = stbuf->st_size; >> +#ifdef _WIN32 >> + /* Blksize is the optimal EA-block, >> + while blocks always refers to 512 blocks >> + */ >> + v9lstat->st_blksize = 4096; >> + v9lstat->st_blocks = ((stbuf->st_size + 1) / 512) + 1; >> +#else >> v9lstat->st_blksize = stbuf->st_blksize; >> v9lstat->st_blocks = stbuf->st_blocks; >> +#endif >> v9lstat->st_atime_sec = stbuf->st_atime; >> +#ifdef _WIN32 >> + v9lstat->st_atime_nsec = 0; >> +#else >> v9lstat->st_atime_nsec = stbuf->st_atim.tv_nsec; >> +#endif >> v9lstat->st_mtime_sec = stbuf->st_mtime; >> +#ifdef _WIN32 >> + v9lstat->st_mtime_nsec = 0; >> +#else >> v9lstat->st_mtime_nsec = stbuf->st_mtim.tv_nsec; >> +#endif >> v9lstat->st_ctime_sec = stbuf->st_ctime; >> +#ifdef _WIN32 >> + v9lstat->st_ctime_nsec = 0; >> +#else >> v9lstat->st_ctime_nsec = stbuf->st_ctim.tv_nsec; >> +#endif >> /* Currently we only support BASIC fields in stat */ >> v9lstat->st_result_mask = P9_STATS_BASIC; >> >> @@ -1639,7 +1684,10 @@ static int v9fs_do_readdir_with_stat(V9fsPDU >> *pdu, >> v9fs_path_init(&path); >> err = v9fs_co_readdir_r(pdu, fidp, dent, &result); >> if (err || !result) { >> + error_printf("v9fs_do_readdir_with_stat: exiting...\n"); >> break; >> + } else { >> + error_printf("v9fs_do_readdir_with_stat: continue\n"); >> } >> err = v9fs_co_name_to_path(pdu, &fidp->path, dent->d_name, >> &path); >> if (err < 0) { >> @@ -1666,7 +1714,12 @@ static int v9fs_do_readdir_with_stat(V9fsPDU >> *pdu, >> count += len; >> v9fs_stat_free(&v9stat); >> v9fs_path_free(&path); >> +#ifdef _WIN32 >> + #warning "Probably right, but could make problems!" >> + saved_dir_pos = v9fs_co_telldir(pdu, fidp); >> +#else >> saved_dir_pos = dent->d_off; >> +#endif >> } >> out: >> g_free(dent); >> @@ -1806,6 +1859,9 @@ static int v9fs_do_readdir(V9fsPDU *pdu, >> int32_t count = 0; >> off_t saved_dir_pos; >> struct dirent *dent, *result; >> +#ifdef _WIN32 >> + uint8_t type = 0; /* DT_UNKNOWN */ >> +#endif >> >> /* save the directory position */ >> saved_dir_pos = v9fs_co_telldir(pdu, fidp); >> @@ -1818,15 +1874,27 @@ static int v9fs_do_readdir(V9fsPDU *pdu, >> while (1) { >> err = v9fs_co_readdir_r(pdu, fidp, dent, &result); >> if (err || !result) { >> + error_printf("v9fs_do_readdir: exiting...\n"); >> break; >> + } else { >> + error_printf("v9fs_do_readdir: continue\n"); >> } >> v9fs_string_init(&name); >> + if (!dent->d_name) { >> + error_printf("\ndent->d_name is NULL!\n"); >> + break; >> + } else { >> + error_printf("v9fs_do_readdir: entry is named %s, strlen >> %u\n", >> + dent->d_name, strlen(dent->d_name)); >> + } >> v9fs_string_sprintf(&name, "%s", dent->d_name); >> if ((count + v9fs_readdir_data_size(&name)) > max_count) { >> /* Ran out of buffer. Set dir back to old position and >> return */ >> v9fs_co_seekdir(pdu, fidp, saved_dir_pos); >> v9fs_string_free(&name); >> g_free(dent); >> + error_printf("v9fs_do_readdir: RAN OUT OF BUFFER return >> %d\n\n", >> + count); >> return count; >> } >> /* >> @@ -1841,9 +1909,16 @@ static int v9fs_do_readdir(V9fsPDU *pdu, >> qid.version = 0; >> >> /* 11 = 7 + 4 (7 = start offset, 4 = space for storing count) >> */ >> +#ifdef _WIN32 >> + #warning "Probably right, but could make problems!" >> + len = pdu_marshal(pdu, 11 + count, "Qqbs", >> + &qid, v9fs_co_telldir(pdu, fidp), >> + type, &name); >> +#else >> len = pdu_marshal(pdu, 11 + count, "Qqbs", >> &qid, dent->d_off, >> dent->d_type, &name); >> +#endif >> if (len < 0) { >> v9fs_co_seekdir(pdu, fidp, saved_dir_pos); >> v9fs_string_free(&name); >> @@ -1852,12 +1927,18 @@ static int v9fs_do_readdir(V9fsPDU *pdu, >> } >> count += len; >> v9fs_string_free(&name); >> +#ifdef _WIN32 >> + #warning "Probably right, but could make problems!" >> + saved_dir_pos = v9fs_co_telldir(pdu, fidp); >> +#else >> saved_dir_pos = dent->d_off; >> +#endif >> } >> g_free(dent); >> if (err < 0) { >> return err; >> } >> + error_printf("v9fs_do_readdir: return %d\n\n", count); >> return count; >> } >> >> @@ -1878,6 +1959,8 @@ static void v9fs_readdir(void *opaque) >> goto out_nofid; >> } >> trace_v9fs_readdir(pdu->tag, pdu->id, fid, initial_offset, >> max_count); >> + error_printf("v9fs_readdir initial: %llu max count: %u\n", >> + initial_offset, max_count); >> >> fidp = get_fid(pdu, fid); >> if (fidp == NULL) { >> @@ -1904,10 +1987,13 @@ static void v9fs_readdir(void *opaque) >> } >> retval += count + offset; >> trace_v9fs_readdir_return(pdu->tag, pdu->id, count, retval); >> + error_printf("v9fs_readdir: count: %d retval: %d\n\n", count, >> retval); >> out: >> put_fid(pdu, fidp); >> out_nofid: >> pdu_complete(pdu, retval); >> + >> + error_printf("v9fs_readdir: return\n"); >> } >> >> static int v9fs_xattr_write(V9fsState *s, V9fsPDU *pdu, V9fsFidState >> *fidp, >> @@ -2166,8 +2252,12 @@ static void v9fs_create(void *opaque) >> } >> v9fs_path_copy(&fidp->path, &path); >> } else if (perm & P9_STAT_MODE_SOCKET) { >> +#ifdef _WIN32 >> + err = -1; >> +#else >> err = v9fs_co_mknod(pdu, fidp, &name, fidp->uid, -1, >> 0, S_IFSOCK | (perm & 0777), &stbuf); >> +#endif >> if (err < 0) { >> goto out; >> } >> @@ -3338,7 +3428,7 @@ int v9fs_device_realize_common(V9fsState *s, Error >> **errp) >> * call back to do that. Since we are in the init path, we don't >> * use co-routines here. >> */ >> - if (s->ops->name_to_path(&s->ctx, NULL, "/", &path) < 0) { >> + if (s->ops->name_to_path(&s->ctx, NULL, DELIMITER_STRING, &path) < >> 0) { >> error_setg(errp, >> "error in converting name to path %s", >> strerror(errno)); >> goto out; >> @@ -3370,6 +3460,7 @@ void v9fs_device_unrealize_common(V9fsState *s, >> Error **errp) >> >> static void __attribute__((__constructor__)) v9fs_set_fd_limit(void) >> { >> +#ifndef _WIN32 >> struct rlimit rlim; >> if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) { >> error_report("Failed to get the resource limit"); >> @@ -3377,4 +3468,5 @@ static void __attribute__((__constructor__)) >> v9fs_set_fd_limit(void) >> } >> open_fd_hw = rlim.rlim_cur - MIN(400, rlim.rlim_cur/3); >> open_fd_rc = rlim.rlim_cur/2; >> +#endif >> } >> diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h >> index 1a19418..7bc8863 100644 >> --- a/hw/9pfs/9p.h >> +++ b/hw/9pfs/9p.h >> @@ -3,7 +3,29 @@ >> >> #include <dirent.h> >> #include <utime.h> >> -#include <sys/resource.h> >> +#ifdef _WIN32 >> +/* Bad workaround, from http://octave.org/doxygen/3.4/fcntl_8h.html */ >> +# define O_NOCTTY 0 >> +# define O_NDELAY 0 >> +# define O_NONBLOCK O_NDELAY >> +# define O_DSYNC 0 >> +# define O_DIRECT 0 >> +# define O_DIRECTORY 0 >> +# define O_NOFOLLOW 0 >> +# define O_NOATIME 0 >> +# define O_SYNC 0 >> +# define O_ASYNC 0 >> + >> +# define FASYNC 0 >> + >> +# define AT_REMOVEDIR 1 >> + >> +# define NAME_MAX 260 >> + >> +#else >> +# include <sys/resource.h> >> +#endif >> + >> #include <glib.h> >> #include "standard-headers/linux/virtio_9p.h" >> #include "hw/virtio/virtio.h" >> @@ -12,6 +34,10 @@ >> #include "qemu/thread.h" >> #include "qemu/coroutine.h" >> >> +#define DELIMITER_STRING "/" >> +#define DELIMITER_IN_PATH "%s/%s" >> +#define DELIMITER_IN_PATH2 "%s/%s/%s" >> + > > Is this really needed (will there be different values for > win32) ? If yes, I guess DELEMITER_STRING should be defined > in a host arch specific header ? And anyway, this should be > pushed to a separate patch. I didn't like the spreading of this strings everywhere, so I defined these constants. Yes, in the first step I thought I need them to be host OS specific, but it turned out there is a better way. > >> enum { >> P9_TLERROR = 6, >> P9_RLERROR, >> @@ -108,9 +134,49 @@ enum p9_proto_version { >> >> #define FID_REFERENCED 0x1 >> #define FID_NON_RECLAIMABLE 0x2 >> + >> +/* combines the host's root dir and the path to a complete host path */ >> static inline char *rpath(FsContext *ctx, const char *path) >> { >> - return g_strdup_printf("%s/%s", ctx->fs_root, path); >> + char *result; >> + result = g_strdup_printf(DELIMITER_IN_PATH, ctx->fs_root, path); >> +#ifdef _WIN32 >> + int input = 0; >> + int output = 0; >> + while (result[input]) { >> + /* error_printf("<-%d %c\n", input, result[input]); */ >> + if (result[input] == '/') { >> + result[output] = '\\'; >> + /* remove duplicate \... */ > > Why do we need to remove duplicate \ ? The other code relies that the host OS ignores dupplicate \ - they occured in several places, e.g. when connecting the base (host) path and the path given by the guest. Without remove them Windows bails out. > >> + if (output > 0 && result[output - 1] == '\\') { >> + /* error_printf("remove duplicate \\\n"); */ >> + output--; >> + } else { >> + result[output] = '\\'; >> + } >> + /* error_printf(" %c\n", result[output]); */ >> + } else { >> + result[output] = result[input]; >> + } >> + /* error_printf("->%d %c\n\n", output, result[output]); */ >> + input++; >> + output++; >> + } >> + /* Kill last \ (but leave it if the char before is a : ...) > > Why kill last \ ? Same reason as above ;-) > >> + So: >> + C:\ -> C:\ >> + C:\blah\ -> C:\blah >> + b\ -> b >> + blah\ -> blah */ >> + if (output > 1 && result[output - 1] == '\\' >> + && (output == 1 || result[output - 2] != ':')) { >> + /* error_printf("Killed last \\\n"); */ >> + result[output - 1] = '\0'; >> + } else { >> + result[output] = '\0'; >> + } >> +#endif > > I understand we need to convert / to \, but I don't see why > we should remove duplicates... and anyway, this should be > moved to a fixup helper. Where should I move the function to? > >> + return result; >> } >> >> /* >> diff --git a/hw/9pfs/Makefile.objs b/hw/9pfs/Makefile.objs >> index da0ae0c..6f6ed19 100644 >> --- a/hw/9pfs/Makefile.objs >> +++ b/hw/9pfs/Makefile.objs >> @@ -1,9 +1,10 @@ >> common-obj-y = 9p.o >> -common-obj-y += 9p-local.o 9p-xattr.o >> -common-obj-y += 9p-xattr-user.o 9p-posix-acl.o >> +common-obj-$(CONFIG_LINUX) += 9p-local.o 9p-xattr.o >> +common-obj-$(CONFIG_LINUX) += 9p-xattr-user.o 9p-posix-acl.o >> +common-obj-$(CONFIG_WIN32) += 9p-local.o >> common-obj-y += coth.o cofs.o codir.o cofile.o >> common-obj-y += coxattr.o 9p-synth.o >> common-obj-$(CONFIG_OPEN_BY_HANDLE) += 9p-handle.o >> -common-obj-y += 9p-proxy.o >> +common-obj-$(CONFIG_POSIX) += 9p-proxy.o >> >> obj-y += virtio-9p-device.o >> diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c >> index 91df7f7..399bd8a 100644 >> --- a/hw/9pfs/codir.c >> +++ b/hw/9pfs/codir.c >> @@ -17,6 +17,8 @@ >> #include "qemu/thread.h" >> #include "qemu/coroutine.h" >> #include "coth.h" >> +/* mifritscher: after killing the debug printf, kill this as well! */ >> +#include "qemu/error-report.h" >> >> int v9fs_co_readdir_r(V9fsPDU *pdu, V9fsFidState *fidp, struct dirent >> *dent, >> struct dirent **result) >> @@ -37,6 +39,12 @@ int v9fs_co_readdir_r(V9fsPDU *pdu, V9fsFidState >> *fidp, struct dirent *dent, >> err = 0; >> } >> }); >> +#ifdef _WIN32 >> + error_printf("v9fs_co_readdir_r: %s %d %p\n", >> + (&fidp->fs)->dir->dd_name, err, *result); >> +#else >> + error_printf("v9fs_co_readdir_r: %d %p\n", err, *result); >> +#endif >> return err; >> } >> >> @@ -55,6 +63,12 @@ off_t v9fs_co_telldir(V9fsPDU *pdu, V9fsFidState >> *fidp) >> err = -errno; >> } >> }); >> +#ifdef _WIN32 >> + error_printf("v9fs_co_telldir_r: %s %lld\n", >> + (&fidp->fs)->dir->dd_name, err); >> +#else >> + error_printf("v9fs_co_telldir_r: %ld\n", err); >> +#endif >> return err; >> } >> >> @@ -68,6 +82,11 @@ void v9fs_co_seekdir(V9fsPDU *pdu, V9fsFidState >> *fidp, off_t offset) >> { >> s->ops->seekdir(&s->ctx, &fidp->fs, offset); >> }); >> +#ifdef _WIN32 >> + error_printf("v9fs_co_seekdir: %s\n", (&fidp->fs)->dir->dd_name); >> +#else >> + error_printf("v9fs_co_seekdir\n"); >> +#endif >> } >> >> void v9fs_co_rewinddir(V9fsPDU *pdu, V9fsFidState *fidp) >> @@ -80,6 +99,11 @@ void v9fs_co_rewinddir(V9fsPDU *pdu, V9fsFidState >> *fidp) >> { >> s->ops->rewinddir(&s->ctx, &fidp->fs); >> }); >> +#ifdef _WIN32 >> + error_printf("v9fs_co_rewinddir: %s\n", (&fidp->fs)->dir->dd_name); >> +#else >> + error_printf("v9fs_co_rewinddir\n"); >> +#endif >> } >> >> int v9fs_co_mkdir(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name, >> @@ -116,6 +140,7 @@ int v9fs_co_mkdir(V9fsPDU *pdu, V9fsFidState *fidp, >> V9fsString *name, >> } >> }); >> v9fs_path_unlock(s); >> + error_printf("v9fs_co_mkdir: %d\n", err); >> return err; >> } >> >> @@ -144,6 +169,11 @@ int v9fs_co_opendir(V9fsPDU *pdu, V9fsFidState >> *fidp) >> v9fs_reclaim_fd(pdu); >> } >> } >> +#ifdef _WIN32 >> + error_printf("v9fs_co_opendir: %s %d\n", (&fidp->fs)->dir->dd_name, >> err); >> +#else >> + error_printf("v9fs_co_opendir: %d\n", err); >> +#endif >> return err; >> } >> >> @@ -165,5 +195,6 @@ int v9fs_co_closedir(V9fsPDU *pdu, V9fsFidOpenState >> *fs) >> if (!err) { >> total_open_fd--; >> } >> + error_printf("v9fs_co_closedir: %d\n", err); >> return err; >> } >> diff --git a/hw/9pfs/cofile.c b/hw/9pfs/cofile.c >> index 293483e..a9c1a10 100644 >> --- a/hw/9pfs/cofile.c >> +++ b/hw/9pfs/cofile.c >> @@ -17,6 +17,8 @@ >> #include "qemu/thread.h" >> #include "qemu/coroutine.h" >> #include "coth.h" >> +/* mifritscher: after killing the debug printf, kill this as well! */ >> +#include "qemu/error-report.h" >> >> int v9fs_co_st_gen(V9fsPDU *pdu, V9fsPath *path, mode_t st_mode, >> V9fsStatDotl *v9stat) >> @@ -39,6 +41,7 @@ int v9fs_co_st_gen(V9fsPDU *pdu, V9fsPath *path, >> mode_t st_mode, >> }); >> v9fs_path_unlock(s); >> } >> + error_printf("v9fs_co_st_gen: %d\n", err); >> return err; >> } >> >> @@ -59,6 +62,7 @@ int v9fs_co_lstat(V9fsPDU *pdu, V9fsPath *path, struct >> stat *stbuf) >> } >> }); >> v9fs_path_unlock(s); >> + error_printf("v9fs_co_lstat: %d\n", err); >> return err; >> } >> >> @@ -91,6 +95,7 @@ int v9fs_co_fstat(V9fsPDU *pdu, V9fsFidState *fidp, >> struct stat *stbuf) >> err = 0; >> } >> } >> + error_printf("v9fs_co_fstat: %s %d\n", (&fidp->path)->data, err); >> return err; >> } >> >> @@ -119,6 +124,7 @@ int v9fs_co_open(V9fsPDU *pdu, V9fsFidState *fidp, >> int flags) >> v9fs_reclaim_fd(pdu); >> } >> } >> + error_printf("v9fs_co_open: %s %d\n", (&fidp->path)->data, err); >> return err; >> } >> >> @@ -147,13 +153,17 @@ int v9fs_co_open2(V9fsPDU *pdu, V9fsFidState >> *fidp, V9fsString *name, gid_t gid, >> { >> err = s->ops->open2(&s->ctx, &fidp->path, >> name->data, flags, &cred, &fidp->fs); >> + error_printf("v9fs_co_open2: open returned %d\n", err); >> if (err < 0) { >> err = -errno; >> } else { >> v9fs_path_init(&path); >> err = v9fs_name_to_path(s, &fidp->path, name->data, >> &path); >> + error_printf("v9fs_co_open2: v9fs_name_to_path returned >> %d\n", >> + err); >> if (!err) { >> err = s->ops->lstat(&s->ctx, &path, stbuf); >> + error_printf("v9fs_co_open2: lstat returned %d\n", >> err); >> if (err < 0) { >> err = -errno; >> s->ops->close(&s->ctx, &fidp->fs); >> @@ -173,6 +183,7 @@ int v9fs_co_open2(V9fsPDU *pdu, V9fsFidState *fidp, >> V9fsString *name, gid_t gid, >> v9fs_reclaim_fd(pdu); >> } >> } >> + error_printf("v9fs_co_open2: %s %d\n", (&fidp->path)->data, err); >> return err; >> } >> >> @@ -194,6 +205,7 @@ int v9fs_co_close(V9fsPDU *pdu, V9fsFidOpenState >> *fs) >> if (!err) { >> total_open_fd--; >> } >> + error_printf("v9fs_co_close: %d\n", err); >> return err; >> } >> >> @@ -234,6 +246,7 @@ int v9fs_co_link(V9fsPDU *pdu, V9fsFidState *oldfid, >> } >> }); >> v9fs_path_unlock(s); >> + error_printf("v9fs_co_link: %d\n", err); >> return err; >> } >> >> @@ -253,6 +266,7 @@ int v9fs_co_pwritev(V9fsPDU *pdu, V9fsFidState >> *fidp, >> err = -errno; >> } >> }); >> + error_printf("v9fs_co_pwritev: %s %d\n", (&fidp->path)->data, err); >> return err; >> } >> >> @@ -272,5 +286,6 @@ int v9fs_co_preadv(V9fsPDU *pdu, V9fsFidState *fidp, >> err = -errno; >> } >> }); >> + error_printf("v9fs_co_preadv: %s %d\n", (&fidp->path)->data, err); >> return err; >> } >> diff --git a/hw/9pfs/cofs.c b/hw/9pfs/cofs.c >> index 18c81cb..a3a42bf 100644 >> --- a/hw/9pfs/cofs.c >> +++ b/hw/9pfs/cofs.c >> @@ -17,6 +17,8 @@ >> #include "qemu/thread.h" >> #include "qemu/coroutine.h" >> #include "coth.h" >> +/* mifritscher: after killing the debug printf, kill this as well! */ >> +#include "qemu/error-report.h" >> >> static ssize_t __readlink(V9fsState *s, V9fsPath *path, V9fsString >> *buf) >> { >> @@ -67,6 +69,7 @@ int v9fs_co_readlink(V9fsPDU *pdu, V9fsPath *path, >> V9fsString *buf) >> } >> }); >> v9fs_path_unlock(s); >> + error_printf("v9fs_co_readlink: %d\n", err); >> return err; >> } >> >> @@ -87,6 +90,7 @@ int v9fs_co_statfs(V9fsPDU *pdu, V9fsPath *path, >> struct statfs *stbuf) >> } >> }); >> v9fs_path_unlock(s); >> + error_printf("v9fs_co_statfs: %d\n", err); >> return err; >> } >> >> @@ -110,6 +114,7 @@ int v9fs_co_chmod(V9fsPDU *pdu, V9fsPath *path, >> mode_t mode) >> } >> }); >> v9fs_path_unlock(s); >> + error_printf("v9fs_co_chmod: %d\n", err); >> return err; >> } >> >> @@ -131,6 +136,7 @@ int v9fs_co_utimensat(V9fsPDU *pdu, V9fsPath *path, >> } >> }); >> v9fs_path_unlock(s); >> + error_printf("v9fs_co_utimensat: %d\n", err); >> return err; >> } >> >> @@ -155,6 +161,7 @@ int v9fs_co_chown(V9fsPDU *pdu, V9fsPath *path, >> uid_t uid, gid_t gid) >> } >> }); >> v9fs_path_unlock(s); >> + error_printf("v9fs_co_chown: %d\n", err); >> return err; >> } >> >> @@ -175,6 +182,7 @@ int v9fs_co_truncate(V9fsPDU *pdu, V9fsPath *path, >> off_t size) >> } >> }); >> v9fs_path_unlock(s); >> + error_printf("v9fs_co_truncate: %d\n", err); >> return err; >> } >> >> @@ -213,6 +221,7 @@ int v9fs_co_mknod(V9fsPDU *pdu, V9fsFidState *fidp, >> V9fsString *name, uid_t uid, >> } >> }); >> v9fs_path_unlock(s); >> + error_printf("v9fs_co_mknod: %d\n", err); >> return err; >> } >> >> @@ -234,6 +243,7 @@ int v9fs_co_remove(V9fsPDU *pdu, V9fsPath *path) >> } >> }); >> v9fs_path_unlock(s); >> + error_printf("v9fs_co_remove: %d\n", err); >> return err; >> } >> >> @@ -254,6 +264,7 @@ int v9fs_co_unlinkat(V9fsPDU *pdu, V9fsPath *path, >> V9fsString *name, int flags) >> } >> }); >> v9fs_path_unlock(s); >> + error_printf("v9fs_co_unlinkat: %d\n", err); >> return err; >> } >> >> @@ -273,6 +284,7 @@ int v9fs_co_rename(V9fsPDU *pdu, V9fsPath *oldpath, >> V9fsPath *newpath) >> err = -errno; >> } >> }); >> + error_printf("v9fs_co_rename: %d\n", err); >> return err; >> } >> >> @@ -293,6 +305,7 @@ int v9fs_co_renameat(V9fsPDU *pdu, V9fsPath >> *olddirpath, V9fsString *oldname, >> err = -errno; >> } >> }); >> + error_printf("v9fs_co_renameat: %d\n", err); >> return err; >> } >> >> @@ -331,6 +344,7 @@ int v9fs_co_symlink(V9fsPDU *pdu, V9fsFidState >> *dfidp, V9fsString *name, >> } >> }); >> v9fs_path_unlock(s); >> + error_printf("v9fs_co_symlink: %d\n", err); >> return err; >> } >> >> @@ -361,5 +375,6 @@ int v9fs_co_name_to_path(V9fsPDU *pdu, V9fsPath >> *dirpath, >> } >> }); >> } >> + error_printf("v9fs_co_name_to_path: %d\n", err); >> return err; >> } >> diff --git a/hw/9pfs/coxattr.c b/hw/9pfs/coxattr.c >> index 6ad96ea..49fbd5e 100644 >> --- a/hw/9pfs/coxattr.c >> +++ b/hw/9pfs/coxattr.c >> @@ -17,6 +17,8 @@ >> #include "qemu/thread.h" >> #include "qemu/coroutine.h" >> #include "coth.h" >> +/* mifritscher: after killing the debug printf, kill this as well! */ >> +#include "qemu/error-report.h" >> >> int v9fs_co_llistxattr(V9fsPDU *pdu, V9fsPath *path, void *value, >> size_t size) >> { >> @@ -35,6 +37,7 @@ int v9fs_co_llistxattr(V9fsPDU *pdu, V9fsPath *path, >> void *value, size_t size) >> } >> }); >> v9fs_path_unlock(s); >> + error_printf("v9fs_co_llistxattr: %d\n", err); >> return err; >> } >> >> @@ -59,6 +62,7 @@ int v9fs_co_lgetxattr(V9fsPDU *pdu, V9fsPath *path, >> } >> }); >> v9fs_path_unlock(s); >> + error_printf("v9fs_co_lgetxattr: %d\n", err); >> return err; >> } >> >> @@ -83,6 +87,7 @@ int v9fs_co_lsetxattr(V9fsPDU *pdu, V9fsPath *path, >> } >> }); >> v9fs_path_unlock(s); >> + error_printf("v9fs_co_lsetxattr: %d\n", err); >> return err; >> } >> >> @@ -104,5 +109,6 @@ int v9fs_co_lremovexattr(V9fsPDU *pdu, V9fsPath >> *path, >> } >> }); >> v9fs_path_unlock(s); >> + error_printf("v9fs_co_lremovexattr: %d\n", err); >> return err; >> } >> diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c >> index a38850e..59d0a50 100644 >> --- a/hw/9pfs/virtio-9p-device.c >> +++ b/hw/9pfs/virtio-9p-device.c >> @@ -17,7 +17,9 @@ >> #include "qemu/sockets.h" >> #include "virtio-9p.h" >> #include "fsdev/qemu-fsdev.h" >> -#include "9p-xattr.h" >> +#ifndef WIN32 >> + #include "9p-xattr.h" >> +#endif >> #include "coth.h" >> #include "hw/virtio/virtio-access.h" >> #include "qemu/iov.h" > >
On Mon, 9 May 2016 11:12:51 +0200 "Michael Fritscher" <michael@fritscher.net> wrote: > Hello Greg, > Hi Michael ! > I commented your comments :-) > > To summerize: > * I didn't know where to put the win32 specific functions/wrappers - > thanks showing me the locations! > * Binary mode is needed by Windows - else newlines are screwed up. > * Windows is way more picky than Linux regarding paths. > * Which looking mechanism should I use? > > Best regards, > Michael > > P.S. is there a nice tool to edit / split patchfiles? > Dunno... I always redo a full round of coding/git when splitting big patches. > > More comments. > > > > On Tue, 12 Apr 2016 09:52:00 +0200 > > Michael Fritscher <michael@fritscher.net> wrote: > > > >> It was tested on Windows & Linux hosts, on the later no obvious > >> regressions could be found. The guest was a Knoppix 7.6.0 live cd. > >> > >> This is WIP and a RFC - it isn't meant to be upstreamed yet. The > >> error_printf are only for debugging and will be deleted in the final > >> patch. > >> > >> There are some comments with "mifritscher" - I'm not quite sure how to > >> handle these problems (e.g. on mingw, this in 32 bit, while on Linux > >> this is 16 bit and so on). Additionally, some places from which I > >> suspect problems are marked with a #warning. > >> > >> Changes against v1: > >> * fixed open (added binary flag) -> read/write is fine now, file > >> creation was fixed as well > >> * added inode calculation using own crude hash algorithm > >> * fixed xattr returning -1 + EOPNOTSUP -> fixes e.g. executing files > >> * fixed unlinkat / remove für directories by trying rmdir as well > >> * prepend 777 mode on files (for executing) > >> > >> What does work: > >> * reading/writing "big" files (5MB, verified with md5sum) > >> * creating files > >> * executing files > >> * mkdir > >> * rm / rmdir > >> * cp files > >> * running gcc > >> * cp first 250 files & directories from /etc > >> * tar it from and to the 9p mount > >> * create a 100 MB swap file and do a mkswap on it > >> > >> What does not work: > >> * swapon - no real surprise (doesn't work on Linux as well - with the > >> same error message) ;-) (swapon returns -1 EINVAL) > >> * link / symlink (there is no real aequivalent for this on windows) > >> * mknod (dito) > >> * chown (dito - prepend success for compatibility) > >> > >> State of v1: > >> What works: > >> * mount > >> * stat > >> * chdir > >> * readdir (aka ls) > >> * read of small files (<10k) > >> * overwrite > >> > >> What does not work: > >> * create new files (in 90% problems with path handling (old path > >> occurs) > >> * read / probably write big files > >> > >> > >> Signed-off-by: Michael Fritscher <michael@fritscher.net> > >> --- > >> On https://github.com/mifritscher/qemu/tree/9pfs_windows is a git tree > >> with the patch. > >> > >> I gave a shot at xattr (try to include xattr stuff) but it ended up even > >> more #ifdefs. So I gave up at this. > >> Now I'm waiting on comments etc. If there are no big objections, I'll > >> remove the debug output and make a patch which is meant for upstreaming. > >> > >> Thanks to everybody which helped me! > >> > >> Makefile.objs | 1 + > >> configure | 15 ++- > >> fsdev/9p-iov-marshal.c | 2 + > >> fsdev/9p-marshal.c | 4 +- > >> fsdev/file-op-9p.h | 35 ++++- > >> fsdev/qemu-fsdev.c | 2 + > >> hw/9pfs/9p-local.c | 326 > >> +++++++++++++++++++++++++++++++++++++++++---- > >> hw/9pfs/9p-synth.c | 10 +- > >> hw/9pfs/9p.c | 102 +++++++++++++- > >> hw/9pfs/9p.h | 70 +++++++++- > >> hw/9pfs/Makefile.objs | 7 +- > >> hw/9pfs/codir.c | 31 +++++ > >> hw/9pfs/cofile.c | 15 +++ > >> hw/9pfs/cofs.c | 15 +++ > >> hw/9pfs/coxattr.c | 6 + > >> hw/9pfs/virtio-9p-device.c | 4 +- > >> 16 files changed, 600 insertions(+), 45 deletions(-) > >> > >> diff --git a/Makefile.objs b/Makefile.objs > >> index 8f705f6..6fd02bc 100644 > >> --- a/Makefile.objs > >> +++ b/Makefile.objs > >> @@ -48,6 +48,7 @@ common-obj-$(CONFIG_WIN32) += os-win32.o > >> common-obj-$(CONFIG_POSIX) += os-posix.o > >> > >> common-obj-$(CONFIG_LINUX) += fsdev/ > >> +common-obj-$(CONFIG_WIN32) += fsdev/ > >> > >> common-obj-y += migration/ > >> common-obj-y += qemu-char.o #aio.o > >> diff --git a/configure b/configure > >> index 5db29f0..a4797c3 100755 > >> --- a/configure > >> +++ b/configure > >> @@ -4566,12 +4566,21 @@ if test "$want_tools" = "yes" ; then > >> fi > >> if test "$softmmu" = yes ; then > >> if test "$virtfs" != no ; then > >> - if test "$cap" = yes && test "$linux" = yes && test "$attr" = yes ; > >> then > >> + if test "$linux" = yes ; then > >> + if test "$cap" = yes && test "$attr" = yes ; then > >> + virtfs=yes > >> + tools="$tools fsdev/virtfs-proxy-helper\$(EXESUF)" > >> + else > >> + if test "$virtfs" = yes; then > >> + error_exit "VirtFS requires libcap-devel and libattr-devel on > >> Linux" > >> + fi > >> + virtfs=no > >> + fi > >> + elif test "$mingw32" = yes; then > >> virtfs=yes > >> - tools="$tools fsdev/virtfs-proxy-helper\$(EXESUF)" > >> else > >> if test "$virtfs" = yes; then > >> - error_exit "VirtFS is supported only on Linux and requires > >> libcap-devel and libattr-devel" > >> + error_exit "VirtFS is only supported on Linux or Windows" > >> fi > >> virtfs=no > >> fi > >> diff --git a/fsdev/9p-iov-marshal.c b/fsdev/9p-iov-marshal.c > >> index fb40bdf..1a292c6 100644 > >> --- a/fsdev/9p-iov-marshal.c > >> +++ b/fsdev/9p-iov-marshal.c > >> @@ -15,7 +15,9 @@ > >> #include <glib.h> > >> #include <glib/gprintf.h> > >> #include <utime.h> > >> +#ifndef _WIN32 > >> #include <sys/uio.h> > >> +#endif > >> > >> #include "9p-iov-marshal.h" > >> #include "qemu/bswap.h" > >> diff --git a/fsdev/9p-marshal.c b/fsdev/9p-marshal.c > >> index 183d366..081cb88 100644 > >> --- a/fsdev/9p-marshal.c > >> +++ b/fsdev/9p-marshal.c > >> @@ -16,7 +16,9 @@ > >> #include <glib/gprintf.h> > >> #include <dirent.h> > >> #include <utime.h> > >> -#include <sys/uio.h> > >> +#ifndef WIN32 > >> + #include <sys/uio.h> > >> +#endif > >> > >> #include "9p-marshal.h" > >> > >> diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h > >> index b8c2602..446c6a5 100644 > >> --- a/fsdev/file-op-9p.h > >> +++ b/fsdev/file-op-9p.h > >> @@ -14,12 +14,43 @@ > >> #define _FILEOP_H > >> #include <dirent.h> > >> #include <utime.h> > >> -#include <sys/uio.h> > >> -#include <sys/vfs.h> > >> +#ifndef _WIN32 > >> + #include <sys/uio.h> > >> + #include <sys/vfs.h> > >> +#endif > >> > >> #define SM_LOCAL_MODE_BITS 0600 > >> #define SM_LOCAL_DIR_MODE_BITS 0700 > >> > >> +#ifdef _WIN32 > >> +typedef uint32_t uid_t; > >> +typedef uint32_t gid_t; > >> + > >> +/* from http://man7.org/linux/man-pages/man2/statfs.2.html */ > >> +typedef uint32_t __fsword_t; > >> +typedef uint32_t fsblkcnt_t; > >> +typedef uint32_t fsfilcnt_t; > >> + > >> +/* from linux/include/uapi/asm-generic/posix_types.h */ > >> +typedef struct { > >> + long __val[2]; > >> +} fsid_t; > >> + > >> +struct statfs { > >> + __fsword_t f_type; > >> + __fsword_t f_bsize; > >> + fsblkcnt_t f_blocks; > >> + fsblkcnt_t f_bfree; > >> + fsblkcnt_t f_bavail; > >> + fsfilcnt_t f_files; > >> + fsfilcnt_t f_ffree; > >> + fsid_t f_fsid; > >> + __fsword_t f_namelen; > >> + __fsword_t f_frsize; > >> + __fsword_t f_flags; > >> +}; > >> +#endif > >> + > >> typedef struct FsCred > >> { > >> uid_t fc_uid; > >> diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c > >> index bf7f0b0..384d72e 100644 > >> --- a/fsdev/qemu-fsdev.c > >> +++ b/fsdev/qemu-fsdev.c > >> @@ -26,7 +26,9 @@ static FsDriverTable FsDrivers[] = { > >> { .name = "handle", .ops = &handle_ops}, > >> #endif > >> { .name = "synth", .ops = &synth_ops}, > >> +#ifndef WIN32 > >> { .name = "proxy", .ops = &proxy_ops}, > >> +#endif > >> }; > >> > >> int qemu_fsdev_add(QemuOpts *opts) > >> diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c > >> index 16f45f4..710ab5f 100644 > >> --- a/hw/9pfs/9p-local.c > >> +++ b/hw/9pfs/9p-local.c > >> @@ -12,23 +12,174 @@ > >> */ > >> > >> #include "qemu/osdep.h" > >> +/* mifritscher: after killing the debug printf, kill this as well! */ > >> +#include "qemu/error-report.h" > >> #include "9p.h" > >> -#include "9p-xattr.h" > >> +#ifdef _WIN32 > >> +/* idea from > >> http://mingw-users.1079350.n2.nabble.com/Undefined-reference-to-quot-lstat-quot-and-quot-S-ISLNK-quot-td5450984.html > >> */ > >> +# define lstat(path, buffer) stat(path, buffer) > >> + > >> +# define mkdir(path, mode) mkdir(path) > > > > Maybe these definitions can go to include/sysemu/os-win32.h ? > I didn't know that we have this file - in fact, I wanted to provoke a > reaction on this how to handle this properly ;-) Yes, good idea. That's the way it goes :) > > > >> +# define getxattr(buffer, name, pointer, length) 0 > >> + > >> +/* pretend success */ > >> +static int setxattr(const char *path, const char *name, > >> + const void *value, size_t size, int flags) > >> +{ > >> + return 0; > >> +} > >> + > >> +static ssize_t fgetxattr(int fd, const char *name, > >> + void *value, size_t size) > >> +{ > >> + return 0; > >> +} > >> + > > > > and these xattr definitions to include/qemu/xattr.h ? > Yes - or perhaps a xattr-win32.h (I think there was some problem including > xattr.h) > Hmm... what problem ? Can't it be fixed ? > > > >> +# define lchown(buffer, uid, gid) 0 > >> +# define readlink(buffer, buf, bufsz) 0 > >> +# define mknod(buffer, mode, u) 0 > >> +# define link(buffer, buffer1) 0 > >> +# define symlink(buffer, buffer1) 0 > >> + Since these are standard names also used in FileOperations, I guess it's better to have static inline functions returning 0. > >> +static ssize_t v9fs_get_xattr(FsContext *ctx, const char *path, > >> + const char *name, void *value, size_t > >> size) > >> +{ > >> + errno = 95; /* EOPNOTSUP - wrong definition in mingw(130); */ > > > > This is ENOTSUP actually. > Aahhh - thanks :-) > > > > >> + return -1; > >> +} > >> + > >> +static ssize_t v9fs_list_xattr(FsContext *ctx, const char *path, > >> + void *value, size_t vsize) > >> +{ > >> + errno = 95; /* EOPNOTSUP - wrong definition in mingw(130); */ > >> + return -1; > >> +} > >> + > >> +static int v9fs_set_xattr(FsContext *ctx, const char *path, > >> + const char *name, void *value, size_t size, > >> + int flags) > >> +{ > >> + errno = 95; /* EOPNOTSUP - wrong definition in mingw(130); */ > >> + return -1; > >> +} > >> + > >> +static int v9fs_remove_xattr(FsContext *ctx, const char *path, > >> + const char *name) > >> +{ > >> + errno = 95; /* EOPNOTSUP - wrong definition in mingw(130); */ > >> + return -1; > >> +} > >> + > >> +static int readdir_r(DIR *dirp, struct dirent *entry, > >> + struct dirent **result) > >> +{ > >> + struct dirent *temp; > >> + errno = 0; > >> + temp = readdir(dirp); > > > > readdir() isn't expected to be thread safe... I believe we need some > > locking here. > > > > Also this function should probably be in os-win32.c. > @locking: Yes, I stumbled over that. Which locking mechanism do you prefer? Something like pthread_mutex_lock() if it exists in win32 ? > @os-win32.c: Yes :-) > > > > > >> + if (temp == 0) { > >> + error_printf("readdir_r: End of directory reached -> returning > >> NULL\n"); > >> + *result = 0; > >> + } else { > >> + /* Copy it from the stack to the buffer got from the caller */ > >> + memcpy(entry, temp, sizeof(struct dirent)); > >> + error_printf("readdir_r: Name: %hu %s\n", > >> + temp->d_namlen, temp->d_name); > >> + error_printf("readdir_r: Name: %hu %s\n", > >> + entry->d_namlen, entry->d_name); > >> + *result = entry; > >> + } > >> + return errno; > >> +} > >> + > >> +/* Can be done better... */ > >> +static int statfs(const char *file, struct statfs *buf) > >> +{ > >> + memset(buf, 0, sizeof(struct statfs)); > >> + buf->f_type = 0x01021997; /* V9FS_MAGIC */ > >> + buf->f_bsize = 4096; > >> + buf->f_blocks = 4000000; > >> + buf->f_bfree = 3000000; > >> + buf->f_bavail = 2999000; > >> + buf->f_files = 1000000; > >> + buf->f_ffree = 800000; > >> + buf->f_namelen = NAME_MAX; > >> + return 0; > >> +} > >> + > >> +/* a crude hash function (needed for fake inodes) */ > >> +static ino_t hash(const char *path) > >> +{ > >> + ino_t result = (ino_t)41021998; > >> + int len = strlen(path); > >> + if (!len) { > >> + return result; > >> + } > >> + > >> + /* Q&D canolizement of the path */ > >> + if (path[len - 1] == '\\' || path[len - 1] == '/') { > >> + len--; > >> + } > >> + if (!len) { > >> + return result; > >> + } > >> + > >> + if (path[len - 1] == '.') { > >> + if (len == 1) { > >> + return result; > >> + } > >> + len--; > >> + if (path[len - 1] == '\\' || path[len - 1] == '/') { > >> + len--; > >> + /* .. -> kill last part */ > >> + } else if (path[len - 1] == '.') { > >> + len--; > >> + while (len) { > >> + if (path[len - 1] == '\\' || path[len - 1] == '/') { > >> + len--; > >> + break; > >> + } > >> + len--; > >> + } > >> + } > >> + } > >> + > >> + if (!len) { > >> + return result; > >> + } > >> + > >> + for (int i = 0; i < len; i++) { > >> + result += path[i] << (i % 7); > >> + result += path[i] << ((i + 11) % 17); > >> + result += path[i] << ((i + 19) % 23); > >> + } > >> + > >> + return result; > >> +} > >> + > >> +#else > >> +# include "9p-xattr.h" > >> +#endif > > > > I'd prefer the missing xattr bits to be added to win32... and > > if we really need different implementations, then maybe add > > 9p-xattr-posix.c and 9p-xattr-win32.c... > Yes. > > > > >> #include "fsdev/qemu-fsdev.h" /* local_ops */ > >> +#ifndef _WIN32 > >> #include <arpa/inet.h> > >> #include <pwd.h> > >> #include <grp.h> > >> #include <sys/socket.h> > >> #include <sys/un.h> > >> #include "qemu/xattr.h" > >> +#endif > >> #include "qemu/cutils.h" > >> #include "qemu/error-report.h" > >> #include <libgen.h> > >> -#include <linux/fs.h> > >> +#ifndef _WIN32 > >> + #include <linux/fs.h> > >> +#endif > >> #ifdef CONFIG_LINUX_MAGIC_H > >> #include <linux/magic.h> > >> #endif > >> +#ifndef _WIN32 > >> #include <sys/ioctl.h> > >> +#endif > >> > >> #ifndef XFS_SUPER_MAGIC > >> #define XFS_SUPER_MAGIC 0x58465342 > >> @@ -76,7 +227,7 @@ static FILE *local_fopen(const char *path, const char > >> *mode) > >> } else { > >> return NULL; > >> } > >> - fd = open(path, flags, o_mode); > >> + fd = open(path, flags | O_BINARY, o_mode); > > > > Why is this needed ? > Because on Windows, the files are opened in textmode - which screws up > line endings. Stephan Weil told me that this flag is ignored on other > OSes, which open files in binary mode by default. > > > > >> if (fd == -1) { > >> return NULL; > >> } > >> @@ -124,10 +275,20 @@ static int local_lstat(FsContext *fs_ctx, V9fsPath > >> *fs_path, struct stat *stbuf) > >> char *path = fs_path->data; > >> > >> buffer = rpath(fs_ctx, path); > >> - err = lstat(buffer, stbuf); > >> + error_printf("\nrpath %s + %s -> %s\n\n", fs_ctx->fs_root, path, > >> buffer); > >> + err = lstat(buffer, stbuf); > >> if (err) { > >> goto err_out; > >> } > >> +#ifdef _WIN32 > >> + /* This way, all files are executable > >> + (MingW seems to do 777 on dirs, but 666 on files) */ > >> + stbuf->st_mode |= S_IXUSR | S_IXGRP | S_IXOTH; > >> + > >> + /* Under WIN32 (MingW), st_ino seems to be always 2, > >> + which leads to confusion */ > >> + stbuf->st_ino = hash(path); > >> +#endif > >> if (fs_ctx->export_flags & V9FS_SM_MAPPED) { > >> /* Actual credentials are part of extended attrs */ > >> uid_t tmp_uid; > >> @@ -162,7 +323,7 @@ static int local_create_mapped_attr_dir(FsContext > >> *ctx, const char *path) > >> char *attr_dir; > >> char *tmp_path = g_strdup(path); > >> > >> - attr_dir = g_strdup_printf("%s/%s/%s", > >> + attr_dir = g_strdup_printf(DELIMITER_IN_PATH2, > >> ctx->fs_root, dirname(tmp_path), VIRTFS_META_DIR); > >> > >> err = mkdir(attr_dir, 0700); > >> @@ -223,7 +384,8 @@ update_map_file: > >> if (credp->fc_gid != -1) { > >> gid = credp->fc_gid; > >> } > >> - if (credp->fc_mode != -1) { > >> + /* mifritscher: is normally unsigned... */ > >> + if ((int16_t)(credp->fc_mode) != -1) { > >> mode = credp->fc_mode; > >> } > >> if (credp->fc_rdev != -1) { > >> @@ -268,7 +430,8 @@ static int local_set_xattr(const char *path, FsCred > >> *credp) > >> return err; > >> } > >> } > >> - if (credp->fc_mode != -1) { > >> + /* mifritscher: is normally unsigned... */ > >> + if ((int16_t)(credp->fc_mode) != -1) { > >> uint32_t tmp_mode = cpu_to_le32(credp->fc_mode); > >> err = setxattr(path, "user.virtfs.mode", &tmp_mode, > >> sizeof(mode_t), 0); > >> if (err) { > >> @@ -323,7 +486,7 @@ static ssize_t local_readlink(FsContext *fs_ctx, > >> V9fsPath *fs_path, > >> (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE)) { > >> int fd; > >> buffer = rpath(fs_ctx, path); > >> - fd = open(buffer, O_RDONLY | O_NOFOLLOW); > >> + fd = open(buffer, O_RDONLY | O_NOFOLLOW | O_BINARY); > >> g_free(buffer); > >> if (fd == -1) { > >> return -1; > >> @@ -358,7 +521,8 @@ static int local_open(FsContext *ctx, V9fsPath > >> *fs_path, > >> char *path = fs_path->data; > >> > >> buffer = rpath(ctx, path); > >> - fs->fd = open(buffer, flags | O_NOFOLLOW); > >> + error_printf("File which should be opened: %s\n", buffer); > >> + fs->fd = open(buffer, flags | O_NOFOLLOW | O_BINARY); > > > > I see you add O_BINARY on all open() call sites ? Does this mean we > > need a helper ? > I could make a helper function if you want, which wraps open() and adds > O_BINARY to the flag. Where should I add this helper? > Maybe you can leave it in 9p-local.c for the moment. > > > >> g_free(buffer); > >> return fs->fd; > >> } > >> @@ -370,6 +534,7 @@ static int local_opendir(FsContext *ctx, > >> char *path = fs_path->data; > >> > >> buffer = rpath(ctx, path); > >> + error_printf("Directory (opendir) which should be opened: %s\n", > >> buffer); > >> fs->dir = opendir(buffer); > >> g_free(buffer); > >> if (!fs->dir) { > >> @@ -395,17 +560,36 @@ static int local_readdir_r(FsContext *ctx, > >> V9fsFidOpenState *fs, > >> int ret; > >> > >> again: > >> +#ifdef _WIN32 > >> + error_printf("local_readdir_r: Directory which should be > >> read:%s\n", > >> + fs->dir->dd_name); > >> +#endif > >> ret = readdir_r(fs->dir, entry, result); > >> if (ctx->export_flags & V9FS_SM_MAPPED) { > >> +#ifndef _WIN32 > >> entry->d_type = DT_UNKNOWN; > >> +#endif > >> } else if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { > >> if (!ret && *result != NULL && > >> !strcmp(entry->d_name, VIRTFS_META_DIR)) { > >> /* skp the meta data directory */ > >> goto again; > >> } > >> +#ifndef _WIN32 > >> entry->d_type = DT_UNKNOWN; > >> +#endif > >> } > >> + if (*result == NULL) { > >> + error_printf("local_readdir_r: End of directory -> returning > >> NULL\n"); > >> + } else { > >> +#ifdef _WIN32 > >> + error_printf("local_readdir_r: Name: %hu %s\n", > >> + entry->d_namlen, entry->d_name); > >> +#else > >> + error_printf("local_readdir_r: Name: %s\n", entry->d_name); > >> +#endif > >> + } > >> + error_printf("local_readdir_r: return %d\n", ret); > >> return ret; > >> } > >> > >> @@ -418,10 +602,15 @@ static ssize_t local_preadv(FsContext *ctx, > >> V9fsFidOpenState *fs, > >> const struct iovec *iov, > >> int iovcnt, off_t offset) > >> { > >> + error_printf("local_preadv: #iov: %u, addr: %p, #bytes: %u, offset: > >> %llu\n", > >> + iovcnt, iov->iov_base, iov->iov_len, offset); > >> #ifdef CONFIG_PREADV > >> + error_printf("local_preadv: using preadv\n"); > >> return preadv(fs->fd, iov, iovcnt, offset); > >> #else > >> + error_printf("local_preadv: not using preadv\n"); > >> int err = lseek(fs->fd, offset, SEEK_SET); > >> + error_printf("local_preadv: lseek returned %d\n", err); > >> if (err == -1) { > >> return err; > >> } else { > >> @@ -491,7 +680,7 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath > >> *dir_path, > >> char *buffer = NULL; > >> > >> v9fs_string_init(&fullname); > >> - v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); > >> + v9fs_string_sprintf(&fullname, DELIMITER_IN_PATH, dir_path->data, > >> name); > >> path = fullname.data; > >> > >> /* Determine the security model */ > >> @@ -552,7 +741,7 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath > >> *dir_path, > >> char *buffer = NULL; > >> > >> v9fs_string_init(&fullname); > >> - v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); > >> + v9fs_string_sprintf(&fullname, DELIMITER_IN_PATH, dir_path->data, > >> name); > >> path = fullname.data; > >> > >> /* Determine the security model */ > >> @@ -610,7 +799,14 @@ static int local_fstat(FsContext *fs_ctx, int > >> fid_type, > >> int err, fd; > >> > >> if (fid_type == P9_FID_DIR) { > >> + /* Don't know if that's right... > >> + (on WIN32/mingw, DIR has no fd entry) */ > >> +#ifdef _WIN32 > >> + #warning "Could cause problems!" > >> + fd = fs->fd; > >> +#else > >> fd = dirfd(fs->dir); > >> +#endif > >> } else { > >> fd = fs->fd; > >> } > >> @@ -619,6 +815,13 @@ static int local_fstat(FsContext *fs_ctx, int > >> fid_type, > >> if (err) { > >> return err; > >> } > >> +#ifdef _WIN32 > >> + /* This way, all files are executable > >> + (MingW seems to do 777 on dirs, but 666 on files) */ > >> + stbuf->st_mode |= S_IXUSR | S_IXGRP | S_IXOTH; > >> + > >> + /* mifritscher: TODO: fake inode? */ > >> +#endif > >> if (fs_ctx->export_flags & V9FS_SM_MAPPED) { > >> /* Actual credentials are part of extended attrs */ > >> uid_t tmp_uid; > >> @@ -661,13 +864,16 @@ static int local_open2(FsContext *fs_ctx, V9fsPath > >> *dir_path, const char *name, > >> flags |= O_NOFOLLOW; > >> > >> v9fs_string_init(&fullname); > >> - v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); > >> + v9fs_string_sprintf(&fullname, DELIMITER_IN_PATH, dir_path->data, > >> name); > >> path = fullname.data; > >> > >> + error_printf("local_open2: got %s %s\n", dir_path->data, name); > >> + error_printf("local_open2: full path: %s\n", path); > >> + > >> /* Determine the security model */ > >> if (fs_ctx->export_flags & V9FS_SM_MAPPED) { > >> buffer = rpath(fs_ctx, path); > >> - fd = open(buffer, flags, SM_LOCAL_MODE_BITS); > >> + fd = open(buffer, flags | O_BINARY, SM_LOCAL_MODE_BITS); > >> if (fd == -1) { > >> err = fd; > >> goto out; > >> @@ -681,7 +887,7 @@ static int local_open2(FsContext *fs_ctx, V9fsPath > >> *dir_path, const char *name, > >> } > >> } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { > >> buffer = rpath(fs_ctx, path); > >> - fd = open(buffer, flags, SM_LOCAL_MODE_BITS); > >> + fd = open(buffer, flags | O_BINARY, SM_LOCAL_MODE_BITS); > >> if (fd == -1) { > >> err = fd; > >> goto out; > >> @@ -696,12 +902,17 @@ static int local_open2(FsContext *fs_ctx, V9fsPath > >> *dir_path, const char *name, > >> } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || > >> (fs_ctx->export_flags & V9FS_SM_NONE)) { > >> buffer = rpath(fs_ctx, path); > >> - fd = open(buffer, flags, credp->fc_mode); > >> + error_printf("local_open2: File which should be opened (open2): > >> %s\n", > >> + buffer); > >> + fd = open(buffer, flags | O_BINARY, credp->fc_mode); > >> + error_printf("local_open2: open returned %d\n", fd); > >> if (fd == -1) { > >> err = fd; > >> goto out; > >> } > >> err = local_post_create_passthrough(fs_ctx, path, credp); > >> + error_printf("local_open2: local_post_create_passthrough > >> returned %u\n", > >> + err); > >> if (err == -1) { > >> serrno = errno; > >> goto err_end; > >> @@ -732,7 +943,7 @@ static int local_symlink(FsContext *fs_ctx, const > >> char *oldpath, > >> char *buffer = NULL; > >> > >> v9fs_string_init(&fullname); > >> - v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); > >> + v9fs_string_sprintf(&fullname, DELIMITER_IN_PATH, dir_path->data, > >> name); > >> newpath = fullname.data; > >> > >> /* Determine the security model */ > >> @@ -740,7 +951,9 @@ static int local_symlink(FsContext *fs_ctx, const > >> char *oldpath, > >> int fd; > >> ssize_t oldpath_size, write_size; > >> buffer = rpath(fs_ctx, newpath); > >> - fd = open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, > >> SM_LOCAL_MODE_BITS); > >> + fd = open(buffer, > >> + O_CREAT | O_EXCL | O_RDWR | O_NOFOLLOW | O_BINARY, > >> + SM_LOCAL_MODE_BITS); > >> if (fd == -1) { > >> err = fd; > >> goto out; > >> @@ -758,8 +971,10 @@ static int local_symlink(FsContext *fs_ctx, const > >> char *oldpath, > >> goto err_end; > >> } > >> close(fd); > >> - /* Set cleint credentials in symlink's xattr */ > >> + /* Set client credentials in symlink's xattr */ > >> +#ifndef _WIN32 > >> credp->fc_mode = credp->fc_mode|S_IFLNK; > >> +#endif > >> err = local_set_xattr(buffer, credp); > >> if (err == -1) { > >> serrno = errno; > >> @@ -769,7 +984,9 @@ static int local_symlink(FsContext *fs_ctx, const > >> char *oldpath, > >> int fd; > >> ssize_t oldpath_size, write_size; > >> buffer = rpath(fs_ctx, newpath); > >> - fd = open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, > >> SM_LOCAL_MODE_BITS); > >> + fd = open(buffer, > >> + O_CREAT | O_EXCL | O_RDWR | O_NOFOLLOW | O_BINARY, > >> + SM_LOCAL_MODE_BITS); > >> if (fd == -1) { > >> err = fd; > >> goto out; > >> @@ -788,7 +1005,9 @@ static int local_symlink(FsContext *fs_ctx, const > >> char *oldpath, > >> } > >> close(fd); > >> /* Set cleint credentials in symlink's xattr */ > >> +#ifndef _WIN32 > >> credp->fc_mode = credp->fc_mode|S_IFLNK; > >> +#endif > >> err = local_set_mapped_file_attr(fs_ctx, newpath, credp); > >> if (err == -1) { > >> serrno = errno; > >> @@ -833,7 +1052,7 @@ static int local_link(FsContext *ctx, V9fsPath > >> *oldpath, > >> char *buffer, *buffer1; > >> > >> v9fs_string_init(&newpath); > >> - v9fs_string_sprintf(&newpath, "%s/%s", dirpath->data, name); > >> + v9fs_string_sprintf(&newpath, DELIMITER_IN_PATH, dirpath->data, > >> name); > >> > >> buffer = rpath(ctx, oldpath->data); > >> buffer1 = rpath(ctx, newpath.data); > >> @@ -934,7 +1153,12 @@ static int local_utimensat(FsContext *s, V9fsPath > >> *fs_path, > >> char *path = fs_path->data; > >> > >> buffer = rpath(s, path); > >> +#ifdef _WIN32 > >> + #warning "Could cause problems!" > >> + ret = 0; > >> +#else > >> ret = qemu_utimens(buffer, buf); > >> +#endif > >> g_free(buffer); > >> return ret; > >> } > >> @@ -949,6 +1173,7 @@ static int local_remove(FsContext *ctx, const char > >> *path) > >> buffer = rpath(ctx, path); > >> err = lstat(buffer, &stbuf); > >> g_free(buffer); > >> + error_printf("local_remove: stat %d %d\n", err, errno); > >> if (err) { > >> goto err_out; > >> } > >> @@ -957,10 +1182,12 @@ static int local_remove(FsContext *ctx, const > >> char *path) > >> * directory > >> */ > >> if (S_ISDIR(stbuf.st_mode)) { > >> - buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root, > >> + buffer = g_strdup_printf(DELIMITER_IN_PATH2, ctx->fs_root, > >> path, VIRTFS_META_DIR); > >> err = remove(buffer); > >> g_free(buffer); > >> + error_printf("local_remove: .virtfs_metdata remove %d > >> %d\n", > >> + err, errno); > >> if (err < 0 && errno != ENOENT) { > >> /* > >> * We didn't had the .virtfs_metadata file. May be file > >> created > >> @@ -976,6 +1203,8 @@ static int local_remove(FsContext *ctx, const char > >> *path) > >> buffer = local_mapped_attr_path(ctx, path); > >> err = remove(buffer); > >> g_free(buffer); > >> + error_printf("local_remove: local_mapped_attr_path remove %d > >> %d\n", > >> + err, errno); > >> if (err < 0 && errno != ENOENT) { > >> /* > >> * We didn't had the .virtfs_metadata file. May be file > >> created > >> @@ -986,7 +1215,14 @@ static int local_remove(FsContext *ctx, const char > >> *path) > >> } > >> > >> buffer = rpath(ctx, path); > >> - err = remove(buffer); > >> + /* mifritscher: posix remove can delete directories as well, > >> windows not */ > >> + if (S_ISDIR(stbuf.st_mode)) { > >> + err = rmdir(buffer); > >> + } else { > >> + err = remove(buffer); > >> + } > >> + error_printf("local_remove: final remove %d %d\n", > >> + err, errno); > >> g_free(buffer); > >> err_out: > >> return err; > >> @@ -998,7 +1234,12 @@ static int local_fsync(FsContext *ctx, int > >> fid_type, > >> int fd; > >> > >> if (fid_type == P9_FID_DIR) { > >> +#ifdef _WIN32 > >> + #warning "Could cause problems!" > >> + fd = fs->fd; > >> +#else > >> fd = dirfd(fs->dir); > >> +#endif > >> } else { > >> fd = fs->fd; > >> } > >> @@ -1058,10 +1299,14 @@ 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", > >> + v9fs_string_sprintf((V9fsString *)target, DELIMITER_IN_PATH, > >> dir_path->data, name); > >> + error_printf("local_name_to_path: "); > >> + error_printf(DELIMITER_IN_PATH, dir_path->data, name); > >> + error_printf("\n"); > >> } else { > >> v9fs_string_sprintf((V9fsString *)target, "%s", name); > >> + error_printf("local_name_to_path: %s\n", name); > >> } > >> /* Bump the size for including terminating NULL */ > >> target->size++; > >> @@ -1078,8 +1323,10 @@ static int local_renameat(FsContext *ctx, > >> V9fsPath *olddir, > >> 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); > >> + v9fs_string_sprintf(&old_full_name, > >> + DELIMITER_IN_PATH, olddir->data, old_name); > >> + v9fs_string_sprintf(&new_full_name, > >> + DELIMITER_IN_PATH, newdir->data, new_name); > >> > >> ret = local_rename(ctx, old_full_name.data, new_full_name.data); > >> v9fs_string_free(&old_full_name); > >> @@ -1096,17 +1343,19 @@ static int local_unlinkat(FsContext *ctx, > >> V9fsPath *dir, > >> > >> v9fs_string_init(&fullname); > >> > >> - v9fs_string_sprintf(&fullname, "%s/%s", dir->data, name); > >> + v9fs_string_sprintf(&fullname, DELIMITER_IN_PATH, dir->data, name); > >> if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { > >> if (flags == AT_REMOVEDIR) { > >> /* > >> * If directory remove .virtfs_metadata contained in the > >> * directory > >> */ > >> - buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root, > >> + buffer = g_strdup_printf(DELIMITER_IN_PATH2, ctx->fs_root, > >> fullname.data, VIRTFS_META_DIR); > >> ret = remove(buffer); > >> g_free(buffer); > >> + error_printf("local_unlinkat: .virtfs_metadata %d %d\n", > >> + ret, errno); > >> if (ret < 0 && errno != ENOENT) { > >> /* > >> * We didn't had the .virtfs_metadata file. May be file > >> created > >> @@ -1121,6 +1370,8 @@ static int local_unlinkat(FsContext *ctx, V9fsPath > >> *dir, > >> */ > >> buffer = local_mapped_attr_path(ctx, fullname.data); > >> ret = remove(buffer); > >> + error_printf("local_unlinkat: local_mapped_attr_path %d %d\n", > >> + ret, errno); > >> g_free(buffer); > >> if (ret < 0 && errno != ENOENT) { > >> /* > >> @@ -1133,6 +1384,19 @@ static int local_unlinkat(FsContext *ctx, > >> V9fsPath *dir, > >> /* Remove the name finally */ > >> buffer = rpath(ctx, fullname.data); > >> ret = remove(buffer); > >> + error_printf("local_unlinkat: final |%s| %d %d\n", buffer, ret, > >> errno); > >> + /* extension for MingW: remove or Windows can't handle > >> directories... */ > >> +#ifdef _WIN32 > >> + /* mifritscher: Try to delete it as directory > >> + (AT_REMOVEDIR doesn't seem to be set in this case > >> + (testcase: rmdir from Linux)) */ > >> + if (ret < 0) { > >> + ret = rmdir(buffer); > >> + error_printf("local_unlinkat: final rmdir |%s| %d %d\n", > >> + buffer, ret, errno); > >> + > >> + } > >> +#endif > >> g_free(buffer); > >> > >> err_out: > >> @@ -1140,6 +1404,7 @@ err_out: > >> return ret; > >> } > >> > >> +#ifndef _WIN32 > >> static int local_ioc_getversion(FsContext *ctx, V9fsPath *path, > >> mode_t st_mode, uint64_t *st_gen) > >> { > >> @@ -1167,12 +1432,18 @@ static int local_ioc_getversion(FsContext *ctx, > >> V9fsPath *path, > >> return -1; > >> #endif > >> } > >> +#endif > >> > >> static int local_init(FsContext *ctx) > >> { > >> int err = 0; > >> +#ifdef FS_IOC_GETVERSION > >> struct statfs stbuf; > >> +#endif > >> > >> +#ifdef _WIN32 > >> + ctx->xops = 0; > >> +#else > >> if (ctx->export_flags & V9FS_SM_PASSTHROUGH) { > >> ctx->xops = passthrough_xattr_ops; > >> } else if (ctx->export_flags & V9FS_SM_MAPPED) { > >> @@ -1186,6 +1457,7 @@ static int local_init(FsContext *ctx) > >> */ > >> ctx->xops = passthrough_xattr_ops; > >> } > >> +#endif > >> ctx->export_flags |= V9FS_PATHNAME_FSCONTEXT; > >> #ifdef FS_IOC_GETVERSION > >> /* > >> diff --git a/hw/9pfs/9p-synth.c b/hw/9pfs/9p-synth.c > >> index f1475df..8355722 100644 > >> --- a/hw/9pfs/9p-synth.c > >> +++ b/hw/9pfs/9p-synth.c > >> @@ -15,7 +15,9 @@ > >> #include "qemu/osdep.h" > >> #include "hw/virtio/virtio.h" > >> #include "9p.h" > >> -#include "9p-xattr.h" > >> +#ifndef _WIN32 > >> + #include "9p-xattr.h" > >> +#endif > >> #include "fsdev/qemu-fsdev.h" > >> #include "9p-synth.h" > >> #include "qemu/rcu.h" > >> @@ -152,8 +154,10 @@ static void v9fs_synth_fill_statbuf(V9fsSynthNode > >> *node, struct stat *stbuf) > >> stbuf->st_gid = 0; > >> stbuf->st_rdev = 0; > >> stbuf->st_size = 0; > >> +#ifndef _WIN32 > >> stbuf->st_blksize = 0; > >> stbuf->st_blocks = 0; > >> +#endif > >> stbuf->st_atime = 0; > >> stbuf->st_mtime = 0; > >> stbuf->st_ctime = 0; > >> @@ -222,7 +226,11 @@ static void v9fs_synth_direntry(V9fsSynthNode > >> *node, > >> { > >> strcpy(entry->d_name, node->name); > >> entry->d_ino = node->attr->inode; > >> +#ifdef _WIN32 > >> + #warning "Can cause problems!" > >> +#else > >> entry->d_off = off + 1; > >> +#endif > >> } > >> > >> static int v9fs_synth_get_dentry(V9fsSynthNode *dir, struct dirent > >> *entry, > >> diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c > >> index f5e3012..7980f33 100644 > >> --- a/hw/9pfs/9p.c > >> +++ b/hw/9pfs/9p.c > >> @@ -20,7 +20,21 @@ > >> #include "qemu/sockets.h" > >> #include "virtio-9p.h" > >> #include "fsdev/qemu-fsdev.h" > >> -#include "9p-xattr.h" > >> +#ifdef _WIN32 > >> +/* taken from linux/kdev_t.h */ > >> +# define MINORBITS 20 > >> +# define MINORMASK ((1U << MINORBITS) - 1) > >> + > >> +# define major(dev) ((unsigned int) ((dev) >> MINORBITS)) > >> +# define minor(dev) ((unsigned int) ((dev) & MINORMASK)) > >> +# define makedev(ma, mi) (((ma) << MINORBITS) | (mi)) > >> + > >> +/* taken from linux/include/linux/stat.h */ > >> +# define UTIME_NOW ((1l << 30) - 1l) > >> +# define UTIME_OMIT ((1l << 30) - 2l) > >> +#else > >> +# include "9p-xattr.h" > >> +#endif > >> #include "coth.h" > >> #include "trace.h" > >> #include "migration/migration.h" > >> @@ -576,9 +590,11 @@ static void stat_to_qid(const struct stat *stbuf, > >> V9fsQID *qidp) > >> if (S_ISDIR(stbuf->st_mode)) { > >> qidp->type |= P9_QID_TYPE_DIR; > >> } > >> - if (S_ISLNK(stbuf->st_mode)) { > >> - qidp->type |= P9_QID_TYPE_SYMLINK; > >> - } > >> + #ifndef _WIN32 > >> + if (S_ISLNK(stbuf->st_mode)) { > >> + qidp->type |= P9_QID_TYPE_SYMLINK; > >> + } > >> + #endif > >> } > >> > >> static int fid_to_qid(V9fsPDU *pdu, V9fsFidState *fidp, V9fsQID *qidp) > >> @@ -677,12 +693,15 @@ static mode_t v9mode_to_mode(uint32_t mode, > >> V9fsString *extension) > >> ret |= S_IFDIR; > >> } > >> > >> +#ifndef _WIN32 > >> if (mode & P9_STAT_MODE_SYMLINK) { > >> ret |= S_IFLNK; > >> } > >> if (mode & P9_STAT_MODE_SOCKET) { > >> ret |= S_IFSOCK; > >> } > >> +#endif > >> + > >> if (mode & P9_STAT_MODE_NAMED_PIPE) { > >> ret |= S_IFIFO; > >> } > >> @@ -698,6 +717,7 @@ static mode_t v9mode_to_mode(uint32_t mode, > >> V9fsString *extension) > >> ret |= S_IFREG; > >> } > >> > >> +#ifndef _WIN32 > >> if (mode & P9_STAT_MODE_SETUID) { > >> ret |= S_ISUID; > >> } > >> @@ -707,6 +727,7 @@ static mode_t v9mode_to_mode(uint32_t mode, > >> V9fsString *extension) > >> if (mode & P9_STAT_MODE_SETVTX) { > >> ret |= S_ISVTX; > >> } > >> +#endif > >> > >> return ret; > >> } > >> @@ -762,6 +783,7 @@ static uint32_t stat_to_v9mode(const struct stat > >> *stbuf) > >> mode |= P9_STAT_MODE_DIR; > >> } > >> > >> +#ifndef _WIN32 > >> if (S_ISLNK(stbuf->st_mode)) { > >> mode |= P9_STAT_MODE_SYMLINK; > >> } > >> @@ -769,6 +791,7 @@ static uint32_t stat_to_v9mode(const struct stat > >> *stbuf) > >> if (S_ISSOCK(stbuf->st_mode)) { > >> mode |= P9_STAT_MODE_SOCKET; > >> } > >> +#endif > >> > >> if (S_ISFIFO(stbuf->st_mode)) { > >> mode |= P9_STAT_MODE_NAMED_PIPE; > >> @@ -778,6 +801,7 @@ static uint32_t stat_to_v9mode(const struct stat > >> *stbuf) > >> mode |= P9_STAT_MODE_DEVICE; > >> } > >> > >> +#ifndef _WIN32 > >> if (stbuf->st_mode & S_ISUID) { > >> mode |= P9_STAT_MODE_SETUID; > >> } > >> @@ -789,6 +813,7 @@ static uint32_t stat_to_v9mode(const struct stat > >> *stbuf) > >> if (stbuf->st_mode & S_ISVTX) { > >> mode |= P9_STAT_MODE_SETVTX; > >> } > >> +#endif > >> > >> return mode; > >> } > >> @@ -881,14 +906,34 @@ static void stat_to_v9stat_dotl(V9fsState *s, > >> const struct stat *stbuf, > >> v9lstat->st_gid = stbuf->st_gid; > >> v9lstat->st_rdev = stbuf->st_rdev; > >> v9lstat->st_size = stbuf->st_size; > >> +#ifdef _WIN32 > >> + /* Blksize is the optimal EA-block, > >> + while blocks always refers to 512 blocks > >> + */ > >> + v9lstat->st_blksize = 4096; > >> + v9lstat->st_blocks = ((stbuf->st_size + 1) / 512) + 1; > >> +#else > >> v9lstat->st_blksize = stbuf->st_blksize; > >> v9lstat->st_blocks = stbuf->st_blocks; > >> +#endif > >> v9lstat->st_atime_sec = stbuf->st_atime; > >> +#ifdef _WIN32 > >> + v9lstat->st_atime_nsec = 0; > >> +#else > >> v9lstat->st_atime_nsec = stbuf->st_atim.tv_nsec; > >> +#endif > >> v9lstat->st_mtime_sec = stbuf->st_mtime; > >> +#ifdef _WIN32 > >> + v9lstat->st_mtime_nsec = 0; > >> +#else > >> v9lstat->st_mtime_nsec = stbuf->st_mtim.tv_nsec; > >> +#endif > >> v9lstat->st_ctime_sec = stbuf->st_ctime; > >> +#ifdef _WIN32 > >> + v9lstat->st_ctime_nsec = 0; > >> +#else > >> v9lstat->st_ctime_nsec = stbuf->st_ctim.tv_nsec; > >> +#endif > >> /* Currently we only support BASIC fields in stat */ > >> v9lstat->st_result_mask = P9_STATS_BASIC; > >> > >> @@ -1639,7 +1684,10 @@ static int v9fs_do_readdir_with_stat(V9fsPDU > >> *pdu, > >> v9fs_path_init(&path); > >> err = v9fs_co_readdir_r(pdu, fidp, dent, &result); > >> if (err || !result) { > >> + error_printf("v9fs_do_readdir_with_stat: exiting...\n"); > >> break; > >> + } else { > >> + error_printf("v9fs_do_readdir_with_stat: continue\n"); > >> } > >> err = v9fs_co_name_to_path(pdu, &fidp->path, dent->d_name, > >> &path); > >> if (err < 0) { > >> @@ -1666,7 +1714,12 @@ static int v9fs_do_readdir_with_stat(V9fsPDU > >> *pdu, > >> count += len; > >> v9fs_stat_free(&v9stat); > >> v9fs_path_free(&path); > >> +#ifdef _WIN32 > >> + #warning "Probably right, but could make problems!" > >> + saved_dir_pos = v9fs_co_telldir(pdu, fidp); > >> +#else > >> saved_dir_pos = dent->d_off; > >> +#endif > >> } > >> out: > >> g_free(dent); > >> @@ -1806,6 +1859,9 @@ static int v9fs_do_readdir(V9fsPDU *pdu, > >> int32_t count = 0; > >> off_t saved_dir_pos; > >> struct dirent *dent, *result; > >> +#ifdef _WIN32 > >> + uint8_t type = 0; /* DT_UNKNOWN */ > >> +#endif > >> > >> /* save the directory position */ > >> saved_dir_pos = v9fs_co_telldir(pdu, fidp); > >> @@ -1818,15 +1874,27 @@ static int v9fs_do_readdir(V9fsPDU *pdu, > >> while (1) { > >> err = v9fs_co_readdir_r(pdu, fidp, dent, &result); > >> if (err || !result) { > >> + error_printf("v9fs_do_readdir: exiting...\n"); > >> break; > >> + } else { > >> + error_printf("v9fs_do_readdir: continue\n"); > >> } > >> v9fs_string_init(&name); > >> + if (!dent->d_name) { > >> + error_printf("\ndent->d_name is NULL!\n"); > >> + break; > >> + } else { > >> + error_printf("v9fs_do_readdir: entry is named %s, strlen > >> %u\n", > >> + dent->d_name, strlen(dent->d_name)); > >> + } > >> v9fs_string_sprintf(&name, "%s", dent->d_name); > >> if ((count + v9fs_readdir_data_size(&name)) > max_count) { > >> /* Ran out of buffer. Set dir back to old position and > >> return */ > >> v9fs_co_seekdir(pdu, fidp, saved_dir_pos); > >> v9fs_string_free(&name); > >> g_free(dent); > >> + error_printf("v9fs_do_readdir: RAN OUT OF BUFFER return > >> %d\n\n", > >> + count); > >> return count; > >> } > >> /* > >> @@ -1841,9 +1909,16 @@ static int v9fs_do_readdir(V9fsPDU *pdu, > >> qid.version = 0; > >> > >> /* 11 = 7 + 4 (7 = start offset, 4 = space for storing count) > >> */ > >> +#ifdef _WIN32 > >> + #warning "Probably right, but could make problems!" > >> + len = pdu_marshal(pdu, 11 + count, "Qqbs", > >> + &qid, v9fs_co_telldir(pdu, fidp), > >> + type, &name); > >> +#else > >> len = pdu_marshal(pdu, 11 + count, "Qqbs", > >> &qid, dent->d_off, > >> dent->d_type, &name); > >> +#endif > >> if (len < 0) { > >> v9fs_co_seekdir(pdu, fidp, saved_dir_pos); > >> v9fs_string_free(&name); > >> @@ -1852,12 +1927,18 @@ static int v9fs_do_readdir(V9fsPDU *pdu, > >> } > >> count += len; > >> v9fs_string_free(&name); > >> +#ifdef _WIN32 > >> + #warning "Probably right, but could make problems!" > >> + saved_dir_pos = v9fs_co_telldir(pdu, fidp); > >> +#else > >> saved_dir_pos = dent->d_off; > >> +#endif > >> } > >> g_free(dent); > >> if (err < 0) { > >> return err; > >> } > >> + error_printf("v9fs_do_readdir: return %d\n\n", count); > >> return count; > >> } > >> > >> @@ -1878,6 +1959,8 @@ static void v9fs_readdir(void *opaque) > >> goto out_nofid; > >> } > >> trace_v9fs_readdir(pdu->tag, pdu->id, fid, initial_offset, > >> max_count); > >> + error_printf("v9fs_readdir initial: %llu max count: %u\n", > >> + initial_offset, max_count); > >> > >> fidp = get_fid(pdu, fid); > >> if (fidp == NULL) { > >> @@ -1904,10 +1987,13 @@ static void v9fs_readdir(void *opaque) > >> } > >> retval += count + offset; > >> trace_v9fs_readdir_return(pdu->tag, pdu->id, count, retval); > >> + error_printf("v9fs_readdir: count: %d retval: %d\n\n", count, > >> retval); > >> out: > >> put_fid(pdu, fidp); > >> out_nofid: > >> pdu_complete(pdu, retval); > >> + > >> + error_printf("v9fs_readdir: return\n"); > >> } > >> > >> static int v9fs_xattr_write(V9fsState *s, V9fsPDU *pdu, V9fsFidState > >> *fidp, > >> @@ -2166,8 +2252,12 @@ static void v9fs_create(void *opaque) > >> } > >> v9fs_path_copy(&fidp->path, &path); > >> } else if (perm & P9_STAT_MODE_SOCKET) { > >> +#ifdef _WIN32 > >> + err = -1; > >> +#else > >> err = v9fs_co_mknod(pdu, fidp, &name, fidp->uid, -1, > >> 0, S_IFSOCK | (perm & 0777), &stbuf); > >> +#endif > >> if (err < 0) { > >> goto out; > >> } > >> @@ -3338,7 +3428,7 @@ int v9fs_device_realize_common(V9fsState *s, Error > >> **errp) > >> * call back to do that. Since we are in the init path, we don't > >> * use co-routines here. > >> */ > >> - if (s->ops->name_to_path(&s->ctx, NULL, "/", &path) < 0) { > >> + if (s->ops->name_to_path(&s->ctx, NULL, DELIMITER_STRING, &path) < > >> 0) { > >> error_setg(errp, > >> "error in converting name to path %s", > >> strerror(errno)); > >> goto out; > >> @@ -3370,6 +3460,7 @@ void v9fs_device_unrealize_common(V9fsState *s, > >> Error **errp) > >> > >> static void __attribute__((__constructor__)) v9fs_set_fd_limit(void) > >> { > >> +#ifndef _WIN32 > >> struct rlimit rlim; > >> if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) { > >> error_report("Failed to get the resource limit"); > >> @@ -3377,4 +3468,5 @@ static void __attribute__((__constructor__)) > >> v9fs_set_fd_limit(void) > >> } > >> open_fd_hw = rlim.rlim_cur - MIN(400, rlim.rlim_cur/3); > >> open_fd_rc = rlim.rlim_cur/2; > >> +#endif > >> } > >> diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h > >> index 1a19418..7bc8863 100644 > >> --- a/hw/9pfs/9p.h > >> +++ b/hw/9pfs/9p.h > >> @@ -3,7 +3,29 @@ > >> > >> #include <dirent.h> > >> #include <utime.h> > >> -#include <sys/resource.h> > >> +#ifdef _WIN32 > >> +/* Bad workaround, from http://octave.org/doxygen/3.4/fcntl_8h.html */ > >> +# define O_NOCTTY 0 > >> +# define O_NDELAY 0 > >> +# define O_NONBLOCK O_NDELAY > >> +# define O_DSYNC 0 > >> +# define O_DIRECT 0 > >> +# define O_DIRECTORY 0 > >> +# define O_NOFOLLOW 0 > >> +# define O_NOATIME 0 > >> +# define O_SYNC 0 > >> +# define O_ASYNC 0 > >> + > >> +# define FASYNC 0 > >> + > >> +# define AT_REMOVEDIR 1 > >> + > >> +# define NAME_MAX 260 > >> + > >> +#else > >> +# include <sys/resource.h> > >> +#endif > >> + > >> #include <glib.h> > >> #include "standard-headers/linux/virtio_9p.h" > >> #include "hw/virtio/virtio.h" > >> @@ -12,6 +34,10 @@ > >> #include "qemu/thread.h" > >> #include "qemu/coroutine.h" > >> > >> +#define DELIMITER_STRING "/" > >> +#define DELIMITER_IN_PATH "%s/%s" > >> +#define DELIMITER_IN_PATH2 "%s/%s/%s" > >> + > > > > Is this really needed (will there be different values for > > win32) ? If yes, I guess DELEMITER_STRING should be defined > > in a host arch specific header ? And anyway, this should be > > pushed to a separate patch. > I didn't like the spreading of this strings everywhere, so I defined these > constants. Yes, in the first step I thought I need them to be host OS > specific, but it turned out there is a better way. > > > > >> enum { > >> P9_TLERROR = 6, > >> P9_RLERROR, > >> @@ -108,9 +134,49 @@ enum p9_proto_version { > >> > >> #define FID_REFERENCED 0x1 > >> #define FID_NON_RECLAIMABLE 0x2 > >> + > >> +/* combines the host's root dir and the path to a complete host path */ > >> static inline char *rpath(FsContext *ctx, const char *path) > >> { > >> - return g_strdup_printf("%s/%s", ctx->fs_root, path); > >> + char *result; > >> + result = g_strdup_printf(DELIMITER_IN_PATH, ctx->fs_root, path); > >> +#ifdef _WIN32 > >> + int input = 0; > >> + int output = 0; > >> + while (result[input]) { > >> + /* error_printf("<-%d %c\n", input, result[input]); */ > >> + if (result[input] == '/') { > >> + result[output] = '\\'; > >> + /* remove duplicate \... */ > > > > Why do we need to remove duplicate \ ? > The other code relies that the host OS ignores dupplicate \ - they occured > in several places, e.g. when connecting the base (host) path and the path > given by the guest. Without remove them Windows bails out. > > > > >> + if (output > 0 && result[output - 1] == '\\') { > >> + /* error_printf("remove duplicate \\\n"); */ > >> + output--; > >> + } else { > >> + result[output] = '\\'; > >> + } > >> + /* error_printf(" %c\n", result[output]); */ > >> + } else { > >> + result[output] = result[input]; > >> + } > >> + /* error_printf("->%d %c\n\n", output, result[output]); */ > >> + input++; > >> + output++; > >> + } > >> + /* Kill last \ (but leave it if the char before is a : ...) > > > > Why kill last \ ? > Same reason as above ;-) > Ok, understood. > > > >> + So: > >> + C:\ -> C:\ > >> + C:\blah\ -> C:\blah > >> + b\ -> b > >> + blah\ -> blah */ > >> + if (output > 1 && result[output - 1] == '\\' > >> + && (output == 1 || result[output - 2] != ':')) { > >> + /* error_printf("Killed last \\\n"); */ > >> + result[output - 1] = '\0'; > >> + } else { > >> + result[output] = '\0'; > >> + } > >> +#endif > > > > I understand we need to convert / to \, but I don't see why > > we should remove duplicates... and anyway, this should be > > moved to a fixup helper. > Where should I move the function to? > In a #ifdef _WIN32 block just above the definition of rpath() would be a good start. > > > >> + return result; > >> } > >> > >> /* > >> diff --git a/hw/9pfs/Makefile.objs b/hw/9pfs/Makefile.objs > >> index da0ae0c..6f6ed19 100644 > >> --- a/hw/9pfs/Makefile.objs > >> +++ b/hw/9pfs/Makefile.objs > >> @@ -1,9 +1,10 @@ > >> common-obj-y = 9p.o > >> -common-obj-y += 9p-local.o 9p-xattr.o > >> -common-obj-y += 9p-xattr-user.o 9p-posix-acl.o > >> +common-obj-$(CONFIG_LINUX) += 9p-local.o 9p-xattr.o > >> +common-obj-$(CONFIG_LINUX) += 9p-xattr-user.o 9p-posix-acl.o > >> +common-obj-$(CONFIG_WIN32) += 9p-local.o > >> common-obj-y += coth.o cofs.o codir.o cofile.o > >> common-obj-y += coxattr.o 9p-synth.o > >> common-obj-$(CONFIG_OPEN_BY_HANDLE) += 9p-handle.o > >> -common-obj-y += 9p-proxy.o > >> +common-obj-$(CONFIG_POSIX) += 9p-proxy.o > >> > >> obj-y += virtio-9p-device.o > >> diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c > >> index 91df7f7..399bd8a 100644 > >> --- a/hw/9pfs/codir.c > >> +++ b/hw/9pfs/codir.c > >> @@ -17,6 +17,8 @@ > >> #include "qemu/thread.h" > >> #include "qemu/coroutine.h" > >> #include "coth.h" > >> +/* mifritscher: after killing the debug printf, kill this as well! */ > >> +#include "qemu/error-report.h" > >> > >> int v9fs_co_readdir_r(V9fsPDU *pdu, V9fsFidState *fidp, struct dirent > >> *dent, > >> struct dirent **result) > >> @@ -37,6 +39,12 @@ int v9fs_co_readdir_r(V9fsPDU *pdu, V9fsFidState > >> *fidp, struct dirent *dent, > >> err = 0; > >> } > >> }); > >> +#ifdef _WIN32 > >> + error_printf("v9fs_co_readdir_r: %s %d %p\n", > >> + (&fidp->fs)->dir->dd_name, err, *result); > >> +#else > >> + error_printf("v9fs_co_readdir_r: %d %p\n", err, *result); > >> +#endif > >> return err; > >> } > >> > >> @@ -55,6 +63,12 @@ off_t v9fs_co_telldir(V9fsPDU *pdu, V9fsFidState > >> *fidp) > >> err = -errno; > >> } > >> }); > >> +#ifdef _WIN32 > >> + error_printf("v9fs_co_telldir_r: %s %lld\n", > >> + (&fidp->fs)->dir->dd_name, err); > >> +#else > >> + error_printf("v9fs_co_telldir_r: %ld\n", err); > >> +#endif > >> return err; > >> } > >> > >> @@ -68,6 +82,11 @@ void v9fs_co_seekdir(V9fsPDU *pdu, V9fsFidState > >> *fidp, off_t offset) > >> { > >> s->ops->seekdir(&s->ctx, &fidp->fs, offset); > >> }); > >> +#ifdef _WIN32 > >> + error_printf("v9fs_co_seekdir: %s\n", (&fidp->fs)->dir->dd_name); > >> +#else > >> + error_printf("v9fs_co_seekdir\n"); > >> +#endif > >> } > >> > >> void v9fs_co_rewinddir(V9fsPDU *pdu, V9fsFidState *fidp) > >> @@ -80,6 +99,11 @@ void v9fs_co_rewinddir(V9fsPDU *pdu, V9fsFidState > >> *fidp) > >> { > >> s->ops->rewinddir(&s->ctx, &fidp->fs); > >> }); > >> +#ifdef _WIN32 > >> + error_printf("v9fs_co_rewinddir: %s\n", (&fidp->fs)->dir->dd_name); > >> +#else > >> + error_printf("v9fs_co_rewinddir\n"); > >> +#endif > >> } > >> > >> int v9fs_co_mkdir(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name, > >> @@ -116,6 +140,7 @@ int v9fs_co_mkdir(V9fsPDU *pdu, V9fsFidState *fidp, > >> V9fsString *name, > >> } > >> }); > >> v9fs_path_unlock(s); > >> + error_printf("v9fs_co_mkdir: %d\n", err); > >> return err; > >> } > >> > >> @@ -144,6 +169,11 @@ int v9fs_co_opendir(V9fsPDU *pdu, V9fsFidState > >> *fidp) > >> v9fs_reclaim_fd(pdu); > >> } > >> } > >> +#ifdef _WIN32 > >> + error_printf("v9fs_co_opendir: %s %d\n", (&fidp->fs)->dir->dd_name, > >> err); > >> +#else > >> + error_printf("v9fs_co_opendir: %d\n", err); > >> +#endif > >> return err; > >> } > >> > >> @@ -165,5 +195,6 @@ int v9fs_co_closedir(V9fsPDU *pdu, V9fsFidOpenState > >> *fs) > >> if (!err) { > >> total_open_fd--; > >> } > >> + error_printf("v9fs_co_closedir: %d\n", err); > >> return err; > >> } > >> diff --git a/hw/9pfs/cofile.c b/hw/9pfs/cofile.c > >> index 293483e..a9c1a10 100644 > >> --- a/hw/9pfs/cofile.c > >> +++ b/hw/9pfs/cofile.c > >> @@ -17,6 +17,8 @@ > >> #include "qemu/thread.h" > >> #include "qemu/coroutine.h" > >> #include "coth.h" > >> +/* mifritscher: after killing the debug printf, kill this as well! */ > >> +#include "qemu/error-report.h" > >> > >> int v9fs_co_st_gen(V9fsPDU *pdu, V9fsPath *path, mode_t st_mode, > >> V9fsStatDotl *v9stat) > >> @@ -39,6 +41,7 @@ int v9fs_co_st_gen(V9fsPDU *pdu, V9fsPath *path, > >> mode_t st_mode, > >> }); > >> v9fs_path_unlock(s); > >> } > >> + error_printf("v9fs_co_st_gen: %d\n", err); > >> return err; > >> } > >> > >> @@ -59,6 +62,7 @@ int v9fs_co_lstat(V9fsPDU *pdu, V9fsPath *path, struct > >> stat *stbuf) > >> } > >> }); > >> v9fs_path_unlock(s); > >> + error_printf("v9fs_co_lstat: %d\n", err); > >> return err; > >> } > >> > >> @@ -91,6 +95,7 @@ int v9fs_co_fstat(V9fsPDU *pdu, V9fsFidState *fidp, > >> struct stat *stbuf) > >> err = 0; > >> } > >> } > >> + error_printf("v9fs_co_fstat: %s %d\n", (&fidp->path)->data, err); > >> return err; > >> } > >> > >> @@ -119,6 +124,7 @@ int v9fs_co_open(V9fsPDU *pdu, V9fsFidState *fidp, > >> int flags) > >> v9fs_reclaim_fd(pdu); > >> } > >> } > >> + error_printf("v9fs_co_open: %s %d\n", (&fidp->path)->data, err); > >> return err; > >> } > >> > >> @@ -147,13 +153,17 @@ int v9fs_co_open2(V9fsPDU *pdu, V9fsFidState > >> *fidp, V9fsString *name, gid_t gid, > >> { > >> err = s->ops->open2(&s->ctx, &fidp->path, > >> name->data, flags, &cred, &fidp->fs); > >> + error_printf("v9fs_co_open2: open returned %d\n", err); > >> if (err < 0) { > >> err = -errno; > >> } else { > >> v9fs_path_init(&path); > >> err = v9fs_name_to_path(s, &fidp->path, name->data, > >> &path); > >> + error_printf("v9fs_co_open2: v9fs_name_to_path returned > >> %d\n", > >> + err); > >> if (!err) { > >> err = s->ops->lstat(&s->ctx, &path, stbuf); > >> + error_printf("v9fs_co_open2: lstat returned %d\n", > >> err); > >> if (err < 0) { > >> err = -errno; > >> s->ops->close(&s->ctx, &fidp->fs); > >> @@ -173,6 +183,7 @@ int v9fs_co_open2(V9fsPDU *pdu, V9fsFidState *fidp, > >> V9fsString *name, gid_t gid, > >> v9fs_reclaim_fd(pdu); > >> } > >> } > >> + error_printf("v9fs_co_open2: %s %d\n", (&fidp->path)->data, err); > >> return err; > >> } > >> > >> @@ -194,6 +205,7 @@ int v9fs_co_close(V9fsPDU *pdu, V9fsFidOpenState > >> *fs) > >> if (!err) { > >> total_open_fd--; > >> } > >> + error_printf("v9fs_co_close: %d\n", err); > >> return err; > >> } > >> > >> @@ -234,6 +246,7 @@ int v9fs_co_link(V9fsPDU *pdu, V9fsFidState *oldfid, > >> } > >> }); > >> v9fs_path_unlock(s); > >> + error_printf("v9fs_co_link: %d\n", err); > >> return err;SWUP > >> } > >> > >> @@ -253,6 +266,7 @@ int v9fs_co_pwritev(V9fsPDU *pdu, V9fsFidState > >> *fidp, > >> err = -errno; > >> } > >> }); > >> + error_printf("v9fs_co_pwritev: %s %d\n", (&fidp->path)->data, err); > >> return err; > >> } > >> > >> @@ -272,5 +286,6 @@ int v9fs_co_preadv(V9fsPDU *pdu, V9fsFidState *fidp, > >> err = -errno; > >> } > >> }); > >> + error_printf("v9fs_co_preadv: %s %d\n", (&fidp->path)->data, err); > >> return err; > >> } > >> diff --git a/hw/9pfs/cofs.c b/hw/9pfs/cofs.c > >> index 18c81cb..a3a42bf 100644 > >> --- a/hw/9pfs/cofs.c > >> +++ b/hw/9pfs/cofs.c > >> @@ -17,6 +17,8 @@ > >> #include "qemu/thread.h" > >> #include "qemu/coroutine.h" > >> #include "coth.h" > >> +/* mifritscher: after killing the debug printf, kill this as well! */ > >> +#include "qemu/error-report.h" > >> > >> static ssize_t __readlink(V9fsState *s, V9fsPath *path, V9fsString > >> *buf) > >> { > >> @@ -67,6 +69,7 @@ int v9fs_co_readlink(V9fsPDU *pdu, V9fsPath *path, > >> V9fsString *buf) > >> } > >> }); > >> v9fs_path_unlock(s); > >> + error_printf("v9fs_co_readlink: %d\n", err); > >> return err; > >> }SWUP > >> > >> @@ -87,6 +90,7 @@ int v9fs_co_statfs(V9fsPDU *pdu, V9fsPath *path, > >> struct statfs *stbuf) > >> } > >> }); > >> v9fs_path_unlock(s); > >> + error_printf("v9fs_co_statfs: %d\n", err); > >> return err; > >> } > >> > >> @@ -110,6 +114,7 @@ int v9fs_co_chmod(V9fsPDU *pdu, V9fsPath *path, > >> mode_t mode) > >> } > >> }); > >> v9fs_path_unlock(s); > >> + error_printf("v9fs_co_chmod: %d\n", err); > >> return err; > >> } > >> > >> @@ -131,6 +136,7 @@ int v9fs_co_utimensat(V9fsPDU *pdu, V9fsPath *path, > >> } > >> }); > >> v9fs_path_unlock(s); > >> + error_printf("v9fs_co_utimensat: %d\n", err); > >> return err; > >> } > >> > >> @@ -155,6 +161,7 @@ int v9fs_co_chown(V9fsPDU *pdu, V9fsPath *path, > >> uid_t uid, gid_t gid) > >> } > >> }); > >> v9fs_path_unlock(s); > >> + error_printf("v9fs_co_chown: %d\n", err); > >> return err; > >> } > >> > >> @@ -175,6 +182,7 @@ int v9fs_co_truncate(V9fsPDU *pdu, V9fsPath *path, > >> off_t size) > >> } > >> }); > >> v9fs_path_unlock(s); > >> + error_printf("v9fs_co_truncate: %d\n", err); > >> return err; > >> } > >> > >> @@ -213,6 +221,7 @@ int v9fs_co_mknod(V9fsPDU *pdu, V9fsFidState *fidp, > >> V9fsString *name, uid_t uid, > >> } > >> }); > >> v9fs_path_unlock(s); > >> + error_printf("v9fs_co_mknod: %d\n", err); > >> return err; > >> } > >> > >> @@ -234,6 +243,7 @@ int v9fs_co_remove(V9fsPDU *pdu, V9fsPath *path) > >> } > >> }); > >> v9fs_path_unlock(s); > >> + error_printf("v9fs_co_remove: %d\n", err); > >> return err; > >> } > >> > >> @@ -254,6 +264,7 @@ int v9fs_co_unlinkat(V9fsPDU *pdu, V9fsPath *path, > >> V9fsString *name, int flags) > >> } > >> }); > >> v9fs_path_unlock(s); > >> + error_printf("v9fs_co_unlinkat: %d\n", err); > >> return err; > >> } > >> > >> @@ -273,6 +284,7 @@ int v9fs_co_rename(V9fsPDU *pdu, V9fsPath *oldpath, > >> V9fsPath *newpath) > >> err = -errno; > >> } > >> }); > >> + error_printf("v9fs_co_rename: %d\n", err); > >> return err; > >> } > >> > >> @@ -293,6 +305,7 @@ int v9fs_co_renameat(V9fsPDU *pdu, V9fsPath > >> *olddirpath, V9fsString *oldname, > >> err = -errno; > >> } > >> }); > >> + error_printf("v9fs_co_renameat: %d\n", err); > >> return err; > >> } > >> > >> @@ -331,6 +344,7 @@ int v9fs_co_symlink(V9fsPDU *pdu, V9fsFidState > >> *dfidp, V9fsString *name, > >> } > >> }); > >> v9fs_path_unlock(s); > >> + error_printf("v9fs_co_symlink: %d\n", err); > >> return err; > >> } > >> > >> @@ -361,5 +375,6 @@ int v9fs_co_name_to_path(V9fsPDU *pdu, V9fsPath > >> *dirpath, > >> } > >> }); > >> } > >> + error_printf("v9fs_co_name_to_path: %d\n", err); > >> return err; > >> } > >> diff --git a/hw/9pfs/coxattr.c b/hw/9pfs/coxattr.c > >> index 6ad96ea..49fbd5e 100644 > >> --- a/hw/9pfs/coxattr.c > >> +++ b/hw/9pfs/coxattr.c > >> @@ -17,6 +17,8 @@ > >> #include "qemu/thread.h" > >> #include "qemu/coroutine.h" > >> #include "coth.h" > >> +/* mifritscher: after killing the debug printf, kill this as well! */ > >> +#include "qemu/error-report.h" > >> > >> int v9fs_co_llistxattr(V9fsPDU *pdu, V9fsPath *path, void *value, > >> size_t size) > >> { > >> @@ -35,6 +37,7 @@ int v9fs_co_llistxattr(V9fsPDU *pdu, V9fsPath *path, > >> void *value, size_t size) > >> } > >> }); > >> v9fs_path_unlock(s); > >> + error_printf("v9fs_co_llistxattr: %d\n", err); > >> return err; > >> } > >> > >> @@ -59,6 +62,7 @@ int v9fs_co_lgetxattr(V9fsPDU *pdu, V9fsPath *path, > >> } > >> }); > >> v9fs_path_unlock(s); > >> + error_printf("v9fs_co_lgetxattr: %d\n", err); > >> return err; > >> } > >> > >> @@ -83,6 +87,7 @@ int v9fs_co_lsetxattr(V9fsPDU *pdu, V9fsPath *path, > >> } > >> }); > >> v9fs_path_unlock(s); > >> + error_printf("v9fs_co_lsetxattr: %d\n", err); > >> return err; > >> } > >> > >> @@ -104,5 +109,6 @@ int v9fs_co_lremovexattr(V9fsPDU *pdu, V9fsPath > >> *path, > >> } > >> }); > >> v9fs_path_unlock(s); > >> + error_printf("v9fs_co_lremovexattr: %d\n", err); > >> return err; > >> } > >> diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c > >> index a38850e..59d0a50 100644 > >> --- a/hw/9pfs/virtio-9p-device.c > >> +++ b/hw/9pfs/virtio-9p-device.c > >> @@ -17,7 +17,9 @@ > >> #include "qemu/sockets.h" > >> #include "virtio-9p.h" > >> #include "fsdev/qemu-fsdev.h" > >> -#include "9p-xattr.h" > >> +#ifndef WIN32 > >> + #include "9p-xattr.h" > >> +#endif > >> #include "coth.h" > >> #include "hw/virtio/virtio-access.h" > >> #include "qemu/iov.h" > > > > > >
Good day, only a short announcement: Sorry for the very long delay :-( But I'm working on this again. The biggest issue seems to be the *at stuff. I'll try to workaround this via getting the directories' path from the file descriptor with the /proc (as it is already done in the 9pfs_utils) - luckily,the mingw environment emulates the /proc. If this doesn't work I've another idea (the file descriptors needs to be "registered" with the path (and saved in a sparse vector or map with the fd as key and the path as value). The "big" solution would be to write a 9p_local_windows.c from scratch, but I would like to avoid it. Additionally, I changed my approach: Instead of one big patch with everything in it, I split it into 2 patch series with several patches: * The first one only fixes the build via adding #ifdefs, creating stubs in os-win32.h etc. and introduces no regressions. Status: Ready in my local repo: It compiles fine with enabled 9pfs and works. If 9pfs is tried to use there is a clean error message that the fsdev couldn't be initialized - as expected. * The second one actually get 9pfs working. This involves mostly implementing the *at functions and a few tiny things (O_BINARY and so on) Status: Not started yet (will be at the next weekend I hope), but is a combination of parts of the the old patch + the implementation of the *at functions. My hope is that the first series could be merged independently from the second. Meanings? If so I'll clean up the first patch series a bit (History cleaning) and send it to the list. Best regards, Michael Fritscher
On Mon, 28 Aug 2017 09:35:45 +0200 "Michael Fritscher" <michael@fritscher.net> wrote: > Good day, > Hi! > only a short announcement: Sorry for the very long delay :-( But I'm > working on this again. The biggest issue seems to be the *at stuff. I'll > try to workaround this via getting the directories' path from the file > descriptor with the /proc (as it is already done in the 9pfs_utils) - > luckily,the mingw environment emulates the /proc. If this doesn't work > I've another idea (the file descriptors needs to be "registered" with the > path (and saved in a sparse vector or map with the fd as key and the path > as value). The "big" solution would be to write a 9p_local_windows.c from > scratch, but I would like to avoid it. > > Additionally, I changed my approach: Instead of one big patch with > everything in it, I split it into 2 patch series with several patches: > I'd prefer to have a single series with all the patches because... > * The first one only fixes the build via adding #ifdefs, creating stubs > in os-win32.h etc. and introduces no regressions. Status: Ready in my > local repo: It compiles fine with enabled 9pfs and works. If 9pfs is > tried to use there is a clean error message that the fsdev couldn't be > initialized - as expected. > * The second one actually get 9pfs working. This involves mostly > implementing the *at functions and a few tiny things (O_BINARY and so > on) Status: Not started yet (will be at the next weekend I hope), but is > a combination of parts of the the old patch + the implementation of the > *at functions. > > My hope is that the first series could be merged independently from the > second. Meanings? If so I'll clean up the first patch series a bit ... I don't want to merge a bunch of code before I'm 100% sure the 9pfs support on win32 is viable. Cheers, -- Greg > (History cleaning) and send it to the list. > > Best regards, > Michael Fritscher >
diff --git a/Makefile.objs b/Makefile.objs index 8f705f6..6fd02bc 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -48,6 +48,7 @@ common-obj-$(CONFIG_WIN32) += os-win32.o common-obj-$(CONFIG_POSIX) += os-posix.o common-obj-$(CONFIG_LINUX) += fsdev/ +common-obj-$(CONFIG_WIN32) += fsdev/ common-obj-y += migration/ common-obj-y += qemu-char.o #aio.o diff --git a/configure b/configure index 5db29f0..a4797c3 100755 --- a/configure +++ b/configure @@ -4566,12 +4566,21 @@ if test "$want_tools" = "yes" ; then fi if test "$softmmu" = yes ; then if test "$virtfs" != no ; then - if test "$cap" = yes && test "$linux" = yes && test "$attr" = yes ; then + if test "$linux" = yes ; then + if test "$cap" = yes && test "$attr" = yes ; then + virtfs=yes + tools="$tools fsdev/virtfs-proxy-helper\$(EXESUF)" + else + if test "$virtfs" = yes; then + error_exit "VirtFS requires libcap-devel and libattr-devel on Linux" + fi + virtfs=no + fi + elif test "$mingw32" = yes; then virtfs=yes - tools="$tools fsdev/virtfs-proxy-helper\$(EXESUF)" else if test "$virtfs" = yes; then - error_exit "VirtFS is supported only on Linux and requires libcap-devel and libattr-devel" + error_exit "VirtFS is only supported on Linux or Windows" fi virtfs=no fi diff --git a/fsdev/9p-iov-marshal.c b/fsdev/9p-iov-marshal.c index fb40bdf..1a292c6 100644 --- a/fsdev/9p-iov-marshal.c +++ b/fsdev/9p-iov-marshal.c @@ -15,7 +15,9 @@ #include <glib.h> #include <glib/gprintf.h> #include <utime.h> +#ifndef _WIN32 #include <sys/uio.h> +#endif #include "9p-iov-marshal.h" #include "qemu/bswap.h" diff --git a/fsdev/9p-marshal.c b/fsdev/9p-marshal.c index 183d366..081cb88 100644 --- a/fsdev/9p-marshal.c +++ b/fsdev/9p-marshal.c @@ -16,7 +16,9 @@ #include <glib/gprintf.h> #include <dirent.h> #include <utime.h> -#include <sys/uio.h> +#ifndef WIN32 + #include <sys/uio.h> +#endif #include "9p-marshal.h" diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h index b8c2602..446c6a5 100644 --- a/fsdev/file-op-9p.h +++ b/fsdev/file-op-9p.h @@ -14,12 +14,43 @@ #define _FILEOP_H #include <dirent.h> #include <utime.h> -#include <sys/uio.h> -#include <sys/vfs.h> +#ifndef _WIN32 + #include <sys/uio.h> + #include <sys/vfs.h> +#endif #define SM_LOCAL_MODE_BITS 0600 #define SM_LOCAL_DIR_MODE_BITS 0700 +#ifdef _WIN32 +typedef uint32_t uid_t; +typedef uint32_t gid_t; + +/* from http://man7.org/linux/man-pages/man2/statfs.2.html */ +typedef uint32_t __fsword_t; +typedef uint32_t fsblkcnt_t; +typedef uint32_t fsfilcnt_t; + +/* from linux/include/uapi/asm-generic/posix_types.h */ +typedef struct { + long __val[2]; +} fsid_t; + +struct statfs { + __fsword_t f_type; + __fsword_t f_bsize; + fsblkcnt_t f_blocks; + fsblkcnt_t f_bfree; + fsblkcnt_t f_bavail; + fsfilcnt_t f_files; + fsfilcnt_t f_ffree; + fsid_t f_fsid; + __fsword_t f_namelen; + __fsword_t f_frsize; + __fsword_t f_flags; +}; +#endif + typedef struct FsCred { uid_t fc_uid; diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c index bf7f0b0..384d72e 100644 --- a/fsdev/qemu-fsdev.c +++ b/fsdev/qemu-fsdev.c @@ -26,7 +26,9 @@ static FsDriverTable FsDrivers[] = { { .name = "handle", .ops = &handle_ops}, #endif { .name = "synth", .ops = &synth_ops}, +#ifndef WIN32 { .name = "proxy", .ops = &proxy_ops}, +#endif }; int qemu_fsdev_add(QemuOpts *opts) diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c index 16f45f4..710ab5f 100644 --- a/hw/9pfs/9p-local.c +++ b/hw/9pfs/9p-local.c @@ -12,23 +12,174 @@ */ #include "qemu/osdep.h" +/* mifritscher: after killing the debug printf, kill this as well! */ +#include "qemu/error-report.h" #include "9p.h" -#include "9p-xattr.h" +#ifdef _WIN32 +/* idea from http://mingw-users.1079350.n2.nabble.com/Undefined-reference-to-quot-lstat-quot-and-quot-S-ISLNK-quot-td5450984.html */ +# define lstat(path, buffer) stat(path, buffer) + +# define mkdir(path, mode) mkdir(path) +# define getxattr(buffer, name, pointer, length) 0 + +/* pretend success */ +static int setxattr(const char *path, const char *name, + const void *value, size_t size, int flags) +{ + return 0; +} + +static ssize_t fgetxattr(int fd, const char *name, + void *value, size_t size) +{ + return 0; +} + +# define lchown(buffer, uid, gid) 0 +# define readlink(buffer, buf, bufsz) 0 +# define mknod(buffer, mode, u) 0 +# define link(buffer, buffer1) 0 +# define symlink(buffer, buffer1) 0 + +static ssize_t v9fs_get_xattr(FsContext *ctx, const char *path, + const char *name, void *value, size_t size) +{ + errno = 95; /* EOPNOTSUP - wrong definition in mingw(130); */ + return -1; +} + +static ssize_t v9fs_list_xattr(FsContext *ctx, const char *path, + void *value, size_t vsize) +{ + errno = 95; /* EOPNOTSUP - wrong definition in mingw(130); */ + return -1; +} + +static int v9fs_set_xattr(FsContext *ctx, const char *path, + const char *name, void *value, size_t size, + int flags) +{ + errno = 95; /* EOPNOTSUP - wrong definition in mingw(130); */ + return -1; +} + +static int v9fs_remove_xattr(FsContext *ctx, const char *path, + const char *name) +{ + errno = 95; /* EOPNOTSUP - wrong definition in mingw(130); */ + return -1; +} + +static int readdir_r(DIR *dirp, struct dirent *entry, + struct dirent **result) +{ + struct dirent *temp; + errno = 0; + temp = readdir(dirp); + if (temp == 0) { + error_printf("readdir_r: End of directory reached -> returning NULL\n"); + *result = 0; + } else { + /* Copy it from the stack to the buffer got from the caller */ + memcpy(entry, temp, sizeof(struct dirent)); + error_printf("readdir_r: Name: %hu %s\n", + temp->d_namlen, temp->d_name); + error_printf("readdir_r: Name: %hu %s\n", + entry->d_namlen, entry->d_name); + *result = entry; + } + return errno; +} + +/* Can be done better... */ +static int statfs(const char *file, struct statfs *buf) +{ + memset(buf, 0, sizeof(struct statfs)); + buf->f_type = 0x01021997; /* V9FS_MAGIC */ + buf->f_bsize = 4096; + buf->f_blocks = 4000000; + buf->f_bfree = 3000000; + buf->f_bavail = 2999000; + buf->f_files = 1000000; + buf->f_ffree = 800000; + buf->f_namelen = NAME_MAX; + return 0; +} + +/* a crude hash function (needed for fake inodes) */ +static ino_t hash(const char *path) +{ + ino_t result = (ino_t)41021998; + int len = strlen(path); + if (!len) { + return result; + } + + /* Q&D canolizement of the path */ + if (path[len - 1] == '\\' || path[len - 1] == '/') { + len--; + } + if (!len) { + return result; + } + + if (path[len - 1] == '.') { + if (len == 1) { + return result; + } + len--; + if (path[len - 1] == '\\' || path[len - 1] == '/') { + len--; + /* .. -> kill last part */ + } else if (path[len - 1] == '.') { + len--; + while (len) { + if (path[len - 1] == '\\' || path[len - 1] == '/') { + len--; + break; + } + len--; + } + } + } + + if (!len) { + return result; + } + + for (int i = 0; i < len; i++) { + result += path[i] << (i % 7); + result += path[i] << ((i + 11) % 17); + result += path[i] << ((i + 19) % 23); + } + + return result; +} + +#else +# include "9p-xattr.h" +#endif #include "fsdev/qemu-fsdev.h" /* local_ops */ +#ifndef _WIN32 #include <arpa/inet.h> #include <pwd.h> #include <grp.h> #include <sys/socket.h> #include <sys/un.h> #include "qemu/xattr.h" +#endif #include "qemu/cutils.h" #include "qemu/error-report.h" #include <libgen.h> -#include <linux/fs.h> +#ifndef _WIN32 + #include <linux/fs.h> +#endif #ifdef CONFIG_LINUX_MAGIC_H #include <linux/magic.h> #endif +#ifndef _WIN32 #include <sys/ioctl.h> +#endif #ifndef XFS_SUPER_MAGIC #define XFS_SUPER_MAGIC 0x58465342 @@ -76,7 +227,7 @@ static FILE *local_fopen(const char *path, const char *mode) } else { return NULL; } - fd = open(path, flags, o_mode); + fd = open(path, flags | O_BINARY, o_mode); if (fd == -1) { return NULL; } @@ -124,10 +275,20 @@ static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf) char *path = fs_path->data; buffer = rpath(fs_ctx, path); - err = lstat(buffer, stbuf); + error_printf("\nrpath %s + %s -> %s\n\n", fs_ctx->fs_root, path, buffer); + err = lstat(buffer, stbuf); if (err) { goto err_out; } +#ifdef _WIN32 + /* This way, all files are executable + (MingW seems to do 777 on dirs, but 666 on files) */ + stbuf->st_mode |= S_IXUSR | S_IXGRP | S_IXOTH; + + /* Under WIN32 (MingW), st_ino seems to be always 2, + which leads to confusion */ + stbuf->st_ino = hash(path); +#endif if (fs_ctx->export_flags & V9FS_SM_MAPPED) { /* Actual credentials are part of extended attrs */ uid_t tmp_uid; @@ -162,7 +323,7 @@ static int local_create_mapped_attr_dir(FsContext *ctx, const char *path) char *attr_dir; char *tmp_path = g_strdup(path); - attr_dir = g_strdup_printf("%s/%s/%s", + attr_dir = g_strdup_printf(DELIMITER_IN_PATH2, ctx->fs_root, dirname(tmp_path), VIRTFS_META_DIR); err = mkdir(attr_dir, 0700); @@ -223,7 +384,8 @@ update_map_file: if (credp->fc_gid != -1) { gid = credp->fc_gid; } - if (credp->fc_mode != -1) { + /* mifritscher: is normally unsigned... */ + if ((int16_t)(credp->fc_mode) != -1) { mode = credp->fc_mode; } if (credp->fc_rdev != -1) { @@ -268,7 +430,8 @@ static int local_set_xattr(const char *path, FsCred *credp) return err; } } - if (credp->fc_mode != -1) { + /* mifritscher: is normally unsigned... */ + if ((int16_t)(credp->fc_mode) != -1) { uint32_t tmp_mode = cpu_to_le32(credp->fc_mode); err = setxattr(path, "user.virtfs.mode", &tmp_mode, sizeof(mode_t), 0); if (err) { @@ -323,7 +486,7 @@ static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path, (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE)) { int fd; buffer = rpath(fs_ctx, path); - fd = open(buffer, O_RDONLY | O_NOFOLLOW); + fd = open(buffer, O_RDONLY | O_NOFOLLOW | O_BINARY); g_free(buffer); if (fd == -1) { return -1; @@ -358,7 +521,8 @@ static int local_open(FsContext *ctx, V9fsPath *fs_path, char *path = fs_path->data; buffer = rpath(ctx, path); - fs->fd = open(buffer, flags | O_NOFOLLOW); + error_printf("File which should be opened: %s\n", buffer); + fs->fd = open(buffer, flags | O_NOFOLLOW | O_BINARY); g_free(buffer); return fs->fd; } @@ -370,6 +534,7 @@ static int local_opendir(FsContext *ctx, char *path = fs_path->data; buffer = rpath(ctx, path); + error_printf("Directory (opendir) which should be opened: %s\n", buffer); fs->dir = opendir(buffer); g_free(buffer); if (!fs->dir) { @@ -395,17 +560,36 @@ static int local_readdir_r(FsContext *ctx, V9fsFidOpenState *fs, int ret; again: +#ifdef _WIN32 + error_printf("local_readdir_r: Directory which should be read:%s\n", + fs->dir->dd_name); +#endif ret = readdir_r(fs->dir, entry, result); if (ctx->export_flags & V9FS_SM_MAPPED) { +#ifndef _WIN32 entry->d_type = DT_UNKNOWN; +#endif } else if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { if (!ret && *result != NULL && !strcmp(entry->d_name, VIRTFS_META_DIR)) { /* skp the meta data directory */ goto again; } +#ifndef _WIN32 entry->d_type = DT_UNKNOWN; +#endif } + if (*result == NULL) { + error_printf("local_readdir_r: End of directory -> returning NULL\n"); + } else { +#ifdef _WIN32 + error_printf("local_readdir_r: Name: %hu %s\n", + entry->d_namlen, entry->d_name); +#else + error_printf("local_readdir_r: Name: %s\n", entry->d_name); +#endif + } + error_printf("local_readdir_r: return %d\n", ret); return ret; } @@ -418,10 +602,15 @@ static ssize_t local_preadv(FsContext *ctx, V9fsFidOpenState *fs, const struct iovec *iov, int iovcnt, off_t offset) { + error_printf("local_preadv: #iov: %u, addr: %p, #bytes: %u, offset: %llu\n", + iovcnt, iov->iov_base, iov->iov_len, offset); #ifdef CONFIG_PREADV + error_printf("local_preadv: using preadv\n"); return preadv(fs->fd, iov, iovcnt, offset); #else + error_printf("local_preadv: not using preadv\n"); int err = lseek(fs->fd, offset, SEEK_SET); + error_printf("local_preadv: lseek returned %d\n", err); if (err == -1) { return err; } else { @@ -491,7 +680,7 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path, char *buffer = NULL; v9fs_string_init(&fullname); - v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); + v9fs_string_sprintf(&fullname, DELIMITER_IN_PATH, dir_path->data, name); path = fullname.data; /* Determine the security model */ @@ -552,7 +741,7 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path, char *buffer = NULL; v9fs_string_init(&fullname); - v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); + v9fs_string_sprintf(&fullname, DELIMITER_IN_PATH, dir_path->data, name); path = fullname.data; /* Determine the security model */ @@ -610,7 +799,14 @@ static int local_fstat(FsContext *fs_ctx, int fid_type, int err, fd; if (fid_type == P9_FID_DIR) { + /* Don't know if that's right... + (on WIN32/mingw, DIR has no fd entry) */ +#ifdef _WIN32 + #warning "Could cause problems!" + fd = fs->fd; +#else fd = dirfd(fs->dir); +#endif } else { fd = fs->fd; } @@ -619,6 +815,13 @@ static int local_fstat(FsContext *fs_ctx, int fid_type, if (err) { return err; } +#ifdef _WIN32 + /* This way, all files are executable + (MingW seems to do 777 on dirs, but 666 on files) */ + stbuf->st_mode |= S_IXUSR | S_IXGRP | S_IXOTH; + + /* mifritscher: TODO: fake inode? */ +#endif if (fs_ctx->export_flags & V9FS_SM_MAPPED) { /* Actual credentials are part of extended attrs */ uid_t tmp_uid; @@ -661,13 +864,16 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name, flags |= O_NOFOLLOW; v9fs_string_init(&fullname); - v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); + v9fs_string_sprintf(&fullname, DELIMITER_IN_PATH, dir_path->data, name); path = fullname.data; + error_printf("local_open2: got %s %s\n", dir_path->data, name); + error_printf("local_open2: full path: %s\n", path); + /* Determine the security model */ if (fs_ctx->export_flags & V9FS_SM_MAPPED) { buffer = rpath(fs_ctx, path); - fd = open(buffer, flags, SM_LOCAL_MODE_BITS); + fd = open(buffer, flags | O_BINARY, SM_LOCAL_MODE_BITS); if (fd == -1) { err = fd; goto out; @@ -681,7 +887,7 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name, } } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { buffer = rpath(fs_ctx, path); - fd = open(buffer, flags, SM_LOCAL_MODE_BITS); + fd = open(buffer, flags | O_BINARY, SM_LOCAL_MODE_BITS); if (fd == -1) { err = fd; goto out; @@ -696,12 +902,17 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name, } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) || (fs_ctx->export_flags & V9FS_SM_NONE)) { buffer = rpath(fs_ctx, path); - fd = open(buffer, flags, credp->fc_mode); + error_printf("local_open2: File which should be opened (open2): %s\n", + buffer); + fd = open(buffer, flags | O_BINARY, credp->fc_mode); + error_printf("local_open2: open returned %d\n", fd); if (fd == -1) { err = fd; goto out; } err = local_post_create_passthrough(fs_ctx, path, credp); + error_printf("local_open2: local_post_create_passthrough returned %u\n", + err); if (err == -1) { serrno = errno; goto err_end; @@ -732,7 +943,7 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath, char *buffer = NULL; v9fs_string_init(&fullname); - v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); + v9fs_string_sprintf(&fullname, DELIMITER_IN_PATH, dir_path->data, name); newpath = fullname.data; /* Determine the security model */ @@ -740,7 +951,9 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath, int fd; ssize_t oldpath_size, write_size; buffer = rpath(fs_ctx, newpath); - fd = open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, SM_LOCAL_MODE_BITS); + fd = open(buffer, + O_CREAT | O_EXCL | O_RDWR | O_NOFOLLOW | O_BINARY, + SM_LOCAL_MODE_BITS); if (fd == -1) { err = fd; goto out; @@ -758,8 +971,10 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath, goto err_end; } close(fd); - /* Set cleint credentials in symlink's xattr */ + /* Set client credentials in symlink's xattr */ +#ifndef _WIN32 credp->fc_mode = credp->fc_mode|S_IFLNK; +#endif err = local_set_xattr(buffer, credp); if (err == -1) { serrno = errno; @@ -769,7 +984,9 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath, int fd; ssize_t oldpath_size, write_size; buffer = rpath(fs_ctx, newpath); - fd = open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, SM_LOCAL_MODE_BITS); + fd = open(buffer, + O_CREAT | O_EXCL | O_RDWR | O_NOFOLLOW | O_BINARY, + SM_LOCAL_MODE_BITS); if (fd == -1) { err = fd; goto out; @@ -788,7 +1005,9 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath, } close(fd); /* Set cleint credentials in symlink's xattr */ +#ifndef _WIN32 credp->fc_mode = credp->fc_mode|S_IFLNK; +#endif err = local_set_mapped_file_attr(fs_ctx, newpath, credp); if (err == -1) { serrno = errno; @@ -833,7 +1052,7 @@ static int local_link(FsContext *ctx, V9fsPath *oldpath, char *buffer, *buffer1; v9fs_string_init(&newpath); - v9fs_string_sprintf(&newpath, "%s/%s", dirpath->data, name); + v9fs_string_sprintf(&newpath, DELIMITER_IN_PATH, dirpath->data, name); buffer = rpath(ctx, oldpath->data); buffer1 = rpath(ctx, newpath.data); @@ -934,7 +1153,12 @@ static int local_utimensat(FsContext *s, V9fsPath *fs_path, char *path = fs_path->data; buffer = rpath(s, path); +#ifdef _WIN32 + #warning "Could cause problems!" + ret = 0; +#else ret = qemu_utimens(buffer, buf); +#endif g_free(buffer); return ret; } @@ -949,6 +1173,7 @@ static int local_remove(FsContext *ctx, const char *path) buffer = rpath(ctx, path); err = lstat(buffer, &stbuf); g_free(buffer); + error_printf("local_remove: stat %d %d\n", err, errno); if (err) { goto err_out; } @@ -957,10 +1182,12 @@ static int local_remove(FsContext *ctx, const char *path) * directory */ if (S_ISDIR(stbuf.st_mode)) { - buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root, + buffer = g_strdup_printf(DELIMITER_IN_PATH2, ctx->fs_root, path, VIRTFS_META_DIR); err = remove(buffer); g_free(buffer); + error_printf("local_remove: .virtfs_metdata remove %d %d\n", + err, errno); if (err < 0 && errno != ENOENT) { /* * We didn't had the .virtfs_metadata file. May be file created @@ -976,6 +1203,8 @@ static int local_remove(FsContext *ctx, const char *path) buffer = local_mapped_attr_path(ctx, path); err = remove(buffer); g_free(buffer); + error_printf("local_remove: local_mapped_attr_path remove %d %d\n", + err, errno); if (err < 0 && errno != ENOENT) { /* * We didn't had the .virtfs_metadata file. May be file created @@ -986,7 +1215,14 @@ static int local_remove(FsContext *ctx, const char *path) } buffer = rpath(ctx, path); - err = remove(buffer); + /* mifritscher: posix remove can delete directories as well, windows not */ + if (S_ISDIR(stbuf.st_mode)) { + err = rmdir(buffer); + } else { + err = remove(buffer); + } + error_printf("local_remove: final remove %d %d\n", + err, errno); g_free(buffer); err_out: return err; @@ -998,7 +1234,12 @@ static int local_fsync(FsContext *ctx, int fid_type, int fd; if (fid_type == P9_FID_DIR) { +#ifdef _WIN32 + #warning "Could cause problems!" + fd = fs->fd; +#else fd = dirfd(fs->dir); +#endif } else { fd = fs->fd; } @@ -1058,10 +1299,14 @@ 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", + v9fs_string_sprintf((V9fsString *)target, DELIMITER_IN_PATH, dir_path->data, name); + error_printf("local_name_to_path: "); + error_printf(DELIMITER_IN_PATH, dir_path->data, name); + error_printf("\n"); } else { v9fs_string_sprintf((V9fsString *)target, "%s", name); + error_printf("local_name_to_path: %s\n", name); } /* Bump the size for including terminating NULL */ target->size++; @@ -1078,8 +1323,10 @@ static int local_renameat(FsContext *ctx, V9fsPath *olddir, 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); + v9fs_string_sprintf(&old_full_name, + DELIMITER_IN_PATH, olddir->data, old_name); + v9fs_string_sprintf(&new_full_name, + DELIMITER_IN_PATH, newdir->data, new_name); ret = local_rename(ctx, old_full_name.data, new_full_name.data); v9fs_string_free(&old_full_name); @@ -1096,17 +1343,19 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir, v9fs_string_init(&fullname); - v9fs_string_sprintf(&fullname, "%s/%s", dir->data, name); + v9fs_string_sprintf(&fullname, DELIMITER_IN_PATH, dir->data, name); if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { if (flags == AT_REMOVEDIR) { /* * If directory remove .virtfs_metadata contained in the * directory */ - buffer = g_strdup_printf("%s/%s/%s", ctx->fs_root, + buffer = g_strdup_printf(DELIMITER_IN_PATH2, ctx->fs_root, fullname.data, VIRTFS_META_DIR); ret = remove(buffer); g_free(buffer); + error_printf("local_unlinkat: .virtfs_metadata %d %d\n", + ret, errno); if (ret < 0 && errno != ENOENT) { /* * We didn't had the .virtfs_metadata file. May be file created @@ -1121,6 +1370,8 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir, */ buffer = local_mapped_attr_path(ctx, fullname.data); ret = remove(buffer); + error_printf("local_unlinkat: local_mapped_attr_path %d %d\n", + ret, errno); g_free(buffer); if (ret < 0 && errno != ENOENT) { /* @@ -1133,6 +1384,19 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir, /* Remove the name finally */ buffer = rpath(ctx, fullname.data); ret = remove(buffer); + error_printf("local_unlinkat: final |%s| %d %d\n", buffer, ret, errno); + /* extension for MingW: remove or Windows can't handle directories... */ +#ifdef _WIN32 + /* mifritscher: Try to delete it as directory + (AT_REMOVEDIR doesn't seem to be set in this case + (testcase: rmdir from Linux)) */ + if (ret < 0) { + ret = rmdir(buffer); + error_printf("local_unlinkat: final rmdir |%s| %d %d\n", + buffer, ret, errno); + + } +#endif g_free(buffer); err_out: @@ -1140,6 +1404,7 @@ err_out: return ret; } +#ifndef _WIN32 static int local_ioc_getversion(FsContext *ctx, V9fsPath *path, mode_t st_mode, uint64_t *st_gen) { @@ -1167,12 +1432,18 @@ static int local_ioc_getversion(FsContext *ctx, V9fsPath *path, return -1; #endif } +#endif static int local_init(FsContext *ctx) { int err = 0; +#ifdef FS_IOC_GETVERSION struct statfs stbuf; +#endif +#ifdef _WIN32 + ctx->xops = 0; +#else if (ctx->export_flags & V9FS_SM_PASSTHROUGH) { ctx->xops = passthrough_xattr_ops; } else if (ctx->export_flags & V9FS_SM_MAPPED) { @@ -1186,6 +1457,7 @@ static int local_init(FsContext *ctx) */ ctx->xops = passthrough_xattr_ops; } +#endif ctx->export_flags |= V9FS_PATHNAME_FSCONTEXT; #ifdef FS_IOC_GETVERSION /* diff --git a/hw/9pfs/9p-synth.c b/hw/9pfs/9p-synth.c index f1475df..8355722 100644 --- a/hw/9pfs/9p-synth.c +++ b/hw/9pfs/9p-synth.c @@ -15,7 +15,9 @@ #include "qemu/osdep.h" #include "hw/virtio/virtio.h" #include "9p.h" -#include "9p-xattr.h" +#ifndef _WIN32 + #include "9p-xattr.h" +#endif #include "fsdev/qemu-fsdev.h" #include "9p-synth.h" #include "qemu/rcu.h" @@ -152,8 +154,10 @@ static void v9fs_synth_fill_statbuf(V9fsSynthNode *node, struct stat *stbuf) stbuf->st_gid = 0; stbuf->st_rdev = 0; stbuf->st_size = 0; +#ifndef _WIN32 stbuf->st_blksize = 0; stbuf->st_blocks = 0; +#endif stbuf->st_atime = 0; stbuf->st_mtime = 0; stbuf->st_ctime = 0; @@ -222,7 +226,11 @@ static void v9fs_synth_direntry(V9fsSynthNode *node, { strcpy(entry->d_name, node->name); entry->d_ino = node->attr->inode; +#ifdef _WIN32 + #warning "Can cause problems!" +#else entry->d_off = off + 1; +#endif } static int v9fs_synth_get_dentry(V9fsSynthNode *dir, struct dirent *entry, diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c index f5e3012..7980f33 100644 --- a/hw/9pfs/9p.c +++ b/hw/9pfs/9p.c @@ -20,7 +20,21 @@ #include "qemu/sockets.h" #include "virtio-9p.h" #include "fsdev/qemu-fsdev.h" -#include "9p-xattr.h" +#ifdef _WIN32 +/* taken from linux/kdev_t.h */ +# define MINORBITS 20 +# define MINORMASK ((1U << MINORBITS) - 1) + +# define major(dev) ((unsigned int) ((dev) >> MINORBITS)) +# define minor(dev) ((unsigned int) ((dev) & MINORMASK)) +# define makedev(ma, mi) (((ma) << MINORBITS) | (mi)) + +/* taken from linux/include/linux/stat.h */ +# define UTIME_NOW ((1l << 30) - 1l) +# define UTIME_OMIT ((1l << 30) - 2l) +#else +# include "9p-xattr.h" +#endif #include "coth.h" #include "trace.h" #include "migration/migration.h" @@ -576,9 +590,11 @@ static void stat_to_qid(const struct stat *stbuf, V9fsQID *qidp) if (S_ISDIR(stbuf->st_mode)) { qidp->type |= P9_QID_TYPE_DIR; } - if (S_ISLNK(stbuf->st_mode)) { - qidp->type |= P9_QID_TYPE_SYMLINK; - } + #ifndef _WIN32 + if (S_ISLNK(stbuf->st_mode)) { + qidp->type |= P9_QID_TYPE_SYMLINK; + } + #endif } static int fid_to_qid(V9fsPDU *pdu, V9fsFidState *fidp, V9fsQID *qidp) @@ -677,12 +693,15 @@ static mode_t v9mode_to_mode(uint32_t mode, V9fsString *extension) ret |= S_IFDIR; } +#ifndef _WIN32 if (mode & P9_STAT_MODE_SYMLINK) { ret |= S_IFLNK; } if (mode & P9_STAT_MODE_SOCKET) { ret |= S_IFSOCK; } +#endif + if (mode & P9_STAT_MODE_NAMED_PIPE) { ret |= S_IFIFO; } @@ -698,6 +717,7 @@ static mode_t v9mode_to_mode(uint32_t mode, V9fsString *extension) ret |= S_IFREG; } +#ifndef _WIN32 if (mode & P9_STAT_MODE_SETUID) { ret |= S_ISUID; } @@ -707,6 +727,7 @@ static mode_t v9mode_to_mode(uint32_t mode, V9fsString *extension) if (mode & P9_STAT_MODE_SETVTX) { ret |= S_ISVTX; } +#endif return ret; } @@ -762,6 +783,7 @@ static uint32_t stat_to_v9mode(const struct stat *stbuf) mode |= P9_STAT_MODE_DIR; } +#ifndef _WIN32 if (S_ISLNK(stbuf->st_mode)) { mode |= P9_STAT_MODE_SYMLINK; } @@ -769,6 +791,7 @@ static uint32_t stat_to_v9mode(const struct stat *stbuf) if (S_ISSOCK(stbuf->st_mode)) { mode |= P9_STAT_MODE_SOCKET; } +#endif if (S_ISFIFO(stbuf->st_mode)) { mode |= P9_STAT_MODE_NAMED_PIPE; @@ -778,6 +801,7 @@ static uint32_t stat_to_v9mode(const struct stat *stbuf) mode |= P9_STAT_MODE_DEVICE; } +#ifndef _WIN32 if (stbuf->st_mode & S_ISUID) { mode |= P9_STAT_MODE_SETUID; } @@ -789,6 +813,7 @@ static uint32_t stat_to_v9mode(const struct stat *stbuf) if (stbuf->st_mode & S_ISVTX) { mode |= P9_STAT_MODE_SETVTX; } +#endif return mode; } @@ -881,14 +906,34 @@ static void stat_to_v9stat_dotl(V9fsState *s, const struct stat *stbuf, v9lstat->st_gid = stbuf->st_gid; v9lstat->st_rdev = stbuf->st_rdev; v9lstat->st_size = stbuf->st_size; +#ifdef _WIN32 + /* Blksize is the optimal EA-block, + while blocks always refers to 512 blocks + */ + v9lstat->st_blksize = 4096; + v9lstat->st_blocks = ((stbuf->st_size + 1) / 512) + 1; +#else v9lstat->st_blksize = stbuf->st_blksize; v9lstat->st_blocks = stbuf->st_blocks; +#endif v9lstat->st_atime_sec = stbuf->st_atime; +#ifdef _WIN32 + v9lstat->st_atime_nsec = 0; +#else v9lstat->st_atime_nsec = stbuf->st_atim.tv_nsec; +#endif v9lstat->st_mtime_sec = stbuf->st_mtime; +#ifdef _WIN32 + v9lstat->st_mtime_nsec = 0; +#else v9lstat->st_mtime_nsec = stbuf->st_mtim.tv_nsec; +#endif v9lstat->st_ctime_sec = stbuf->st_ctime; +#ifdef _WIN32 + v9lstat->st_ctime_nsec = 0; +#else v9lstat->st_ctime_nsec = stbuf->st_ctim.tv_nsec; +#endif /* Currently we only support BASIC fields in stat */ v9lstat->st_result_mask = P9_STATS_BASIC; @@ -1639,7 +1684,10 @@ static int v9fs_do_readdir_with_stat(V9fsPDU *pdu, v9fs_path_init(&path); err = v9fs_co_readdir_r(pdu, fidp, dent, &result); if (err || !result) { + error_printf("v9fs_do_readdir_with_stat: exiting...\n"); break; + } else { + error_printf("v9fs_do_readdir_with_stat: continue\n"); } err = v9fs_co_name_to_path(pdu, &fidp->path, dent->d_name, &path); if (err < 0) { @@ -1666,7 +1714,12 @@ static int v9fs_do_readdir_with_stat(V9fsPDU *pdu, count += len; v9fs_stat_free(&v9stat); v9fs_path_free(&path); +#ifdef _WIN32 + #warning "Probably right, but could make problems!" + saved_dir_pos = v9fs_co_telldir(pdu, fidp); +#else saved_dir_pos = dent->d_off; +#endif } out: g_free(dent); @@ -1806,6 +1859,9 @@ static int v9fs_do_readdir(V9fsPDU *pdu, int32_t count = 0; off_t saved_dir_pos; struct dirent *dent, *result; +#ifdef _WIN32 + uint8_t type = 0; /* DT_UNKNOWN */ +#endif /* save the directory position */ saved_dir_pos = v9fs_co_telldir(pdu, fidp); @@ -1818,15 +1874,27 @@ static int v9fs_do_readdir(V9fsPDU *pdu, while (1) { err = v9fs_co_readdir_r(pdu, fidp, dent, &result); if (err || !result) { + error_printf("v9fs_do_readdir: exiting...\n"); break; + } else { + error_printf("v9fs_do_readdir: continue\n"); } v9fs_string_init(&name); + if (!dent->d_name) { + error_printf("\ndent->d_name is NULL!\n"); + break; + } else { + error_printf("v9fs_do_readdir: entry is named %s, strlen %u\n", + dent->d_name, strlen(dent->d_name)); + } v9fs_string_sprintf(&name, "%s", dent->d_name); if ((count + v9fs_readdir_data_size(&name)) > max_count) { /* Ran out of buffer. Set dir back to old position and return */ v9fs_co_seekdir(pdu, fidp, saved_dir_pos); v9fs_string_free(&name); g_free(dent); + error_printf("v9fs_do_readdir: RAN OUT OF BUFFER return %d\n\n", + count); return count; } /* @@ -1841,9 +1909,16 @@ static int v9fs_do_readdir(V9fsPDU *pdu, qid.version = 0; /* 11 = 7 + 4 (7 = start offset, 4 = space for storing count) */ +#ifdef _WIN32 + #warning "Probably right, but could make problems!" + len = pdu_marshal(pdu, 11 + count, "Qqbs", + &qid, v9fs_co_telldir(pdu, fidp), + type, &name); +#else len = pdu_marshal(pdu, 11 + count, "Qqbs", &qid, dent->d_off, dent->d_type, &name); +#endif if (len < 0) { v9fs_co_seekdir(pdu, fidp, saved_dir_pos); v9fs_string_free(&name); @@ -1852,12 +1927,18 @@ static int v9fs_do_readdir(V9fsPDU *pdu, } count += len; v9fs_string_free(&name); +#ifdef _WIN32 + #warning "Probably right, but could make problems!" + saved_dir_pos = v9fs_co_telldir(pdu, fidp); +#else saved_dir_pos = dent->d_off; +#endif } g_free(dent); if (err < 0) { return err; } + error_printf("v9fs_do_readdir: return %d\n\n", count); return count; } @@ -1878,6 +1959,8 @@ static void v9fs_readdir(void *opaque) goto out_nofid; } trace_v9fs_readdir(pdu->tag, pdu->id, fid, initial_offset, max_count); + error_printf("v9fs_readdir initial: %llu max count: %u\n", + initial_offset, max_count); fidp = get_fid(pdu, fid); if (fidp == NULL) { @@ -1904,10 +1987,13 @@ static void v9fs_readdir(void *opaque) } retval += count + offset; trace_v9fs_readdir_return(pdu->tag, pdu->id, count, retval); + error_printf("v9fs_readdir: count: %d retval: %d\n\n", count, retval); out: put_fid(pdu, fidp); out_nofid: pdu_complete(pdu, retval); + + error_printf("v9fs_readdir: return\n"); } static int v9fs_xattr_write(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp, @@ -2166,8 +2252,12 @@ static void v9fs_create(void *opaque) } v9fs_path_copy(&fidp->path, &path); } else if (perm & P9_STAT_MODE_SOCKET) { +#ifdef _WIN32 + err = -1; +#else err = v9fs_co_mknod(pdu, fidp, &name, fidp->uid, -1, 0, S_IFSOCK | (perm & 0777), &stbuf); +#endif if (err < 0) { goto out; } @@ -3338,7 +3428,7 @@ int v9fs_device_realize_common(V9fsState *s, Error **errp) * call back to do that. Since we are in the init path, we don't * use co-routines here. */ - if (s->ops->name_to_path(&s->ctx, NULL, "/", &path) < 0) { + if (s->ops->name_to_path(&s->ctx, NULL, DELIMITER_STRING, &path) < 0) { error_setg(errp, "error in converting name to path %s", strerror(errno)); goto out; @@ -3370,6 +3460,7 @@ void v9fs_device_unrealize_common(V9fsState *s, Error **errp) static void __attribute__((__constructor__)) v9fs_set_fd_limit(void) { +#ifndef _WIN32 struct rlimit rlim; if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) { error_report("Failed to get the resource limit"); @@ -3377,4 +3468,5 @@ static void __attribute__((__constructor__)) v9fs_set_fd_limit(void) } open_fd_hw = rlim.rlim_cur - MIN(400, rlim.rlim_cur/3); open_fd_rc = rlim.rlim_cur/2; +#endif } diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h index 1a19418..7bc8863 100644 --- a/hw/9pfs/9p.h +++ b/hw/9pfs/9p.h @@ -3,7 +3,29 @@ #include <dirent.h> #include <utime.h> -#include <sys/resource.h> +#ifdef _WIN32 +/* Bad workaround, from http://octave.org/doxygen/3.4/fcntl_8h.html */ +# define O_NOCTTY 0 +# define O_NDELAY 0 +# define O_NONBLOCK O_NDELAY +# define O_DSYNC 0 +# define O_DIRECT 0 +# define O_DIRECTORY 0 +# define O_NOFOLLOW 0 +# define O_NOATIME 0 +# define O_SYNC 0 +# define O_ASYNC 0 + +# define FASYNC 0 + +# define AT_REMOVEDIR 1 + +# define NAME_MAX 260 + +#else +# include <sys/resource.h> +#endif + #include <glib.h> #include "standard-headers/linux/virtio_9p.h" #include "hw/virtio/virtio.h" @@ -12,6 +34,10 @@ #include "qemu/thread.h" #include "qemu/coroutine.h" +#define DELIMITER_STRING "/" +#define DELIMITER_IN_PATH "%s/%s" +#define DELIMITER_IN_PATH2 "%s/%s/%s" + enum { P9_TLERROR = 6, P9_RLERROR, @@ -108,9 +134,49 @@ enum p9_proto_version { #define FID_REFERENCED 0x1 #define FID_NON_RECLAIMABLE 0x2 + +/* combines the host's root dir and the path to a complete host path */ static inline char *rpath(FsContext *ctx, const char *path) { - return g_strdup_printf("%s/%s", ctx->fs_root, path); + char *result; + result = g_strdup_printf(DELIMITER_IN_PATH, ctx->fs_root, path); +#ifdef _WIN32 + int input = 0; + int output = 0; + while (result[input]) { + /* error_printf("<-%d %c\n", input, result[input]); */ + if (result[input] == '/') { + result[output] = '\\'; + /* remove duplicate \... */ + if (output > 0 && result[output - 1] == '\\') { + /* error_printf("remove duplicate \\\n"); */ + output--; + } else { + result[output] = '\\'; + } + /* error_printf(" %c\n", result[output]); */ + } else { + result[output] = result[input]; + } + /* error_printf("->%d %c\n\n", output, result[output]); */ + input++; + output++; + } + /* Kill last \ (but leave it if the char before is a : ...) + So: + C:\ -> C:\ + C:\blah\ -> C:\blah + b\ -> b + blah\ -> blah */ + if (output > 1 && result[output - 1] == '\\' + && (output == 1 || result[output - 2] != ':')) { + /* error_printf("Killed last \\\n"); */ + result[output - 1] = '\0'; + } else { + result[output] = '\0'; + } +#endif + return result; } /* diff --git a/hw/9pfs/Makefile.objs b/hw/9pfs/Makefile.objs index da0ae0c..6f6ed19 100644 --- a/hw/9pfs/Makefile.objs +++ b/hw/9pfs/Makefile.objs @@ -1,9 +1,10 @@ common-obj-y = 9p.o -common-obj-y += 9p-local.o 9p-xattr.o -common-obj-y += 9p-xattr-user.o 9p-posix-acl.o +common-obj-$(CONFIG_LINUX) += 9p-local.o 9p-xattr.o +common-obj-$(CONFIG_LINUX) += 9p-xattr-user.o 9p-posix-acl.o +common-obj-$(CONFIG_WIN32) += 9p-local.o common-obj-y += coth.o cofs.o codir.o cofile.o common-obj-y += coxattr.o 9p-synth.o common-obj-$(CONFIG_OPEN_BY_HANDLE) += 9p-handle.o -common-obj-y += 9p-proxy.o +common-obj-$(CONFIG_POSIX) += 9p-proxy.o obj-y += virtio-9p-device.o diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c index 91df7f7..399bd8a 100644 --- a/hw/9pfs/codir.c +++ b/hw/9pfs/codir.c @@ -17,6 +17,8 @@ #include "qemu/thread.h" #include "qemu/coroutine.h" #include "coth.h" +/* mifritscher: after killing the debug printf, kill this as well! */ +#include "qemu/error-report.h" int v9fs_co_readdir_r(V9fsPDU *pdu, V9fsFidState *fidp, struct dirent *dent, struct dirent **result) @@ -37,6 +39,12 @@ int v9fs_co_readdir_r(V9fsPDU *pdu, V9fsFidState *fidp, struct dirent *dent, err = 0; } }); +#ifdef _WIN32 + error_printf("v9fs_co_readdir_r: %s %d %p\n", + (&fidp->fs)->dir->dd_name, err, *result); +#else + error_printf("v9fs_co_readdir_r: %d %p\n", err, *result); +#endif return err; } @@ -55,6 +63,12 @@ off_t v9fs_co_telldir(V9fsPDU *pdu, V9fsFidState *fidp) err = -errno; } }); +#ifdef _WIN32 + error_printf("v9fs_co_telldir_r: %s %lld\n", + (&fidp->fs)->dir->dd_name, err); +#else + error_printf("v9fs_co_telldir_r: %ld\n", err); +#endif return err; } @@ -68,6 +82,11 @@ void v9fs_co_seekdir(V9fsPDU *pdu, V9fsFidState *fidp, off_t offset) { s->ops->seekdir(&s->ctx, &fidp->fs, offset); }); +#ifdef _WIN32 + error_printf("v9fs_co_seekdir: %s\n", (&fidp->fs)->dir->dd_name); +#else + error_printf("v9fs_co_seekdir\n"); +#endif } void v9fs_co_rewinddir(V9fsPDU *pdu, V9fsFidState *fidp) @@ -80,6 +99,11 @@ void v9fs_co_rewinddir(V9fsPDU *pdu, V9fsFidState *fidp) { s->ops->rewinddir(&s->ctx, &fidp->fs); }); +#ifdef _WIN32 + error_printf("v9fs_co_rewinddir: %s\n", (&fidp->fs)->dir->dd_name); +#else + error_printf("v9fs_co_rewinddir\n"); +#endif } int v9fs_co_mkdir(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name, @@ -116,6 +140,7 @@ int v9fs_co_mkdir(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name, } }); v9fs_path_unlock(s); + error_printf("v9fs_co_mkdir: %d\n", err); return err; } @@ -144,6 +169,11 @@ int v9fs_co_opendir(V9fsPDU *pdu, V9fsFidState *fidp) v9fs_reclaim_fd(pdu); } } +#ifdef _WIN32 + error_printf("v9fs_co_opendir: %s %d\n", (&fidp->fs)->dir->dd_name, err); +#else + error_printf("v9fs_co_opendir: %d\n", err); +#endif return err; } @@ -165,5 +195,6 @@ int v9fs_co_closedir(V9fsPDU *pdu, V9fsFidOpenState *fs) if (!err) { total_open_fd--; } + error_printf("v9fs_co_closedir: %d\n", err); return err; } diff --git a/hw/9pfs/cofile.c b/hw/9pfs/cofile.c index 293483e..a9c1a10 100644 --- a/hw/9pfs/cofile.c +++ b/hw/9pfs/cofile.c @@ -17,6 +17,8 @@ #include "qemu/thread.h" #include "qemu/coroutine.h" #include "coth.h" +/* mifritscher: after killing the debug printf, kill this as well! */ +#include "qemu/error-report.h" int v9fs_co_st_gen(V9fsPDU *pdu, V9fsPath *path, mode_t st_mode, V9fsStatDotl *v9stat) @@ -39,6 +41,7 @@ int v9fs_co_st_gen(V9fsPDU *pdu, V9fsPath *path, mode_t st_mode, }); v9fs_path_unlock(s); } + error_printf("v9fs_co_st_gen: %d\n", err); return err; } @@ -59,6 +62,7 @@ int v9fs_co_lstat(V9fsPDU *pdu, V9fsPath *path, struct stat *stbuf) } }); v9fs_path_unlock(s); + error_printf("v9fs_co_lstat: %d\n", err); return err; } @@ -91,6 +95,7 @@ int v9fs_co_fstat(V9fsPDU *pdu, V9fsFidState *fidp, struct stat *stbuf) err = 0; } } + error_printf("v9fs_co_fstat: %s %d\n", (&fidp->path)->data, err); return err; } @@ -119,6 +124,7 @@ int v9fs_co_open(V9fsPDU *pdu, V9fsFidState *fidp, int flags) v9fs_reclaim_fd(pdu); } } + error_printf("v9fs_co_open: %s %d\n", (&fidp->path)->data, err); return err; } @@ -147,13 +153,17 @@ int v9fs_co_open2(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name, gid_t gid, { err = s->ops->open2(&s->ctx, &fidp->path, name->data, flags, &cred, &fidp->fs); + error_printf("v9fs_co_open2: open returned %d\n", err); if (err < 0) { err = -errno; } else { v9fs_path_init(&path); err = v9fs_name_to_path(s, &fidp->path, name->data, &path); + error_printf("v9fs_co_open2: v9fs_name_to_path returned %d\n", + err); if (!err) { err = s->ops->lstat(&s->ctx, &path, stbuf); + error_printf("v9fs_co_open2: lstat returned %d\n", err); if (err < 0) { err = -errno; s->ops->close(&s->ctx, &fidp->fs); @@ -173,6 +183,7 @@ int v9fs_co_open2(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name, gid_t gid, v9fs_reclaim_fd(pdu); } } + error_printf("v9fs_co_open2: %s %d\n", (&fidp->path)->data, err); return err; } @@ -194,6 +205,7 @@ int v9fs_co_close(V9fsPDU *pdu, V9fsFidOpenState *fs) if (!err) { total_open_fd--; } + error_printf("v9fs_co_close: %d\n", err); return err; } @@ -234,6 +246,7 @@ int v9fs_co_link(V9fsPDU *pdu, V9fsFidState *oldfid, } }); v9fs_path_unlock(s); + error_printf("v9fs_co_link: %d\n", err); return err; } @@ -253,6 +266,7 @@ int v9fs_co_pwritev(V9fsPDU *pdu, V9fsFidState *fidp, err = -errno; } }); + error_printf("v9fs_co_pwritev: %s %d\n", (&fidp->path)->data, err); return err; } @@ -272,5 +286,6 @@ int v9fs_co_preadv(V9fsPDU *pdu, V9fsFidState *fidp, err = -errno; } }); + error_printf("v9fs_co_preadv: %s %d\n", (&fidp->path)->data, err); return err; } diff --git a/hw/9pfs/cofs.c b/hw/9pfs/cofs.c index 18c81cb..a3a42bf 100644 --- a/hw/9pfs/cofs.c +++ b/hw/9pfs/cofs.c @@ -17,6 +17,8 @@ #include "qemu/thread.h" #include "qemu/coroutine.h" #include "coth.h" +/* mifritscher: after killing the debug printf, kill this as well! */ +#include "qemu/error-report.h" static ssize_t __readlink(V9fsState *s, V9fsPath *path, V9fsString *buf) { @@ -67,6 +69,7 @@ int v9fs_co_readlink(V9fsPDU *pdu, V9fsPath *path, V9fsString *buf) } }); v9fs_path_unlock(s); + error_printf("v9fs_co_readlink: %d\n", err); return err; } @@ -87,6 +90,7 @@ int v9fs_co_statfs(V9fsPDU *pdu, V9fsPath *path, struct statfs *stbuf) } }); v9fs_path_unlock(s); + error_printf("v9fs_co_statfs: %d\n", err); return err; } @@ -110,6 +114,7 @@ int v9fs_co_chmod(V9fsPDU *pdu, V9fsPath *path, mode_t mode) } }); v9fs_path_unlock(s); + error_printf("v9fs_co_chmod: %d\n", err); return err; } @@ -131,6 +136,7 @@ int v9fs_co_utimensat(V9fsPDU *pdu, V9fsPath *path, } }); v9fs_path_unlock(s); + error_printf("v9fs_co_utimensat: %d\n", err); return err; } @@ -155,6 +161,7 @@ int v9fs_co_chown(V9fsPDU *pdu, V9fsPath *path, uid_t uid, gid_t gid) } }); v9fs_path_unlock(s); + error_printf("v9fs_co_chown: %d\n", err); return err; } @@ -175,6 +182,7 @@ int v9fs_co_truncate(V9fsPDU *pdu, V9fsPath *path, off_t size) } }); v9fs_path_unlock(s); + error_printf("v9fs_co_truncate: %d\n", err); return err; } @@ -213,6 +221,7 @@ int v9fs_co_mknod(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name, uid_t uid, } }); v9fs_path_unlock(s); + error_printf("v9fs_co_mknod: %d\n", err); return err; } @@ -234,6 +243,7 @@ int v9fs_co_remove(V9fsPDU *pdu, V9fsPath *path) } }); v9fs_path_unlock(s); + error_printf("v9fs_co_remove: %d\n", err); return err; } @@ -254,6 +264,7 @@ int v9fs_co_unlinkat(V9fsPDU *pdu, V9fsPath *path, V9fsString *name, int flags) } }); v9fs_path_unlock(s); + error_printf("v9fs_co_unlinkat: %d\n", err); return err; } @@ -273,6 +284,7 @@ int v9fs_co_rename(V9fsPDU *pdu, V9fsPath *oldpath, V9fsPath *newpath) err = -errno; } }); + error_printf("v9fs_co_rename: %d\n", err); return err; } @@ -293,6 +305,7 @@ int v9fs_co_renameat(V9fsPDU *pdu, V9fsPath *olddirpath, V9fsString *oldname, err = -errno; } }); + error_printf("v9fs_co_renameat: %d\n", err); return err; } @@ -331,6 +344,7 @@ int v9fs_co_symlink(V9fsPDU *pdu, V9fsFidState *dfidp, V9fsString *name, } }); v9fs_path_unlock(s); + error_printf("v9fs_co_symlink: %d\n", err); return err; } @@ -361,5 +375,6 @@ int v9fs_co_name_to_path(V9fsPDU *pdu, V9fsPath *dirpath, } }); } + error_printf("v9fs_co_name_to_path: %d\n", err); return err; } diff --git a/hw/9pfs/coxattr.c b/hw/9pfs/coxattr.c index 6ad96ea..49fbd5e 100644 --- a/hw/9pfs/coxattr.c +++ b/hw/9pfs/coxattr.c @@ -17,6 +17,8 @@ #include "qemu/thread.h" #include "qemu/coroutine.h" #include "coth.h" +/* mifritscher: after killing the debug printf, kill this as well! */ +#include "qemu/error-report.h" int v9fs_co_llistxattr(V9fsPDU *pdu, V9fsPath *path, void *value, size_t size) { @@ -35,6 +37,7 @@ int v9fs_co_llistxattr(V9fsPDU *pdu, V9fsPath *path, void *value, size_t size) } }); v9fs_path_unlock(s); + error_printf("v9fs_co_llistxattr: %d\n", err); return err; } @@ -59,6 +62,7 @@ int v9fs_co_lgetxattr(V9fsPDU *pdu, V9fsPath *path, } }); v9fs_path_unlock(s); + error_printf("v9fs_co_lgetxattr: %d\n", err); return err; } @@ -83,6 +87,7 @@ int v9fs_co_lsetxattr(V9fsPDU *pdu, V9fsPath *path, } }); v9fs_path_unlock(s); + error_printf("v9fs_co_lsetxattr: %d\n", err); return err; } @@ -104,5 +109,6 @@ int v9fs_co_lremovexattr(V9fsPDU *pdu, V9fsPath *path, } }); v9fs_path_unlock(s); + error_printf("v9fs_co_lremovexattr: %d\n", err); return err; } diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c index a38850e..59d0a50 100644 --- a/hw/9pfs/virtio-9p-device.c +++ b/hw/9pfs/virtio-9p-device.c @@ -17,7 +17,9 @@ #include "qemu/sockets.h" #include "virtio-9p.h" #include "fsdev/qemu-fsdev.h" -#include "9p-xattr.h" +#ifndef WIN32 + #include "9p-xattr.h" +#endif #include "coth.h" #include "hw/virtio/virtio-access.h" #include "qemu/iov.h"
It was tested on Windows & Linux hosts, on the later no obvious regressions could be found. The guest was a Knoppix 7.6.0 live cd. This is WIP and a RFC - it isn't meant to be upstreamed yet. The error_printf are only for debugging and will be deleted in the final patch. There are some comments with "mifritscher" - I'm not quite sure how to handle these problems (e.g. on mingw, this in 32 bit, while on Linux this is 16 bit and so on). Additionally, some places from which I suspect problems are marked with a #warning. Changes against v1: * fixed open (added binary flag) -> read/write is fine now, file creation was fixed as well * added inode calculation using own crude hash algorithm * fixed xattr returning -1 + EOPNOTSUP -> fixes e.g. executing files * fixed unlinkat / remove für directories by trying rmdir as well * prepend 777 mode on files (for executing) What does work: * reading/writing "big" files (5MB, verified with md5sum) * creating files * executing files * mkdir * rm / rmdir * cp files * running gcc * cp first 250 files & directories from /etc * tar it from and to the 9p mount * create a 100 MB swap file and do a mkswap on it What does not work: * swapon - no real surprise (doesn't work on Linux as well - with the same error message) ;-) (swapon returns -1 EINVAL) * link / symlink (there is no real aequivalent for this on windows) * mknod (dito) * chown (dito - prepend success for compatibility) State of v1: What works: * mount * stat * chdir * readdir (aka ls) * read of small files (<10k) * overwrite What does not work: * create new files (in 90% problems with path handling (old path occurs) * read / probably write big files Signed-off-by: Michael Fritscher <michael@fritscher.net> --- On https://github.com/mifritscher/qemu/tree/9pfs_windows is a git tree with the patch. I gave a shot at xattr (try to include xattr stuff) but it ended up even more #ifdefs. So I gave up at this. Now I'm waiting on comments etc. If there are no big objections, I'll remove the debug output and make a patch which is meant for upstreaming. Thanks to everybody which helped me! Makefile.objs | 1 + configure | 15 ++- fsdev/9p-iov-marshal.c | 2 + fsdev/9p-marshal.c | 4 +- fsdev/file-op-9p.h | 35 ++++- fsdev/qemu-fsdev.c | 2 + hw/9pfs/9p-local.c | 326 +++++++++++++++++++++++++++++++++++++++++---- hw/9pfs/9p-synth.c | 10 +- hw/9pfs/9p.c | 102 +++++++++++++- hw/9pfs/9p.h | 70 +++++++++- hw/9pfs/Makefile.objs | 7 +- hw/9pfs/codir.c | 31 +++++ hw/9pfs/cofile.c | 15 +++ hw/9pfs/cofs.c | 15 +++ hw/9pfs/coxattr.c | 6 + hw/9pfs/virtio-9p-device.c | 4 +- 16 files changed, 600 insertions(+), 45 deletions(-)