Выделить файл на диск без обнуления
Мне нужно выделить огромный файл без обнуления его содержимого. Я делаю эти шаги fopen => ftruncate => fclose => mmap => (...work...) => munmap
с огромными размерами файлов (сотни гигабайт). Приложение зависает при завершении работы в течение нескольких минут, пока система пытается обнулить байты файла - ИМХО из-за ftruncate
использование.
ftruncate(ofd, 0);
#ifdef HAVE_FALLOCATE
int ret = fallocate(ofd, 0, 0, cache_size);
if (ret == -1) {
printf("Failed to expand file to size %llu (errno %d - %s).\n", cache_size, errno, strerror(errno));
exit(-1);
}
#elif defined(HAVE_POSIX_FALLOCATE)
int ret = posix_fallocate(ofd, 0, cache_size);
if (ret == -1) {
printf("Failed to expand file to size %llu (errno %d - %s).\n", cache_size, errno, strerror(errno));
exit(-1);
}
#elif defined(__APPLE__)
fstore_t store = {F_ALLOCATECONTIG, F_PEOFPOSMODE, 0, cache_size, 0};
int ret = fcntl(ofd, F_PREALLOCATE, &store);
if (ret == -1) {
store.fst_flags = F_ALLOCATEALL;
ret = fcntl(ofd, F_PREALLOCATE, &store);
}
if (ret == -1) { // read fcntl docs - must test against -1
printf("Failed to expand file to size %llu (errno %d - %s).\n", cache_size, errno, strerror(errno));
exit(-1);
}
struct stat sb;
ret = fstat(ofd, &sb);
if (ret != 0) {
printf("Failed to write to file to establish the size.\n");
exit(-1);
}
//ftruncate(ofd, cache_size); <-- [1]
#endif
Вроде не работает с закомментированной строкой [1]
, Но раскомментирование этой строки приводит к обнулению файла, которого я пытаюсь избежать. Мне действительно безразлично грязное содержимое файла перед записью. Я просто хочу избежать зависания приложения.
РЕШЕНИЕ:
Согласно tofro, заменил весь мой код, связанный с Apple, следующими строчками:
unsigned long long result_size = cache_size;
int ret = fcntl(ofd, F_SETSIZE, &result_size);
if(ret == -1) {
printf("Failed set size %llu (errno %d - %s).\n", cache_size, errno, strerror(errno));
exit(-1);
}
Но работает только для суперпользователя!
1 ответ
Это MacOS X, по-видимому.
Вы можете попробовать заменить ftruncate
позвонить с
fcntl(ofd, F_SETSIZE, &size);
(примечание требует привилегий root и может создать дыру в безопасности, потому что она может обеспечить доступ к старому содержимому файла, которое было там ранее, поэтому к нему следует обращаться с особой осторожностью. "Грязное содержимое файла", которое вас не волнует, на самом деле может быть пользователем пароли банковских счетов он удалил неделю назад...)
MacOS X на самом деле не поддерживает разреженные файлы - он создает и поддерживает их, но его драйвер файловой системы очень хочет как можно скорее заполнить дыры.