Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
SummerGao.
rt-thread
提交
0bc01ad0
R
rt-thread
项目概览
SummerGao.
/
rt-thread
与 Fork 源项目一致
Fork自
RT-Thread / rt-thread
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
rt-thread
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
0bc01ad0
编写于
12月 14, 2022
作者:
G
guo
提交者:
GitHub
12月 14, 2022
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[dfs] sync cromfs (#6739)
上级
e2bdd8a1
变更
4
显示空白变更内容
内联
并排
Showing
4 changed file
with
1198 addition
and
1 deletion
+1198
-1
components/dfs/Kconfig
components/dfs/Kconfig
+1
-1
components/dfs/filesystems/cromfs/SConscript
components/dfs/filesystems/cromfs/SConscript
+11
-0
components/dfs/filesystems/cromfs/dfs_cromfs.c
components/dfs/filesystems/cromfs/dfs_cromfs.c
+1170
-0
components/dfs/filesystems/cromfs/dfs_cromfs.h
components/dfs/filesystems/cromfs/dfs_cromfs.h
+16
-0
未找到文件。
components/dfs/Kconfig
浏览文件 @
0bc01ad0
...
@@ -142,7 +142,7 @@ if RT_USING_DFS
...
@@ -142,7 +142,7 @@ if RT_USING_DFS
default n
default n
config RT_USING_DFS_CROMFS
config RT_USING_DFS_CROMFS
bool "Enable
reado
nly compressed file system on flash"
bool "Enable
ReadO
nly compressed file system on flash"
default n
default n
# select PKG_USING_ZLIB
# select PKG_USING_ZLIB
...
...
components/dfs/filesystems/cromfs/SConscript
0 → 100644
浏览文件 @
0bc01ad0
# RT-Thread building script for component
from
building
import
*
cwd
=
GetCurrentDir
()
src
=
Glob
(
'*.c'
)
CPPPATH
=
[
cwd
]
group
=
DefineGroup
(
'Filesystem'
,
src
,
depend
=
[
'RT_USING_DFS'
,
'RT_USING_DFS_CROMFS'
],
CPPPATH
=
CPPPATH
)
Return
(
'group'
)
components/dfs/filesystems/cromfs/dfs_cromfs.c
0 → 100644
浏览文件 @
0bc01ad0
/*
* Copyright (c) 2006-2020, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020/08/21 ShaoJinchun first version
*/
#include <rtthread.h>
#include <dfs.h>
#include <dfs_fs.h>
#include <dfs_file.h>
#include "dfs_cromfs.h"
#include <stdint.h>
#include "zlib.h"
/**********************************/
#define CROMFS_PATITION_HEAD_SIZE 256
#define CROMFS_DIRENT_CACHE_SIZE 8
#define CROMFS_MAGIC "CROMFSMG"
#define CROMFS_CT_ASSERT(name, x) \
struct assert_##name {char ary[2 * (x) - 1];}
#define CROMFS_POS_ROOT (0x0UL)
#define CROMFS_POS_ERROR (0x1UL)
typedef
struct
{
uint8_t
magic
[
8
];
/* CROMFS_MAGIC */
uint32_t
version
;
uint32_t
partition_attr
;
/* expand, now reserved 0 */
uint32_t
partition_size
;
/* with partition head */
uint32_t
root_dir_pos
;
/* root dir pos */
uint32_t
root_dir_size
;
}
partition_head_data
;
typedef
struct
{
partition_head_data
head
;
uint8_t
padding
[
CROMFS_PATITION_HEAD_SIZE
-
sizeof
(
partition_head_data
)];
}
partition_head
;
#define CROMFS_DIRENT_ATTR_DIR 0x1UL
#define CROMFS_DIRENT_ATTR_FILE 0x0UL
typedef
struct
{
uint16_t
attr
;
/* dir or file add other */
uint16_t
name_size
;
/* name real size */
uint32_t
file_size
;
/* file data size */
uint32_t
file_origin_size
;
/* file size before compress */
uint32_t
parition_pos
;
/* offset of data */
uint8_t
name
[
0
];
/* name data */
}
cromfs_dirent
;
#define CROMFS_ALIGN_SIZE_BIT 4
#define CROMFS_ALIGN_SIZE (1UL << CROMFS_ALIGN_SIZE_BIT)
/* must be same as sizeof cromfs_dirent */
#define CROMFS_ALIGN_SIZE_MASK (CROMFS_ALIGN_SIZE - 1)
CROMFS_CT_ASSERT
(
align_size
,
CROMFS_ALIGN_SIZE
==
sizeof
(
cromfs_dirent
));
typedef
union
{
cromfs_dirent
dirent
;
uint8_t
name
[
CROMFS_ALIGN_SIZE
];
}
cromfs_dirent_item
;
/**********************************/
typedef
struct
{
rt_list_t
list
;
uint32_t
partition_pos
;
uint32_t
size
;
uint8_t
*
buff
;
}
cromfs_dirent_cache
;
typedef
struct
st_cromfs_info
{
rt_device_t
device
;
uint32_t
partition_size
;
uint32_t
bytes_per_sector
;
uint32_t
(
*
read_bytes
)(
struct
st_cromfs_info
*
ci
,
uint32_t
pos
,
void
*
buf
,
uint32_t
size
);
partition_head_data
part_info
;
struct
rt_mutex
lock
;
struct
cromfs_avl_struct
*
cromfs_avl_root
;
rt_list_t
cromfs_dirent_cache_head
;
int
cromfs_dirent_cache_nr
;
}
cromfs_info
;
typedef
struct
{
uint32_t
ref
;
uint32_t
partition_pos
;
cromfs_info
*
ci
;
uint32_t
size
;
uint8_t
*
buff
;
uint32_t
partition_size
;
int
data_valid
;
}
file_info
;
/**********************************/
#define avl_key_t uint32_t
#define AVL_EMPTY (struct cromfs_avl_struct *)0
#define avl_maxheight 32
#define heightof(tree) ((tree) == AVL_EMPTY ? 0 : (tree)->avl_height)
struct
cromfs_avl_struct
{
struct
cromfs_avl_struct
*
avl_left
;
struct
cromfs_avl_struct
*
avl_right
;
int
avl_height
;
avl_key_t
avl_key
;
file_info
*
fi
;
};
static
void
cromfs_avl_remove
(
struct
cromfs_avl_struct
*
node_to_delete
,
struct
cromfs_avl_struct
**
ptree
);
static
void
cromfs_avl_insert
(
struct
cromfs_avl_struct
*
new_node
,
struct
cromfs_avl_struct
**
ptree
);
static
struct
cromfs_avl_struct
*
cromfs_avl_find
(
avl_key_t
key
,
struct
cromfs_avl_struct
*
ptree
);
static
void
cromfs_avl_rebalance
(
struct
cromfs_avl_struct
***
nodeplaces_ptr
,
int
count
)
{
for
(;
count
>
0
;
count
--
)
{
struct
cromfs_avl_struct
**
nodeplace
=
*--
nodeplaces_ptr
;
struct
cromfs_avl_struct
*
node
=
*
nodeplace
;
struct
cromfs_avl_struct
*
nodeleft
=
node
->
avl_left
;
struct
cromfs_avl_struct
*
noderight
=
node
->
avl_right
;
int
heightleft
=
heightof
(
nodeleft
);
int
heightright
=
heightof
(
noderight
);
if
(
heightright
+
1
<
heightleft
)
{
struct
cromfs_avl_struct
*
nodeleftleft
=
nodeleft
->
avl_left
;
struct
cromfs_avl_struct
*
nodeleftright
=
nodeleft
->
avl_right
;
int
heightleftright
=
heightof
(
nodeleftright
);
if
(
heightof
(
nodeleftleft
)
>=
heightleftright
)
{
node
->
avl_left
=
nodeleftright
;
nodeleft
->
avl_right
=
node
;
nodeleft
->
avl_height
=
1
+
(
node
->
avl_height
=
1
+
heightleftright
);
*
nodeplace
=
nodeleft
;
}
else
{
nodeleft
->
avl_right
=
nodeleftright
->
avl_left
;
node
->
avl_left
=
nodeleftright
->
avl_right
;
nodeleftright
->
avl_left
=
nodeleft
;
nodeleftright
->
avl_right
=
node
;
nodeleft
->
avl_height
=
node
->
avl_height
=
heightleftright
;
nodeleftright
->
avl_height
=
heightleft
;
*
nodeplace
=
nodeleftright
;
}
}
else
if
(
heightleft
+
1
<
heightright
)
{
struct
cromfs_avl_struct
*
noderightright
=
noderight
->
avl_right
;
struct
cromfs_avl_struct
*
noderightleft
=
noderight
->
avl_left
;
int
heightrightleft
=
heightof
(
noderightleft
);
if
(
heightof
(
noderightright
)
>=
heightrightleft
)
{
node
->
avl_right
=
noderightleft
;
noderight
->
avl_left
=
node
;
noderight
->
avl_height
=
1
+
(
node
->
avl_height
=
1
+
heightrightleft
);
*
nodeplace
=
noderight
;
}
else
{
noderight
->
avl_left
=
noderightleft
->
avl_right
;
node
->
avl_right
=
noderightleft
->
avl_left
;
noderightleft
->
avl_right
=
noderight
;
noderightleft
->
avl_left
=
node
;
noderight
->
avl_height
=
node
->
avl_height
=
heightrightleft
;
noderightleft
->
avl_height
=
heightright
;
*
nodeplace
=
noderightleft
;
}
}
else
{
int
height
=
(
heightleft
<
heightright
?
heightright
:
heightleft
)
+
1
;
if
(
height
==
node
->
avl_height
)
{
break
;
}
node
->
avl_height
=
height
;
}
}
}
static
void
cromfs_avl_remove
(
struct
cromfs_avl_struct
*
node_to_delete
,
struct
cromfs_avl_struct
**
ptree
)
{
avl_key_t
key
=
node_to_delete
->
avl_key
;
struct
cromfs_avl_struct
**
nodeplace
=
ptree
;
struct
cromfs_avl_struct
**
stack
[
avl_maxheight
];
uint32_t
stack_count
=
0
;
struct
cromfs_avl_struct
***
stack_ptr
=
&
stack
[
0
];
/* = &stack[stackcount] */
struct
cromfs_avl_struct
**
nodeplace_to_delete
;
for
(;;)
{
struct
cromfs_avl_struct
*
node
=
*
nodeplace
;
if
(
node
==
AVL_EMPTY
)
{
return
;
}
*
stack_ptr
++
=
nodeplace
;
stack_count
++
;
if
(
key
==
node
->
avl_key
)
{
break
;
}
if
(
key
<
node
->
avl_key
)
{
nodeplace
=
&
node
->
avl_left
;
}
else
{
nodeplace
=
&
node
->
avl_right
;
}
}
nodeplace_to_delete
=
nodeplace
;
if
(
node_to_delete
->
avl_left
==
AVL_EMPTY
)
{
*
nodeplace_to_delete
=
node_to_delete
->
avl_right
;
stack_ptr
--
;
stack_count
--
;
}
else
{
struct
cromfs_avl_struct
***
stack_ptr_to_delete
=
stack_ptr
;
struct
cromfs_avl_struct
**
nodeplace
=
&
node_to_delete
->
avl_left
;
struct
cromfs_avl_struct
*
node
;
for
(;;)
{
node
=
*
nodeplace
;
if
(
node
->
avl_right
==
AVL_EMPTY
)
{
break
;
}
*
stack_ptr
++
=
nodeplace
;
stack_count
++
;
nodeplace
=
&
node
->
avl_right
;
}
*
nodeplace
=
node
->
avl_left
;
node
->
avl_left
=
node_to_delete
->
avl_left
;
node
->
avl_right
=
node_to_delete
->
avl_right
;
node
->
avl_height
=
node_to_delete
->
avl_height
;
*
nodeplace_to_delete
=
node
;
*
stack_ptr_to_delete
=
&
node
->
avl_left
;
}
cromfs_avl_rebalance
(
stack_ptr
,
stack_count
);
}
static
void
cromfs_avl_insert
(
struct
cromfs_avl_struct
*
new_node
,
struct
cromfs_avl_struct
**
ptree
)
{
avl_key_t
key
=
new_node
->
avl_key
;
struct
cromfs_avl_struct
**
nodeplace
=
ptree
;
struct
cromfs_avl_struct
**
stack
[
avl_maxheight
];
int
stack_count
=
0
;
struct
cromfs_avl_struct
***
stack_ptr
=
&
stack
[
0
];
/* = &stack[stackcount] */
for
(;;)
{
struct
cromfs_avl_struct
*
node
=
*
nodeplace
;
if
(
node
==
AVL_EMPTY
)
{
break
;
}
*
stack_ptr
++
=
nodeplace
;
stack_count
++
;
if
(
key
<
node
->
avl_key
)
{
nodeplace
=
&
node
->
avl_left
;
}
else
{
nodeplace
=
&
node
->
avl_right
;
}
}
new_node
->
avl_left
=
AVL_EMPTY
;
new_node
->
avl_right
=
AVL_EMPTY
;
new_node
->
avl_height
=
1
;
*
nodeplace
=
new_node
;
cromfs_avl_rebalance
(
stack_ptr
,
stack_count
);
}
static
struct
cromfs_avl_struct
*
cromfs_avl_find
(
avl_key_t
key
,
struct
cromfs_avl_struct
*
ptree
)
{
for
(;;)
{
if
(
ptree
==
AVL_EMPTY
)
{
return
(
struct
cromfs_avl_struct
*
)
0
;
}
if
(
key
==
ptree
->
avl_key
)
{
break
;
}
if
(
key
<
ptree
->
avl_key
)
{
ptree
=
ptree
->
avl_left
;
}
else
{
ptree
=
ptree
->
avl_right
;
}
}
return
ptree
;
}
/**********************************/
static
uint32_t
cromfs_read_bytes
(
cromfs_info
*
ci
,
uint32_t
pos
,
void
*
buf
,
uint32_t
size
)
{
if
(
pos
>=
ci
->
partition_size
||
pos
+
size
>
ci
->
partition_size
)
{
return
0
;
}
return
ci
->
read_bytes
(
ci
,
pos
,
buf
,
size
);
}
static
uint32_t
cromfs_noblk_read_bytes
(
cromfs_info
*
ci
,
uint32_t
pos
,
void
*
buf
,
uint32_t
size
)
{
uint32_t
ret
=
0
;
ret
=
rt_device_read
(
ci
->
device
,
pos
,
buf
,
size
);
if
(
ret
!=
size
)
{
return
0
;
}
else
{
return
ret
;
}
}
static
uint32_t
cromfs_blk_read_bytes
(
cromfs_info
*
ci
,
uint32_t
pos
,
void
*
buf
,
uint32_t
size
)
{
uint32_t
ret
=
0
;
uint32_t
size_bak
=
size
;
uint32_t
start_blk
=
0
;
uint32_t
end_blk
=
0
;
uint32_t
off_s
=
0
;
uint32_t
sector_nr
=
0
;
uint8_t
*
block_buff
=
NULL
;
uint32_t
ret_len
=
0
;
if
(
!
size
||
!
buf
)
{
return
0
;
}
block_buff
=
(
uint8_t
*
)
malloc
(
2
*
ci
->
bytes_per_sector
);
if
(
!
block_buff
)
{
return
0
;
}
start_blk
=
pos
/
ci
->
bytes_per_sector
;
off_s
=
pos
%
ci
->
bytes_per_sector
;
end_blk
=
(
pos
+
size
-
1
)
/
ci
->
bytes_per_sector
;
sector_nr
=
end_blk
-
start_blk
;
if
(
sector_nr
<
2
)
{
ret_len
=
rt_device_read
(
ci
->
device
,
start_blk
,
block_buff
,
sector_nr
+
1
);
if
(
ret_len
!=
sector_nr
+
1
)
{
goto
end
;
}
memcpy
(
buf
,
block_buff
+
off_s
,
size
);
}
else
{
ret_len
=
rt_device_read
(
ci
->
device
,
start_blk
,
block_buff
,
1
);
if
(
ret_len
!=
1
)
{
goto
end
;
}
memcpy
(
buf
,
block_buff
+
off_s
,
ci
->
bytes_per_sector
-
off_s
);
off_s
=
(
ci
->
bytes_per_sector
-
off_s
);
size
-=
off_s
;
sector_nr
--
;
start_blk
++
;
if
(
sector_nr
)
{
ret_len
=
rt_device_read
(
ci
->
device
,
start_blk
,
(
char
*
)
buf
+
off_s
,
sector_nr
);
if
(
ret_len
!=
sector_nr
)
{
goto
end
;
}
start_blk
+=
sector_nr
;
off_s
+=
(
sector_nr
*
ci
->
bytes_per_sector
);
size
-=
(
sector_nr
*
ci
->
bytes_per_sector
);
}
ret_len
=
rt_device_read
(
ci
->
device
,
start_blk
,
block_buff
,
1
);
if
(
ret_len
!=
1
)
{
goto
end
;
}
memcpy
((
char
*
)
buf
+
off_s
,
block_buff
,
size
);
}
ret
=
size_bak
;
end:
free
(
block_buff
);
return
ret
;
}
/**********************************/
static
uint8_t
*
cromfs_dirent_cache_get
(
cromfs_info
*
ci
,
uint32_t
pos
,
uint32_t
size
)
{
rt_list_t
*
l
=
NULL
;
cromfs_dirent_cache
*
dir
=
NULL
;
uint32_t
len
=
0
;
/* find */
for
(
l
=
ci
->
cromfs_dirent_cache_head
.
next
;
l
!=
&
ci
->
cromfs_dirent_cache_head
;
l
=
l
->
next
)
{
dir
=
(
cromfs_dirent_cache
*
)
l
;
if
(
dir
->
partition_pos
==
pos
)
{
RT_ASSERT
(
dir
->
size
==
size
);
rt_list_remove
(
l
);
rt_list_insert_after
(
&
ci
->
cromfs_dirent_cache_head
,
l
);
return
dir
->
buff
;
}
}
/* not found */
if
(
ci
->
cromfs_dirent_cache_nr
>=
CROMFS_DIRENT_CACHE_SIZE
)
{
l
=
ci
->
cromfs_dirent_cache_head
.
prev
;
dir
=
(
cromfs_dirent_cache
*
)
l
;
rt_list_remove
(
l
);
free
(
dir
->
buff
);
free
(
dir
);
ci
->
cromfs_dirent_cache_nr
--
;
}
dir
=
(
cromfs_dirent_cache
*
)
malloc
(
sizeof
*
dir
);
if
(
!
dir
)
{
return
NULL
;
}
dir
->
buff
=
(
uint8_t
*
)
malloc
(
size
);
if
(
!
dir
->
buff
)
{
free
(
dir
);
return
NULL
;
}
len
=
cromfs_read_bytes
(
ci
,
pos
,
dir
->
buff
,
size
);
if
(
len
!=
size
)
{
free
(
dir
->
buff
);
free
(
dir
);
return
NULL
;
}
rt_list_insert_after
(
&
ci
->
cromfs_dirent_cache_head
,
(
rt_list_t
*
)
dir
);
ci
->
cromfs_dirent_cache_nr
++
;
dir
->
partition_pos
=
pos
;
dir
->
size
=
size
;
return
dir
->
buff
;
}
static
void
cromfs_dirent_cache_destroy
(
cromfs_info
*
ci
)
{
rt_list_t
*
l
=
NULL
;
cromfs_dirent_cache
*
dir
=
NULL
;
while
((
l
=
ci
->
cromfs_dirent_cache_head
.
next
)
!=
&
ci
->
cromfs_dirent_cache_head
)
{
rt_list_remove
(
l
);
dir
=
(
cromfs_dirent_cache
*
)
l
;
free
(
dir
->
buff
);
free
(
dir
);
ci
->
cromfs_dirent_cache_nr
--
;
}
}
/**********************************/
static
int
dfs_cromfs_mount
(
struct
dfs_filesystem
*
fs
,
unsigned
long
rwflag
,
const
void
*
data
)
{
struct
rt_device_blk_geometry
geometry
;
uint32_t
len
=
0
;
cromfs_info
*
ci
=
NULL
;
ci
=
(
cromfs_info
*
)
malloc
(
sizeof
*
ci
);
if
(
!
ci
)
{
return
-
ENOMEM
;
}
memset
(
ci
,
0
,
sizeof
*
ci
);
ci
->
device
=
fs
->
dev_id
;
ci
->
partition_size
=
UINT32_MAX
;
if
(
ci
->
device
->
type
==
RT_Device_Class_Block
)
{
rt_device_control
(
ci
->
device
,
RT_DEVICE_CTRL_BLK_GETGEOME
,
&
geometry
);
ci
->
bytes_per_sector
=
geometry
.
bytes_per_sector
;
ci
->
read_bytes
=
cromfs_blk_read_bytes
;
}
else
{
ci
->
read_bytes
=
cromfs_noblk_read_bytes
;
}
len
=
cromfs_read_bytes
(
ci
,
0
,
&
ci
->
part_info
,
sizeof
ci
->
part_info
);
if
(
len
!=
sizeof
ci
->
part_info
||
memcmp
(
ci
->
part_info
.
magic
,
CROMFS_MAGIC
,
sizeof
ci
->
part_info
.
magic
)
!=
0
)
{
free
(
ci
);
return
-
RT_ERROR
;
}
ci
->
partition_size
=
ci
->
part_info
.
partition_size
;
fs
->
data
=
ci
;
rt_mutex_init
(
&
ci
->
lock
,
"crom"
,
RT_IPC_FLAG_FIFO
);
ci
->
cromfs_avl_root
=
NULL
;
rt_list_init
(
&
ci
->
cromfs_dirent_cache_head
);
ci
->
cromfs_dirent_cache_nr
=
0
;
return
RT_EOK
;
}
static
int
dfs_cromfs_unmount
(
struct
dfs_filesystem
*
fs
)
{
rt_err_t
result
=
RT_EOK
;
cromfs_info
*
ci
=
NULL
;
ci
=
(
cromfs_info
*
)
fs
->
data
;
result
=
rt_mutex_take
(
&
ci
->
lock
,
RT_WAITING_FOREVER
);
if
(
result
!=
RT_EOK
)
{
return
-
RT_ERROR
;
}
cromfs_dirent_cache_destroy
(
ci
);
while
(
ci
->
cromfs_avl_root
)
{
struct
cromfs_avl_struct
*
node
;
file_info
*
fi
=
NULL
;
node
=
ci
->
cromfs_avl_root
;
fi
=
node
->
fi
;
cromfs_avl_remove
(
node
,
&
ci
->
cromfs_avl_root
);
free
(
node
);
if
(
fi
->
buff
)
{
free
(
fi
->
buff
);
}
free
(
fi
);
}
rt_mutex_detach
(
&
ci
->
lock
);
free
(
ci
);
return
RT_EOK
;
}
static
int
dfs_cromfs_ioctl
(
struct
dfs_fd
*
file
,
int
cmd
,
void
*
args
)
{
return
-
EIO
;
}
static
uint32_t
cromfs_lookup
(
cromfs_info
*
ci
,
const
char
*
path
,
int
*
is_dir
,
uint32_t
*
size
,
uint32_t
*
osize
)
{
uint32_t
cur_size
=
0
,
cur_pos
=
0
,
cur_osize
=
0
;
const
char
*
subpath
=
NULL
,
*
subpath_end
=
NULL
;
void
*
di_mem
=
NULL
;
int
isdir
=
0
;
if
(
path
[
0
]
==
'\0'
)
{
return
CROMFS_POS_ERROR
;
}
cur_size
=
ci
->
part_info
.
root_dir_size
;
cur_osize
=
0
;
cur_pos
=
ci
->
part_info
.
root_dir_pos
;
isdir
=
1
;
subpath_end
=
path
;
while
(
1
)
{
cromfs_dirent_item
*
di_iter
=
NULL
;
int
found
=
0
;
/* skip /// */
while
(
*
subpath_end
&&
*
subpath_end
==
'/'
)
{
subpath_end
++
;
}
subpath
=
subpath_end
;
while
((
*
subpath_end
!=
'/'
)
&&
*
subpath_end
)
{
subpath_end
++
;
}
if
(
*
subpath
==
'\0'
)
{
break
;
}
/* if not dir or empty dir, error */
if
(
!
isdir
||
!
cur_size
)
{
return
CROMFS_POS_ERROR
;
}
/* find subpath */
di_mem
=
cromfs_dirent_cache_get
(
ci
,
cur_pos
,
cur_size
);
if
(
!
di_mem
)
{
return
CROMFS_POS_ERROR
;
}
found
=
0
;
di_iter
=
(
cromfs_dirent_item
*
)
di_mem
;
while
(
1
)
{
uint32_t
name_len
=
subpath_end
-
subpath
;
uint32_t
name_block
=
0
;
if
(
di_iter
->
dirent
.
name_size
==
name_len
)
{
if
(
memcmp
(
di_iter
->
dirent
.
name
,
subpath
,
name_len
)
==
0
)
{
found
=
1
;
cur_size
=
di_iter
->
dirent
.
file_size
;
cur_osize
=
di_iter
->
dirent
.
file_origin_size
;
cur_pos
=
di_iter
->
dirent
.
parition_pos
;
if
(
di_iter
->
dirent
.
attr
==
CROMFS_DIRENT_ATTR_DIR
)
{
isdir
=
1
;
}
else
{
isdir
=
0
;
}
break
;
}
}
name_block
=
(
di_iter
->
dirent
.
name_size
+
CROMFS_ALIGN_SIZE_MASK
)
>>
CROMFS_ALIGN_SIZE_BIT
;
di_iter
+=
(
1
+
name_block
);
if
((
uint32_t
)
di_iter
-
(
uint32_t
)
di_mem
>=
cur_size
)
{
break
;
}
}
if
(
!
found
)
{
return
CROMFS_POS_ERROR
;
}
}
*
size
=
cur_size
;
*
osize
=
cur_osize
;
*
is_dir
=
isdir
;
return
cur_pos
;
}
static
uint32_t
dfs_cromfs_lookup
(
cromfs_info
*
ci
,
const
char
*
path
,
int
*
is_dir
,
uint32_t
*
size
,
uint32_t
*
osize
)
{
rt_err_t
result
=
RT_EOK
;
uint32_t
ret
=
0
;
result
=
rt_mutex_take
(
&
ci
->
lock
,
RT_WAITING_FOREVER
);
if
(
result
!=
RT_EOK
)
{
return
CROMFS_POS_ERROR
;
}
ret
=
cromfs_lookup
(
ci
,
path
,
is_dir
,
size
,
osize
);
rt_mutex_release
(
&
ci
->
lock
);
return
ret
;
}
static
int
fill_file_data
(
file_info
*
fi
)
{
int
ret
=
-
1
;
cromfs_info
*
ci
=
NULL
;
void
*
compressed_file_buff
=
NULL
;
uint32_t
size
=
0
,
osize
=
0
;
if
(
!
fi
->
data_valid
)
{
RT_ASSERT
(
fi
->
buff
!=
NULL
);
ci
=
fi
->
ci
;
osize
=
fi
->
size
;
size
=
fi
->
partition_size
;
compressed_file_buff
=
(
void
*
)
malloc
(
size
);
if
(
!
compressed_file_buff
)
{
goto
end
;
}
if
(
cromfs_read_bytes
(
ci
,
fi
->
partition_pos
,
compressed_file_buff
,
size
)
!=
size
)
{
goto
end
;
}
if
(
uncompress
((
uint8_t
*
)
fi
->
buff
,
(
uLongf
*
)
&
osize
,
(
uint8_t
*
)
compressed_file_buff
,
size
)
!=
Z_OK
)
{
goto
end
;
}
fi
->
data_valid
=
1
;
}
ret
=
0
;
end:
if
(
compressed_file_buff
)
{
free
(
compressed_file_buff
);
}
return
ret
;
}
static
int
dfs_cromfs_read
(
struct
dfs_fd
*
file
,
void
*
buf
,
size_t
count
)
{
rt_err_t
result
=
RT_EOK
;
struct
dfs_filesystem
*
fs
=
NULL
;
file_info
*
fi
=
NULL
;
cromfs_info
*
ci
=
NULL
;
uint32_t
length
=
0
;
fs
=
(
struct
dfs_filesystem
*
)
file
->
vnode
->
fs
;
ci
=
(
cromfs_info
*
)
fs
->
data
;
fi
=
(
file_info
*
)
file
->
vnode
->
data
;
if
(
count
<
file
->
vnode
->
size
-
file
->
pos
)
{
length
=
count
;
}
else
{
length
=
file
->
vnode
->
size
-
file
->
pos
;
}
if
(
length
>
0
)
{
RT_ASSERT
(
fi
->
size
!=
0
);
if
(
fi
->
buff
)
{
int
fill_ret
=
0
;
result
=
rt_mutex_take
(
&
ci
->
lock
,
RT_WAITING_FOREVER
);
if
(
result
!=
RT_EOK
)
{
return
0
;
}
fill_ret
=
fill_file_data
(
fi
);
rt_mutex_release
(
&
ci
->
lock
);
if
(
fill_ret
<
0
)
{
return
0
;
}
memcpy
(
buf
,
fi
->
buff
+
file
->
pos
,
length
);
}
else
{
void
*
di_mem
=
NULL
;
result
=
rt_mutex_take
(
&
ci
->
lock
,
RT_WAITING_FOREVER
);
if
(
result
!=
RT_EOK
)
{
return
0
;
}
di_mem
=
cromfs_dirent_cache_get
(
ci
,
fi
->
partition_pos
,
fi
->
size
);
if
(
di_mem
)
{
memcpy
(
buf
,
(
char
*
)
di_mem
+
file
->
pos
,
length
);
}
rt_mutex_release
(
&
ci
->
lock
);
if
(
!
di_mem
)
{
return
0
;
}
}
/* update file current position */
file
->
pos
+=
length
;
}
return
length
;
}
static
int
dfs_cromfs_lseek
(
struct
dfs_fd
*
file
,
off_t
offset
)
{
if
(
offset
<=
file
->
vnode
->
size
)
{
file
->
pos
=
offset
;
return
file
->
pos
;
}
return
-
EIO
;
}
static
file_info
*
get_file_info
(
cromfs_info
*
ci
,
uint32_t
partition_pos
,
int
inc_ref
)
{
struct
cromfs_avl_struct
*
node
=
cromfs_avl_find
(
partition_pos
,
ci
->
cromfs_avl_root
);
if
(
node
)
{
if
(
inc_ref
)
{
node
->
fi
->
ref
++
;
}
return
node
->
fi
;
}
return
NULL
;
}
static
file_info
*
inset_file_info
(
cromfs_info
*
ci
,
uint32_t
partition_pos
,
int
is_dir
,
uint32_t
size
,
uint32_t
osize
)
{
file_info
*
fi
=
NULL
;
void
*
file_buff
=
NULL
;
struct
cromfs_avl_struct
*
node
=
NULL
;
fi
=
(
file_info
*
)
malloc
(
sizeof
*
fi
);
if
(
!
fi
)
{
goto
err
;
}
fi
->
partition_pos
=
partition_pos
;
fi
->
ci
=
ci
;
if
(
is_dir
)
{
fi
->
size
=
size
;
}
else
{
fi
->
size
=
osize
;
fi
->
partition_size
=
size
;
fi
->
data_valid
=
0
;
if
(
osize
)
{
file_buff
=
(
void
*
)
malloc
(
osize
);
if
(
!
file_buff
)
{
goto
err
;
}
}
}
fi
->
buff
=
file_buff
;
fi
->
ref
=
1
;
node
=
(
struct
cromfs_avl_struct
*
)
malloc
(
sizeof
*
node
);
if
(
!
node
)
{
goto
err
;
}
node
->
avl_key
=
partition_pos
;
node
->
fi
=
fi
;
cromfs_avl_insert
(
node
,
&
ci
->
cromfs_avl_root
);
return
fi
;
err:
if
(
file_buff
)
{
free
(
file_buff
);
}
if
(
fi
)
{
free
(
fi
);
}
return
NULL
;
}
static
void
deref_file_info
(
cromfs_info
*
ci
,
uint32_t
partition_pos
)
{
struct
cromfs_avl_struct
*
node
=
cromfs_avl_find
(
partition_pos
,
ci
->
cromfs_avl_root
);
file_info
*
fi
=
NULL
;
if
(
node
)
{
node
->
fi
->
ref
--
;
if
(
node
->
fi
->
ref
==
0
)
{
fi
=
node
->
fi
;
cromfs_avl_remove
(
node
,
&
ci
->
cromfs_avl_root
);
free
(
node
);
if
(
fi
->
buff
)
{
free
(
fi
->
buff
);
}
free
(
fi
);
}
}
}
static
int
dfs_cromfs_close
(
struct
dfs_fd
*
file
)
{
file_info
*
fi
=
NULL
;
struct
dfs_filesystem
*
fs
=
NULL
;
cromfs_info
*
ci
=
NULL
;
rt_err_t
result
=
0
;
RT_ASSERT
(
file
->
vnode
->
ref_count
>
0
);
if
(
file
->
vnode
->
ref_count
>
1
)
{
return
0
;
}
fi
=
(
file_info
*
)
file
->
vnode
->
data
;
fs
=
(
struct
dfs_filesystem
*
)
file
->
vnode
->
fs
;
ci
=
(
cromfs_info
*
)
fs
->
data
;
result
=
rt_mutex_take
(
&
ci
->
lock
,
RT_WAITING_FOREVER
);
if
(
result
!=
RT_EOK
)
{
return
-
RT_ERROR
;
}
deref_file_info
(
ci
,
fi
->
partition_pos
);
rt_mutex_release
(
&
ci
->
lock
);
file
->
vnode
->
data
=
NULL
;
return
RT_EOK
;
}
static
int
dfs_cromfs_open
(
struct
dfs_fd
*
file
)
{
int
ret
=
0
;
struct
dfs_filesystem
*
fs
=
NULL
;
file_info
*
fi
=
NULL
;
cromfs_info
*
ci
=
NULL
;
uint32_t
file_pos
=
0
;
uint32_t
size
=
0
,
osize
=
0
;
int
is_dir
=
0
;
rt_err_t
result
=
RT_EOK
;
if
(
file
->
flags
&
(
O_CREAT
|
O_WRONLY
|
O_APPEND
|
O_TRUNC
|
O_RDWR
))
{
return
-
EINVAL
;
}
RT_ASSERT
(
file
->
vnode
->
ref_count
>
0
);
if
(
file
->
vnode
->
ref_count
>
1
)
{
if
(
file
->
vnode
->
type
==
FT_DIRECTORY
&&
!
(
file
->
flags
&
O_DIRECTORY
))
{
return
-
ENOENT
;
}
file
->
pos
=
0
;
return
0
;
}
fs
=
file
->
vnode
->
fs
;
ci
=
(
cromfs_info
*
)
fs
->
data
;
file_pos
=
dfs_cromfs_lookup
(
ci
,
file
->
vnode
->
path
,
&
is_dir
,
&
size
,
&
osize
);
if
(
file_pos
==
CROMFS_POS_ERROR
)
{
ret
=
-
ENOENT
;
goto
end
;
}
/* entry is a directory file type */
if
(
is_dir
)
{
if
(
!
(
file
->
flags
&
O_DIRECTORY
))
{
ret
=
-
ENOENT
;
goto
end
;
}
file
->
vnode
->
type
=
FT_DIRECTORY
;
}
else
{
/* entry is a file, but open it as a directory */
if
(
file
->
flags
&
O_DIRECTORY
)
{
ret
=
-
ENOENT
;
goto
end
;
}
file
->
vnode
->
type
=
FT_REGULAR
;
}
result
=
rt_mutex_take
(
&
ci
->
lock
,
RT_WAITING_FOREVER
);
if
(
result
!=
RT_EOK
)
{
ret
=
-
EINTR
;
goto
end
;
}
fi
=
get_file_info
(
ci
,
file_pos
,
1
);
if
(
!
fi
)
{
fi
=
inset_file_info
(
ci
,
file_pos
,
is_dir
,
size
,
osize
);
}
rt_mutex_release
(
&
ci
->
lock
);
if
(
!
fi
)
{
ret
=
-
ENOENT
;
goto
end
;
}
file
->
vnode
->
data
=
fi
;
if
(
is_dir
)
{
file
->
vnode
->
size
=
size
;
}
else
{
file
->
vnode
->
size
=
osize
;
}
file
->
pos
=
0
;
ret
=
RT_EOK
;
end:
return
ret
;
}
static
int
dfs_cromfs_stat
(
struct
dfs_filesystem
*
fs
,
const
char
*
path
,
struct
stat
*
st
)
{
uint32_t
size
=
0
,
osize
=
0
;
int
is_dir
=
0
;
cromfs_info
*
ci
=
NULL
;
uint32_t
file_pos
=
0
;
ci
=
(
cromfs_info
*
)
fs
->
data
;
file_pos
=
dfs_cromfs_lookup
(
ci
,
path
,
&
is_dir
,
&
size
,
&
osize
);
if
(
file_pos
==
CROMFS_POS_ERROR
)
{
return
-
ENOENT
;
}
st
->
st_dev
=
0
;
st
->
st_mode
=
S_IFREG
|
S_IRUSR
|
S_IRGRP
|
S_IROTH
|
S_IWUSR
|
S_IWGRP
|
S_IWOTH
;
if
(
is_dir
)
{
st
->
st_mode
&=
~
S_IFREG
;
st
->
st_mode
|=
S_IFDIR
|
S_IXUSR
|
S_IXGRP
|
S_IXOTH
;
st
->
st_size
=
size
;
}
else
{
st
->
st_size
=
osize
;
}
st
->
st_mtime
=
0
;
return
RT_EOK
;
}
static
int
dfs_cromfs_getdents
(
struct
dfs_fd
*
file
,
struct
dirent
*
dirp
,
uint32_t
count
)
{
uint32_t
index
=
0
;
uint8_t
*
name
=
NULL
;
struct
dirent
*
d
=
NULL
;
file_info
*
fi
=
NULL
;
cromfs_info
*
ci
=
NULL
;
cromfs_dirent_item
*
dirent
=
NULL
,
*
sub_dirent
=
NULL
;
void
*
di_mem
=
NULL
;
rt_err_t
result
=
RT_EOK
;
fi
=
(
file_info
*
)
file
->
vnode
->
data
;
ci
=
fi
->
ci
;
RT_ASSERT
(
fi
->
buff
==
NULL
);
if
(
!
fi
->
size
)
{
return
-
EINVAL
;
}
dirent
=
(
cromfs_dirent_item
*
)
malloc
(
fi
->
size
);
if
(
!
dirent
)
{
return
-
ENOMEM
;
}
result
=
rt_mutex_take
(
&
ci
->
lock
,
RT_WAITING_FOREVER
);
if
(
result
!=
RT_EOK
)
{
free
(
dirent
);
return
-
EINTR
;
}
di_mem
=
cromfs_dirent_cache_get
(
ci
,
fi
->
partition_pos
,
fi
->
size
);
if
(
di_mem
)
{
memcpy
(
dirent
,
di_mem
,
fi
->
size
);
}
rt_mutex_release
(
&
ci
->
lock
);
if
(
!
di_mem
)
{
free
(
dirent
);
return
-
ENOMEM
;
}
/* make integer count */
count
=
(
count
/
sizeof
(
struct
dirent
));
if
(
count
==
0
)
{
free
(
dirent
);
return
-
EINVAL
;
}
for
(
index
=
0
;
index
<
count
&&
file
->
pos
<
file
->
vnode
->
size
;
index
++
)
{
uint32_t
name_size
=
0
;
d
=
dirp
+
index
;
sub_dirent
=
&
dirent
[
file
->
pos
>>
CROMFS_ALIGN_SIZE_BIT
];
name
=
sub_dirent
->
dirent
.
name
;
/* fill dirent */
if
(
sub_dirent
->
dirent
.
attr
==
CROMFS_DIRENT_ATTR_DIR
)
{
d
->
d_type
=
DT_DIR
;
}
else
{
d
->
d_type
=
DT_REG
;
}
d
->
d_namlen
=
sub_dirent
->
dirent
.
name_size
;
d
->
d_reclen
=
(
rt_uint16_t
)
sizeof
(
struct
dirent
);
memcpy
(
d
->
d_name
,
(
char
*
)
name
,
sub_dirent
->
dirent
.
name_size
);
d
->
d_name
[
sub_dirent
->
dirent
.
name_size
]
=
'\0'
;
name_size
=
(
sub_dirent
->
dirent
.
name_size
+
CROMFS_ALIGN_SIZE_MASK
)
&
~
CROMFS_ALIGN_SIZE_MASK
;
/* move to next position */
file
->
pos
+=
(
name_size
+
sizeof
*
sub_dirent
);
}
free
(
dirent
);
return
index
*
sizeof
(
struct
dirent
);
}
static
const
struct
dfs_file_ops
_crom_fops
=
{
dfs_cromfs_open
,
dfs_cromfs_close
,
dfs_cromfs_ioctl
,
dfs_cromfs_read
,
NULL
,
NULL
,
dfs_cromfs_lseek
,
dfs_cromfs_getdents
,
};
static
const
struct
dfs_filesystem_ops
_cromfs
=
{
"crom"
,
DFS_FS_FLAG_DEFAULT
,
&
_crom_fops
,
dfs_cromfs_mount
,
dfs_cromfs_unmount
,
NULL
,
NULL
,
NULL
,
dfs_cromfs_stat
,
NULL
,
};
int
dfs_cromfs_init
(
void
)
{
/* register crom file system */
dfs_register
(
&
_cromfs
);
return
0
;
}
INIT_COMPONENT_EXPORT
(
dfs_cromfs_init
);
components/dfs/filesystems/cromfs/dfs_cromfs.h
0 → 100644
浏览文件 @
0bc01ad0
/*
* Copyright (c) 2006-2020, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020/08/21 ShaoJinchun firset version
*/
#ifndef __DFS_CROMFS_H__
#define __DFS_CROMFS_H__
int
dfs_cromfs_init
(
void
);
#endif
/*__DFS_CROMFS_H__*/
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录