C'de bir dosya tanımlayıcısının (Linux) dosya adını almak mümkün müdür?
C'de bir dosya tanımlayıcısının (Linux) dosya adını almak mümkün müdür?
Yanıtlar:
Sen kullanabilirsiniz readlink
üzerinde /proc/self/fd/NNN
NNN dosya tanıtıcısı olduğu. Bu size dosyanın adını, açıldığı zamandaki haliyle verecektir - ancak, o zamandan beri dosya taşınmış veya silinmişse, artık doğru olmayabilir (Linux bazı durumlarda yeniden adları izleyebilmesine rağmen). Doğrulamak için, stat
verilen dosya adı ve fstat
sahip olduğunuz fd st_dev
ve st_ino
aynı olduğundan emin olun .
Elbette, tüm dosya tanımlayıcıları dosyalara atıfta bulunmaz ve bunlar için pipe:[1538488]
. Gerçek dosya adlarının tümü mutlak yollar olacağından, hangilerinin yeterli olduğunu kolayca belirleyebilirsiniz. Ayrıca, diğerlerinin de belirttiği gibi, dosyalar kendilerine işaret eden birden çok sabit bağlantıya sahip olabilir - bu, yalnızca açıldığı dosyayı bildirir. Belirli bir dosya için tüm isimleri bulmak istiyorsanız, sadece tüm dosya sistemini dolaşmanız gerekir.
fd
böyle bir referans olacaktır), inode numarası olamaz yeniden. Dosyayı kapattıktan sonra veya açmadan önce bir inode numarasını kullanan herhangi bir yazılım, doğası gereği yarış koşullarına tabidir.
setuid()
hile yaparsanız /proc/self/fd
, işleminiz tarafından erişilebilir olmamak mümkündür . Bkz: permalink.gmane.org/gmane.linux.kernel/1302546
Mac OS X'te bu sorunu yaşadım. /proc
Sanal dosya sistemimiz yok, bu yüzden kabul edilen çözüm çalışamıyor.
Bunun yerine aşağıdakiler için bir F_GETPATH
emrimiz var fcntl
:
F_GETPATH Get the path of the file descriptor Fildes. The argu-
ment must be a buffer of size MAXPATHLEN or greater.
Dolayısıyla, bir dosya tanımlayıcısıyla ilişkili dosyayı almak için şu pasajı kullanabilirsiniz:
#include <sys/syslimits.h>
#include <fcntl.h>
char filePath[PATH_MAX];
if (fcntl(fd, F_GETPATH, filePath) != -1)
{
// do something with the file path
}
Nerenin MAXPATHLEN
tanımlandığını hiç hatırlamadığım PATH_MAX
için sistem sınırlarından iyi olacağını düşündüm .
getsockname
.
Windows'ta GetFileInformationByHandleEx ile FileNameInfo'yu geçerek dosya adını alabilirsiniz.
Tyler'ın işaret ettiği gibi, istediğiniz şeyi "doğrudan ve güvenilir bir şekilde" yapmanın bir yolu yoktur, çünkü belirli bir FD 0 dosya adına (çeşitli durumlarda) veya> 1'e (birden çok "sabit bağlantı") karşılık gelebilir, son durum genel olarak açıklanır ). Hala tüm sınırlamalarla işlevselliğe ihtiyacınız varsa (hızda VE 1 yerine 0, 2, ... sonuç alma olasılığında), bunu şu şekilde yapabilirsiniz: önce, FD'yi - bu size söyler , sonuçta struct stat
, dosyanın hangi cihazda yaşadığını, kaç tane sabit bağlantıya sahip olduğunu, özel bir dosya olup olmadığını, vb. Bu, sorunuzu zaten yanıtlayabilir - örneğin, 0 sabit bağlantı varsa, gerçekte karşılık gelen bir dosya adı olmadığını BİLECEĞİNİZ diskte.
İstatistikler size umut veriyorsa, tüm sabit bağlantıları bulana kadar (veya birden fazlasına ihtiyacınız yoksa yalnızca ilkini bulana kadar) ilgili cihazdaki dizinlerin "ağacında yürümeniz" gerekir. ). Bu amaçla, readdir (ve tabii ki opendir & c) alt dizinleri tekrar tekrar açarak struct dirent
, orijinalde sahip olduğunuz aynı inode numarasını bulana kadar kullanırsınız struct stat
(bu durumda, sadece ad yerine tüm yolu istiyorsanız, dizinler zincirini yeniden yapılandırmak için geriye doğru yürümeniz gerekir).
Bu genel yaklaşım kabul edilebilirse, ancak daha ayrıntılı C koduna ihtiyacınız varsa, bize bildirin, yazmak zor olmayacaktır (ancak işe yaramazsa yazmamayı tercih ederim, yani kaçınılmaz olarak yavaş performansa veya Başvurunuzun amaçları doğrultusunda! = 1 sonuç alma imkanı ;-).
Struct stat ile dosyanın inode'unu almak için fstat () kullanabilirsiniz. Daha sonra readdir () kullanarak bulduğunuz inode'u bir dizinde bulunanlarla (struct dirent) karşılaştırabilirsiniz (dizini bildiğinizi varsayarak, aksi takdirde tüm dosya sistemini aramanız gerekir) ve ilgili dosya adını bulabilirsiniz. Kötü mü?
İmkansız. Bir dosya tanımlayıcısının dosya sisteminde birden fazla adı olabilir veya hiç adı olmayabilir.
Düzenleme: Bir işletim sistemi belirtmediğiniz için işletim sistemine özgü herhangi bir API olmadan düz eski bir POSIX sisteminden bahsettiğinizi varsayalım.