LINUX.ORG.RU

Откуда rm знает что директория НЕ пуста если у него нет прав её читать?

 , , ,


0

5

Для того чтобы удалить директорию надо сначала её опустошить. Однако по идее для этого нам нужен доступ к списку содержимого директории. Если же директория находится в режиме запрещяющим чтение онного списка (то есть чтение запрещенно), то тогда мы будем неспособны узнать (без изменения прав доступа) является ли онная директория пустой. Гипотетически в зависимости от того софта который мы используем мы либо должны получить ошибку (если софт боится удалять директорию в которой может что-то быть) либо предупреждение типа «Фиг его знает, но данная директория может оказаться НЕ пустой. Вы точно уверены что хотите её удалить?».

Я от имени root создал пустую директорию TopSecret в режиме «только запись» и потом попытался удалить с помощью Thunar(файловый менеджер XFCE). У меня вывелось окошко «Deleting files», таким образом сообщая об попытке Thunar удалить файлы внутри папки. Онная попытка закончилась неудачей из-за недостаточных прав доступа, в результате чего Thunar отказался от идеи удалить папку.

Потом я зашёл в консоль(как обычный юзер) и успешно удалил туже папку с помощью «rm -fd». Ради эксперимента я потом снова от имени root создал директорию TopSecret в режиме «только запись», но на этот раз внутри папки был файл «secret.txt». Результат меня поразил, «rm -fd» отказалась удалять директорию ссылаясь на недостаточные права. Midnight Commander (который тоже успешно удалял пустой TopSecret) оказался более разговорчивым, он прямо сказал что не может удалить папку так как в ней что-то есть.

Вот только как MC и rm узнали что в папке что-то есть, у них же недостаточно прав для того чтобы просмотреть список содержания папки? И почему попытка Thunar удалить пустую TopSecret провалилась, в отличии от MC с rm?

Deleted

strace приходит на помощь, в каталоге test внутри есть файл, на каталоге права 000:

$ stat test
Access: (0000/d---------)
$ cd test
bash: cd: test: Permission denied
$ rmdir test
rmdir: failed to remove 'test': Directory not empty
$ strace rmdir test
...
rmdir("test")                           = -1 ENOTEMPTY (Directory not empty)
write(2, ": Directory not empty", 21: Directory not empty)   = 21
write(2, "\n", 1

Подробности читать в man 2 rmdir

anonymous ()
Ответ на: комментарий от anonymous

Я читал man 2 rmdir и man 3 rmdir, но что-то нифига толком не понял. Я в программировании не особо силён, не могли бы «на пальцах» объяснить что происходит?

Deleted ()
Ответ на: комментарий от Deleted

в man 2 rmdir нихера нет, кроме описания кодов возврата, тот анонимус троллит.

syscall получает инфу о директории из ядра и отдает ее в виде кода возврата команде rmdir

ENTRY(rmdir)
    pushl   %ebx
    mov     8(%esp), %ebx
    movl    $__NR_rmdir, %eax
    int     $0x80
    cmpl    $-MAX_ERRNO, %eax
    jb      1f
    negl    %eax
    pushl   %eax
    call    __set_errno
    addl    $4, %esp
    orl     $-1, %eax
1:
    popl    %ebx
    ret
END(rmdir)
anonymous ()

На самом деле rm ничего не проверяет. Он просто просит ОС удалить каталог. Если ОС отказывается что-то сделать, то она сообщает код ошибки (а rm просто преобразует код в текст по таблице кодов ошибок и выводит пользователю). И среди прочих есть код «каталог не пуст» (а ядро ОС без всяких прав доступа всегда знает пуст каталог или нет). Это ограничение не команды rm, а системной функции ОС, которая удаляет каталоги - она требует, чтобы каталог был пуст (иначе нужно рекурсивно пройтись по каталогу и сначала удалить все файлы - это делает опция -r). В винде, если что, такое же ограничение на функцию удаления каталога. Некоторые библиотеки могут включать в себя продвинутую функцию, удаления, которые автоматически удаляют сначала содержимое, а уже потом каталог. Однако rm использует напрямую сервис ядра, без обёрток.

KivApple ★★★★★ ()
Последнее исправление: KivApple (всего исправлений: 2)

Какая версия ядра?

Deleted ()
Ответ на: комментарий от Deleted

Linux debian 4.5.0-2-686-pae #1 SMP Debian 4.5.2-1 (2016-04-28) i686 GNU/Linux

Deleted ()
Ответ на: комментарий от Alexonline

Не понял, что Вы этим хотели сказать?

Deleted ()
Ответ на: комментарий от anonymous

Я надеюсь ты это накатал в качестве реверс троллинга.

anonymous ()
Ответ на: комментарий от KivApple

На самом деле ты прав только в первой части ответа. Если у текущего процесса нет прав на чтение содержимого каталога, Linux возвращает ENOTEMPTY, даже если он пуст. Кстати, это не документировано.

intelfx ★★★★★ ()

rm этого не знает, а ядро знает. Поэтому при выполнении системного вызова для удаления директории ядро отказывается это делать, если директория не пустая.

proud_anon ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.