summaryrefslogtreecommitdiffstats
path: root/sysif.c
diff options
context:
space:
mode:
authorKaz Kyheku <kaz@kylheku.com>2020-01-15 20:07:06 -0800
committerKaz Kyheku <kaz@kylheku.com>2020-01-15 20:07:06 -0800
commit267802c97c4a19354647eb96893429d5c67214df (patch)
treed326a40f3c5133de1c46e7e3489b65b80189a83a /sysif.c
parentf76995965d0d8c5cff6885ff305c4f8b0cec524e (diff)
downloadtxr-267802c97c4a19354647eb96893429d5c67214df.tar.gz
txr-267802c97c4a19354647eb96893429d5c67214df.tar.bz2
txr-267802c97c4a19354647eb96893429d5c67214df.zip
chmod: work on streams and descriptors using fchmod.
* configure: extend chmod detection to cover fchmod. * sysif.c (get_fd): New static functions. (chmod_wrap): Include fchmod wrapping for integer or stream argument. (sysif_init): Register fchmod intrinsic.
Diffstat (limited to 'sysif.c')
-rw-r--r--sysif.c37
1 files changed, 31 insertions, 6 deletions
diff --git a/sysif.c b/sysif.c
index aa36c3a6..8e9457d0 100644
--- a/sysif.c
+++ b/sysif.c
@@ -451,17 +451,42 @@ static val mknod_wrap(val path, val mode, val dev)
#if HAVE_CHMOD
-static val chmod_wrap(val path, val mode)
+static int get_fd(val stream, val self)
{
+ val fd_in = if3(integerp(stream), stream, stream_get_prop(stream, fd_k));
+
+ if (stream && !fd_in)
+ uw_throwf(file_error_s,
+ lit("~a: stream ~s has no :fd property"),
+ self, stream, nao);
+
+ if (!stream)
+ uw_throwf(file_error_s,
+ lit("~a: ~s isn't a stream object"),
+ self, stream, nao);
+
+ return c_int(fd_in, self);
+}
+
+static val chmod_wrap(val target, val mode)
+{
+ val self = lit("chmod");
cnum cmode = c_num(mode);
- char *u8path = utf8_dup_to(c_str(path));
- int err = chmod(u8path, cmode);
- free(u8path);
+ int err;
+
+ if (stringp(target)) {
+ char *u8path = utf8_dup_to(c_str(target));
+ err = chmod(u8path, cmode);
+ free(u8path);
+ } else {
+ int fd = get_fd(target, self);
+ err = fchmod(fd, cmode);
+ }
if (err < 0) {
int eno = errno;
- uw_throwf(errno_to_file_error(eno), lit("chmod ~a #o~o: ~d/~s"),
- path, mode, num(eno), string_utf8(strerror(eno)), nao);
+ uw_throwf(errno_to_file_error(eno), lit("~a ~a #o~o: ~d/~s"),
+ self, target, mode, num(eno), string_utf8(strerror(eno)), nao);
}
return t;