diff mbox series

[v2,10/19] hw/9pfs: Add a helper qemu_stat_rdev()

Message ID 20221111042225.1115931-11-bin.meng@windriver.com (mailing list archive)
State New, archived
Headers show
Series At present there is no Windows support for 9p file system. | expand

Commit Message

Bin Meng Nov. 11, 2022, 4:22 a.m. UTC
As Windows host does not have stat->st_rdev field, we use the first
3 characters of the root path to build a device id.

Add a helper qemu_stat_rdev() to use it to avoid direct access to
stat->st_rdev.

Co-developed-by: Guohuai Shi <guohuai.shi@windriver.com>
Signed-off-by: Bin Meng <bin.meng@windriver.com>

---

Changes in v2:
- new patch: "hw/9pfs: Add a helper qemu_stat_rdev()"

 hw/9pfs/9p-util.h       | 20 +++++++++++++++++---
 hw/9pfs/9p-util-win32.c | 15 +++++++++++++++
 hw/9pfs/9p.c            |  7 +++++--
 3 files changed, 37 insertions(+), 5 deletions(-)
diff mbox series

Patch

diff --git a/hw/9pfs/9p-util.h b/hw/9pfs/9p-util.h
index 892465b392..c424cb00ca 100644
--- a/hw/9pfs/9p-util.h
+++ b/hw/9pfs/9p-util.h
@@ -19,7 +19,7 @@ 
 #define O_PATH_9P_UTIL 0
 #endif
 
-#if !defined(CONFIG_LINUX)
+#ifdef CONFIG_DARWIN
 
 /*
  * Generates a Linux device number (a.k.a. dev_t) for given device major
@@ -51,10 +51,12 @@  static inline uint64_t makedev_dotl(uint32_t dev_major, uint32_t dev_minor)
  */
 static inline uint64_t host_dev_to_dotl_dev(dev_t dev)
 {
-#ifdef CONFIG_LINUX
+#if defined(CONFIG_LINUX) || defined(CONFIG_WIN32)
     return dev;
-#else
+#elif defined(CONFIG_DARWIN)
     return makedev_dotl(major(dev), minor(dev));
+#else
+#error Missing host_dev_to_dotl_dev() implementation for this host system
 #endif
 }
 
@@ -130,6 +132,7 @@  QemuFd_t openat_dir(QemuFd_t dirfd, const char *name);
 QemuFd_t openat_file(QemuFd_t dirfd, const char *name, int flags,
                      mode_t mode);
 off_t qemu_dirent_off_win32(void *s, void *fs);
+uint64_t qemu_stat_rdev_win32(void *fs_ctx);
 #endif
 
 static inline void close_preserve_errno(QemuFd_t fd)
@@ -251,6 +254,17 @@  static inline struct dirent *qemu_dirent_dup(struct dirent *dent)
     return g_memdup(dent, sz);
 }
 
+static inline uint64_t qemu_stat_rdev(const struct stat *stbuf, void *fs_ctx)
+{
+#if defined(CONFIG_LINUX) || defined(CONFIG_DARWIN)
+    return stbuf->st_rdev;
+#elif defined(CONFIG_WIN32)
+    return qemu_stat_rdev_win32(fs_ctx);
+#else
+#error Missing qemu_stat_rdev() implementation for this host system
+#endif
+}
+
 /*
  * As long as mknodat is not available on macOS, this workaround
  * using pthread_fchdir_np is needed. qemu_mknodat is defined in
diff --git a/hw/9pfs/9p-util-win32.c b/hw/9pfs/9p-util-win32.c
index a8b8b8c832..44c10370ae 100644
--- a/hw/9pfs/9p-util-win32.c
+++ b/hw/9pfs/9p-util-win32.c
@@ -939,3 +939,18 @@  off_t qemu_dirent_off_win32(void *s, void *fs)
 
     return v9fs->ops->telldir(&v9fs->ctx, (V9fsFidOpenState *)fs);
 }
+
+uint64_t qemu_stat_rdev_win32(void *fs_ctx)
+{
+    uint64_t rdev = 0;
+    LocalData *data = ((FsContext *)fs_ctx)->private;
+
+    /*
+     * As Windows host does not have stat->st_rdev field, we use the first
+     * 3 characters of the root path to build a device id.
+     *
+     * (Windows root path always starts from a driver letter like "C:\")
+     */
+    memcpy(&rdev, data->root_path, 3);
+    return rdev;
+}
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index be247eeb30..7080503b97 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -1266,7 +1266,8 @@  static int coroutine_fn stat_to_v9stat(V9fsPDU *pdu, V9fsPath *path,
     } else if (v9stat->mode & P9_STAT_MODE_DEVICE) {
         v9fs_string_sprintf(&v9stat->extension, "%c %u %u",
                 S_ISCHR(stbuf->st_mode) ? 'c' : 'b',
-                major(stbuf->st_rdev), minor(stbuf->st_rdev));
+                major(qemu_stat_rdev(stbuf, &pdu->s->ctx)),
+                minor(qemu_stat_rdev(stbuf, &pdu->s->ctx)));
     } else if (S_ISDIR(stbuf->st_mode) || S_ISREG(stbuf->st_mode)) {
         v9fs_string_sprintf(&v9stat->extension, "%s %lu",
                 "HARDLINKCOUNT", (unsigned long)stbuf->st_nlink);
@@ -1340,13 +1341,15 @@  static int32_t stat_to_iounit(const V9fsPDU *pdu, const struct stat *stbuf)
 static int stat_to_v9stat_dotl(V9fsPDU *pdu, const struct stat *stbuf,
                                 V9fsStatDotl *v9lstat)
 {
+    dev_t rdev = qemu_stat_rdev(stbuf, &pdu->s->ctx);
+
     memset(v9lstat, 0, sizeof(*v9lstat));
 
     v9lstat->st_mode = stbuf->st_mode;
     v9lstat->st_nlink = stbuf->st_nlink;
     v9lstat->st_uid = stbuf->st_uid;
     v9lstat->st_gid = stbuf->st_gid;
-    v9lstat->st_rdev = host_dev_to_dotl_dev(stbuf->st_rdev);
+    v9lstat->st_rdev = host_dev_to_dotl_dev(rdev);
     v9lstat->st_size = stbuf->st_size;
     v9lstat->st_blksize = stat_to_iounit(pdu, stbuf);
     v9lstat->st_blocks = stbuf->st_blocks;