Запись пустого файла не записывает файл, запись слишком большого файла записывает пустой файл

#c #memcpy #fuse

#c #memcpy #предохранитель

Вопрос:

Я пишу файловые операции для программы FUSE. Однако у меня возникли некоторые проблемы с file_operations.write функцией. Проблема, с которой я сталкиваюсь, заключается в:

  • Попытка записать пустой файл (открыть в vim и сразу сохранить, поэтому написано 0L 0C), он вообще не записывается и оставляет содержимое нетронутым, поэтому, если файл ранее содержал «текст», он все равно будет содержать «текст».
  • Попытка записать большой файл (около 10 КБ) приведет к созданию пустого файла.

Для части пустых файлов. Я уже пробовал несколько вещей, таких как проверка, меньше ли размер 1 (который, как я предполагал, является размером, заданным при записи пустых файлов) и просто сделал char* точку одним '' байтом.

Я также пробовал отдельные случаи if и обнаружил, что размер равен -2 по какой-то странной причине, однако, когда я попытался записать пустой файл, как описано выше, когда найдено -2, это все равно не сработало.

Для файлов слишком большого размера я понятия не имею.

 static int fs_write(const char* path, const char* buffer, size_t size, off_t offset, struct fuse_file_info* ffinfo) {
  // Find the associated file_t* and dir_t* to the file.
  file_t* file = get_file_from_path(path);
  dir_t* directories = get_parents_from_path(path);

  // The contents of a file are stored in a char* so I have to realloc
  // the previous pointer and memcpy the new contents from buffer to
  // file->contents, using size and offset as an indication of how large
  // to make the realloc and what to copy over.

  char* file_contents_new = (char*) realloc(file->contents, (size   1) * sizeof(char));

    // realloc failed
    if (file_contents_new == NULL)
        return -ENOMEM;

    //  point the previous file contents pointer to the newly allocated section.
    file->contents = file_contents_new;

    // Copy from buffer offset to the file contents with the size provided.
    memcpy(file->contents, buffer   offset, size);

    *(file->contents   size) = ''; // Append NULL char to end file string.

    return size;
}
  

Здесь я ожидаю получить надлежащую обработку и для пустых и больших файлов, потому что:

  • размер 0 (который имеет наибольший смысл для меня) будет перераспределен на символ * размером 0 1 (1 для нулевого байта)
  • затем укажите file-> contents на него
  • затем скопируйте 0 байт из буфера в файл-> содержимое
  • запишите '' символ в конец файла-> содержимое (по размеру, который является length of the realloc'ed block - 1 ); в этом случае записывает '' с 0-м индексом.
  • верните записанный размер, в данном случае 0.

Однако vim закрывается, сообщая, что он записал 0L 0C в файл, но файл не был затронут.

Большие файлы:

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

Комментарии:

1. Ваш realloc вызов кажется странным, разве это не должно быть что-то вроде realloc(file->contents, size file->size); ?

2. @Mathieu Я пробовал realloc(file->contents, strlen(file->contents) use_size 1); , это ничего не изменило. Я предположил, что size это новый размер буфера. Вместо добавления данных, он перезапишет данные. итак, если бы я хотел записать «test» в файл, он был бы перераспределен до символа * размером 4 1, чтобы в основном сгенерировать «test 0». поэтому я перераспределяю, просто 4 1 * sizeof(char) пишу «test», затем добавляю нулевой байт.

3. Эта функция каждый раз перезаписывает содержимое файла новым значением. Вам нужно показать, как вы вызываете эту функцию.

Ответ №1:

Я не использую FUSE, но я думаю, что вы плохо используете аргументы (см.https://github.com/libfuse/libfuse/blob/master/example/passthrough.c )

  • buffer : данные для записи
  • size : размер буфера
  • offset : позиция для записи в файл.

Итак, ваш код выглядит как:

 static int fs_write(const char* path, const char* buffer, size_t size, off_t offset, struct fuse_file_info* ffinfo) 
{
  // Find the associated file_t* and dir_t* to the file.
  file_t* file = get_file_from_path(path);
  dir_t* directories = get_parents_from_path(path);


    /* realloc to store data. Note the  1 to store the final  */
    char* file_contents_new = realloc(file->contents, file->size   size 1);

    // realloc failed
    if (file_contents_new == NULL)
        return -ENOMEM;


    //  point the previous file contents pointer to the newly allocated section.
    file->contents = file_contents_new;

    /* update size too, without to  1 to prevent adding one at each write call */
    file->size = file->size   size;

    // Copy buffer to the file taking offset into account
    memcpy(file->contents   offset, buffer, size);

    /* Append NULL char to end file string. */
    *(file->contents   file->size) = ''; 

    return size;
}
  

Комментарии:

1. Проблема, вероятно, заключалась в источнике, который я использовал, чтобы выяснить, что означает «смещение». Они описали это как - offset: offset from where chunk should start , я интерпретировал это как смещение в буфере. но имеет смысл использовать смещение в файле.

2. Однако это все еще не исправлено. Возможно ли, что запись завершается ошибкой, потому что функция чтения также неверна? Или это не должно влиять на запись.