2010-10-10 15 views
5

Piszę aplikację wieloplatformową i potrzebuję całkowitego dostępnego miejsca na dysku. W systemach posix (Linux i MacOS) używam statvfs. Stworzyłem tę metodę C++:Jak uzyskać całkowitą dostępną przestrzeń dyskową w systemach Posix?

long OSSpecificPosix::getFreeDiskSpace(const char* absoluteFilePath) { 
    struct statvfs buf; 

    if (!statvfs(absoluteFilePath, &buf)) { 
     unsigned long blksize, blocks, freeblks, disk_size, used, free; 
     blksize = buf.f_bsize; 
     blocks = buf.f_blocks; 
     freeblks = buf.f_bfree; 

     disk_size = blocks*blksize; 
     free = freeblks*blksize; 
     used = disk_size - free; 

     return free; 
    } 
    else { 
     return -1; 
    } 
} 

Niestety, otrzymuję dość dziwne wartości, których nie mogę zrozumieć. Na przykład: f_blocks = 73242188 = 1048576 f_bsize f_bfree = 50393643 ...

Czy te wartości w bitów, bajtów lub cokolwiek innego? Czytałem tutaj na stackoverflow te powinny być bajtów, ale chciałbym uzyskać całkowitą liczbę bajtów wolnych jest: f_bsize * f_bfree = 1048576 * 50393643 ale to oznacza 49212.542GB ... zbyt dużo ...

Am Robię coś nie tak z kodem lub cokolwiek innego? Dzięki!

+0

Jaki system plików używasz, który ma rozmiar bloku 1048576? –

+0

To jest Mac OS Extended (Case-Sensitive, Journaled). Obecnie pracuję na Macu, ale, o ile mogę to zrozumieć, to ma działać. –

+0

Poza dziwactwem rozmiaru bloku i rzekomego napędu o pojemności 70 TB - należy pamiętać, że "długi" na 32-bitowym OSX ma tylko 32 bity. Nawet jeśli masz odpowiednie liczby, prawdopodobnie jest to wystarczająco duża liczba * bloków *, ale nie jest wystarczająco duża dla liczby * bajtów *. Napędy o pojemności 4 GB są łatwo dostępne u wyspecjalizowanych dostawców ;-) –

Odpowiedz

2

Przypuszczam, że ostatnie dwie odpowiedzi są poprawne i użyteczne. Jednak rozwiązałem przez zastąpienie funkcji statvfs z funkcją statfs. Rozmiar bloku wynosi wtedy 4096 zgodnie z oczekiwaniami i wszystko wydaje się poprawne. Dzięki!

+1

'statfs' jest przestarzałe. –

+0

Nie widzę, gdzie 'statfs' jest przestarzałe na OS X. Również' statfs' produkuje prawidłowe wartości. – codingFriend1

+0

Nie widzę tego również: https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man2/statfs.2.html. –

8

nie wiem OSX na tyle dobrze, aby przewidzieć, jest to z pewnością odpowiedź, ale f_blocks i f_bfree rzeczywiście odnoszą się do „podstawowych bloków”, lub „fragmentów” (które są wielkości buf.f_frsize bajtów), a nie „blok plików rozmiar”(co jest buf.f_bsize bajtów):

http://www.opengroup.org/onlinepubs/009695399/basedefs/sys/statvfs.h.html

f_bsize jest tylko wskazówką co preferowany rozmiar jest dla operacji I/o, to nie koniecznie coś zrobić z tym, jak system plików jest podzielony.

3

następujące wiersze:

disk_size = blocks*blksize; 
free = freeblks*blksize; 

spowoduje przepełnienie gdy mający ogromny HDS.

Również otrzymywałem dziwne wyniki, dopóki nie doszedłem do wniosku, że moja HD to 455GiB, proszę rozważyć rzucenie bloków, blksize i freeblks vars do unsigned long long przed wykonaniem multiplikacji.

coś takiego:

unsigned long long disk_size = (unsigned long long) (blocks) * (unsigned long long) (blksize) 

Widziałem wiele pytań, takich jak to, ale nikt nie zauważył to od odpowiedzi.

+0

Dobry połów! Też widziałem te dziwne liczby (niepodpisane długo) – lppier

1
uint64_t userAvailableFreeSpace() 
{ 
    struct statvfs stat; 
    struct passwd *pw = getpwuid(getuid()); 
    if (NULL != pw && 0 == statvfs(pw->pw_dir, &stat)) 
    { 
     uint64_t freeBytes = (uint64_t)stat.f_bavail * stat.f_frsize; 
     return freeBytes; 
    } 
    return 0ULL; 
} 
Powiązane problemy