diff options
author | Kaz Kyheku <kaz@kylheku.com> | 2020-01-28 05:25:00 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2020-01-28 05:25:00 -0800 |
commit | 354824aeceb339dbd854c90f397d9a6c8a27505b (patch) | |
tree | 7255ca97f4324e8fba112f26b5feaf195f05dfd4 | |
parent | 558f7e76cc334e85bc30bf5dd9b62fa8038832ef (diff) | |
download | txr-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-x | configure | 19 | ||||
-rw-r--r-- | sysif.c | 46 | ||||
-rw-r--r-- | txr.1 | 77 |
3 files changed, 141 insertions, 1 deletions
@@ -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> @@ -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)); @@ -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 ) |