diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2023-09-23 00:15:46 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2023-09-23 00:15:46 -0700 |
commit | 2df419cdb5295b405a98d24f0226cb42bfbf37d2 (patch) | |
tree | 8573aac3d9beecd34b10387df4147e1cc518bcc0 | |
parent | 9e197d1ef054cd389a3ed89cfe66f80ac1a979f2 (diff) | |
download | txr-2df419cdb5295b405a98d24f0226cb42bfbf37d2.tar.gz txr-2df419cdb5295b405a98d24f0226cb42bfbf37d2.tar.bz2 txr-2df419cdb5295b405a98d24f0226cb42bfbf37d2.zip |
New function: rlink.
This uses the linkat function to implement a variant of
link which resolves the source object if it is a symlink.
* configure: test for linkat.
* sysif.c (link_wrap_common): New static function, used
by both link_wrap and rlink_wrap.
(link_wrap): Now a one-liner which calls link_wrap_common.
(rlink_wrap): New static function.
(sysif_init): Register rlink intrinsic.
* txr.1: Documented.
-rwxr-xr-x | configure | 20 | ||||
-rw-r--r-- | sysif.c | 23 | ||||
-rw-r--r-- | txr.1 | 16 |
3 files changed, 55 insertions, 4 deletions
@@ -2665,6 +2665,26 @@ else printf "no\n" fi +printf "Checking for linkat ... " + +cat > conftest.c <<! +#include <unistd.h> +#include <fcntl.h> + +int main(void) +{ + int e1 = linkat(AT_FDCWD, "foo", AT_FDCWD, "bar", AT_SYMLINK_FOLLOW); + return 0; +} +! +if conftest ; then + printf "yes\n" + printf "#define HAVE_LINKAT 1\n" >> config.h + have_unistd=y +else + printf "no\n" +fi + printf "Checking for POSIX mkdir ... " cat > conftest.c <<! @@ -957,14 +957,18 @@ static val symlink_wrap(val target, val to) return t; } -static val link_wrap(val target, val to) +static val link_wrap_common(val target, val to, val follow_link, val self) { - val self = lit("link"); const wchar_t *wtarget = c_str(target, self); const wchar_t *wto = c_str(to, self); char *u8target = utf8_dup_to(wtarget); char *u8to = utf8_dup_to(wto); +#if HAVE_LINKAT + int err = linkat(AT_FDCWD, u8target, AT_FDCWD, u8to, + if3(follow_link, AT_SYMLINK_FOLLOW, 0)); +#else int err = link(u8target, u8to); +#endif free(u8target); free(u8to); @@ -977,6 +981,18 @@ static val link_wrap(val target, val to) return t; } +static val link_wrap(val target, val to) +{ + return link_wrap_common(target, to, nil, lit("link")); +} + +#if HAVE_LINKAT +static val rlink_wrap(val target, val to) +{ + return link_wrap_common(target, to, t, lit("rlink")); +} +#endif + static val readlink_wrap(val path) { val self = lit("readlink"); @@ -2783,6 +2799,9 @@ void sysif_init(void) reg_fun(intern(lit("symlink"), user_package), func_n2(symlink_wrap)); reg_fun(intern(lit("link"), user_package), func_n2(link_wrap)); reg_fun(intern(lit("readlink"), user_package), func_n1(readlink_wrap)); +#if HAVE_LINKAT + reg_fun(intern(lit("rlink"), user_package), func_n2(rlink_wrap)); +#endif #endif #if HAVE_FCNTL @@ -73601,10 +73601,11 @@ of the .code s-ififo type and the permission mode bits. -.coNP Functions @ symlink and @ link +.coNP Functions @, symlink @ link and @ rlink .synb .mets (symlink < target << path ) .mets (link < target << path ) +.mets (rlink < target << path ) .syne .desc The @@ -73617,13 +73618,24 @@ are the absolute or relative path .meta target does not actually have to exist. -The link function creates a hard link. The object at +The +.code link +function creates a hard link. The object at .meta target is installed into the filesystem at .meta path also. +The +.code rlink +function is like +.code link +except that if +.meta path +is a symbolic link, it is resolved. + + If these functions succeed, they return .codn t . Otherwise they throw an exception |