more Sftp operations;
authorwenzelm
Mon, 10 Oct 2016 16:04:57 +0200
changeset 64132 c2594513687b
parent 64131 f01fca58e0a5
child 64133 e8407039b572
more Sftp operations;
src/Pure/General/ssh.scala
--- a/src/Pure/General/ssh.scala	Mon Oct 10 14:45:32 2016 +0200
+++ b/src/Pure/General/ssh.scala	Mon Oct 10 16:04:57 2016 +0200
@@ -12,7 +12,7 @@
 import scala.collection.JavaConversions
 
 import com.jcraft.jsch.{JSch, Logger => JSch_Logger, Session => JSch_Session,
-  OpenSSHConfig, UserInfo, Channel => JSch_Channel, ChannelExec, ChannelSftp}
+  OpenSSHConfig, UserInfo, Channel => JSch_Channel, ChannelExec, ChannelSftp, SftpATTRS}
 
 
 object SSH
@@ -81,7 +81,7 @@
   }
 
 
-  /* channel: exec, sftp etc. */
+  /* channel */
 
   class Channel[C <: JSch_Channel] private[SSH](val session: Session,
     val kind: String, val channel_options: Options, val channel: C)
@@ -91,6 +91,9 @@
     def close { channel.disconnect }
   }
 
+
+  /* exec channel */
+
   class Exec private[SSH](
     session: Session, kind: String, channel_options: Options, channel: ChannelExec)
     extends Channel[ChannelExec](session, kind, channel_options, channel)
@@ -99,6 +102,16 @@
   }
 
 
+  /* Sftp channel */
+
+  type Attrs = SftpATTRS
+
+  sealed case class Dir_Entry(name: String, attrs: Attrs)
+  {
+    def is_file: Boolean = attrs.isReg
+    def is_dir: Boolean = attrs.isDir
+  }
+
   class Sftp private[SSH](
     session: Session, kind: String, channel_options: Options, channel: ChannelSftp)
     extends Channel[ChannelSftp](session, kind, channel_options, channel)
@@ -112,6 +125,32 @@
     def mkdir(remote_path: String) { channel.mkdir(remote_path) }
     def rmdir(remote_path: String) { channel.rmdir(remote_path) }
 
+    def stat(remote_path: String): Dir_Entry =
+      Dir_Entry(remote_path, channel.stat(remote_path))
+
+    def read_dir(remote_path: String): List[Dir_Entry] =
+    {
+      val dir = channel.ls(remote_path)
+      (for {
+        i <- (0 until dir.size).iterator
+        a = dir.get(i).asInstanceOf[AnyRef]
+        name = Untyped.get[String](a, "filename")
+        attrs = Untyped.get[Attrs](a, "attrs")
+        if name != "." && name != ".."
+      } yield Dir_Entry(name, attrs)).toList
+    }
+
+    def find_files(remote_path: String, pred: Dir_Entry => Boolean = _ => true): List[Dir_Entry] =
+    {
+      def find(dir: String): List[Dir_Entry] =
+        read_dir(dir).flatMap(entry =>
+          {
+            val file = dir + "/" + entry.name
+            if (entry.is_dir) find(file) else if (pred(entry)) List(entry) else Nil
+          })
+      find(remote_path)
+    }
+
     def open_input(remote_path: String): InputStream = channel.get(remote_path)
     def open_output(remote_path: String): OutputStream = channel.put(remote_path)