2010-10-10 28 views
5

Tôi đang viết một ứng dụng đa nền tảng và tôi cần tổng dung lượng đĩa sẵn có. Đối với hệ thống posix (Linux và Macos) tôi đang sử dụng statvfs. Tôi đã tạo phương pháp C++ này:Làm thế nào để có được tổng dung lượng đĩa sẵn có trong các hệ thống 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; 
    } 
} 

Thật không may tôi nhận được các giá trị khá lạ mà tôi không thể hiểu được. Ví dụ: f_blocks = 73.242.188 f_bsize = 1048576 f_bfree = 50.393.643 ...

Là những giá trị trong bit, byte hoặc bất cứ điều gì khác? Tôi đọc ở đây trên stackoverflow những người cần được byte, nhưng sau đó tôi sẽ nhận được tổng số byte miễn phí là: f_bsize * f_bfree = 1048576 * 50.393.643 nhưng điều này có nghĩa 49212.542GB ... quá nhiều ...

Am Tôi làm điều gì đó sai với mã hoặc bất cứ điều gì khác? Cảm ơn!

+0

Bạn đang sử dụng hệ thống tệp nào có kích thước khối 1048576? –

+0

Đây là một hệ điều hành Mac mở rộng (Phân biệt chữ hoa chữ thường, được ghi nhật ký). Ngay bây giờ tôi đang làm việc trên mac, nhưng, theo như tôi có thể hiểu, điều này là nghĩa vụ phải làm việc. –

+0

Ngoài sự kỳ quặc với kích thước khối và ổ đĩa 70TB bị cáo buộc của bạn - hãy cẩn thận rằng một 'dài' trên OSX 32 bit chỉ là 32 bit. Ngay cả khi bạn có số lượng phù hợp, điều đó có thể đủ lớn cho số lượng * khối * của bạn, nhưng không đủ lớn cho số lượng * byte * của bạn. Ổ đĩa lớn như 4GB có sẵn từ các nhà cung cấp chuyên nghiệp ;-) –

Trả lời

2

Tôi cho rằng hai câu trả lời cuối cùng là chính xác và hữu ích. Tuy nhiên, tôi đã giải quyết bằng cách thay thế chức năng statvfs bằng chức năng statfs. Kích thước khối sau đó là 4096 như mong đợi và mọi thứ dường như là chính xác. Cảm ơn!

+1

'statfs' không được chấp nhận. –

+0

Tôi không thể thấy vị trí 'statfs' không được chấp nhận trên OS X. Ngoài ra' statfs' cũng tạo ra các giá trị chính xác. – codingFriend1

+0

Tôi cũng không thể thấy rằng: https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man2/statfs.2.html. –

8

Tôi không biết OSX cũng đủ để dự đoán điều này chắc chắn là câu trả lời, nhưng f_blocksf_bfree thực sự đề cập đến "các khối cơ bản", hay "mảnh vỡ" (mà có kích thước buf.f_frsize byte), không phải là "hệ thống tập tin khối Kích thước"(đó là buf.f_bsize byte):

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

f_bsize chỉ là một gợi ý gì kích thước ưa thích là cho/O hoạt động, nó cũng không hẳn bất cứ điều gì để làm với cách hệ thống tập tin được chia.

3

Các dòng sau:

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

sẽ gây tràn bộ nhớ khi có HUGE HDS.

Tôi đã nhận được kết quả lạ quá cho đến khi tôi tìm ra HD của tôi là 455GiB, vui lòng xem xét các khối đúc, blksize và freeblks vars để unsigned lâu dài trước khi thực hiện phép nhân.

Something như thế này:

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

Tôi đã nhìn thấy rất nhiều câu hỏi như thế này nhưng không ai nhận thấy điều này trên các câu trả lời.

+0

Tốt bắt! Tôi cũng thấy những con số kỳ lạ là (unsigned long long) – 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; 
} 
Các vấn đề liên quan