sftp.scm 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. ;;; sftp.scm -- Procedures for working with SFTP.
  2. ;; Copyright (C) 2015 Artyom V. Poptsov <poptsov.artyom@gmail.com>
  3. ;;
  4. ;; This file is a part of Guile-SSH.
  5. ;;
  6. ;; Guile-SSH is free software: you can redistribute it and/or
  7. ;; modify it under the terms of the GNU General Public License as
  8. ;; published by the Free Software Foundation, either version 3 of the
  9. ;; License, or (at your option) any later version.
  10. ;;
  11. ;; Guile-SSH is distributed in the hope that it will be useful, but
  12. ;; WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. ;; General Public License for more details.
  15. ;;
  16. ;; You should have received a copy of the GNU General Public License
  17. ;; along with Guile-SSH. If not, see <http://www.gnu.org/licenses/>.
  18. ;;; Commentary:
  19. ;; This module contains SFTP API procedures.
  20. ;;
  21. ;; The module exports:
  22. ;; sftp-session?
  23. ;; make-sftp-session
  24. ;; sftp-init
  25. ;; sftp-get-session
  26. ;; sftp-get-error
  27. ;; sftp-mkdir
  28. ;; sftp-rmdir
  29. ;; sftp-mv
  30. ;; sftp-symlink
  31. ;; sftp-readlink
  32. ;; sftp-chmod
  33. ;; sftp-unlink
  34. ;; %make-sftp-session
  35. ;; %sftp-init
  36. ;; sftp-open
  37. ;; sftp-file?
  38. ;; call-with-remote-input-file
  39. ;; call-with-remote-output-file
  40. ;; with-input-from-remote-file
  41. ;; with-output-to-remote-file
  42. ;;
  43. ;; See the Info documentation for the detailed description of these
  44. ;; procedures.
  45. ;;; Code:
  46. (define-module (ssh sftp)
  47. #:use-module (ice-9 receive)
  48. #:export (sftp-session?
  49. make-sftp-session
  50. sftp-init
  51. sftp-get-session
  52. sftp-get-error
  53. sftp-mkdir
  54. sftp-rmdir
  55. sftp-mv
  56. sftp-symlink
  57. sftp-readlink
  58. sftp-chmod
  59. sftp-unlink
  60. ;; Low-level SFTP session procedures
  61. %make-sftp-session
  62. %sftp-init
  63. ;; File ports
  64. sftp-open
  65. sftp-file?
  66. ;; High-level operations on remote files
  67. call-with-remote-input-file
  68. call-with-remote-output-file
  69. with-input-from-remote-file
  70. with-output-to-remote-file))
  71. ;;; Low-level SFTP session procedures.
  72. (define (%make-sftp-session ssh-session)
  73. "Make a new SFTP session using an SSH-SESSION without initialization of the
  74. session with a server. Throw 'guile-ssh-error' exception on an error."
  75. (%gssh-make-sftp-session ssh-session))
  76. (define (%sftp-init sftp-session)
  77. "Initialize a SFTP-SESSION with the server. Throw 'guile-ssh-error'
  78. exception on an error, return value is undefined."
  79. (%gssh-sftp-init sftp-session))
  80. ;;; Main SFTP session API.
  81. (define (make-sftp-session ssh-session)
  82. "Make a new SFTP session using an SSH-SESSION, initialize the session with a
  83. server. Return initialized SFTP session or throw 'guile-ssh-error' exception
  84. on an error"
  85. (let ((sftp-session (%gssh-make-sftp-session ssh-session)))
  86. (%gssh-sftp-init sftp-session)
  87. sftp-session))
  88. (define (sftp-session? x)
  89. "Return #t if X is a SFTP session, #f otherwise."
  90. (%gssh-sftp-session? x))
  91. (define (sftp-get-session sftp-session)
  92. "Get the parent SSH session for a SFTP-SESSION."
  93. (%gssh-sftp-get-session sftp-session))
  94. (define (sftp-get-error sftp-session)
  95. "Get the last SFTP error from a SFTP-SESSION. Return the error name as a symbol,
  96. or throw 'guile-ssh-error' on if an error occured in the procedure itself."
  97. (%gssh-sftp-get-error sftp-session))
  98. (define* (sftp-mkdir sftp-session dirname #:optional (mode #o777))
  99. "Create a directory DIRNAME using a SFTP-SESSION with permissions specified
  100. by a MODE. The permissions of the created file are (MODE & ~umask). If the
  101. MODE is omitted, #o777 is used."
  102. (%gssh-sftp-mkdir sftp-session dirname mode))
  103. (define (sftp-rmdir sftp-session dirname)
  104. "Remove a directory DIRNAME. Throw 'guile-ssh-error' on an error. Return
  105. value is undefined."
  106. (%gssh-sftp-rmdir sftp-session dirname))
  107. (define (sftp-mv sftp-session source dest)
  108. "Move or rename a file SOURCE into a DEST. Throw 'guile-ssh-error' on an
  109. error. Return value is undefined."
  110. (%gssh-sftp-mv sftp-session source dest))
  111. (define (sftp-symlink sftp-session target dest)
  112. "Create a symbolic link to a TARGET in a DEST. Throw 'guile-ssh-error' on an
  113. error. Return value is undefined."
  114. (%gssh-sftp-symlink sftp-session target dest))
  115. (define (sftp-readlink sftp-session path)
  116. "Read the value of a symbolic link pointed by a PATH. Return the value or
  117. '#f' on an error."
  118. (%gssh-sftp-readlink sftp-session path))
  119. (define* (sftp-chmod sftp-session filename mode)
  120. "Change permissions of a FILENAME. Permissions are set to 'MODE & ~umask'.
  121. Throw 'guile-ssh-error' on an error. Return value is undefined."
  122. (%gssh-sftp-chmod sftp-session filename mode))
  123. (define (sftp-unlink sftp-session filename)
  124. "Unlink (delete) a FILENAME. Throw 'guile-ssh-error' on an error. Return
  125. value is undefined."
  126. (%gssh-sftp-unlink sftp-session filename))
  127. ;;; SFTP file API.
  128. (define* (sftp-open sftp-session filename flags #:optional (mode #o666))
  129. "Open a FILENAME with permissions specified by MODE, return an open file
  130. port. Permissions are set to 'MODE & ~umask'; the default MODE is #o666.
  131. Throw 'guile-ssh-error' on an error."
  132. (%gssh-sftp-open sftp-session filename flags mode))
  133. (define (sftp-file? x)
  134. "Return #t if X is an SFTP file port, #f otherwise."
  135. (%gssh-sftp-file? x))
  136. ;;; High-Level operations on remote files.
  137. ;; Those procedures are partly based on GNU Guile's 'r4rs.scm'; the goal is to
  138. ;; provide a convenient API similar to Guile I/O API.
  139. (define (with-input-from-port port thunk)
  140. (let ((swaports (lambda () (set! port (set-current-input-port port)))))
  141. (dynamic-wind swaports thunk swaports)))
  142. (define (with-output-to-port port thunk)
  143. (let ((swaports (lambda () (set! port (set-current-output-port port)))))
  144. (dynamic-wind swaports thunk swaports)))
  145. (define (call-with-remote-input-file sftp-session filename proc)
  146. "Call a PROC with a remote file port opened for input using an SFTP-SESSION.
  147. PROC should be a procedure of one argument, FILENAME should be a string naming
  148. a file. The behaviour is unspecified if a file already exists.
  149. The procedure calls PROC with one argument: the port obtained by opening the
  150. named remote file for input.
  151. If the procedure returns, then the port is closed automatically and the values
  152. yielded by the procedure are returned. If the procedure does not return, then
  153. the port will not be closed automatically unless it is possible to prove that
  154. the port will never again be used for a read or write operation."
  155. (let ((input-file (sftp-open sftp-session filename O_RDONLY)))
  156. (call-with-values
  157. (lambda () (proc input-file))
  158. (lambda vals
  159. (close-port input-file)
  160. (apply values vals)))))
  161. (define (call-with-remote-output-file sftp-session filename proc)
  162. "Call a PROC with a remote file port opened for output using an
  163. SFTP-SESSION. PROC should be a procedure of one argument, FILENAME should be
  164. a string naming a file. The behaviour is unspecified if a file already
  165. exists.
  166. The procedure calls PROC with one argument: the port obtained by opening the
  167. named remote file for output.
  168. If the procedure returns, then the port is closed automatically and the values
  169. yielded by the procedure are returned. If the procedure does not return, then
  170. the port will not be closed automatically unless it is possible to prove that
  171. the port will never again be used for a read or write operation."
  172. (let ((output-file-port (sftp-open sftp-session filename
  173. (logior O_WRONLY O_CREAT))))
  174. (call-with-values
  175. (lambda () (proc output-file-port))
  176. (lambda vals
  177. (close-port output-file-port)
  178. (apply values vals)))))
  179. (define (with-input-from-remote-file sftp-session filename thunk)
  180. "THUNK must be a procedure of no arguments, and FILENAME must be a string
  181. naming a file. The file must already exist. The file is opened for input, an
  182. input port connected to it is made the default value returned by
  183. 'current-input-port', and the THUNK is called with no arguments. When the
  184. THUNK returns, the port is closed and the previous default is restored.
  185. Returns the values yielded by THUNK. If an escape procedure is used to escape
  186. from the continuation of these procedures, their behavior is implementation
  187. dependent."
  188. (call-with-remote-input-file sftp-session filename
  189. (lambda (p) (with-input-from-port p thunk))))
  190. (define (with-output-to-remote-file sftp-session filename thunk)
  191. "THUNK must be a procedure of no arguments, and FILENAME must be a string
  192. naming a file. The effect is unspecified if the file already exists. The
  193. file is opened for output, an output port connected to it is made the default
  194. value returned by 'current-output-port', and the THUNK is called with no
  195. arguments. When the THUNK returns, the port is closed and the previous
  196. default is restored. Returns the values yielded by THUNK. If an escape
  197. procedure is used to escape from the continuation of these procedures, their
  198. behavior is implementation dependent."
  199. (call-with-remote-output-file sftp-session filename
  200. (lambda (p) (with-output-to-port p thunk))))
  201. ;;; Load libraries.
  202. (load-extension "libguile-ssh" "init_sftp_session")
  203. (load-extension "libguile-ssh" "init_sftp_file")
  204. ;;; sftp-session.scm ends here.