È possibile ottenere il nome del file di un descrittore di file (Linux) in C?
È possibile ottenere il nome del file di un descrittore di file (Linux) in C?
Risposte:
È possibile utilizzare readlink
su /proc/self/fd/NNN
dove NNN è il descrittore di file. Questo ti darà il nome del file com'era quando è stato aperto - tuttavia, se il file è stato spostato o cancellato da allora, potrebbe non essere più accurato (sebbene Linux possa tenere traccia delle rinomine in alcuni casi). Per verificare, stat
il nome del file dato e fstat
il fd che hai, e assicurati che st_dev
e st_ino
siano gli stessi.
Ovviamente, non tutti i descrittori di file si riferiscono a file e per quelli vedrai alcune strane stringhe di testo, come pipe:[1538488]
. Poiché tutti i nomi di file reali saranno percorsi assoluti, è possibile determinare quali sono abbastanza facilmente. Inoltre, come altri hanno notato, i file possono avere più collegamenti fisici che puntano a loro: questo riporterà solo quello con cui è stato aperto. Se vuoi trovare tutti i nomi per un dato file, dovrai solo attraversare l'intero filesystem.
fd
sarebbe un tale riferimento), il numero di inode non può essere riutilizzato. Qualsiasi software che utilizza un numero di inode dopo aver chiuso il file o prima di aprirlo è intrinsecamente soggetto a condizioni di competizione.
setuid()
trucchi, è possibile /proc/self/fd
che non sia accessibile dal tuo processo. Vedi: permalink.gmane.org/gmane.linux.kernel/1302546
Ho avuto questo problema su Mac OS X. Non abbiamo un /proc
file system virtuale, quindi la soluzione accettata non può funzionare.
Abbiamo, invece, un F_GETPATH
comando per fcntl
:
F_GETPATH Get the path of the file descriptor Fildes. The argu-
ment must be a buffer of size MAXPATHLEN or greater.
Quindi, per ottenere il file associato a un descrittore di file, puoi usare questo frammento:
#include <sys/syslimits.h>
#include <fcntl.h>
char filePath[PATH_MAX];
if (fcntl(fd, F_GETPATH, filePath) != -1)
{
// do something with the file path
}
Dato che non ricordo mai dove MAXPATHLEN
è definito, ho pensato che PATH_MAX
da syslimits sarebbe andato bene.
getsockname
.
In Windows, con GetFileInformationByHandleEx , passando FileNameInfo , è possibile recuperare il nome del file.
Come fa notare Tyler, non c'è modo di fare ciò che si richiede "direttamente e in modo affidabile", poiché un dato FD può corrispondere a 0 nomi di file (in vari casi) o> 1 (più "collegamenti fisici" è come viene generalmente descritta l'ultima situazione ). Se hai ancora bisogno della funzionalità con tutte le limitazioni (sulla velocità E sulla possibilità di ottenere 0, 2, ... risultati invece di 1), ecco come puoi farlo: primo, fstat FD - questo ti dice , nel risultato struct stat
, su quale dispositivo risiede il file, quanti collegamenti fisici ha, se si tratta di un file speciale, ecc. Questo potrebbe già rispondere alla tua domanda - ad es. se 0 collegamenti fisici SAPRETE che in realtà non esiste un nome file corrispondente su disco.
Se le statistiche ti danno speranza, allora devi "percorrere l'albero" delle directory sul dispositivo pertinente finché non trovi tutti i collegamenti fisici (o solo il primo, se non ne hai bisogno più di uno e nessuno lo farà ). A tale scopo, usi readdir (e opendir & c ovviamente) aprendo ricorsivamente le sottodirectory finché non trovi in un struct dirent
così ricevuto lo stesso numero di inode che avevi nell'originale struct stat
(in quel momento se vuoi l'intero percorso, piuttosto che solo il nome, dovrai percorrere la catena di directory all'indietro per ricostruirla).
Se questo approccio generale è accettabile, ma hai bisogno di codice C più dettagliato, faccelo sapere, non sarà difficile da scrivere (anche se preferirei non scriverlo se è inutile, cioè non puoi sopportare le prestazioni inevitabilmente lente o il possibilità di ottenere! = 1 risultato ai fini dell'applicazione ;-).
Prima di scrivere questo come impossibile ti suggerisco di guardare il codice sorgente del comando lsof .
Potrebbero esserci delle restrizioni ma lsof sembra in grado di determinare il descrittore e il nome del file. Queste informazioni esistono nel filesystem / proc quindi dovrebbe essere possibile ottenerle dal tuo programma.
Puoi usare fstat () per ottenere l'inode del file da struct stat. Quindi, usando readdir () puoi confrontare l'inode che hai trovato con quelli che esistono (struct dirent) in una directory (assumendo che tu conosca la directory, altrimenti dovrai cercare in tutto il filesystem) e trovare il nome del file corrispondente. Cattiva?
Impossibile. Un descrittore di file può avere più nomi nel filesystem o potrebbe non avere alcun nome.
Modifica: supponendo che tu stia parlando di un semplice vecchio sistema POSIX, senza API specifiche del sistema operativo, poiché non hai specificato un sistema operativo.