Na seguinte situaçãols -alh
total 0
drwxrwx--- 1 user http 20 Nov 30 08:08 .
drwxrws--- 1 user http 310 Nov 30 08:07 ..
drwx------ 1 http http 10 Nov 30 08:08 empty-subdir
drwx------ 1 http http 12 Nov 30 08:08 non-empty-subdir
onde existem dois subdiretórios (não pertencentes a mim), que listo como:
sudo ls empty-subdir -alh
total 0
drwx------ 1 http http 10 Nov 30 08:08 .
drwxrwx--- 1 user http 20 Nov 30 08:08 ..
sudo ls non-empty-subdir -alh
total 0
drwx------ 1 http http 12 Nov 30 08:08 .
drwxrwx--- 1 user http 20 Nov 30 08:08 ..
drwx------ 1 http http 0 Nov 30 08:08 subdir
A diferença entre os dois subdiretórios é que o não vazio non-empty-subdir
contém uma pasta.
Minha pergunta é se é por design que tento rm -rf
remover os subdiretórios que obtenho resultados:
$ rm empty-subdir -rf
$ rm non-empty-subdir -rf
rm: cannot remove 'non-empty-subdir': Permission denied
$ ls -alh
total 0
drwxrwx---+ 1 user http 10 Nov 30 08:14 .
drwxrws---+ 1 user http 310 Nov 30 08:07 ..
drwx------+ 1 http http 12 Nov 30 08:08 non-empty-subdir
Parece que o usuário com permissões de gravação em um diretório pode remover uma entrada de um arquivo ou um subdiretório vazio de algum outro usuário, mas não um subdiretório não vazio .
Uma resposta ideal para essa pergunta forneceria informações como:
- uma confirmação de que o comportamento descrito é reproduzível em outras máquinas (e não meras peculiaridades da minha caixa estragada)
- uma justificativa para explicar esse comportamento (por exemplo, existem casos de uso?)
- uma visão geral se houver diferenças entre os sistemas (BSD, Linux....)
Atualização : Com relação ao comentário de Ipor Sircer, testei novamente o cenário, sem nenhum recurso de ACL e é o mesmo. Portanto, modifiquei a pergunta para remover os +
es das listagens para não dar origem a uma ideia de que o comportamento pode estar relacionado a ACLs.
Só é possível remover um diretório (com a
rmdir()
chamada do sistema) se estiver vazio.rm -r dir
remove o diretório e todos os arquivos contidos nele, começando pelas folhas da árvore de diretórios e subindo até a raiz (dir
).Para remover um arquivo (com
rmdir()
para diretórios eunlink()
para outros tipos de arquivos, ou*at()
variantes), o que importa não é a permissão do arquivo em si, mas as do diretório do qual você está removendo o arquivo (cuidado com ot
bit nas permissões, como para/tmp
, acrescenta mais complicações a isso).Antes de tudo, você não está realmente removendo o arquivo , você está desvinculando-o de um diretório (e quando for o último link que você está removendo, o arquivo acaba sendo deletado por consequência), ou seja, você está modificando o diretório, então você precisa modificar (escrever) permissões para esse diretório.
O motivo pelo qual você não pode remover
non-empty-dir
é que não pode desvincularsubdir
primeiro, pois não tem o direito de modificarnon-empty-dir
. Você teria o direito de desvincularnon-empty-dir
de seu diretório pessoal, pois tem permissão de gravação/modificação para aquele, apenas você não pode remover um diretório que não esteja vazio.No seu caso, conforme observado por @PeterCordes nos comentários, a
rmdir()
chamada do sistema falha com umENOTEMPTY
código de erro (Diretório não vazio), mas como você não tem permissão de leitura para o diretório,rm
não consegue nem descobrir quais arquivos e diretórios (incluindosubdir
) ele precisaria se desvincular dele para poder esvaziá-lo (não que pudesse desvinculá-los se soubesse, pois não tem permissões de gravação).Você também pode entrar em situações em que
rm
poderia remover um diretório se pudesse descobrir quais arquivos estão nele, como no caso de um diretório somente para gravação:Ainda assim, posso removê-lo, pois sei que ele contém apenas um
file
arquivo:Observe também que com Unices modernos você pode renomear isso
non-empty-dir
, mas em alguns como Linux ou FreeBSD (mas não Solaris), não movê-lo para um diretório diferente, mesmo se você também tivesse permissão de gravação para esse diretório, como (eu acho que e para Linux , conforme sugerido pelo comentário para o código relevante ) isso envolveria modificaçãonon-empty-dir
(a..
entrada nele apontaria para um diretório diferente).Pode-se argumentar que remover your
empty-dir
também envolve remover as entradas..
e.
nele, portanto, modificá-lo, mas ainda assim, o sistema permite que você faça isso.Ignorando a possível alteração por meio das ACLs, posso confirmar esse comportamento para meu sistema (sem ACLs).
O comportamento observado é a consequência lógica de dois princípios:
1) Os direitos de um diretório determinam quem pode alterar o diretório, ou seja, excluir entradas no diretório. Os direitos das entradas nesse diretório não desempenham nenhum papel nisso.
2) A remoção de um arquivo requer potencialmente a remoção e limpeza das informações associadas, ou seja, inodes, listas de alocação de blocos etc. tornar-se inacessível, mas as informações associadas não teriam sido limpas.
Portanto, você pode remover
empty-subdir
, porque tem o direito de gravar no diretório em que ele está. Você não pode removernon-empty-subdir
, porque não tem o direito de limpar primeiro os arquivos contidos neste subdiretório.Não há realmente nenhuma razão ou caso de uso para isso. Alguém poderia ter construído uma limpeza recursiva de um subdiretório no kernel, mas o Unix original manteve tudo simples, e a limpeza recursiva teria sido muito complicada quando pode ser realizada com um utilitário de espaço de usuário.
Não posso fornecer uma visão geral abrangente entre os diferentes tipos, mas esse era o comportamento no Unix original e esperaria que fosse o mesmo em todos os tipos de Unix, e ficaria surpreso se houvesse um tipo de Unix que se comportou de maneira diferente.
Tentei reproduzir o que você descreve e executei
strace rm -rf ./nonempty
. O que isso revela é o seguinte:e de acordo com o
unlinkat
manual (que no Linux é o mesmounlink(2)
, grifo meu):Como o diretório pai,
nonempty
, não concedeuser
permissão x (pesquisa), faz sentido com base naEACCES
descrição quesubdir
não pode ser removida.