É possível obter o nome do arquivo de um descritor de arquivo (Linux) em C?
É possível obter o nome do arquivo de um descritor de arquivo (Linux) em C?
Respostas:
Você pode usar readlink
em /proc/self/fd/NNN
onde NNN é o descritor de arquivo. Isso fornecerá o nome do arquivo como estava quando foi aberto - entretanto, se o arquivo foi movido ou excluído desde então, ele pode não ser mais preciso (embora o Linux possa rastrear renomeações em alguns casos). Para verificar, stat
o nome do arquivo dado e fstat
o fd que você tem, e certifique-se st_dev
e st_ino
são os mesmos.
Obviamente, nem todos os descritores de arquivo se referem a arquivos e, para eles, você verá algumas strings de texto estranhas, como pipe:[1538488]
. Como todos os nomes de arquivos reais serão caminhos absolutos, você pode determinar quais são facilmente. Além disso, como outros notaram, os arquivos podem ter vários links físicos apontando para eles - isso só informará aquele com o qual foi aberto. Se você quiser encontrar todos os nomes de um determinado arquivo, terá apenas que percorrer todo o sistema de arquivos.
fd
seria essa referência), o número do inode não pode ser reutilizado. Qualquer software que faça uso de um número de inode depois de fechar o arquivo ou antes de abri-lo está inerentemente sujeito a condições de corrida.
setuid()
truques, é possível /proc/self/fd
que seu processo não fique acessível. Veja: permalink.gmane.org/gmane.linux.kernel/1302546
Tive esse problema no Mac OS X. Não temos um /proc
sistema de arquivos virtual, então a solução aceita não funciona.
Em vez disso, temos um 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.
Portanto, para obter o arquivo associado a um descritor de arquivo, você pode usar este 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
}
Como nunca me lembro onde MAXPATHLEN
está definido, pensei que PATH_MAX
syslimits seria bom.
getsockname
.
No Windows, com GetFileInformationByHandleEx , passando FileNameInfo , você pode recuperar o nome do arquivo.
Como Tyler aponta, não há como fazer o que você precisa "direta e confiável", uma vez que um determinado FD pode corresponder a 0 nomes de arquivo (em vários casos) ou> 1 (vários "links físicos" é como a última situação é geralmente descrita ) Se você ainda precisa da funcionalidade com todas as limitações (na velocidade E na possibilidade de obter 0, 2, ... resultados em vez de 1), veja como você pode fazer isso: primeiro, fstat o FD - isso lhe diz , no resultado struct stat
, em qual dispositivo o arquivo reside, quantos links físicos ele possui, se é um arquivo especial, etc. Isso já pode responder à sua pergunta - por exemplo, se 0 links físicos você SABER que de fato não há nenhum nome de arquivo correspondente no disco.
Se as estatísticas te dão esperança, então você tem que "andar na árvore" de diretórios no dispositivo relevante até encontrar todos os links físicos (ou apenas o primeiro, se você não precisar de mais de um e qualquer um servirá ) Para esse propósito, você usa readdir (e opendir & c, é claro) abrindo subdiretórios recursivamente até encontrar em um, struct dirent
portanto, recebeu o mesmo número de inode que você tinha no original struct stat
(nesse momento, se você quiser todo o caminho, em vez de apenas o nome, você precisará percorrer a cadeia de diretórios para trás para reconstruí-la).
Se esta abordagem geral for aceitável, mas você precisar de um código C mais detalhado, informe-nos, não será difícil escrever (embora eu prefira não escrevê-lo se for inútil, ou seja, você não pode suportar o desempenho inevitavelmente lento ou o possibilidade de obter! = 1 resultado para os fins de sua aplicação ;-).
Antes de descartar isso como impossível, sugiro que você examine o código-fonte do comando lsof .
Pode haver restrições, mas lsof parece capaz de determinar o descritor e o nome do arquivo. Essas informações existem no sistema de arquivos / proc, portanto, deve ser possível obtê-las em seu programa.
Você pode usar fstat () para obter o inode do arquivo por struct stat. Então, usando readdir () você pode comparar o inode que você encontrou com aqueles que existem (struct dirent) em um diretório (assumindo que você conhece o diretório, caso contrário, você terá que pesquisar todo o sistema de arquivos) e encontrar o nome do arquivo correspondente. Desagradável?
Impossível. Um descritor de arquivo pode ter vários nomes no sistema de arquivos ou pode não ter nenhum nome.
Edit: Supondo que você esteja falando sobre um sistema POSIX simples e antigo, sem APIs específicas do sistema operacional, já que você não especificou um sistema operacional.