From 83069df4633d21fc176aec2f4c9d9ba027514dcf Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Wed, 17 May 2023 18:54:40 +0300 Subject: genfile: implement the --set-time option * doc/genfile.texi: Document changes. * tests/genfile.c: New options: --set-time and --no-dereference. --- doc/genfile.texi | 49 +++++++++++++++++++++++++++++++++++++++++++++---- tests/genfile.c | 45 ++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 87 insertions(+), 7 deletions(-) diff --git a/doc/genfile.texi b/doc/genfile.texi index 17c97d2..1c3de81 100644 --- a/doc/genfile.texi +++ b/doc/genfile.texi @@ -14,7 +14,7 @@ the testsuite, hence its name. However, new operation modes were being implemented as the testsuite grew more sophisticated, and now @command{genfile} is a multi-purpose instrument. - There are three basic operation modes: + There are four basic operation modes: @table @asis @item File Generation @@ -24,6 +24,10 @@ generates data files. @item File Status In this mode @command{genfile} displays status of specified files. +@item Set File Time + Set last access and modification times of files given in the +command line. + @item Synchronous Execution. In this mode @command{genfile} executes the given program with @option{--checkpoint} option and executes a set of actions when @@ -31,9 +35,10 @@ specified checkpoints are reached. @end table @menu -* Generate Mode:: File Generation Mode. -* Status Mode:: File Status Mode. -* Exec Mode:: Synchronous Execution mode. +* Generate Mode:: File Generation Mode. +* Status Mode:: File Status Mode. +* Set File Time:: Set File Time Mode. +* Exec Mode:: Synchronous Execution Mode. @end menu @node Generate Mode @@ -278,6 +283,34 @@ directory: genfile --stat=name,atime * @end smallexample + By default, @command{genfile} follows symbolic links and returns +information about files pointed to by them. To get information about +the symlink files themselves, use the @option{--no-dereference} +(@option{-h}) option. + +@node Set File Time +@appendixsec Set File Time +@cindex Set File Time Mode, @command{genfile} + This mode is requested by the @option{--set-time} (@option{-t}) +command line option. In this mode @command{genfile} operates +similarly to the @command{touch} command: for each file listed in the +command line, it sets its access and modification times to the current +timestamp or to the value given with the @option{--date} option. The +@option{--date} option takes a date specification in +an almost arbitrary format as its argument (@pxref{Date input +formats}), e.g.: + +@example +genfile --set-time --date='2 days ago' a b c +@end example + + By default, @command{genfile} follows symbolic links and sets +times of the file they point to. This can be changed by supplying the +@option{--no-dereference} (@option{-h}) option: if it is given, +@command{genfile} will change access and modification times of the +symbolic link itself. Notice, that not all operating systems allow +this. + @node Exec Mode @appendixsec Exec Mode @@ -346,6 +379,14 @@ option was given, in which case they are changed to the specified time. Argument to @option{--date} option is a date specification in an almost arbitrary format (@pxref{Date input formats}). +@item -h +@itemx --no-dereference + Modifies the action of the @option{--touch} option. If both +options are given and @var{file} argument to the @option{--touch} +names a symbolic link, @command{genfile} will modify access and +modification times of the symbolic link file itself, instead the +file the symlink points to. + @item --exec @var{command} Execute given shell command. diff --git a/tests/genfile.c b/tests/genfile.c index be4a2d3..0074c5c 100644 --- a/tests/genfile.c +++ b/tests/genfile.c @@ -77,7 +77,8 @@ enum genfile_mode mode_generate, mode_sparse, mode_stat, - mode_exec + mode_exec, + mode_set_times }; enum genfile_mode mode = mode_generate; @@ -106,6 +107,9 @@ int verbose; /* Quiet mode */ int quiet; +/* Don't dereference symlinks (for --stat) */ +int no_dereference_option; + const char *argp_program_version = "genfile (" PACKAGE ") " VERSION; const char *argp_program_bug_address = "<" PACKAGE_BUGREPORT ">"; static char doc[] = N_("genfile manipulates data files for GNU paxutils test suite.\n" @@ -155,6 +159,14 @@ static struct argp_option options[] = { N_("Print contents of struct stat for each given file. Default FORMAT is: ") DEFAULT_STAT_FORMAT, GRP+1 }, + {"no-dereference", 'h', NULL, 0, + N_("stat symbolic links instead of referenced files"), + GRP+1 }, + + {"set-times", 't', NULL, 0, + N_("Set access and modification times of the files to the time supplied" + " by --date option"), + GRP+1 }, #undef GRP #define GRP 20 @@ -348,6 +360,14 @@ parse_opt (int key, char *arg, struct argp_state *state) stat_format = arg; break; + case 't': + mode = mode_set_times; + break; + + case 'h': + no_dereference_option = 1; + break; + case 'r': mode = mode_exec; checkpoint_granularity = arg ? arg : "1"; @@ -647,7 +667,7 @@ print_stat (const char *name) char *fmt, *p; struct stat st; - if (stat (name, &st)) + if ((no_dereference_option ? lstat : stat) (name, &st)) { error (0, errno, _("stat(%s) failed"), name); return; @@ -725,6 +745,17 @@ print_stat (const char *name) free (fmt); } +void +set_times (char const *name) +{ + struct timespec ts[2]; + + ts[0] = ts[1] = touch_time; + if (utimensat (AT_FDCWD, name, ts, no_dereference_option ? AT_SYMLINK_NOFOLLOW : 0) != 0) + { + error (EXIT_FAILURE, errno, _("cannot set time on `%s'"), name); + } +} /* Exec Mode */ @@ -740,7 +771,7 @@ exec_checkpoint (struct action *p) struct timespec ts[2]; ts[0] = ts[1] = p->ts; - if (utimensat (AT_FDCWD, p->name, ts, 0) != 0) + if (utimensat (AT_FDCWD, p->name, ts, no_dereference_option ? AT_SYMLINK_NOFOLLOW : 0) != 0) { error (0, errno, _("cannot set time on `%s'"), p->name); break; @@ -987,6 +1018,14 @@ main (int argc, char **argv) print_stat (*argv++); break; + case mode_set_times: + if (argc == 0) + error (EXIT_USAGE, 0, _("--set-times requires file names")); + + while (argc--) + set_times (*argv++); + break; + case mode_sparse: generate_sparse_file (argc, argv); verify_file (file_name); -- cgit v1.2.1