¿Las interfaces de llamada de sistema típicas permiten reducir el tamaño de un archivo (sin reemplazarlo con un inodo diferente)?

9

¿Hay alguna forma de open()archivo y hacer que se encoja? Uno puede, por supuesto, abrirlos en modo anexar o buscar hasta el final y escribir para hacerlos crecer. Sin embargo, hasta donde yo sé, no hay ningún método para reducir un archivo a través de interfaces de llamada de sistema de estilo unix típico.

La única forma de hacerlo, hasta donde yo sé, es fingirlo creando un nuevo archivo más corto y rename()en lugar del anterior.

Solo quería confirmación, porque vi una respuesta que implicaba que era posible crear editores de archivos que funcionaran directamente en un archivo en lugar de pasar por el proceso de crear uno nuevo y renombrarlo en su lugar.

Siempre he pensado que la API de archivo en libc y las interfaces de llamada de sistema de estilo Unix no permitían la reducción de archivos para facilitar la implementación de sistemas de archivos y tal vez evitar patrones de uso que podrían contribuir a la fragmentación.

JoL
fuente
2
Simplemente abriendo un archivo fopenen modo "w" (o "w +") lo truncará a cero automáticamente. ¿O te refieres a reducir a un tamaño distinto de cero para preservar algunos de los contenidos anteriores?
Wyzard el
44
Solo para su información, open()y openat()ya tengo una bandera para truncar, O_TRUNCpor lo que técnicamente hace que el archivo se encoja, es decir, se encoja por completo, sin cambiar el inodo. El ejemplo más famoso de eso es command > file.txt, donde el archivo se truncará si existe. Si se ejecuta straceen el bash -c 'true > /dev/null'que veremos openat(AT_FDCWD, "/dev/null", O_WRONLY|O_CREAT|O_TRUNC, 0666)en la salida. Por supuesto, para un tamaño variable de truncamiento necesita truncate()syscall. Avíseme si desea que esto sea una respuesta real en lugar del comentario.
Sergiy Kolodyazhnyy
@SergiyKolodyazhnyy Estaba pensando en reducir a un tamaño arbitrario. He votado a favor de la respuesta de David Foerster porque responde a un subconjunto de la pregunta, pero no la acepto a la luz de Ícaro. Lo habría tomado como una respuesta de tipo sí y no, mientras que la respuesta de Ícaro ya mostró que la respuesta real es un "sí".
JoL

Respuestas:

22

man -s 2 ftruncate dice

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).

continúa diciendo que si usa ftruncate debe haber abierto el archivo para escribir, y si usa truncate, el archivo debe poder escribirse.

Ícaro
fuente
Agregar un archivo hace que el sistema operativo truncatelo acomode primero para el nuevo tamaño de archivo y luego write lo haga . Así truncatees la llamada al sistema que estás buscando.
mgarciaisaia
1
En Linux, vea tambiénfallocate(FALLOC_FL_COLLAPSE_RANGE)
Stéphane Chazelas el
2

La open(2)llamada al sistema acepta el O_TRUNCindicador que puede reducir el tamaño del archivo:

O_TRUNC- Si el archivo existe y es un archivo normal, y el archivo se abre con éxito O_RDWRo O_WRONLY, su longitud se truncará a 0, y el modo y el propietario no se modificarán. No tendrá ningún efecto en archivos especiales FIFO o archivos de dispositivos terminales. Su efecto en otros tipos de archivos está definido por la implementación. El resultado de usar O_TRUNCsin cualquiera O_RDWRo O_WRONLYno está definido.

Se usa con frecuencia cuando el programa tiene como objetivo sobrescribir el contenido de un archivo por completo. Un ejemplo es el operador de redirección de archivos de su shell como en command > file.

David Foerster
fuente