summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kyheku <kaz@kylheku.com>2020-01-28 05:25:00 -0800
committerKaz Kylheku <kaz@kylheku.com>2020-01-28 05:25:00 -0800
commit354824aeceb339dbd854c90f397d9a6c8a27505b (patch)
tree7255ca97f4324e8fba112f26b5feaf195f05dfd4
parent558f7e76cc334e85bc30bf5dd9b62fa8038832ef (diff)
downloadtxr-354824aeceb339dbd854c90f397d9a6c8a27505b.tar.gz
txr-354824aeceb339dbd854c90f397d9a6c8a27505b.tar.bz2
txr-354824aeceb339dbd854c90f397d9a6c8a27505b.zip
New functions: chown, lchown.
* configure: New configure test for chown, fchown and lchown. * sysif.c (get_fd): Define for HAVE_CHOWN also. (do_chown, chown_wrap, lchown_wrap): New functions. (sysif_init): chown and lchown intrinsics registered. * txr.1: Documented.
-rwxr-xr-xconfigure19
-rw-r--r--sysif.c46
-rw-r--r--txr.177
3 files changed, 141 insertions, 1 deletions
diff --git a/configure b/configure
index 69a69e57..fcfe51c8 100755
--- a/configure
+++ b/configure
@@ -2425,6 +2425,25 @@ else
printf "no\n"
fi
+printf "Checking for chown/fchown/lchown ... "
+cat > conftest.c <<!
+#include <unistd.h>
+
+int main(void)
+{
+ int r0 = chown("a", 0, 0);
+ int r1 = fchown(4, 0, 0);
+ int r2 = lchown("a", 0, 0);
+ return 0;
+}
+!
+if conftest ; then
+ printf "yes\n"
+ printf "#define HAVE_CHOWN 1\n" >> config.h
+else
+ printf "no\n"
+fi
+
printf "Checking for pipe ... "
cat > conftest.c <<!
#include <unistd.h>
diff --git a/sysif.c b/sysif.c
index a12d625f..e6402858 100644
--- a/sysif.c
+++ b/sysif.c
@@ -507,7 +507,7 @@ static val mkfifo_wrap(val path, val mode)
#endif
-#if HAVE_CHMOD || HAVE_SYS_STAT || HAVE_FILE_STAMP_CHANGE
+#if HAVE_CHMOD || HAVE_CHOWN || HAVE_SYS_STAT || HAVE_FILE_STAMP_CHANGE
static int get_fd(val stream, val self)
{
val fd_in = if3(integerp(stream), stream, stream_get_prop(stream, fd_k));
@@ -554,6 +554,45 @@ static val chmod_wrap(val target, val mode)
#endif
+#if HAVE_CHOWN
+
+static val do_chown(val target, val uid, val gid, val link_p, val self)
+{
+ cnum cuid = c_num(uid);
+ cnum cgid = c_num(gid);
+ int err;
+
+ if (stringp(target)) {
+ char *u8path = utf8_dup_to(c_str(target));
+ err = if3(link_p, lchown, chown)(u8path, cuid, cgid);
+ free(u8path);
+ } else {
+ int fd = get_fd(target, self);
+ err = fchown(fd, cuid, cgid);
+ }
+
+ if (err < 0) {
+ int eno = errno;
+ uw_throwf(errno_to_file_error(eno), lit("~a ~a ~a ~a: ~d/~s"),
+ self, target, uid, gid, num(eno),
+ string_utf8(strerror(eno)), nao);
+ }
+
+ return t;
+}
+
+static val chown_wrap(val target, val uid, val gid)
+{
+ return do_chown(target, uid, gid, nil, lit("chown"));
+}
+
+static val lchown_wrap(val target, val uid, val gid)
+{
+ return do_chown(target, uid, gid, t, lit("lchown"));
+}
+
+#endif
+
#if HAVE_SYMLINK
static val symlink_wrap(val target, val to)
@@ -2097,6 +2136,11 @@ void sysif_init(void)
reg_fun(intern(lit("chmod"), user_package), func_n2(chmod_wrap));
#endif
+#if HAVE_CHOWN
+ reg_fun(intern(lit("chown"), user_package), func_n3(chown_wrap));
+ reg_fun(intern(lit("lchown"), user_package), func_n3(lchown_wrap));
+#endif
+
#if HAVE_SYMLINK
reg_fun(intern(lit("symlink"), user_package), func_n2(symlink_wrap));
reg_fun(intern(lit("link"), user_package), func_n2(link_wrap));
diff --git a/txr.1 b/txr.1
index bcbc1520..0510b7f9 100644
--- a/txr.1
+++ b/txr.1
@@ -57990,6 +57990,83 @@ function.
s-iroth))
.brev
+.coNP Functions @ chown and @ lchown
+.synb
+.mets (chown < target < id << gid )
+.mets (lchown < target < id << gid )
+.syne
+.desc
+The
+.code chown
+and
+.code lchown
+functions change the user and group ownership of the filesystem object
+specified by
+.metn target .
+
+They implemented in terms of the POSIX functions
+.codn chown ,
+.code fchown
+and
+.codn lchown .
+
+The ownership attributes are specified by
+.meta uid
+and
+.metn gid ,
+both integer arguments.
+
+The existing ownership attributes may be obtained using the
+.code stat
+function.
+
+These functions throw a
+.code file-error
+exception if an error occurs, otherwise they returns
+.codn t .
+
+The
+.meta target
+argument may be a character string, in which case it specifies a pathname in
+the filesystem. In this case, the same-named POSIX function
+.code chown
+is invoked by
+.codn chown ,
+whereas
+.code lchown
+likewise invokes its respective same-named POSIX counterpart.
+The difference is that if
+.meta target
+is a pathname denoting a symbolic link, then
+.code lchown
+operates on the symbolic link, whereas
+.code chown
+dereferences the symbolic link.
+
+The
+.meta target
+argument may also be an integer file descriptor, or a stream. In these two
+cases, the POSIX
+.code fchown
+function is invoked by either function. For a stream
+.metn target ,
+the integer file descriptor is retrieved from the stream using
+.code fileno
+function.
+
+Note: in most POSIX systems, unprivileged processes may not change the user
+ownership denoted by
+.metn uid .
+They may change the group ownership indicated in
+.metn gid ,
+if that value corresponds to the effective group ID of the calling
+process or one of its ancillary group IDs.
+
+To avoid trying to change the user ownership (and therefore failing),
+the caller should specify a
+.meta uid
+value which matches the object's existing owner.
+
.coNP Functions @ utimes and @ lutimes
.synb
.mets (utimes < target < atime-s < atime-ns < mtime-s << mtime-ns )