guile-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Guile-commits] 04/14: Define ‘symlinkat’ wrapper when supported.


From: Ludovic Courtès
Subject: [Guile-commits] 04/14: Define ‘symlinkat’ wrapper when supported.
Date: Thu, 16 Jun 2022 04:50:45 -0400 (EDT)

civodul pushed a commit to branch wip-openat
in repository guile.

commit ff245aa6226576d194ee63cdfc8fa5128a2a0398
Author: Maxime Devos <maximedevos@telenet.be>
AuthorDate: Tue Nov 16 11:06:27 2021 +0000

    Define ‘symlinkat’ wrapper when supported.
    
    * configure.ac: Detect whether ‘symlinkat’ exists.
    * libguile/filesys.c (scm_symlinkat): Define a Scheme binding
      when it exists.
    * libguile/filesys.h: Make the binding part of the public C API.
    * doc/ref/posix.texi (File System): Document the binding.
    * test-suite/tests/filesys.test ("symlinkat"): Test it.
    
    Signed-off-by: Ludovic Courtès <ludo@gnu.org>
---
 configure.ac                  |  2 +-
 doc/ref/posix.texi            |  6 ++++++
 libguile/filesys.c            | 23 +++++++++++++++++++++++
 libguile/filesys.h            |  1 +
 test-suite/tests/filesys.test | 27 +++++++++++++++++++++++++++
 5 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index 9f30cca47..2463f068d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -529,7 +529,7 @@ AC_CHECK_HEADERS([assert.h crt_externs.h])
 #
 AC_CHECK_FUNCS([DINFINITY DQNAN cexp chsize clog clog10 ctermid         \
   fesetround ftime ftruncate fchown fchmod fchdir readlinkat           \
-  getcwd geteuid getsid                                                        
\
+  symlinkat getcwd geteuid getsid                                              
        \
   gettimeofday getuid getgid gmtime_r ioctl lstat mkdir mkdtemp mknod   \
   nice readlink rename rmdir setegid seteuid                            \
   setlocale setuid setgid setpgid setsid sigaction siginterrupt stat64  \
diff --git a/doc/ref/posix.texi b/doc/ref/posix.texi
index b6deffd43..a329eec39 100644
--- a/doc/ref/posix.texi
+++ b/doc/ref/posix.texi
@@ -891,6 +891,12 @@ Create a symbolic link named @var{newpath} with the value 
(i.e., pointing to)
 @var{oldpath}.  The return value is unspecified.
 @end deffn
 
+@deffn {Scheme Procedure} symlinkat dir oldpath newpath
+@deffnx {C Function} scm_symlinkat (dir, oldpath, newpath)
+Like @code{symlink}, but resolve @var{newpath} relative to
+the directory referred to by the file port @var{dir}.
+@end deffn
+
 @deffn {Scheme Procedure} mkdir path [mode]
 @deffnx {C Function} scm_mkdir (path, mode)
 Create a new directory named by @var{path}.  If @var{mode} is omitted
diff --git a/libguile/filesys.c b/libguile/filesys.c
index c5bedec07..bfd223434 100644
--- a/libguile/filesys.c
+++ b/libguile/filesys.c
@@ -1045,6 +1045,29 @@ SCM_DEFINE (scm_symlink, "symlink", 2, 0, 0,
 #undef FUNC_NAME
 #endif /* HAVE_SYMLINK */
 
+#ifdef HAVE_SYMLINKAT
+SCM_DEFINE (scm_symlinkat, "symlinkat", 3, 0, 0,
+            (SCM dir, SCM oldpath, SCM newpath),
+            "Like @code{symlink}, but resolve @var{newpath} relative\n"
+            "to the directory referred to by the file port @var{dir}.")
+#define FUNC_NAME s_scm_symlinkat
+{
+  int val;
+  int fdes;
+
+  SCM_VALIDATE_OPFPORT (SCM_ARG1, dir);
+  fdes = SCM_FPORT_FDES (dir);
+  STRING2_SYSCALL (oldpath, c_oldpath,
+                  newpath, c_newpath,
+                  val = symlinkat (c_oldpath, fdes, c_newpath));
+  scm_remember_upto_here_1 (dir);
+  if (val != 0)
+    SCM_SYSERROR;
+  return SCM_UNSPECIFIED;
+}
+#undef FUNC_NAME
+#endif /* HAVE_SYMLINKAT */
+
 /* Static helper function for choosing between readlink
    and readlinkat. */
 static int
diff --git a/libguile/filesys.h b/libguile/filesys.h
index a3b257c12..d181aca52 100644
--- a/libguile/filesys.h
+++ b/libguile/filesys.h
@@ -62,6 +62,7 @@ SCM_API SCM scm_select (SCM reads, SCM writes, SCM excepts, 
SCM secs, SCM msecs)
 SCM_API SCM scm_fcntl (SCM object, SCM cmd, SCM value);
 SCM_API SCM scm_fsync (SCM object);
 SCM_API SCM scm_symlink (SCM oldpath, SCM newpath);
+SCM_API SCM scm_symlinkat (SCM dir, SCM oldpath, SCM newpath);
 SCM_API SCM scm_readlink (SCM path);
 SCM_API SCM scm_lstat (SCM str);
 SCM_API SCM scm_copy_file (SCM oldfile, SCM newfile);
diff --git a/test-suite/tests/filesys.test b/test-suite/tests/filesys.test
index 7feb3492f..64bf92333 100644
--- a/test-suite/tests/filesys.test
+++ b/test-suite/tests/filesys.test
@@ -367,3 +367,30 @@
 
   (false-if-exception (delete-file (test-symlink)))
   (false-if-exception (delete-file (test-file))))
+
+(with-test-prefix "symlinkat"
+  (pass-if-equal "create" (test-file)
+    (unless (defined? 'symlinkat)
+      (throw 'unsupported))
+    (call-with-port
+     (open "." O_RDONLY)
+     (lambda (port)
+       (symlinkat port (test-file) (test-symlink))
+       (readlink (test-symlink)))))
+  (false-if-exception (delete-file (test-symlink)))
+
+  (pass-if-exception "not a port" exception:wrong-type-arg
+    (unless (defined? 'symlinkat)
+      (throw 'unsupported))
+    (symlinkat "bogus" (test-file) (test-symlink)))
+
+  (pass-if-exception "not a file port" exception:wrong-type-arg
+    (unless (defined? 'symlinkat)
+      (throw 'unsupported))
+    (symlinkat (open-input-string "") (test-file) (test-symlink)))
+
+  (pass-if-exception "closed port" exception:wrong-type-arg
+    (unless (defined? 'symlinkat)
+      (throw 'unsupported))
+    (symlinkat (call-with-port (open "." O_RDONLY) identity)
+               (test-file) (test-symlink))))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]