diff options
author | Maxime Devos <maximedevos@telenet.be> | 2021-11-16 11:06:25 +0000 |
---|---|---|
committer | Ludovic Courtès <ludo@gnu.org> | 2022-10-21 17:39:38 +0200 |
commit | 30247dc414fb38329f580b1d41abbe202285adbe (patch) | |
tree | 65ba8b4cbd3ef778c6b58fefabfe553bb53b38e0 /test-suite | |
parent | 273bfe7510da8ab740e65df11b72d9bb801885f3 (diff) | |
download | guile-30247dc414fb38329f580b1d41abbe202285adbe.tar.gz |
Allow file ports in ‘readlink’.
* configure.ac: Detect whether ‘readlinkat’ is defined.
* libguile/filesys.c (scm_readlink): Support file ports
when ‘readlinkat’ exists.
(scm_init_filesys): Provide ‘chdir-ports’ when it exists.
* doc/ref/posix.texi (File System): Document it.
* test-suite/tests/filesys.test ("readlink"): Test it.
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
Diffstat (limited to 'test-suite')
-rw-r--r-- | test-suite/tests/filesys.test | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/test-suite/tests/filesys.test b/test-suite/tests/filesys.test index 6b09a2ba0..7feb3492f 100644 --- a/test-suite/tests/filesys.test +++ b/test-suite/tests/filesys.test @@ -306,3 +306,64 @@ (pass-if-exception "non-file port" exception:wrong-type-arg (chdir (open-input-string "")))) + +(with-test-prefix "readlink" + (false-if-exception (delete-file (test-symlink))) + (false-if-exception (delete-file (test-file))) + (call-with-output-file (test-file) + (lambda (port) + (display "hello" port))) + (if (not (false-if-exception + (begin (symlink (test-file) (test-symlink)) #t))) + (display "cannot create symlink, some readlink tests skipped\n") + (let () + (pass-if-equal "file name of symlink" (test-file) + (readlink (test-symlink))) + + (pass-if-equal "port representing a symlink" (test-file) + (let () + (unless (and (provided? 'readlink-port) + (defined? 'O_NOFOLLOW) + (defined? 'O_PATH) + (not (= 0 O_NOFOLLOW)) + (not (= 0 O_PATH))) + (throw 'unsupported)) + (define port (open (test-symlink) (logior O_NOFOLLOW O_PATH))) + (define points-to (false-if-exception (readlink port))) + (close-port port) + points-to)) + + (pass-if-exception "not a port or file name" exception:wrong-type-arg + (readlink '(stuff))))) + + (pass-if-equal "port representing a regular file" EINVAL + (call-with-input-file (test-file) + (lambda (port) + (unless (provided? 'readlink-port) + (throw 'unsupported)) + (catch 'system-error + (lambda () + (readlink port) + (close-port port) ; should be unreachable + #f) + (lambda args + (close-port port) + ;; At least Linux 5.10.46 returns ENOENT instead of EINVAL. + ;; Possibly surprising, but it is documented in some man + ;; pages and it doesn't appear to be an accident: + ;; <https://elixir.bootlin.com/linux/v5.10.46/source/fs/stat.c#L419>. + (define error (system-error-errno args)) + (if (= error ENOENT) + EINVAL + error)))))) + + (pass-if-exception "non-file port" exception:wrong-type-arg + (readlink (open-input-string ""))) + + (pass-if-exception "closed port" exception:wrong-type-arg + (let ((port (open-file (test-file) "r"))) + (close-port port) + (readlink port))) + + (false-if-exception (delete-file (test-symlink))) + (false-if-exception (delete-file (test-file)))) |