none
ディスクのセクター位置を指定してファイルを新規作成する方法はないでしょうか? RRS feed

  • 質問

  • 対象OSはWindows7/10を想定しています。

    CreateFile等でファイルを新規作成した場合、ディスクのどのセクター位置に書かれるかは

    ファイルシステム依存だと考えております。

    これを、任意の期待したセクター位置を始点としてファイルを新規作成することは可能でしょうか?

    ファイルはプレーンテキストファイルでの作成を考えております。

    ファイルの新規作成とセクター位置の指定を同時に行うことが無理な場合、作成したファイルを

    任意のセクター位置に移動する方法があればそちらでも問題ございません。

    よろしくお願いいたします。

    2017年12月6日 6:30

回答

  • 「一般的にはできない」が答えになりますが、
    本件については、その目的を明らかにすべきだと思います。
    目的によって可能な場合と、不可能な場合と、代替案がありえる場合が想定できます。

    1.ボリュームやパーティションを意識して開くことは可能です。
    2.その物理情報(DISK_PARTITION_INFO等)は取得できます。
    3.開いたボリュームから特定のバイト数を読むことができます(セクタは指定できませんけど)。
    4.書き込みは保護されていてできない場合があります。
     SDカードなど外部ドライブには書き込めます。
    5.ボリュームのフォーマットによってはできない場合もあります。
    6.たとえ書き込めても、OSによって消される場合を想定しなければなりません(禁止できません)。

    2017年12月6日 7:10

すべての返信

  • 「一般的にはできない」が答えになりますが、
    本件については、その目的を明らかにすべきだと思います。
    目的によって可能な場合と、不可能な場合と、代替案がありえる場合が想定できます。

    1.ボリュームやパーティションを意識して開くことは可能です。
    2.その物理情報(DISK_PARTITION_INFO等)は取得できます。
    3.開いたボリュームから特定のバイト数を読むことができます(セクタは指定できませんけど)。
    4.書き込みは保護されていてできない場合があります。
     SDカードなど外部ドライブには書き込めます。
    5.ボリュームのフォーマットによってはできない場合もあります。
    6.たとえ書き込めても、OSによって消される場合を想定しなければなりません(禁止できません)。

    2017年12月6日 7:10
  • 仲澤様

    ご回答ありがとうございます。

    Storport配下のminiportドライバを作成するにあたって、特定のLBAへのRead/Writeの挙動を

    テストする上でテスト用データとしてテキストファイルを用意して動作確認を行いたいと

    考えていました。

    わかりやすい例だと、境界値試験などになります。

    32bit/64bitに関連した2TByteの壁や、ATAの28bit/BigDrive対応の48bitなどの境界値付近への

    ファイルアクセス試験を行う上で、それら境界値付近を狙ってテキストファイルを作成したいと

    考えておりました。

    ファイルの断片化なども考慮しなければならず、可能であればLBAを直で指定したかったのですが

    一般的にはできないのであれば別の方法を考えないといけないですね。

    ありがとうございました。

    2017年12月6日 7:59
  • ファイルシステムを破壊してでも書き込みたいということでしょうか?

    CreateFile()はファイルだけでなくディレクトリなど様々なものを扱えますが、その中にデバイスがあります。 \\.\C: であればC:ドライブを、 \\.\PhysicalDrive0 であれば最初ディスクをそれぞれオープンできます。後は 適切な位置にシークを行った後にread/writeされればいいかと。

    # read経験はありますが、破壊してまでのwrite経験はありませんw

    2017年12月6日 8:08
  • 「シリンダ、セクタ番号などの指定」という意味ではできませんが、
    「オープンしたボリュームの先頭からのオフセットバイト数」の指定は、
    空読みや空書きを駆使すればセクタ数や位置は算出可能可能となります。
    ただし、フォーマットの属性(512Byte/Sectorなど)が事前に分かっていることが前提になります。
    ですが、しょせんOS経由のアクセスなので、試験に使えるほど確実なのか、
    という意味では「いいえ」ということになりますね。

    2017年12月6日 8:22
  • > ファイルの断片化なども考慮しなければならず、
    > 可能であればLBAを直で指定したかったのですが
    > 一般的にはできないのであれば別の方法を考えないといけないですね。

    既にご認識されているようですが、「ファイルの断片化」は常に起こります。
    なので「考慮」ではなく「前提」とする必要があり、LBA を直に指定したら確実におかしくなると思います。

    この手の検証を本格的にやるとなると、非常に難しいですね。。。
    とりあえず思いつく方法としては。。。。
    ファイル I/O から SCSI コマンドへの変換は disk.sys ドライバ辺りがやっているので、LBA への変換も disk.sys ドライバがやっているんだと思います。
    (大昔に調べたけど、詳細はきれいさっぱり忘れました。)
    ということは、disk.sys の Lower Filter としてアタッチする検証ドライバを別途作成すれば、(方向性はちょっと違うかもしれないけど) 目的とする検証ができるのでは。。。。という気がします。
    既に佐祐理さんがコメントされていますが、ファイルではなく単なる「データ」としての読み書きであれば、CreateFile() / ReadFile() / WriteFile() でも行けますが、ファイル I/O と LBA を関連付けての検証の場合、ユーザ モード側からだけの制御では限界があると思います。
    今後発生するであろう不具合対応等のメンテナンス性を向上させる意味でも、ファイル システムやボリューム、ディスク等のデバイス スタックにアタッチする、検証用フィルタ ドライバを別途作成したほうが、将来的にもいいと思います。
    (Stor Miniport を開発できるだけのスキルがあるのだから、あともうちょっとだけ根性出せばフィルタ ドライバも作れるのでは?)
    2017年12月6日 9:17
  • 佐祐理様、仲澤様、お馬鹿様

    ご回答ありがとうございます。

    てっとり早くファイルを作成できれば楽かな、と思っていたのですがやはり難しいですよね。

    大人の事情で新たにドライバを作るのは難しいので、DeviceIoControl()で狙ったセクターへのRead/Writeを行う方針で検討いたします。

    ありがとうございました。

    2017年12月6日 23:37
  • 手段に目星はついていたのですがドキュメントが見つけられずに提案できずにいました。が、今更になってドキュメントを見つけたので提案しておきます。

    defragユーティリティは実質的にファイルを移動する機能を有していますので、移動させるAPIもどこかで公開されているはずと考えていました。Defragmenting a fileがその解説ですが、これを用いることでファイルを希望するセクターに移動可能かと思います。FSCTL_MOVE_FILEらしいですね。

    2018年1月16日 8:54
  • 佐祐理様

    クローズ後にも拘わらずお調べいただきありがとうございました。

    ご紹介いただいた情報について勉強してみたいと思います。

    2018年3月1日 4:06