SharpSsh は.NET 環境で SSH 接続をするための ライブラリ です。
今回、とあるシステム開発のために、VC# で SFTP を行う必要があったので、使ってみました。
とても簡単に使えて便利なのですが、ファイル更新時刻を取得/設定できなかったので、それ用の関数を追加しました。
変更箇所
SharpSshはソースも公開されているので、簡単に機能追加ができます。
今回手を加えたのは、Sftp.cs というファイルです。public class Sftp のブロックの中に以下のコードを追加しました。
namespace Tamir.SharpSsh
{
public class Sftp : SshTransferProtocolBase
{
(略)
// MTime
public int GetMTime(string path)
{
Tamir.SharpSsh.jsch.SftpATTRS attr;
try
{
attr = SftpChannel.stat(path);
return attr.getMTime();
}
catch (Exception e)
{
return 0;
}
}
public void SetMTime(string path,int mtime)
{
try
{
SftpChannel.setMtime(path,mtime);
}
catch (Exception e)
{
}
}
(略)
}
}
実はSharpSsh ライブラリのソース内では、SFTPの(たぶん)全ての機能を使えるように実装されているのですが、外部に公開されている関数がごく一部なのです。
なので、今回組んだのは機能を外部に提供する部分だけです。
使用上の注意
この機能(リモートファイルの更新時刻を取得/設定)を使いたかったのは、ローカルファイルのそれと比較してどちらか新しい方を残す、ということをしたかったのです。
ところが、.NET で使われるファイル更新時刻の表現方法は DateTime 型で、今回作ったGetMTime()関数とは異なる形式です。
DateTime 型は、1601/01/01 00:00:00 からの経過時間を 100ns で割った値です。
片やGetMTime()の戻り値はUNIX形式。つまり、1970/01/01 00:00:00 からの経過時間(秒)です。
そこで、DateTime 型を UNIX形式に変換する関数を作りました。
static int DateTime2UnitTime(DateTime dt)
{
const long basetime = 116444736000000000L;
// ( = DateTime(1970,1,1,9,0,0,0).ToFileTime() )
return (int)((dt.ToFileTime() - basetime) / 10000000);
}
basetime定数は、1970/01/01 09:00:00(DateTime が日本時間なので9時です。本来ならUTCに合わせて作るべきなのですが・・・)を ToFileTime()関数でlong型にしたもの。1601年から1970年までを、100ns単位で表したものです。
で、それを知りたいDateTimeから引いて、秒単位に直すと 目的のUNIX形式になる、というわけです。
他にも
他のSFTPの機能も簡単に実装できるので、そのうち作りたいと思います。