GNU/Linux >> Linux Esercitazione >  >> Linux

Recupera il nome del file dal descrittore di file in C

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 associare il file a un descrittore di file, puoi utilizzare questo snippet:

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

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

Dal momento che non ricordo mai dove MAXPATHLEN è definito, ho pensato PATH_MAX da syslimits andrebbe bene.


Puoi usare 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 eliminato da allora, potrebbe non essere più accurato (sebbene Linux possa tenere traccia delle rinominazioni 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 sono uguali.

Naturalmente, 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 determinato file, dovrai solo attraversare l'intero filesystem.


Come sottolinea Tyler, non c'è modo di fare ciò di cui hai bisogno "direttamente e in modo affidabile", poiché un dato FD può corrispondere a 0 nomi di file (in vari casi) o> 1 (più "hard link" è come viene generalmente descritta quest'ultima situazione ). Se hai ancora bisogno della funzionalità con tutte le limitazioni (sulla velocità E sulla possibilità di ottenere 0, 2, ... risultati anziché 1), ecco come puoi farlo:in primo luogo, fstat l'FD - questo ti dice , nel risultante struct stat , su quale dispositivo risiede il file, quanti hard link ha, se si tratta di un file speciale, ecc. Questo potrebbe già rispondere alla tua domanda, ad es. se 0 hard link saprai che in realtà non esiste alcun nome di file corrispondente sul 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 di più di uno e uno qualsiasi andrà bene ). A tale scopo, usi readdir (e opendir &c ovviamente) aprendo in modo ricorsivo le sottodirectory finché non trovi in ​​un struct dirent ha quindi ricevuto lo stesso numero di inode che avevi nel struct stat originale (a quel punto se vuoi l'intero percorso, piuttosto che solo il nome, dovrai ripercorrere 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 della tua candidatura;-).


In Windows, con GetFileInformationByHandleEx, passando FileNameInfo, puoi recuperare il nome del file.


Linux
  1. Lettura da un file in assembly

  2. Aggiunta di timestamp a un nome file con mv in BASH

  3. Come creare un file in Linux dalla finestra del terminale?

  4. È possibile utilizzare / in un nome file?

  5. Crea un PEM da un file PPK

Come ottenere il nome del file dal percorso completo in Linux

Come rimuovere (^M) caratteri da un file in Linux

Perché è così difficile trovare un file in Ubuntu?

in che modo cp -f è diverso da cp --remove-destination?

Il modo più sicuro per forzare la chiusura di un descrittore di file

Comando Linux per recuperare un intervallo di byte da un file