2013-03-27 39 views
6

Pod Linuksem, mam dwie ścieżki plików A i B:Ustalenie, czy dwie ścieżki do pliku wskazują na ten sam plik w systemie Linux/C?

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

Teraz chcę, aby określić, powinienem je zarówno open(2) ...

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

... dostanę dwa uchwytów plików otworzyć na ten sam plik w systemie plików?

Aby to ustalić, myślałem stat(2):

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

Coś (pseudo-kod):

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; 
} 

Czy istnieją przypadki, gdzie A i B są takie same, ale plik IsSameFile wróci fałszywy?

Czy są przypadki, w których A i B to różne pliki, ale IsSameFile zwróci wartość true?

Czy istnieje lepszy sposób robienia tego, co próbuję zrobić?

+0

Możesz mieć wiele deskryptorów plików, które odnoszą się do tego samego pliku, tak. – teppic

+0

@teppic: Tak, możesz także mieć wiele deskryptorów plików, które odnoszą się do różnych plików. Moje pytanie brzmi: jak określić, który z tych dwóch wszechświatów, w których się znajduję (lub które będą w nim być) –

+0

Jeśli masz otwarte deskryptory plików, możesz po prostu użyć 'fstat' bezpośrednio na nich - jeśli i-węzły i numery urządzeń są równe , nie jest możliwe, aby dwie ścieżki odnosiły się do różnych plików. – teppic

Odpowiedz

4

Twój program będzie działał poprawnie we wszystkich przypadkach, ponieważ A.st_ino zwróci i-węzłów o numerach plików w twoim systemie. Ponieważ numer i-węzła jest unikalny, Twój program poprawnie określi, czy oba otwarte pliki są takie same czy nie.

Można również sprawdzić wartość A.st_mode, aby sprawdzić, czy plik jest linkiem symbolicznym .

+2

Możesz się tylko dowiedzieć, że nazwa jest (zerwanym) dowiązaniem symbolicznym przez 'stat()', jeśli w rzeczywistości jest uszkodzonym dowiązaniem symbolicznym. Jeśli nie jest uszkodzony, 'stat()' zgłasza się do pliku lub urządzenia na końcu łącza; 'lstat()' zgłasza się na (pierwszym) dowiązaniu symbolicznym, jeśli nazwa jest dowiązaniem symbolicznym. –

0

To zależy od tego, dlaczego dokładnie nie chcesz otwierać tego samego pliku dwukrotnie. Twoje rozwiązanie jest zwykle poprawne, ale są sytuacje, w których pliki powinny być traktowane tak samo, jeśli mają tę samą absolutną ścieżkę, ale nie, jeśli są linkami do tego samego i-węzła. W takim przypadku musisz przekonwertować ścieżki na ścieżki bezwzględne i porównać je ... zobacz Getting absolute path of a file

Musisz również zdecydować, czy uważasz dowiązanie symboliczne do pliku równoważnego plikowi, czy też dowiązaniu symbolicznemu do niego. W przypadku równoważności i-węzłów określa, czy używać stat czy lstat. W przypadku równoważności ścieżek określa, czy można użyć realpath, czy też trzeba uzyskać bezwzględną ścieżkę bez następujących dowiązań symbolicznych.

+1

Używając 'stat()', kod będzie niepomny dla dowiązań symbolicznych (z wyjątkiem być może uszkodzonych). Czy możesz rozwinąć "sytuacje, w których pliki powinny być traktowane tak samo, jeśli mają tę samą absolutną ścieżkę, ale nie, jeśli są linkami do tego samego i-węzła"? –

+0

@ JonathanLeffler "Używając stat(), kod będzie obojętny na dowiązania symboliczne" - ale nie używając * lstat * - to dokładnie rozróżnienie, które zrobiłem.Opracowanie: niektóre schematy tworzenia kopii zapasowych wymagają jednokrotnego skopiowania plików dla każdej ścieżki (szczególnie, jeśli przywracanie zostanie wykonane na fs, który nie obsługuje twardych linków), podczas gdy nie ma sensu dwukrotne zapisywanie tej samej ścieżki. Mogą to być inne przypadki użycia. Ale jak powiedziałem, równoważnik i-węzła to ** zwykle ** to, co jest potrzebne. –

+0

@ JonathanLeffler I faktycznie jest to 'lstat', który nie zwraca uwagi na dowiązania symboliczne, podczas gdy' stat' ma efektywny "readlink" na nich i podąża za nimi. W rzeczywistości implementacja 'lstat' jest właśnie tym, co było przed implementacją' stat', zanim pojawiły się dowiązania symboliczne (np. Wtedy pisałem kod jądra UNIX). –