xfs_io: implement 'utimes' command
PATCH 1/1 xfs_io: implement 'utimes' command
Add the utimes command to provide a way to utilize the futimens C library call. This is the interface to the utimensat system call, which updates the mtime and atime of a file.
--- include/input.h | 1 + io/Makefile | 2 +- io/init.c | 1 + io/io.h | 1 + io/utimes.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ libxcmd/input.c | 22 +++++++++++++++ man/man8/xfs_io.8 | 12 ++++++++ 7 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 io/utimes.c
include/input.h +1 -0
@@ -48,6 +48,7 @@ extern uid_t uid_from_string(char *user);extern gid_t gid_from_string (char *group);extern prid_t prid_from_string (char *project);extern bool isdigits_only (const char *str); +extern int timespec_from_string (const char *sec,const char *nsec,struct timespec *ts);#define HAVE_FTW_H 1/* TODO: configure me */
io/Makefile +1 -1
@@ -11,7 +11,7 @@ HFILES = init.h io.h CFILES = init.c \ attr.c bmap.c file.c freeze.c fsync.c getrusage.c imap.c link.c \ mmap.c open.c parent.c pread.c prealloc.c pwrite.c seek.c shutdown.c \ - sync.c truncate.c reflink.c + sync.c truncate.c reflink.c utimes.c LLDLIBS = $(LIBXCMD) $(LIBHANDLE) LTDEPENDENCIES = $(LIBXCMD) $(LIBHANDLE)
io/init.c +1 -0
@@ -85,6 +85,7 @@ init_commands(void)sync_range_init ();truncate_init ();reflink_init (); +utimes_init (); } static int
io/io.h +1 -0
@@ -113,6 +113,7 @@ extern void seek_init(void);extern void shutdown_init (void );extern void sync_init (void );extern void truncate_init (void ); +extern void utimes_init (void );#ifdef HAVE_FADVISE extern void fadvise_init (void );
io/utimes.c new file +84 -0
84 lines not on this page · raw message
libxcmd/input.c +22 -0
@@ -327,6 +327,28 @@ timestr( }/* +* Convert from a pair of arbitrary user strings into a timespec. +*/ + +int +timespec_from_string ( +const char * secs, +const char * nsecs, +struct timespec * ts) +{ +char * p; +if (!secs || !nsecs || !ts) +return -1 ; + ts->tv_sec =strtoull (secs, &p,0 ); +if (*p) +return -1 ; + ts->tv_nsec =strtoull (nsecs, &p,0 ); +if (*p) +return -1 ; +return 0 ; +} + +/* * Convert from arbitrary user strings into a numeric ID. * If it's all numeric, we convert that inplace, else we do * the name lookup, and return the found identifier.
man/man8/xfs_io.8 +12 -0
@@ -589,6 +589,17 @@ Copy data into the open file beginning at Copy up to .I length bytes of data. +.RE +.PD +.TP +.TP +.BI utimes " atime_sec atime_nsec mtime_sec mtime_nsec" +The utimes command changes the atime and mtime of the current file. +sec uses UNIX timestamp notation and is the seconds elapsed since +1970-01-01 00:00:00 UTC. +nsec is the nanoseconds since the sec. This value needs to be in +the range 0-999999999 with UTIME_NOW and UTIME_OMIT being exceptions. +Each (sec, nsec) pair constitutes a single timestamp value. .SH MEMORY MAPPED I/O COMMANDS .TP
@@ -875,6 +886,7 @@ verbose output will be printed. .BR fstatfs (2), .BR fsync (2), .BR ftruncate (2), +.BR futimens (3), .BR mmap (2), .BR msync (2), .BR open (2),
Signature · 1 line
2.7.4
Quoted 6 lines · Deepa Dinamani
Add the utimes command to provide a way to utilize the futimens C library call. This is the interface to the utimensat system call, which updates the mtime and atime of a file.
Signed-off-by Deepa Dinamani <[email protected]>
...
io/utimes.c line 48
Quoted 10 lines
io/utimes.c new file +10
-0+static int +utimes_f ( +int argc, +char **argv) +{ +struct timespec t[2 ]; +int result; + +if (argc !=5 ) +return command_usage (&utimes_cmd);
Because you set argsmin & argsmax to 4, it should be impossible to get here with anything other than argc=5 - it's caught elsewhere:
xfs_io> utimes
bad argument count 0 to utimes, expected 4 arguments xfs_io> utimes 1 2 3 4 5
bad argument count 5 to utimes, expected 4 arguments
Quoted 8 lines
io/utimes.c new file +8
-0+ +/* Get the timestamps */ + result =timespec_from_string (argv[1 ], argv[2 ], &t[0 ]); +if (result) { +fprintf (stderr,"Bad value for atime\n" ); +return 1 ; + } + result =timespec_from_string (argv[3 ], argv[4 ], &t[1 ]);
io/utimes.c line 66
Quoted 10 lines
io/utimes.c new file +10
-0+if (result) { +fprintf (stderr,"Bad value for mtime\n" ); +return 1 ; + } + +/* Call futimens to update time. */ +if (futimens (file->fd, t)) { +perror ("futimens" ); +return 1 ; + }
Most xfs_io functions return 0 even on errors, possibly after setting exit_code = 1 to change the ultimate exit code; returning 1 will cause all processing to stop, and/or kick you out of the interactive shell:
$ xfs_io file xfs_io> utimes a b c d Bad value for atime $
This needs some attention across all of xfs_io, but you might want to return 0 for now for consistency with other commands.
-Eric
Quoted 35 lines
io/utimes.c new file +18
-0+ +return 0 ; +} + +void +utimes_init (void ) +{ + utimes_cmd.name ="utimes" ; + utimes_cmd.cfunc = utimes_f; + utimes_cmd.argmin =4 ; + utimes_cmd.argmax =4 ; + utimes_cmd.flags =CMD_NOMAP_OK |CMD_FOREIGN_OK ; + utimes_cmd.args =_ ("atime_sec atime_nsec mtime_sec mtime_nsec" ); + utimes_cmd.oneline =_ ("Update file times of the current file" ); + utimes_cmd.help = utimes_help; + +add_command (&utimes_cmd); +}libxcmd/input.c +9
-0@@ -327,6 +327,28 @@ timestr( }/* +* Convert from a pair of arbitrary user strings into a timespec. +*/ + +int +timespec_from_string ( +const char * secs, +const char * nsecs, +struct timespec * ts) +{
libxcmd/input.c timestr( · line 348
Quoted 10 lines
libxcmd/input.c +10
-0+char * p; +if (!secs || !nsecs || !ts) +return -1 ; + ts->tv_sec =strtoull (secs, &p,0 ); +if (*p) +return -1 ; + ts->tv_nsec =strtoull (nsecs, &p,0 ); +if (*p) +return -1 ; +return 0 ;
I'd return 1/0 not -1/0 - not that big a deal, but the reason the i.e. prid_from_string() functions return -1 on error is because they actually return an ID, which is >= 0, so it detects "== -1" as an error, and can't simply test 1/0.
Quoted 11 lines
libxcmd/input.c +3
-0+} + +/* * Convert from arbitrary user strings into a numeric ID. * If it's all numeric, we convert that inplace, else we do * the name lookup, and return the found identifier. man/man8/xfs_io.8 +0
-0
man/man8/xfs_io.8 Copy data into the open file beginning at · line 595
Quoted 7 lines
man/man8/xfs_io.8 +4
-0@@ -589,6 +589,17 @@ Copy data into the open file beginning at Copy up to .I length bytes of data. +.RE +.PD +.TP +.TP
don't need two .TPs, a patch to remove the others is pending.
thanks,
-Eric
Quoted 19 lines
man/man8/xfs_io.8 +8
-0+.BI utimes " atime_sec atime_nsec mtime_sec mtime_nsec" +The utimes command changes the atime and mtime of the current file. +sec uses UNIX timestamp notation and is the seconds elapsed since +1970-01-01 00:00:00 UTC. +nsec is the nanoseconds since the sec. This value needs to be in +the range 0-999999999 with UTIME_NOW and UTIME_OMIT being exceptions. +Each (sec, nsec) pair constitutes a single timestamp value. .SH MEMORY MAPPED I/O COMMANDS .TP@@ -875,6 +886,7 @@ verbose output will be printed. .BR fstatfs (2), .BR fsync (2), .BR ftruncate (2), +.BR futimens (3), .BR mmap (2), .BR msync (2), .BR open (2),
Quoted 4 lines · Eric Sandeen
This needs some attention across all of
xfs_io, but you might want to return 0 for now for consistency with other commands.-Eric
sorry, signed off too early, there were more comments below :)
Quoted 93 lines
Quoted 35 lines
io/utimes.c new file +18
-0+ +return 0 ; +} + +void +utimes_init (void ) +{ + utimes_cmd.name ="utimes" ; + utimes_cmd.cfunc = utimes_f; + utimes_cmd.argmin =4 ; + utimes_cmd.argmax =4 ; + utimes_cmd.flags =CMD_NOMAP_OK |CMD_FOREIGN_OK ; + utimes_cmd.args =_ ("atime_sec atime_nsec mtime_sec mtime_nsec" ); + utimes_cmd.oneline =_ ("Update file times of the current file" ); + utimes_cmd.help = utimes_help; + +add_command (&utimes_cmd); +}libxcmd/input.c +9
-0@@ -327,6 +327,28 @@ timestr( }/* +* Convert from a pair of arbitrary user strings into a timespec. +*/ + +int +timespec_from_string ( +const char * secs, +const char * nsecs, +struct timespec * ts) +{libxcmd/input.c timestr( · line 348
Quoted 10 lines
libxcmd/input.c +10
-0+char * p; +if (!secs || !nsecs || !ts) +return -1 ; + ts->tv_sec =strtoull (secs, &p,0 ); +if (*p) +return -1 ; + ts->tv_nsec =strtoull (nsecs, &p,0 ); +if (*p) +return -1 ; +return 0 ;I'd return 1/0 not -1/0 - not that big a deal, but the reason the i.e.
prid_from_string()functions return -1 on error is because they actually return an ID, which is >= 0, so it detects "== -1" as an error, and can't simply test 1/0.Quoted 11 lines
libxcmd/input.c +3
-0+} + +/* * Convert from arbitrary user strings into a numeric ID. * If it's all numeric, we convert that inplace, else we do * the name lookup, and return the found identifier. man/man8/xfs_io.8 +0
-0man/man8/xfs_io.8 Copy data into the open file beginning at · line 595
Quoted 7 lines
man/man8/xfs_io.8 +4
-0@@ -589,6 +589,17 @@ Copy data into the open file beginning at Copy up to .I length bytes of data. +.RE +.PD +.TP +.TPdon't need two .TPs, a patch to remove the others is pending.
thanks,
-EricQuoted 18 lines
man/man8/xfs_io.8 +8
-0+.BI utimes " atime_sec atime_nsec mtime_sec mtime_nsec" +The utimes command changes the atime and mtime of the current file. +sec uses UNIX timestamp notation and is the seconds elapsed since +1970-01-01 00:00:00 UTC. +nsec is the nanoseconds since the sec. This value needs to be in +the range 0-999999999 with UTIME_NOW and UTIME_OMIT being exceptions. +Each (sec, nsec) pair constitutes a single timestamp value. .SH MEMORY MAPPED I/O COMMANDS .TP@@ -875,6 +886,7 @@ verbose output will be printed. .BR fstatfs (2), .BR fsync (2), .BR ftruncate (2), +.BR futimens (3), .BR mmap (2), .BR msync (2), .BR open (2),
Quoted 6 lines
io/utimes.c line 48
Quoted 2 lines
io/utimes.c new file +2
-0+if (argc !=5 ) +return command_usage (&utimes_cmd);Because you set argsmin & argsmax to 4, it should be impossible to get here with anything other than argc=5 - it's caught elsewhere:
Yes, you are right. This was something I was using to debug. I will remove this. Thanks.
Quoted 23 lines
Quoted 7 lines
io/utimes.c new file +7
-0+/* Get the timestamps */ + result =timespec_from_string (argv[1 ], argv[2 ], &t[0 ]); +if (result) { +fprintf (stderr,"Bad value for atime\n" ); +return 1 ; + } + result =timespec_from_string (argv[3 ], argv[4 ], &t[1 ]);io/utimes.c line 66
Quoted 10 lines
io/utimes.c new file +10
-0+if (result) { +fprintf (stderr,"Bad value for mtime\n" ); +return 1 ; + } + +/* Call futimens to update time. */ +if (futimens (file->fd, t)) { +perror ("futimens" ); +return 1 ; + }Most
xfs_iofunctions return 0 even on errors, possibly after settingexit_code= 1 to change the ultimate exit code; returning 1 will cause all processing to stop, and/or kick you out of the interactive shell:
Quoted 7 lines
$ xfs_io file xfs_io> utimes a b c d Bad value for atime $This needs some attention across all of
xfs_io, but you might want to return 0 for now for consistency with other commands.
Will change to return 0 always. Thanks.
Quoted 18 lines
Quoted 18 lines
/*
+ * Convert from a pair of arbitrary user strings into a timespec.
+ */libxcmd/input.c +15
-0+ +int +timespec_from_string ( +const char * secs, +const char * nsecs, +struct timespec * ts) +{ +char * p; +if (!secs || !nsecs || !ts) +return -1 ; + ts->tv_sec =strtoull (secs, &p,0 ); +if (*p) +return -1 ; + ts->tv_nsec =strtoull (nsecs, &p,0 ); +if (*p)
Quoted 8 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+ return -1; + return 0;I'd return 1/0 not -1/0 - not that big a deal, but the reason the i.e.
prid_from_string()functions return -1 on error is because they actually return an ID, which is >= 0, so it detects "== -1" as an error, and can't simply test 1/0.
Ok. Will change this to return 1/0.
Quoted 6 lines
Quoted 6 lines
man/man8/xfs_io.8 +0
-0@@ -589,6 +589,17 @@ Copy data into the open file beginning at Copy up to
Quoted 8 lines
man/man8/xfs_io.8 Copy data into the open file beginning at · line 595
Quoted 6 lines
man/man8/xfs_io.8 +4
-0.I length bytes of data. +.RE +.PD +.TP +.TPdon't need two .TPs, a patch to remove the others is pending.
Ok, will remove it.
I will wait for a couple of days to see if there are any more comments before submitting a v2.
-Deepa