`memcpy` не копирует все байты - PullRequest
       30

`memcpy` не копирует все байты

0 голосов
/ 28 сентября 2019

Я пытаюсь скопировать байты структуры в символ *, который действует как буфер.Для этого я конвертирую свою структуру (vdnxfs_node) в массив char.Длина этой структуры составляет 64 байта, а размер буфера - 1024 байта.
Однако при выполнении операции memcpy в буфер копируются только первые 4 байта структуры.

Файл: fs.c

int mkfs(uint8_t _dev, uint8_t _mode)
{
    // VDNXFS_BUFFER_SZ = 1024
    char* buf = (char*)malloc(VDNXFS_BUFFER_SZ);

    // Other code non relevant to the question...

    // vdnxfs_init_new_node(); returns an `vdnxfs_node*` initialized
    // as `calloc(1, sizeof(vdnxfs_node));`
    vdnxfs_node* node = vdnxfs_init_new_node();
    node->st_mode = VDNXFS_ST_IRWXU | VDNXFS_ST_IRGRP | VDNXFS_ST_IXGRP | VDNXFS_ST_IROTH | VDNXFS_ST_IXOTH;
    node->st_uid = 1;
    node->st_gid = 1;
    node->st_pid = 0;
    node->st_size = 0;
    node->st_slnk = 1;
    node->st_atime = 0xffff;
    node->st_mtime = 0xffff;
    node->st_ctime = 0xffff;
    strcpy(node->st_name, "ROOT_DIR\0");

    // With this I get the array of bytes(char) of the struct
    char* node_buf = encode_dnxfs_node(node);

    // Updating the buffer
    memcpy(buf, node_buf, sizeof(vdnxfs_node));

    // Here I write the content of `buf` to a file.
    if(!vdnxfs_write_disk(_dev, block, off, buf))
    {
        printf("Couldn't write superblock to disk `sda%d`.", _dev);
        return -1;
    }
    free(buf);
    free(node_buf);
}

Файл: stat.h

typedef struct __vdnxfs_node
{
    uint16_t st_mode;
    uint16_t st_uid;
    uint16_t st_gid;
    uint32_t st_pid; // Parent ID
    uint32_t st_size;
    uint8_t st_slnk; // Number of symbolic links
    time_t st_atime;
    time_t st_mtime;
    time_t st_ctime;
    char st_name[16];
}vdnxfs_node;

Файл: stat.c
Краткое описание: Преобразовать все байты узла в массив символов

char* encode_dnxfs_node(vdnxfs_node* node)
{
    if(!node) // Node is null
    {
        return NULL;
    }
    char* buffer = (char*)malloc(sizeof(vdnxfs_node));

    if(!buffer)
    {
        printf("Failed to allocate buffer for encoding.");
        return NULL;
    }

    memcpy(buffer, node, sizeof(vdnxfs_node));

    return buffer;
}

Файл: disk.c
Краткое описание: Напишите содержимое файла _buf в файл.Содержимое, записанное на диск, всегда имеет длину 1024 bytes, как определено в VDNXFS_BUFFER_SZ._off - это смещение внутри блока.

char* vdnxfs_write_disk(uint8_t _dev, size_t _block, size_t _off, char* _buf)
{
    char* fl_name = (char*)calloc(1, 7);
    strcpy(fl_name, vdnxfs_disks[_dev]->fl_name);

    FILE* fp_buf = fopen(fl_name, "r+b");

    if(!fp_buf)
    {
        printf("DISK DRIVER: Couldn't open Disk %s\n", fl_name);
        return NULL;
    }

    // If succesful
    if(!fseek(fp_buf, (_block * VDNXFS_BUFFER_SZ) + _off, SEEK_SET))
    {
        fputs(_buf, fp_buf);
    }else { return NULL; }

    fclose(fp_buf);

    return _buf;
}

sizeof(vdnxfs_node) возвращает 64, то есть не дополняется.Я действительно думаю, что проблема не в самом memcpy, а в моей функции vdnxfs_write_disk(...), хотя я уже тестировал, записывая как нулевой символ, так и случайные символы, и это работало, как и ожидалось.В моем тесте я записал в файл 1024 a символов, и это сработало.Итак, либо у меня проблема, когда я пытаюсь memcpy node_buf в buf, либо я что-то упускаю.

Примечание: если я печатаю node_buf char за символом, я получаю такой результат:

φ                                           ROOT_DIR

Однако при анализе файла с помощью hex-редактора первые 4 байта блока:

ED 01 01 00

Остальные все 00

Все это хранится в режиме с прямым порядком байтов.01ED действительно node->st_mode.Я уверен, что это правильно, потому что я использую разрешения Linux, а 755 - это 1ED в шестнадцатеричном формате.

1 Ответ

0 голосов
/ 30 сентября 2019

Через некоторое время я заметил, что я передаю vdnxfs_write_disk неправильный размер буфера (я передаю VDXNFS_BUFFER_SZ вместо размера данных, которые я хотел записать).Я также передавал vdnxfs_write_disk неправильное смещение и блок.Я фактически передавал 1 для аргументов блока, а смещение fseek вычисляется как (block * VDNXFS_BUFFER_SZ) + off смещение fseek превышает 1024 bytes, что было неправильно.

Если кто-тоинтересно, вот мой окончательный (фиксированный) результат mkfs:

int mkfs(uint8_t _dev, uint8_t _mode)
{
    char* buf = (char*)malloc(sizeof(size_t));
    char* signature_buf = vdnxfs_read_disk(_dev, 0, 4, 4);
    memcpy(buf, signature_buf, sizeof(size_t));
    free(signature_buf);

    // Signing the disk with the appopriate signature.
    size_t signature = _mode == vdnxfs_system ? VDNXFS_BDSK_SIGNATURE : VDNXFS_DDSK_SIGNATURE;
    // printf("Signature: %X\n", signature);

    for(int i = 0; i < 4; i++)
    {
        // Disk signature starts at 4th byte
        buf[i] = ((signature >> (8 * i)) & 0xff);
    }

    // Updating the content to disk
    if(!vdnxfs_write_disk(_dev, 0, 4, buf, 4))
    {
        printf("Couldn't sign disk `sda%d`.", _dev);
        return -1;
    }

    // Getting the Super Block based on the mode.
    // Boot/System FS stores the superblock from bytes 1024 to 2047
    // Data FS stores the superblock from bytes 512 to 1535
    size_t block = 0;
    size_t off = _mode == vdnxfs_system ? VDNXFS_BFS_SBLK_START : VDNXFS_DFS_SBLK_START;

    vdnxfs_node* node = (vdnxfs_node*)calloc(1, 64);
    node->st_mode = VDNXFS_ST_IRWXU | VDNXFS_ST_IRGRP | VDNXFS_ST_IXGRP | VDNXFS_ST_IROTH | VDNXFS_ST_IXOTH;
    node->st_uid = 1;
    node->st_gid = 1;
    node->st_pid = 0;
    node->st_size = 0;
    node->st_slnk = 1;
    node->st_atime = 0xffff;
    node->st_mtime = 0xffff;
    node->st_ctime = 0xffff;
    strcpy(node->st_name, "ROOT_DIR");
    // Updating the superblock to disk
    if(!vdnxfs_write_disk(_dev, block, off, encode_dnxfs_node(node), 64))
    {
        printf("Couldn't write superblock to disk `sda%d`.", _dev);
        free(node);
        free(buf);
        return -1;
    }

    free(node);
    free(buf);
}
...