GNU/Linux >> Tutoriales Linux >  >> Linux

Recuperar nombre de archivo del descriptor de archivo en C

Tuve este problema en Mac OS X. No tenemos un /proc sistema de archivos virtual, por lo que la solución aceptada no puede funcionar.

En cambio, tenemos un F_GETPATH comando para fcntl :

 F_GETPATH          Get the path of the file descriptor Fildes.  The argu-
                    ment must be a buffer of size MAXPATHLEN or greater.

Entonces, para asociar el archivo a un descriptor de archivo, puede usar este fragmento:

#include <sys/syslimits.h>
#include <fcntl.h>

char filePath[PATH_MAX];
if (fcntl(fd, F_GETPATH, filePath) != -1)
{
    // do something with the file path
}

Ya que nunca recuerdo donde MAXPATHLEN está definido, pensé PATH_MAX de syslimits estaría bien.


Puedes usar readlink el /proc/self/fd/NNN donde NNN es el descriptor de archivo. Esto le dará el nombre del archivo tal como era cuando se abrió; sin embargo, si el archivo se movió o eliminó desde entonces, es posible que ya no sea exacto (aunque Linux puede rastrear los cambios de nombre en algunos casos). Para verificar, stat el nombre de archivo dado y fstat el fd que tienes, y asegúrate de que st_dev y st_ino son iguales.

Por supuesto, no todos los descriptores de archivos se refieren a archivos, y para ellos verá algunas cadenas de texto extrañas, como pipe:[1538488] . Dado que todos los nombres de archivo reales serán rutas absolutas, puede determinar cuáles son con bastante facilidad. Además, como han notado otros, los archivos pueden tener múltiples enlaces duros que apuntan a ellos; esto solo informará con el que se abrió. Si desea encontrar todos los nombres de un archivo determinado, solo tendrá que recorrer todo el sistema de archivos.


Como señala Tyler, no hay forma de hacer lo que necesita "directa y confiablemente", ya que un FD dado puede corresponder a 0 nombres de archivo (en varios casos) o> 1 (múltiples "enlaces duros" es como generalmente se describe la última situación ). Si aún necesita la funcionalidad con todas las limitaciones (sobre la velocidad Y sobre la posibilidad de obtener 0, 2, ... resultados en lugar de 1), así es como puede hacerlo:primero, fstat el FD:esto le dice , en el struct stat resultante , en qué dispositivo se encuentra el archivo, cuántos enlaces duros tiene, si es un archivo especial, etc. Esto ya puede responder a su pregunta, p. si hay 0 enlaces fijos, SABRÁ que, de hecho, no hay un nombre de archivo correspondiente en el disco.

Si las estadísticas le dan esperanza, entonces tiene que "recorrer el árbol" de directorios en el dispositivo relevante hasta que encuentre todos los enlaces duros (o solo el primero, si no necesita más de uno y cualquiera servirá). ). Para ese propósito, usa readdir (y opendir &c por supuesto) abriendo subdirectorios recursivamente hasta que encuentre en un struct dirent así recibió el mismo número de inodo que tenía en el struct stat original (En ese momento, si desea la ruta completa, en lugar de solo el nombre, deberá recorrer la cadena de directorios hacia atrás para reconstruirla).

Si este enfoque general es aceptable, pero necesita un código C más detallado, infórmenos, no será difícil de escribir (aunque prefiero no escribirlo si es inútil, es decir, no puede soportar el rendimiento inevitablemente lento o el posibilidad de obtener !=1 resultado a efectos de su aplicación;-).


En Windows, con GetFileInformationByHandleEx, pasando FileNameInfo, puede recuperar el nombre del archivo.


Linux
  1. ¿Cómo catear un archivo de Awk?

  2. Awk de diferentes líneas?

  3. Lectura de un archivo en ensamblaje

  4. Agregar marca de tiempo a un nombre de archivo con mv en BASH

  5. ¿Cómo crear un archivo en Linux desde la ventana de terminal?

Cómo obtener el nombre de archivo de la ruta completa en Linux

Cómo quitar (^M) caracteres de un archivo en Linux

¿Leyendo patrones Grep de un archivo?

¿Por qué es tan difícil encontrar un archivo en Ubuntu?

copiar archivo de windows a linux

La forma más segura de forzar el cierre de un descriptor de archivo