summaryrefslogtreecommitdiffstats
path: root/sysif.c
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 /sysif.c
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.
Diffstat (limited to 'sysif.c')
-rw-r--r--sysif.c65
1 files changed, 46 insertions, 19 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
}