diff mbox

[v5] virtio-9p: fix build on !CONFIG_UTIMENSAT

Message ID 4CEC7A92.3080302@jp.fujitsu.com (mailing list archive)
State New, archived
Headers show

Commit Message

Hidetoshi Seto Nov. 24, 2010, 2:38 a.m. UTC
None
diff mbox

Patch

diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index 0d52020..41603ea 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -480,9 +480,9 @@  static int local_chown(FsContext *fs_ctx, const char *path, FsCred *credp)
 }
 
 static int local_utimensat(FsContext *s, const char *path,
-		       const struct timespec *buf)
+                           const struct timespec *buf)
 {
-    return utimensat(AT_FDCWD, rpath(s, path), buf, AT_SYMLINK_NOFOLLOW);
+    return qemu_utimensat(AT_FDCWD, rpath(s, path), buf, AT_SYMLINK_NOFOLLOW);
 }
 
 static int local_remove(FsContext *ctx, const char *path)
diff --git a/oslib-posix.c b/oslib-posix.c
index 727dee1..edd4ddf 100644
--- a/oslib-posix.c
+++ b/oslib-posix.c
@@ -111,3 +111,51 @@  int qemu_pipe(int pipefd[2])
 
     return ret;
 }
+
+int qemu_utimensat(int dirfd, const char *path, const struct timespec *times,
+                   int flags)
+{
+    struct timeval tv[2], tv_now;
+    struct stat st;
+    int i;
+#ifdef CONFIG_UTIMENSAT
+    int ret;
+
+    ret = utimensat(dirfd, path, times, flags);
+    if (ret != -1 || errno != ENOSYS) {
+        return ret;
+    }
+#endif
+    /* Fallback: use utimes() instead of utimensat() */
+
+    /* happy if special cases */
+    if (times[0].tv_nsec == UTIME_OMIT && times[1].tv_nsec == UTIME_OMIT) {
+        return 0;
+    }
+    if (times[0].tv_nsec == UTIME_NOW && times[1].tv_nsec == UTIME_NOW) {
+        return utimes(path, NULL);
+    }
+
+    /* prepare for hard cases */
+    if (times[0].tv_nsec == UTIME_NOW || times[1].tv_nsec == UTIME_NOW) {
+        gettimeofday(&tv_now, NULL);
+    }
+    if (times[0].tv_nsec == UTIME_OMIT || times[1].tv_nsec == UTIME_OMIT) {
+        stat(path, &st);
+    }
+
+    for (i = 0; i < 2; i++) {
+        if (times[i].tv_nsec == UTIME_NOW) {
+            tv[i].tv_sec = tv_now.tv_sec;
+            tv[i].tv_usec = tv_now.tv_usec;
+        } else if (times[i].tv_nsec == UTIME_OMIT) {
+            tv[i].tv_sec = (i == 0) ? st.st_atime : st.st_mtime;
+            tv[i].tv_usec = 0;
+        } else {
+            tv[i].tv_sec = times[i].tv_sec;
+            tv[i].tv_usec = times[i].tv_nsec / 1000;
+        }
+    }
+
+    return utimes(path, &tv[0]);
+}
diff --git a/qemu-os-posix.h b/qemu-os-posix.h
index 353f878..81fd9ab 100644
--- a/qemu-os-posix.h
+++ b/qemu-os-posix.h
@@ -39,4 +39,16 @@  void os_setup_post(void);
 typedef struct timeval qemu_timeval;
 #define qemu_gettimeofday(tp) gettimeofday(tp, NULL)
 
+#ifndef CONFIG_UTIMENSAT
+#ifndef UTIME_NOW
+# define UTIME_NOW     ((1l << 30) - 1l)
+#endif
+#ifndef UTIME_OMIT
+# define UTIME_OMIT    ((1l << 30) - 2l)
+#endif
+#endif
+typedef struct timespec qemu_timespec;
+int qemu_utimensat(int dirfd, const char *path, const qemu_timespec *times,
+    int flags);
+
 #endif