From owner-svn-src-stable-10@freebsd.org Sat Jan 9 17:41:02 2016 Return-Path: Delivered-To: svn-src-stable-10@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 496C7A69B40; Sat, 9 Jan 2016 17:41:02 +0000 (UTC) (envelope-from dchagin@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 0CE1718B1; Sat, 9 Jan 2016 17:41:01 +0000 (UTC) (envelope-from dchagin@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u09Hf13G062134; Sat, 9 Jan 2016 17:41:01 GMT (envelope-from dchagin@FreeBSD.org) Received: (from dchagin@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u09Hf0l2062126; Sat, 9 Jan 2016 17:41:00 GMT (envelope-from dchagin@FreeBSD.org) Message-Id: <201601091741.u09Hf0l2062126@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: dchagin set sender to dchagin@FreeBSD.org using -f From: Dmitry Chagin Date: Sat, 9 Jan 2016 17:41:00 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r293582 - in stable/10/sys: amd64/linux amd64/linux32 compat/linux i386/linux X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-10@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 09 Jan 2016 17:41:02 -0000 Author: dchagin Date: Sat Jan 9 17:41:00 2016 New Revision: 293582 URL: https://svnweb.freebsd.org/changeset/base/293582 Log: MFC r283480: Add utimensat() system call. Modified: stable/10/sys/amd64/linux/linux_dummy.c stable/10/sys/amd64/linux/syscalls.master stable/10/sys/amd64/linux32/linux32_dummy.c stable/10/sys/amd64/linux32/syscalls.master stable/10/sys/compat/linux/linux_misc.c stable/10/sys/compat/linux/linux_misc.h stable/10/sys/i386/linux/linux_dummy.c stable/10/sys/i386/linux/syscalls.master Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/amd64/linux/linux_dummy.c ============================================================================== --- stable/10/sys/amd64/linux/linux_dummy.c Sat Jan 9 17:39:41 2016 (r293581) +++ stable/10/sys/amd64/linux/linux_dummy.c Sat Jan 9 17:41:00 2016 (r293582) @@ -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: stable/10/sys/amd64/linux/syscalls.master ============================================================================== --- stable/10/sys/amd64/linux/syscalls.master Sat Jan 9 17:39:41 2016 (r293581) +++ stable/10/sys/amd64/linux/syscalls.master Sat Jan 9 17:41:00 2016 (r293582) @@ -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: stable/10/sys/amd64/linux32/linux32_dummy.c ============================================================================== --- stable/10/sys/amd64/linux32/linux32_dummy.c Sat Jan 9 17:39:41 2016 (r293581) +++ stable/10/sys/amd64/linux32/linux32_dummy.c Sat Jan 9 17:41:00 2016 (r293582) @@ -105,7 +105,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: stable/10/sys/amd64/linux32/syscalls.master ============================================================================== --- stable/10/sys/amd64/linux32/syscalls.master Sat Jan 9 17:39:41 2016 (r293581) +++ stable/10/sys/amd64/linux32/syscalls.master Sat Jan 9 17:41:00 2016 (r293582) @@ -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: stable/10/sys/compat/linux/linux_misc.c ============================================================================== --- stable/10/sys/compat/linux/linux_misc.c Sat Jan 9 17:39:41 2016 (r293581) +++ stable/10/sys/compat/linux/linux_misc.c Sat Jan 9 17:41:00 2016 (r293582) @@ -823,6 +823,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: stable/10/sys/compat/linux/linux_misc.h ============================================================================== --- stable/10/sys/compat/linux/linux_misc.h Sat Jan 9 17:39:41 2016 (r293581) +++ stable/10/sys/compat/linux/linux_misc.h Sat Jan 9 17:41:00 2016 (r293582) @@ -119,6 +119,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: stable/10/sys/i386/linux/linux_dummy.c ============================================================================== --- stable/10/sys/i386/linux/linux_dummy.c Sat Jan 9 17:39:41 2016 (r293581) +++ stable/10/sys/i386/linux/linux_dummy.c Sat Jan 9 17:41:00 2016 (r293582) @@ -101,7 +101,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: stable/10/sys/i386/linux/syscalls.master ============================================================================== --- stable/10/sys/i386/linux/syscalls.master Sat Jan 9 17:39:41 2016 (r293581) +++ stable/10/sys/i386/linux/syscalls.master Sat Jan 9 17:41:00 2016 (r293582) @@ -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); }