The branch main has been updated by dchagin:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=e4bffb80bbc6a2e4b3be89aefcbd5bb2c2fc0ba0

commit e4bffb80bbc6a2e4b3be89aefcbd5bb2c2fc0ba0
Author:     Dmitry Chagin <dcha...@freebsd.org>
AuthorDate: 2021-06-07 01:54:30 +0000
Commit:     Dmitry Chagin <dcha...@freebsd.org>
CommitDate: 2021-06-07 01:54:30 +0000

    linux(4): Implement utimensat_time64 system call.
    
    MFC after:      2 weeks
---
 sys/amd64/linux32/linux32_dummy_machdep.c |   1 -
 sys/amd64/linux32/syscalls.master         |   7 +-
 sys/compat/linux/linux_misc.c             | 181 ++++++++++++++++++++----------
 sys/i386/linux/linux_dummy_machdep.c      |   1 -
 sys/i386/linux/syscalls.master            |   7 +-
 5 files changed, 134 insertions(+), 63 deletions(-)

diff --git a/sys/amd64/linux32/linux32_dummy_machdep.c 
b/sys/amd64/linux32/linux32_dummy_machdep.c
index 5eb54fefd276..be07eb033e77 100644
--- a/sys/amd64/linux32/linux32_dummy_machdep.c
+++ b/sys/amd64/linux32/linux32_dummy_machdep.c
@@ -76,7 +76,6 @@ DUMMY(timer_gettime64);
 DUMMY(timer_settime64);
 DUMMY(timerfd_gettime64);
 DUMMY(timerfd_settime64);
-DUMMY(utimensat_time64);
 DUMMY(pselect6_time64);
 DUMMY(ppoll_time64);
 DUMMY(io_pgetevents_time64);
diff --git a/sys/amd64/linux32/syscalls.master 
b/sys/amd64/linux32/syscalls.master
index d7002ed5ac72..67591b487652 100644
--- a/sys/amd64/linux32/syscalls.master
+++ b/sys/amd64/linux32/syscalls.master
@@ -2368,7 +2368,12 @@
                int linux_timerfd_settime64(void);
        }
 412    AUE_NULL        STD {
-               int linux_utimensat_time64(void);
+               int linux_utimensat_time64(
+                   l_int dfd,
+                   const char *pathname,
+                   const struct l_timespec64 *times64,
+                   l_int flags
+               );
        }
 413    AUE_NULL        STD {
                int linux_pselect6_time64(void);
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c
index c3f783694d84..bfa7bb659d5f 100644
--- a/sys/compat/linux/linux_misc.c
+++ b/sys/compat/linux/linux_misc.c
@@ -130,7 +130,14 @@ struct l_pselect6arg {
        l_size_t        ss_len;
 };
 
-static int     linux_utimensat_nsec_valid(l_long);
+static int     linux_utimensat_lts_to_ts(struct l_timespec *,
+                       struct timespec *);
+#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
+static int     linux_utimensat_lts64_to_ts(struct l_timespec64 *,
+                       struct timespec *);
+#endif
+static int     linux_common_utimensat(struct thread *, int,
+                       const char *, struct timespec *, int);
 
 int
 linux_sysinfo(struct thread *td, struct linux_sysinfo_args *args)
@@ -780,89 +787,66 @@ linux_utimes(struct thread *td, struct linux_utimes_args 
*args)
 #endif
 
 static int
-linux_utimensat_nsec_valid(l_long nsec)
+linux_utimensat_lts_to_ts(struct l_timespec *l_times, struct timespec *times)
 {
 
-       if (nsec == LINUX_UTIME_OMIT || nsec == LINUX_UTIME_NOW)
-               return (0);
-       if (nsec >= 0 && nsec <= 999999999)
-               return (0);
-       return (1);
+       if (l_times->tv_nsec != LINUX_UTIME_OMIT &&
+           l_times->tv_nsec != LINUX_UTIME_NOW &&
+           (l_times->tv_nsec < 0 || l_times->tv_nsec > 999999999))
+               return (EINVAL);
+
+       times->tv_sec = l_times->tv_sec;
+       switch (l_times->tv_nsec)
+       {
+       case LINUX_UTIME_OMIT:
+               times->tv_nsec = UTIME_OMIT;
+               break;
+       case LINUX_UTIME_NOW:
+               times->tv_nsec = UTIME_NOW;
+               break;
+       default:
+               times->tv_nsec = l_times->tv_nsec;
+       }
+
+       return (0);
 }
 
-int
-linux_utimensat(struct thread *td, struct linux_utimensat_args *args)
+static int
+linux_common_utimensat(struct thread *td, int ldfd, const char *pathname,
+    struct timespec *timesp, int lflags)
 {
-       struct l_timespec l_times[2];
-       struct timespec times[2], *timesp = NULL;
        char *path = NULL;
        int error, dfd, flags = 0;
 
-       dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd;
+       dfd = (ldfd == LINUX_AT_FDCWD) ? AT_FDCWD : ldfd;
 
-       if (args->flags & ~(LINUX_AT_SYMLINK_NOFOLLOW | LINUX_AT_EMPTY_PATH))
+       if (lflags & ~(LINUX_AT_SYMLINK_NOFOLLOW | LINUX_AT_EMPTY_PATH))
                return (EINVAL);
 
-       if (args->times != NULL) {
-               error = copyin(args->times, l_times, sizeof(l_times));
-               if (error != 0)
-                       return (error);
-
-               if (linux_utimensat_nsec_valid(l_times[0].tv_nsec) != 0 ||
-                   linux_utimensat_nsec_valid(l_times[1].tv_nsec) != 0)
-                       return (EINVAL);
-
-               times[0].tv_sec = l_times[0].tv_sec;
-               switch (l_times[0].tv_nsec)
-               {
-               case LINUX_UTIME_OMIT:
-                       times[0].tv_nsec = UTIME_OMIT;
-                       break;
-               case LINUX_UTIME_NOW:
-                       times[0].tv_nsec = UTIME_NOW;
-                       break;
-               default:
-                       times[0].tv_nsec = l_times[0].tv_nsec;
-               }
-
-               times[1].tv_sec = l_times[1].tv_sec;
-               switch (l_times[1].tv_nsec)
-               {
-               case LINUX_UTIME_OMIT:
-                       times[1].tv_nsec = UTIME_OMIT;
-                       break;
-               case LINUX_UTIME_NOW:
-                       times[1].tv_nsec = UTIME_NOW;
-                       break;
-               default:
-                       times[1].tv_nsec = l_times[1].tv_nsec;
-                       break;
-               }
-               timesp = times;
-
+       if (timesp != NULL) {
                /* This breaks POSIX, but is what the Linux kernel does
                 * _on purpose_ (documented in the man page for utimensat(2)),
                 * so we must follow that behaviour. */
-               if (times[0].tv_nsec == UTIME_OMIT &&
-                   times[1].tv_nsec == UTIME_OMIT)
+               if (timesp[0].tv_nsec == UTIME_OMIT &&
+                   timesp[1].tv_nsec == UTIME_OMIT)
                        return (0);
        }
 
-       if (args->flags & LINUX_AT_SYMLINK_NOFOLLOW)
+       if (lflags & LINUX_AT_SYMLINK_NOFOLLOW)
                flags |= AT_SYMLINK_NOFOLLOW;
-       if (args->flags & LINUX_AT_EMPTY_PATH)
+       if (lflags & LINUX_AT_EMPTY_PATH)
                flags |= AT_EMPTY_PATH;
 
        if (!LUSECONVPATH(td)) {
-               if (args->pathname != NULL) {
-                       return (kern_utimensat(td, dfd, args->pathname,
+               if (pathname != NULL) {
+                       return (kern_utimensat(td, dfd, pathname,
                            UIO_USERSPACE, timesp, UIO_SYSSPACE, flags));
                }
        }
 
-       if (args->pathname != NULL)
-               LCONVPATHEXIST_AT(td, args->pathname, &path, dfd);
-       else if (args->flags != 0)
+       if (pathname != NULL)
+               LCONVPATHEXIST_AT(td, pathname, &path, dfd);
+       else if (lflags != 0)
                return (EINVAL);
 
        if (path == NULL)
@@ -876,6 +860,85 @@ linux_utimensat(struct thread *td, struct 
linux_utimensat_args *args)
        return (error);
 }
 
+int
+linux_utimensat(struct thread *td, struct linux_utimensat_args *args)
+{
+       struct l_timespec l_times[2];
+       struct timespec times[2], *timesp;
+       int error;
+
+       if (args->times != NULL) {
+               error = copyin(args->times, l_times, sizeof(l_times));
+               if (error != 0)
+                       return (error);
+
+               error = linux_utimensat_lts_to_ts(&l_times[0], &times[0]);
+               if (error != 0)
+                       return (error);
+               error = linux_utimensat_lts_to_ts(&l_times[1], &times[1]);
+               if (error != 0)
+                       return (error);
+               timesp = times;
+       } else
+               timesp = NULL;
+
+       return (linux_common_utimensat(td, args->dfd, args->pathname,
+           timesp, args->flags));
+}
+
+#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
+static int
+linux_utimensat_lts64_to_ts(struct l_timespec64 *l_times, struct timespec 
*times)
+{
+
+       if (l_times->tv_nsec != LINUX_UTIME_OMIT &&
+           l_times->tv_nsec != LINUX_UTIME_NOW &&
+           (l_times->tv_nsec < 0 || l_times->tv_nsec > 999999999))
+               return (EINVAL);
+
+       times->tv_sec = l_times->tv_sec;
+       switch (l_times->tv_nsec)
+       {
+       case LINUX_UTIME_OMIT:
+               times->tv_nsec = UTIME_OMIT;
+               break;
+       case LINUX_UTIME_NOW:
+               times->tv_nsec = UTIME_NOW;
+               break;
+       default:
+               times->tv_nsec = l_times->tv_nsec;
+       }
+
+       return (0);
+}
+
+int
+linux_utimensat_time64(struct thread *td, struct linux_utimensat_time64_args 
*args)
+{
+       struct l_timespec64 l_times[2];
+       struct timespec times[2], *timesp;
+       int error;
+
+       if (args->times64 != NULL) {
+               error = copyin(args->times64, l_times, sizeof(l_times));
+               if (error != 0)
+                       return (error);
+
+               error = linux_utimensat_lts64_to_ts(&l_times[0], &times[0]);
+               if (error != 0)
+                       return (error);
+               error = linux_utimensat_lts64_to_ts(&l_times[1], &times[1]);
+               if (error != 0)
+                       return (error);
+               timesp = times;
+       } else
+               timesp = NULL;
+
+       return (linux_common_utimensat(td, args->dfd, args->pathname,
+           timesp, args->flags));
+}
+#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
+
 #ifdef LINUX_LEGACY_SYSCALLS
 int
 linux_futimesat(struct thread *td, struct linux_futimesat_args *args)
diff --git a/sys/i386/linux/linux_dummy_machdep.c 
b/sys/i386/linux/linux_dummy_machdep.c
index dfcc691a3582..d479ecde7a01 100644
--- a/sys/i386/linux/linux_dummy_machdep.c
+++ b/sys/i386/linux/linux_dummy_machdep.c
@@ -78,7 +78,6 @@ DUMMY(timer_gettime64);
 DUMMY(timer_settime64);
 DUMMY(timerfd_gettime64);
 DUMMY(timerfd_settime64);
-DUMMY(utimensat_time64);
 DUMMY(pselect6_time64);
 DUMMY(ppoll_time64);
 DUMMY(io_pgetevents_time64);
diff --git a/sys/i386/linux/syscalls.master b/sys/i386/linux/syscalls.master
index e2732d211235..5ba21877f42c 100644
--- a/sys/i386/linux/syscalls.master
+++ b/sys/i386/linux/syscalls.master
@@ -2386,7 +2386,12 @@
                int linux_timerfd_settime64(void);
        }
 412    AUE_NULL        STD {
-               int linux_utimensat_time64(void);
+               int linux_utimensat_time64(
+                   l_int dfd,
+                   const char *pathname,
+                   const struct l_timespec64 *times64,
+                   l_int flags
+               );
        }
 413    AUE_NULL        STD {
                int linux_pselect6_time64(void);
_______________________________________________
dev-commits-src-main@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-main
To unsubscribe, send any mail to "dev-commits-src-main-unsubscr...@freebsd.org"

Reply via email to