1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-04-29 19:30:36 +02:00

Define bindings to ‘mkdirat’ when the C function exists.

* configure.ac: Detect if ‘mkdirat’ exists.
* libguile/filesys.c (scm_mkdirat): Define the Scheme binding.
* doc/ref/posix.texi (File System): Document it.

Signed-off-by: Ludovic Courtès <ludo@gnu.org>
This commit is contained in:
Maxime Devos 2021-11-16 11:06:28 +00:00 committed by Ludovic Courtès
parent 6c350b6094
commit 58ddd5c7bc
5 changed files with 71 additions and 1 deletions

View file

@ -517,7 +517,7 @@ AC_CHECK_HEADERS([crt_externs.h])
#
AC_CHECK_FUNCS([DINFINITY DQNAN cexp chsize clog clog10 ctermid \
fesetround ftime ftruncate fchown fchmod fchdir readlinkat \
symlinkat getcwd geteuid getsid \
symlinkat mkdirat getcwd geteuid getsid \
gettimeofday getuid getgid gmtime_r ioctl lstat mkdir mkdtemp mknod \
nice readlink rmdir setegid seteuid \
setuid setgid setpgid setsid sigaction siginterrupt stat64 \

View file

@ -924,6 +924,12 @@ Otherwise they are set to the value specified with @var{mode}.
The return value is unspecified.
@end deffn
@deffn {Scheme Procedure} mkdirat dir path [mode]
@deffnx {C Function} scm_mkdirat (dir, path, mode)
Like @code{mkdir}, but resolve @var{path} relative to the directory
referred to by the file port @var{dir} instead.
@end deffn
@deffn {Scheme Procedure} rmdir path
@deffnx {C Function} scm_rmdir (path)
Remove the existing directory named by @var{path}. The directory must

View file

@ -1351,6 +1351,31 @@ SCM_DEFINE (scm_mkdir, "mkdir", 1, 1, 0,
}
#undef FUNC_NAME
#ifdef HAVE_MKDIRAT
SCM_DEFINE (scm_mkdirat, "mkdirat", 2, 1, 0,
(SCM dir, SCM path, SCM mode),
"Like @code{mkdir}, but resolve @var{path} relative to the directory\n"
"referred to by the file port @var{dir} instead.")
#define FUNC_NAME s_scm_mkdirat
{
int rv;
int dir_fdes;
mode_t c_mode;
c_mode = SCM_UNBNDP (mode) ? 0777 : scm_to_uint (mode);
SCM_VALIDATE_OPFPORT (SCM_ARG1, dir);
dir_fdes = SCM_FPORT_FDES (dir);
STRING_SYSCALL (path, c_path, rv = mkdirat (dir_fdes, c_path, c_mode));
if (rv != 0)
SCM_SYSERROR;
scm_remember_upto_here_1 (dir);
return SCM_UNSPECIFIED;
}
#undef FUNC_NAME
#endif
SCM_DEFINE (scm_rmdir, "rmdir", 1, 0, 0,
(SCM path),
"Remove the existing directory named by @var{path}. The directory must\n"

View file

@ -50,6 +50,7 @@ SCM_API SCM scm_link (SCM oldpath, SCM newpath);
SCM_API SCM scm_rename (SCM oldname, SCM newname);
SCM_API SCM scm_delete_file (SCM str);
SCM_API SCM scm_mkdir (SCM path, SCM mode);
SCM_API SCM scm_mkdirat (SCM dir, SCM path, SCM mode);
SCM_API SCM scm_rmdir (SCM path);
SCM_API SCM scm_directory_stream_p (SCM obj);
SCM_API SCM scm_opendir (SCM dirname);

View file

@ -29,6 +29,8 @@
(data-file-name "filesys-test.tmp"))
(define (test-symlink)
(data-file-name "filesys-test-link.tmp"))
(define (test-directory)
(data-file-name "filesys-test-dir.tmp"))
;;;
@ -394,3 +396,39 @@
(throw 'unsupported))
(symlinkat (call-with-port (open "." O_RDONLY) identity)
(test-file) (test-symlink))))
(with-test-prefix "mkdirat"
(define (skip-if-unsupported)
(unless (defined? 'mkdirat)
(throw 'unsupported)))
(define (maybe-delete-directory)
(when (file-exists? (test-directory))
(rmdir (test-directory))))
(maybe-delete-directory)
(pass-if-equal "create" 'directory
(skip-if-unsupported)
(call-with-port
(open "." O_RDONLY)
(lambda (port)
(mkdirat port (test-directory))
(stat:type (stat (test-directory))))))
(maybe-delete-directory)
(pass-if-equal "explicit perms" (logand #o111 (lognot (umask)))
(skip-if-unsupported)
(call-with-port
(open "." O_RDONLY)
(lambda (port)
(mkdirat port (test-directory) #o111)
(stat:perms (stat (test-directory))))))
(maybe-delete-directory)
(pass-if-equal "create, implicit perms" (logand #o777 (lognot (umask)))
(skip-if-unsupported)
(call-with-port
(open "." O_RDONLY)
(lambda (port)
(mkdirat port (test-directory))
(stat:perms (stat (test-directory))))))
(maybe-delete-directory))