Có thể lấy tên tệp của bộ mô tả tệp (Linux) trong C không?
Có thể lấy tên tệp của bộ mô tả tệp (Linux) trong C không?
Câu trả lời:
Bạn có thể sử dụng readlink
trên /proc/self/fd/NNN
nơi NNN là mô tả tập tin. Điều này sẽ cung cấp cho bạn tên của tệp như khi nó được mở - tuy nhiên, nếu tệp đã bị di chuyển hoặc bị xóa kể từ đó, nó có thể không còn chính xác nữa (mặc dù Linux có thể theo dõi tên trong một số trường hợp). Để xác minh, stat
tên tệp đã cho và fstat
fd bạn có, đồng thời đảm bảo st_dev
và st_ino
giống nhau.
Tất nhiên, không phải tất cả các trình mô tả tệp đều tham chiếu đến tệp và đối với những tệp đó, bạn sẽ thấy một số chuỗi văn bản kỳ lạ, chẳng hạn như pipe:[1538488]
. Vì tất cả các tên tệp thực sẽ là đường dẫn tuyệt đối, bạn có thể dễ dàng xác định chúng là đủ. Hơn nữa, như những người khác đã lưu ý, các tệp có thể có nhiều liên kết cứng trỏ đến chúng - điều này sẽ chỉ báo cáo tệp được mở bằng. Nếu bạn muốn tìm tất cả các tên cho một tệp nhất định, bạn sẽ phải duyệt qua toàn bộ hệ thống tệp.
fd
sẽ là tham chiếu như vậy), số inode không thể được sử dụng lại. Bất kỳ phần mềm nào sử dụng số inode sau khi đóng tệp hoặc trước khi mở tệp vốn dĩ phải tuân theo các điều kiện chủng tộc.
setuid()
thủ thuật, có thể /proc/self/fd
quy trình của bạn không thể truy cập được. Xem: permalink.gmane.org/gmane.linux.kernel/1302546
Tôi gặp sự cố này trên Mac OS X. Chúng tôi không có /proc
hệ thống tệp ảo, vì vậy giải pháp được chấp nhận không thể hoạt động.
Thay vào đó, chúng tôi có một F_GETPATH
lệnh cho fcntl
:
F_GETPATH Get the path of the file descriptor Fildes. The argu-
ment must be a buffer of size MAXPATHLEN or greater.
Vì vậy, để có được tệp được liên kết với trình mô tả tệp, bạn có thể sử dụng đoạn mã này:
#include <sys/syslimits.h>
#include <fcntl.h>
char filePath[PATH_MAX];
if (fcntl(fd, F_GETPATH, filePath) != -1)
{
// do something with the file path
}
Vì tôi không bao giờ nhớ nơi MAXPATHLEN
được xác định, tôi nghĩ PATH_MAX
từ syslimits sẽ ổn.
getsockname
.
Trong Windows, với GetFileInformationByHandleEx , truyền FileNameInfo , bạn có thể truy xuất tên tệp.
Như Tyler đã chỉ ra, không có cách nào để thực hiện những gì bạn yêu cầu "trực tiếp và đáng tin cậy", vì FD nhất định có thể tương ứng với 0 tên tệp (trong các trường hợp khác nhau) hoặc> 1 (nhiều "liên kết cứng" là cách tình huống thứ hai thường được mô tả ). Nếu bạn vẫn cần chức năng với tất cả các giới hạn (về tốc độ VÀ khả năng nhận được kết quả 0, 2, ... thay vì 1), đây là cách bạn có thể làm điều đó: trước tiên, hãy gõ FD - điều này cho bạn biết , kết quả là struct stat
thiết bị của tệp, có bao nhiêu liên kết cứng, đó có phải là tệp đặc biệt hay không, v.v. Điều này có thể đã trả lời câu hỏi của bạn - ví dụ: nếu 0 liên kết cứng, bạn sẽ BIẾT thực tế không có tên tệp tương ứng trên đĩa.
Nếu số liệu thống kê mang lại cho bạn hy vọng, thì bạn phải "đi dạo trên cây" các thư mục trên thiết bị có liên quan cho đến khi bạn tìm thấy tất cả các liên kết cứng (hoặc chỉ liên kết đầu tiên, nếu bạn không cần nhiều hơn một và bất kỳ liên kết nào sẽ làm được ). Với mục đích đó, bạn sử dụng readdir (và tất nhiên là opendir & c) mở một cách đệ quy các thư mục con cho đến khi bạn tìm thấy trong một thư mục con struct dirent
do đó nhận được cùng một số inode mà bạn có trong bản gốc struct stat
(tại thời điểm đó nếu bạn muốn toàn bộ đường dẫn, thay vì chỉ tên, bạn sẽ cần phải đi ngược lại chuỗi thư mục để xây dựng lại nó).
Nếu cách tiếp cận chung này có thể chấp nhận được, nhưng bạn cần mã C chi tiết hơn, hãy cho chúng tôi biết, nó sẽ không khó viết (mặc dù tôi không muốn viết nó nếu nó vô dụng, tức là bạn không thể chịu được hiệu suất chậm chắc chắn hoặc khả năng nhận được! = 1 kết quả cho các mục đích của ứng dụng của bạn ;-).
Bạn có thể sử dụng fstat () để lấy inode của tệp theo struct stat. Sau đó, sử dụng readdir (), bạn có thể so sánh inode bạn tìm thấy với những inode tồn tại (struct dirent) trong một thư mục (giả sử rằng bạn biết thư mục, nếu không bạn sẽ phải tìm kiếm toàn bộ hệ thống tệp) và tìm tên tệp tương ứng. Bẩn thỉu?
Không thể nào. Một bộ mô tả tệp có thể có nhiều tên trong hệ thống tệp hoặc nó có thể không có tên nào cả.
Chỉnh sửa: Giả sử bạn đang nói về một hệ thống POSIX cũ thuần túy, không có bất kỳ API dành riêng cho hệ điều hành nào, vì bạn không chỉ định một hệ điều hành.