Skip site navigation (1)Skip section navigation (2)
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>