Introduction
前回は、System.IO.FileStreamを使ってファイルのアクセス権限を確認してみました。
今回は少し高度なファイルへのアクセス可否についてです。
P/Invoke
ファイルに実際にアクセスしてみて、アクセスできるかどうかを試すって、結構良くないと思います。
かといって、Windowsの.NET Frameworkにアクセスできるかどうかを試すAPIは無かったはずです。
ですが、Linuxのシステムコールを使えば、それが実現可能です。
システムコールの呼び出しは当然P/Invokeで実現します。
Linuxのシステムコールで、ファイルに対して、読み込みができるか、書き込みが出来るか、実行できるか、という状態を調べるには、accessを呼び出します。
大抵のシステムコールはlibcに定義されています。
実際に、libcに定義されている関数の一覧からaccessを探してみます。
そのために、nmコマンドに -D オプションを渡します。
1 | nm -D /usr/lib64/lib.so.6 | grep access |
これでlibcにaccessが定義されていることがわかりました。
次にaccessの使い方です。
定義は下記です。
1 | int access(const char *pathname, int mode); |
第一引数はファイルパスです。
第二引数は調べるモードを表します。
値 | 意味 |
---|---|
F_OK | 存在するか |
R_OK | 読み込み可能か |
W_OK | 書き込み可能か |
X_OK | 実行可能か |
第二引数のモードを組み合わせることで、アクセス可否をチェックします。
指定したモードを満たせば、0を返します。
満たさない場合は-1を返します。
Try
今回は、**/etc/passwd**を調べてみます。
1 | ls -la /etc/passwd |
root以外は、読み込みしかできません。
では、これをコードで調べてみます。
1 | using System; |
引数で指定したファイルの読み込み、書き込み、実行の可否を調べます。
前回同様、まずは、一般ユーザで確認します。
whichでdotnetコマンドの場所を調べているのは、rootユーザでdotnetまでのパスが通っていなかったので、実施しているだけです。
パスが通っているなら不要です。
引数のファイルパスはdotnet runの直後に追記することで指定できます。
1 | dotnetコマンドの場所を調べます |
読み込みしかできないようです。
ls -laで調べたとおりです。
続いて、rootで確認します。
1 | sudo /opt/rh/rh-dotnetcore11/root/usr/bin/dotnet run /etc/passwd |
読み書きができて、実行できないことが確認できました。
これも、ls -laで調べたとおりです。
では、存在しないファイルを指定してみます。
1 | /opt/rh/rh-dotnetcore11/root/usr/bin/dotnet run /etc/passwd2 |
きちんと存在しないことを確認してくれます。
フォルダも調べることが出来ます。
1 | ls -lad /etc |
Conclusion
Windows同様、P/Invokeが利用可能であることを確認できました。