diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index c7fac128..13e88906 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -46,3 +46,4 @@ luna_app(socket-test.cpp socket-test) luna_app(socket-client.cpp socket-client) luna_app(input.cpp input) luna_app(shmem-test.cpp shmem-test) +luna_app(touch.cpp touch) diff --git a/apps/touch.cpp b/apps/touch.cpp new file mode 100644 index 00000000..334499d2 --- /dev/null +++ b/apps/touch.cpp @@ -0,0 +1,47 @@ +#include +#include +#include +#include + +Result luna_main(int argc, char** argv) +{ + Vector files; + + bool only_atime { false }; + bool only_mtime { false }; + bool no_create { false }; + bool no_dereference { false }; + + os::ArgumentParser parser; + parser.add_description("Update the access and modification times of files."_sv); + parser.add_system_program_info("touch"_sv); + parser.set_vector_argument(files, "files", true); + parser.add_switch_argument(only_atime, 'a', ""_sv, "change only the access time"_sv); + parser.add_switch_argument(no_create, 'c', "no-create"_sv, "do not create new files"_sv); + parser.add_switch_argument(no_dereference, 'h', "no-dereference"_sv, "do not follow symbolic links"_sv); + parser.add_switch_argument(only_mtime, 'm', ""_sv, "change only the modification time"_sv); + TRY(parser.parse(argc, argv)); + + if (only_atime && only_mtime) + { + os::eprintln("%s: only one of -a and -m can be specified.", argv[0]); + parser.short_usage(argv[0]); + } + + struct timespec times[2] = { + { .tv_sec = 0, .tv_nsec = only_mtime ? UTIME_OMIT : UTIME_NOW }, + { .tv_sec = 0, .tv_nsec = only_atime ? UTIME_OMIT : UTIME_NOW }, + }; + + for (auto& filename : files) + { + SharedPtr file; + if (no_create) file = TRY(os::File::open(filename, os::File::ReadOnly)); + else + file = TRY(os::File::open_or_create(filename, os::File::ReadOnly)); + + if (futimens(file->fd(), times, no_dereference ? AT_SYMLINK_NOFOLLOW : 0) < 0) return err(errno); + } + + return 0; +} diff --git a/kernel/src/sys/file.cpp b/kernel/src/sys/file.cpp index a1e511b3..a49b70d7 100644 --- a/kernel/src/sys/file.cpp +++ b/kernel/src/sys/file.cpp @@ -300,14 +300,20 @@ Result sys_utimensat(Registers*, SyscallArgs args) if (ktimes[0].tv_nsec != UTIME_OMIT) { if (ktimes[0].tv_nsec == UTIME_NOW) metadata.atime = *Timer::realtime_clock(); - if (ktimes[0].tv_nsec < 0 || ktimes[0].tv_nsec > 999'999'999) return err(EINVAL); - metadata.atime = ktimes[0]; + else + { + if (ktimes[0].tv_nsec < 0 || ktimes[0].tv_nsec > 999'999'999) return err(EINVAL); + metadata.atime = ktimes[0]; + } } if (ktimes[1].tv_nsec != UTIME_OMIT) { if (ktimes[1].tv_nsec == UTIME_NOW) metadata.mtime = *Timer::realtime_clock(); - if (ktimes[1].tv_nsec < 0 || ktimes[1].tv_nsec > 999'999'999) return err(EINVAL); - metadata.mtime = ktimes[1]; + else + { + if (ktimes[1].tv_nsec < 0 || ktimes[1].tv_nsec > 999'999'999) return err(EINVAL); + metadata.mtime = ktimes[1]; + } } TRY(inode->set_metadata(metadata));