summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2023-05-17 18:54:40 +0300
committerSergey Poznyakoff <gray@gnu.org>2023-05-17 18:54:40 +0300
commit83069df4633d21fc176aec2f4c9d9ba027514dcf (patch)
tree83286a252a59e48957f253c37f467fc5b6f13e92
parent8d51e798761485e9f8291539a1401ecbc40b3956 (diff)
downloadpaxutils-master.tar.gz
genfile: implement the --set-time optionHEADmaster
* doc/genfile.texi: Document changes. * tests/genfile.c: New options: --set-time and --no-dereference.
-rw-r--r--doc/genfile.texi49
-rw-r--r--tests/genfile.c45
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);