From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:57953) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1azgiO-00048C-R4 for qemu-devel@nongnu.org; Mon, 09 May 2016 04:39:02 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1azgiJ-0004xV-ID for qemu-devel@nongnu.org; Mon, 09 May 2016 04:38:56 -0400 Received: from e06smtp08.uk.ibm.com ([195.75.94.104]:60415) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1azgiI-0004wk-Vy for qemu-devel@nongnu.org; Mon, 09 May 2016 04:38:51 -0400 Received: from localhost by e06smtp08.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 9 May 2016 09:38:45 +0100 Received: from b06cxnps3074.portsmouth.uk.ibm.com (d06relay09.portsmouth.uk.ibm.com [9.149.109.194]) by d06dlp01.portsmouth.uk.ibm.com (Postfix) with ESMTP id 2FBB217D805A for ; Mon, 9 May 2016 09:39:39 +0100 (BST) Received: from d06av07.portsmouth.uk.ibm.com (d06av07.portsmouth.uk.ibm.com [9.149.37.248]) by b06cxnps3074.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id u498cggm459186 for ; Mon, 9 May 2016 08:38:42 GMT Received: from d06av07.portsmouth.uk.ibm.com (localhost [127.0.0.1]) by d06av07.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id u498cgGE021697 for ; Mon, 9 May 2016 04:38:42 -0400 Date: Mon, 9 May 2016 10:38:28 +0200 From: Greg Kurz Message-ID: <20160509103828.6bfc5b96@bahia.huguette.org> In-Reply-To: <1460447520-12499-1-git-send-email-michael@fritscher.net> References: <1460447520-12499-1-git-send-email-michael@fritscher.net> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Subject: Re: [Qemu-devel] [PATCH v2] [WIP] [RFC ]Add initial 9pfs support for Windows hosts v2 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Michael Fritscher Cc: sw@weilnetz.de, aneesh.kumar@linux.vnet.ibm.com, mst@redhat.com, qemu-devel@nongnu.org More comments. On Tue, 12 Apr 2016 09:52:00 +0200 Michael Fritscher wrote: > It was tested on Windows & Linux hosts, on the later no obvious regressio= ns could be found. The guest was a Knoppix 7.6.0 live cd. >=20 > This is WIP and a RFC - it isn't meant to be upstreamed yet. The error_pr= intf are only for debugging and will be deleted in the final patch. >=20 > There are some comments with "mifritscher" - I'm not quite sure how to ha= ndle 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. >=20 > 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=C3=BCr directories by trying rmdir as well > * prepend 777 mode on files (for executing) >=20 > 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 >=20 > What does not work: > * swapon - no real surprise (doesn't work on Linux as well - with the s= ame 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) >=20 > State of v1: > What works: > * mount > * stat > * chdir > * readdir (aka ls) > * read of small files (<10k) > * overwrite >=20 > What does not work: > * create new files (in 90% problems with path handling (old path occur= s) > * read / probably write big files >=20 >=20 > Signed-off-by: Michael Fritscher > --- > On https://github.com/mifritscher/qemu/tree/9pfs_windows is a git tree wi= th the patch. >=20 > 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 rem= ove the debug output and make a patch which is meant for upstreaming. >=20 > Thanks to everybody which helped me! >=20 > 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(-) >=20 > 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) +=3D os-win32.o > common-obj-$(CONFIG_POSIX) +=3D os-posix.o >=20 > common-obj-$(CONFIG_LINUX) +=3D fsdev/ > +common-obj-$(CONFIG_WIN32) +=3D fsdev/ >=20 > common-obj-y +=3D migration/ > common-obj-y +=3D 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" =3D "yes" ; then > fi > if test "$softmmu" =3D yes ; then > if test "$virtfs" !=3D no ; then > - if test "$cap" =3D yes && test "$linux" =3D yes && test "$attr" =3D = yes ; then > + if test "$linux" =3D yes ; then > + if test "$cap" =3D yes && test "$attr" =3D yes ; then > + virtfs=3Dyes > + tools=3D"$tools fsdev/virtfs-proxy-helper\$(EXESUF)" > + else > + if test "$virtfs" =3D yes; then > + error_exit "VirtFS requires libcap-devel and libattr-devel on = Linux" > + fi > + virtfs=3Dno > + fi > + elif test "$mingw32" =3D yes; then > virtfs=3Dyes > - tools=3D"$tools fsdev/virtfs-proxy-helper\$(EXESUF)" > else > if test "$virtfs" =3D yes; then > - error_exit "VirtFS is supported only on Linux and requires libca= p-devel and libattr-devel" > + error_exit "VirtFS is only supported on Linux or Windows" > fi > virtfs=3Dno > 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 > #include > #include > +#ifndef _WIN32 > #include > +#endif >=20 > #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 > #include > #include > -#include > +#ifndef WIN32 > + #include > +#endif >=20 > #include "9p-marshal.h" >=20 > 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 > #include > -#include > -#include > +#ifndef _WIN32 > + #include > + #include > +#endif >=20 > #define SM_LOCAL_MODE_BITS 0600 > #define SM_LOCAL_DIR_MODE_BITS 0700 >=20 > +#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[] =3D { > { .name =3D "handle", .ops =3D &handle_ops}, > #endif > { .name =3D "synth", .ops =3D &synth_ops}, > +#ifndef WIN32 > { .name =3D "proxy", .ops =3D &proxy_ops}, > +#endif > }; >=20 > 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 @@ > */ >=20 > #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-referenc= e-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 =3D 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 =3D 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 =3D 95; /* EOPNOTSUP - wrong definition in mingw(130); */ > + return -1; > +} > + > +static int v9fs_remove_xattr(FsContext *ctx, const char *path, > + const char *name) > +{ > + errno =3D 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 =3D 0; > + temp =3D readdir(dirp); readdir() isn't expected to be thread safe... I believe we need some lockin= g here. Also this function should probably be in os-win32.c. > + if (temp =3D=3D 0) { > + error_printf("readdir_r: End of directory reached -> returning N= ULL\n"); > + *result =3D 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 =3D 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 =3D 0x01021997; /* V9FS_MAGIC */ > + buf->f_bsize =3D 4096; > + buf->f_blocks =3D 4000000; > + buf->f_bfree =3D 3000000; > + buf->f_bavail =3D 2999000; > + buf->f_files =3D 1000000; > + buf->f_ffree =3D 800000; > + buf->f_namelen =3D NAME_MAX; > + return 0; > +} > + > +/* a crude hash function (needed for fake inodes) */ > +static ino_t hash(const char *path) > +{ > + ino_t result =3D (ino_t)41021998; > + int len =3D strlen(path); > + if (!len) { > + return result; > + } > + > + /* Q&D canolizement of the path */ > + if (path[len - 1] =3D=3D '\\' || path[len - 1] =3D=3D '/') { > + len--; > + } > + if (!len) { > + return result; > + } > + > + if (path[len - 1] =3D=3D '.') { > + if (len =3D=3D 1) { > + return result; > + } > + len--; > + if (path[len - 1] =3D=3D '\\' || path[len - 1] =3D=3D '/') { > + len--; > + /* .. -> kill last part */ > + } else if (path[len - 1] =3D=3D '.') { > + len--; > + while (len) { > + if (path[len - 1] =3D=3D '\\' || path[len - 1] =3D=3D '/= ') { > + len--; > + break; > + } > + len--; > + } > + } > + } > + > + if (!len) { > + return result; > + } > + > + for (int i =3D 0; i < len; i++) { > + result +=3D path[i] << (i % 7); > + result +=3D path[i] << ((i + 11) % 17); > + result +=3D 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 > #include > #include > #include > #include > #include "qemu/xattr.h" > +#endif > #include "qemu/cutils.h" > #include "qemu/error-report.h" > #include > -#include > +#ifndef _WIN32 > + #include > +#endif > #ifdef CONFIG_LINUX_MAGIC_H > #include > #endif > +#ifndef _WIN32 > #include > +#endif >=20 > #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 =3D open(path, flags, o_mode); > + fd =3D open(path, flags | O_BINARY, o_mode); Why is this needed ? > if (fd =3D=3D -1) { > return NULL; > } > @@ -124,10 +275,20 @@ static int local_lstat(FsContext *fs_ctx, V9fsPath = *fs_path, struct stat *stbuf) > char *path =3D fs_path->data; >=20 > buffer =3D rpath(fs_ctx, path); > - err =3D lstat(buffer, stbuf); > + error_printf("\nrpath %s + %s -> %s\n\n", fs_ctx->fs_root, path, buf= fer); > + err =3D 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 |=3D S_IXUSR | S_IXGRP | S_IXOTH; > + > + /* Under WIN32 (MingW), st_ino seems to be always 2, > + which leads to confusion */ > + stbuf->st_ino =3D 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 *ct= x, const char *path) > char *attr_dir; > char *tmp_path =3D g_strdup(path); >=20 > - attr_dir =3D g_strdup_printf("%s/%s/%s", > + attr_dir =3D g_strdup_printf(DELIMITER_IN_PATH2, > ctx->fs_root, dirname(tmp_path), VIRTFS_META_DIR); >=20 > err =3D mkdir(attr_dir, 0700); > @@ -223,7 +384,8 @@ update_map_file: > if (credp->fc_gid !=3D -1) { > gid =3D credp->fc_gid; > } > - if (credp->fc_mode !=3D -1) { > + /* mifritscher: is normally unsigned... */ > + if ((int16_t)(credp->fc_mode) !=3D -1) { > mode =3D credp->fc_mode; > } > if (credp->fc_rdev !=3D -1) { > @@ -268,7 +430,8 @@ static int local_set_xattr(const char *path, FsCred *= credp) > return err; > } > } > - if (credp->fc_mode !=3D -1) { > + /* mifritscher: is normally unsigned... */ > + if ((int16_t)(credp->fc_mode) !=3D -1) { > uint32_t tmp_mode =3D cpu_to_le32(credp->fc_mode); > err =3D setxattr(path, "user.virtfs.mode", &tmp_mode, sizeof(mod= e_t), 0); > if (err) { > @@ -323,7 +486,7 @@ static ssize_t local_readlink(FsContext *fs_ctx, V9fs= Path *fs_path, > (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE)) { > int fd; > buffer =3D rpath(fs_ctx, path); > - fd =3D open(buffer, O_RDONLY | O_NOFOLLOW); > + fd =3D open(buffer, O_RDONLY | O_NOFOLLOW | O_BINARY); > g_free(buffer); > if (fd =3D=3D -1) { > return -1; > @@ -358,7 +521,8 @@ static int local_open(FsContext *ctx, V9fsPath *fs_pa= th, > char *path =3D fs_path->data; >=20 > buffer =3D rpath(ctx, path); > - fs->fd =3D open(buffer, flags | O_NOFOLLOW); > + error_printf("File which should be opened: %s\n", buffer); > + fs->fd =3D 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 =3D fs_path->data; >=20 > buffer =3D rpath(ctx, path); > + error_printf("Directory (opendir) which should be opened: %s\n", buf= fer); > fs->dir =3D opendir(buffer); > g_free(buffer); > if (!fs->dir) { > @@ -395,17 +560,36 @@ static int local_readdir_r(FsContext *ctx, V9fsFidO= penState *fs, > int ret; >=20 > again: > +#ifdef _WIN32 > + error_printf("local_readdir_r: Directory which should be read:%s\n", > + fs->dir->dd_name); > +#endif > ret =3D readdir_r(fs->dir, entry, result); > if (ctx->export_flags & V9FS_SM_MAPPED) { > +#ifndef _WIN32 > entry->d_type =3D DT_UNKNOWN; > +#endif > } else if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { > if (!ret && *result !=3D NULL && > !strcmp(entry->d_name, VIRTFS_META_DIR)) { > /* skp the meta data directory */ > goto again; > } > +#ifndef _WIN32 > entry->d_type =3D DT_UNKNOWN; > +#endif > } > + if (*result =3D=3D NULL) { > + error_printf("local_readdir_r: End of directory -> returning NUL= L\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; > } >=20 > @@ -418,10 +602,15 @@ static ssize_t local_preadv(FsContext *ctx, V9fsFid= OpenState *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 =3D lseek(fs->fd, offset, SEEK_SET); > + error_printf("local_preadv: lseek returned %d\n", err); > if (err =3D=3D -1) { > return err; > } else { > @@ -491,7 +680,7 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *d= ir_path, > char *buffer =3D NULL; >=20 > v9fs_string_init(&fullname); > - v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); > + v9fs_string_sprintf(&fullname, DELIMITER_IN_PATH, dir_path->data, na= me); > path =3D fullname.data; >=20 > /* Determine the security model */ > @@ -552,7 +741,7 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath *d= ir_path, > char *buffer =3D NULL; >=20 > v9fs_string_init(&fullname); > - v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); > + v9fs_string_sprintf(&fullname, DELIMITER_IN_PATH, dir_path->data, na= me); > path =3D fullname.data; >=20 > /* Determine the security model */ > @@ -610,7 +799,14 @@ static int local_fstat(FsContext *fs_ctx, int fid_ty= pe, > int err, fd; >=20 > if (fid_type =3D=3D 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 =3D fs->fd; > +#else > fd =3D dirfd(fs->dir); > +#endif > } else { > fd =3D fs->fd; > } > @@ -619,6 +815,13 @@ static int local_fstat(FsContext *fs_ctx, int fid_ty= pe, > 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 |=3D 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 |=3D O_NOFOLLOW; >=20 > v9fs_string_init(&fullname); > - v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); > + v9fs_string_sprintf(&fullname, DELIMITER_IN_PATH, dir_path->data, na= me); > path =3D fullname.data; >=20 > + 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 =3D rpath(fs_ctx, path); > - fd =3D open(buffer, flags, SM_LOCAL_MODE_BITS); > + fd =3D open(buffer, flags | O_BINARY, SM_LOCAL_MODE_BITS); > if (fd =3D=3D -1) { > err =3D fd; > goto out; > @@ -681,7 +887,7 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *d= ir_path, const char *name, > } > } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) { > buffer =3D rpath(fs_ctx, path); > - fd =3D open(buffer, flags, SM_LOCAL_MODE_BITS); > + fd =3D open(buffer, flags | O_BINARY, SM_LOCAL_MODE_BITS); > if (fd =3D=3D -1) { > err =3D 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 =3D rpath(fs_ctx, path); > - fd =3D open(buffer, flags, credp->fc_mode); > + error_printf("local_open2: File which should be opened (open2): = %s\n", > + buffer); > + fd =3D open(buffer, flags | O_BINARY, credp->fc_mode); > + error_printf("local_open2: open returned %d\n", fd); > if (fd =3D=3D -1) { > err =3D fd; > goto out; > } > err =3D local_post_create_passthrough(fs_ctx, path, credp); > + error_printf("local_open2: local_post_create_passthrough returne= d %u\n", > + err); > if (err =3D=3D -1) { > serrno =3D errno; > goto err_end; > @@ -732,7 +943,7 @@ static int local_symlink(FsContext *fs_ctx, const cha= r *oldpath, > char *buffer =3D NULL; >=20 > v9fs_string_init(&fullname); > - v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name); > + v9fs_string_sprintf(&fullname, DELIMITER_IN_PATH, dir_path->data, na= me); > newpath =3D fullname.data; >=20 > /* Determine the security model */ > @@ -740,7 +951,9 @@ static int local_symlink(FsContext *fs_ctx, const cha= r *oldpath, > int fd; > ssize_t oldpath_size, write_size; > buffer =3D rpath(fs_ctx, newpath); > - fd =3D open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, SM_LOCAL_M= ODE_BITS); > + fd =3D open(buffer, > + O_CREAT | O_EXCL | O_RDWR | O_NOFOLLOW | O_BINARY, > + SM_LOCAL_MODE_BITS); > if (fd =3D=3D -1) { > err =3D fd; > goto out; > @@ -758,8 +971,10 @@ static int local_symlink(FsContext *fs_ctx, const ch= ar *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 =3D credp->fc_mode|S_IFLNK; > +#endif > err =3D local_set_xattr(buffer, credp); > if (err =3D=3D -1) { > serrno =3D errno; > @@ -769,7 +984,9 @@ static int local_symlink(FsContext *fs_ctx, const cha= r *oldpath, > int fd; > ssize_t oldpath_size, write_size; > buffer =3D rpath(fs_ctx, newpath); > - fd =3D open(buffer, O_CREAT|O_EXCL|O_RDWR|O_NOFOLLOW, SM_LOCAL_M= ODE_BITS); > + fd =3D open(buffer, > + O_CREAT | O_EXCL | O_RDWR | O_NOFOLLOW | O_BINARY, > + SM_LOCAL_MODE_BITS); > if (fd =3D=3D -1) { > err =3D fd; > goto out; > @@ -788,7 +1005,9 @@ static int local_symlink(FsContext *fs_ctx, const ch= ar *oldpath, > } > close(fd); > /* Set cleint credentials in symlink's xattr */ > +#ifndef _WIN32 > credp->fc_mode =3D credp->fc_mode|S_IFLNK; > +#endif > err =3D local_set_mapped_file_attr(fs_ctx, newpath, credp); > if (err =3D=3D -1) { > serrno =3D errno; > @@ -833,7 +1052,7 @@ static int local_link(FsContext *ctx, V9fsPath *oldp= ath, > char *buffer, *buffer1; >=20 > v9fs_string_init(&newpath); > - v9fs_string_sprintf(&newpath, "%s/%s", dirpath->data, name); > + v9fs_string_sprintf(&newpath, DELIMITER_IN_PATH, dirpath->data, name= ); >=20 > buffer =3D rpath(ctx, oldpath->data); > buffer1 =3D rpath(ctx, newpath.data); > @@ -934,7 +1153,12 @@ static int local_utimensat(FsContext *s, V9fsPath *= fs_path, > char *path =3D fs_path->data; >=20 > buffer =3D rpath(s, path); > +#ifdef _WIN32 > + #warning "Could cause problems!" > + ret =3D 0; > +#else > ret =3D qemu_utimens(buffer, buf); > +#endif > g_free(buffer); > return ret; > } > @@ -949,6 +1173,7 @@ static int local_remove(FsContext *ctx, const char *= path) > buffer =3D rpath(ctx, path); > err =3D 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 =3D g_strdup_printf("%s/%s/%s", ctx->fs_root, > + buffer =3D g_strdup_printf(DELIMITER_IN_PATH2, ctx->fs_root, > path, VIRTFS_META_DIR); > err =3D remove(buffer); > g_free(buffer); > + error_printf("local_remove: .virtfs_metdata remove %d %d\n", > + err, errno); > if (err < 0 && errno !=3D 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 =3D local_mapped_attr_path(ctx, path); > err =3D remove(buffer); > g_free(buffer); > + error_printf("local_remove: local_mapped_attr_path remove %d %d\= n", > + err, errno); > if (err < 0 && errno !=3D ENOENT) { > /* > * We didn't had the .virtfs_metadata file. May be file crea= ted > @@ -986,7 +1215,14 @@ static int local_remove(FsContext *ctx, const char = *path) > } >=20 > buffer =3D rpath(ctx, path); > - err =3D remove(buffer); > + /* mifritscher: posix remove can delete directories as well, windows= not */ > + if (S_ISDIR(stbuf.st_mode)) { > + err =3D rmdir(buffer); > + } else { > + err =3D 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; >=20 > if (fid_type =3D=3D P9_FID_DIR) { > +#ifdef _WIN32 > + #warning "Could cause problems!" > + fd =3D fs->fd; > +#else > fd =3D dirfd(fs->dir); > +#endif > } else { > fd =3D fs->fd; > } > @@ -1058,10 +1299,14 @@ static int local_name_to_path(FsContext *ctx, V9f= sPath *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); >=20 > - 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); >=20 > ret =3D 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, V9fsPat= h *dir, >=20 > v9fs_string_init(&fullname); >=20 > - 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 =3D=3D AT_REMOVEDIR) { > /* > * If directory remove .virtfs_metadata contained in the > * directory > */ > - buffer =3D g_strdup_printf("%s/%s/%s", ctx->fs_root, > + buffer =3D g_strdup_printf(DELIMITER_IN_PATH2, ctx->fs_root, > fullname.data, VIRTFS_META_DIR); > ret =3D remove(buffer); > g_free(buffer); > + error_printf("local_unlinkat: .virtfs_metadata %d %d\n", > + ret, errno); > if (ret < 0 && errno !=3D 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 =3D local_mapped_attr_path(ctx, fullname.data); > ret =3D remove(buffer); > + error_printf("local_unlinkat: local_mapped_attr_path %d %d\n", > + ret, errno); > g_free(buffer); > if (ret < 0 && errno !=3D ENOENT) { > /* > @@ -1133,6 +1384,19 @@ static int local_unlinkat(FsContext *ctx, V9fsPath= *dir, > /* Remove the name finally */ > buffer =3D rpath(ctx, fullname.data); > ret =3D remove(buffer); > + error_printf("local_unlinkat: final |%s| %d %d\n", buffer, ret, errn= o); > + /* 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 =3D rmdir(buffer); > + error_printf("local_unlinkat: final rmdir |%s| %d %d\n", > + buffer, ret, errno); > + > + } > +#endif > g_free(buffer); >=20 > err_out: > @@ -1140,6 +1404,7 @@ err_out: > return ret; > } >=20 > +#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, V= 9fsPath *path, > return -1; > #endif > } > +#endif >=20 > static int local_init(FsContext *ctx) > { > int err =3D 0; > +#ifdef FS_IOC_GETVERSION > struct statfs stbuf; > +#endif >=20 > +#ifdef _WIN32 > + ctx->xops =3D 0; > +#else > if (ctx->export_flags & V9FS_SM_PASSTHROUGH) { > ctx->xops =3D passthrough_xattr_ops; > } else if (ctx->export_flags & V9FS_SM_MAPPED) { > @@ -1186,6 +1457,7 @@ static int local_init(FsContext *ctx) > */ > ctx->xops =3D passthrough_xattr_ops; > } > +#endif > ctx->export_flags |=3D 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 *n= ode, struct stat *stbuf) > stbuf->st_gid =3D 0; > stbuf->st_rdev =3D 0; > stbuf->st_size =3D 0; > +#ifndef _WIN32 > stbuf->st_blksize =3D 0; > stbuf->st_blocks =3D 0; > +#endif > stbuf->st_atime =3D 0; > stbuf->st_mtime =3D 0; > stbuf->st_ctime =3D 0; > @@ -222,7 +226,11 @@ static void v9fs_synth_direntry(V9fsSynthNode *node, > { > strcpy(entry->d_name, node->name); > entry->d_ino =3D node->attr->inode; > +#ifdef _WIN32 > + #warning "Can cause problems!" > +#else > entry->d_off =3D off + 1; > +#endif > } >=20 > static int v9fs_synth_get_dentry(V9fsSynthNode *dir, struct dirent *entr= y, > 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, V9= fsQID *qidp) > if (S_ISDIR(stbuf->st_mode)) { > qidp->type |=3D P9_QID_TYPE_DIR; > } > - if (S_ISLNK(stbuf->st_mode)) { > - qidp->type |=3D P9_QID_TYPE_SYMLINK; > - } > + #ifndef _WIN32 > + if (S_ISLNK(stbuf->st_mode)) { > + qidp->type |=3D P9_QID_TYPE_SYMLINK; > + } > + #endif > } >=20 > static int fid_to_qid(V9fsPDU *pdu, V9fsFidState *fidp, V9fsQID *qidp) > @@ -677,12 +693,15 @@ static mode_t v9mode_to_mode(uint32_t mode, V9fsStr= ing *extension) > ret |=3D S_IFDIR; > } >=20 > +#ifndef _WIN32 > if (mode & P9_STAT_MODE_SYMLINK) { > ret |=3D S_IFLNK; > } > if (mode & P9_STAT_MODE_SOCKET) { > ret |=3D S_IFSOCK; > } > +#endif > + > if (mode & P9_STAT_MODE_NAMED_PIPE) { > ret |=3D S_IFIFO; > } > @@ -698,6 +717,7 @@ static mode_t v9mode_to_mode(uint32_t mode, V9fsStrin= g *extension) > ret |=3D S_IFREG; > } >=20 > +#ifndef _WIN32 > if (mode & P9_STAT_MODE_SETUID) { > ret |=3D S_ISUID; > } > @@ -707,6 +727,7 @@ static mode_t v9mode_to_mode(uint32_t mode, V9fsStrin= g *extension) > if (mode & P9_STAT_MODE_SETVTX) { > ret |=3D S_ISVTX; > } > +#endif >=20 > return ret; > } > @@ -762,6 +783,7 @@ static uint32_t stat_to_v9mode(const struct stat *stb= uf) > mode |=3D P9_STAT_MODE_DIR; > } >=20 > +#ifndef _WIN32 > if (S_ISLNK(stbuf->st_mode)) { > mode |=3D P9_STAT_MODE_SYMLINK; > } > @@ -769,6 +791,7 @@ static uint32_t stat_to_v9mode(const struct stat *stb= uf) > if (S_ISSOCK(stbuf->st_mode)) { > mode |=3D P9_STAT_MODE_SOCKET; > } > +#endif >=20 > if (S_ISFIFO(stbuf->st_mode)) { > mode |=3D P9_STAT_MODE_NAMED_PIPE; > @@ -778,6 +801,7 @@ static uint32_t stat_to_v9mode(const struct stat *stb= uf) > mode |=3D P9_STAT_MODE_DEVICE; > } >=20 > +#ifndef _WIN32 > if (stbuf->st_mode & S_ISUID) { > mode |=3D P9_STAT_MODE_SETUID; > } > @@ -789,6 +813,7 @@ static uint32_t stat_to_v9mode(const struct stat *stb= uf) > if (stbuf->st_mode & S_ISVTX) { > mode |=3D P9_STAT_MODE_SETVTX; > } > +#endif >=20 > return mode; > } > @@ -881,14 +906,34 @@ static void stat_to_v9stat_dotl(V9fsState *s, const= struct stat *stbuf, > v9lstat->st_gid =3D stbuf->st_gid; > v9lstat->st_rdev =3D stbuf->st_rdev; > v9lstat->st_size =3D stbuf->st_size; > +#ifdef _WIN32 > + /* Blksize is the optimal EA-block, > + while blocks always refers to 512 blocks > + */ > + v9lstat->st_blksize =3D 4096; > + v9lstat->st_blocks =3D ((stbuf->st_size + 1) / 512) + 1; > +#else > v9lstat->st_blksize =3D stbuf->st_blksize; > v9lstat->st_blocks =3D stbuf->st_blocks; > +#endif > v9lstat->st_atime_sec =3D stbuf->st_atime; > +#ifdef _WIN32 > + v9lstat->st_atime_nsec =3D 0; > +#else > v9lstat->st_atime_nsec =3D stbuf->st_atim.tv_nsec; > +#endif > v9lstat->st_mtime_sec =3D stbuf->st_mtime; > +#ifdef _WIN32 > + v9lstat->st_mtime_nsec =3D 0; > +#else > v9lstat->st_mtime_nsec =3D stbuf->st_mtim.tv_nsec; > +#endif > v9lstat->st_ctime_sec =3D stbuf->st_ctime; > +#ifdef _WIN32 > + v9lstat->st_ctime_nsec =3D 0; > +#else > v9lstat->st_ctime_nsec =3D stbuf->st_ctim.tv_nsec; > +#endif > /* Currently we only support BASIC fields in stat */ > v9lstat->st_result_mask =3D P9_STATS_BASIC; >=20 > @@ -1639,7 +1684,10 @@ static int v9fs_do_readdir_with_stat(V9fsPDU *pdu, > v9fs_path_init(&path); > err =3D 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 =3D v9fs_co_name_to_path(pdu, &fidp->path, dent->d_name, &pa= th); > if (err < 0) { > @@ -1666,7 +1714,12 @@ static int v9fs_do_readdir_with_stat(V9fsPDU *pdu, > count +=3D len; > v9fs_stat_free(&v9stat); > v9fs_path_free(&path); > +#ifdef _WIN32 > + #warning "Probably right, but could make problems!" > + saved_dir_pos =3D v9fs_co_telldir(pdu, fidp); > +#else > saved_dir_pos =3D dent->d_off; > +#endif > } > out: > g_free(dent); > @@ -1806,6 +1859,9 @@ static int v9fs_do_readdir(V9fsPDU *pdu, > int32_t count =3D 0; > off_t saved_dir_pos; > struct dirent *dent, *result; > +#ifdef _WIN32 > + uint8_t type =3D 0; /* DT_UNKNOWN */ > +#endif >=20 > /* save the directory position */ > saved_dir_pos =3D v9fs_co_telldir(pdu, fidp); > @@ -1818,15 +1874,27 @@ static int v9fs_do_readdir(V9fsPDU *pdu, > while (1) { > err =3D 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 retur= n */ > 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 =3D 0; >=20 > /* 11 =3D 7 + 4 (7 =3D start offset, 4 =3D space for storing cou= nt) */ > +#ifdef _WIN32 > + #warning "Probably right, but could make problems!" > + len =3D pdu_marshal(pdu, 11 + count, "Qqbs", > + &qid, v9fs_co_telldir(pdu, fidp), > + type, &name); > +#else > len =3D 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 +=3D len; > v9fs_string_free(&name); > +#ifdef _WIN32 > + #warning "Probably right, but could make problems!" > + saved_dir_pos =3D v9fs_co_telldir(pdu, fidp); > +#else > saved_dir_pos =3D dent->d_off; > +#endif > } > g_free(dent); > if (err < 0) { > return err; > } > + error_printf("v9fs_do_readdir: return %d\n\n", count); > return count; > } >=20 > @@ -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); >=20 > fidp =3D get_fid(pdu, fid); > if (fidp =3D=3D NULL) { > @@ -1904,10 +1987,13 @@ static void v9fs_readdir(void *opaque) > } > retval +=3D 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"); > } >=20 > static int v9fs_xattr_write(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fi= dp, > @@ -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 =3D -1; > +#else > err =3D 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, Err= or **errp) >=20 > 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_s= et_fd_limit(void) > } > open_fd_hw =3D rlim.rlim_cur - MIN(400, rlim.rlim_cur/3); > open_fd_rc =3D 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 @@ >=20 > #include > #include > -#include > +#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 > +#endif > + > #include > #include "standard-headers/linux/virtio_9p.h" > #include "hw/virtio/virtio.h" > @@ -12,6 +34,10 @@ > #include "qemu/thread.h" > #include "qemu/coroutine.h" >=20 > +#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 =3D 6, > P9_RLERROR, > @@ -108,9 +134,49 @@ enum p9_proto_version { >=20 > #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 =3D g_strdup_printf(DELIMITER_IN_PATH, ctx->fs_root, path); > +#ifdef _WIN32 > + int input =3D 0; > + int output =3D 0; > + while (result[input]) { > + /* error_printf("<-%d %c\n", input, result[input]); */ > + if (result[input] =3D=3D '/') { > + result[output] =3D '\\'; > + /* remove duplicate \... */ Why do we need to remove duplicate \ ? > + if (output > 0 && result[output - 1] =3D=3D '\\') { > + /* error_printf("remove duplicate \\\n"); */ > + output--; > + } else { > + result[output] =3D '\\'; > + } > + /* error_printf(" %c\n", result[output]); */ > + } else { > + result[output] =3D 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] =3D=3D '\\' > + && (output =3D=3D 1 || result[output - 2] !=3D ':')) { > + /* error_printf("Killed last \\\n"); */ > + result[output - 1] =3D '\0'; > + } else { > + result[output] =3D '\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; > } >=20 > /* > 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 =3D 9p.o > -common-obj-y +=3D 9p-local.o 9p-xattr.o > -common-obj-y +=3D 9p-xattr-user.o 9p-posix-acl.o > +common-obj-$(CONFIG_LINUX) +=3D 9p-local.o 9p-xattr.o > +common-obj-$(CONFIG_LINUX) +=3D 9p-xattr-user.o 9p-posix-acl.o > +common-obj-$(CONFIG_WIN32) +=3D 9p-local.o > common-obj-y +=3D coth.o cofs.o codir.o cofile.o > common-obj-y +=3D coxattr.o 9p-synth.o > common-obj-$(CONFIG_OPEN_BY_HANDLE) +=3D 9p-handle.o > -common-obj-y +=3D 9p-proxy.o > +common-obj-$(CONFIG_POSIX) +=3D 9p-proxy.o >=20 > obj-y +=3D 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" >=20 > int v9fs_co_readdir_r(V9fsPDU *pdu, V9fsFidState *fidp, struct dirent *d= ent, > struct dirent **result) > @@ -37,6 +39,12 @@ int v9fs_co_readdir_r(V9fsPDU *pdu, V9fsFidState *fidp= , struct dirent *dent, > err =3D 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; > } >=20 > @@ -55,6 +63,12 @@ off_t v9fs_co_telldir(V9fsPDU *pdu, V9fsFidState *fidp) > err =3D -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; > } >=20 > @@ -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 > } >=20 > void v9fs_co_rewinddir(V9fsPDU *pdu, V9fsFidState *fidp) > @@ -80,6 +99,11 @@ void v9fs_co_rewinddir(V9fsPDU *pdu, V9fsFidState *fid= p) > { > 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 > } >=20 > int v9fs_co_mkdir(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name, > @@ -116,6 +140,7 @@ int v9fs_co_mkdir(V9fsPDU *pdu, V9fsFidState *fidp, V= 9fsString *name, > } > }); > v9fs_path_unlock(s); > + error_printf("v9fs_co_mkdir: %d\n", err); > return err; > } >=20 > @@ -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; > } >=20 > @@ -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" >=20 > 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; > } >=20 > @@ -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; > } >=20 > @@ -91,6 +95,7 @@ int v9fs_co_fstat(V9fsPDU *pdu, V9fsFidState *fidp, str= uct stat *stbuf) > err =3D 0; > } > } > + error_printf("v9fs_co_fstat: %s %d\n", (&fidp->path)->data, err); > return err; > } >=20 > @@ -119,6 +124,7 @@ int v9fs_co_open(V9fsPDU *pdu, V9fsFidState *fidp, in= t flags) > v9fs_reclaim_fd(pdu); > } > } > + error_printf("v9fs_co_open: %s %d\n", (&fidp->path)->data, err); > return err; > } >=20 > @@ -147,13 +153,17 @@ int v9fs_co_open2(V9fsPDU *pdu, V9fsFidState *fidp,= V9fsString *name, gid_t gid, > { > err =3D 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 =3D -errno; > } else { > v9fs_path_init(&path); > err =3D v9fs_name_to_path(s, &fidp->path, name->data, &p= ath); > + error_printf("v9fs_co_open2: v9fs_name_to_path returned = %d\n", > + err); > if (!err) { > err =3D s->ops->lstat(&s->ctx, &path, stbuf); > + error_printf("v9fs_co_open2: lstat returned %d\n", e= rr); > if (err < 0) { > err =3D -errno; > s->ops->close(&s->ctx, &fidp->fs); > @@ -173,6 +183,7 @@ int v9fs_co_open2(V9fsPDU *pdu, V9fsFidState *fidp, V= 9fsString *name, gid_t gid, > v9fs_reclaim_fd(pdu); > } > } > + error_printf("v9fs_co_open2: %s %d\n", (&fidp->path)->data, err); > return err; > } >=20 > @@ -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; > } >=20 > @@ -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; > } >=20 > @@ -253,6 +266,7 @@ int v9fs_co_pwritev(V9fsPDU *pdu, V9fsFidState *fidp, > err =3D -errno; > } > }); > + error_printf("v9fs_co_pwritev: %s %d\n", (&fidp->path)->data, err); > return err; > } >=20 > @@ -272,5 +286,6 @@ int v9fs_co_preadv(V9fsPDU *pdu, V9fsFidState *fidp, > err =3D -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" >=20 > static ssize_t __readlink(V9fsState *s, V9fsPath *path, V9fsString *buf) > { > @@ -67,6 +69,7 @@ int v9fs_co_readlink(V9fsPDU *pdu, V9fsPath *path, V9fs= String *buf) > } > }); > v9fs_path_unlock(s); > + error_printf("v9fs_co_readlink: %d\n", err); > return err; > } >=20 > @@ -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; > } >=20 > @@ -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; > } >=20 > @@ -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; > } >=20 > @@ -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; > } >=20 > @@ -175,6 +182,7 @@ int v9fs_co_truncate(V9fsPDU *pdu, V9fsPath *path, of= f_t size) > } > }); > v9fs_path_unlock(s); > + error_printf("v9fs_co_truncate: %d\n", err); > return err; > } >=20 > @@ -213,6 +221,7 @@ int v9fs_co_mknod(V9fsPDU *pdu, V9fsFidState *fidp, V= 9fsString *name, uid_t uid, > } > }); > v9fs_path_unlock(s); > + error_printf("v9fs_co_mknod: %d\n", err); > return err; > } >=20 > @@ -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; > } >=20 > @@ -254,6 +264,7 @@ int v9fs_co_unlinkat(V9fsPDU *pdu, V9fsPath *path, V9= fsString *name, int flags) > } > }); > v9fs_path_unlock(s); > + error_printf("v9fs_co_unlinkat: %d\n", err); > return err; > } >=20 > @@ -273,6 +284,7 @@ int v9fs_co_rename(V9fsPDU *pdu, V9fsPath *oldpath, V= 9fsPath *newpath) > err =3D -errno; > } > }); > + error_printf("v9fs_co_rename: %d\n", err); > return err; > } >=20 > @@ -293,6 +305,7 @@ int v9fs_co_renameat(V9fsPDU *pdu, V9fsPath *olddirpa= th, V9fsString *oldname, > err =3D -errno; > } > }); > + error_printf("v9fs_co_renameat: %d\n", err); > return err; > } >=20 > @@ -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; > } >=20 > @@ -361,5 +375,6 @@ int v9fs_co_name_to_path(V9fsPDU *pdu, V9fsPath *dirp= ath, > } > }); > } > + 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" >=20 > 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, vo= id *value, size_t size) > } > }); > v9fs_path_unlock(s); > + error_printf("v9fs_co_llistxattr: %d\n", err); > return err; > } >=20 > @@ -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; > } >=20 > @@ -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; > } >=20 > @@ -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"