diff options
author | Maxime Devos <maximedevos@telenet.be> | 2021-11-16 11:06:36 +0000 |
---|---|---|
committer | Ludovic Courtès <ludo@gnu.org> | 2022-10-21 17:42:20 +0200 |
commit | c8b81ffb3492d1f1e7fc6886809108f31ac55794 (patch) | |
tree | 8bea11430518da4200975f0e1d9eb86f29ab8019 /libguile | |
parent | cf255dd3a4f01da5e88c6da3738e7745ad8b9594 (diff) | |
download | guile-c8b81ffb3492d1f1e7fc6886809108f31ac55794.tar.gz |
Define Scheme bindings to ‘openat’ when available.
* configure.ac: Detect if ‘openat’ is defined.
* libguile/filesys.c
(flags_to_mode): Extract from ...
(scm_mode): ... here.
(scm_open_fdes_at, scm_openat): Define the Scheme bindings.
* libguile/filesys.h (scm_open_fdes_at, scm_openat): Make them part
of the API.
* doc/ref/posix.texi (File System): Document them.
* test-suite/tests/filesys.test ("openat"): Test ‘openat’.
* libguile/syscalls.h (openat_or_openat64): Decide between ‘openat’
and ‘openat64’.
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
Diffstat (limited to 'libguile')
-rw-r--r-- | libguile/filesys.c | 96 | ||||
-rw-r--r-- | libguile/filesys.h | 2 | ||||
-rw-r--r-- | libguile/syscalls.h | 1 |
3 files changed, 79 insertions, 20 deletions
diff --git a/libguile/filesys.c b/libguile/filesys.c index 6fa641d16..1f0bba556 100644 --- a/libguile/filesys.c +++ b/libguile/filesys.c @@ -236,6 +236,60 @@ SCM_DEFINE (scm_open_fdes, "open-fdes", 2, 1, 0, } #undef FUNC_NAME +#ifdef HAVE_OPENAT +SCM_DEFINE (scm_open_fdes_at, "open-fdes-at", 3, 1, 0, + (SCM dir, SCM path, SCM flags, SCM mode), + "Similar to @code{openat}, but return a file descriptor instead\n" + "of a port.") +#define FUNC_NAME s_scm_open_fdes_at +{ + int dir_fdes; + int fd; + int iflags; + int imode; + + iflags = SCM_NUM2INT (SCM_ARG2, flags); + imode = SCM_NUM2INT_DEF (3, mode, 0666); + SCM_VALIDATE_OPFPORT (SCM_ARG1, dir); + dir_fdes = SCM_FPORT_FDES (dir); + + STRING_SYSCALL (path, c_path, + fd = openat_or_openat64 (dir_fdes, c_path, iflags, imode)); + scm_remember_upto_here_1 (dir); + if (fd == -1) + SCM_SYSERROR; + return scm_from_int (fd); +} +#undef FUNC_NAME +#endif /* HAVE_OPENAT */ + +/* A helper function for converting some open flags to + what scm_fdes_to_port expects. */ +static char * +flags_to_mode (int iflags) +{ + if ((iflags & O_RDWR) == O_RDWR) + { + /* Opened read-write. */ + if (iflags & O_APPEND) + return "a+"; + else if (iflags & O_CREAT) + return "w+"; + else + return "r+"; + } + else + { + /* Opened read-only or write-only. */ + if (iflags & O_APPEND) + return "a"; + else if (iflags & O_WRONLY) + return "w"; + else + return "r"; + } +} + SCM_DEFINE (scm_open, "open", 2, 1, 0, (SCM path, SCM flags, SCM mode), "Open the file named by @var{path} for reading and/or writing.\n" @@ -272,31 +326,33 @@ SCM_DEFINE (scm_open, "open", 2, 1, 0, fd = scm_to_int (scm_open_fdes (path, flags, mode)); iflags = SCM_NUM2INT (2, flags); - if ((iflags & O_RDWR) == O_RDWR) - { - /* Opened read-write. */ - if (iflags & O_APPEND) - port_mode = "a+"; - else if (iflags & O_CREAT) - port_mode = "w+"; - else - port_mode = "r+"; - } - else - { - /* Opened read-only or write-only. */ - if (iflags & O_APPEND) - port_mode = "a"; - else if (iflags & O_WRONLY) - port_mode = "w"; - else - port_mode = "r"; - } + port_mode = (char *) flags_to_mode (iflags); + newpt = scm_fdes_to_port (fd, port_mode, path); + return newpt; +} +#undef FUNC_NAME +#ifdef HAVE_OPENAT +SCM_DEFINE (scm_openat, "openat", 3, 1, 0, + (SCM dir, SCM path, SCM flags, SCM mode), + "Similar to @code{open}, but resolve the file name @var{path}\n" + "relative to the directory referred to by the file port @var{dir}\n" + "instead.") +#define FUNC_NAME s_scm_openat +{ + SCM newpt; + char *port_mode; + int fd; + int iflags; + + iflags = SCM_NUM2INT (2, flags); + port_mode = (char *) flags_to_mode (iflags); + fd = scm_to_int (scm_open_fdes_at (dir, path, flags, mode)); newpt = scm_fdes_to_port (fd, port_mode, path); return newpt; } #undef FUNC_NAME +#endif /* HAVE_OPENAT */ SCM_DEFINE (scm_close, "close", 1, 0, 0, (SCM fd_or_port), diff --git a/libguile/filesys.h b/libguile/filesys.h index 8af0f989a..1ce50d30e 100644 --- a/libguile/filesys.h +++ b/libguile/filesys.h @@ -44,7 +44,9 @@ SCM_API SCM scm_chmod (SCM object, SCM mode); SCM_API SCM scm_chmodat (SCM dir, SCM pathname, SCM mode, SCM flags); SCM_API SCM scm_umask (SCM mode); SCM_API SCM scm_open_fdes (SCM path, SCM flags, SCM mode); +SCM_API SCM scm_open_fdes_at (SCM dir, SCM path, SCM flags, SCM mode); SCM_API SCM scm_open (SCM path, SCM flags, SCM mode); +SCM_API SCM scm_openat (SCM dir, SCM path, SCM flags, SCM mode); SCM_API SCM scm_close (SCM fd_or_port); SCM_API SCM scm_close_fdes (SCM fd); SCM_API SCM scm_stat (SCM object, SCM exception_on_error); diff --git a/libguile/syscalls.h b/libguile/syscalls.h index 37d532e60..6f4061138 100644 --- a/libguile/syscalls.h +++ b/libguile/syscalls.h @@ -58,6 +58,7 @@ #define lstat_or_lstat64 CHOOSE_LARGEFILE(lstat,lstat64) #define off_t_or_off64_t CHOOSE_LARGEFILE(off_t,off64_t) #define open_or_open64 CHOOSE_LARGEFILE(open,open64) +#define openat_or_openat64 CHOOSE_LARGEFILE(openat,openat64) #define readdir_or_readdir64 CHOOSE_LARGEFILE(readdir,readdir64) #if SCM_HAVE_READDIR64_R == 1 # define readdir_r_or_readdir64_r CHOOSE_LARGEFILE(readdir_r,readdir64_r) |