Mario Domenech Goulart <mario.goul...@gmail.com> writes:
> Maybe "readlink -f" ?

OK, Peter found that even that is not portable so I changed the test
itself to do the path canonicalization. Turns out that while the posix
unit's read-symbolic-link has a CANONICALIZE option it doesn't quite
behave like the readlink(1) program. So I went ahead and adapted its
behavior to match that. I also noticed that the types.db entry for
read-symbolic-link did not include that optional argument so I took it
as an opportunity to fix this, as well.

Moritz

>From e98ed45bcfeca57d8d0a293da4ee335ea8d1ff4b Mon Sep 17 00:00:00 2001
From: Moritz Heidkamp <mor...@twoticketsplease.de>
Date: Sat, 25 May 2013 17:08:09 +0200
Subject: [PATCH 1/3] Improve read-symbolic-link canonicalization

Passing #t for the CANONICALIZE option of read-symbolic-link now behaves
like the --canonicalize option of readlink(1), i.e. it recursively
follows every symlink in every component of the given path. When called
like this, read-symbolic-link like readlink(1) now verifies that all
components exist.
---
 posixunix.scm | 43 +++++++++++++++++++++++++++++--------------
 1 file changed, 29 insertions(+), 14 deletions(-)

diff --git a/posixunix.scm b/posixunix.scm
index a2776da..6cdb4ef 100644
--- a/posixunix.scm
+++ b/posixunix.scm
@@ -1241,21 +1241,36 @@ EOF
 
 (define-foreign-variable _filename_max int "FILENAME_MAX")
 
-(define read-symbolic-link
+(define ##sys#read-symbolic-link
   (let ((buf (make-string (fx+ _filename_max 1))))
-    (lambda (fname #!optional canonicalize)
-      (##sys#check-string fname 'read-symbolic-link)
-      (let ((len (##core#inline 
-		  "C_do_readlink"
-		  (##sys#make-c-string (##sys#expand-home-path fname) 'read-symbolic-link) buf)))
-	(if (fx< len 0)
-	    (if canonicalize
-		fname
-		(posix-error #:file-error 'read-symbolic-link "cannot read symbolic link" fname))
-	    (let ((pathname (substring buf 0 len)))
-	      (if (and canonicalize (symbolic-link? pathname))
-		  (read-symbolic-link pathname 'canonicalize)
-		  pathname ) ) ) ) ) ) )
+    (lambda (fname location)
+      (let ((len (##core#inline
+                  "C_do_readlink"
+                  (##sys#make-c-string fname location) buf)))
+        (if (fx< len 0)
+            (posix-error #:file-error location "cannot read symbolic link" fname)
+            (substring buf 0 len))))))
+
+(define (read-symbolic-link fname #!optional canonicalize)
+  (##sys#check-string fname 'read-symbolic-link)
+  (let ((fname (##sys#expand-home-path fname)))
+    (if canonicalize
+        (receive (base-origin base-directory directory-components) (decompose-directory fname)
+          (let loop ((components directory-components)
+                     (result (string-append (or base-origin "") (or base-directory ""))))
+            (if (null? components)
+                result
+                (let ((pathname (make-pathname result (car components))))
+                  (if (file-exists? pathname)
+                      (loop (cdr components)
+                            (if (symbolic-link? pathname)
+                                (let ((target (##sys#read-symbolic-link pathname 'read-symbolic-link)))
+                                  (if (absolute-pathname? target)
+                                      link
+                                      (make-pathname result target)))
+                                pathname))
+                      (##sys#signal-hook #:file-error 'read-symbolic-link "could not canonicalize path with symbolic links, component does not exist" pathname))))))
+        (##sys#read-symbolic-link fname 'read-symbolic-link))))
 
 (define file-link
   (let ([link (foreign-lambda int "link" c-string c-string)])
-- 
1.8.2.3

>From a7de20ed3d344f9fcaa981fd746091624869be60 Mon Sep 17 00:00:00 2001
From: Moritz Heidkamp <mor...@twoticketsplease.de>
Date: Sat, 25 May 2013 17:27:55 +0200
Subject: [PATCH 2/3] Fix read-symbolic-link types.db entry

The optional CANONICALIZE argument was missing.
---
 types.db | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/types.db b/types.db
index 01d84e2..c061092 100644
--- a/types.db
+++ b/types.db
@@ -1765,7 +1765,7 @@
 (prot/none fixnum)
 (prot/read fixnum)
 (prot/write fixnum)
-(read-symbolic-link (#(procedure #:clean #:enforce) read-symbolic-link (string) string))
+(read-symbolic-link (#(procedure #:clean #:enforce) read-symbolic-link (string #!optional boolean) string))
 (regular-file? (#(procedure #:clean #:enforce) regular-file? ((or string fixnum)) boolean))
 (seconds->local-time (#(procedure #:clean #:enforce) seconds->local-time (#!optional number) (vector fixnum fixnum fixnum fixnum fixnum fixnum fixnum fixnum boolean fixnum)))
 (seconds->string (#(procedure #:clean #:enforce) seconds->string (#!optional number) string))
-- 
1.8.2.3

>From a3cea67616c7d50092e20374ebc47176c7fee660 Mon Sep 17 00:00:00 2001
From: Moritz Heidkamp <mor...@twoticketsplease.de>
Date: Sat, 25 May 2013 17:31:12 +0200
Subject: [PATCH 3/3] Make tests work from symlinked paths

The private repository path tests didn't work when run from inside a
path containing symlinks because runtests.sh didn't expand symlinks
while the -private-repository mechanism does. This lead the test
assertion which compares the two paths to fail.
---
 tests/private-repository-test.scm | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/tests/private-repository-test.scm b/tests/private-repository-test.scm
index 9ad524c..6a4f5c7 100644
--- a/tests/private-repository-test.scm
+++ b/tests/private-repository-test.scm
@@ -1,10 +1,15 @@
 ;;;; private-repository-test.scm
 
 
-(use files)
+(use files posix)
 
-(define repo (normalize-pathname (repository-path)))
-(define dir (normalize-pathname (car (command-line-arguments))))
+(define read-symbolic-link*
+  (cond-expand
+   ((and windows (not cygwin)) (lambda (x) x))
+   (else read-symbolic-link)))
+
+(define repo (normalize-pathname (read-symbolic-link* (repository-path) #t)))
+(define dir (normalize-pathname (read-symbolic-link* (car (command-line-arguments)) #t)))
 
 (print (list dir repo))
 
-- 
1.8.2.3

_______________________________________________
Chicken-hackers mailing list
Chicken-hackers@nongnu.org
https://lists.nongnu.org/mailman/listinfo/chicken-hackers

Reply via email to