Volver a vincular un archivo anónimo (no vinculado pero abierto)

En Unix, es posible crear un identificador para un archivo anónimo, por ejemplo, crearlo y abrirlo con creat () y luego eliminar el enlace del directorio con unlink (), dejándolo con un archivo con inodo y almacenamiento, pero no hay forma posible de hacerlo. para volver a abrirlo. Dichos archivos a menudo se usan como archivos temporales (y típicamente esto es lo que tmpfile () le devuelve).

Mi pregunta: ¿hay alguna forma de volver a adjuntar un archivo como este en la estructura del directorio? Si pudieras hacer esto, significa que podrías, por ejemplo, implementar escrituras de archivo para que el archivo aparezca atómico y completamente formado. Esto apela a mi pulcritud compulsiva. 😉

Al hojear las funciones de llamada al sistema relevantes, esperaba encontrar una versión de link () llamada flink () (compárese con chmod () / fchmod ()) pero, al menos en Linux, esto no existe.

Puntos de bonificación por decirme cómo crear el archivo anónimo sin exponer brevemente un nombre de archivo en la estructura de directorios del disco.

Hace varios años se envió un parche para una llamada al sistema Linux flink() propuesta , pero cuando Linus declaró “no hay forma de que HELL pueda hacerlo de forma segura sin otras incursiones” , eso prácticamente puso fin al debate sobre si añadir esto .

Actualización: a partir de Linux 3.11, ahora es posible crear un archivo sin entrada de directorio usando open() con el nuevo indicador O_TMPFILE , y vincularlo al sistema de archivos una vez que está completamente formado usando linkat() en /proc/self/fd/ fd con el indicador AT_SYMLINK_FOLLOW .

El siguiente ejemplo se proporciona en la página de manual de open() :

  char path[PATH_MAX]; fd = open("/path/to/dir", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR); /* File I/O on 'fd'... */ snprintf(path, PATH_MAX, "/proc/self/fd/%d", fd); linkat(AT_FDCWD, path, AT_FDCWD, "/path/for/file", AT_SYMLINK_FOLLOW); 

Tenga en cuenta que linkat() no permitirá que los archivos abiertos se vuelvan a conectar después de eliminar el último enlace con unlink() .

Mi pregunta: ¿hay alguna forma de volver a adjuntar un archivo como este en la estructura del directorio? Si pudieras hacer esto, significa que podrías, por ejemplo, implementar escrituras de archivo para que el archivo aparezca atómico y completamente formado. Esto apela a mi pulcritud compulsiva. 😉

Si este es su único objective, puede lograrlo de una manera mucho más simple y más ampliamente utilizada. Si está a.dat a a.dat :

  1. Abra a.dat.part para escribir.
  2. Escribe tus datos
  3. Cambie el nombre de a.dat.part a a.dat .

Puedo entender que quiero ser limpio, pero desvincular un archivo y volver a vincularlo solo para ser “limpio” es algo tonto.

Esta pregunta sobre la falla del servidor parece indicar que este tipo de enlace no es seguro y no es compatible.

Gracias a @ mark4o publicando sobre linkat(2) , mira su respuesta para más detalles.

Quería probarlo para ver qué sucedió realmente al intentar vincular un archivo anónimo al sistema de archivos en el que está almacenado. (a menudo /tmp , por ejemplo, para datos de video que Firefox está reproduciendo).


A partir de Linux 3.16, todavía parece que no hay forma de recuperar un archivo eliminado que aún se mantiene abierto. Ni AT_SYMLINK_FOLLOW ni AT_EMPTY_PATH para linkat(2) hacen el truco para los archivos eliminados que solían tener un nombre, incluso como raíz.

La única alternativa es tail -c +1 -f /proc/19044/fd/1 > data.recov , que hace una copia por separado, y tienes que eliminarla manualmente cuando esté lista.


Aquí está el envoltorio de perl que preparé para probar. Utilice strace -eopen,linkat linkat.pl - para verificar que su sistema aún no puede recuperar los archivos abiertos. (Lo mismo se aplica incluso con sudo ). Obviamente, debería leer el código que encuentra en Internet antes de ejecutarlo, o usar una cuenta de espacio aislado.

 #!/usr/bin/perl -w # 2015 Peter Cordes  # public domain. If it breaks, you get to keep both pieces. Share and enjoy # Linux-only linkat(2) wrapper (opens "." to get a directory FD for relative paths) if ($#ARGV != 1) { print "wrong number of args. Usage:\n"; print "linkat old new \t# will use AT_SYMLINK_FOLLOW\n"; print "linkat -  

Claramente, esto es posible, fsck hace, por ejemplo. Sin embargo, fsck hace con el principal sistema de archivos localizado mojo y claramente no será portátil ni ejecutable como un usuario sin privilegios. Es similar al comentario de debugfs anterior.

Escribir ese llamado flink(2) sería un ejercicio interesante. Como señala ijw, ofrecería algunas ventajas sobre la práctica actual de cambio de nombre de archivo temporal (cambiar el nombre, nota, se garantiza atómico).

Hace un tiempo, pero acabo de encontrar http://computer-forensics.sans.org/blog/2009/01/27/recovering-open-but-unlinked-file-data que puede responder a la pregunta. No lo he probado, así que, YMMV. Se ve bien.