As interfaces típicas de chamada do sistema permitem reduzir o tamanho de um arquivo (sem substituí-lo por um inode diferente)?

9

Existe uma maneira de open()um arquivo e fazer com que ele encolha? Pode-se, é claro, abri-los no modo de acréscimo ou procurar até o fim e escrever para fazê-los crescer. No entanto, até onde eu sei, não existe um método para reduzir um arquivo por meio de interfaces de chamada de sistema típicas no estilo unix.

A única maneira de fazê-lo, até onde eu sei, é falsificá-lo criando um novo arquivo menor e rename()no lugar do antigo.

Eu só queria confirmação, porque vi uma resposta que implicava que era possível criar editores de arquivos que funcionassem diretamente em um arquivo, em vez de passar pelo processo de criar um novo e renomeá-lo.

Eu sempre pensei que a API do arquivo nas interfaces de chamada de sistema libc e estilo unix não permitia o encolhimento de arquivos para facilitar a implementação de sistemas de arquivos e talvez evitar padrões de uso que possam contribuir para a fragmentação.

JoL
fonte
2
Basta abrir um arquivo fopenno modo "w" (ou "w +") para truncá-lo no tamanho zero automaticamente. Ou você quer dizer encolher para um tamanho diferente de zero, para preservar parte do conteúdo antigo?
wyzard
4
Apenas para sua informação, open()e openat()já possui um sinalizador para truncar, O_TRUNCportanto , tecnicamente, o arquivo diminui - ou seja, diminui completamente - sem alterar o inode. O exemplo mais famoso disso é command > file.txtque o arquivo será truncado, se existir. Se você executar straceem bash -c 'true > /dev/null'que você verá openat(AT_FDCWD, "/dev/null", O_WRONLY|O_CREAT|O_TRUNC, 0666)na saída. Obviamente, para tamanho variável de truncamento, você precisa do truncate()syscall. Deixe-me saber se você quer isso como uma resposta real em vez do comentário.
Sergiy Kolodyazhnyy 23/01/19
@SergiyKolodyazhnyy Eu estava pensando em diminuir para um tamanho arbitrário. Promovi a resposta de David Foerster porque ela responde a um subconjunto da pergunta, mas não a aceito à luz da icarus. Eu a consideraria uma resposta do tipo sim e não, enquanto a resposta do icarus já mostrava que a resposta real é um "sim".
JOL

Respostas:

22

man -s 2 ftruncate diz

DESCRIPTION
   The  truncate()  and  ftruncate()  functions cause the regular file
   named by path or referenced by fd to be truncated to a size of precisely
   length bytes.

...

CONFORMING TO
   POSIX.1-2001, POSIX.1-2008, 4.4BSD, SVr4 (these calls first appeared in 4.2BSD).

continua dizendo que, se você usar ftruncate, deverá ter aberto o arquivo para gravação e, se usar truncado, o arquivo deverá ser gravável.

Icaro
fonte
Anexar a um arquivo faz com que o sistema operacional truncateo acomode primeiro para o novo tamanho do arquivo e depois para write ele. Assim truncateé a chamada do sistema que você está procurando.
precisa saber é o seguinte
1
No Linux, veja tambémfallocate(FALLOC_FL_COLLAPSE_RANGE)
Stéphane Chazelas 23/01/19
2

A open(2)chamada do sistema aceita o O_TRUNCsinalizador que pode reduzir o tamanho do arquivo:

O_TRUNC- Se o arquivo existir e for regular, e o arquivo for aberto com êxito O_RDWRou O_WRONLY, seu comprimento será truncado para 0 e o modo e o proprietário permanecerão inalterados. Não terá efeito nos arquivos especiais FIFO ou nos arquivos do dispositivo terminal. Seu efeito em outros tipos de arquivo é definido pela implementação. O resultado do uso O_TRUNCsem O_RDWRou não O_WRONLYé definido.

É freqüentemente usado quando o programa pretende sobrescrever completamente o conteúdo de um arquivo. Um exemplo é o operador de redirecionamento de arquivos do seu shell, como em command > file.

David Foerster
fonte