aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Bennett <steveb@workware.net.au>2016-08-27 14:09:31 +1000
committerSteve Bennett <steveb@workware.net.au>2018-09-21 12:57:41 +1000
commitfd07366b2c527527425dce94d1c337168ea86638 (patch)
tree4e5de3da314e9d70cacfcc818327c5b193d40133
parent022f90263261694bbcb98373ad7e5a282ab74453 (diff)
downloadjimtcl-fd07366b2c527527425dce94d1c337168ea86638.zip
jimtcl-fd07366b2c527527425dce94d1c337168ea86638.tar.gz
jimtcl-fd07366b2c527527425dce94d1c337168ea86638.tar.bz2
file: Add microsecond resolution for mtime: mtimeus
Note that actual support is dependent upon the underlying operating system and filesystem. Signed-off-by: Steve Bennett <steveb@workware.net.au>
-rw-r--r--auto.def5
-rw-r--r--jim-file.c75
-rw-r--r--jim_tcl.txt14
3 files changed, 78 insertions, 16 deletions
diff --git a/auto.def b/auto.def
index 394cc62..fc937ff 100644
--- a/auto.def
+++ b/auto.def
@@ -130,6 +130,11 @@ if {[cc-check-functions sysinfo]} {
}
}
+cc-with {-includes {sys/types.h sys/stat.h}} {
+ cc-check-members "struct stat.st_mtimespec"
+ cc-check-members "struct stat.st_mtim"
+}
+
cc-with {-includes fcntl.h} {
cc-check-types "struct flock"
}
diff --git a/jim-file.c b/jim-file.c
index 8185839..dca906d 100644
--- a/jim-file.c
+++ b/jim-file.c
@@ -77,6 +77,13 @@
#define ISWINDOWS 0
#endif
+/* extract nanosecond resolution mtime from struct stat */
+#if defined(HAVE_STRUCT_STAT_ST_MTIMESPEC)
+ #define STAT_MTIME_US(STAT) ((STAT).st_mtimespec.tv_sec * 1000000ll + (STAT).st_mtimespec.tv_nsec / 1000)
+#elif defined(HAVE_STRUCT_STAT_ST_MTIM)
+ #define STAT_MTIME_US(STAT) ((STAT).st_mtim.tv_sec * 1000000ll + (STAT).st_mtim.tv_nsec / 1000)
+#endif
+
/*
*----------------------------------------------------------------------
*
@@ -169,6 +176,9 @@ static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat
AppendStatElement(interp, listObj, "atime", sb->st_atime);
AppendStatElement(interp, listObj, "mtime", sb->st_mtime);
AppendStatElement(interp, listObj, "ctime", sb->st_ctime);
+#ifdef STAT_MTIME_US
+ AppendStatElement(interp, listObj, "mtimeus", STAT_MTIME_US(*sb));
+#endif
Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "type", -1));
Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, JimGetFileType((int)sb->st_mode), -1));
@@ -610,37 +620,65 @@ static int file_cmd_atime(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
return JIM_OK;
}
+/**
+ * Set file atime/mtime to the given time in microseconds since the epoch.
+ */
+static int JimSetFileTimes(Jim_Interp *interp, const char *filename, jim_wide us)
+{
+#ifdef HAVE_UTIMES
+ struct timeval times[2];
+
+ times[1].tv_sec = times[0].tv_sec = us / 1000000;
+ times[1].tv_usec = times[0].tv_usec = us % 1000000;
+
+ if (utimes(filename, times) != 0) {
+ Jim_SetResultFormatted(interp, "can't set time on \"%s\": %s", filename, strerror(errno));
+ return JIM_ERR;
+ }
+ return JIM_OK;
+#else
+ Jim_SetResultString(interp, "Not implemented", -1);
+ return JIM_ERR;
+#endif
+}
+
static int file_cmd_mtime(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
struct stat sb;
if (argc == 2) {
-#ifdef HAVE_UTIMES
- jim_wide newtime;
- struct timeval times[2];
-
- if (Jim_GetWide(interp, argv[1], &newtime) != JIM_OK) {
+ jim_wide secs;
+ if (Jim_GetWide(interp, argv[1], &secs) != JIM_OK) {
return JIM_ERR;
}
+ return JimSetFileTimes(interp, Jim_String(argv[0]), secs * 1000000);
+ }
+ if (file_stat(interp, argv[0], &sb) != JIM_OK) {
+ return JIM_ERR;
+ }
+ Jim_SetResultInt(interp, sb.st_mtime);
+ return JIM_OK;
+}
- times[1].tv_sec = times[0].tv_sec = newtime;
- times[1].tv_usec = times[0].tv_usec = 0;
+#ifdef STAT_MTIME_US
+static int file_cmd_mtimeus(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ struct stat sb;
- if (utimes(Jim_String(argv[0]), times) != 0) {
- Jim_SetResultFormatted(interp, "can't set time on \"%#s\": %s", argv[0], strerror(errno));
+ if (argc == 2) {
+ jim_wide us;
+ if (Jim_GetWide(interp, argv[1], &us) != JIM_OK) {
return JIM_ERR;
}
-#else
- Jim_SetResultString(interp, "Not implemented", -1);
- return JIM_ERR;
-#endif
+ return JimSetFileTimes(interp, Jim_String(argv[0]), us);
}
if (file_stat(interp, argv[0], &sb) != JIM_OK) {
return JIM_ERR;
}
- Jim_SetResultInt(interp, sb.st_mtime);
+ Jim_SetResultInt(interp, STAT_MTIME_US(sb));
return JIM_OK;
}
+#endif
static int file_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
@@ -765,6 +803,15 @@ static const jim_subcmd_type file_command_table[] = {
2,
/* Description: Get or set last modification time */
},
+#ifdef STAT_MTIME_US
+ { "mtimeus",
+ "name ?time?",
+ file_cmd_mtimeus,
+ 1,
+ 2,
+ /* Description: Get or set last modification time in microseconds */
+ },
+#endif
{ "copy",
"?-force? source dest",
file_cmd_copy,
diff --git a/jim_tcl.txt b/jim_tcl.txt
index efe13c5..64642a9 100644
--- a/jim_tcl.txt
+++ b/jim_tcl.txt
@@ -3,7 +3,7 @@ Jim Tcl(n)
NAME
----
-Jim Tcl v0.78 - reference manual for the Jim Tcl scripting language
+Jim Tcl v0.78+ - reference manual for the Jim Tcl scripting language
SYNOPSIS
--------
@@ -52,6 +52,10 @@ Some notable differences with Tcl 8.5/8.6 are:
RECENT CHANGES
--------------
+Changes since 0.78
+~~~~~~~~~~~~~~~~~~
+1. Add `file mtimeus` for high resolution file timestamps
+
Changes between 0.77 and 0.78
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1. Add serial/tty support with `aio tty`
@@ -2373,6 +2377,12 @@ abbreviation for +'option'+ is acceptable. The valid options are:
error is generated. If +'time'+ is given, sets the modification time
of the file to the given value.
++*file mtimeus* 'name ?time_us?'+::
+ As for `file mtime` except the time value is in microseconds
+ since the epoch (see also `clock microseconds`).
+ Note that some platforms and some filesystems don't support high
+ resolution timestamps for files.
+
+*file normalize* 'name'+::
Return the normalized path of +'name'+. See 'realpath(3)'.
@@ -2410,7 +2420,7 @@ abbreviation for +'option'+ is acceptable. The valid options are:
Invoke the 'stat' kernel call on +'name'+, and return the result
as a dictionary with the following keys: 'atime',
'ctime', 'dev', 'gid', 'ino', 'mode', 'mtime',
- 'nlink', 'size', 'type', 'uid'.
+ 'nlink', 'size', 'type', 'uid', 'mtimeus' (if supported - see `file mtimeus`)
Each element except 'type' is a decimal string with the value of
the corresponding field from the 'stat' return structure; see the
manual entry for 'stat' for details on the meanings of the values.