Как определить нехватку места на диске при использовании файловых операций stdio в C/C++?

Я делаю небольшую программу следующим образом:

void reserve_file_space(char* file_path, size_t amount)
{
    FILE* fp = fopen(file_path, "w+b");
    if(!fp)
    {
        printf("could not create a new file\n");
        return;
    }

    int fseek_ret = fseek(fp, amount, SEEK_SET);
    if(fseek_ret != 0)
    {
        printf("could not seek to the desired position\n");
        fclose(fp);
        return;
    }

    char garbage = 1;
    size_t ret = fwrite(&garbage, 1, 1, fp);
    if(ret != 1)
    {
        printf("could not write the garbage character\n");
    }

    fclose(fp);
}

int main(int argc, char* argv[])
{
    reserve_file_space("C:\\Users\\SysPart\\Desktop\\test.bin", 1 << 30);
    return 0;
}

Свободное место на диске на моем компьютере составляет около 500 МБ. В main(), если я вызываю reserve_file_space("C:\\Users\\SysPart\\Desktop\\test.bin", 1 << 28 /*256 MB*/);, он выводит файл, созданный с точным размером 256 МБ. Однако, если я вызываю reserve_file_space("C:\\Users\\SysPart\\Desktop\\test.bin", 1 << 30 /*1 GB*/);, он создает выходной файл с размером 0 и без вывода каких-либо уведомлений об ошибках.

Как я могу узнать, достаточно ли места на диске для правильной обработки?


person duong_dajgja    schedule 27.07.2016    source источник
comment
Первое, что нужно сделать, это проверить возвращаемое значение fseek и даже fclose.   -  person kaylum    schedule 27.07.2016
comment
@kaylum Я сделал. Все они возвращали 0 в двух вызовах.   -  person duong_dajgja    schedule 27.07.2016
comment
@kaylum Проверка возвращаемого значения fclose имеет смысл. Благодарю вас!   -  person duong_dajgja    schedule 27.07.2016


Ответы (1)


Как я могу узнать, достаточно ли места на диске для правильной обработки?

В стандартной библиотеке для этого нет функций. Поиск вперед (как вы это сделали) не обязательно приведет к сбою, поскольку файловая система может отложить фактическое выделение дискового пространства до тех пор, пока это пространство действительно не понадобится (потому что вы записываете в него данные). Вы пишете только один символ, поэтому на данный момент фактически требуется только место для этого одного символа (и некоторая метаинформация).

Чтобы быть действительно уверенным, что у вас будет достаточно места (даже при рассмотрении других процессов, которые могут занимать место после того, как вы проверили), вам придется записать случайные данные желаемого размера, а затем перезаписать их вашими фактическими данными, что не является эффективный способ делать вещи.

Стандартная практика заключается в том, чтобы просто попытаться записать (без предварительного выделения памяти) и проверить успешность этой операции записи. Это также позволяет избежать завершения процесса, в результате чего некоторые «предварительно зарезервированные», но бесполезные файлы остаются лежать без дела.

Чтобы заранее проверить доступное место на диске, вы должны полагаться на специфические функции ОС.

Для систем POSIX используется statvfs().

Для WinAPI существует GetDiskFreeSpace() .

person DevSolar    schedule 27.07.2016
comment
@RedX: я упомянул об этом состоянии гонки, а также упомянул, почему предварительное распределение может быть не лучшим путем вперед. - person DevSolar; 27.07.2016
comment
Извините, я пропустил очень важное предложение в скобках. Ссылка, которую я предоставляю, относится к сообщению, в котором подробно описано, как зарезервировать место под окнами без необходимости записи в файл. Я попытался уточнить это в своем первом комментарии. - person RedX; 27.07.2016
comment
POSIX statvfs даст вам приблизительное предположение, основанное на резервах файловой системы (например, удержание корня, которое является частью файловой системы, но не отражает каких-либо дополнительных удерживаемых системных ресурсов. Если точное количество оставшихся блоков/размер вам также потребуются ограничения операционной системы. - person David C. Rankin; 27.07.2016
comment
@DavidC.Rankin: Поскольку файловая система предположительно может сжиматься, а другие процессы все время используют и освобождают дисковое пространство, все, что вы получите в любом случае, это приблизительное предположение... - person DevSolar; 27.07.2016
comment
Это тоже хороший момент, который я не учел. Я быстро взглянул на свой ноутбук (диск 640G). statvfs сообщает 425G user available, а df сообщает 417 (это всего лишь 8G, но это очень важно, если вам нужно точное число) - person David C. Rankin; 27.07.2016
comment
Итог - попытайтесь записать, проверьте результат. - person DevSolar; 27.07.2016
comment
Я предпочитаю использовать boost::filesystem::space(...) для проверки свободного объема каталога. Однако, как упоминал @RedX, мы можем столкнуться с условиями гонки. - person duong_dajgja; 27.07.2016
comment
@duong_dajgja: я не упомянул Boost, поскольку вы отметили вопрос C. Но да, это удобная оболочка для функций, специфичных для ОС ... со всеми их недостатками. - person DevSolar; 27.07.2016