From 3820d7bd043dfead88c1379b24639e258af1bda4 Mon Sep 17 00:00:00 2001 From: Eitaro Fukamachi Date: Wed, 9 Oct 2024 08:39:22 +0000 Subject: [PATCH 1/3] Fix SFTP file modes to be octets. --- src/types.lisp | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/types.lisp b/src/types.lisp index 19408b7..46cfbc8 100644 --- a/src/types.lisp +++ b/src/types.lisp @@ -219,22 +219,22 @@ (:excl #x20)) (defbitfield (sftp-modes :long) - (:named-pipe #x10000) - (:character-special #x20000) - (:directory #x40000) - (:block-special #x60000) - (:regular #x100000) - (:symbolic-link #x120000) - (:socket #x140000) - (:user-read #x400) - (:user-write #x200) - (:user-execute #x100) - (:group-read #x40) - (:group-write #x20) - (:group-execute #x10) - (:other-read #x4) - (:other-write #x2) - (:other-execute #x1)) + (:named-pipe #o10000) + (:character-special #o20000) + (:directory #o40000) + (:block-special #o60000) + (:regular #o100000) + (:symbolic-link #o120000) + (:socket #o140000) + (:user-read #o400) + (:user-write #o200) + (:user-execute #o100) + (:group-read #o40) + (:group-write #o20) + (:group-execute #o10) + (:other-read #o4) + (:other-write #o2) + (:other-execute #o1)) (defcenum (sftp-error-code :unsigned-long) (:ok 0) From 36547fef0d5a3c6e195ef142ae36f18dd7005c82 Mon Sep 17 00:00:00 2001 From: Eitaro Fukamachi Date: Wed, 9 Oct 2024 08:42:04 +0000 Subject: [PATCH 2/3] Export `sftp-get` and `sftp-delete`. --- src/package.lisp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/package.lisp b/src/package.lisp index 6159af8..4251ad8 100644 --- a/src/package.lisp +++ b/src/package.lisp @@ -53,6 +53,8 @@ ;; SFTP :sftp-list-directory + :sftp-get + :sftp-delete ;; STREAMS API // BLOCKING From 716ccf164da4016a65b5d55e101c053a8c6ec54e Mon Sep 17 00:00:00 2001 From: Eitaro Fukamachi Date: Wed, 9 Oct 2024 08:42:25 +0000 Subject: [PATCH 3/3] Add `sftp-put` for writing a file via SFTP. --- src/package.lisp | 1 + src/sftp.lisp | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/package.lisp b/src/package.lisp index 4251ad8..0c6251b 100644 --- a/src/package.lisp +++ b/src/package.lisp @@ -55,6 +55,7 @@ :sftp-list-directory :sftp-get :sftp-delete + :sftp-put ;; STREAMS API // BLOCKING diff --git a/src/sftp.lisp b/src/sftp.lisp index 54ca974..93e9ff7 100644 --- a/src/sftp.lisp +++ b/src/sftp.lisp @@ -83,3 +83,21 @@ It is possible to combine `MAXFILES' and `EXTENSIONS' (retrieve 5 files with ext (ssh2.debug "Trying to delete remote file ~A" remote-path) (let ((result (libssh2-sftp-unlink-ex sftp remote-path))) (ssh2.debug "Deleting ~A resulted in ~A." remote-path result)))) + +(defun sftp-put (ssh-connection local-path remote-path &key (modes #o644)) + (with-sftp (sftp ssh-connection) + (let ((handle)) + (unwind-protect + (progn + (ssh2.debug "Trying to send local file ~A to remote file ~A" local-path remote-path) + (setf handle (libssh2-sftp-open-ex sftp remote-path + (foreign-bitfield-value 'sftp-flags '(:write :creat :trunc)) + modes + :file)) + (with-open-file (in local-path :direction :input :element-type '(unsigned-byte 8)) + (let ((buffer (make-array 1024 :element-type '(unsigned-byte 8)))) + (loop for numbytes = (read-sequence buffer in) + until (zerop numbytes) + do (cffi:with-foreign-array (array buffer `(:array :uint8 ,numbytes)) (libssh2-sftp-write handle array numbytes))))) + (ssh2.debug "Local file ~A was written to ~A" local-path remote-path))) + (when handle (libssh2-sftp-close-handle handle)))))