Add utimensat() system call.
The patch developed by Jilles Tjoelker and Andrew Wilcox and adopted for lemul branch by me.
This commit is contained in:
parent
0c38abc250
commit
19d8b461f4
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=283480
@ -98,7 +98,6 @@ DUMMY(tee);
|
||||
DUMMY(sync_file_range);
|
||||
DUMMY(vmsplice);
|
||||
DUMMY(move_pages);
|
||||
DUMMY(utimensat);
|
||||
DUMMY(epoll_pwait);
|
||||
DUMMY(signalfd);
|
||||
DUMMY(timerfd);
|
||||
|
@ -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); }
|
||||
|
@ -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: */
|
||||
|
@ -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); }
|
||||
|
@ -824,6 +824,87 @@ linux_utimes(struct thread *td, struct linux_utimes_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 = 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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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: */
|
||||
|
@ -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); }
|
||||
|
Loading…
Reference in New Issue
Block a user