Date: Sun, 24 May 2015 17:57:08 +0000 (UTC) From: Dmitry Chagin <dchagin@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r283480 - in head/sys: amd64/linux amd64/linux32 compat/linux i386/linux Message-ID: <201505241757.t4OHv8Iv035816@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: dchagin Date: Sun May 24 17:57:07 2015 New Revision: 283480 URL: https://svnweb.freebsd.org/changeset/base/283480 Log: Add utimensat() system call. The patch developed by Jilles Tjoelker and Andrew Wilcox and adopted for lemul branch by me. Modified: head/sys/amd64/linux/linux_dummy.c head/sys/amd64/linux/syscalls.master head/sys/amd64/linux32/linux32_dummy.c head/sys/amd64/linux32/syscalls.master head/sys/compat/linux/linux_misc.c head/sys/compat/linux/linux_misc.h head/sys/i386/linux/linux_dummy.c head/sys/i386/linux/syscalls.master Modified: head/sys/amd64/linux/linux_dummy.c ============================================================================== --- head/sys/amd64/linux/linux_dummy.c Sun May 24 17:56:02 2015 (r283479) +++ head/sys/amd64/linux/linux_dummy.c Sun May 24 17:57:07 2015 (r283480) @@ -98,7 +98,6 @@ DUMMY(tee); DUMMY(sync_file_range); DUMMY(vmsplice); DUMMY(move_pages); -DUMMY(utimensat); DUMMY(epoll_pwait); DUMMY(signalfd); DUMMY(timerfd); Modified: head/sys/amd64/linux/syscalls.master ============================================================================== --- head/sys/amd64/linux/syscalls.master Sun May 24 17:56:02 2015 (r283479) +++ head/sys/amd64/linux/syscalls.master Sun May 24 17:57:07 2015 (r283480) @@ -468,7 +468,8 @@ 277 AUE_NULL STD { int linux_sync_file_range(void); } 278 AUE_NULL STD { int linux_vmsplice(void); } 279 AUE_NULL STD { int linux_move_pages(void); } -280 AUE_NULL STD { int linux_utimensat(void); } +280 AUE_FUTIMESAT STD { int linux_utimensat(l_int dfd, const char *pathname, \ + const struct l_timespec *times, l_int flags); } 281 AUE_NULL STD { int linux_epoll_pwait(l_int epfd, struct epoll_event *events, \ l_int maxevents, l_int timeout, l_sigset_t *mask); } 282 AUE_NULL STD { int linux_signalfd(void); } Modified: head/sys/amd64/linux32/linux32_dummy.c ============================================================================== --- head/sys/amd64/linux32/linux32_dummy.c Sun May 24 17:56:02 2015 (r283479) +++ head/sys/amd64/linux32/linux32_dummy.c Sun May 24 17:57:07 2015 (r283480) @@ -104,7 +104,6 @@ DUMMY(move_pages); DUMMY(getcpu); DUMMY(epoll_pwait); /* linux 2.6.22: */ -DUMMY(utimensat); DUMMY(signalfd); DUMMY(timerfd_create); /* linux 2.6.25: */ Modified: head/sys/amd64/linux32/syscalls.master ============================================================================== --- head/sys/amd64/linux32/syscalls.master Sun May 24 17:56:02 2015 (r283479) +++ head/sys/amd64/linux32/syscalls.master Sun May 24 17:57:07 2015 (r283480) @@ -533,7 +533,8 @@ 319 AUE_NULL STD { int linux_epoll_pwait(l_int epfd, struct epoll_event *events, \ l_int maxevents, l_int timeout, l_osigset_t *mask); } ; linux 2.6.22: -320 AUE_NULL STD { int linux_utimensat(void); } +320 AUE_FUTIMESAT STD { int linux_utimensat(l_int dfd, const char *pathname, \ + const struct l_timespec *times, l_int flags); } 321 AUE_NULL STD { int linux_signalfd(void); } 322 AUE_NULL STD { int linux_timerfd_create(void); } 323 AUE_NULL STD { int linux_eventfd(l_uint initval); } Modified: head/sys/compat/linux/linux_misc.c ============================================================================== --- head/sys/compat/linux/linux_misc.c Sun May 24 17:56:02 2015 (r283479) +++ head/sys/compat/linux/linux_misc.c Sun May 24 17:57:07 2015 (r283480) @@ -824,6 +824,87 @@ linux_utimes(struct thread *td, struct l return (error); } +int +linux_utimensat(struct thread *td, struct linux_utimensat_args *args) +{ + 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; + +#ifdef DEBUG + if (ldebug(utimensat)) + printf(ARGS(utimensat, "%d, *"), dfd); +#endif + + if (args->flags & ~LINUX_AT_SYMLINK_NOFOLLOW) + return (EINVAL); + + if (args->times != NULL) { + error = copyin(args->times, l_times, sizeof(l_times)); + if (error != 0) + return (error); + + if (l_times[0].tv_nsec > 999999999 || + l_times[1].tv_nsec > 999999999) + 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 (times[0].tv_nsec == UTIME_OMIT && times[1].tv_nsec == UTIME_OMIT) + /* 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. */ + return (0); + + if (args->pathname != NULL) + LCONVPATHEXIST_AT(td, args->pathname, &path, dfd); + else if (args->flags != 0) + return (EINVAL); + + if (args->flags & LINUX_AT_SYMLINK_NOFOLLOW) + flags |= AT_SYMLINK_NOFOLLOW; + + if (path == NULL) + error = kern_futimens(td, dfd, timesp, UIO_SYSSPACE); + else { + error = kern_utimensat(td, dfd, path, UIO_SYSSPACE, timesp, + UIO_SYSSPACE, flags); + LFREEPATH(path); + } + + return (error); +} + int linux_futimesat(struct thread *td, struct linux_futimesat_args *args) { Modified: head/sys/compat/linux/linux_misc.h ============================================================================== --- head/sys/compat/linux/linux_misc.h Sun May 24 17:56:02 2015 (r283479) +++ head/sys/compat/linux/linux_misc.h Sun May 24 17:57:07 2015 (r283480) @@ -121,6 +121,9 @@ struct l_new_utsname { #define LINUX_CLOCK_REALTIME_HR 4 #define LINUX_CLOCK_MONOTONIC_HR 5 +#define LINUX_UTIME_NOW 0x3FFFFFFF +#define LINUX_UTIME_OMIT 0x3FFFFFFE + extern int stclohz; #define LINUX_WNOHANG 0x00000001 Modified: head/sys/i386/linux/linux_dummy.c ============================================================================== --- head/sys/i386/linux/linux_dummy.c Sun May 24 17:56:02 2015 (r283479) +++ head/sys/i386/linux/linux_dummy.c Sun May 24 17:57:07 2015 (r283480) @@ -100,7 +100,6 @@ DUMMY(move_pages); DUMMY(getcpu); DUMMY(epoll_pwait); /* linux 2.6.22: */ -DUMMY(utimensat); DUMMY(signalfd); DUMMY(timerfd_create); /* linux 2.6.25: */ Modified: head/sys/i386/linux/syscalls.master ============================================================================== --- head/sys/i386/linux/syscalls.master Sun May 24 17:56:02 2015 (r283479) +++ head/sys/i386/linux/syscalls.master Sun May 24 17:57:07 2015 (r283480) @@ -541,7 +541,8 @@ 319 AUE_NULL STD { int linux_epoll_pwait(l_int epfd, struct epoll_event *events, \ l_int maxevents, l_int timeout, l_osigset_t *mask); } ; linux 2.6.22: -320 AUE_NULL STD { int linux_utimensat(void); } +320 AUE_FUTIMESAT STD { int linux_utimensat(l_int dfd, const char *pathname, \ + const struct l_timespec *times, l_int flags); } 321 AUE_NULL STD { int linux_signalfd(void); } 322 AUE_NULL STD { int linux_timerfd_create(void); } 323 AUE_NULL STD { int linux_eventfd(l_uint initval); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201505241757.t4OHv8Iv035816>