summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2020-07-09 20:41:52 -0700
committerKaz Kylheku <kaz@kylheku.com>2020-07-09 20:41:52 -0700
commit812e63ca8f42637f6a856e66f57678cbb0472821 (patch)
tree26209ed43872cafcf598cd7f62f50f298e50c1a7
parent1d8d2214495fa29931948e08041cc8a1159fdd19 (diff)
downloadtxr-812e63ca8f42637f6a856e66f57678cbb0472821.tar.gz
txr-812e63ca8f42637f6a856e66f57678cbb0472821.tar.bz2
txr-812e63ca8f42637f6a856e66f57678cbb0472821.zip
Add dirstat function.
This function back-fills the missing d-type information in a dirent on platforms that don't provide d_type in the native dirent. * sysif.c (DT_FIFO, DT_CHR, DT_DIR, DT_BLK, DT_REG, DT_LNK, DT_SOCK): Define all these preprocessor symbols to their Linux values on platforms where DT_DIR is not defined. (DT_UNKNOWN): Make sure this symbol is #undef-d if DT_DIR is not defined, so the corresponding dt-unknown variable does not exist. (dirstat): New static function. (sysif_init): Register dirstat intrinsic. Register dt-fifo and the rest unconditionally now. Changing their order to increasing numeric. * txr.1: Documented.
-rw-r--r--sysif.c65
-rw-r--r--txr.189
2 files changed, 130 insertions, 24 deletions
diff --git a/sysif.c b/sysif.c
index 2ac7ad29..c76be87b 100644
--- a/sysif.c
+++ b/sysif.c
@@ -102,6 +102,17 @@
#include "txr.h"
#include "sysif.h"
+#ifndef DT_DIR
+#undef DT_UNKNOWN
+#define DT_FIFO 1
+#define DT_CHR 2
+#define DT_DIR 4
+#define DT_BLK 6
+#define DT_REG 8
+#define DT_LNK 10
+#define DT_SOCK 12
+#endif
+
val stat_s;
val dev_k, ino_k, mode_k, nlink_k, uid_k;
val gid_k, rdev_k, size_k, blksize_k, blocks_k;
@@ -2311,6 +2322,35 @@ static val readdir_wrap(val dirobj, val dirent_in)
}
}
+static val dirstat(val dirent, val dir_path)
+{
+ val self = lit("dirstat");
+ val name = slot(dirent, name_s);
+ val path = if3(null_or_missing_p(dir_path), name, path_cat(dir_path, name));
+ val stat = stat_wrap(path);
+ val mode = slot(stat, mode_s);
+
+ if (mode) {
+ cnum mod = c_num(mode, self);
+ val type = nil;
+
+ switch (mod & S_IFMT) {
+ case S_IFBLK: type = num_fast(DT_BLK); break;
+ case S_IFCHR: type = num_fast(DT_CHR); break;
+ case S_IFDIR: type = num_fast(DT_DIR); break;
+ case S_IFIFO: type = num_fast(DT_FIFO); break;
+ case S_IFLNK: type = num_fast(DT_LNK); break;
+ case S_IFREG: type = num_fast(DT_REG); break;
+ case S_IFSOCK: type = num_fast(DT_SOCK); break;
+ }
+
+ if (type)
+ slotset(dirent, type_s, type);
+ }
+
+ return stat;
+}
+
void sysif_init(void)
{
prot1(&at_exit_list);
@@ -2884,29 +2924,16 @@ void sysif_init(void)
reg_fun(intern(lit("opendir"), user_package), func_n2o(opendir_wrap, 1));
reg_fun(intern(lit("closedir"), user_package), func_n1(closedir_wrap));
reg_fun(intern(lit("readdir"), user_package), func_n2o(readdir_wrap, 1));
+ reg_fun(intern(lit("dirstat"), user_package), func_n2o(dirstat, 1));
-#ifdef DT_BLK
- reg_varl(intern(lit("dt-blk"), user_package), num_fast(DT_BLK));
+#ifdef DT_UNKNOWN
+ reg_varl(intern(lit("dt-unknown"), user_package), num_fast(DT_UNKNOWN));
#endif
-#ifdef DT_CHR
+ reg_varl(intern(lit("dt-fifo"), user_package), num_fast(DT_FIFO));
reg_varl(intern(lit("dt-chr"), user_package), num_fast(DT_CHR));
-#endif
-#ifdef DT_DIR
reg_varl(intern(lit("dt-dir"), user_package), num_fast(DT_DIR));
-#endif
-#ifdef DT_FIFO
- reg_varl(intern(lit("dt-fifo"), user_package), num_fast(DT_FIFO));
-#endif
-#ifdef DT_LNK
- reg_varl(intern(lit("dt-lnk"), user_package), num_fast(DT_LNK));
-#endif
-#ifdef DT_REG
+ reg_varl(intern(lit("dt-blk"), user_package), num_fast(DT_BLK));
reg_varl(intern(lit("dt-reg"), user_package), num_fast(DT_REG));
-#endif
-#ifdef DT_SOCK
+ reg_varl(intern(lit("dt-lnk"), user_package), num_fast(DT_LNK));
reg_varl(intern(lit("dt-sock"), user_package), num_fast(DT_SOCK));
-#endif
-#ifdef DT_UNKNOWN
- reg_varl(intern(lit("dt-unknown"), user_package), num_fast(DT_UNKNOWN));
-#endif
}
diff --git a/txr.1 b/txr.1
index 4fd20484..3d54cfca 100644
--- a/txr.1
+++ b/txr.1
@@ -62793,10 +62793,9 @@ slot indicates the type of the object, which is an integer code. Support for
this member is platform-dependent. If the directory traversal doesn't provide
the information, then this slot takes on the
.code nil
-value. In this situation, if the information requires type information about
-the object, it must use the
-.code stat
-function to obtain it in a different form.
+value. In this situation, the
+.code dirstat
+function may be used to back-fill the missing information.
.coNP Variables @, dt-blk @, dt-chr @, dt-dir @, dt-fifo @, dt-lnk @, dt-reg @ dt-sock and @ dt-unknown
.desc
@@ -62805,7 +62804,26 @@ These variables give the possible type code values exhibited by the
slot of the
.code dirent
structure.
-If this information is not available, then these variables do not exist.
+
+If the underlying host platform does not feature a
+.code d_type
+field in the
+.code dirent
+C structure, then almost all these variables are defined anyway using the values that they
+have on GNU/Linux.
+These definitions are useful in conjunction with the
+.code dirstat
+function below.
+
+If the host platform does does not feature a
+.code d_type
+field in the
+.code dirent
+structure, then the variable
+.code dt-unknown
+is not defined. Note: the application can take advantage of this this to detect
+the situation, in order to conditionally define code in such a way that some
+run-time checking is avoided.
.coNP Function @ opendir
.synb
@@ -62926,6 +62944,67 @@ function implicitly closes
.meta dir-handle
when the handle indicates that no more directory entries remain to be traversed.
+.coNP Function @ dirstat
+.synb
+.mets (dirstat < dirent-struct <> [ dir-path ])
+.syne
+.desc
+The
+.code dirstat
+function invokes
+.code stat
+on the object represented by the
+.code dirent
+structure
+.metn dirent-struct ,
+sets the
+.code type
+slot of the
+.meta dirent-struct
+accordingly, and also returns the
+.code stat
+structure.
+
+The
+.meta dir-path
+parameter must be specified, if the
+.code name
+slot of
+.meta dirent-struct
+is a simple directory entry name, rather than the full path to the object.
+In that case, the slot's value gives the effective path.
+If the
+.code name
+slot is already a path (due to, for instance, a true value of
+.meta prefix-p
+having been passed to
+.codn opendir )
+then
+.meta dir-path
+must not be specified.
+If
+.meta dir-path
+is specified, then its value is combined with the
+.meta name
+slot of
+.meta dirent-struct
+using
+.code path-cat
+to form the effective path.
+
+The
+.code stat
+function is invoked on the effective path, and if it succeeds,
+then type information is obtained from the resulting
+.code stat
+structure to set the value of the
+.code type
+slot of
+.metn dirent-struct .
+The
+.code stat
+structure is then returned.
+
.SS* Unix Sockets
On platforms where the underlying system interface is available, \*(TX provides