diff options
-rw-r--r-- | sysif.c | 65 | ||||
-rw-r--r-- | txr.1 | 89 |
2 files changed, 130 insertions, 24 deletions
@@ -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 } @@ -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 |