summary refs log tree commit diff
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2013-04-27 16:25:54 +0200
committerLudovic Courtès <ludo@gnu.org>2013-04-27 16:25:54 +0200
commit87dfd45594e6e1f6d4ab790412b4fe0a607f30cd (patch)
treeb71823d4ed3de7a3ad84774141417a5edb313859
parentaccf7a373eb8040c3df5ba2f9512899805f5da57 (diff)
downloadguix-87dfd45594e6e1f6d4ab790412b4fe0a607f30cd.tar.gz
ftp-client: `ftp-chdir' changes one step at a time.
* guix/ftp-client.scm (%char-set:not-slash): New variable.
  (ftp-chdir): Add docstring.  Change to DIR one step at a time.
  (ftp-retr): Fix indentation.
-rw-r--r--guix/ftp-client.scm35
1 files changed, 24 insertions, 11 deletions
diff --git a/guix/ftp-client.scm b/guix/ftp-client.scm
index e3bacc3720..ba3201fdab 100644
--- a/guix/ftp-client.scm
+++ b/guix/ftp-client.scm
@@ -130,9 +130,22 @@ or a TCP port number), and return it."
 (define (ftp-close conn)
   (close (ftp-connection-socket conn)))
 
+(define %char-set:not-slash
+  (char-set-complement (char-set #\/)))
+
 (define (ftp-chdir conn dir)
-  (%ftp-command (string-append "CWD " dir) 250
-                (ftp-connection-socket conn)))
+  "Change to directory DIR."
+
+  ;; On ftp.gnupg.org, "PASV" right after "CWD /gcrypt/gnupg" hangs.  Doing
+  ;; CWD in two steps works, so just do this.
+  (let ((components (string-tokenize dir %char-set:not-slash)))
+    (fold (lambda (dir result)
+            (%ftp-command (string-append "CWD " dir) 250
+                          (ftp-connection-socket conn)))
+          #f
+          (if (string-prefix? "/" dir)
+              (cons "/" components)
+              components))))
 
 (define (ftp-size conn file)
   "Return the size in bytes of FILE."
@@ -238,15 +251,15 @@ must be closed before CONN can be used for other purposes."
                                    (rec (read! bv start count)
                                         (match (get-bytevector-n! s bv
                                                                   start count)
-                                       ((? eof-object?) 0)
-                                       (0
-                                        ;; Nothing available yet, so try
-                                        ;; again.  This is important because
-                                        ;; the return value of `read!' makes
-                                        ;; it impossible to distinguish
-                                        ;; between "not yet" and "EOF".
-                                        (read! bv start count))
-                                       (read read)))
+                                          ((? eof-object?) 0)
+                                          (0
+                                           ;; Nothing available yet, so try
+                                           ;; again.  This is important because
+                                           ;; the return value of `read!' makes
+                                           ;; it impossible to distinguish
+                                           ;; between "not yet" and "EOF".
+                                           (read! bv start count))
+                                          (read read)))
                                    #f #f          ; no get/set position
                                    terminate)))