Obtener el nombre de archivo del descriptor de archivo en C

¿Es posible obtener el nombre de archivo de un descriptor de archivo (Linux) en C?

Puede usar readlink en /proc/self/fd/NNN donde NNN es el descriptor del 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 preciso (aunque Linux puede rastrear el cambio de nombre en algunos casos). Para verificar, stat el nombre de archivo dado y fstat el fd que tiene, y asegúrese de que st_dev y st_ino son los mismos.

Por supuesto, no todos los descriptores de archivos hacen referencia a los archivos, y para ellos verá algunas cadenas de texto impares, como pipe:[1538488] . Dado que todos los nombres de archivo reales serán rutas absolutas, puede determinar cuáles son lo suficientemente fáciles. Además, como otros han notado, los archivos pueden tener enlaces permanentes múltiples apuntando hacia ellos, esto solo informará sobre el que se abrió. Si desea buscar todos los nombres para un archivo determinado, tendrá que atravesar todo el sistema de archivos.

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

En cambio, tenemos un comando fcntl 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 obtener el archivo asociado a un descriptor de archivo, puede usar este fragmento:

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

Como nunca recuerdo dónde se define MAXPATHLEN , pensé que PATH_MAX de los syslimits estaría bien.

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

Como señala Tyler, no hay forma de hacer lo que requiera “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 cómo se describe generalmente esta última situación) ) Si aún necesita la funcionalidad con todas las limitaciones (en velocidad Y en la posibilidad de obtener 0, 2, … resultados en lugar de 1), aquí le mostramos cómo puede hacerlo: primero, fstat el FD – esto le dice , en la struct stat resultante, en qué dispositivo vive el archivo, cuántos enlaces duros tiene, si es un archivo especial, etc. Esto ya puede responder a su pregunta; por ejemplo, si tiene 0 enlaces duros, SABER que de hecho no existe nombre de archivo correspondiente en el disco.

Si las estadísticas te dan esperanza, entonces tienes que “recorrer el árbol” de directorios en el dispositivo relevante hasta que encuentres todos los enlaces duros (o solo el primero, si no necesitas más de uno y cualquiera lo hará) ) Para ese propósito, usas readdir (y opendir & c por supuesto) abriendo recursivamente subdirectorios hasta que encuentres en una struct dirent así recibiste el mismo número de inodo que tenías en la struct stat (en ese momento si quieres la ruta completa, en lugar de solo el nombre, tendrá que recorrer la cadena de directorios hacia atrás para reconstruirlo).

Si este enfoque general es aceptable, pero necesita un código C más detallado, háganoslo saber, no será difícil 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 para los fines de su aplicación ;-).

Antes de escribir esto como imposible, sugiero que mires el código fuente del comando lsof .

Puede haber restricciones pero lsof parece capaz de determinar el descriptor de archivo y el nombre de archivo. Esta información existe en el sistema de archivos / proc, por lo que debería ser posible acceder desde su progtwig.

Puede usar fstat () para obtener el inode del archivo mediante struct stat. Luego, usando readdir () puedes comparar el inodo que encontraste con los que existen (struct dirent) en un directorio (asumiendo que conoces el directorio, de lo contrario tendrás que buscar todo el sistema de archivos) y encontrar el nombre de archivo correspondiente. ¿Asqueroso?

Imposible. Un descriptor de archivo puede tener varios nombres en el sistema de archivos, o puede no tener ningún nombre.

Editar: Suponiendo que está hablando de un viejo sistema POSIX simple, sin ninguna API específica del sistema operativo, ya que no especificó un sistema operativo.