少し前からlftpのmirrorがうまく動かない原因を探していた。
前に調べてあたりを付けたのが「サイズが同じだとアップロードしない」という問題。
オプションのせいかな、と思って-nとか--ignore-sizeを試してみたが、結局のところこれではなかったらしい。
-nはともかく、--ignore-sizeというのは「更新されたかどうかを調べるのにsizeを判断材料に使わない」ということなので、これではsizeが同じだろうと違おうとダメらしい。同様に--ignore-timeも。これなんか、timeが違ってもsizeが同じなら動作しないわけだから、今回の解決には至らなかった。
対象となるファイルをいろいろtouchして頑張ってみると、ファイルを9時間未来にすると更新されたと判定されることが判明。ということは、ローカルのファイルの時間判定を間違っているか、リモートのファイルの時間判定を間違っているかのどちらか、という線が強い。
manpageを見ると、ftp:timezoneという設定があることが判明、しかもこれ、デフォルトはGMTだった。ここを-9とかjstとかJSTとか(勢い余って)+9とかしても、lsによる結果は変わらないが、cls -lによる結果は変わることがわかった。これをなんとかいじればmirrorでなんとかなるか?と思ったが結局ダメだった。やるに事欠いて+18とか-18とかやってみたけどまったくうまく動かない。
じゃああれか?まさかローカルのファイルの時刻判定を間違っているのか?とソースを眺めて時刻判定を探す。c++なんてまともにいじらないから追っかけるのが大変だったよ、と思いつつ結局ただstatでmtimeのエポック秒を取り出していることだけが判明。まあ普通はそうするよね。
エポック秒ということは基本的にはGMTで比較しているわけだ*1。やっぱりリモートか。ということでリモートのファイル一覧を取るあたりをいろんな方向から眺めることに。とはいうものの変な動きをしているところは見つからない。
いまいちどgoogleでlftp,timezone,mirrorあたりのキーワードを使って探すが日本語のサイトにはそれらしい情報がない。まあ探しているうちにlftpでコマンドを実行する際の-eと-cの違いなんかがわかってそれは興味深かったけど*2。
英語で探すと出てくるのがこのMLアーカイブ。うーん?「MDTMを使うとファイルの最終更新日時がGMTで返ってくるよ」って書かれているのが気になる。そういえばさっきこの辺のFTP接続に関する説明とかこの辺のPASVモードに関する説明を見てつないでみたときに、MDTMコマンド試してみたんだが、なんかJSTで結果が返ってきてなかったか?
MDTM,GMT,localtimeとかあたりの検索キーワードでgoogle検索すると、どうもこの辺の動作はGMTが基本だけど、localtimeな実装もあり得ない話ではないらしい。ということはもしかしてlftpはMDTM実装をGMT決めうちでやってるのかな?と思ってftpclass.ccを見たらその中のConvertFtpDateの中で案の定UTC決めうちで変換やってることがわかった。まあこれはこれで正しいんだろうな。
ということで、MDTMを使わない設定(set ftp:use-mdtm no)にして、さらにtimezoneを-9にする形(set ftp:timezone -9)で*3、設定したら普通に動いた。
結局ここまで見ないといけないとなると、perlあたりでNet::Ftpとか使って自作しちゃった方が早いかもしれないよなあ。出来合いだとこういうときに疲れる。