Windowsにおけるファイルコピーに関する驚くほど複雑な注意点 103
ストーリー by hylom
互換性と拡張の結果 部門より
互換性と拡張の結果 部門より
あるAnonymous Coward 曰く、
ソフトイーサの創業者として知られる登大遊氏が、「Windows のファイルのコピーは、驚くほど奥が深い」としてWindowsにおけるファイルおよびディレクトリーのコピー時に注意しなければならない仕様19点を挙げている。
どうしてそうなったんだ……。
これによると、Windowsでは歴史的経緯から長いファイル名を扱う際に「謎の呪文」を使わなければならなかったり、Windows特有の複雑なファイル属性やアクセス権限や代替ストリーム、ファイルシステムによって異なるタイムスタンプ精度などの仕様、面倒なシンボリックの仕様、OSのバージョンによる互換性問題などを考慮しなければならないとのことで、Windowsのファイルコピーは非常に複雑になっているという。
Windowsでまともなファイルバックアップソフトウェアがほとんど存在しない理由 (スコア:2)
ってそういうことなんすね。
というのが♪ 当然書き連ねられていた。
(知らない/よくわからないのが多かったけど)
そして、♪?♪?♪? 最大限の恐怖!
Re:Windowsでまともなファイルバックアップソフトウェアがほとんど存在しない理由 (スコア:2, 興味深い)
記事でも挙げられてるが昔からあるBackupExecはすげーよな、ADもSQL ServerもHyper-Vもちゃんと吸い出せてしかも速い。
結構な頻度で販売元が変わるのが怖いのと、テープ関連が一度動かなくなるとトラブルシューティングが難儀なの以外は価格相応の価値がある。
Re:Windowsでまともなファイルバックアップソフトウェアがほとんど存在しない理由 (スコア:1)
Win10に標準で付いてる『ファイル履歴』ですら、パスが長かったり(?)
一部の記号を含むファイルがあったりすると途中でコケるみたいだしなぁ。
Win10に移行して『ファイル履歴』でバックアップ取ってるつもりで、
半年後にコケてることに気付いたよ。
どのファイルでエラーが出てるのかログなりで表示してくれるなら
まだ対処のしようもあるけど、それすらなく黙ってコケるからタチが悪い。
イベントビューアに一応なんか出てるけど、だから何やねんって話。
どこでエラーが起きたのかが知りたいのに、「エラーが出た」だけじゃわからんわ。
Re:Windowsでまともなファイルバックアップソフトウェアがほとんど存在しない理由 (スコア:3, 参考になる)
ファイル履歴は全角文字と半角文字を区別しないため、「File.txt」と「File.txt」を同一ファイルと誤認する。
そして、同一ファイルが同一フォルダに複数存在するとコケる。
でもそういうのがなくてもまともに動作しないですね。
パスの長さとかダメ文字とかなんだろうとは思いますが。
ファイルパスの余計な正規化処理が入っていて、それが国際化非対応なんでしょう。
何度も公式フォーラムで出ている話題ですが、全く改善される気配がありません。
公式フォーラムからのフィードバックしてないんでしょうね。
Re:Windowsでまともなファイルバックアップソフトウェアがほとんど存在しない理由 (スコア:1)
コマンドプロンプトからDOSコマンドでやってます。
エラーが出たところで止まるのでわかりやすいです。
Re: (スコア:0)
ファイラーもほとんど開発されないしね
なるほど納得できる人が居ないんだ
ツッコミどころいろいろ (スコア:2, 参考になる)
UNIXではコピー先に書き込みパーミッションの落とされたファイルがあるときに、勝手にパーミッションを立てて更新したりはしないと思うんだけど、Windowsでも間違って書き込まれたくないから読み取り専用属性を立てるんじゃないの? 上書きしていいかどうかは状況によるのでは?
BackupReadやBackupWriteに言及していないのは非同期I/Oをサポートしていないからか? しかし(公開APIでは)これ以外に読み書きの方法がないメタ情報もあるので、避けて通ることはできない。
WSLが第3のシンボリックリンク的な実装としてIO_REPARSE_TAG_LX_SYMLINKを導入した。
Vista以降ではCancelSynchronusIoという同期I/Oをキャンセルできる関数が追加された。
実際には、NT系ではゼロクリアされると仮定していい。別ドキュメントに根拠もある(Windowsのプロたるものドキュメントが相互矛盾している程度のことでうろたえてはならない)。ゼロクリアしたくないときはSetFileValidDataを使う。削除されたファイルの残骸かもしれないデータが読めてしまうのは重大なセキュリティ問題なので、この動作が変わることは考えづらい。SetFileValidDataもSeManageVolumePrivilegeを持つ(最初からボリューム全体を読み取れる)ユーザーにしか許可されていない。SetEndOfFileやSetFilePointerのドキュメントが保証を与えていないのは、Win9xではゼロクリアされなかったため。詳しくは白水氏(FastCopyの作者)のツイートを参照。
FSCTL_SET_ZERO_DATAはNT系では無駄に二重にゼロクリアするだけだし、Win9x系ではサポートされていないので、ゼロ初期化の目的で役に立つ場面はない。これは基本的にスパースファイルに穴を開けるために使うもの。
Vista以降ではGetFileInformationByHandleExでACLを無視したストリーム情報が取れるはずなので、これを使うべき。(18)を考慮しても、FindFirstStreamWがそもそもVista以降だしそれ以前のOSでもBackupReadがあるので非公開APIに出番はない。ていうかWin95時代から脳死状態でコピペを繰り返してるだけのSetEndOfFileやSetFilePointerのドキュメントの重箱の隅は異常に気にするくせにどうしてドキュメント化されていないAPIを平気で使うんだよ。
エクスプローラー以外は怖い (スコア:1)
NTFSはUnix系のファイルシステムより高機能・複雑だし、権限管理周りもそう。
普段意識する事はないがたまに気づかされる時もある。
そういう事もあって、Windowsのファイル操作をExplorer意外でやるのはちょっと怖い。
Linuxでマウントして操作するのも多少不安感があるな。
ファイラーを作るってのはそこまで難しい事ではないし、Explorerの不便な点(主にタブ、あと長いパス名)もあるがそれでも避けてしまうな。
Explorerなら安全は保障されていると思えるし。
とはいえ場合によっては権限周りを無視できる点でLinuxとかから触った方が早い。
まぁAPIがややこしいと言っても裏でrobocopyあたりを呼べば大概OKだろうけど、自前で高速コピーツールとか作る人は流石だと思う。
相当仕様(非公開APIまで!)に知悉していないとできないだろうね。
普通に使う時はスパースファイルやら代替ストリームやらのない単なるファイルだと思って、せいぜい残り容量・既にファイルが存在するか・長いファイル名・禁止文字(コピーだから触れられていないが重要)程度に注意すれば十分だろう。
あと予想できない不条理な理由でファイルが作成できない事もあるくらいに想定しておくべきか。
ついでにファイルシステムを超えるとタイムスタンプが一致しないってのも基本かな。期待する方がおかしいが。
なんというか、NTFSの問題というよりAPIの問題が多くを占めているように思える。
Win32 APIがクソだってのはみんな知ってるからその点では今更感はあるな。
とはいえ権限もシンボリックリンクもハードリンクも代替データストリームもないFATの世界の気楽さは確かにある。
USBメモリやSDカードの利便性の一つだと言えると思う。NTFSとかだと相当混乱したはずだ。
Re:エクスプローラー以外は怖い (スコア:1)
エクスプローラでも以前↓という話題があったので十分怖いのではないでしょうか
Windows 10の「特定条件でCtrl+Zを押すと警告無しにコピーしたファイルが消える」問題は仕様
https://srad.jp/story/17/12/12/0658247/ [srad.jp]
Windowsのプロはこの機能を♪当然知っていて使わないのかもしれませんが…
Re: (スコア:0)
俺たちもwinfileで初心に帰ろう
https://github.com/Microsoft/winfile [github.com]
昔のMacOSのようなファイル名の制限 (スコア:0)
ほんの十数年前までは31文字までだったんだから、今でもそのくせで長いファイル名を名付けようと思わない。
https://support.apple.com/kb/TA20771?locale=ja_JP&viewlocale=ja_JP [apple.com]
SEOやファイル検索対策で、やたらと長いファイル名やURLにする人いるけど、扱う側にとっては無駄でしかないと思う。
ページタイトルを英語にしなきゃいけないし、下手なローマ字変換していると恥をかくし。
Re:昔のMacOSのようなファイル名の制限 (スコア:3, 参考になる)
最初の項目「(1)♪」で述べられているのは「パス文字列」なのだから、
ファイル名が短かろうと、ディレクトリ階層の奥深くにあったりしたら、
トータルのパス文字列数があっさり260を超えてしまうこともありうるのだよ。
それに自分でつけなくとも、
・ネットからファイルをダウンロードしようとしたら、それにとんでもなく長い名前が付けられていた。
・アーカイブされたファイルを展開しようとしたら、それに(以下略。
・アーカイブファイルに深いファイル構造が仕込まれていて、展開場所のパスに追加されて260文字の制限を超えてしまう。
なんてことも起きうるんだ。
Re:昔のMacOSのようなファイル名の制限 (スコア:2)
>ほんの十数年前までは31文字までだったんだから、今でもそのくせで長いファイル名を名付けようと思わない。
ファイル名だけでなくて、デリレクトリ含めたファイルパスの文字列の長さのことなんじゃないすかね。
(1)♪ 当然、ファイルやディレクトリのパス文字列は 260 文字を超える可能性があるのだから、当然、先頭に謎の呪文である "\\?\" という文字列を付加する必要がある。これにより最大約 32767 文字までのパス名を取り扱えるようにすることを忘れるな。
♪ 当然
ってどっかで流行ってる?
Re: (スコア:0)
Win10で、エクスプローラからルードディレクトリにファイル作って、
300文字をファイル名にペーストしたら244文字で切られました。半角全角共に。
パス長36文字のフォルダ以下だと211文字。
場所によってファイル名に使える文字数が変わるってのがまたいやらしい。
ドライブ+フォルダ+ファイル名=247文字っすかね。
260文字までの残り13文字ってなんだろう。
ちなみにWSL(Ubuntu)からファイル作れば255文字行けました。半角でも全角でも255文字。
くっそ深い階層のWSLのホーム以下でも、浅い階層のWin側のホーム以下でも変わらず。
まあそうじゃないとダメなんですが。
Re:昔のMacOSのようなファイル名の制限 (スコア:1)
Windowsではファイル名の長さが8.3形式より長いものをさして「長いファイル名(LFN,Long File Name)」という歴史的経緯があるので、この書き方はまずいと思う。
ソースの文章の記述は正しいのに、色々と台無しだw
Win10のエクスプローラーは (スコア:0)
Win10のエクスプローラーは「長いパス名」に対応しておらず、
長いパス名を含むフォルダを右クリックしてファイルの個数や容量をしらべたり、
長いパス名を含むフォルダをコピーすると、長いパス名のファイルが含まれてないことがある
ところが、長いファイル名のファイルをWin10のエクスプローラで作ることは可能
作ったはずのファイルが、環境によって存在したり消えたりする不思議な仕様?バグ?
Re:Win10のエクスプローラーは (スコア:1)
仕様と言うにはちと不条理な末尾ドットファイルの怪
"file."
Re:Win10のエクスプローラーは (スコア:1)
エクスプローラー(探検家?)故、困難や不条理がついて回るのはしょうがない。
という話をどっかで見たっけ。
Windows以外では気にしなくていいとは知らなかった。 (スコア:0)
FAT16でフォーマットされているSDカードにコピーしてもアクセス権限や所有者などの定義は残るのか。それはすごいな。
Re: (スコア:0)
NTFSはフォーマットが非公開なのでファイルにどのような機能があるのか分かりにくく、多くの人たちに意見を聞けないのだろうね。
そして場当たり的な拡張が積もり積もった結果今に至っているんじゃないかと。
#簡単にファイルを整理するためのアプリをC#.NETで作ろうとしたら、dllの直接呼出しだらけになってC#を諦めるしかなかったOrz
そりゃ (スコア:0)
各種フォーマット毎のお約束が有るのが当然の上、それらの相互処理もやろうってのだからねぇ。
どっかで互換性を切って統一化すれば良いだろうが、今更それも無理だろうし。
この方の不満をすべて同時に解決している OS/FileSystem って何だろう (スコア:0)
構成の限られた組み込み OS ではなく、現実的な一般ユーザーの使う OS で「何も考えなくても大丈夫」な FileCopy ができる OS ってどれ?
Linux と macOS は外れるしなぁ
Re: (スコア:0)
Human68k
Re: (スコア:0)
mac、悪の枢軸HFS+は論外ですがAPFSそんなに筋悪いですか
Re:この方の不満をすべて同時に解決している OS/FileSystem って何だろう (スコア:1)
BSDサブシステムで扱える範囲が限られちゃってることかな。BSDの範囲で扱う分には楽。
Re: (スコア:0)
ファイルコピーまわりでCocoaから出来てBSDで出来んことってなんでしょう?
Re: (スコア:0)
CpMacってどっちですか。
Re: (スコア:0)
APFSでしか動かないファイルコピーなんて実際のソフトウェアには入れられないでしょ。iOSならまだしも、MacではHFS+も混在していることを前提にしないと無理。
ただ、HFS+はcorruption耐性とか性能とかいった面ではクソではあるが、ファイルコピーに関してはそこまで変なファイルシステムかなあ。
コピー先がシンボリックリンクじゃないとか書き込み可能かとかいった通常のUnixのコピーにまつわる罠はあるが、それ以外はcopyfile(3)で拡張属性もリソースフォークもなにもひっくるまて普通に処理できるんじゃ。
Re:この方の不満をすべて同時に解決している OS/FileSystem って何だろう (スコア:2, すばらしい洞察)
ファイル名の正規化が糞
Re: (スコア:0)
ファイルシステムとしてはFATは割と頭使わなくて済むんじゃない?
機能が制限されてるから難しい事も考えなくて済む。
現代的なOSでは何も考えずに確実なファイルコピーができるって事はシステムを破壊できかねないって事だから基本は無理だと思う。
でも「ユーザーが通常期待するファイルコピーを行うAPI」を提供する事は可能だし、大抵のOSは標準のコマンドがそういう動作を行っているとは期待できる。
もちろん安全に/権限上それができない時は失敗するわけだが。
Re:この方の不満をすべて同時に解決している OS/FileSystem って何だろう (スコア:1)
旧来のinodeのVFSという概念の上に、タイムスタンプとか最小の権限セットとかの基準ラインの仕様がほしいですね。
そういうのがないと、FS間でどのレベルで精度を保つか、どの権限が存在するかとかでどうしても無理がでるよな...
M-FalconSky (暑いか寒い)
move (スコア:0)
コマンドプロンプトからmoveを使う場合「上書きしますか?」と確認が来るのだが、
batにまとめて実行すると確認なしの強制上書きになるのです。
最近知ってガクブル。
Re:move (スコア:1)
/-Yスイッチ付けるだけで解決する
まぁ、確かに複雑 (スコア:0)
だけど、ほとんどの人にとってはCopyFile系のAPIで事足りるんじゃないかなぁ。
https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbas... [microsoft.com]
みんなやってくれて使いやすいラッパーライブラリ (スコア:0)
それだけ判っているならサクッと作って公開してくれたら(ただで)
よのなかの沢山の人が幸せになれると思うの
Re: (スコア:0)
それはOSベンダーがやるべき仕事じゃないのかねえ。
つーかWindows付属のxcopyとかrobocopyもこれらの仕様を網羅できてないのでは。
Re:みんなやってくれて使いやすいラッパーライブラリ (スコア:3, 参考になる)
ちょっと前に、HDDが死にかけたので慌てて吸い出せる分だけrobocopyで吸い出したのですが
(普通のバックアップ系ソフトでは途中でエラーになって落ちてダメだった。robocopy で何度かリトライさせれば読み取りにに成功してある程度救える状況)、
C:\Documents and Settings\ほげ\Local Settings\Application Data\Application Data\Application Data\…
と無限ループコピーしようとしたり、
「C:\Documents and Settings\ほげ」と「C:\Users\ほげ」とで二重にコピーしやがってコピー元よりもコピー先の方が容量くってたりとか
さんざんでした。今回の記事指摘のジャンクション関係はまったく対応してなさそうな感じ。
Re:みんなやってくれて使いやすいラッパーライブラリ (スコア:1)
robocopy /? より
/XJ :: 接合ポイントとシンボリック リンクを除外します (通常は既定で含まれます)。
# ヘルプがわかりにくい、とは思いますが。
Re:みんなやってくれて使いやすいラッパーライブラリ (スコア:1)
うわー、そんなオプションがあったのかーorz
一応、/? は一通り眺めたんですけど、見逃してました。
Re:みんなやってくれて使いやすいラッパーライブラリ (スコア:1)
RCJファイルには
/XJ :: 接合ポイントを除外します (通常、既定で含まれます)。
/XJF :: ファイルの接合ポイントを除外します。
/XJD :: ディレクトリの接合ポイントを除外します。
一応全部指定していますが、ジャンクションを含めて同じ状態にしてほしいのが本音です。robocopyではどうしようもないのかよくわからないまま今日に至っています。
試行回数がデフォルトで100万回とか、なんかrobocopyもいまひとつ感がただよいます。
Re: (スコア:0)
以前、robocopyでまるっと日付を保存してバックアップコピーしたかったのですが
ディレクトリの日付が変わってしまっていました
該当のオプションは指定したはずなのに・・・
なんだかマイナーバグがありそうです
元の EOF の位置と新しい位置の間にあるファイルの内容は未定義です。 (スコア:0)
ファイルの内容は不定です、ならまあゴミデータか何か訳わからんけど何がしかのバイト列が読み出されてくるんだろうな、と期待できるけど、未定義ですとか言われちゃうと本当に悪魔から核ミサイルまで何でも出てくる可能性があるってことになるが。
Re:元の EOF の位置と新しい位置の間にあるファイルの内容は未定義です。 (スコア:2, 参考になる)
> ファイルを読むだけで鼻から悪魔が出る可能性があるのか…
ここの原文は以下のようになっていて undefined behavior (鼻から悪魔) というわけではなく
データの内容が未定義というだけです:
https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileap... [microsoft.com]
> the contents of the file between the old end of the file and the new end of the file are not defined
あと、このデータ内容が未定義という仕様は Windows 95 の実装を考慮した記述になっているせいで
Windows NT 系なら seek して飛ばして書いたところはゼロクリアされることが保証されているとか:
https://twitter.com/shirouzu/status/1125975975735377920 [twitter.com]
> MSの生き字引、レイモンド・チェンによると(ACLなどない)Win95ではSetEndOfFileでゼロクリアしていなかったらしい。
> ドキュメントに保証する記述が無いのは、そのためと。
> https://devblogs.microsoft.com/oldnewthing/?p=45171 [microsoft.com]
https://twitter.com/shirouzu/status/1125977301831671808 [twitter.com]
> それに関して「(ファイルシステム部が)NT系なら拡張部分を0と仮定してよい」と書いてあった。
そのセクターに書かれていた古いデータが読めたりするとセキュリティ的な問題が生じるわけで、
モダンなOSであれば 0 フィルされていることを期待しても大丈夫な筈です。
Re:元の EOF の位置と新しい位置の間にあるファイルの内容は未定義です。 (スコア:1)
悪魔が出ることはないが、仕様上何が入ってるか保証されない、という意味で本当にわからない。
ゼロ埋めするかもしれないし、しないかもしれないし、てきとーなビット列で埋まってるかもしれない。
だから例えばセクタ上の古いデータを読み出す目的に使えるかというと、そういうことにも使えない。
ゼロ埋めされて「いない」データを期待することもできない。
昔、巨大なダミーファイルを作る必要があって(Windows2000時代で、まだfsutilコマンドは無かった)、調べてSetEndOfFileの仕様を知ったとき、「へ〜、一体どんなデータが読めるんだろう?」とワクワクしながら叩いてみたら、きっかり全ゼロで埋められててガッカリした。
Re: (スコア:0)
悪魔がデジタルデータに変化して潜んでいても上書きされないかもしれないんだから、出てくる可能性はあるんじゃないの?
Re: (スコア:0)
まあ未定義と不定の違いは置いといて、mallocからの類推から当然に既定では内容は不定だと思ってた。
記事書いた人的には「最大限の恐怖」らしいんだけど、しがないアプリ書きには全然ピンと来ない話だ。
// 未定義と不定の違いを言ってるのかと思ったけど、そこらへんは問題にしてないようだし。
Re:元の EOF の位置と新しい位置の間にあるファイルの内容は未定義です。 (スコア:1)
ゼロクリアにコストはかからないのでクリアする方が自然だから
Re: (スコア:0)
「不定」と「未定義」って同じようなものとは思わないがそんなにかけ離れてはいない気がするけど
Re: (スコア:0)
そういや、たしかJavaの旧IO系(java.io)APIもこのWindowsの仕様に準じてファイルポインタの移動で拡張した領域の内容は未定義とかってなってたはず……
もっともファイルポインタの移動でファイル領域を拡張できる全てのAPIにこの注意書きが書いてあるわけではないとかいうアレげな事になってるので……
Re:fsutil 8dot3name (スコア:1)
意図しないエイリアスが出来ているのと等価なので、
単純マッチしちゃうようなアプリに対するセキュリティバグになるんですよ。 [ipa.go.jp]