最近の記事
- 4/22 - 思い出の紙時計
- 3/29 - さくらインターネットの VPS リニューアル
- 3/19 - SSHD への攻撃を分析してみた
- 3/9 - キーボードの過酷さ
- 3/8 - .NET のパフォーマンスについて
- 3/7 - phpMyAdmin への攻撃
- 3/1 - ミイラ取りがミイラになりかけた
- 2/22 - URL を知らなければ安全だと?
- 2/16 - 決意
- 1/30 - ルーターの UPnP 対応状況
Entering Passive Mode
昨日、マウントポイントのバッファの内容を直接取り出したが、
そのリンク先のパスは、以下のようになっていた。
\??\Volume{f08e7d20-64f1-11db-b10d-001125868411}\
だが、これを GetVolumeNameForVolumeMountPoint で
取り出すと以下のようになる。
\\?\Volume{f08e7d20-64f1-11db-b10d-001125868411}\
一見同じに見えるが、接頭辞が異なっている。
これらはどう違い、どんな意味をもっているのだろうか。
では、実際にリパースデータバッファを取得し、
マウントポイントのリンク先を取得してみよう。
========== 1st half of mountpoint.c ==========
#define UNICODE
#define STRICT
#define WIN32_LEAN_AND_MEAN
#define _WIN32_WINNT 0x0500
リパースタグなどの特殊なデータにアクセスする場合、
デバイスドライバに対して制御コードを送り、
データ構造を直接扱う必要がある。
Windows には、DeviceIoControl という API があり、
これを使うことで、デバイスドライバの制御が可能である。
リパースポイントの情報を得るためには、
対象のディレクトリハンドルに対して、
FSCTL_GET_REPARSE_POINT という制御コードを送る。
そうすれば、その結果としてリパースポイントの情報が、
リパースデータバッファと呼ばれる構造で返却される。
NTFS のボリュームマウントポイントは、
ディレクトリに設定することができ、
リンクの処理は NTFS によって行われる。
そのため、一度設定したマウントポイントは、
OS を再起動しても維持されている。
また、ディスクを異なる PC に持っていっても、
リンク先のボリュームが存在すれば利用できる。
こんなことが可能なのは、リンク先に関する情報が、
ディスク自身に保存されているからである。
ボリュームマウントポイントの API も充実している。
ボリュームを、ドライブやパスに割り当てるには、
SetVolumeMountPoint API を使うだけでできる。
BOOL SetVolumeMountPoint(
LPCSTR lpszVolumeMountPoint,
LPCSTR lpszVolumeName
);
lpszVolumeMountPoint には、割り当てるドライブの
ルートディレクトリや、マウント先ディレクトリを指定する。
例えば、「R:\」や「D:\mnt\cdrom\」などとなる。
どちらの場合でも、パスの最後には \ 記号が必要だ。
Windows 2000 以降は、管理ツール「ディスクの管理」の、
「ドライブ文字とパスの変更」メニューより、
ボリュームに割り当てるドライブ名を変更可能だ。
この画面では、ドライブの追加や削除ができる。
ボリュームには、ドライブを割り当てるのは任意であるが、
割り当てる場合は最大 1 つのドライブ名しか指定できない。
どうしても複数のドライブ名を割り当てたい場合は、
割り当てたドライブのルートディレクトリに対して
subst することで仮想ドライブを作ることが可能である。
Windows 2000 以降の NT 系では、
ディスクの管理機能が強化され、
ディスク構成の変更に非常に強くなっている。
ハードディスクのパーティションや、
CD-ROM ドライブ、外付けドライブなどは、
ボリューム、又はディスクボリュームと呼ばれているが、
従来はドライブ名によってこれを識別した。
Windows 2000 では、ドライブ名の代わりに、
ボリュームを一意に識別できる GUID を持っている。
この識別子はボリューム識別子と呼ばれる。
NTFS のハードリンクは、UNIX 系のそれと同じ機能である。
複数のファイル名が、同じファイルデータを指す状態だ。
それぞれのファイル名には主従関係は存在せず、
共通のデータを持つ以外、通常のファイルと変わらない。
リンクというのは、ファイルシステム内の概念であり、
NTFS ではファイル名とデータ(全ストリーム)の関係を指す。
通常のファイルは、1 つのデータに対して、
1 つのファイル名がリンクしているが、
ハードリンクされたファイルの場合、1 つのデータに対して、
複数のファイル名がリンクしているということだ。
今まで色々なリンク機能を見てきたが、
これらはシェルやカーネル(サブシステム)の能力であった。
ショートカットやフォルダリンクは、
シェルを使わない場合は利用できない。
ドライブのマッピング機能は、
プログラムからも利用することはできるが、
ドライブへの割り当てしかできず、制約もある。
このトピックの一番最初では、
UNIX ファイルシステムのリンク機能について書いた。
ドライブの割り当ては、2 種類あった。
ローカルパスとネットワークボリューム。
利用者から見てみれば両者は同じような物だが、
プログラム的に考えると、全く別のものだ。
ローカルパスの割り当ては、
ドライブ(MS-DOS デバイス)に対して、
別のデバイスパスへリンクを定義する作業となり、
DefineDosDevice API を使う。
ネットワークボリュームの割り当ては、
まず、ファイル共有を提供しているサーバに接続し、
そして、その接続をローカルドライブにマッピングする。
これは、LAN Manager 系の NetUseAdd API か、
Windows 系の、WNetAddConnection API を使う。