Как получить общее доступное дисковое пространство в системах Posix? - PullRequest
5 голосов
/ 10 октября 2010

Я пишу кроссплатформенное приложение, и мне нужно общее доступное дисковое пространство.Для систем posix (Linux и Macos) я использую statvfs.Я создал этот метод C ++:

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

К сожалению, я получаю довольно странные значения, которые не могу понять.Например: f_blocks = 73242188 f_bsize = 1048576 f_bfree = 50393643 ...

Являются ли эти значения в битах, байтах или чем-то еще?Я читаю здесь, на stackoverflow, это должны быть байты, но тогда я получу общее количество свободных байтов: f_bsize * f_bfree = 1048576 * 50393643, но это означает 49212.542GB ... слишком много ...

AmЯ делаю что-то не так с кодом или что-то еще?Спасибо!

Ответы [ 4 ]

8 голосов
/ 10 октября 2010

Я не знаю OSX достаточно хорошо, чтобы предсказать, что это определенно ответ, но f_blocks и f_bfree на самом деле относятся к «фундаментальным блокам» или «фрагментам» (размером buf.f_frsize байтов)не «размер блока файловой системы» (который составляет buf.f_bsize байт):

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

f_bsize - это просто подсказка, какой предпочтительный размер для операций ввода-вывода, этоне обязательно имеет отношение к разделению файловой системы.

3 голосов
/ 26 апреля 2012

следующие строки:

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

Будет вызывать переполнение при наличии огромных HD.

Я тоже получал странные результаты, пока не выяснил, что мой HD равен 455 ГБ, пожалуйста, перед тем, как умножить, рассмотрите приведение блоков, blksize и freeblks vars к unsigned задолго до *.

Примерно так:

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

Я видел много подобных вопросов, но никто не заметил этого в ответах.

2 голосов
/ 11 октября 2010

Полагаю, последние два ответа верны и полезны. Однако я решил, просто заменив функцию statvfs на функцию statfs . Размер блока составляет 4096, как и ожидалось, и все кажется правильным. Спасибо!

1 голос
/ 14 января 2015
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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...