#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; }