summaryrefslogtreecommitdiffstats
path: root/sysif.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2015-08-02 08:44:33 -0700
committerKaz Kylheku <kaz@kylheku.com>2015-08-02 08:44:33 -0700
commit64d3f8fcc8ef6e83e6fd789614e1aadfa526d18d (patch)
treee8bc344e3bb388c4c66a7e58704341fdc8ef833c /sysif.c
parentb9d23bcf53ee7b041b511a25a36291ae7166c73b (diff)
downloadtxr-64d3f8fcc8ef6e83e6fd789614e1aadfa526d18d.tar.gz
txr-64d3f8fcc8ef6e83e6fd789614e1aadfa526d18d.tar.bz2
txr-64d3f8fcc8ef6e83e6fd789614e1aadfa526d18d.zip
Support lstat and fstat.
* stream.h (statf): Declaration removed. * sysif.c (w_stat): Function takes val instead of const wchar_t * as leftmost argument. (w_lstat, w_fstat): New static functions, with same interface as w_stat. (stat_to_list, stat_impl): New static functions. (statp, statl): New static functions. (statf): Function removed, name re-used for new static function. (sysif_init): stat intrinsic registered to statp function, not statf. lstat and fstat intrinsics registered to statl and statf. * txr.1: Documented lstat and fstat.
Diffstat (limited to 'sysif.c')
-rw-r--r--sysif.c72
1 files changed, 60 insertions, 12 deletions
diff --git a/sysif.c b/sysif.c
index 6c0cb547..6761b912 100644
--- a/sysif.c
+++ b/sysif.c
@@ -519,25 +519,40 @@ static val exit_star_wrap(val status)
#endif
#if HAVE_SYS_STAT
-static int w_stat(const wchar_t *wpath, struct stat *buf)
+static int w_stat(val wpath, struct stat *buf)
{
- char *path = utf8_dup_to(wpath);
+ char *path = utf8_dup_to(c_str(wpath));
int res = stat(path, buf);
free(path);
return res;
}
-#endif
-val statf(val path)
+static int w_lstat(val wpath, struct stat *buf)
{
-#if HAVE_SYS_STAT
- struct stat st;
- int res = w_stat(c_str(path), &st);
+ char *path = utf8_dup_to(c_str(wpath));
+ int res = lstat(path, buf);
+ free(path);
+ return res;
+}
- if (res == -1)
- uw_throwf(file_error_s, lit("unable to stat ~a: ~a/~s"),
- path, num(errno), string_utf8(strerror(errno)), nao);
+static int w_fstat(val stream, struct stat *buf)
+{
+ val fd = stream_get_prop(stream, fd_k);
+ if (fd) {
+ int res = fstat(c_num(fd), buf);
+ return res;
+ }
+
+ uw_throwf(file_error_s,
+ lit("cannot fstat stream ~s: it has no :fd property"),
+ stream, nao);
+}
+#endif
+
+#if HAVE_SYS_STAT
+static val stat_to_list(struct stat st)
+{
return list(dev_k, num(st.st_dev),
ino_k, num(st.st_ino),
mode_k, num(st.st_mode),
@@ -557,11 +572,42 @@ val statf(val path)
mtime_k, num(st.st_mtime),
ctime_k, num(st.st_ctime),
nao);
+}
+
+#endif
+
+static val stat_impl(val obj, int (*statfn)(val, struct stat *),
+ val name)
+{
+#if HAVE_SYS_STAT
+ struct stat st;
+ int res = statfn(obj, &st);
+
+ if (res == -1)
+ uw_throwf(file_error_s, lit("unable to ~a ~a: ~a/~s"),
+ name, obj, num(errno), string_utf8(strerror(errno)), nao);
+
+ return stat_to_list(st);
#else
- uw_throwf(file_error_s, lit("stat is not implemented"), nao);
+ uw_throwf(file_error_s, lit("~a is not implemented"), name, nao);
#endif
}
+static val statp(val path)
+{
+ return stat_impl(path, w_stat, lit("stat"));
+}
+
+static val statl(val path)
+{
+ return stat_impl(path, w_lstat, lit("lstat"));
+}
+
+static val statf(val stream)
+{
+ return stat_impl(stream, w_fstat, lit("lstat"));
+}
+
#if HAVE_PIPE
static val pipe_wrap(void)
@@ -723,7 +769,9 @@ void sysif_init(void)
reg_fun(intern(lit("readlink"), user_package), func_n1(readlink_wrap));
#endif
- reg_fun(intern(lit("stat"), user_package), func_n1(statf));
+ reg_fun(intern(lit("stat"), user_package), func_n1(statp));
+ reg_fun(intern(lit("lstat"), user_package), func_n1(statl));
+ reg_fun(intern(lit("fstat"), user_package), func_n1(statf));
#if HAVE_SYS_STAT
#ifndef S_IFSOCK