From ede0571926d369541ff1b64a7a7c8ef72efd087a Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Wed, 24 Feb 2016 16:29:37 +0100 Subject: [PATCH] Add UTIME_NOW and UTIME_OMIT. --- ext/fsmarshall.cpp | 21 ++++++++++++---- kernel/descriptor.cpp | 29 ++++++++++++++++++----- kernel/fs/user.cpp | 15 ++++-------- kernel/include/sortix/kernel/descriptor.h | 5 ++-- kernel/include/sortix/kernel/inode.h | 10 +++----- kernel/include/sortix/kernel/vnode.h | 5 ++-- kernel/include/sortix/stat.h | 5 +++- kernel/initrd.cpp | 9 +++---- kernel/inode.cpp | 23 ++++++++++-------- kernel/io.cpp | 10 ++------ kernel/vnode.cpp | 8 +++---- 11 files changed, 78 insertions(+), 62 deletions(-) diff --git a/ext/fsmarshall.cpp b/ext/fsmarshall.cpp index 04f2c0f7..415823c9 100644 --- a/ext/fsmarshall.cpp +++ b/ext/fsmarshall.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2013, 2014, 2015. + Copyright(C) Jonas 'Sortie' Termansen 2013, 2014, 2015, 2016. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free @@ -243,10 +243,21 @@ void HandleUTimens(int chl, struct fsm_req_utimens* msg, Filesystem* fs) if ( !fs->device->write ) { RespondError(chl, EROFS); return; } Inode* inode = SafeGetInode(fs, msg->ino); if ( !inode ) { RespondError(chl, errno); return; } - inode->BeginWrite(); - inode->data->i_atime = msg->times[0].tv_sec; - inode->data->i_mtime = msg->times[1].tv_sec; - inode->FinishWrite(); + if ( msg->times[0].tv_nsec != UTIME_OMIT || + msg->times[1].tv_nsec != UTIME_OMIT ) + { + time_t now = time(NULL); + inode->BeginWrite(); + if ( msg->times[0].tv_nsec == UTIME_NOW ) + inode->data->i_atime = now; + else if ( msg->times[0].tv_nsec != UTIME_OMIT ) + inode->data->i_atime = msg->times[0].tv_sec; + if ( msg->times[1].tv_nsec == UTIME_NOW ) + inode->data->i_mtime = now; + else if ( msg->times[1].tv_nsec != UTIME_OMIT ) + inode->data->i_mtime = msg->times[1].tv_sec; + inode->FinishWrite(); + } inode->Unref(); RespondSuccess(chl); } diff --git a/kernel/descriptor.cpp b/kernel/descriptor.cpp index 3493c458..4eafd74b 100644 --- a/kernel/descriptor.cpp +++ b/kernel/descriptor.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014, 2015. + Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014, 2015, 2016. This file is part of Sortix. @@ -337,12 +337,29 @@ ssize_t Descriptor::pwrite(ioctx_t* ctx, const uint8_t* buf, size_t count, off_t return vnode->pwrite(ctx, buf, count, off); } -int Descriptor::utimens(ioctx_t* ctx, - const struct timespec* atime, - const struct timespec* ctime, - const struct timespec* mtime) +static inline bool valid_utimens_timespec(struct timespec ts) { - return vnode->utimens(ctx, atime, ctime, mtime); + return ts.tv_nsec < 1000000000 || + ts.tv_nsec == UTIME_NOW || + ts.tv_nsec == UTIME_OMIT; +} + +int Descriptor::utimens(ioctx_t* ctx, const struct timespec* user_times) +{ + struct timespec times[2]; + if ( !user_times ) + { + times[0].tv_sec = 0; + times[0].tv_nsec = UTIME_NOW; + times[1].tv_sec = 0; + times[1].tv_nsec = UTIME_NOW; + } + else if ( !ctx->copy_from_src(×, user_times, sizeof(times)) ) + return -1; + if ( !valid_utimens_timespec(times[0]) || + !valid_utimens_timespec(times[1]) ) + return errno = EINVAL; + return vnode->utimens(ctx, times); } int Descriptor::isatty(ioctx_t* ctx) diff --git a/kernel/fs/user.cpp b/kernel/fs/user.cpp index 0eb2a544..b6c9cda1 100644 --- a/kernel/fs/user.cpp +++ b/kernel/fs/user.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014, 2015. + Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014, 2015, 2016. This file is part of Sortix. @@ -213,9 +213,7 @@ public: virtual ssize_t write(ioctx_t* ctx, const uint8_t* buf, size_t count); virtual ssize_t pwrite(ioctx_t* ctx, const uint8_t* buf, size_t count, off_t off); - virtual int utimens(ioctx_t* ctx, const struct timespec* atime, - const struct timespec* ctime, - const struct timespec* mtime); + virtual int utimens(ioctx_t* ctx, const struct timespec* times); virtual int isatty(ioctx_t* ctx); virtual ssize_t readdirents(ioctx_t* ctx, struct dirent* dirent, size_t size, off_t start); @@ -974,10 +972,7 @@ ssize_t Unode::pwrite(ioctx_t* ctx, const uint8_t* buf, size_t count, off_t off) return ret; } -int Unode::utimens(ioctx_t* ctx, - const struct timespec* atime, - const struct timespec* /*ctime*/, - const struct timespec* mtime) +int Unode::utimens(ioctx_t* ctx, const struct timespec* times) { Channel* channel = server->Connect(ctx); if ( !channel ) @@ -985,8 +980,8 @@ int Unode::utimens(ioctx_t* ctx, int ret = -1; struct fsm_req_utimens msg; msg.ino = ino; - msg.times[0] = atime ? *atime : timespec_nul(); - msg.times[1] = mtime ? *mtime : timespec_nul(); + msg.times[0] = times[0]; + msg.times[1] = times[1]; if ( SendMessage(channel, FSM_REQ_UTIMENS, &msg, sizeof(msg)) && RecvMessage(channel, FSM_RESP_SUCCESS, NULL, 0) ) ret = 0; diff --git a/kernel/include/sortix/kernel/descriptor.h b/kernel/include/sortix/kernel/descriptor.h index 7a674105..606cc030 100644 --- a/kernel/include/sortix/kernel/descriptor.h +++ b/kernel/include/sortix/kernel/descriptor.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014, 2015. + Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014, 2015, 2016. This file is part of Sortix. @@ -72,8 +72,7 @@ public: ssize_t pread(ioctx_t* ctx, uint8_t* buf, size_t count, off_t off); ssize_t write(ioctx_t* ctx, const uint8_t* buf, size_t count); ssize_t pwrite(ioctx_t* ctx, const uint8_t* buf, size_t count, off_t off); - int utimens(ioctx_t* ctx, const struct timespec* atime, - const struct timespec* ctime, const struct timespec* mtime); + int utimens(ioctx_t* ctx, const struct timespec* times); int isatty(ioctx_t* ctx); ssize_t readdirents(ioctx_t* ctx, struct dirent* dirent, size_t size); Ref open(ioctx_t* ctx, const char* filename, int flags, diff --git a/kernel/include/sortix/kernel/inode.h b/kernel/include/sortix/kernel/inode.h index c0922a7c..96df0baf 100644 --- a/kernel/include/sortix/kernel/inode.h +++ b/kernel/include/sortix/kernel/inode.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014, 2015. + Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014, 2015, 2016. This file is part of Sortix. @@ -72,9 +72,7 @@ public: virtual ssize_t write(ioctx_t* ctx, const uint8_t* buf, size_t count) = 0; virtual ssize_t pwrite(ioctx_t* ctx, const uint8_t* buf, size_t count, off_t off) = 0; - virtual int utimens(ioctx_t* ctx, const struct timespec* atime, - const struct timespec* ctime, - const struct timespec* mtime) = 0; + virtual int utimens(ioctx_t* ctx, const struct timespec* times) = 0; virtual int isatty(ioctx_t* ctx) = 0; virtual ssize_t readdirents(ioctx_t* ctx, struct dirent* dirent, size_t size, off_t start) = 0; @@ -167,9 +165,7 @@ public: virtual ssize_t write(ioctx_t* ctx, const uint8_t* buf, size_t count); virtual ssize_t pwrite(ioctx_t* ctx, const uint8_t* buf, size_t count, off_t off); - virtual int utimens(ioctx_t* ctx, const struct timespec* atime, - const struct timespec* ctime, - const struct timespec* mtime); + virtual int utimens(ioctx_t* ctx, const struct timespec* times); virtual int isatty(ioctx_t* ctx); virtual ssize_t readdirents(ioctx_t* ctx, struct dirent* dirent, size_t size, off_t start); diff --git a/kernel/include/sortix/kernel/vnode.h b/kernel/include/sortix/kernel/vnode.h index 8770e693..5c5aea52 100644 --- a/kernel/include/sortix/kernel/vnode.h +++ b/kernel/include/sortix/kernel/vnode.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014, 2015. + Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014, 2015, 2016. This file is part of Sortix. @@ -69,8 +69,7 @@ public: ssize_t pread(ioctx_t* ctx, uint8_t* buf, size_t count, off_t off); ssize_t write(ioctx_t* ctx, const uint8_t* buf, size_t count); ssize_t pwrite(ioctx_t* ctx, const uint8_t* buf, size_t count, off_t off); - int utimens(ioctx_t* ctx, const struct timespec* atime, - const struct timespec* ctime, const struct timespec* mtime); + int utimens(ioctx_t* ctx, const struct timespec* times); int isatty(ioctx_t* ctx); ssize_t readdirents(ioctx_t* ctx, struct dirent* dirent, size_t size, off_t start); diff --git a/kernel/include/sortix/stat.h b/kernel/include/sortix/stat.h index 8df20c3d..47bb812b 100644 --- a/kernel/include/sortix/stat.h +++ b/kernel/include/sortix/stat.h @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014, 2015. + Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014, 2015, 2016. This file is part of Sortix. @@ -89,6 +89,9 @@ struct stat #define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) +#define UTIME_NOW 0x3FFFFFFF +#define UTIME_OMIT 0x3FFFFFFE + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/kernel/initrd.cpp b/kernel/initrd.cpp index 5901094b..12d42826 100644 --- a/kernel/initrd.cpp +++ b/kernel/initrd.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014, 2015. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014, 2015, 2016. This file is part of Sortix. @@ -293,9 +293,10 @@ static void ExtractNode(struct initrd_context* ctx, ExtractDir(ctx, inode, node); if ( INITRD_S_ISREG(inode->mode) ) ExtractFile(ctx, inode, node); - struct timespec ctime = timespec_make((time_t) inode->ctime, 0); - struct timespec mtime = timespec_make((time_t) inode->mtime, 0); - if ( node->utimens(&ctx->ioctx, &mtime, &ctime, &mtime) < 0 ) + struct timespec times[2]; + times[0] = timespec_make((time_t) inode->mtime, 0); + times[1] = timespec_make((time_t) inode->mtime, 0); + if ( node->utimens(&ctx->ioctx, times) < 0 ) PanicF("initrd: utimens: %m"); } diff --git a/kernel/inode.cpp b/kernel/inode.cpp index 885e5073..edc2070f 100644 --- a/kernel/inode.cpp +++ b/kernel/inode.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014, 2015. + Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014, 2015, 2016. This file is part of Sortix. @@ -180,17 +180,20 @@ ssize_t AbstractInode::pwrite(ioctx_t* /*ctx*/, const uint8_t* /*buf*/, return errno = EBADF, -1; } -int AbstractInode::utimens(ioctx_t* /*ctx*/, const struct timespec* atime, - const struct timespec* ctime, - const struct timespec* mtime) +int AbstractInode::utimens(ioctx_t* /*ctx*/, const struct timespec* times) { ScopedLock lock(&metalock); - if ( atime ) - stat_atim = *atime; - if ( ctime ) - stat_ctim = *ctime; - if ( mtime ) - stat_mtim = *mtime; + struct timespec now = { 0, 0 }; + if ( times[0].tv_nsec == UTIME_NOW || times[1].tv_nsec == UTIME_NOW ) + now = Time::Get(CLOCK_REALTIME); + if ( times[0].tv_nsec == UTIME_NOW ) + stat_atim = now; + else if ( times[0].tv_nsec != UTIME_OMIT ) + stat_atim = times[0]; + if ( times[1].tv_nsec == UTIME_NOW ) + stat_mtim = now; + else if ( times[1].tv_nsec != UTIME_OMIT ) + stat_mtim = times[1]; return 0; } diff --git a/kernel/io.cpp b/kernel/io.cpp index 68bf809b..6996e693 100644 --- a/kernel/io.cpp +++ b/kernel/io.cpp @@ -507,14 +507,11 @@ int sys_fchmodat(int dirfd, const char* path, mode_t mode, int flags) int sys_futimens(int fd, const struct timespec* user_times) { - struct timespec times[2]; - if ( !CopyFromUser(times, user_times, sizeof(times)) ) - return -1; Ref desc = CurrentProcess()->GetDescriptor(fd); if ( !desc ) return -1; ioctx_t ctx; SetupUserIOCtx(&ctx); - return desc->utimens(&ctx, ×[0], NULL, ×[1]); + return desc->utimens(&ctx, user_times); } int sys_utimensat(int dirfd, const char* path, @@ -522,9 +519,6 @@ int sys_utimensat(int dirfd, const char* path, { if ( flags & ~(AT_SYMLINK_NOFOLLOW) ) return errno = EINVAL, -1; - struct timespec times[2]; - if ( !CopyFromUser(times, user_times, sizeof(times)) ) - return -1; char* pathcopy = GetStringFromUser(path); if ( !pathcopy ) return -1; @@ -537,7 +531,7 @@ int sys_utimensat(int dirfd, const char* path, delete[] pathcopy; if ( !desc ) return -1; - return desc->utimens(&ctx, ×[0], NULL, ×[1]); + return desc->utimens(&ctx, user_times); } int sys_linkat(int olddirfd, const char* oldpath, diff --git a/kernel/vnode.cpp b/kernel/vnode.cpp index 2eea3b3a..d21b4934 100644 --- a/kernel/vnode.cpp +++ b/kernel/vnode.cpp @@ -1,6 +1,6 @@ /******************************************************************************* - Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014, 2015. + Copyright(C) Jonas 'Sortie' Termansen 2012, 2013, 2014, 2015, 2016. This file is part of Sortix. @@ -269,11 +269,9 @@ ssize_t Vnode::pwrite(ioctx_t* ctx, const uint8_t* buf, size_t count, off_t off) return inode->pwrite(ctx, buf, count, off); } -int Vnode::utimens(ioctx_t* ctx, const struct timespec* atime, - const struct timespec* ctime, - const struct timespec* mtime) +int Vnode::utimens(ioctx_t* ctx, const struct timespec* times) { - return inode->utimens(ctx, atime, ctime, mtime); + return inode->utimens(ctx, times); } int Vnode::isatty(ioctx_t* ctx)