mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-29 19:30:36 +02:00
Define a Scheme binding to ‘renameat’ when it exists.
* configure.ac: Detect if ‘renameat’ is defined. * libguile/filesys.c (scm_renameat): Define a Scheme binding to the ‘renameat’ system call. * doc/ref/posix.texi (File System): Document it. * libguile/filesys.h (scm_renameat): Make it part of the C API. * test-suite/tests/filesys.test ("rename-file-at"): New tests. Signed-off-by: Ludovic Courtès <ludo@gnu.org>
This commit is contained in:
parent
24028e75ca
commit
3a0554c60f
5 changed files with 149 additions and 1 deletions
|
@ -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 mkdirat getcwd geteuid getsid \
|
||||
symlinkat mkdirat renameat 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 \
|
||||
|
|
|
@ -895,6 +895,15 @@ Renames the file specified by @var{oldname} to @var{newname}.
|
|||
The return value is unspecified.
|
||||
@end deffn
|
||||
|
||||
@findex renameat
|
||||
@deffn {Scheme Procedure} rename-file-at olddir oldname newdir newname
|
||||
@deffnx {C Function} scm_renameat (olddir, oldname, newdir, newname)
|
||||
Like @code{rename-file}, but when @var{olddir} or @var{newdir} is true,
|
||||
resolve @var{oldname} or @var{newname} relative to the directory
|
||||
specified by the file port @var{olddir} or @var{newdir} instead of the
|
||||
current working directory.
|
||||
@end deffn
|
||||
|
||||
@deffn {Scheme Procedure} link oldpath newpath
|
||||
@deffnx {C Function} scm_link (oldpath, newpath)
|
||||
Creates a new name @var{newpath} in the file system for the
|
||||
|
|
|
@ -1408,6 +1408,40 @@ SCM_DEFINE (scm_rename, "rename-file", 2, 0, 0,
|
|||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
#ifdef HAVE_RENAMEAT
|
||||
SCM_DEFINE (scm_renameat, "rename-file-at", 4, 0, 0,
|
||||
(SCM olddir, SCM oldname, SCM newdir, SCM newname),
|
||||
"Like @code{rename-file}, but when @var{olddir} or @var{newdir}\n"
|
||||
"is true, resolve @var{oldname} or @var{newname} relative to\n"
|
||||
"the directory specified by file port @var{olddir} or\n"
|
||||
"@var{newdir} instead of the current working directory.")
|
||||
#define FUNC_NAME s_scm_renameat
|
||||
{
|
||||
int rv;
|
||||
int old_fdes, new_fdes;
|
||||
|
||||
old_fdes = AT_FDCWD;
|
||||
new_fdes = AT_FDCWD;
|
||||
|
||||
if (scm_is_true (olddir)) {
|
||||
SCM_VALIDATE_OPFPORT (SCM_ARG1, olddir);
|
||||
old_fdes = SCM_FPORT_FDES (olddir);
|
||||
}
|
||||
if (scm_is_true (newdir)) {
|
||||
SCM_VALIDATE_OPFPORT (SCM_ARG3, newdir);
|
||||
new_fdes = SCM_FPORT_FDES (newdir);
|
||||
}
|
||||
|
||||
STRING2_SYSCALL (oldname, c_oldname,
|
||||
newname, c_newname,
|
||||
rv = renameat (old_fdes, c_oldname, new_fdes, c_newname));
|
||||
scm_remember_upto_here_2 (olddir, newdir);
|
||||
if (rv != 0)
|
||||
SCM_SYSERROR;
|
||||
return SCM_UNSPECIFIED;
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
#endif
|
||||
|
||||
SCM_DEFINE (scm_delete_file, "delete-file", 1, 0, 0,
|
||||
(SCM str),
|
||||
|
|
|
@ -48,6 +48,7 @@ SCM_API SCM scm_close_fdes (SCM fd);
|
|||
SCM_API SCM scm_stat (SCM object, SCM exception_on_error);
|
||||
SCM_API SCM scm_link (SCM oldpath, SCM newpath);
|
||||
SCM_API SCM scm_rename (SCM oldname, SCM newname);
|
||||
SCM_API SCM scm_renameat (SCM olddir, SCM oldname, SCM newdir, 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);
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
(data-file-name "filesys-test-link.tmp"))
|
||||
(define (test-directory)
|
||||
(data-file-name "filesys-test-dir.tmp"))
|
||||
(define (test-directory2)
|
||||
(data-file-name "filesys-test-dir2.tmp"))
|
||||
|
||||
|
||||
;;;
|
||||
|
@ -432,3 +434,105 @@
|
|||
(mkdirat port (test-directory))
|
||||
(stat:perms (stat (test-directory))))))
|
||||
(maybe-delete-directory))
|
||||
|
||||
(with-test-prefix "rename-file-at"
|
||||
(define (skip-if-unsupported)
|
||||
(unless (defined? 'rename-file-at)
|
||||
(throw 'unsupported)))
|
||||
(pass-if-equal "current working directory" '(#f "hello")
|
||||
(skip-if-unsupported)
|
||||
;; Create a file in the test directory
|
||||
(call-with-output-file "filesys-test-a.tmp"
|
||||
(lambda (port) (display "hello" port)))
|
||||
;; Try to rename it
|
||||
(rename-file-at #f "filesys-test-a.tmp" #f "filesys-test-b.tmp")
|
||||
;; Verify it exists under the new name, and not under the old name
|
||||
(list (file-exists? "filesys-test-a.tmp")
|
||||
(call-with-input-file "filesys-test-b.tmp" get-string-all)))
|
||||
|
||||
(false-if-exception (delete-file "filesys-test-a.tmp"))
|
||||
(false-if-exception (delete-file "filesys-test-b.tmp"))
|
||||
|
||||
(pass-if-equal "two ports" '(#f "hello")
|
||||
(skip-if-unsupported)
|
||||
(mkdir (test-directory))
|
||||
(mkdir (test-directory2))
|
||||
;; Create a file in the first directory
|
||||
(call-with-output-file (in-vicinity (test-directory) "a")
|
||||
(lambda (port) (display "hello" port)))
|
||||
(let ((port1 (open (test-directory) O_RDONLY))
|
||||
(port2 (open (test-directory2) O_RDONLY)))
|
||||
;; Try to rename it
|
||||
(rename-file-at port1 "a" port2 "b")
|
||||
(close-port port1)
|
||||
(close-port port2)
|
||||
;; Verify it exists under the new name, and not under the old name
|
||||
(list (file-exists? (in-vicinity (test-directory) "a"))
|
||||
(call-with-input-file (in-vicinity (test-directory2) "b")
|
||||
get-string-all))))
|
||||
(false-if-exception (delete-file (in-vicinity (test-directory) "a")))
|
||||
(false-if-exception (delete-file (in-vicinity (test-directory2) "b")))
|
||||
(false-if-exception (rmdir (test-directory)))
|
||||
(false-if-exception (rmdir (test-directory2)))
|
||||
|
||||
(pass-if-equal "port and current working directory" '(#f "hello")
|
||||
(skip-if-unsupported)
|
||||
(mkdir (test-directory))
|
||||
;; Create a file in (test-directory)
|
||||
(call-with-output-file (in-vicinity (test-directory) "a")
|
||||
(lambda (port) (display "hello" port)))
|
||||
(let ((port (open (test-directory) O_RDONLY)))
|
||||
;; Try to rename it
|
||||
(rename-file-at port "a" #f (basename (test-file)))
|
||||
(close-port port)
|
||||
;; Verify it exists under the new name, and not under the old name.
|
||||
(list (file-exists? (in-vicinity (test-directory) "a"))
|
||||
(call-with-input-file (test-file) get-string-all))))
|
||||
(false-if-exception (delete-file (in-vicinity (test-directory) "a")))
|
||||
(false-if-exception (rmdir (test-directory)))
|
||||
(false-if-exception (delete-file (test-file)))
|
||||
|
||||
(pass-if-equal "current working directory and port" '(#f "hello")
|
||||
(skip-if-unsupported)
|
||||
(mkdir (test-directory))
|
||||
;; Create a file in the working directory
|
||||
(call-with-output-file (test-file)
|
||||
(lambda (port) (display "hello" port)))
|
||||
(let ((port (open (test-directory) O_RDONLY)))
|
||||
;; Try to rename it
|
||||
(rename-file-at #f (basename (test-file)) port "b")
|
||||
(close-port port)
|
||||
;; Verify it exists under the new name, and not under the old name.
|
||||
(list (file-exists? (test-file))
|
||||
(call-with-input-file (in-vicinity (test-directory) "b")
|
||||
get-string-all))))
|
||||
|
||||
(false-if-exception (delete-file (in-vicinity (test-directory) "b")))
|
||||
(false-if-exception (delete-file (test-file)))
|
||||
(false-if-exception (rmdir (test-directory)))
|
||||
|
||||
(pass-if-exception "not a file port (1)" exception:wrong-type-arg
|
||||
(skip-if-unsupported)
|
||||
(rename-file-at (open-input-string "") "some" #f "thing"))
|
||||
|
||||
(pass-if-exception "not a file port (2)" exception:wrong-type-arg
|
||||
(skip-if-unsupported)
|
||||
(rename-file-at #f "some" (open-input-string "") "thing"))
|
||||
|
||||
(pass-if-exception "closed port (1)" exception:wrong-type-arg
|
||||
(skip-if-unsupported)
|
||||
(rename-file-at (call-with-port (open "." O_RDONLY) identity)
|
||||
"some" #f "thing"))
|
||||
|
||||
(pass-if-exception "closed port (2)" exception:wrong-type-arg
|
||||
(skip-if-unsupported)
|
||||
(rename-file-at #f "some" (call-with-port (open "." O_RDONLY) identity)
|
||||
"thing"))
|
||||
|
||||
(pass-if-exception "not a string (1)" exception:wrong-type-arg
|
||||
(skip-if-unsupported)
|
||||
(rename-file-at #f 'what #f "thing"))
|
||||
|
||||
(pass-if-exception "not a string (2)" exception:wrong-type-arg
|
||||
(skip-if-unsupported)
|
||||
(rename-file-at #f "some" #f 'what)))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue