これは決して行うべきではないことは承知していますが、Linux でファイル名内のディレクトリを区切るスラッシュ文字を使用する方法はありますか?
ベストアンサー1
答えは、ファイルシステムにバグがない限り、それはできない、ということです。理由は次のとおりです。
fs/namei.c
で定義されているファイルの名前を変更するためのシステム コールが : ですrenameat
。
SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname,
int, newdfd, const char __user *, newname)
システム コールが呼び出されると、do_path_lookup
名前のパス検索 ( ) が行われます。これをトレースし続けると、link_path_walk
次のようになります。
static int link_path_walk(const char *name, struct nameidata *nd)
{
struct path next;
int err;
unsigned int lookup_flags = nd->flags;
while (*name=='/')
name++;
if (!*name)
return 0;
...
このコードは、どのファイル システムにも適用されます。これは何を意味するのでしょうか。従来の方法を使用して、ファイル名として実際の文字を含むパラメータを渡そうとすると'/'
、期待どおりに動作しないことを意味します。文字をエスケープする方法はありません。ファイル システムがこれを「サポート」している場合、それは次のいずれかの理由です。
- ユニコード文字か何かを使って見た目スラッシュのようですが、そうではありません。
- バグがあります。
さらに、もしあなたがしたバイトを編集してファイル名にスラッシュ文字を追加すると、問題が起こります。これは、このファイルを名前で参照できないためです :( なぜなら、名前で参照すると、Linux は存在しないディレクトリを参照していると想定するからです。 'rm *' テクニックも機能しません。bash はそれをファイル名に展開するだけだからです。rm -rf
単純な strace で、内部で何が起こっているかがわかるので、これも機能しません (短縮):
$ ls testdir
myfile2 out
$ strace -vf rm -rf testdir
...
unlinkat(3, "myfile2", 0) = 0
unlinkat(3, "out", 0) = 0
fcntl(3, F_GETFD) = 0x1 (flags FD_CLOEXEC)
close(3) = 0
unlinkat(AT_FDCWD, "testdir", AT_REMOVEDIR) = 0
...
これらの呼び出しは、unlinkat
ファイルを名前で参照する必要があるため失敗することに注意してください。