2013-03-27 43 views
6

Dưới Linux, tôi có hai đường dẫn tập tin A và B:Xác định xem hai đường dẫn tệp có trỏ đến cùng một tệp trong Linux/C không?

const char* A = ...; 
const char* B = ...; 

bây giờ tôi muốn xác định, tôi nên open(2) cả hai ...

int fda = open(A, ...); 
int fdb = open(B, ...); 

... Tôi sẽ nhận được hai filehandles mở cùng một tệp trong hệ thống tệp?

Để xác định điều này tôi nghĩ stat(2):

struct stat 
{ 
    dev_t st_dev; 
    ino_t st_ino; 
    ... 
} 

Giống như (pseudo-code):

bool IsSameFile(const char* sA, const char* sB) 
{ 
    stat A = stat(sA); 
    stat B = stat(sB); 

    return A.st_dev == B.st_dev && A.st_ino == B.st_ino; 
} 

Có bất kỳ trường hợp A và B là các tập tin tương tự nhưng IsSameFile sẽ trở lại sai?

Có trường hợp nào A và B là các tệp khác nhau nhưng IsSameFile sẽ trả về true?

Có cách nào tốt hơn để làm những gì tôi đang cố gắng làm không?

+0

Bạn có thể có nhiều bộ mô tả tệp tham chiếu đến cùng một tệp, vâng. – teppic

+0

@teppic: Có, và bạn cũng có thể có nhiều bộ mô tả tệp tham chiếu đến các tệp khác nhau. Câu hỏi của tôi là làm cách nào để xác định hai vũ trụ mà tôi đang ở (hoặc sẽ ở trong) –

+0

Nếu bạn mở các bộ mô tả tập tin, bạn có thể sử dụng 'fstat' trực tiếp trên chúng - nếu các số inode và số thiết bị bằng nhau , hai con đường không thể tham chiếu đến các tệp khác nhau. – teppic

Trả lời

4

Chương trình của bạn sẽ hoạt động tốt trong tất cả các trường hợp vì A.st_ino sẽ trả lại số số inode của các tệp trong hệ thống của bạn. Vì số inode là duy nhất nên chương trình của bạn sẽ xác định chính xác xem hai tệp đã mở có giống nhau hay không.

Bạn cũng có thể kiểm tra giá trị A.st_mode để tìm hiểu xem tệp có phải là liên kết tượng trưng hay không.

+2

Bạn chỉ có thể tìm ra rằng tên là một liên kết tượng trưng (bị hỏng) thông qua 'stat()' nếu thực ra nó là một liên kết tượng trưng bị hỏng. Nếu nó không bị hỏng, các báo cáo 'stat()' trên tệp hoặc thiết bị ở cuối liên kết; 'lstat()' báo cáo trên liên kết (đầu tiên) nếu tên là một liên kết tượng trưng. –

0

Tùy thuộc vào lý do chính xác bạn muốn tránh mở cùng một tệp hai lần. Giải pháp của bạn thường là giải pháp đúng, nhưng có một số tình huống trong đó các tệp phải được xem là giống nhau nếu chúng có cùng đường dẫn tuyệt đối nhưng không phải nếu chúng là các liên kết đến cùng một inode. Trong trường hợp đó, bạn cần phải chuyển đổi đường dẫn thành đường dẫn tuyệt đối và so sánh chúng ... xem Getting absolute path of a file

Bạn cũng cần quyết định xem bạn có xem liên kết tượng trưng đến tệp tương đương với tệp hoặc liên kết tượng trưng khác không. Đối với tính tương đương inode, xác định có sử dụng stat hoặc lstat hay không. Đối với tương đương đường dẫn, nó xác định xem bạn có thể sử dụng realpath hoặc nếu bạn cần có đường dẫn tuyệt đối không có các liên kết tượng trưng sau đây.

+1

Sử dụng 'stat()', mã sẽ không được biết đến với các liên kết tượng trưng (ngoại trừ các liên kết có thể bị hỏng). Bạn có thể xây dựng trên 'một số tình huống mà các tập tin cần được xem xét giống nhau nếu chúng có cùng một đường dẫn tuyệt đối nhưng không nếu chúng là các liên kết đến cùng một inode'? –

+0

@JonathanLeffler "Sử dụng stat(), mã sẽ không được biết đến với các liên kết tượng trưng" - nhưng không sử dụng * lstat * - đó chính xác là sự khác biệt mà tôi tạo ra.Xây dựng: một số đề án sao lưu yêu cầu các tệp được sao chép một lần cho mỗi đường dẫn (đặc biệt nếu khôi phục sẽ được thực hiện cho một fs không hỗ trợ liên kết cứng), trong khi không có điểm nào trong việc lưu cùng một đường dẫn hai lần. Chúng có thể là các trường hợp sử dụng khác. Nhưng như tôi đã nói, inode tương đương là ** thường ** những gì là mong muốn. –

+0

@JonathanLeffler Và thực sự nó là 'lstat' không biết gì về các liên kết tượng trưng, ​​trong khi' stat' thực hiện 'readlink' hiệu quả trên chúng và theo chúng. Trong thực tế, việc thực hiện 'lstat' chỉ là việc thực hiện' stat' trước khi có các liên kết tượng trưng (ví dụ, tôi đã viết mã hạt nhân UNIX trở lại sau đó). –

Các vấn đề liên quan