`memcpy` 不复制所有字节
`memcpy` doesn't copy all bytes
我正在尝试将结构的字节复制到充当缓冲区的 char*。为此,我将 struct(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[=10=]");
// 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)
returns64
,意思就是不填充。
我真的认为问题不在实际的 memcpy
中,而是在我的 vdnxfs_write_disk(...)
函数中,即使我已经通过写入空字符和随机字符进行了测试,并且它按预期工作。在我的测试中,我在文件中写入了 1024 a
个字符,并且成功了。
所以,当我尝试 memcpy
node_buf
进入 buf
时,要么是我的问题,要么是我遗漏了一些东西。
注意:如果我按字符打印 node_buf
个字符,我会得到以下结果:
φ ROOT_DIR
然而,当用十六进制编辑器分析文件时,块的前 4 个字节是:
ED 01 01 00
其余全部00
都是小端模式存储的。 01ED
确实是 node->st_mode
。我确定它是正确的,因为我使用的是 linux 权限,并且 755
是十六进制的 1ED
。
一段时间后,我注意到我向 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);
}
我正在尝试将结构的字节复制到充当缓冲区的 char*。为此,我将 struct(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[=10=]");
// 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)
returns64
,意思就是不填充。
我真的认为问题不在实际的 memcpy
中,而是在我的 vdnxfs_write_disk(...)
函数中,即使我已经通过写入空字符和随机字符进行了测试,并且它按预期工作。在我的测试中,我在文件中写入了 1024 a
个字符,并且成功了。
所以,当我尝试 memcpy
node_buf
进入 buf
时,要么是我的问题,要么是我遗漏了一些东西。
注意:如果我按字符打印 node_buf
个字符,我会得到以下结果:
φ ROOT_DIR
然而,当用十六进制编辑器分析文件时,块的前 4 个字节是:
ED 01 01 00
其余全部00
都是小端模式存储的。 01ED
确实是 node->st_mode
。我确定它是正确的,因为我使用的是 linux 权限,并且 755
是十六进制的 1ED
。
一段时间后,我注意到我向 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);
}