aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Bennett <steveb@workware.net.au>2021-07-15 14:15:08 +1000
committerSteve Bennett <steveb@workware.net.au>2022-04-14 11:18:01 +1000
commit81e1890c0f595c474cabcaa83f66882005336d93 (patch)
tree75e9fe03c05b9780c1a34039e508121bb6cfced6
parent703ac20adb9daff423eea44f4af548f485a97254 (diff)
downloadjimtcl-81e1890c0f595c474cabcaa83f66882005336d93.zip
jimtcl-81e1890c0f595c474cabcaa83f66882005336d93.tar.gz
jimtcl-81e1890c0f595c474cabcaa83f66882005336d93.tar.bz2
aio: TIP 603 - Implement stat of an open file handle
Although the interface is different ('$handle stat' vs 'chan configure -stat') the behaviour is the same. Signed-off-by: Steve Bennett <steveb@workware.net.au>
-rw-r--r--jim-aio.c24
-rw-r--r--jim-file.c12
-rw-r--r--jim_tcl.txt5
-rw-r--r--jimiocompat.h8
-rw-r--r--tests/file.test18
5 files changed, 62 insertions, 5 deletions
diff --git a/jim-aio.c b/jim-aio.c
index 4b3237f..5769f78 100644
--- a/jim-aio.c
+++ b/jim-aio.c
@@ -121,6 +121,7 @@
/* no fdopen() with ANSIC, so can't support these */
#undef HAVE_PIPE
#undef HAVE_SOCKETPAIR
+#undef Jim_FileStat
#endif
#if defined(HAVE_SOCKETS) && !defined(JIM_BOOTSTRAP)
@@ -1426,6 +1427,20 @@ static int aio_cmd_onexception(Jim_Interp *interp, int argc, Jim_Obj *const *arg
}
#endif
+#if defined(jim_ext_file) && defined(Jim_FileStat)
+static int aio_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ jim_stat_t sb;
+ AioFile *af = Jim_CmdPrivData(interp);
+
+ if (Jim_FileStat(af->fd, &sb) == -1) {
+ JimAioSetError(interp, NULL);
+ return JIM_ERR;
+ }
+ return Jim_FileStoreStatData(interp, argc == 0 ? NULL : argv[0], &sb);
+}
+#endif
+
#if defined(JIM_SSL) && !defined(JIM_BOOTSTRAP)
static int aio_cmd_ssl(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
@@ -1803,6 +1818,15 @@ static const jim_subcmd_type aio_command_table[] = {
1,
/* Description: Sets buffering */
},
+#if defined(jim_ext_file) && defined(Jim_FileStat)
+ { "stat",
+ "?var?",
+ aio_cmd_stat,
+ 0,
+ 1,
+ /* Description: 'file stat' on the open file */
+ },
+#endif
#ifdef jim_ext_eventloop
{ "readable",
"?readable-script?",
diff --git a/jim-file.c b/jim-file.c
index 5532cb4..b73076f 100644
--- a/jim-file.c
+++ b/jim-file.c
@@ -140,11 +140,13 @@ static const char *JimGetFileType(int mode)
/*
*----------------------------------------------------------------------
*
- * StoreStatData --
+ * Jim_FileStoreStatData --
*
* This is a utility procedure that breaks out the fields of a
* "stat" structure and stores them in textual form into the
- * elements of an associative array.
+ * elements of an associative array (dict).
+ * The result is also returned as the Tcl result.
+ * If varName is NULL, the result is only returned, not stored.
*
* Results:
* Returns a standard Tcl return value. If an error occurs then
@@ -161,7 +163,7 @@ static void AppendStatElement(Jim_Interp *interp, Jim_Obj *listObj, const char *
Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, value));
}
-static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const jim_stat_t *sb)
+int Jim_FileStoreStatData(Jim_Interp *interp, Jim_Obj *varName, const jim_stat_t *sb)
{
/* Just use a list to store the data */
Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
@@ -849,7 +851,7 @@ static int file_cmd_lstat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
if (file_lstat(interp, argv[0], &sb) != JIM_OK) {
return JIM_ERR;
}
- return StoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb);
+ return Jim_FileStoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb);
}
#else
#define file_cmd_lstat file_cmd_stat
@@ -862,7 +864,7 @@ static int file_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
if (file_stat(interp, argv[0], &sb) != JIM_OK) {
return JIM_ERR;
}
- return StoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb);
+ return Jim_FileStoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb);
}
static const jim_subcmd_type file_command_table[] = {
diff --git a/jim_tcl.txt b/jim_tcl.txt
index f84101f..442b34a 100644
--- a/jim_tcl.txt
+++ b/jim_tcl.txt
@@ -67,6 +67,7 @@ Changes between 0.80 and 0.81
10. `open` now supports POSIX-style access arguments
11. TIP 526, `expr` now only allows a single argument (unless --compat is enabled)
12. `try` now supports trap to match on errorcode
+13. TIP 603, `aio stat` is now supported to stat a file handle
Changes between 0.79 and 0.80
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -4963,6 +4964,10 @@ aio
+$handle *sockname*+::
Returns the bound address or path of the socket. See 'getsockname(2)'.
++$handle *stat* ?varName?+::
+ Implements the same functionality as `file stat` for a filehandle.
+ Only available on platforms that support 'fstat(2)' or equivalent.
+
+$handle *sockopt* '?name value?'+::
With no arguments, returns a dictionary of socket options currently set for the handle
(will be empty for a non-socket). With +'name'+ and +'value'+, sets the socket option
diff --git a/jimiocompat.h b/jimiocompat.h
index e44e6d5..5ac7576 100644
--- a/jimiocompat.h
+++ b/jimiocompat.h
@@ -67,10 +67,12 @@ int Jim_OpenForRead(const char *filename);
typedef struct _stat64 jim_stat_t;
#define Jim_Stat __stat64
+ #define Jim_FileStat _fstat64
#else
typedef struct stat jim_stat_t;
#define Jim_Stat stat
+ #define Jim_FileStat fstat
#if defined(HAVE_UNISTD_H)
#include <unistd.h>
@@ -89,4 +91,10 @@ int Jim_OpenForRead(const char *filename);
#endif
#endif
+/* jim-file.c */
+/* Note that this is currently an internal function only.
+ * It does not form part of the public Jim API
+ */
+int Jim_FileStoreStatData(Jim_Interp *interp, Jim_Obj *varName, const jim_stat_t *sb);
+
#endif
diff --git a/tests/file.test b/tests/file.test
index 2347e5b..cf54c05 100644
--- a/tests/file.test
+++ b/tests/file.test
@@ -8,8 +8,10 @@ testConstraint filelstat [string match "wrong # args:*" $msg]
testConstraint unix [expr {$tcl_platform(platform) eq "unix"}]
if {[testConstraint jim]} {
testConstraint mtimeset [expr {!$tcl_platform(bootstrap)}]
+ testConstraint aiostat [expr {!$tcl_platform(bootstrap)}]
} else {
testConstraint mtimeset 1
+ testConstraint aiostat 0
}
test join-1.1 "One name" {
@@ -171,6 +173,22 @@ test stat-1.7 {file stat no variable} jim {
set a(type)
} {file}
+test aio-stat-1.1 {file stat via an open file descriptor} {jim aiostat} {
+ set filename [info script]
+ set fstat [file stat $filename]
+ set f [open $filename]
+ set aiostat [$f stat]
+ $f close
+ set ok 1
+ foreach field {size type mode mtime} {
+ if {$fstat($field) != $aiostat($field)} {
+ puts "error: $field: file stat:$fstat($field) != aio stat:$aiostat($field)"
+ set ok 0
+ }
+ }
+ set ok
+} {1}
+
test ext-1.1 {file ext} -body {
file ext
} -returnCodes error -result {wrong # args: should be "file extension name"}