进入rt-thread\components\dfs\filesystems omfs目录下,创建一个romfs目录
在我们创建的romfs中,创建一个文件夹sdcard,用于挂载我们的sd卡,同时在里面创建一个文件,使用英文命名,并添加一些内容。
注意:如果不添加这个文件,会在之后的程序编译遇到一下错误:
compiling romfs.c...
..\..\components\dfs\filesystems omfs omfs.c(7): error: #29: expected an expression
};
..\..\components\dfs\filesystems omfs omfs.c(5): error: #1514: an empty initializer is invalid for an array with unspecified bound
static const struct romfs_dirent _romfs_root_sdcard[] = {
..\..\components\dfs\filesystems omfs omfs.c(14): error: #44: expression must have pointer type
{
OMFS_DIRENT_DIR, "sdcard", (rt_uint8_t *)_romfs_root_sdcard, sizeof(_romfs_root_sdcard)/sizeof(_romfs_root_sdcard[0])},
..\..\components\dfs\filesystems omfs omfs.c(19): error: #44: expression must have pointer type
OMFS_DIRENT_DIR, "/", (rt_uint8_t *)_romfs_root, sizeof(_romfs_root)/sizeof(_romfs_root[0])
..\..\components\dfs\filesystems omfs omfs.c: 0 warnings, 4 errors
result = mmcsd_wait_cd_changed(RT_TICK_PER_SECOND);
if (result == MMCSD_HOST_PLUGED)
{
if (dfs_mount(RT_NULL, "/", "rom", 0, &(romfs_root)) == 0)
rt_kprintf("ROM System initialized!<br>");
else
rt_kprintf("ROM System init failed!<br>");
/* mount sd card fat partition 1 as root directory */
if (dfs_mount("sd0", "/sdcard", "elm", 0, 0) == 0)
rt_kprintf("File System initialized!<br>");
else
rt_kprintf("File System init failed!<br>");
}
else
{
rt_kprintf("sdcard init fail or timeout: %d!<br>", result);
}
运行程序能看到如下:
romfs挂载成功
tar格式的设计最初是为了在磁带上归档一堆文件。
一个tar文件由一个个文件块构成,每个文件块都是一个原本文件的封装。
文件块顺序摆放,在末尾加上一个全0的512字节标志。但是实际上这个标志不一定存在(例如我拿到的一个tar文件就么有这512个0),因此打开tar文件的时候不能依赖这个标志,而要依赖文件结尾来判断tar文件的结束。
每个文件块由一个个block(512字节)构成,这也是结束标志是512字节的原因所在。
每个文件块的开头第一个block是一个header,是tar格式的封装信息。其余block是将原文件按照512字节分块之后,依次存储下来的,末尾补0以对其到512字节。如果文件刚好是512字节的倍数,那就不用补0了,因此文件大小和tar打包之后占用的block数的计算是
Block数 = (文件字节数 + 511)/ 512
header的结构如下:
struct header {
char name[100];
char mode[8];
char uid[8];
char gid[8];
char size[12];
char mtime[12];
char chksum[8];
char linkflag;
char linkname[100];
char magic[8];
char uname[32];
char gname[32];
char devmajor[8];
char devminor[8];
char prefix[155]
char padding[12];
};
所有字节都被解释为了ascii字符,因此每个字段以 ‘\0’结尾。
其中
size和checksum是8进制数。
mtime使用 “Unix时间”。
linkflag是’5’表示这个文件是目录,那么这个文件块将没有数据,下一个block就是下一个文件块。其余情况还有“符号链接”等等,这里暂时不深入讨论,可以参考:http://www.moon-soft.com/program/FORMAT/comm/tar.htm
magic是一个字符串”ustar”,用于标示这是一个tar文件(头)。
struct tar_header
{
char name[100];
char mode[8];
char uid[8];
char gid[8];
char size[12];
char mtime[12];
char chksum[8];
char typeflag;
char linkname[100];
char magic[6];
char version[2];
char uname[32];
char gname[32];
char devmajor[8];
char devminor[8];
char prefix[155];
char padding[12];
}tsTarHeader;
#define UNTAR_TARGET_DIR "/sdcard/"
#define TAR_FILE_BLOCK_SIZE 512
#define TAR_FILE_TYPE_FILE '0'
#define TAR_FILE_TYPE_DIR '5'
//八进制转十进制
int convertOctalToDecimal(int octalNumber)
{
int decimalNumber = 0, i = 0;
while(octalNumber != 0)
{
decimalNumber += (octalNumber%10) * pow(8,i);
++i;
octalNumber/=10;
}
return decimalNumber;
}
int main(void)
{
rt_uint32_t result;
int tar_fd, size, block_num = 0, i, j, k;
struct stat buf;
struct tar_header tar_file_header;
char target_dir[128] = {0}, file_dir[128] = {0};
rt_uint8_t block_data[TAR_FILE_BLOCK_SIZE];
int file_total_size;
//dump_clock();
dump_cc_info();
dump_link_info();
rt_kprintf("build time: %s %s<br>", __DATE__, __TIME__);
#if defined(RT_USING_DFS) && defined(RT_USING_SDIO)
result = mmcsd_wait_cd_changed(RT_TICK_PER_SECOND);
if (result == MMCSD_HOST_PLUGED)
{
if (dfs_mount(RT_NULL, "/", "rom", 0, &(romfs_root)) == 0)
rt_kprintf("ROM System initialized!<br>");
else
rt_kprintf("ROM System init failed!<br>");
/* mount sd card fat partition 1 as root directory */
if (dfs_mount("sd0", "/sdcard", "elm", 0, 0) == 0)
rt_kprintf("File System initialized!<br>");
else
rt_kprintf("File System init failed!<br>");
}
else
{
rt_kprintf("sdcard init fail or timeout: %d!<br>", result);
}
#endif
stat("/untar_test.tar", &buf);
rt_kprintf("untar_test.tar file size = %d block %d<br>", buf.st_size, buf.st_size/512);
rt_kprintf("tar_header size %d<br>", sizeof(struct tar_header));
block_num = buf.st_size/512;
fd = open("/untar_test.tar", O_RDONLY);
if (fd < 0)
{
rt_kprintf("Failed to open %s<br>", "untar_test.tar");
}
for(i = 0; i < block_num; i++)
{
size = read(fd, &tar_file_header, sizeof(struct tar_header));
if((size == TAR_FILE_BLOCK_SIZE) && !(strcmp(tar_file_header.magic, "ustar")))
{
//rt_kprintf("block:%d name:%s typeflag:%c<br>", i, tar_file_header.name, tar_file_header.typeflag);
if(tar_file_header.typeflag == TAR_FILE_TYPE_DIR)
{
//将读到的目录创建出来
memset(target_dir, 0, sizeof(target_dir));
strcat(target_dir, UNTAR_TARGET_DIR);
strcat(target_dir, tar_file_header.name);
mkdir(target_dir, 0x777);
}
else if(tar_file_header.typeflag == TAR_FILE_TYPE_FILE)
{
//先创建文件目录
memset(file_dir, 0, sizeof(file_dir));
strcat(file_dir, UNTAR_TARGET_DIR);
strcat(file_dir, tar_file_header.name);
for(j=(rt_strlen(file_dir)-1); j--; j>0)
if(file_dir[j] == '/')
file_dir[j+1] = 0; //截断
mkdir(file_dir, 0x777);
//在开始创建文件
memset(file_dir, 0, sizeof(file_dir));
strcat(file_dir, UNTAR_TARGET_DIR);
strcat(file_dir, tar_file_header.name);
tar_fd = open(file_dir, O_RDWR | O_CREAT | O_APPEND, 0);
if(tar_fd < 0)
rt_kprintf("open %s failed<br>", tar_file_header.name);
file_total_size = convertOctalToDecimal(atoi(tar_file_header.size));
j = 0;
}
}
else
{
memcpy(block_data, &tar_file_header, TAR_FILE_BLOCK_SIZE);
k = 0;
for( k = 0; k<TAR_FILE_BLOCK_SIZE; k++)
{
write(tar_fd, &block_data[k], 1);
j++;
//读取数据结束
if(j >= file_total_size)
close(tar_fd);
}
}
}
close(fd);
while (1)
{
rt_thread_delay(RT_TICK_PER_SECOND);
}
}
编译运行如下:
==bingo!!!==