Выделить файл на диск без обнуления

Мне нужно выделить огромный файл без обнуления его содержимого. Я делаю эти шаги 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 на самом деле не поддерживает разреженные файлы - он создает и поддерживает их, но его драйвер файловой системы очень хочет как можно скорее заполнить дыры.

Другие вопросы по тегам