开发者

How to obtain total available disk space in Posix systems?

I'm writing a cross-platform application, and I need the total available disk space. For posix systems (Linux and Macos) I'm using statvfs. I created this C++ method:

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;
开发者_运维问答   }
}

Unfortunately I'm getting quite strange values I can't understand. For instance: f_blocks = 73242188 f_bsize = 1048576 f_bfree = 50393643 ...

Are those values in bits, bytes or anything else? I read here on stackoverflow those should be bytes, but then I would get the total number of bytes free is: f_bsize*f_bfree = 1048576*50393643 but this means 49212.542GB... too much...

Am I doing something wrong with the code or anything else? Thanks!


I don't know OSX well enough to predict this is definitely the answer, but f_blocks and f_bfree actually refer to "fundamental blocks", or "fragments" (which are of size buf.f_frsize bytes), not the "filesystem block size" (which is buf.f_bsize bytes):

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

f_bsize is just a hint what the preferred size is for I/O operations, it's not necessarily anything to do with how the filesystem is divided.


The following lines:

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

Will cause overflow when having HUGE HDs.

I was getting strange results too until I figured out my HD is 455GiB , please consider casting blocks,blksize and freeblks vars to unsigned long long before doing the multiplication .

Something like this:

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

I've seen lots of questions like this but nobody noticed this on the answers.


I suppose the last two answers are correct and useful. However I solved by simply replacing the function statvfs with the function statfs. The block size is then 4096 as expected and everything seems to be correct. Thanks!


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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜