¿Es posible obtener el nombre de archivo de un descriptor de archivo (Linux) en C?
¿Es posible obtener el nombre de archivo de un descriptor de archivo (Linux) en C?
Respuestas:
Se puede utilizar readlink
en /proc/self/fd/NNN
donde NNN es el descriptor de archivo. Esto le dará el nombre del archivo tal como estaba 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 verificarlo, stat
el nombre de archivo dado y fstat
el DF que tiene, y asegúrese st_dev
y st_ino
son los mismos.
Por supuesto, no todos los descriptores de archivo 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 señalado otros, los archivos pueden tener varios vínculos físicos que los apunten; 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.
fd
sería dicha referencia), el número de inodo no se puede reutilizar. Cualquier software que utilice un número de inodo después de cerrar el archivo o antes de abrirlo está inherentemente sujeto a condiciones de carrera.
setuid()
trucos, es posible /proc/self/fd
que su proceso no pueda acceder a él. Ver: permalink.gmane.org/gmane.linux.kernel/1302546
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 obtener el archivo asociado 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
}
Como nunca recuerdo dónde MAXPATHLEN
está definido, pensé que PATH_MAX
desde syslimits estaría bien.
getsockname
.
En Windows, con GetFileInformationByHandleEx , pasando FileNameInfo , puede recuperar el nombre del archivo.
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 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), así es como puede hacerlo: primero, fstat el FD - esto le dice , en el resultado struct stat
, en qué dispositivo vive el archivo, cuántos enlaces físicos tiene, si es un archivo especial, etc. Esto ya puede responder a su pregunta, por ejemplo, si hay 0 enlaces físicos, SABERÁ que de hecho no hay un nombre de archivo correspondiente. en 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 físicos (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 de manera recursiva hasta que encuentre en un struct dirent
así recibido el mismo número de inodo que tenía en el original struct stat
(en ese momento, si desea la ruta completa, en lugar de solo el nombre, necesitará caminar la cadena de directorios hacia atrás para reconstruirlo).
Si este enfoque general es aceptable, pero necesita un código C más detallado, avísenos, 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 para los propósitos de su aplicación ;-).
Antes de descartar esto como imposible, le sugiero que mire el código fuente del comando lsof .
Puede haber restricciones, pero lsof parece capaz de determinar el descriptor y el nombre del archivo. Esta información existe en el sistema de archivos / proc, por lo que debería ser posible acceder a ella desde su programa.
Puede usar fstat () para obtener el inodo del archivo por struct stat. Luego, usando readdir () puede comparar el inodo que encontró con los que existen (struct dirent) en un directorio (asumiendo que conoce el directorio, de lo contrario tendrá que buscar en 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 que no tenga ningún nombre.
Editar: Suponiendo que está hablando de un sistema POSIX antiguo, sin ninguna API específica del sistema operativo, ya que no especificó un sistema operativo.