Ответ в том, что вы не можете, если в вашей файловой системе нет ошибки. И вот почему:
Для переименования файла, определенного в 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;
...
Этот код применяется к любой файловой системе. Что это значит? Это означает, что если вы попытаетесь передать параметр с действительным символом '/'
в качестве имени файла с использованием традиционных средств, он не будет выполнять то, что вы хотите. Нет способа убежать от персонажа. Если файловая система «поддерживает» это, это потому, что они либо:
- Используйте символ Unicode или что-то, что выглядит как косая черта, но не так.
- У них есть ошибка.
Кроме того, если вы сделали , войдите и отредактируете байты для добавления символа косой черты в имя файла, могут произойти плохие вещи. Это потому, что вы никогда не можете ссылаться на этот файл по имени :(, поскольку в любое время Linux предполагал, что вы ссылаетесь на несуществующий каталог. Использование метода 'rm *' также не будет работать, поскольку bash просто расширяет его до имени файла. Даже rm -rf
не сработает, так как простая полоска показывает, как все происходит под капотом (сокращено):
$ 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
не будут выполнены, потому что они должны ссылаться на файлы по имени.