Легко понять, что права доступа к файлу не имеют отношения к возможности удаления этого файла. Возможность изменять список каталогов контролируется разрешениями каталога.
Однако в течение многих лет я считал, что целью разрешения на запись было разрешение на изменение каталога, а разрешение на выполнение – на поиск, переименование файлов или изменение в каталог.
Сегодня я обнаружил, что нельзя хранить файл в каталоге, если не установлены оба бита записи и выполнения. На самом деле, без выполнения набора, запись кажется почти бесполезной.
$ tree foo/ foo/ └── file_to_delete 0 directories, 1 file $ chmod -x foo $ ls -ld foo drw-rw-r-- 2 ire_and_curses users 4096 Sep 18 22:08 foo/ $ rm foo/file_to_delete rm: cannot remove 'foo/file_to_delete': Permission denied $ chmod +x foo/ $ rm foo/file_to_delete $ tree foo/ foo/ 0 directories, 0 files $
Я нахожу это поведение довольно неожиданным. Для каталогов, какова причина того, что выполнение необходимо для того, чтобы написать полезную на практике?
Без бита выполнения вы не можете запустить stat()
в файлах в каталоге, что означает, что вы не можете определить информацию об инодах этих файлов. Чтобы удалить файл, вы должны знать информацию, которая будет возвращена stat()
.
Демонстрация этого:
$ ls -ld test drw------- 2 alienth alienth 4096 Sep 18 23:45 test $ stat test/file stat: cannot stat 'test/file': Permission denied $ strace -e newfstatat rm test/file newfstatat(AT_FDCWD, "test/file", 0x1a3f368, AT_SYMLINK_NOFOLLOW) = -1 EACCES (Permission denied) newfstatat(AT_FDCWD, "test/file", 0x7fff13d4f4f0, AT_SYMLINK_NOFOLLOW) = -1 EACCES (Permission denied) rm: cannot remove 'test/file': Permission denied +++ exited with 1 +++
Вы также можете продемонстрировать это с помощью простого ls -l
. Информация метаданных каталога может быть доступна для чтения и записи для пользователя, но без выполнения вы не можете определить детали файла в каталоге.
$ ls -l test ls: cannot access test/file: Permission denied total 0 -????????? ? ? ? ? ? file