First commit XiUOS

This commit is contained in:
xuetest
2021-04-28 17:49:18 +08:00
commit 6001051eb7
1331 changed files with 433955 additions and 0 deletions

96
tool/shell/Kconfig Normal file
View File

@@ -0,0 +1,96 @@
menu "Command shell"
menuconfig TOOL_SHELL
bool "Enable letter-shell function"
default y
if TOOL_SHELL
config SHELL_ENTER_CR
bool
config SHELL_ENTER_LF
bool
choice
prompt "Set shell end-of-line markers :"
default SHELL_ENTER_CR_AND_LF
config SHELL_ENTER_CR_AND_LF
bool "Using CR And LF as end-of-line markers"
select SHELL_ENTER_CR
select SHELL_ENTER_LF
config SHELL_ENTER_CRLF
bool "Using CRLF as end-of-line markers"
endchoice
menu "Set shell user control"
config SHELL_DEFAULT_USER
string "Set default user's name"
default "letter"
config SHELL_DEFAULT_USER_PASSWORD
string "Set default user's password(none for unnecessary)"
default ""
config SHELL_LOCK_TIMEOUT
int "Set the lock time(ms) if password isn't none."
default 10000
endmenu
menu "Set shell config param"
config SHELL_TASK_STACK_SIZE
int "Set the stack size for shell "
default 4096
config SHELL_TASK_PRIORITY
int
default 5 if KTASK_PRIORITY_8
default 20 if KTASK_PRIORITY_32
default 120 if KTASK_PRIORITY_256
config SHELL_MAX_NUMBER
int "Set the max shell count"
default 5
config SHELL_PARAMETER_MAX_NUMBER
int "Set the max number of parameter"
default 8
help
The max number of parameter in shell. We support up to eight including command name.
config SHELL_HISTORY_MAX_NUMBER
int "Set the max number of command history"
default 5
config SHELL_PRINT_BUFFER
int "Set the max number of print buffer"
default 128
endmenu
config SHELL_HELP_SHOW_PERMISSION
bool "Enable the function of showing permission"
default y
help
Show Command and Variable Permission in Shell
config SHELL_HELP_LIST_USER
bool "List all users "
default n
help
List all users in shell
config SHELL_HELP_LIST_VAR
bool "List all variable "
default y
help
List all variable in shell
config SHELL_HELP_LIST_KEY
bool "List all keys "
default n
help
List all keys in shell
endif
endmenu

3
tool/shell/Makefile Normal file
View File

@@ -0,0 +1,3 @@
SRC_DIR := letter-shell
include $(KERNEL_ROOT)/compiler.mk

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Letter
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,7 @@
SRC_FILES := shell.c shell_ext.c shell_port.c cmd.c
ifeq ($(CONFIG_FS_VFS), y)
SRC_DIR += file_ext
endif
include $(KERNEL_ROOT)/compiler.mk

View File

@@ -0,0 +1,214 @@
# letter shell 3.0
![version](https://img.shields.io/badge/version-3.0.5-brightgreen.svg)
![standard](https://img.shields.io/badge/standard-c99-brightgreen.svg)
![build](https://img.shields.io/badge/build-2020.08.23-brightgreen.svg)
![license](https://img.shields.io/badge/license-MIT-brightgreen.svg)
一个功能强大的嵌入式shell
## 简介
[letter shell 3.0](https://github.com/NevermindZZT/letter-shell/tree/shell3.0)是一个C语言编写的可以嵌入在程序中的嵌入式shell主要面向嵌入式设备以C语言函数为运行单位可以通过命令行调用运行程序中的函数
该移植适配了Xiuos操作系统并进行了精简。
原始版本的使用说明可参考[Letter shell 3.0 全新出发](https://nevermindzzt.github.io/2020/01/19/Letter%20shell%203.0%E5%85%A8%E6%96%B0%E5%87%BA%E5%8F%91/)
## 功能
- 命令自动补全
- 快捷键功能定义
- 命令权限管理
- 用户管理
- 变量支持
- 文件系统的支持
## 配置选项()
1. 配置宏
下面列出了用于配置shell的宏在使用前可用menuconfig进行配置
| 宏 | 意义 |
| - | - |
| TOOL_SHELL | 是否开启shell(默认y) |
| | |
| SHELL_HELP_LIST_USER | 是否在输入命令列表中列出用户 |
| SHELL_HELP_LIST_VAR | 是否在输入命令列表中列出变量 |
| SHELL_HELP_LIST_KEY | 是否在输入命令列表中列出按键 |
| SHELL_ENTER_LF | 使用LF作为命令行回车触发 |
| SHELL_ENTER_CR | 使用CR作为命令行回车触发 |
| SHELL_ENTER_CRLF | 使用CRLF作为命令行回车触发 |
| SHELL_COMMAND_MAX_LENGTH | shell命令最大长度 |
| SHELL_PARAMETER_MAX_NUMBER | shell命令参数最大数量 |
| SHELL_HISTORY_MAX_NUMBER | 历史命令记录数量 |
| SHELL_MAX_NUMBER | 管理的最大shell数量 |
| SHELL_DEFAULT_USER | shell默认用户 |
| SHELL_DEFAULT_USER_PASSWORD | 默认用户密码 |
| SHELL_LOCK_TIMEOUT | shell自动锁定超时 |
## 使用方式
### 命令定义
letter shell 3.0将可执行的函数定义,变量定义统一归为命令定义,使用相同的结构储存,查找和执行
#### 定义方式
letter shell 的命令导出方式支持在函数体外部,采用定义常量的方式定义命令,例如`SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE (SHELL_TYPE_CMD_MAIN)|SHELL_CMD_DISABLE_RETURN,help, shellHelp, show command info\r\nhelp [cmd]);`
letter shell 的命令表方式只支持在shell_cmd_list.c源文件的shellCommandList数据结构中添加命令例如`SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)|SHELL_CMD_DISABLE_RETURN,help, shellHelp, show command info\r\nhelp [cmd]),`
#### 命令导出宏
letter shell 3.0对可执行命令提供了一个宏,用于进行命令导出。
对可执行命令定义使用宏`SHELL_EXPORT_CMD`定义可执行命令,宏定义如下
```C
/**
* @brief shell 命令定义
*
* @param _attr 命令属性
* @param _name 命令名
* @param _func 命令函数
* @param _desc 命令描述
*/
#define SHELL_EXPORT_CMD(_attr, _name, _func, _desc) \
const char shellCmd##_name[] = #_name; \
const char shellDesc##_name[] = #_desc; \
const ShellCommand \
shellCommand##_name SECTION("shellCommand") = \
{ \
.attr.value = _attr, \
.data.cmd.name = shellCmd##_name, \
.data.cmd.function = (int (*)())_func, \
.data.cmd.desc = shellDesc##_name \
}
```
#### 命令属性字段说明
在命令定义中,有一个`attr`字段,表示该命令的属性,具体定义为
```C
union
{
struct
{
unsigned char permission : 8; /**< command权限 */
ShellCommandType type : 4; /**< command类型 */
unsigned char enableUnchecked : 1; /**< 在未校验密码的情况下可用 */
unsigned char readOnly : 1; /**< 只读 */
unsigned char reserve : 1; /**< 保留 */
unsigned char paramNum : 4; /**< 参数数量 */
} attrs;
int value;
} attr;
```
在定义命令时,需要给定这些值,可以通过宏快速声明:
```c
SHELL_CMD_PERMISSION(permission)
SHELL_CMD_TYPE(type)
SHELL_CMD_ENABLE_UNCHECKED
SHELL_CMD_DISABLE_RETURN
SHELL_CMD_READ_ONLY
SHELL_CMD_PARAM_NUM(num)
```
### 命令导出时,函数参数形式
letter shell 3.0同时支持两种形式的函数定义方式形如main函数定义的`func(int argc, char *agrv[])`以及形如普通C函数的定义`func(int i, char *str, ...)`,两种函数定义方式适用于不同的场景
#### main函数形式
使用此方式,一个函数定义的例子如下:
```C
int func(int argc, char *agrv[])
{
printf("%dparameter(s)\r\n", argc);
for (char i = 1; i < argc; i++)
{
printf("%s\r\n", argv[i]);
}
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), func, func, test);
```
终端调用
```sh
letter:/$ func "hello world"
2 parameter(s)
hello world
```
#### 普通C函数形式
使用此方式shell会自动对参数进行转化处理目前支持二进制八进制十进制十六进制整形字符字符串的自动处理例子如下
```C
int func(int i, char ch, char *str)
{
printf("input int: %d, char: %c, string: %s\r\n", i, ch, str);
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC), func, func, test);
```
终端调用
```sh
letter:/$ func 666 'A' "hello world"
input int: 666, char: A, string: hello world
```
### 变量定义
letter shell 3.0支持导出变量,通过命令行查看,设置以及使用变量的值
- 导出变量
变量导出使用`SHELL_EXPORT_VAR`宏,支持整形(char, short, int),字符串,指针以及节点变量,变量导出需要使用引用的方式,如果不允许对变量进行修改,在属性中添加`SHELL_CMD_READ_ONLY`
```C
int varInt = 0;
SHELL_EXPORT_VAR(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_VAR_INT), varInt, &varInt, test);
char str[] = "test string";
SHELL_EXPORT_VAR(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_VAR_STRING), varStr, str, test);
Log log;
SHELL_EXPORT_VAR(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_VAR_POINT), log, &log, test);
```
- 查看变量
在命令行直接输入导出的变量名即可查看变量当前的值
```sh
letter:/$ varInt
varInt = 0, 0x00000000
letter:/$ varStr
varStr = "test string"
```
- 修改变量
使用`setVar`命令修改变量的值,对于字符串型变量,请确认字符串有分配足够的空间,指针类型的变量不可修改
```sh
letter:/$ setVar varInt 45678
varInt = 45678, 0x0000b26e
letter:/$ setVar varStr "hello"
varStr = "hello"
```

View File

@@ -0,0 +1,823 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include <xiuos.h>
#include "shell.h"
#include <bus.h>
#include <xs_ktask_stat.h>
#include <string.h>
#define LIST_FIND_OBJ_NR 8
long Hello(void)
{
KPrintf("Hello World!\n");
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(0)|SHELL_CMD_DISABLE_RETURN,
Hello, Hello, say Hello world);
extern void ShowBanner(void);
long Version(void)
{
ShowBanner();
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(0)|SHELL_CMD_DISABLE_RETURN,
Version,Version, show xios Version information);
static __inline void ObjectSplit(int len)
{
while (len--) KPrintf("-");
}
typedef struct
{
DoubleLinklistType *list;
DoubleLinklistType **array;
uint8 type;
int nr;
int nr_out;
} ListGetNext_t;
extern DoubleLinklistType xiaoshan_task_head;
#ifdef KERNEL_SEMAPHORE
extern DoubleLinklistType k_sem_list;
#endif
#ifdef KERNEL_MUTEX
extern DoubleLinklistType k_mutex_list;
#endif
#ifdef KERNEL_EVENT
extern DoubleLinklistType k_event_list;
#endif
#ifdef KERNEL_MESSAGEQUEUE
extern DoubleLinklistType k_mq_list;
#endif
#ifdef KERNEL_SOFTTIMER
extern DoubleLinklistType k_timer_list;
#endif
#ifdef KERNEL_MEMBLOCK
extern DoubleLinklistType xiaoshan_memgather_head;
#endif
extern DoubleLinklistType bus_linklist;
static DoubleLinklistType * GetTypelistManagelist(uint8 type)
{
DoubleLinklistType *list = NONE;
switch(type)
{
case Cmpt_KindN_Task:
list = &xiaoshan_task_head;
break;
case Cmpt_KindN_Semaphore:
#ifdef KERNEL_SEMAPHORE
list = &k_sem_list;
#endif
break;
case Cmpt_KindN_Mutex:
#ifdef KERNEL_MUTEX
list = &k_mutex_list;
#endif
break;
case Cmpt_KindN_Event:
#ifdef KERNEL_EVENT
list = &k_event_list;
#endif
break;
case Cmpt_KindN_MessageQueue:
#ifdef KERNEL_MESSAGEQUEUE
list = &k_mq_list;
#endif
break;
case Cmpt_KindN_MemPool:
#ifdef KERNEL_MEMBLOCK
list = &xiaoshan_memgather_head;
#endif
break;
case Cmpt_KindN_Timer:
#ifdef KERNEL_SOFTTIMER
list = &k_timer_list;
#endif
break;
case Cmpt_KindN_Bus:
list = &bus_linklist;
break;
default:
break;
}
return list;
}
static void ListFindManagelistInit(ListGetNext_t *p, uint8 type, DoubleLinklistType **array, int nr)
{
DoubleLinklistType *list;
list = GetTypelistManagelist(type);
if (NONE == list) {
return;
}
p->list = list;
p->type = type;
p->array = array;
p->nr = nr;
p->nr_out = 0;
}
static DoubleLinklistType *ListGetNext(DoubleLinklistType *current, ListGetNext_t *arg)
{
int first_flag = 0;
x_ubase level;
DoubleLinklistType *node, *list;
DoubleLinklistType **array;
int nr;
arg->nr_out = 0;
if (!arg->nr || !arg->type) {
return (DoubleLinklistType *)NONE;
}
list = arg->list;
if (!current) {
node = list;
first_flag = 1;
} else {
node = current;
}
level = CriticalAreaLock();
if (!first_flag) {
struct CommonMember *obj;
obj = SYS_DOUBLE_LINKLIST_ENTRY(node, struct CommonMember, list);
if ((obj->type & ~Cmpt_KindN_Static) != arg->type) {
CriticalAreaUnLock(level);
return (DoubleLinklistType *)NONE;
}
}
nr = 0;
array = arg->array;
while (1) {
node = node->node_next;
if (node == list) {
node = (DoubleLinklistType *)NONE;
break;
}
nr++;
*array++ = node;
if (nr == arg->nr) {
break;
}
}
CriticalAreaUnLock(level);
arg->nr_out = nr;
return node;
}
long ShowTask(void)
{
x_ubase level;
ListGetNext_t find_arg;
DoubleLinklistType *obj_list[LIST_FIND_OBJ_NR];
DoubleLinklistType *next = (DoubleLinklistType*)NONE;
const char *item_title = "task";
int maxlen;
ListFindManagelistInit(&find_arg, Cmpt_KindN_Task, obj_list, sizeof(obj_list)/sizeof(obj_list[0]));
maxlen = NAME_NUM_MAX;
#ifndef SCHED_POLICY_FIFO
#ifdef ARCH_SMP
KPrintf("%-*.s cpu pri status sp stack size max used left tick error\n", maxlen, item_title); ObjectSplit(maxlen);
KPrintf( " --- --- ------- ---------- ---------- ------ ---------- ---\n");
#else
KPrintf("%-*.s pri status sp stack size max used left tick error\n", maxlen, item_title); ObjectSplit(maxlen);
KPrintf( " --- ------- ---------- ---------- ------ ---------- ---\n");
#endif
#else
#ifdef ARCH_SMP
KPrintf("%-*.s cpu pri status sp stack size max used error\n", maxlen, item_title); ObjectSplit(maxlen);
KPrintf( " --- --- ------- ---------- ---------- ------ ---\n");
#else
KPrintf("%-*.s pri status sp stack size max used error\n", maxlen, item_title); ObjectSplit(maxlen);
KPrintf( " --- ------- ---------- ---------- ------ ---\n");
#endif
#endif
do
{
next = ListGetNext(next, &find_arg);
{
int i;
for (i = 0; i < find_arg.nr_out; i++) {
struct TaskDescriptor *obj;
struct TaskDescriptor task_info, *task;
obj = SYS_DOUBLE_LINKLIST_ENTRY(obj_list[i], struct TaskDescriptor, link);
level = CriticalAreaLock();
memcpy(&task_info, obj, sizeof task_info);
CriticalAreaUnLock(level);
task = (struct TaskDescriptor*)obj;
{
uint8 stat;
uint8 *ptr;
#ifdef ARCH_SMP
KPrintf("%-*.*s %3d %3d ", maxlen, NAME_NUM_MAX, task->task_base_info.name, task->task_smp_info.runing_coreid, task->task_dync_sched_member.cur_prio);
#else
KPrintf("%-*.*s %3d ", maxlen, NAME_NUM_MAX, task->task_base_info.name, task->task_dync_sched_member.cur_prio);
#endif
stat = KTaskStatGet(task);
if (stat == KTASK_READY) KPrintf(" ready ");
else if (stat == KTASK_SUSPEND) KPrintf(" suspend");
else if (stat == KTASK_INIT) KPrintf(" init ");
else if (stat == KTASK_CLOSE) KPrintf(" close ");
else if (stat == KTASK_RUNNING) KPrintf(" running");
#ifndef SCHED_POLICY_FIFO
ptr = (uint8 *)task->task_base_info.stack_start;
while (*ptr == '#')ptr ++;
KPrintf(" 0x%08x 0x%08x %02d%% 0x%08x %03d\n",
task->task_base_info.stack_depth + ((x_ubase)task->task_base_info.stack_start - (x_ubase)task->stack_point),
task->task_base_info.stack_depth,
(task->task_base_info.stack_depth - ((x_ubase) ptr - (x_ubase) task->task_base_info.stack_start)) * 100
/ task->task_base_info.stack_depth,
task->task_dync_sched_member.rest_timeslice,
task->exstatus);
#else
ptr = (uint8 *)task->task_base_info.stack_start;
while (*ptr == '#')ptr ++;
KPrintf(" 0x%08x 0x%08x %02d%% %03d\n",
task->task_base_info.stack_depth + ((x_ubase)task->task_base_info.stack_start - (x_ubase)task->stack_point),
task->task_base_info.stack_depth,
(task->task_base_info.stack_depth - ((x_ubase) ptr - (x_ubase) task->task_base_info.stack_start)) * 100
/ task->task_base_info.stack_depth,
task->exstatus);
#endif
}
}
}
}
while (next != (DoubleLinklistType*)NONE);
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(0)|SHELL_CMD_DISABLE_RETURN,
ShowTask,ShowTask, list task information);
static void ShowWaitQueue(struct SysDoubleLinklistNode *list)
{
struct TaskDescriptor *task;
struct SysDoubleLinklistNode *node;
for (node = list->node_next; node != list; node = node->node_next) {
task = SYS_DOUBLE_LINKLIST_ENTRY(node, struct TaskDescriptor, task_dync_sched_member.sched_link);
KPrintf("%s", task->task_base_info.name);
if (node->node_next != list)
KPrintf("/");
}
}
#ifdef KERNEL_SEMAPHORE
long ShowSem(void)
{
ListGetNext_t find_arg;
DoubleLinklistType *obj_list[LIST_FIND_OBJ_NR];
DoubleLinklistType *next = (DoubleLinklistType*)NONE;
int maxlen;
const char *item_title = "semaphore";
ListFindManagelistInit(&find_arg, Cmpt_KindN_Semaphore, obj_list, sizeof(obj_list)/sizeof(obj_list[0]));
maxlen = NAME_NUM_MAX;
KPrintf("%-*.s v suspend task\n", maxlen, item_title); ObjectSplit(maxlen);
KPrintf( " --- --------------\n");
do
{
next = ListGetNext(next, &find_arg);
{
int i;
for (i = 0; i < find_arg.nr_out; i++) {
struct Semaphore *obj;
struct Semaphore *sem;
obj = SYS_DOUBLE_LINKLIST_ENTRY(obj_list[i], struct Semaphore, link);
sem = obj;
if (!IsDoubleLinkListEmpty(&sem->pend_list)) {
KPrintf("%-*.*d %03d %d:",
maxlen, NAME_NUM_MAX,
sem->id.id,
sem->value,
DoubleLinkListLenGet(&sem->pend_list));
ShowWaitQueue(&(sem->pend_list));
KPrintf("\n");
} else {
KPrintf("%-*.*d %03d %d\n",
maxlen, NAME_NUM_MAX,
sem->id.id,
sem->value,
DoubleLinkListLenGet(&sem->pend_list));
}
}
}
}
while (next != (DoubleLinklistType*)NONE);
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(0)|SHELL_CMD_DISABLE_RETURN,
ShowSem,ShowSem, show xios semaphore in system);
#endif
#ifdef KERNEL_EVENT
long ShowEvent(void)
{
ListGetNext_t find_arg;
DoubleLinklistType *obj_list[LIST_FIND_OBJ_NR];
DoubleLinklistType *next = (DoubleLinklistType*)NONE;
int maxlen;
const char *item_title = "event";
ListFindManagelistInit(&find_arg, Cmpt_KindN_Event, obj_list, sizeof(obj_list)/sizeof(obj_list[0]));
maxlen = NAME_NUM_MAX;
KPrintf("%-*.s set suspend task\n", maxlen, item_title); ObjectSplit(maxlen);
KPrintf( " ---------- --------------\n");
do
{
next = ListGetNext(next, &find_arg);
{
int i;
for (i = 0; i < find_arg.nr_out; i++) {
struct Event *obj;
struct Event *e;
obj = SYS_DOUBLE_LINKLIST_ENTRY(obj_list[i], struct Event, link);
e = obj;
if (!IsDoubleLinkListEmpty(&e->pend_list)) {
KPrintf("%-*.*d 0x%x %03d:",
maxlen, NAME_NUM_MAX,
e->id.id,
e->events,
DoubleLinkListLenGet(&e->pend_list));
ShowWaitQueue(&(e->pend_list));
KPrintf("\n");
} else {
KPrintf("%-*.*d 0x%08x 0\n",
maxlen, NAME_NUM_MAX, e->id.id, e->events);
}
}
}
}
while (next != (DoubleLinklistType*)NONE);
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(0)|SHELL_CMD_DISABLE_RETURN,
ShowEvent,ShowEvent, list event in system);
#endif
#ifdef KERNEL_MUTEX
long ShowMutex(void)
{
ListGetNext_t find_arg;
DoubleLinklistType *obj_list[LIST_FIND_OBJ_NR];
DoubleLinklistType *next = NONE;
int maxlen;
const char *item_title = "mutex";
ListFindManagelistInit(&find_arg, Cmpt_KindN_Mutex, obj_list, sizeof(obj_list)/sizeof(obj_list[0]));
maxlen = NAME_NUM_MAX;
KPrintf("%-*.s owner hold suspend task cnt\n", maxlen, item_title); ObjectSplit(maxlen);
KPrintf( " -------- ---- --------------\n");
do
{
next = ListGetNext(next, &find_arg);
{
int i;
for (i = 0; i < find_arg.nr_out; i++) {
struct Mutex *obj;
struct Mutex *m;
obj = SYS_DOUBLE_LINKLIST_ENTRY(obj_list[i], struct Mutex, link);
m = obj;
KPrintf("%-*.*d %-8.*s %04d %d\n",
maxlen, NAME_NUM_MAX,
m->id.id,
NAME_NUM_MAX,
m->holder->task_base_info.name,
m->recursive_cnt,
DoubleLinkListLenGet(&m->pend_list));
}
}
}
while (next != NONE);
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(0)|SHELL_CMD_DISABLE_RETURN,ShowMutex, ShowMutex,show xios semaphore in system);
#endif
#ifdef KERNEL_MESSAGEQUEUE
long ShowMsgQueue(void)
{
ListGetNext_t find_arg;
DoubleLinklistType *obj_list[LIST_FIND_OBJ_NR];
DoubleLinklistType *next = (DoubleLinklistType*)NONE;
int maxlen;
const char *item_title = "msgqueue";
ListFindManagelistInit(&find_arg, Cmpt_KindN_MessageQueue, obj_list, sizeof(obj_list)/sizeof(obj_list[0]));
maxlen = NAME_NUM_MAX;
KPrintf("%-*.s entry suspend task\n", maxlen, item_title); ObjectSplit(maxlen);
KPrintf( " ---- --------------\n");
do
{
next = ListGetNext(next, &find_arg);
{
int i;
for (i = 0; i < find_arg.nr_out; i++) {
struct MsgQueue *obj;
struct MsgQueue *m;
obj = SYS_DOUBLE_LINKLIST_ENTRY(obj_list[i], struct MsgQueue, link);
m = obj;
if (!IsDoubleLinkListEmpty(&m->recv_pend_list))
{
KPrintf("%-*.*d %04d %d:",
maxlen, NAME_NUM_MAX,
m->id.id,
m->num_msgs,
DoubleLinkListLenGet(&m->recv_pend_list));
ShowWaitQueue(&(m->recv_pend_list));
KPrintf("\n");
} else {
KPrintf("%-*.*d %04d %d\n",
maxlen, NAME_NUM_MAX,
m->id.id,
m->num_msgs,
DoubleLinkListLenGet(&m->recv_pend_list));
}
}
}
}
while (next != (DoubleLinklistType*)NONE);
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(0)|SHELL_CMD_DISABLE_RETURN,
ShowMsgQueue,ShowMsgQueue, list message queue in system);
#endif
#ifdef KERNEL_MEMBLOCK
long ShowMemPool(void)
{
x_ubase level;
ListGetNext_t find_arg;
DoubleLinklistType *obj_list[LIST_FIND_OBJ_NR];
DoubleLinklistType *next = (DoubleLinklistType*)NONE;
int maxlen;
const char *item_title = "mempool";
ListFindManagelistInit(&find_arg, Cmpt_KindN_MemPool, obj_list, sizeof(obj_list)/sizeof(obj_list[0]));
maxlen = NAME_NUM_MAX;
KPrintf("%-*.s block total free suspend task\n", maxlen, item_title); ObjectSplit(maxlen);
KPrintf( " ---- ---- ---- --------------\n");
do
{
next = ListGetNext(next, &find_arg);
{
int i;
for (i = 0; i < find_arg.nr_out; i++) {
struct MemGather *mp;
int suspend_task_count;
DoubleLinklistType *node;
mp = SYS_DOUBLE_LINKLIST_ENTRY(obj_list[i], struct MemGather, m_link);
suspend_task_count = 0;
DOUBLE_LINKLIST_FOR_EACH(node, &mp->wait_task)
{
suspend_task_count++;
}
if (suspend_task_count > 0) {
KPrintf("%-*.*s %04d %04d %04d %d:",
maxlen, NAME_NUM_MAX,
mp->m_name,
mp->one_block_size,
mp->block_total_number,
mp->block_free_number,
suspend_task_count);
ShowWaitQueue(&(mp->wait_task));
KPrintf("\n");
} else {
KPrintf("%-*.*s %04d %04d %04d %d\n",
maxlen, NAME_NUM_MAX,
mp->m_name,
mp->one_block_size,
mp->block_total_number,
mp->block_free_number,
suspend_task_count);
}
}
}
}
while (next != (DoubleLinklistType*)NONE);
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(0)|SHELL_CMD_DISABLE_RETURN,
ShowMemPool,ShowMemPool, list memory pool in system);
#endif
#ifdef KERNEL_SOFTTIMER
long ShowTimer(void)
{
ListGetNext_t find_arg;
DoubleLinklistType *obj_list[LIST_FIND_OBJ_NR];
DoubleLinklistType *next = (DoubleLinklistType*)NONE;
int maxlen;
const char *item_title = "timer";
ListFindManagelistInit(&find_arg, Cmpt_KindN_Timer, obj_list, sizeof(obj_list)/sizeof(obj_list[0]));
maxlen = NAME_NUM_MAX;
KPrintf("%-*.s periodic timeout flag\n", maxlen, item_title); ObjectSplit(maxlen);
KPrintf( " ---------- ---------- -----------\n");
do {
next = ListGetNext(next, &find_arg);
{
int i;
for (i = 0; i < find_arg.nr_out; i++) {
struct Timer *obj;
struct Timer *timer;
obj = SYS_DOUBLE_LINKLIST_ENTRY(obj_list[i], struct Timer, link);
timer = obj;
KPrintf("%-*.*s 0x%08x 0x%08x 0x%08x",
maxlen, NAME_NUM_MAX,
timer->name,
timer->origin_timeslice,
timer->deadline_timeslice,
timer->id_node.id);
if (timer->active_status == TIMER_ACTIVE_TRUE)
KPrintf("activated\n");
else
KPrintf("deactivated\n");
}
}
}
while (next != (DoubleLinklistType*)NONE);
KPrintf("current tick:0x%08x\n", CurrentTicksGain());
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(0)|SHELL_CMD_DISABLE_RETURN,
ShowTimer,ShowTimer, list timer in system);
#endif
static char *const bus_type_str[] =
{
"I2C_BUS",
"SPI_BUS",
"HWT_BUS",
"USB_BUS",
"CAN_BUS",
"WDT_BUS",
"SDIO_BUS",
"TOUCH_BUS",
"LCD_BUS",
"PIN_BUS",
"RTC_BUS",
"SERIAL_BUS",
"Unknown"
};
static DriverType showBusFindDriver(struct Bus *bus)
{
struct Driver *driver = NONE;
DoubleLinklistType *node = NONE;
DoubleLinklistType *head = &bus->bus_drvlink;
for(node = head->node_next; node != head; node = node->node_next) {
driver = SYS_DOUBLE_LINKLIST_ENTRY(node, struct Driver, driver_link);
return driver;
}
return NONE;
}
long ShowBus(void)
{
ListGetNext_t find_arg;
DoubleLinklistType *obj_list[LIST_FIND_OBJ_NR];
DoubleLinklistType *next = (DoubleLinklistType*)NONE;
int i = 0;
int dev_cnt, maxlen;
const char *item_type = "bus_type";
const char *item_name_0 = "bus_name";
const char *item_name_1 = "drv_name";
const char *item_name_2 = "dev_name";
const char *item_cnt = "cnt";
ListFindManagelistInit(&find_arg, Cmpt_KindN_Bus, obj_list, sizeof(obj_list)/sizeof(obj_list[0]));
KPrintf(" %-15s%-15s%-15s%-15s%-20s\n", item_type, item_name_0, item_name_1, item_name_2, item_cnt);
maxlen = 65;
while (i < maxlen) {
i++;
if (maxlen == i) {
KPrintf("-\n");
} else {
KPrintf("-");
}
}
do
{
next = ListGetNext(next, &find_arg);
{
int i;
for (i = 0; i < find_arg.nr_out; i++) {
struct Bus *bus;
bus = SYS_DOUBLE_LINKLIST_ENTRY(obj_list[i], struct Bus, bus_link);
if (bus) {
KPrintf("%s", " ");
KPrintf("%-15s%-15s",
bus_type_str[bus->bus_type],
bus->bus_name);
DriverType driver = showBusFindDriver(bus);
if (driver) {
KPrintf("%-15s", driver->drv_name);
} else {
KPrintf("%-15s", "nil");
}
if (bus->haldev_cnt) {
DoubleLinklistType *node = NONE;
DoubleLinklistType *head = &bus->bus_devlink;
node = head->node_next;
dev_cnt = 1;
while (node != head) {
HardwareDevType device = SYS_DOUBLE_LINKLIST_ENTRY(node, struct HardwareDev, dev_link);
if (1 == dev_cnt) {
if (device) {
KPrintf("%-16s%-4d\n", device->dev_name, dev_cnt);
} else {
KPrintf("%-16s%-4d\n", "nil", dev_cnt);
}
} else {
KPrintf("%46s", " ");
if (device) {
KPrintf("%-16s%-4d\n", device->dev_name, dev_cnt);
} else {
KPrintf("%-16s%-4d\n", "nil", dev_cnt);
}
}
dev_cnt++;
node = node->node_next;
}
} else {
KPrintf("\n");
}
}
}
}
}
while (next != (DoubleLinklistType*)NONE);
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(1)|SHELL_CMD_DISABLE_RETURN,
ShowBus, ShowBus, show bus all device and driver in system);
#ifdef RESOURCES_RTC
#include "bus_rtc.h"
static void SetDateAndTime(char argc, char **argv)
{
if (1 == argc) {
time_t now;
now = time(NONE);
KPrintf("%s", ctime(&now));
} else if (argc >= 7) {
struct RtcSetParam rtc_set_param;
rtc_set_param.rtc_set_cmd = OPER_RTC_SET_TIME;
uint16 year;
uint8 month, day, hour, min, sec;
year = atoi(argv[1]);
month = atoi(argv[2]);
day = atoi(argv[3]);
hour = atoi(argv[4]);
min = atoi(argv[5]);
sec = atoi(argv[6]);
if (year > 2099 || year < 2000) {
KPrintf("year is out of range [2000-2099]\n");
return;
}
if (month == 0 || month > 12) {
KPrintf("month is out of range [1-12]\n");
return;
}
if (day == 0 || day > 31) {
KPrintf("day is out of range [1-31]\n");
return;
}
if (hour > 23) {
KPrintf("hour is out of range [0-23]\n");
return;
}
if (min > 59) {
KPrintf("minute is out of range [0-59]\n");
return;
}
if (sec > 59) {
KPrintf("second is out of range [0-59]\n");
return;
}
rtc_set_param.date_param.year = year;
rtc_set_param.date_param.month = month;
rtc_set_param.date_param.day = day;
rtc_set_param.time_param.hour = hour;
rtc_set_param.time_param.minute = min;
rtc_set_param.time_param.second = sec;
RtcDrvSetFunction(RTC_DRV_NAME, &rtc_set_param);
} else {
KPrintf("only support input [year month day hour min sec]\n");
}
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)|SHELL_CMD_PARAM_NUM(9),
SetDateAndTime, SetDateAndTime, set date and time[year month day hour min sec] );
#endif

View File

@@ -0,0 +1,5 @@
SRC_FILES := shell_fs.c bunzip2.c bzip2.c gunzip.c gzip.c tar.c unzip.c utility.c msh_file.c
SRC_DIR := bzlib
include $(KERNEL_ROOT)/compiler.mk

View File

@@ -0,0 +1,656 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include <xiuos.h>
#if defined(FS_VFS) && defined(TOOL_SHELL)
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <iot-vfs_posix.h>
#include "utility.h"
#define MAX_GROUPS 6
#define GROUP_SIZE 50
#define MAX_HUFCODE_BITS 20
#define MAX_SYMBOLS 258
#define SYMBOL_RUNA 0
#define SYMBOL_RUNB 1
#define BZIP2_MAGIC ('B' + 'Z' * 256)
#define IOBUF_SIZE 4096
#define RET_ERROR -1
#define RET_LASTBLOCK -2
struct GroupData {
int32_t limit[MAX_HUFCODE_BITS+1], base[MAX_HUFCODE_BITS], permute[MAX_SYMBOLS];
int minLen, maxLen;
};
typedef struct BunZipData {
uint32_t inbufBitCount, inbufBits;
int in_fd, out_fd, inbufCount, inbufPos;
uint8_t *inbuf;
int writeCopies, writePos, writeRunCountdown, writeCount;
int writeCurrent;
uint32_t headerCRC, totalCRC, writeCRC;
uint32_t *dbuf;
uint32_t dbufSize;
uint32_t crc32Table[256];
uint8_t selectors[32768];
struct GroupData groups[MAX_GROUPS];
} BunZipData_t;
static int GetBits(BunZipData_t *bd, int bits_wanted, uint32_t *bits)
{
uint32_t b = 0;
int bit_count = bd->inbufBitCount;
while (bit_count < bits_wanted) {
if (bd->inbufPos == bd->inbufCount) {
bd->inbufCount = read(bd->in_fd, bd->inbuf, IOBUF_SIZE);
if (bd->inbufCount <= 0)
return -1;
bd->inbufPos = 0;
}
if (bit_count >= 24) {
b = bd->inbufBits & ((1U << bit_count) - 1);
bits_wanted -= bit_count;
b <<= bits_wanted;
bit_count = 0;
}
bd->inbufBits = (bd->inbufBits << 8) | bd->inbuf[bd->inbufPos++];
bit_count += 8;
}
bit_count -= bits_wanted;
bd->inbufBitCount = bit_count;
b |= (bd->inbufBits >> bit_count) & ((1 << bits_wanted) - 1);
*bits = b;
return 0;
}
static int GetNextBlock(BunZipData_t *bd)
{
int groupCount, selector,
i, j, symCount, symTotal, nSelectors, byteCount[256];
uint8_t uc, symToByte[256], mtfSymbol[256], *selectors;
uint32_t *dbuf;
uint32_t origPtr, t;
uint32_t dbufCount, runPos;
uint32_t runCnt = runCnt;
uint32_t tmp;
dbuf = bd->dbuf;
selectors = bd->selectors;
if (GetBits(bd, 24, (uint32_t *)&i) < 0)
return RET_ERROR;
if (GetBits(bd, 24, (uint32_t *)&j) < 0)
return RET_ERROR;
if (GetBits(bd, 32, &bd->headerCRC) < 0)
return RET_ERROR;
if ((i == 0x177245) && (j == 0x385090))
return RET_LASTBLOCK;
if ((i != 0x314159) || (j != 0x265359))
return RET_ERROR;
if (GetBits(bd, 1, &tmp) < 0)
return RET_ERROR;
if (tmp)
return RET_ERROR;
if (GetBits(bd, 24, (uint32_t *)&origPtr) < 0)
return RET_ERROR;
if (origPtr > bd->dbufSize)
return RET_ERROR;
symTotal = 0;
i = 0;
if (GetBits(bd, 16, &t) < 0)
return RET_ERROR;
do {
if (t & (1 << 15)) {
uint32_t inner_map;
if (GetBits(bd, 16, &inner_map) < 0)
return RET_ERROR;
do {
if (inner_map & (1 << 15))
symToByte[symTotal++] = i;
inner_map <<= 1;
i++;
} while (i & 15);
i -= 16;
}
t <<= 1;
i += 16;
} while (i < 256);
if (GetBits(bd, 3, (uint32_t *)&groupCount) < 0)
return RET_ERROR;
if (groupCount < 2 || groupCount > MAX_GROUPS)
return RET_ERROR;
for (i = 0; i < groupCount; i++)
mtfSymbol[i] = i;
if (GetBits(bd, 15, (uint32_t *)&nSelectors) < 0)
return RET_ERROR;
if (!nSelectors)
return RET_ERROR;
for (i = 0; i < nSelectors; i++) {
uint8_t tmp_byte;
int n = 0;
while (GetBits(bd, 1, &tmp) == 0 && tmp) {
n++;
if (n >= groupCount)
return RET_ERROR;
}
tmp_byte = mtfSymbol[n];
while (--n >= 0)
mtfSymbol[n + 1] = mtfSymbol[n];
mtfSymbol[0] = selectors[i] = tmp_byte;
}
symCount = symTotal + 2;
for (j = 0; j < groupCount; j++) {
uint8_t length[MAX_SYMBOLS];
uint32_t temp[MAX_HUFCODE_BITS+1];
struct GroupData *hufGroup;
int32_t *base, *limit;
int minLen, maxLen, pp, len_m1;
if (GetBits(bd, 5, (uint32_t *)&len_m1) < 0)
return RET_ERROR;
len_m1 -= 1;
for (i = 0; i < symCount; i++) {
for (;;) {
int two_bits;
if ((uint32_t)len_m1 > (MAX_HUFCODE_BITS - 1))
return RET_ERROR;
if (GetBits(bd, 2, (uint32_t *)&two_bits) < 0)
return RET_ERROR;
if (two_bits < 2) {
bd->inbufBitCount++;
break;
}
len_m1 += (((two_bits+1) & 2) - 1);
}
length[i] = len_m1 + 1;
}
minLen = maxLen = length[0];
for (i = 1; i < symCount; i++) {
if (length[i] > maxLen)
maxLen = length[i];
else if (length[i] < minLen)
minLen = length[i];
}
hufGroup = bd->groups + j;
hufGroup->minLen = minLen;
hufGroup->maxLen = maxLen;
base = &hufGroup->base[0] - 1;
limit = &hufGroup->limit[0] - 1;
pp = 0;
for (i = minLen; i <= maxLen; i++) {
int k;
temp[i] = limit[i] = 0;
for (k = 0; k < symCount; k++)
if (length[k] == i)
hufGroup->permute[pp++] = k;
}
for (i = 0; i < symCount; i++)
temp[length[i]]++;
pp = t = 0;
for (i = minLen; i < maxLen;) {
uint32_t temp_i = temp[i];
pp += temp_i;
limit[i] = (pp << (maxLen - i)) - 1;
pp <<= 1;
t += temp_i;
base[++i] = pp - t;
}
limit[maxLen] = pp + temp[maxLen] - 1;
limit[maxLen+1] = INT32_MAX;
base[minLen] = 0;
}
for (i = 0; i < 256; i++) {
byteCount[i] = 0;
mtfSymbol[i] = (uint8_t)i;
}
runPos = dbufCount = selector = 0;
for (;;) {
struct GroupData *hufGroup;
int *base, *limit;
int nextSym;
uint8_t ngrp;
symCount = GROUP_SIZE - 1;
if (selector >= nSelectors)
return RET_ERROR;
ngrp = selectors[selector++];
if (ngrp >= groupCount)
return RET_ERROR;
hufGroup = bd->groups + ngrp;
base = hufGroup->base - 1;
limit = hufGroup->limit - 1;
continue_this_group:
if (1) {
int new_cnt;
while ((new_cnt = bd->inbufBitCount - hufGroup->maxLen) < 0) {
if (bd->inbufPos == bd->inbufCount) {
if (GetBits(bd, hufGroup->maxLen, (uint32_t *)&nextSym) < 0)
return RET_ERROR;
goto got_huff_bits;
}
bd->inbufBits = (bd->inbufBits << 8) | bd->inbuf[bd->inbufPos++];
bd->inbufBitCount += 8;
};
bd->inbufBitCount = new_cnt;
nextSym = (bd->inbufBits >> new_cnt) & ((1 << hufGroup->maxLen) - 1);
got_huff_bits: ;
} else {
if (GetBits(bd, hufGroup->maxLen, (uint32_t *)&nextSym) < 0)
return RET_ERROR;
}
i = hufGroup->minLen;
while (nextSym > limit[i])
++i;
j = hufGroup->maxLen - i;
if (j < 0)
return RET_ERROR;
bd->inbufBitCount += j;
nextSym = (nextSym >> j) - base[i];
if ((unsigned)nextSym >= MAX_SYMBOLS)
return RET_ERROR;
nextSym = hufGroup->permute[nextSym];
if ((unsigned)nextSym <= SYMBOL_RUNB) {
if (runPos == 0) {
runPos = 1;
runCnt = 0;
}
runCnt += (runPos << nextSym);
if (runPos < bd->dbufSize) runPos <<= 1;
goto end_of_huffman_loop;
}
if (runPos != 0) {
uint8_t tmp_byte;
if (dbufCount + runCnt > bd->dbufSize)
return RET_ERROR;
tmp_byte = symToByte[mtfSymbol[0]];
byteCount[tmp_byte] += runCnt;
while ((int)--runCnt >= 0)
dbuf[dbufCount++] = (uint32_t)tmp_byte;
runPos = 0;
}
if (nextSym > symTotal)
break;
if (dbufCount >= bd->dbufSize)
return RET_ERROR;
i = nextSym - 1;
uc = mtfSymbol[i];
do {
mtfSymbol[i] = mtfSymbol[i - 1];
} while (--i);
mtfSymbol[0] = uc;
uc = symToByte[uc];
byteCount[uc]++;
dbuf[dbufCount++] = (uint32_t)uc;
end_of_huffman_loop:
if (--symCount >= 0) goto continue_this_group;
}
j = 0;
for (i = 0; i < 256; i++) {
int tmp_count = j + byteCount[i];
byteCount[i] = j;
j = tmp_count;
}
for (i = 0; i < dbufCount; i++) {
uint8_t tmp_byte = (uint8_t)dbuf[i];
int tmp_count = byteCount[tmp_byte];
dbuf[tmp_count] |= (i << 8);
byteCount[tmp_byte] = tmp_count + 1;
}
if (dbufCount) {
uint32_t tmp;
if ((int)origPtr >= dbufCount)
return RET_ERROR;
tmp = dbuf[origPtr];
bd->writeCurrent = (uint8_t)tmp;
bd->writePos = (tmp >> 8);
bd->writeRunCountdown = 5;
}
bd->writeCount = dbufCount;
return 0;
}
static int ReadBunzip(BunZipData_t *bd, char *outbuf, int len)
{
const uint32_t *dbuf;
int pos, current, previous;
uint32_t CRC;
if (bd->writeCount < 0)
return bd->writeCount;
dbuf = bd->dbuf;
pos = bd->writePos;
current = bd->writeCurrent;
CRC = bd->writeCRC;
if (bd->writeCopies) {
dec_writeCopies:
--bd->writeCopies;
for (;;) {
if (--len < 0) {
goto outbuf_full;
}
*outbuf++ = current;
CRC = (CRC << 8) ^ bd->crc32Table[(CRC >> 24) ^ current];
if (bd->writeCopies) {
goto dec_writeCopies;
}
decode_next_byte:
if (--bd->writeCount < 0)
break;
previous = current;
pos = dbuf[pos];
current = (uint8_t)pos;
pos >>= 8;
if (--bd->writeRunCountdown != 0) {
if (current != previous)
bd->writeRunCountdown = 4;
} else {
bd->writeCopies = current;
current = previous;
bd->writeRunCountdown = 5;
if (!bd->writeCopies) goto decode_next_byte;
--bd->writeCopies;
}
}
bd->writeCRC = CRC = ~CRC;
bd->totalCRC = ((bd->totalCRC << 1) | (bd->totalCRC >> 31)) ^ CRC;
if (CRC != bd->headerCRC) {
bd->totalCRC = bd->headerCRC + 1;
return RET_LASTBLOCK;
}
}
{
int r = GetNextBlock(bd);
if (r) {
bd->writeCount = r;
return (r != RET_LASTBLOCK) ? r : len;
}
}
CRC = ~0;
pos = bd->writePos;
current = bd->writeCurrent;
goto decode_next_byte;
outbuf_full:
bd->writePos = pos;
bd->writeCurrent = current;
bd->writeCRC = CRC;
bd->writeCopies++;
return 0;
}
static void Crc32FilltableBigEndian(uint32_t *crc_table)
{
uint32_t polynomial = 0x04c11db7;
uint32_t c;
unsigned i, j;
for (i = 0; i < 256; i++) {
c = i << 24;
for (j = 8; j; j--) {
c = (c & 0x80000000) ? ((c << 1) ^ polynomial) : (c << 1);
}
*crc_table++ = c;
}
}
static int StartBunzip(BunZipData_t **bdp, int in_fd,
const void *inbuf, int len)
{
BunZipData_t *bd;
uint32_t i;
enum {
BZh0 = ('B' << 24) + ('Z' << 16) + ('h' << 8) + '0',
h0 = ('h' << 8) + '0',
};
i = sizeof(BunZipData_t);
if (in_fd != -1)
i += IOBUF_SIZE;
bd = *bdp = malloc(i);
if (bd == NULL)
return RET_ERROR;
memset(bd, 0, sizeof(*bd));
bd->in_fd = in_fd;
if (in_fd == -1) {
bd->inbuf = (void *)inbuf;
} else {
bd->inbuf = (uint8_t *)(bd + 1);
memcpy(bd->inbuf, inbuf, len);
}
bd->inbufCount = len;
Crc32FilltableBigEndian(bd->crc32Table);
if (GetBits(bd, 16, (uint32_t *)&i) < 0)
return RET_ERROR;
if ((unsigned)(i - h0 - 1) >= 9)
return RET_ERROR;
bd->dbufSize = 100000 * (i - h0);
bd->dbuf = malloc(bd->dbufSize * sizeof(bd->dbuf[0]));
if (!bd->dbuf) {
free(bd);
return RET_ERROR;
}
return 0;
}
int Bzip2Decompress(char *file_name)
{
BunZipData_t *bd;
char *out_buf;
int i;
uint32_t len;
int in_fd, out_fd;
uint16_t magic;
int ret = 0;
if ((in_fd = open(file_name, O_RDONLY)) < 0)
return RET_ERROR;
if (TruncateExtension(file_name, ".bz2") < 0) {
ret = RET_ERROR;
goto close_in_fd;
}
if ((out_fd = open(file_name, O_WRONLY | O_CREAT | O_TRUNC)) < 0) {
ret = RET_ERROR;
goto close_in_fd;
}
if ((out_buf = malloc(IOBUF_SIZE)) == NULL) {
ret = RET_ERROR;
goto close_out_fd;
}
if (read(in_fd, &magic, 2) != 2 || magic != BZIP2_MAGIC) {
ret = -1;
goto free_out_buf;
}
len = 0;
while (1) {
i = StartBunzip(&bd, in_fd, out_buf + 2, len);
if (i == 0) {
while (1) {
i = ReadBunzip(bd, out_buf, IOBUF_SIZE);
if (i < 0)
break;
i = IOBUF_SIZE - i;
if (i == 0)
break;
if (write(out_fd, out_buf, i) != i) {
ret = RET_ERROR;
goto free_bd;
}
}
}
if (i != 0 && i != RET_LASTBLOCK)
break;
if (bd->headerCRC != bd->totalCRC)
break;
i = 0;
len = bd->inbufCount - bd->inbufPos;
memcpy(out_buf, &bd->inbuf[bd->inbufPos], len);
if (len < 2) {
if (read(in_fd, out_buf + len, 2 - len) != 2 - len)
break;
len = 2;
}
if (*(uint16_t *)out_buf != BZIP2_MAGIC)
break;
free(bd->dbuf);
free(bd);
len -=2;
}
free_bd:
free(bd->dbuf);
free(bd);
free_out_buf:
free(out_buf);
close_out_fd:
close(out_fd);
close_in_fd:
close(in_fd);
return ret;
}
void Bunzip2PrintUsage()
{
KPrintf("Usage: bunzip2 [FILES]....\n");
KPrintf("File names MUST end with the .bz2 extension\n");
}
int bunzip2(int argc, char **argv)
{
if (argc < 2) {
Bunzip2PrintUsage();
return 0;
}
for (int i = 1; i < argc; i++)
if (Bzip2Decompress(argv[i]) < 0)
KPrintf("Operation failed: %s\n", argv[i]);
return 0;
}
#endif

View File

@@ -0,0 +1,162 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include <xiuos.h>
#if defined(FS_VFS) && defined(TOOL_SHELL)
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <iot-vfs_posix.h>
#include <bzip2.h>
#include "bzlib/bzlib.h"
#include "utility.h"
#define IOBUF_SIZE 8192
char *in_buf, *out_buf;
static int BzWrite(BzStream *stream, int ReadSize, int out_fd)
{
stream->avail_in = ReadSize;
stream->next_in = in_buf;
while (1) {
stream->avail_out = IOBUF_SIZE;
stream->next_out = out_buf;
int ret = BZ2BzCompress(stream,
ReadSize > 0 ? BZ_RUN : BZ_FINISH);
if (ret != BZ_RUN_OK && ret != BZ_FINISH_OK &&
ret != BZ_STREAM_END)
return -1;
int out_buf_cnt = IOBUF_SIZE - stream->avail_out;
if (out_buf_cnt) {
int written_size = write(out_fd, out_buf, out_buf_cnt);
if (written_size != out_buf_cnt)
return -1;
}
if (ret == BZ_STREAM_END || (ReadSize > 0 && stream->avail_in == 0))
break;
}
return 0;
}
int Bzip2Compress(char *file_name)
{
int ret = 0;
char *bz_file_name;
struct stat statbuf;
int in_fd, out_fd;
BzStream stream;
if ((in_fd = open(file_name, O_RDONLY)) < 0)
return -1;
if (fstat(in_fd, &statbuf) < 0 || !S_ISREG(statbuf.st_mode)) {
ret = -1;
goto close_in_fd;
}
if ((bz_file_name = malloc(strlen(file_name) + 5)) == NULL) {
ret = -1;
goto close_in_fd;
}
strcpy(bz_file_name, file_name);
strcat(bz_file_name, ".bz2");
if ((out_fd = open(bz_file_name, O_WRONLY | O_CREAT | O_TRUNC)) < 0) {
ret = -1;
goto free_bz_file_name;
}
if ((in_buf = malloc(2 * IOBUF_SIZE)) == NULL) {
ret = -1;
goto close_out_fd;
}
out_buf = in_buf + IOBUF_SIZE;
memset(&stream, 0, sizeof(BzStream));
BZ2BzCompressInit(&stream, 1);
while (1) {
int ReadSize = read(in_fd, in_buf, IOBUF_SIZE);
if (ReadSize < 0) {
ret = -1;
break;
}
ret = BzWrite(&stream, ReadSize, out_fd);
if (ReadSize == 0 || ret < 0)
break;
}
BZ2BzCompressEnd(&stream);
free(in_buf);
close_out_fd:
close(out_fd);
free_bz_file_name:
free(bz_file_name);
close_in_fd:
close(in_fd);
return ret;
}
static void Bzip2PrintUsage()
{
KPrintf("Usage: bzip2 [OPTIONS]... [FILES]...\n");
KPrintf("Supported option flags:\n");
KPrintf(" d decompress bzip2 file(s)\n");
}
extern int Bzip2Decompress(char *file_name);
int bzip2(int argc, char **argv)
{
int (*bzip2_func)(char *file_name) = Bzip2Compress;
if (argc == 1) {
Bzip2PrintUsage();
return 0;
}
if (argv[1][0] == '-') {
if (strcmp(argv[1], "-b") != 0) {
KPrintf("Bad options\n");
Bzip2PrintUsage();
return 0;
}
bzip2_func = Bzip2Decompress;
argv++;
argc--;
}
for (int i = 1; i < argc; i++)
if (bzip2_func(argv[i]) < 0) {
KPrintf("Operation failed\n");
break;
}
return 0;
}
#endif

View File

@@ -0,0 +1,18 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#ifndef __INC_BZIP2_H__
#define __INC_BZIP2_H__
int Bzip2Compress(char *file_name);
#endif

View File

@@ -0,0 +1,5 @@
SRC_FILES := blocksort.c bzlib.c compress.c huffman.c
include $(KERNEL_ROOT)/compiler.mk

View File

@@ -0,0 +1,838 @@
/* ------------------------------------------------------------------
This file is part of bzip2/libbzip2, a program and library for
lossless, block-sorting data compression.
bzip2/libbzip2 version 1.0.4 of 20 December 2006
Copyright (C) 1996-2006 Julian Seward <jseward@bzip.org>
Please read the WARNING, DISCLAIMER and PATENTS sections in the
README file.
This program is released under the terms of the license contained
in the file LICENSE.
------------------------------------------------------------------ */
#include <string.h>
#include <stdint.h>
#include "bzlib_private.h"
#define MSWAP(zz1, zz2) { \
int32_t zztmp = zz1; \
zz1 = zz2; \
zz2 = zztmp; \
}
static void mvswap(uint32_t* ptr, int32_t zzp1, int32_t zzp2, int32_t zzn)
{
while (zzn > 0) {
MSWAP(ptr[zzp1], ptr[zzp2]);
zzp1++;
zzp2++;
zzn--;
}
}
static inline int32_t mmin(int32_t a, int32_t b)
{
return (a < b) ? a : b;
}
static inline void FallbackSimpleSort(uint32_t* fmap,
uint32_t* eclass,
int32_t lo,
int32_t hi)
{
int32_t i, j, tmp;
uint32_t ec_tmp;
if (lo == hi) return;
if (hi - lo > 3) {
for (i = hi-4; i >= lo; i--) {
tmp = fmap[i];
ec_tmp = eclass[tmp];
for (j = i+4; j <= hi && ec_tmp > eclass[fmap[j]]; j += 4)
fmap[j-4] = fmap[j];
fmap[j-4] = tmp;
}
}
for (i = hi-1; i >= lo; i--) {
tmp = fmap[i];
ec_tmp = eclass[tmp];
for (j = i+1; j <= hi && ec_tmp > eclass[fmap[j]]; j++)
fmap[j-1] = fmap[j];
fmap[j-1] = tmp;
}
}
#define FPUSH(lz,hz) { \
stackLo[sp] = lz; \
stackHi[sp] = hz; \
sp++; \
}
#define FPOP(lz,hz) { \
sp--; \
lz = stackLo[sp]; \
hz = stackHi[sp]; \
}
#define FALLBACK_QSORT_SMALL_THRESH 10
#define FALLBACK_QSORT_STACK_SIZE 100
static void FallbackQSort3(uint32_t* fmap,
uint32_t* eclass,
int32_t loSt,
int32_t hiSt)
{
int32_t sp;
uint32_t r;
int32_t stackLo[FALLBACK_QSORT_STACK_SIZE];
int32_t stackHi[FALLBACK_QSORT_STACK_SIZE];
r = 0;
sp = 0;
FPUSH(loSt, hiSt);
while (sp > 0) {
int32_t unLo, unHi, ltLo, gtHi, n, m;
int32_t lo, hi;
uint32_t med;
uint32_t r3;
ASSERTH(sp < FALLBACK_QSORT_STACK_SIZE - 1, 1004);
FPOP(lo, hi);
if (hi - lo < FALLBACK_QSORT_SMALL_THRESH) {
FallbackSimpleSort(fmap, eclass, lo, hi);
continue;
}
r = ((r * 7621) + 1) % 32768;
r3 = r % 3;
if (r3 == 0)
med = eclass[fmap[lo]];
else if (r3 == 1)
med = eclass[fmap[(lo+hi)>>1]];
else
med = eclass[fmap[hi]];
unLo = ltLo = lo;
unHi = gtHi = hi;
while (1) {
while (1) {
if (unLo > unHi) break;
n = (int32_t)eclass[fmap[unLo]] - (int32_t)med;
if (n == 0) {
MSWAP(fmap[unLo], fmap[ltLo]);
ltLo++;
unLo++;
continue;
}
if (n > 0) break;
unLo++;
}
while (1) {
if (unLo > unHi) break;
n = (int32_t)eclass[fmap[unHi]] - (int32_t)med;
if (n == 0) {
MSWAP(fmap[unHi], fmap[gtHi]);
gtHi--; unHi--;
continue;
}
if (n < 0) break;
unHi--;
}
if (unLo > unHi) break;
MSWAP(fmap[unLo], fmap[unHi]); unLo++; unHi--;
}
ASSERTD(unHi == unLo-1, "fallbackQSort3(2)");
if (gtHi < ltLo) continue;
n = mmin(ltLo-lo, unLo-ltLo); mvswap(fmap, lo, unLo-n, n);
m = mmin(hi-gtHi, gtHi-unHi); mvswap(fmap, unLo, hi-m+1, m);
n = lo + unLo - ltLo - 1;
m = hi - (gtHi - unHi) + 1;
if (n - lo > hi - m) {
FPUSH(lo, n);
FPUSH(m, hi);
} else {
FPUSH(m, hi);
FPUSH(lo, n);
}
}
}
#undef FPUSH
#undef FPOP
#undef FALLBACK_QSORT_SMALL_THRESH
#undef FALLBACK_QSORT_STACK_SIZE
#define SET_BH(zz) bhtab[(zz) >> 5] |= (1 << ((zz) & 31))
#define CLEAR_BH(zz) bhtab[(zz) >> 5] &= ~(1 << ((zz) & 31))
#define ISSET_BH(zz) (bhtab[(zz) >> 5] & (1 << ((zz) & 31)))
#define WORD_BH(zz) bhtab[(zz) >> 5]
#define UNALIGNED_BH(zz) ((zz) & 0x01f)
static void FallbackSort(EState* state)
{
int32_t ftab[257];
int32_t ftabCopy[256];
int32_t H, i, j, k, l, r, cc, cc1;
int32_t nNotDone;
int32_t nBhtab;
uint32_t *const fmap = state->arr1;
uint32_t *const eclass = state->arr2;
#define ECLASS8 ((uint8_t*)eclass)
uint32_t *const bhtab = state->ftab;
const int32_t nblock = state->nblock;
for (i = 0; i < 257; i++) ftab[i] = 0;
for (i = 0; i < nblock; i++) ftab[ECLASS8[i]]++;
for (i = 0; i < 256; i++) ftabCopy[i] = ftab[i];
j = ftab[0];
for (i = 1; i < 257; i++) {
j += ftab[i];
ftab[i] = j;
}
for (i = 0; i < nblock; i++) {
j = ECLASS8[i];
k = ftab[j] - 1;
ftab[j] = k;
fmap[k] = i;
}
nBhtab = 2 + ((uint32_t)nblock / 32);
for (i = 0; i < nBhtab; i++) bhtab[i] = 0;
for (i = 0; i < 256; i++) SET_BH(ftab[i]);
for (i = 0; i < 32; i++) {
SET_BH(nblock + 2*i);
CLEAR_BH(nblock + 2*i + 1);
}
H = 1;
while (1) {
j = 0;
for (i = 0; i < nblock; i++) {
if (ISSET_BH(i))
j = i;
k = fmap[i] - H;
if (k < 0)
k += nblock;
eclass[k] = j;
}
nNotDone = 0;
r = -1;
while (1) {
k = r + 1;
while (ISSET_BH(k) && UNALIGNED_BH(k))
k++;
if (ISSET_BH(k)) {
while (WORD_BH(k) == 0xffffffff) k += 32;
while (ISSET_BH(k)) k++;
}
l = k - 1;
if (l >= nblock)
break;
while (!ISSET_BH(k) && UNALIGNED_BH(k))
k++;
if (!ISSET_BH(k)) {
while (WORD_BH(k) == 0x00000000) k += 32;
while (!ISSET_BH(k)) k++;
}
r = k - 1;
if (r >= nblock)
break;
if (r > l) {
nNotDone += (r - l + 1);
FallbackQSort3(fmap, eclass, l, r);
cc = -1;
for (i = l; i <= r; i++) {
cc1 = eclass[fmap[i]];
if (cc != cc1) {
SET_BH(i);
cc = cc1;
}
}
}
}
H *= 2;
if (H > nblock || nNotDone == 0)
break;
}
j = 0;
for (i = 0; i < nblock; i++) {
while (ftabCopy[j] == 0)
j++;
ftabCopy[j]--;
ECLASS8[fmap[i]] = (uint8_t)j;
}
ASSERTH(j < 256, 1005);
#undef ECLASS8
}
#undef SET_BH
#undef CLEAR_BH
#undef ISSET_BH
#undef WORD_BH
#undef UNALIGNED_BH
static int MainGtU(EState* state,
uint32_t i1,
uint32_t i2)
{
int32_t k;
uint8_t c1, c2;
uint16_t s1, s2;
uint8_t *const block = state->block;
uint16_t *const quadrant = state->quadrant;
const int32_t nblock = state->nblock;
#if BZIP2_SPEED >= 1
#define TIMES_8(code) \
code; code; code; code; \
code; code; code; code;
#define TIMES_12(code) \
code; code; code; code; \
code; code; code; code; \
code; code; code; code;
#else
#define TIMES_8(code) { \
int nn = 8; \
do { \
code; \
} while (--nn); \
}
#define TIMES_12(code) { \
int nn = 12; \
do { \
code; \
} while (--nn); \
}
#endif
ASSERTD(i1 != i2, "mainGtU");
TIMES_12(
c1 = block[i1]; c2 = block[i2];
if (c1 != c2) return (c1 > c2);
i1++; i2++;
)
k = nblock + 8;
do {
TIMES_8(
c1 = block[i1]; c2 = block[i2];
if (c1 != c2) return (c1 > c2);
s1 = quadrant[i1]; s2 = quadrant[i2];
if (s1 != s2) return (s1 > s2);
i1++; i2++;
)
if (i1 >= nblock) i1 -= nblock;
if (i2 >= nblock) i2 -= nblock;
state->budget--;
k -= 8;
} while (k >= 0);
return FALSE;
}
#undef TIMES_8
#undef TIMES_12
static
const uint32_t incs[14] = {
1, 4, 13, 40, 121, 364, 1093, 3280,
9841, 29524, 88573, 265720,
797161, 2391484
};
static void MainSimpleSort(EState* state,
int32_t lo,
int32_t hi,
int32_t d)
{
uint32_t *const ptr = state->ptr;
int hp = 0;
{
int bigN = hi - lo;
if (bigN <= 0)
return;
while (incs[hp] <= bigN)
hp++;
hp--;
}
for (; hp >= 0; hp--) {
int32_t i;
unsigned h;
h = incs[hp];
i = lo + h;
while (1) {
unsigned j;
unsigned v;
if (i > hi) break;
v = ptr[i];
j = i;
while (MainGtU(state, ptr[j-h]+d, v+d)) {
ptr[j] = ptr[j-h];
j = j - h;
if (j <= (lo + h - 1)) break;
}
ptr[j] = v;
i++;
#if BZIP2_SPEED >= 3
if (i > hi) break;
v = ptr[i];
j = i;
while (MainGtU(state, ptr[j-h]+d, v+d)) {
ptr[j] = ptr[j-h];
j = j - h;
if (j <= (lo + h - 1)) break;
}
ptr[j] = v;
i++;
if (i > hi) break;
v = ptr[i];
j = i;
while (MainGtU(state, ptr[j-h]+d, v+d)) {
ptr[j] = ptr[j-h];
j = j - h;
if (j <= (lo + h - 1)) break;
}
ptr[j] = v;
i++;
#endif
if (state->budget < 0) return;
}
}
}
static inline uint8_t mmed3(uint8_t a, uint8_t b, uint8_t c)
{
uint8_t t;
if (a > b) {
t = a;
a = b;
b = t;
}
if (b > c) {
b = c;
if (a > b)
b = a;
}
return b;
}
#define MPUSH(lz,hz,dz) { \
stackLo[sp] = lz; \
stackHi[sp] = hz; \
stackD [sp] = dz; \
sp++; \
}
#define MPOP(lz,hz,dz) { \
sp--; \
lz = stackLo[sp]; \
hz = stackHi[sp]; \
dz = stackD [sp]; \
}
#define MNEXTSIZE(az) (nextHi[az] - nextLo[az])
#define MNEXTSWAP(az,bz) { \
int32_t tz; \
tz = nextLo[az]; nextLo[az] = nextLo[bz]; nextLo[bz] = tz; \
tz = nextHi[az]; nextHi[az] = nextHi[bz]; nextHi[bz] = tz; \
tz = nextD [az]; nextD [az] = nextD [bz]; nextD [bz] = tz; \
}
#define MAIN_QSORT_SMALL_THRESH 20
#define MAIN_QSORT_DEPTH_THRESH (BZ_N_RADIX + BZ_N_QSORT)
#define MAIN_QSORT_STACK_SIZE 100
static void MainQSort3(EState* state,
int32_t loSt,
int32_t hiSt
)
{
enum { dSt = BZ_N_RADIX };
int32_t unLo, unHi, ltLo, gtHi, n, m, med;
int32_t sp, lo, hi, d;
int32_t stackLo[MAIN_QSORT_STACK_SIZE];
int32_t stackHi[MAIN_QSORT_STACK_SIZE];
int32_t stackD [MAIN_QSORT_STACK_SIZE];
int32_t nextLo[3];
int32_t nextHi[3];
int32_t nextD [3];
uint32_t *const ptr = state->ptr;
uint8_t *const block = state->block;
sp = 0;
MPUSH(loSt, hiSt, dSt);
while (sp > 0) {
ASSERTH(sp < MAIN_QSORT_STACK_SIZE - 2, 1001);
MPOP(lo, hi, d);
if (hi - lo < MAIN_QSORT_SMALL_THRESH
|| d > MAIN_QSORT_DEPTH_THRESH
) {
MainSimpleSort(state, lo, hi, d);
if (state->budget < 0)
return;
continue;
}
med = (int32_t) mmed3(block[ptr[lo ] + d],
block[ptr[hi ] + d],
block[ptr[(lo+hi) >> 1] + d]);
unLo = ltLo = lo;
unHi = gtHi = hi;
while (1) {
while (1) {
if (unLo > unHi)
break;
n = ((int32_t)block[ptr[unLo]+d]) - med;
if (n == 0) {
MSWAP(ptr[unLo], ptr[ltLo]);
ltLo++;
unLo++;
continue;
}
if (n > 0) break;
unLo++;
}
while (1) {
if (unLo > unHi)
break;
n = ((int32_t)block[ptr[unHi]+d]) - med;
if (n == 0) {
MSWAP(ptr[unHi], ptr[gtHi]);
gtHi--;
unHi--;
continue;
}
if (n < 0) break;
unHi--;
}
if (unLo > unHi)
break;
MSWAP(ptr[unLo], ptr[unHi]);
unLo++;
unHi--;
}
ASSERTD(unHi == unLo-1, "mainQSort3(2)");
if (gtHi < ltLo) {
MPUSH(lo, hi, d + 1);
continue;
}
n = mmin(ltLo-lo, unLo-ltLo); mvswap(ptr, lo, unLo-n, n);
m = mmin(hi-gtHi, gtHi-unHi); mvswap(ptr, unLo, hi-m+1, m);
n = lo + unLo - ltLo - 1;
m = hi - (gtHi - unHi) + 1;
nextLo[0] = lo; nextHi[0] = n; nextD[0] = d;
nextLo[1] = m; nextHi[1] = hi; nextD[1] = d;
nextLo[2] = n+1; nextHi[2] = m-1; nextD[2] = d+1;
if (MNEXTSIZE(0) < MNEXTSIZE(1)) MNEXTSWAP(0, 1);
if (MNEXTSIZE(1) < MNEXTSIZE(2)) MNEXTSWAP(1, 2);
if (MNEXTSIZE(0) < MNEXTSIZE(1)) MNEXTSWAP(0, 1);
ASSERTD (MNEXTSIZE(0) >= MNEXTSIZE(1), "mainQSort3(8)");
ASSERTD (MNEXTSIZE(1) >= MNEXTSIZE(2), "mainQSort3(9)");
MPUSH(nextLo[0], nextHi[0], nextD[0]);
MPUSH(nextLo[1], nextHi[1], nextD[1]);
MPUSH(nextLo[2], nextHi[2], nextD[2]);
}
}
#undef MPUSH
#undef MPOP
#undef MNEXTSIZE
#undef MNEXTSWAP
#undef MAIN_QSORT_SMALL_THRESH
#undef MAIN_QSORT_DEPTH_THRESH
#undef MAIN_QSORT_STACK_SIZE
#define BIGFREQ(b) (ftab[((b)+1) << 8] - ftab[(b) << 8])
#define SETMASK (1 << 21)
#define CLEARMASK (~(SETMASK))
static void MainSort(EState* state)
{
int32_t i, j;
Bool bigDone[256];
uint8_t runningOrder[256];
#define COPYSTART (state->mainSort__copyStart)
#define COPYEND (state->mainSort__copyEnd)
uint32_t *const ptr = state->ptr;
uint8_t *const block = state->block;
uint32_t *const ftab = state->ftab;
const int32_t nblock = state->nblock;
uint16_t *const quadrant = state->quadrant;
memset(ftab, 0, 65537 * sizeof(ftab[0]));
j = block[0] << 8;
i = nblock - 1;
#if BZIP2_SPEED >= 2
for (; i >= 3; i -= 4) {
quadrant[i] = 0;
j = (j >> 8) | (((unsigned)block[i]) << 8);
ftab[j]++;
quadrant[i-1] = 0;
j = (j >> 8) | (((unsigned)block[i-1]) << 8);
ftab[j]++;
quadrant[i-2] = 0;
j = (j >> 8) | (((unsigned)block[i-2]) << 8);
ftab[j]++;
quadrant[i-3] = 0;
j = (j >> 8) | (((unsigned)block[i-3]) << 8);
ftab[j]++;
}
#endif
for (; i >= 0; i--) {
quadrant[i] = 0;
j = (j >> 8) | (((unsigned)block[i]) << 8);
ftab[j]++;
}
for (i = 0; i < BZ_N_OVERSHOOT; i++) {
block [nblock+i] = block[i];
quadrant[nblock+i] = 0;
}
j = ftab[0];
for (i = 1; i <= 65536; i++) {
j += ftab[i];
ftab[i] = j;
}
{
unsigned s;
s = block[0] << 8;
i = nblock - 1;
#if BZIP2_SPEED >= 2
for (; i >= 3; i -= 4) {
s = (s >> 8) | (block[i] << 8);
j = ftab[s] - 1;
ftab[s] = j;
ptr[j] = i;
s = (s >> 8) | (block[i-1] << 8);
j = ftab[s] - 1;
ftab[s] = j;
ptr[j] = i-1;
s = (s >> 8) | (block[i-2] << 8);
j = ftab[s] - 1;
ftab[s] = j;
ptr[j] = i-2;
s = (s >> 8) | (block[i-3] << 8);
j = ftab[s] - 1;
ftab[s] = j;
ptr[j] = i-3;
}
#endif
for (; i >= 0; i--) {
s = (s >> 8) | (block[i] << 8);
j = ftab[s] - 1;
ftab[s] = j;
ptr[j] = i;
}
}
for (i = 0; i <= 255; i++) {
bigDone [i] = FALSE;
runningOrder[i] = i;
}
{
unsigned h = 364;
do {
h = (h * 171) >> 9;
for (i = h; i <= 255; i++) {
unsigned vv, jh;
vv = runningOrder[i];
j = i;
while (jh = j - h, BIGFREQ(runningOrder[jh]) > BIGFREQ(vv)) {
runningOrder[j] = runningOrder[jh];
j = jh;
if (j < h)
break;
}
runningOrder[j] = vv;
}
} while (h != 1);
}
for (i = 0; ; i++) {
unsigned ss;
ss = runningOrder[i];
for (j = 0; j <= 255; j++) {
if (j != ss) {
unsigned sb;
sb = (ss << 8) + j;
if (!(ftab[sb] & SETMASK)) {
int32_t lo = ftab[sb] ;
int32_t hi = (ftab[sb+1] & CLEARMASK) - 1;
if (hi > lo) {
MainQSort3(state, lo, hi );
if (state->budget < 0) return;
}
}
ftab[sb] |= SETMASK;
}
}
ASSERTH(!bigDone[ss], 1006);
{
for (j = 0; j <= 255; j++) {
COPYSTART[j] = ftab[(j << 8) + ss] & CLEARMASK;
COPYEND [j] = (ftab[(j << 8) + ss + 1] & CLEARMASK) - 1;
}
for (j = ftab[ss << 8] & CLEARMASK; j < COPYSTART[ss]; j++) {
unsigned c1;
int32_t k;
k = ptr[j] - 1;
if (k < 0)
k += nblock;
c1 = block[k];
if (!bigDone[c1])
ptr[COPYSTART[c1]++] = k;
}
for (j = (ftab[(ss+1) << 8] & CLEARMASK) - 1; j > COPYEND[ss]; j--) {
unsigned c1;
int32_t k;
k = ptr[j]-1;
if (k < 0)
k += nblock;
c1 = block[k];
if (!bigDone[c1])
ptr[COPYEND[c1]--] = k;
}
}
ASSERTH((COPYSTART[ss]-1 == COPYEND[ss]) \
|| (COPYSTART[ss] == 0 && COPYEND[ss] == nblock-1), 1007);
for (j = 0; j <= 255; j++)
ftab[(j << 8) + ss] |= SETMASK;
if (i == 255)
break;
bigDone[ss] = TRUE;
{
unsigned bbStart = ftab[ss << 8] & CLEARMASK;
unsigned bbSize = (ftab[(ss+1) << 8] & CLEARMASK) - bbStart;
unsigned shifts = 0;
while ((bbSize >> shifts) > 65534) shifts++;
for (j = bbSize-1; j >= 0; j--) {
unsigned a2update = ptr[bbStart + j];
uint16_t qVal = (uint16_t)(j >> shifts);
quadrant[a2update] = qVal;
if (a2update < BZ_N_OVERSHOOT)
quadrant[a2update + nblock] = qVal;
}
ASSERTH(((bbSize-1) >> shifts) <= 65535, 1002);
}
}
#undef runningOrder
#undef COPYSTART
#undef COPYEND
}
#undef BIGFREQ
#undef SETMASK
#undef CLEARMASK
int32_t BZ2BlockSort(EState* state)
{
enum { wfact = 30 };
unsigned i;
int32_t origPtr = origPtr;
if (state->nblock >= 10000) {
i = state->nblock + BZ_N_OVERSHOOT;
if (i & 1)
i++;
state->quadrant = (uint16_t*) &(state->block[i]);
state->budget = state->nblock * ((wfact-1) / 3);
MainSort(state);
if (state->budget >= 0)
goto good;
}
FallbackSort(state);
good:
#if BZ_LIGHT_DEBUG
origPtr = -1;
#endif
for (i = 0; i < state->nblock; i++) {
if (state->ptr[i] == 0) {
origPtr = i;
break;
}
}
ASSERTH(origPtr != -1, 1003);
return origPtr;
}

View File

@@ -0,0 +1,338 @@
/* ------------------------------------------------------------------
This file is part of bzip2/libbzip2, a program and library for
lossless, block-sorting data compression.
bzip2/libbzip2 version 1.0.4 of 20 December 2006
Copyright (C) 1996-2006 Julian Seward <jseward@bzip.org>
Please read the WARNING, DISCLAIMER and PATENTS sections in the
README file.
This program is released under the terms of the license contained
in the file LICENSE.
------------------------------------------------------------------ */
#include <xiuos.h>
#if defined(FS_VFS) && defined(TOOL_SHELL)
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "bzlib_private.h"
uint32_t BZ2_crc32Table[256] = {
0x00000000L, 0x04c11db7L, 0x09823b6eL, 0x0d4326d9L,
0x130476dcL, 0x17c56b6bL, 0x1a864db2L, 0x1e475005L,
0x2608edb8L, 0x22c9f00fL, 0x2f8ad6d6L, 0x2b4bcb61L,
0x350c9b64L, 0x31cd86d3L, 0x3c8ea00aL, 0x384fbdbdL,
0x4c11db70L, 0x48d0c6c7L, 0x4593e01eL, 0x4152fda9L,
0x5f15adacL, 0x5bd4b01bL, 0x569796c2L, 0x52568b75L,
0x6a1936c8L, 0x6ed82b7fL, 0x639b0da6L, 0x675a1011L,
0x791d4014L, 0x7ddc5da3L, 0x709f7b7aL, 0x745e66cdL,
0x9823b6e0L, 0x9ce2ab57L, 0x91a18d8eL, 0x95609039L,
0x8b27c03cL, 0x8fe6dd8bL, 0x82a5fb52L, 0x8664e6e5L,
0xbe2b5b58L, 0xbaea46efL, 0xb7a96036L, 0xb3687d81L,
0xad2f2d84L, 0xa9ee3033L, 0xa4ad16eaL, 0xa06c0b5dL,
0xd4326d90L, 0xd0f37027L, 0xddb056feL, 0xd9714b49L,
0xc7361b4cL, 0xc3f706fbL, 0xceb42022L, 0xca753d95L,
0xf23a8028L, 0xf6fb9d9fL, 0xfbb8bb46L, 0xff79a6f1L,
0xe13ef6f4L, 0xe5ffeb43L, 0xe8bccd9aL, 0xec7dd02dL,
0x34867077L, 0x30476dc0L, 0x3d044b19L, 0x39c556aeL,
0x278206abL, 0x23431b1cL, 0x2e003dc5L, 0x2ac12072L,
0x128e9dcfL, 0x164f8078L, 0x1b0ca6a1L, 0x1fcdbb16L,
0x018aeb13L, 0x054bf6a4L, 0x0808d07dL, 0x0cc9cdcaL,
0x7897ab07L, 0x7c56b6b0L, 0x71159069L, 0x75d48ddeL,
0x6b93dddbL, 0x6f52c06cL, 0x6211e6b5L, 0x66d0fb02L,
0x5e9f46bfL, 0x5a5e5b08L, 0x571d7dd1L, 0x53dc6066L,
0x4d9b3063L, 0x495a2dd4L, 0x44190b0dL, 0x40d816baL,
0xaca5c697L, 0xa864db20L, 0xa527fdf9L, 0xa1e6e04eL,
0xbfa1b04bL, 0xbb60adfcL, 0xb6238b25L, 0xb2e29692L,
0x8aad2b2fL, 0x8e6c3698L, 0x832f1041L, 0x87ee0df6L,
0x99a95df3L, 0x9d684044L, 0x902b669dL, 0x94ea7b2aL,
0xe0b41de7L, 0xe4750050L, 0xe9362689L, 0xedf73b3eL,
0xf3b06b3bL, 0xf771768cL, 0xfa325055L, 0xfef34de2L,
0xc6bcf05fL, 0xc27dede8L, 0xcf3ecb31L, 0xcbffd686L,
0xd5b88683L, 0xd1799b34L, 0xdc3abdedL, 0xd8fba05aL,
0x690ce0eeL, 0x6dcdfd59L, 0x608edb80L, 0x644fc637L,
0x7a089632L, 0x7ec98b85L, 0x738aad5cL, 0x774bb0ebL,
0x4f040d56L, 0x4bc510e1L, 0x46863638L, 0x42472b8fL,
0x5c007b8aL, 0x58c1663dL, 0x558240e4L, 0x51435d53L,
0x251d3b9eL, 0x21dc2629L, 0x2c9f00f0L, 0x285e1d47L,
0x36194d42L, 0x32d850f5L, 0x3f9b762cL, 0x3b5a6b9bL,
0x0315d626L, 0x07d4cb91L, 0x0a97ed48L, 0x0e56f0ffL,
0x1011a0faL, 0x14d0bd4dL, 0x19939b94L, 0x1d528623L,
0xf12f560eL, 0xf5ee4bb9L, 0xf8ad6d60L, 0xfc6c70d7L,
0xe22b20d2L, 0xe6ea3d65L, 0xeba91bbcL, 0xef68060bL,
0xd727bbb6L, 0xd3e6a601L, 0xdea580d8L, 0xda649d6fL,
0xc423cd6aL, 0xc0e2d0ddL, 0xcda1f604L, 0xc960ebb3L,
0xbd3e8d7eL, 0xb9ff90c9L, 0xb4bcb610L, 0xb07daba7L,
0xae3afba2L, 0xaafbe615L, 0xa7b8c0ccL, 0xa379dd7bL,
0x9b3660c6L, 0x9ff77d71L, 0x92b45ba8L, 0x9675461fL,
0x8832161aL, 0x8cf30badL, 0x81b02d74L, 0x857130c3L,
0x5d8a9099L, 0x594b8d2eL, 0x5408abf7L, 0x50c9b640L,
0x4e8ee645L, 0x4a4ffbf2L, 0x470cdd2bL, 0x43cdc09cL,
0x7b827d21L, 0x7f436096L, 0x7200464fL, 0x76c15bf8L,
0x68860bfdL, 0x6c47164aL, 0x61043093L, 0x65c52d24L,
0x119b4be9L, 0x155a565eL, 0x18197087L, 0x1cd86d30L,
0x029f3d35L, 0x065e2082L, 0x0b1d065bL, 0x0fdc1becL,
0x3793a651L, 0x3352bbe6L, 0x3e119d3fL, 0x3ad08088L,
0x2497d08dL, 0x2056cd3aL, 0x2d15ebe3L, 0x29d4f654L,
0xc5a92679L, 0xc1683bceL, 0xcc2b1d17L, 0xc8ea00a0L,
0xd6ad50a5L, 0xd26c4d12L, 0xdf2f6bcbL, 0xdbee767cL,
0xe3a1cbc1L, 0xe760d676L, 0xea23f0afL, 0xeee2ed18L,
0xf0a5bd1dL, 0xf464a0aaL, 0xf9278673L, 0xfde69bc4L,
0x89b8fd09L, 0x8d79e0beL, 0x803ac667L, 0x84fbdbd0L,
0x9abc8bd5L, 0x9e7d9662L, 0x933eb0bbL, 0x97ffad0cL,
0xafb010b1L, 0xab710d06L, 0xa6322bdfL, 0xa2f33668L,
0xbcb4666dL, 0xb8757bdaL, 0xb5365d03L, 0xb1f740b4L
};
#if BZ_LIGHT_DEBUG
static
void BzAssertFail(int errcode)
{
bb_error_msg_and_die("internal error %d", errcode);
}
#endif
static
void PrepareNewBlock(EState* s)
{
int i;
s->nblock = 0;
BZ_INITIALISE_CRC(s->blockCRC);
for (i = 0; i < 256; i++)
s->inUse[i] = 0;
s->blockNo++;
}
static void InitRL(EState* s)
{
s->state_in_ch = 256;
s->state_in_len = 0;
}
static int IsEmptyRL(EState* s)
{
return (s->state_in_ch >= 256 || s->state_in_len <= 0);
}
void BZ2BzCompressInit(BzStream *strm, int blockSize100k)
{
unsigned n;
EState* s;
s = malloc(sizeof(EState));
memset(s, 0, sizeof(EState));
s->strm = strm;
n = 100000 * blockSize100k;
s->arr1 = malloc(n * sizeof(uint32_t));
s->mtfv = (uint16_t*)s->arr1;
s->ptr = (uint32_t*)s->arr1;
s->arr2 = malloc((n + BZ_N_OVERSHOOT) * sizeof(uint32_t));
s->block = (uint8_t*)s->arr2;
s->ftab = malloc(65537 * sizeof(uint32_t));
s->state = BZ_S_INPUT;
s->mode = BZ_M_RUNNING;
s->blockSize100k = blockSize100k;
s->nblockMAX = n - 19;
strm->state = s;
strm->total_out = 0;
InitRL(s);
PrepareNewBlock(s);
}
static void AddPairToBlock(EState* s)
{
int32_t i;
uint8_t ch = (uint8_t)(s->state_in_ch);
for (i = 0; i < s->state_in_len; i++) {
BZ_UPDATE_CRC(s->blockCRC, ch);
}
s->inUse[s->state_in_ch] = 1;
switch (s->state_in_len) {
case 3:
s->block[s->nblock] = (uint8_t)ch; s->nblock++;
case 2:
s->block[s->nblock] = (uint8_t)ch; s->nblock++;
case 1:
s->block[s->nblock] = (uint8_t)ch; s->nblock++;
break;
default:
s->inUse[s->state_in_len - 4] = 1;
s->block[s->nblock] = (uint8_t)ch; s->nblock++;
s->block[s->nblock] = (uint8_t)ch; s->nblock++;
s->block[s->nblock] = (uint8_t)ch; s->nblock++;
s->block[s->nblock] = (uint8_t)ch; s->nblock++;
s->block[s->nblock] = (uint8_t)(s->state_in_len - 4);
s->nblock++;
break;
}
}
static void FlushRL(EState* s)
{
if (s->state_in_ch < 256) AddPairToBlock(s);
InitRL(s);
}
#define ADD_CHAR_TO_BLOCK(zs, zchh0) { \
uint32_t zchh = (uint32_t)(zchh0); \
if (zchh != zs->state_in_ch && zs->state_in_len == 1) { \
uint8_t ch = (uint8_t)(zs->state_in_ch); \
BZ_UPDATE_CRC(zs->blockCRC, ch); \
zs->inUse[zs->state_in_ch] = 1; \
zs->block[zs->nblock] = (uint8_t)ch; \
zs->nblock++; \
zs->state_in_ch = zchh; \
} else \
if (zchh != zs->state_in_ch || zs->state_in_len == 255) { \
if (zs->state_in_ch < 256) \
AddPairToBlock(zs); \
zs->state_in_ch = zchh; \
zs->state_in_len = 1; \
} else { \
zs->state_in_len++; \
} \
}
static void CopyInputUntilStop(EState* s)
{
#ifdef SAME_CODE_AS_BELOW
if (s->mode == BZ_M_RUNNING) {
while (1) {
if (s->strm->avail_in == 0) break;
if (s->nblock >= s->nblockMAX) break;
ADD_CHAR_TO_BLOCK(s, (uint32_t)(*(uint8_t*)(s->strm->next_in)));
s->strm->next_in++;
s->strm->avail_in--;
}
} else
#endif
{
while (1) {
if (s->strm->avail_in == 0) break;
if (s->nblock >= s->nblockMAX) break;
ADD_CHAR_TO_BLOCK(s, *(uint8_t*)(s->strm->next_in));
s->strm->next_in++;
s->strm->avail_in--;
}
}
}
static void CopyOutputUntilStop(EState* s)
{
while (1) {
if (s->strm->avail_out == 0) break;
if (s->state_out_pos >= s->posZ) break;
*(s->strm->next_out) = *s->state_out_pos++;
s->strm->avail_out--;
s->strm->next_out++;
s->strm->total_out++;
}
}
static void HandleCompress(BzStream *strm)
{
EState* s = strm->state;
while (1) {
if (s->state == BZ_S_OUTPUT) {
CopyOutputUntilStop(s);
if (s->state_out_pos < s->posZ) break;
if (s->mode == BZ_M_FINISHING
&& s->strm->avail_in == 0
&& IsEmptyRL(s))
break;
PrepareNewBlock(s);
s->state = BZ_S_INPUT;
#ifdef FLUSH_IS_UNUSED
if (s->mode == BZ_M_FLUSHING
&& s->avail_in_expect == 0
&& IsEmptyRL(s))
break;
#endif
}
if (s->state == BZ_S_INPUT) {
CopyInputUntilStop(s);
if (s->mode != BZ_M_RUNNING && s->strm->avail_in == 0) {
FlushRL(s);
BZ2CompressBlock(s, (s->mode == BZ_M_FINISHING));
s->state = BZ_S_OUTPUT;
} else
if (s->nblock >= s->nblockMAX) {
BZ2CompressBlock(s, 0);
s->state = BZ_S_OUTPUT;
} else
if (s->strm->avail_in == 0) {
break;
}
}
}
}
int BZ2BzCompress(BzStream *strm, int action)
{
EState* s;
s = strm->state;
switch (s->mode) {
case BZ_M_RUNNING:
if (action == BZ_RUN) {
HandleCompress(strm);
return BZ_RUN_OK;
}
#ifdef FLUSH_IS_UNUSED
else
if (action == BZ_FLUSH) {
s->mode = BZ_M_FLUSHING;
goto case_BZ_M_FLUSHING;
}
#endif
else{
s->mode = BZ_M_FINISHING;
goto case_BZ_M_FINISHING;
}
#ifdef FLUSH_IS_UNUSED
case_BZ_M_FLUSHING:
case BZ_M_FLUSHING:
HandleCompress(strm);
if (s->avail_in_expect > 0 || !IsEmptyRL(s) || s->state_out_pos < s->posZ)
return BZ_FLUSH_OK;
s->mode = BZ_M_RUNNING;
return BZ_RUN_OK;
#endif
case_BZ_M_FINISHING:
default:
HandleCompress(strm);
if (s->strm->avail_in > 0 || !IsEmptyRL(s) || s->state_out_pos < s->posZ)
return BZ_FINISH_OK;
return BZ_STREAM_END;
}
}
void BZ2BzCompressEnd(BzStream *strm)
{
EState* s;
s = strm->state;
free(s->arr1);
free(s->arr2);
free(s->ftab);
free(s);
}
#endif

View File

@@ -0,0 +1,47 @@
/* ------------------------------------------------------------------
This file is part of bzip2/libbzip2, a program and library for
lossless, block-sorting data compression.
bzip2/libbzip2 version 1.0.4 of 20 December 2006
Copyright (C) 1996-2006 Julian Seward <jseward@bzip.org>
Please read the WARNING, DISCLAIMER and PATENTS sections in the
README file.
This program is released under the terms of the license contained
in the file LICENSE.
------------------------------------------------------------------ */
#define BZ_RUN 0
#define BZ_FLUSH 1
#define BZ_FINISH 2
#define BZ_OK 0
#define BZ_RUN_OK 1
#define BZ_FLUSH_OK 2
#define BZ_FINISH_OK 3
#define BZ_STREAM_END 4
#define BZ_SEQUENCE_ERROR (-1)
#define BZ_PARAM_ERROR (-2)
#define BZ_MEM_ERROR (-3)
#define BZ_DATA_ERROR (-4)
#define BZ_DATA_ERROR_MAGIC (-5)
#define BZ_IO_ERROR (-6)
#define BZ_UNEXPECTED_EOF (-7)
#define BZ_OUTBUFF_FULL (-8)
#define BZ_CONFIG_ERROR (-9)
typedef struct BzStream {
void *state;
char *next_in;
char *next_out;
unsigned avail_in;
unsigned avail_out;
unsigned long long total_out;
} BzStream;
void BZ2BzCompressInit(BzStream *strm, int blockSize100k);
int BZ2BzCompress(BzStream *strm, int action);
void BZ2BzCompressEnd(BzStream *strm);

View File

@@ -0,0 +1,165 @@
/* ------------------------------------------------------------------
This file is part of bzip2/libbzip2, a program and library for
lossless, block-sorting data compression.
bzip2/libbzip2 version 1.0.4 of 20 December 2006
Copyright (C) 1996-2006 Julian Seward <jseward@bzip.org>
Please read the WARNING, DISCLAIMER and PATENTS sections in the
README file.
This program is released under the terms of the license contained
in the file LICENSE.
------------------------------------------------------------------ */
#include <stdint.h>
#include "bzlib.h"
typedef unsigned char Bool;
#define TRUE ((Bool)1)
#define FALSE ((Bool)0)
#if BZ_LIGHT_DEBUG
static void BzAssertFail(int errcode) NORETURN;
#define ASSERTH(cond, errcode) do { \
if (!(cond)) \
BzAssertFail(errcode); \
} while (0)
#else
#define ASSERTH(cond, msg) do { } while (0)
#endif
#if BZ_DEBUG
#define ASSERTD(cond, msg) do { \
if (!(cond)) \
bb_error_msg_and_die("(debug build): internal error %s", msg); \
} while (0)
#else
#define ASSERTD(cond, msg) do { } while (0)
#endif
#define BZ_HDR_B 0x42
#define BZ_HDR_Z 0x5a
#define BZ_HDR_H 0x68
#define BZ_HDR_0 0x30
#define BZ_HDR_BZH0 0x425a6830
#define BZ_MAX_ALPHA_SIZE 258
#define BZ_MAX_CODE_LEN 23
#define BZ_RUNA 0
#define BZ_RUNB 1
#define BZ_N_GROUPS 6
#define BZ_G_SIZE 50
#define BZ_N_ITERS 4
#define BZ_MAX_SELECTORS (2 + (900000 / BZ_G_SIZE))
extern uint32_t BZ2_crc32Table[256];
#define BZ_INITIALISE_CRC(crcVar) { \
crcVar = 0xffffffffL; \
}
#define BZ_FINALISE_CRC(crcVar) { \
crcVar = ~(crcVar); \
}
#define BZ_UPDATE_CRC(crcVar,cha) { \
crcVar = (crcVar << 8) ^ \
BZ2_crc32Table[(crcVar >> 24) ^ \
((uint8_t)cha)]; \
}
#define BZ_M_IDLE 1
#define BZ_M_RUNNING 2
#define BZ_M_FLUSHING 3
#define BZ_M_FINISHING 4
#define BZ_S_OUTPUT 1
#define BZ_S_INPUT 2
#define BZ_N_RADIX 2
#define BZ_N_QSORT 12
#define BZ_N_SHELL 18
#define BZ_N_OVERSHOOT (BZ_N_RADIX + BZ_N_QSORT + BZ_N_SHELL + 2)
typedef struct EState {
BzStream *strm;
uint8_t mode;
uint8_t state;
uint8_t blockSize100k;
uint32_t *arr1;
uint32_t *arr2;
uint32_t *ftab;
uint16_t *quadrant;
int32_t budget;
uint32_t *ptr;
uint8_t *block;
uint16_t *mtfv;
uint8_t *zbits;
uint32_t state_in_ch;
int32_t state_in_len;
int32_t nblock;
int32_t nblockMAX;
uint8_t *posZ;
uint8_t *state_out_pos;
uint32_t bsBuff;
int32_t bsLive;
uint32_t blockCRC;
uint32_t combinedCRC;
int32_t blockNo;
int32_t nMTF;
int32_t nInUse;
Bool inUse[256] __attribute__((__aligned__(sizeof(long))));
uint8_t unseqToSeq[256];
int32_t mtfFreq [BZ_MAX_ALPHA_SIZE];
uint8_t selector [BZ_MAX_SELECTORS];
uint8_t selectorMtf[BZ_MAX_SELECTORS];
uint8_t len[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
int32_t sendMTFValues__code [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
int32_t sendMTFValues__rfreq[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
#if BZIP2_SPEED >= 5
uint32_t sendMTFValues__len_pack[BZ_MAX_ALPHA_SIZE][4];
#endif
int32_t BZ2_hbMakeCodeLengths__heap [BZ_MAX_ALPHA_SIZE + 2];
int32_t BZ2_hbMakeCodeLengths__weight[BZ_MAX_ALPHA_SIZE * 2];
int32_t BZ2_hbMakeCodeLengths__parent[BZ_MAX_ALPHA_SIZE * 2];
int32_t mainSort__copyStart[256];
int32_t mainSort__copyEnd[256];
} EState;
int32_t BZ2BlockSort(EState*);
void BZ2CompressBlock(EState*, int);
void BZ2BsInitWrite(EState*);
void BZ2HbAssignCodes(int32_t*, uint8_t*, int32_t, int32_t, int32_t);
void BZ2HbMakeCodeLengths(EState*, uint8_t*, int32_t*, int32_t, int32_t);

View File

@@ -0,0 +1,577 @@
/* ------------------------------------------------------------------
This file is part of bzip2/libbzip2, a program and library for
lossless, block-sorting data compression.
bzip2/libbzip2 version 1.0.4 of 20 December 2006
Copyright (C) 1996-2006 Julian Seward <jseward@bzip.org>
Please read the WARNING, DISCLAIMER and PATENTS sections in the
README file.
This program is released under the terms of the license contained
in the file LICENSE.
------------------------------------------------------------------ */
#include <xiuos.h>
#if defined(FS_VFS) && defined(TOOL_SHELL)
#include <stdint.h>
#include "bzlib_private.h"
#if BZIP2_SPEED >= 5
# define ALWAYS_INLINE_5 ALWAYS_INLINE
#else
# define ALWAYS_INLINE_5
#endif
void BZ2BsInitWrite(EState* s)
{
s->bsLive = 0;
s->bsBuff = 0;
}
static void BsFinishWrite(EState* s)
{
while (s->bsLive > 0) {
*s->posZ++ = (uint8_t)(s->bsBuff >> 24);
s->bsBuff <<= 8;
s->bsLive -= 8;
}
}
static ALWAYS_INLINE_5
void bsW(EState* s, int32_t n, uint32_t v)
{
while (s->bsLive >= 8) {
*s->posZ++ = (uint8_t)(s->bsBuff >> 24);
s->bsBuff <<= 8;
s->bsLive -= 8;
}
s->bsBuff |= (v << (32 - s->bsLive - n));
s->bsLive += n;
}
static
ALWAYS_INLINE_5
void bsW16(EState* s, uint32_t v)
{
while (s->bsLive >= 8) {
*s->posZ++ = (uint8_t)(s->bsBuff >> 24);
s->bsBuff <<= 8;
s->bsLive -= 8;
}
s->bsBuff |= (v << (16 - s->bsLive));
s->bsLive += 16;
}
static inline void bsW1_1(EState* s)
{
if (s->bsLive >= 8) {
*s->posZ++ = (uint8_t)(s->bsBuff >> 24);
s->bsBuff <<= 8;
s->bsLive -= 8;
}
s->bsBuff |= (1 << (31 - s->bsLive));
s->bsLive += 1;
}
static
ALWAYS_INLINE_5
void bsW1_0(EState* s)
{
if (s->bsLive >= 8) {
*s->posZ++ = (uint8_t)(s->bsBuff >> 24);
s->bsBuff <<= 8;
s->bsLive -= 8;
}
s->bsLive += 1;
}
static inline void bsPutU16(EState* s, unsigned u)
{
bsW16(s, u);
}
static
void bsPutU32(EState* s, unsigned u)
{
bsW16(s, (u >> 16) & 0xffff);
bsW16(s, u & 0xffff);
}
static
void MakeMapsE(EState* s)
{
int i;
unsigned cnt = 0;
for (i = 0; i < 256; i++) {
if (s->inUse[i]) {
s->unseqToSeq[i] = cnt;
cnt++;
}
}
s->nInUse = cnt;
}
static
#if defined __i386__
NOINLINE
#endif
int InnerLoop(uint8_t *yy, uint8_t ll_i)
{
register uint8_t rtmp;
register uint8_t* ryy_j;
rtmp = yy[1];
yy[1] = yy[0];
ryy_j = &(yy[1]);
while (ll_i != rtmp) {
register uint8_t rtmp2;
ryy_j++;
rtmp2 = rtmp;
rtmp = *ryy_j;
*ryy_j = rtmp2;
}
yy[0] = rtmp;
return ryy_j - &(yy[0]);
}
static void GenerateMTFValues(EState* s)
{
uint8_t yy[256];
int i;
int zPend;
int32_t wr;
uint32_t* ptr = s->ptr;
MakeMapsE(s);
wr = 0;
zPend = 0;
for (i = 0; i <= s->nInUse+1; i++)
s->mtfFreq[i] = 0;
for (i = 0; i < s->nInUse; i++)
yy[i] = (uint8_t) i;
for (i = 0; i < s->nblock; i++) {
uint8_t ll_i = ll_i;
int32_t j;
ASSERTD(wr <= i, "generateMTFValues(1)");
j = ptr[i] - 1;
if (j < 0)
j += s->nblock;
ll_i = s->unseqToSeq[s->block[j]];
ASSERTD(ll_i < s->nInUse, "generateMTFValues(2a)");
if (yy[0] == ll_i) {
zPend++;
continue;
}
if (zPend > 0) {
process_zPend:
zPend--;
while (1) {
#if 0
if (zPend & 1) {
s->mtfv[wr] = BZ_RUNB; wr++;
s->mtfFreq[BZ_RUNB]++;
} else {
s->mtfv[wr] = BZ_RUNA; wr++;
s->mtfFreq[BZ_RUNA]++;
}
#else
unsigned run = zPend & 1;
s->mtfv[wr] = run;
wr++;
s->mtfFreq[run]++;
#endif
zPend -= 2;
if (zPend < 0)
break;
zPend = (unsigned)zPend / 2;
}
if (i < 0)
goto end;
zPend = 0;
}
j = InnerLoop(yy, ll_i);
s->mtfv[wr] = j+1;
wr++;
s->mtfFreq[j+1]++;
}
i = -1;
if (zPend > 0)
goto process_zPend;
end:
s->mtfv[wr] = s->nInUse+1;
wr++;
s->mtfFreq[s->nInUse+1]++;
s->nMTF = wr;
}
#define BZ_LESSER_ICOST 0
#define BZ_GREATER_ICOST 15
static void SendMTFValues(EState* s)
{
int32_t t, i;
unsigned iter;
unsigned gs;
int32_t alphaSize;
unsigned nSelectors, selCtr;
int32_t nGroups;
#define CODE sendMTFValues__code
#define RFREQ sendMTFValues__rfreq
#define LEN_PACK sendMTFValues__len_pack
unsigned cost[BZ_N_GROUPS];
uint16_t* mtfv = s->mtfv;
alphaSize = s->nInUse + 2;
for (t = 0; t < BZ_N_GROUPS; t++) {
unsigned v;
for (v = 0; v < alphaSize; v++)
s->len[t][v] = BZ_GREATER_ICOST;
}
ASSERTH(s->nMTF > 0, 3001);
nGroups = 2;
nGroups += (s->nMTF >= 200);
nGroups += (s->nMTF >= 600);
nGroups += (s->nMTF >= 1200);
nGroups += (s->nMTF >= 2400);
{
unsigned nPart, remF;
nPart = nGroups;
remF = s->nMTF;
gs = 0;
while (nPart > 0) {
unsigned v;
unsigned ge;
unsigned tFreq, aFreq;
tFreq = remF / nPart;
ge = gs;
aFreq = 0;
while (aFreq < tFreq && ge < alphaSize) {
aFreq += s->mtfFreq[ge++];
}
ge--;
if (ge > gs
&& nPart != nGroups && nPart != 1
&& ((nGroups - nPart) % 2 == 1)
) {
aFreq -= s->mtfFreq[ge];
ge--;
}
for (v = 0; v < alphaSize; v++)
if (v >= gs && v <= ge)
s->len[nPart-1][v] = BZ_LESSER_ICOST;
else
s->len[nPart-1][v] = BZ_GREATER_ICOST;
nPart--;
gs = ge + 1;
remF -= aFreq;
}
}
for (iter = 0; iter < BZ_N_ITERS; iter++) {
for (t = 0; t < nGroups; t++) {
unsigned v;
for (v = 0; v < alphaSize; v++)
s->RFREQ[t][v] = 0;
}
#if BZIP2_SPEED >= 5
if (nGroups == 6) {
unsigned v;
for (v = 0; v < alphaSize; v++) {
s->LEN_PACK[v][0] = (s->len[1][v] << 16) | s->len[0][v];
s->LEN_PACK[v][1] = (s->len[3][v] << 16) | s->len[2][v];
s->LEN_PACK[v][2] = (s->len[5][v] << 16) | s->len[4][v];
}
}
#endif
nSelectors = 0;
gs = 0;
while (1) {
unsigned ge;
unsigned bt, bc;
if (gs >= s->nMTF)
break;
ge = gs + BZ_G_SIZE - 1;
if (ge >= s->nMTF)
ge = s->nMTF-1;
for (t = 0; t < nGroups; t++)
cost[t] = 0;
#if BZIP2_SPEED >= 5
if (nGroups == 6 && 50 == ge-gs+1) {
register uint32_t cost01, cost23, cost45;
register uint16_t icv;
cost01 = cost23 = cost45 = 0;
#define BZ_ITER(nn) \
icv = mtfv[gs+(nn)]; \
cost01 += s->LEN_PACK[icv][0]; \
cost23 += s->LEN_PACK[icv][1]; \
cost45 += s->LEN_PACK[icv][2];
BZ_ITER(0); BZ_ITER(1); BZ_ITER(2); BZ_ITER(3); BZ_ITER(4);
BZ_ITER(5); BZ_ITER(6); BZ_ITER(7); BZ_ITER(8); BZ_ITER(9);
BZ_ITER(10); BZ_ITER(11); BZ_ITER(12); BZ_ITER(13); BZ_ITER(14);
BZ_ITER(15); BZ_ITER(16); BZ_ITER(17); BZ_ITER(18); BZ_ITER(19);
BZ_ITER(20); BZ_ITER(21); BZ_ITER(22); BZ_ITER(23); BZ_ITER(24);
BZ_ITER(25); BZ_ITER(26); BZ_ITER(27); BZ_ITER(28); BZ_ITER(29);
BZ_ITER(30); BZ_ITER(31); BZ_ITER(32); BZ_ITER(33); BZ_ITER(34);
BZ_ITER(35); BZ_ITER(36); BZ_ITER(37); BZ_ITER(38); BZ_ITER(39);
BZ_ITER(40); BZ_ITER(41); BZ_ITER(42); BZ_ITER(43); BZ_ITER(44);
BZ_ITER(45); BZ_ITER(46); BZ_ITER(47); BZ_ITER(48); BZ_ITER(49);
#undef BZ_ITER
cost[0] = cost01 & 0xffff; cost[1] = cost01 >> 16;
cost[2] = cost23 & 0xffff; cost[3] = cost23 >> 16;
cost[4] = cost45 & 0xffff; cost[5] = cost45 >> 16;
} else
#endif
{
for (i = gs; i <= ge; i++) {
unsigned icv = mtfv[i];
for (t = 0; t < nGroups; t++)
cost[t] += s->len[t][icv];
}
}
bc = cost[0];
bt = 0;
for (t = 1; t < nGroups; t++) {
if (cost[t] < bc) {
bc = cost[t];
bt = t;
}
}
s->selector[nSelectors] = bt;
nSelectors++;
#if BZIP2_SPEED >= 4
if (nGroups == 6 && 50 == ge-gs+1) {
#define BZ_ITUR(nn) s->RFREQ[bt][mtfv[gs + (nn)]]++
BZ_ITUR(0); BZ_ITUR(1); BZ_ITUR(2); BZ_ITUR(3); BZ_ITUR(4);
BZ_ITUR(5); BZ_ITUR(6); BZ_ITUR(7); BZ_ITUR(8); BZ_ITUR(9);
BZ_ITUR(10); BZ_ITUR(11); BZ_ITUR(12); BZ_ITUR(13); BZ_ITUR(14);
BZ_ITUR(15); BZ_ITUR(16); BZ_ITUR(17); BZ_ITUR(18); BZ_ITUR(19);
BZ_ITUR(20); BZ_ITUR(21); BZ_ITUR(22); BZ_ITUR(23); BZ_ITUR(24);
BZ_ITUR(25); BZ_ITUR(26); BZ_ITUR(27); BZ_ITUR(28); BZ_ITUR(29);
BZ_ITUR(30); BZ_ITUR(31); BZ_ITUR(32); BZ_ITUR(33); BZ_ITUR(34);
BZ_ITUR(35); BZ_ITUR(36); BZ_ITUR(37); BZ_ITUR(38); BZ_ITUR(39);
BZ_ITUR(40); BZ_ITUR(41); BZ_ITUR(42); BZ_ITUR(43); BZ_ITUR(44);
BZ_ITUR(45); BZ_ITUR(46); BZ_ITUR(47); BZ_ITUR(48); BZ_ITUR(49);
#undef BZ_ITUR
gs = ge + 1;
} else
#endif
{
while (gs <= ge) {
s->RFREQ[bt][mtfv[gs]]++;
gs++;
}
}
}
for (t = 0; t < nGroups; t++)
BZ2HbMakeCodeLengths(s, &(s->len[t][0]), &(s->RFREQ[t][0]), alphaSize, 17 );
}
ASSERTH(nGroups < 8, 3002);
ASSERTH(nSelectors < 32768 && nSelectors <= (2 + (900000 / BZ_G_SIZE)), 3003);
{
uint8_t pos[BZ_N_GROUPS], ll_i, tmp2, tmp;
for (i = 0; i < nGroups; i++)
pos[i] = i;
for (i = 0; i < nSelectors; i++) {
unsigned j;
ll_i = s->selector[i];
j = 0;
tmp = pos[j];
while (ll_i != tmp) {
j++;
tmp2 = tmp;
tmp = pos[j];
pos[j] = tmp2;
}
pos[0] = tmp;
s->selectorMtf[i] = j;
}
}
for (t = 0; t < nGroups; t++) {
unsigned minLen = 32;
unsigned maxLen = 0;
for (i = 0; i < alphaSize; i++) {
if (s->len[t][i] > maxLen) maxLen = s->len[t][i];
if (s->len[t][i] < minLen) minLen = s->len[t][i];
}
ASSERTH(!(maxLen > 17), 3004);
ASSERTH(!(minLen < 1), 3005);
BZ2HbAssignCodes(&(s->CODE[t][0]), &(s->len[t][0]), minLen, maxLen, alphaSize);
}
{
int inUse16 = 0;
for (i = 0; i < 16; i++) {
if (sizeof(long) <= 4) {
inUse16 = inUse16*2 +
((*(uint32_t*)&(s->inUse[i * 16 + 0])
| *(uint32_t*)&(s->inUse[i * 16 + 4])
| *(uint32_t*)&(s->inUse[i * 16 + 8])
| *(uint32_t*)&(s->inUse[i * 16 + 12])) != 0);
} else {
inUse16 = inUse16*2 +
((*(uint64_t*)&(s->inUse[i * 16 + 0])
| *(uint64_t*)&(s->inUse[i * 16 + 8])) != 0);
}
}
bsW16(s, inUse16);
inUse16 <<= (sizeof(int)*8 - 16);
for (i = 0; i < 16; i++) {
if (inUse16 < 0) {
unsigned v16 = 0;
unsigned j;
for (j = 0; j < 16; j++)
v16 = v16*2 + s->inUse[i * 16 + j];
bsW16(s, v16);
}
inUse16 <<= 1;
}
}
bsW(s, 3, nGroups);
bsW(s, 15, nSelectors);
for (i = 0; i < nSelectors; i++) {
unsigned j;
for (j = 0; j < s->selectorMtf[i]; j++)
bsW1_1(s);
bsW1_0(s);
}
for (t = 0; t < nGroups; t++) {
unsigned curr = s->len[t][0];
bsW(s, 5, curr);
for (i = 0; i < alphaSize; i++) {
while (curr < s->len[t][i]) { bsW(s, 2, 2); curr++; }
while (curr > s->len[t][i]) { bsW(s, 2, 3); curr--; }
bsW1_0(s);
}
}
selCtr = 0;
gs = 0;
while (1) {
unsigned ge;
if (gs >= s->nMTF)
break;
ge = gs + BZ_G_SIZE - 1;
if (ge >= s->nMTF)
ge = s->nMTF-1;
ASSERTH(s->selector[selCtr] < nGroups, 3006);
#if 0
if (nGroups == 6 && 50 == ge-gs+1) {
uint16_t mtfv_i;
uint8_t* s_len_sel_selCtr = &(s->len[s->selector[selCtr]][0]);
int32_t* s_code_sel_selCtr = &(s->CODE[s->selector[selCtr]][0]);
#define BZ_ITAH(nn) \
mtfv_i = mtfv[gs+(nn)]; \
bsW(s, s_len_sel_selCtr[mtfv_i], s_code_sel_selCtr[mtfv_i])
BZ_ITAH(0); BZ_ITAH(1); BZ_ITAH(2); BZ_ITAH(3); BZ_ITAH(4);
BZ_ITAH(5); BZ_ITAH(6); BZ_ITAH(7); BZ_ITAH(8); BZ_ITAH(9);
BZ_ITAH(10); BZ_ITAH(11); BZ_ITAH(12); BZ_ITAH(13); BZ_ITAH(14);
BZ_ITAH(15); BZ_ITAH(16); BZ_ITAH(17); BZ_ITAH(18); BZ_ITAH(19);
BZ_ITAH(20); BZ_ITAH(21); BZ_ITAH(22); BZ_ITAH(23); BZ_ITAH(24);
BZ_ITAH(25); BZ_ITAH(26); BZ_ITAH(27); BZ_ITAH(28); BZ_ITAH(29);
BZ_ITAH(30); BZ_ITAH(31); BZ_ITAH(32); BZ_ITAH(33); BZ_ITAH(34);
BZ_ITAH(35); BZ_ITAH(36); BZ_ITAH(37); BZ_ITAH(38); BZ_ITAH(39);
BZ_ITAH(40); BZ_ITAH(41); BZ_ITAH(42); BZ_ITAH(43); BZ_ITAH(44);
BZ_ITAH(45); BZ_ITAH(46); BZ_ITAH(47); BZ_ITAH(48); BZ_ITAH(49);
#undef BZ_ITAH
gs = ge+1;
} else
#endif
{
uint8_t* s_len_sel_selCtr = &(s->len [s->selector[selCtr]][0]);
int32_t* s_code_sel_selCtr = &(s->CODE[s->selector[selCtr]][0]);
while (gs <= ge) {
bsW(s,
s_len_sel_selCtr[mtfv[gs]],
s_code_sel_selCtr[mtfv[gs]]
);
gs++;
}
}
selCtr++;
}
ASSERTH(selCtr == nSelectors, 3007);
#undef CODE
#undef RFREQ
#undef LEN_PACK
}
void BZ2CompressBlock(EState* s, int is_last_block)
{
int32_t origPtr = origPtr;
if (s->nblock > 0) {
BZ_FINALISE_CRC(s->blockCRC);
s->combinedCRC = (s->combinedCRC << 1) | (s->combinedCRC >> 31);
s->combinedCRC ^= s->blockCRC;
if (s->blockNo > 1)
s->posZ = s->zbits;
origPtr = BZ2BlockSort(s);
}
s->zbits = &((uint8_t*)s->arr2)[s->nblock];
s->posZ = s->zbits;
s->state_out_pos = s->zbits;
if (s->blockNo == 1) {
BZ2BsInitWrite(s);
bsPutU32(s, BZ_HDR_BZH0 + s->blockSize100k);
}
if (s->nblock > 0) {
bsPutU32(s, 0x31415926);
bsPutU16(s, 0x5359);
bsPutU32(s, s->blockCRC);
bsW1_0(s);
bsW(s, 24, origPtr);
GenerateMTFValues(s);
SendMTFValues(s);
}
if (is_last_block) {
bsPutU32(s, 0x17724538);
bsPutU16(s, 0x5090);
bsPutU32(s, s->combinedCRC);
BsFinishWrite(s);
}
}
#endif

View File

@@ -0,0 +1,179 @@
/* ------------------------------------------------------------------
This file is part of bzip2/libbzip2, a program and library for
lossless, block-sorting data compression.
bzip2/libbzip2 version 1.0.4 of 20 December 2006
Copyright (C) 1996-2006 Julian Seward <jseward@bzip.org>
Please read the WARNING, DISCLAIMER and PATENTS sections in the
README file.
This program is released under the terms of the license contained
in the file LICENSE.
------------------------------------------------------------------ */
#include <xiuos.h>
#if defined(FS_VFS) && defined(TOOL_SHELL)
#include "bzlib_private.h"
#define WEIGHTOF(zz0) ((zz0) & 0xffffff00)
#define DEPTHOF(zz1) ((zz1) & 0x000000ff)
#define MYMAX(zz2,zz3) ((zz2) > (zz3) ? (zz2) : (zz3))
#define ADDWEIGHTS(zw1,zw2) \
(WEIGHTOF(zw1)+WEIGHTOF(zw2)) | \
(1 + MYMAX(DEPTHOF(zw1),DEPTHOF(zw2)))
#define UPHEAP(z) { \
int32_t zz, tmp; \
zz = z; \
tmp = HEAP[zz]; \
while (WEIGHT[tmp] < WEIGHT[HEAP[zz >> 1]]) { \
HEAP[zz] = HEAP[zz >> 1]; \
zz >>= 1; \
} \
HEAP[zz] = tmp; \
}
#if BZIP2_SPEED >= 1
#define DOWNHEAP1(heap, weight, Heap) { \
int32_t zz, yy, tmp; \
zz = 1; \
tmp = heap[zz]; \
while (1) { \
yy = zz << 1; \
if (yy > nHeap) \
break; \
if (yy < nHeap \
&& weight[heap[yy+1]] < weight[heap[yy]]) \
yy++; \
if (weight[tmp] < weight[heap[yy]]) \
break; \
heap[zz] = heap[yy]; \
zz = yy; \
} \
heap[zz] = tmp; \
}
#else
static void DOWNHEAP1(int32_t *heap, int32_t *weight, int32_t nHeap)
{
int32_t zz, yy, tmp;
zz = 1;
tmp = heap[zz];
while (1) {
yy = zz << 1;
if (yy > nHeap)
break;
if (yy < nHeap
&& weight[heap[yy + 1]] < weight[heap[yy]])
yy++;
if (weight[tmp] < weight[heap[yy]])
break;
heap[zz] = heap[yy];
zz = yy;
}
heap[zz] = tmp;
}
#endif
void BZ2HbMakeCodeLengths(EState *s,
uint8_t *len,
int32_t *freq,
int32_t alphaSize,
int32_t maxLen)
{
int32_t nNodes, nHeap, n1, n2, i, j, k;
Bool tooLong;
#define HEAP (s->BZ2_hbMakeCodeLengths__heap)
#define WEIGHT (s->BZ2_hbMakeCodeLengths__weight)
#define PARENT (s->BZ2_hbMakeCodeLengths__parent)
for (i = 0; i < alphaSize; i++)
WEIGHT[i+1] = (freq[i] == 0 ? 1 : freq[i]) << 8;
while (1) {
nNodes = alphaSize;
nHeap = 0;
HEAP[0] = 0;
WEIGHT[0] = 0;
PARENT[0] = -2;
for (i = 1; i <= alphaSize; i++) {
PARENT[i] = -1;
nHeap++;
HEAP[nHeap] = i;
UPHEAP(nHeap);
}
ASSERTH(nHeap < (BZ_MAX_ALPHA_SIZE+2), 2001);
while (nHeap > 1) {
n1 = HEAP[1]; HEAP[1] = HEAP[nHeap]; nHeap--; DOWNHEAP1(HEAP, WEIGHT, nHeap);
n2 = HEAP[1]; HEAP[1] = HEAP[nHeap]; nHeap--; DOWNHEAP1(HEAP, WEIGHT, nHeap);
nNodes++;
PARENT[n1] = PARENT[n2] = nNodes;
WEIGHT[nNodes] = ADDWEIGHTS(WEIGHT[n1], WEIGHT[n2]);
PARENT[nNodes] = -1;
nHeap++;
HEAP[nHeap] = nNodes;
UPHEAP(nHeap);
}
ASSERTH(nNodes < (BZ_MAX_ALPHA_SIZE * 2), 2002);
tooLong = FALSE;
for (i = 1; i <= alphaSize; i++) {
j = 0;
k = i;
while (PARENT[k] >= 0) {
k = PARENT[k];
j++;
}
len[i-1] = j;
if (j > maxLen)
tooLong = TRUE;
}
if (!tooLong)
break;
for (i = 1; i <= alphaSize; i++) {
j = WEIGHT[i] >> 8;
j = 1 + (j / 2);
WEIGHT[i] = j << 8;
}
}
#undef HEAP
#undef WEIGHT
#undef PARENT
}
void BZ2HbAssignCodes(int32_t *code,
uint8_t *length,
int32_t minLen,
int32_t maxLen,
int32_t alphaSize)
{
int32_t n, vec, i;
vec = 0;
for (n = minLen; n <= maxLen; n++) {
for (i = 0; i < alphaSize; i++) {
if (length[i] == n) {
code[i] = vec;
vec++;
}
}
vec <<= 1;
}
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#ifndef __INC_GUNZIP_H__
#define __INC_GUNZIP_H__
typedef struct GzipHdr {
uint8_t gz_method;
uint8_t flags;
uint32_t mtime;
uint8_t extra_flags;
uint8_t os_flags;
} __attribute__((packed)) GzipHdr_t;
typedef struct huft {
unsigned char e;
unsigned char b;
union {
uint16_t n;
struct huft *t;
};
} huft_t;
#define GUNZIP_WSIZE (1 << 15)
#define GUNZIP_BYTEBUFFER_MAX (1 << 14)
#define BMAX 16
#define NMAX 288
enum methods {
STORED = 1,
CODES,
};
int InflateUnzip(int zip_fd, int dst_fd, uint32_t cmpsize,
uint32_t ucmpsize, uint32_t crc32);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,90 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#ifndef __INC_GZIP_H__
#define __INC_GZIP_H__
#include <stdint.h>
#define WSIZE (1 << 15)
#define OUTBUF_SIZE (1 << 14)
#define WMASK (WSIZE - 1)
#define LIT_BUFSIZE WSIZE
#define DIST_BUFSIZE LIT_BUFSIZE
#define MIN_MATCH 3
#define MAX_MATCH 258
#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1)
#define MAX_CHAIN_LEN 4096
#define MAX_LAZY_MATCH MAX_MATCH
#define MAX_DIST (WSIZE - MIN_LOOKAHEAD)
#define HASH_BITS 15
#define HASH_SIZE (1 << HASH_BITS)
#define HASH_MASK (HASH_SIZE - 1)
#define HASH_SHIFT ((HASH_BITS + MIN_MATCH - 1) / MIN_MATCH)
#define MAX_BITS 15
#define MAX_BL_BITS 7
#define LENGTH_CODES 29
#define LITERALS 256
#define END_BLOCK 256
#define L_CODES (LITERALS + 1 + LENGTH_CODES)
#define D_CODES 30
#define BL_CODES 19
#define STORED_BLOCK 0
#define STATIC_TREES 1
#define DYN_TREES 2
typedef struct CtDate
{
union {
uint16_t freq;
uint16_t code;
};
union {
uint16_t father;
uint16_t len;
};
} CtDate_t;
typedef struct TreeDesc {
CtDate_t *dyn_tree;
CtDate_t *static_tree;
const uint8_t *extra_bits;
int extra_base;
int elems;
int max_length;
int max_code;
} TreeDesc_t;
#define HEAP_SIZE (2 * L_CODES + 1)
#define REP_3_6 16
#define REPZ_3_10 17
#define REPZ_11_138 18
#endif

View File

@@ -0,0 +1,601 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include <xiuos.h>
#if defined(TOOL_SHELL) && defined(FS_VFS)
#include "shell.h"
#include <stdio.h>
#include <string.h>
#include <iot-vfs_posix.h>
#include "utility.h"
extern char working_dir[];
void ls(const char *path)
{
DIR *dir;
struct dirent *dirent;
struct stat statbuf;
if (path == NULL) {
path = strdup(working_dir);
if (path == NULL)
return;
} else {
path = (char *)path;
}
if ((dir = opendir(path)) == NULL) {
KPrintf("Failed to open directory %s\n", path);
return;
}
KPrintf("Directory: %s\n", path);
while ((dirent = readdir(dir)) != NULL) {
stat(dirent->d_name, &statbuf);
KPrintf("%-20s", dirent->d_name);
if (S_ISREG(statbuf.st_mode))
KPrintf("%-25lu\n", (unsigned long)statbuf.st_size);
else
KPrintf("%-25s\n", "<DIR>");
}
closedir(dir);
}
int cmd_ls(int argc, char **argv)
{
if (argc == 1)
ls(working_dir);
else
ls(argv[1]);
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)|SHELL_CMD_DISABLE_RETURN,
ls,cmd_ls, List information about the FILES .);
static int CopyRecursive(const char *from, const char *to, char *buf,
size_t buf_size)
{
struct stat statbuf;
int ret;
if (strcmp(from, to) == 0)
return 0;
ret = stat(from, &statbuf);
if (ret < 0) {
KPrintf("Failed to read %s\n", from);
return -1;
}
if (S_ISREG(statbuf.st_mode)) {
int fd_from, fd_to;
int size_read;
int total_size_written = 0;
fd_from = open(from, O_RDONLY);
if (fd_from < 0) {
KPrintf("Failed to open %s\n", from);
return -1;
}
fd_to = open(to, O_WRONLY);
if (fd_to < 0) {
KPrintf("Failed to open %s\n", to);
close(fd_from);
return -1;
}
while ((size_read = read(fd_from, buf, buf_size)) > 0)
total_size_written += write(fd_to, buf, size_read);
close(fd_from);
close(fd_to);
if (total_size_written != statbuf.st_size) {
KPrintf("Error copying %s to %s\n", from, to);
return -1;
}
return 0;
}
DIR *dirp;
struct dirent *dirent;
char *sub_from, *sub_to;
ret = mkdir(to, 0777);
if (ret < 0) {
KPrintf("Failed to create directory %s\n", to);
return -1;
}
dirp = opendir(from);
if (dirp == NULL) {
KPrintf("Failed to open directory %s\n", from);
return -1;
}
ret = 0;
while ((dirent = readdir(dirp)) != NULL) {
sub_from = malloc(strlen(from) + strlen(dirent->d_name) + 2);
sub_to = malloc(strlen(to) + strlen(dirent->d_name) + 2);
if (sub_from == NULL || sub_to == NULL) {
KPrintf("Out of memory\n");
ret = -1;
goto err;
}
sprintf(sub_from, "%s/%s", from, dirent->d_name);
sprintf(sub_to, "%s/%s", to, dirent->d_name);
if (CopyRecursive(sub_from, sub_to, buf, buf_size) < 0) {
ret = -1;
goto err;
}
free(sub_from);
free(sub_to);
}
err:
closedir(dirp);
free(sub_from);
free(sub_to);
return ret;
}
static int copy(const char *from, const char *to)
{
struct stat statbuf;
char buf[128];
char *abs_from, *abs_to;
int abs_from_len, abs_to_len;
char *last_name;
int last_name_len;
char *GetAbsolutePath(const char *parent, const char *filename);
abs_from = GetAbsolutePath(NULL, from);
abs_to = GetAbsolutePath(NULL, to);
if (abs_from == NULL || abs_to == NULL)
goto err;
abs_from_len = strlen(abs_from);
abs_to_len = strlen(abs_to);
last_name = abs_from + abs_from_len - 1;
while (*last_name != '/')
last_name--;
last_name_len = abs_from + abs_from_len - last_name;
if (stat(abs_to, &statbuf) == 0) {
if (S_ISDIR(statbuf.st_mode)) {
if (strcmp(abs_to, "/") == 0) {
last_name++;
last_name_len--;
}
abs_to = realloc(abs_to, abs_to_len + last_name_len + 1);
if (abs_to == NULL)
goto err;
strcat(abs_to, last_name);
} else {
unlink(abs_to);
}
}
return CopyRecursive(abs_from, abs_to, buf, sizeof(buf)) < 0;
err:
free(abs_from);
free(abs_to);
return -1;
}
int cmd_cp(int argc, char *argv[])
{
if (argc != 3) {
KPrintf("Usage: cp SOURCE DEST\n");
KPrintf("Copy SOURCE to DEST\n");
return 0;
}
copy(argv[1], argv[2]);
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)|SHELL_CMD_DISABLE_RETURN,
cp,cmd_cp, Copy source to dest.);
static void RmRecursive(char *file_name, int recursive)
{
struct stat statbuf;
if (stat(file_name, &statbuf) < 0)
return;
if (recursive && S_ISDIR(statbuf.st_mode)) {
DIR *dir;
struct dirent *dirent;
dir = opendir(file_name);
while ((dirent = readdir(dir)) != NULL) {
char *sub_file_name = malloc(strlen(file_name) +
strlen(dirent->d_name) + 2);
if (sub_file_name == NULL) {
KPrintf("Memory not enough\n");
return;
}
sprintf(sub_file_name, "%s/%s", file_name, dirent->d_name);
RmRecursive(sub_file_name, recursive);
free(sub_file_name);
}
closedir(dir);
}
unlink(file_name);
}
int cmd_mv(int argc, char *argv[])
{
if (argc != 3) {
KPrintf("Usage: mv SOURCE DEST\n");
KPrintf("Move SOURCE to DESn");
return 0;
}
if (rename(argv[1], argv[2]) != 0)
if (copy(argv[1], argv[2]) == 0)
RmRecursive(argv[1], 1);
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)|SHELL_CMD_DISABLE_RETURN,
mv,cmd_mv, Move frome source to dest.);
void cat(const char *filename)
{
int size;
char buf[128];
int fd;
if ((fd = open(filename, O_RDONLY)) < 0) {
KPrintf("Failed to open file %s\n", filename);
return;
}
while ((size = read(fd, buf, 128)) > 0)
for (int i = 0; i < size; i++)
putchar(buf[i]);
close(fd);
}
int cmd_cat(int argc, char **argv)
{
int index;
extern void cat(const char *filename);
if (argc == 1)
{
KPrintf("Usage: cat [FILE]...\n");
KPrintf("Concatenate FILE(s)\n");
return 0;
}
for (index = 1; index < argc; index ++)
{
cat(argv[index]);
}
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)|SHELL_CMD_DISABLE_RETURN,
cat,cmd_cat,Concatenate FILE(s).);
int cmd_rm(int argc, char **argv)
{
int recursive = 0;
if (argc == 1) {
KPrintf("Usage: rm FILE...\n");
KPrintf("Remove (unlink) the FILE(s).\n");
KPrintf("Suppported option flags:\n");
KPrintf(" r recursively remove folders\n");
return 0;
}
if (argv[1][0] == '-') {
if (strcmp(argv[1], "-r") != 0)
KPrintf("Unknown options\n");
recursive = 1;
argc--;
argv++;
}
for (int i = 1; i < argc; i++)
RmRecursive(argv[i], recursive);
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)|SHELL_CMD_DISABLE_RETURN,
rm,cmd_rm,Remove (unlink) the File(s).);
#ifdef VFS_USING_WORKDIR
int cmd_cd(int argc, char **argv)
{
if (argc == 1)
{
KPrintf("%s\n", working_dir);
}
else if (argc == 2)
{
if (chdir(argv[1]) != 0)
{
KPrintf("No such directory: %s\n", argv[1]);
}
}
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)|SHELL_CMD_DISABLE_RETURN,
cd,cmd_cd, Chage the shell wroking directory.);
int cmd_pwd(int argc, char **argv)
{
KPrintf("%s\n", working_dir);
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)|SHELL_CMD_DISABLE_RETURN,
pwd,cmd_pwd, print the name of the current working directory.);
#endif
int cmd_mkdir(int argc, char **argv)
{
if (argc == 1)
{
KPrintf("Usage: mkdir [OPTION] DIRECTORY\n");
KPrintf("Create the DIRECTORY, if they do not already exist.\n");
}
else
{
mkdir(argv[1], 0);
}
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)|SHELL_CMD_DISABLE_RETURN,
mkdir,cmd_mkdir, Create a directory.);
int cmd_df(int argc, char **argv)
{
struct statfs buf;
char *path = argc < 2 ? "/" : argv[1];
static char *unit[] = {"B", "KB", "MB", "GB"};
uint64_t integer, decimal = 0;
int i;
if (statfs(path, &buf) < 0) {
KPrintf("statfs failed: %s\n", path);
return -1;
}
integer = (uint64_t)buf.f_bsize * buf.f_bfree;
for (i = 0; i < 4; i++) {
if (integer < 1024)
break;
decimal = (integer % 1024) * 10 / 1024;
integer /= 1024;
}
if (i >= 4)
i = 3;
KPrintf("Free disk space: %d.%d %s "
"[ %d blocks, %d free blocks, %d bytes per block ]\n",
(int)integer, (int)decimal, unit[i], buf.f_blocks, buf.f_bfree,
buf.f_bsize);
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)|SHELL_CMD_DISABLE_RETURN,
df,cmd_df,disk free);
int cmd_echo(int argc, char** argv)
{
if (argc == 2)
{
KPrintf("%s\n", argv[1]);
}
else if (argc == 3)
{
int fd;
fd = open(argv[2], O_RDWR | O_APPEND | O_CREAT, 0);
if (fd >= 0)
{
write (fd, argv[1], strlen(argv[1]));
close(fd);
}
else
{
KPrintf("open file:%s failed!\n", argv[2]);
}
}
else
{
KPrintf("Usage: echo \"string\" [filename]\n");
}
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)|SHELL_CMD_DISABLE_RETURN,
echo,cmd_echo,echo string to file.);
static void FindRecursive(char *name, char *path)
{
struct stat statbuf;
DIR *dir = opendir(path);
struct dirent *dirent;
while ((dirent = readdir(dir)) != NULL) {
char *sub_path = malloc(strlen(path) +
strlen(dirent->d_name) + 2);
if (sub_path == NULL) {
KPrintf("Memory not enough\n");
return;
}
sprintf(sub_path, "%s/%s", path, dirent->d_name);
if (stat(sub_path, &statbuf) < 0) {
KPrintf("Failed to access %s\n", sub_path);
free(sub_path);
continue;
}
if (strstr(dirent->d_name, name) != NULL)
KPrintf("%s\n", sub_path);
if (S_ISDIR(statbuf.st_mode))
FindRecursive(name, sub_path);
free(sub_path);
}
}
static void FindPrintUsage()
{
KPrintf("Usage: find NAME PATH\n");
}
int cmd_find(int argc, char **argv)
{
struct stat statbuf;
if (argc != 3) {
FindPrintUsage();
return 0;
}
TruncateExtension(argv[2], "/");
if (strcmp(argv[2], "/") == 0)
argv[2][0] = '\0';
if (stat(argv[2], &statbuf) < 0 || !S_ISDIR(statbuf.st_mode)) {
KPrintf("No such directory: %s\n", argv[2]);
return 0;
}
if (strstr(argv[1], "/") != NULL) {
KPrintf("Invalid file name: %s\n", argv[1]);
return 0;
}
FindRecursive(argv[1], argv[2]);
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)|SHELL_CMD_DISABLE_RETURN,
find,cmd_find,search file with given name in specified path.);
int cmd_tar(int argc, char **argv)
{
extern int tar(int argc, char **argv);
tar(argc, argv);
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)|SHELL_CMD_DISABLE_RETURN,
tar,cmd_tar,create or extarct tar archive.);
int cmd_gzip(int argc, char **argv)
{
extern int gzip(int argc, char **argv);
gzip(argc, argv);
return 0;
}
SHELL_EXPORT_CMD(
SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)|SHELL_CMD_DISABLE_RETURN,
gzip,cmd_gzip, creat or extart gzip compressed files);
int cmd_gunzip(int argc, char **argv)
{
extern int gunzip(int argc, char **argv);
gunzip(argc, argv);
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)|SHELL_CMD_DISABLE_RETURN,
gunzip,cmd_gunzip,decompress gzip files.);
int cmd_unzip(int argc, char **argv)
{
extern int unzip(int argc, char **argv);
unzip(argc, argv);
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)|SHELL_CMD_DISABLE_RETURN,
unzip,cmd_unzip, decompress zip files.);
int cmd_bzip2(int argc, char **argv)
{
extern int bzip2(int argc, char **argv);
bzip2(argc, argv);
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)|SHELL_CMD_DISABLE_RETURN,
bzip2,cmd_bzip2,create or extract bzip2 compressed files.);
int cmd_bunzip2(int argc, char **argv)
{
extern int bunzip2(int argc, char **argv);
bunzip2(argc, argv);
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)|SHELL_CMD_DISABLE_RETURN,
bunzip2,cmd_bunzip2,decompress bzip2 files.);
#endif

View File

@@ -0,0 +1,29 @@
/**
* @file shell_fs.c
* @author Letter (nevermindzzt@gmail.com)
* @brief shell file system support
* @version 0.1
* @date 2020-07-22
*
* @copyright (c) 2020 Letter
*
*/
#include "shell_fs.h"
#include "shell.h"
#include "stdio.h"
/**
* @brief init shell filesystem-suport component
*
* @param shellFs filesystem shell object
* @param pathBuffer path
* @param pathLen length of path
*/
void shellFsInit(ShellFs *shellFs, char *pathBuffer, size_t pathLen)
{
shellFs->info.path = pathBuffer;
shellFs->info.pathLen = pathLen;
shellFs->getcwd(shellFs->info.path, pathLen);
}

View File

@@ -0,0 +1,38 @@
/**
* @file shell_fs.h
* @author Letter (nevermindzzt@gmail.com)
* @brief shell file system support
* @version 0.1
* @date 2020-07-22
*
* @copyright (c) 2020 Letter
*
*/
#ifndef __SHELL_FS_H__
#define __SHELL_FS_H__
#include "stddef.h"
#include "shell.h"
#define SHELL_FS_VERSION "1.0.0"
#define SHELL_COMPANION_ID_FS -1
#define SHELL_FS_LIST_FILE_BUFFER_MAX 4096
typedef struct shell_fs
{
char* (*getcwd)(char *, size_t);
int (*chdir)(const char *);
size_t (*listdir)(char *dir, char *buffer, size_t maxLen);
struct {
char *path;
size_t pathLen;
} info;
} ShellFs;
void shellFsInit(ShellFs *shellFs, char *pathBuffer, size_t pathLen);
#endif

View File

@@ -0,0 +1,467 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include <xiuos.h>
#if defined(FS_VFS) && defined(TOOL_SHELL)
#include <iot-vfs_posix.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <ctype.h>
#include "tar.h"
#include "utility.h"
char *bytebuf;
static void PrintOctal(char *str, int len, uint64_t value)
{
char buf[32];
char *cp;
int written_len;
written_len = sprintf(buf, "%0*llo", len, value);
cp = buf + written_len - len;
if (*cp == '0')
cp++;
memcpy(str, cp, len);
}
static uint64_t ScanOctal(char *str, int len)
{
uint64_t ret = 0;
for (int i = 0; i < len; i++) {
if (!isdigit(str[i]))
break;
if (str[i] > '7')
break;
ret = ret * 8 + str[i] - '0';
}
return ret;
}
static void TarChecksumHeader(TarHdr_t *hdr)
{
int chksum;
memcpy(hdr->magic, TAR_MAGIC_STR, 6);
memcpy(hdr->version, "00", 2);
memset(hdr->chksum, ' ', sizeof(hdr->chksum));
chksum = 0;
for (int i = 0; i < sizeof(TarHdr_t); i++)
chksum += ((unsigned char *)hdr)[i];
PrintOctal(hdr->chksum, sizeof(hdr->chksum), chksum);
}
static int TarWriteHeader(int tar_fd, struct stat *tar_statbuf,
char *file_name, char *hdr_file_name, struct stat *statbuf)
{
TarHdr_t hdr;
int written_len;
memset(&hdr, 0, sizeof(TarHdr_t));
strncpy(hdr.name, hdr_file_name, sizeof(hdr.name));
PrintOctal(hdr.mode, sizeof(hdr.mode), statbuf->st_mode & 07777);
PrintOctal(hdr.uid, sizeof(hdr.uid), 1);
PrintOctal(hdr.gid, sizeof(hdr.gid), 1);
PrintOctal(hdr.mtime, sizeof(hdr.mtime),
statbuf->st_mtime >= 0 ? statbuf->st_mtime : 0);
strcpy(hdr.uname, "rtthread");
strcpy(hdr.gname, "rtthread");
if (S_ISDIR(statbuf->st_mode)) {
hdr.typeflag = TYPE_DIR;
if (strlen(hdr.name) < sizeof(hdr.name) - 1)
hdr.name[strlen(hdr.name)] = '/';
} else if (S_ISREG(statbuf->st_mode)) {
hdr.typeflag = TYPE_REG;
uint64_t size = statbuf->st_size;
if (size <= 0777777777777)
PrintOctal(hdr.size, sizeof(hdr.size), size);
else {
return -1;
}
} else {
return -1;
}
TarChecksumHeader(&hdr);
written_len = write(tar_fd, &hdr, sizeof(TarHdr_t));
if (written_len != sizeof(TarHdr_t))
return -1;
return 0;
}
static int TarWriteFileRecursive(int tar_fd,
struct stat *tar_statbuf, char *file_name, int verbose)
{
char *hdr_file_name;
struct stat statbuf;
hdr_file_name = RemoveUnsafePrefix(file_name);
if (hdr_file_name [0] == '\0')
return 0;
stat(file_name, &statbuf);
if (TarWriteHeader(tar_fd, tar_statbuf, file_name,
hdr_file_name, &statbuf) < 0)
return -1;
if (verbose)
KPrintf("%s\n", file_name);
if (S_ISREG(statbuf.st_mode)) {
int fd;
size_t written_size = 0, copied_size;
fd = open(file_name, O_RDONLY);
if (fd < 0)
return -1;
while ((copied_size = read(fd, bytebuf, TAR_BLOCK_SIZE)) > 0) {
if (write(tar_fd, bytebuf, copied_size) != copied_size) {
copied_size = -1;
break;
}
written_size += copied_size;
}
if (copied_size < 0 || written_size != statbuf.st_size) {
close(fd);
return -1;
}
copied_size = TAR_BLOCK_SIZE - (written_size % TAR_BLOCK_SIZE);
copied_size %= TAR_BLOCK_SIZE;
memset(bytebuf, 0, copied_size);
if (write(tar_fd, bytebuf, copied_size) != copied_size) {
close(fd);
return -1;
}
close(fd);
} else {
DIR *dir;
struct dirent *dirent;
dir = opendir(file_name);
if (dir == NULL)
return -1;
while ((dirent = readdir(dir)) != NULL) {
char *sub_file_name;
int ret;
sub_file_name = malloc(strlen(file_name) +
strlen(dirent->d_name) + 2);
if (sub_file_name == NULL)
return -1;
sprintf(sub_file_name, "%s/%s", file_name, dirent->d_name);
ret = TarWriteFileRecursive(tar_fd, tar_statbuf, sub_file_name, verbose);
free(sub_file_name);
if (ret < 0) {
closedir(dir);
return -1;
}
}
closedir(dir);
}
return 0;
}
static int TarCreate(char *tar_name, int npaths, char **paths, int verbose)
{
int tar_fd, written_size;
struct stat tar_statbuf;
if (npaths == 0)
return 0;
tar_fd = open(tar_name, O_WRONLY | O_CREAT | O_TRUNC);
if (tar_fd < 0)
return -1;
fstat(tar_fd, &tar_statbuf);
for (int i = 0; i < npaths; i++) {
int len = strlen(paths[i]);
if (len > 1 && paths[i][len - 1] == '/')
paths[len - 1] = '\0';
if (TarWriteFileRecursive(tar_fd, &tar_statbuf, paths[i], verbose) < 0) {
close(tar_fd);
return -1;
}
}
memset(bytebuf, 0, TAR_BLOCK_SIZE);
written_size = 0;
for (int i = 0; i < 2; i++)
written_size += write(tar_fd, bytebuf, TAR_BLOCK_SIZE);
close(tar_fd);
return written_size == 2 * TAR_BLOCK_SIZE ? 0 : -1;
}
enum {
RET_SUCC = 0,
RET_EMPTY_HDR,
RET_EOF,
};
static int TarParseHeader(int tar_fd, int verbose)
{
int ReadSize;
TarHdr_t hdr;
ReadSize = read(tar_fd, bytebuf, TAR_BLOCK_SIZE);
if (ReadSize == 0)
return RET_EOF;
if (ReadSize != TAR_BLOCK_SIZE)
return -1;
memcpy(&hdr, bytebuf, TAR_BLOCK_SIZE);
if (hdr.name[0] == '\0')
return RET_EMPTY_HDR;
if (!IsPrefixedWith(hdr.magic, TAR_MAGIC_STR))
return -1;
int old_chksum = ScanOctal(hdr.chksum, sizeof(hdr.chksum));
int correct_chksum = 0;
memset(hdr.chksum, ' ', sizeof(hdr.chksum));
for (int i = 0; i < sizeof(TarHdr_t); i++)
correct_chksum += ((unsigned char *)&hdr)[i];
if (old_chksum != correct_chksum)
return -1;
if (hdr.typeflag != TYPE_REG && hdr.typeflag != TYPE_DIR)
return -1;
char *file_name = RemoveUnsafePrefix(hdr.name);
if (verbose)
KPrintf("%s\n", file_name);
if (hdr.typeflag == TYPE_DIR) {
if (mkdir(file_name, 0777) < 0)
return -1;
return RET_SUCC;
}
int size_to_write = ScanOctal(hdr.size, sizeof(hdr.size));
int written_size;
int fd = open(file_name, O_WRONLY | O_CREAT | O_TRUNC);
if (fd < 0)
return -1;
while (size_to_write > 0) {
ReadSize = read(tar_fd, bytebuf, TAR_BLOCK_SIZE);
if (ReadSize != TAR_BLOCK_SIZE) {
close(fd);
return -1;
}
written_size = write(fd, bytebuf, MIN(size_to_write, TAR_BLOCK_SIZE));
if (written_size != MIN(size_to_write, TAR_BLOCK_SIZE)) {
close(fd);
return -1;
}
size_to_write -= TAR_BLOCK_SIZE;
}
close(fd);
return RET_SUCC;
}
static int TarExtract(char *tar_name, int verbose)
{
int tar_fd, ret, empty_hdrs = 0;
struct stat tar_statbuf;
if (stat(tar_name, &tar_statbuf) < 0)
return -1;
if (tar_statbuf.st_size % TAR_BLOCK_SIZE != 0)
return -1;
tar_fd = open(tar_name, O_RDONLY);
if (tar_fd < 0)
return -1;
while ((ret = TarParseHeader(tar_fd, verbose)) >= 0) {
if (ret == RET_EOF) {
ret = 0;
break;
}
if (ret == RET_EMPTY_HDR) {
empty_hdrs++;
if (empty_hdrs >= 2) {
ret = 0;
break;
}
}
else
empty_hdrs = 0;
}
close(tar_fd);
return ret;
}
void TarTruncateCmpExtension(char *file_name, int filter)
{
switch (filter) {
case GZIP:
TruncateExtension(file_name, ".gz");
break;
case BZIP2:
TruncateExtension(file_name, ".bz2");
break;
}
}
extern int GzipCompress(char *file_name);
extern int GzipDecompress(char *file_name);
extern int Bzip2Compress(char *file_name);
extern int Bzip2Decompress(char *file_name);
static void TarPrintUsage()
{
KPrintf("Usage: tar [OPTIONS]... [FILES]...\n");
KPrintf("Supported option flags:\n");
KPrintf(" c create a new tarball\n");
KPrintf(" x extract files from an existing tarball\n");
KPrintf(" f specify name of the tarball\n");
KPrintf(" v show verbose status\n");
KPrintf(" z filter the tarball through gzip\n");
KPrintf(" j filter the tarball through bzip2\n");
}
int tar(int argc, char **argv)
{
int flag_create = 0, flag_extract = 0, flag_file = 0, verbose = 0;
int filter = 0;
int ret = 0;
char *tar_name;
if (argc < 2 || argv[1][0] != '-') {
TarPrintUsage();
return 0;
}
for (int i = 1; i < strlen(argv[1]); i++)
switch(argv[1][i]) {
case 'c':
flag_create = 1;
break;
case 'x':
flag_extract = 1;
break;
case 'f':
flag_file = 1;
break;
case 'z':
if (filter != 0) {
KPrintf("Bad options\n");
return 0;
}
filter = GZIP;
break;
case 'j':
if (filter != 0) {
KPrintf("Bad options\n");
return 0;
}
filter = BZIP2;
break;
case 'v':
verbose = 1;
break;
default:
KPrintf("Unknown option: %c\n", argv[1][i]);
return 0;
}
if (flag_create == flag_extract || flag_file == 0 || argc < 3) {
KPrintf("Bad options\n");
TarPrintUsage();
return 0;
}
bytebuf = malloc(TAR_BLOCK_SIZE);
tar_name = argv[2];
if (flag_create) {
TarTruncateCmpExtension(tar_name, filter);
ret = TarCreate(tar_name, argc - 3, &argv[3], verbose);
if (ret == 0) {
switch (filter) {
case GZIP:
ret = GzipCompress(tar_name);
break;
case BZIP2:
ret = Bzip2Compress(tar_name);
break;
}
}
} else if (flag_extract) {
if (argc > 3) {
KPrintf("Too many arguments\n");
ret = -1;
} else {
switch (filter) {
case GZIP:
ret = GzipDecompress(tar_name);
break;
case BZIP2:
ret = Bzip2Decompress(tar_name);
}
TarTruncateCmpExtension(tar_name, filter);
if (ret == 0) {
ret = TarExtract(tar_name, verbose);
}
}
}
if (ret < 0)
KPrintf("Operation failed\n");
free(bytebuf);
return 0;
}
#endif

View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#ifndef __INC_TAR_H__
#define __INC_TAR_H__
#define TAR_BLOCK_SIZE 512
#define TAR_FILE_NAME_LEN 100
#define TAR_MAGIC_STR "ustar"
#define ROUNDUP(a, align) (((a) + (align) - 1) & ~((align) - 1))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
typedef struct TarHdr {
char name[TAR_FILE_NAME_LEN];
char mode[8];
char uid[8];
char gid[8];
char size[12];
char mtime[12];
char chksum[8];
char typeflag;
char linkname[TAR_FILE_NAME_LEN];
char magic[6];
char version[2];
char uname[32];
char gname[32];
char devmajor[8];
char devminor[8];
char prefix[155];
char padding[12];
} TarHdr_t;
enum FileType {
TYPE_REG = '0',
TYPE_LNK = '1',
TYPE_SYM = '2',
TYPE_CHR = '3',
TYPE_BLK = '4',
TYPE_DIR = '5',
TYPE_FIFO = '6',
};
enum FilterType {
GZIP = 1,
BZIP2,
};
#endif

View File

@@ -0,0 +1,283 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include <xiuos.h>
#if defined(FS_VFS) && defined(TOOL_SHELL)
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <iot-vfs_posix.h>
#include <unzip.h>
#include <gunzip.h>
#include "utility.h"
#include <string.h>
int zip_fd;
static void ReadZipHdr(ZipHdr_t *zip_hdr)
{
zip_hdr->version = read16Le(zip_fd);
zip_hdr->zip_flags = read16Le(zip_fd);
zip_hdr->method = read16Le(zip_fd);
zip_hdr->modtime = read16Le(zip_fd);
zip_hdr->moddate = read16Le(zip_fd);
zip_hdr->crc32 = read32Le(zip_fd);
zip_hdr->cmpsize = read32Le(zip_fd);
zip_hdr->ucmpsize = read32Le(zip_fd);
zip_hdr->filename_len = read16Le(zip_fd);
zip_hdr->extra_len = read16Le(zip_fd);
}
static void ReadCdfHdr(CdfHdr_t *cdf_hdr)
{
cdf_hdr->version_made_by = read16Le(zip_fd);
cdf_hdr->version_needed = read16Le(zip_fd);
cdf_hdr->cdf_flags = read16Le(zip_fd);
cdf_hdr->method = read16Le(zip_fd);
cdf_hdr->modtime = read16Le(zip_fd);
cdf_hdr->moddate = read16Le(zip_fd);
cdf_hdr->crc32 = read32Le(zip_fd);
cdf_hdr->cmpsize = read32Le(zip_fd);
cdf_hdr->ucmpsize = read32Le(zip_fd);
cdf_hdr->filename_len = read16Le(zip_fd);
cdf_hdr->extra_len = read16Le(zip_fd);
cdf_hdr->file_comment_len = read16Le(zip_fd);
cdf_hdr->disk_number_start = read16Le(zip_fd);
cdf_hdr->internal_attributes = read16Le(zip_fd);
cdf_hdr->external_attributes = read32Le(zip_fd);
cdf_hdr->local_header_offset = read32Le(zip_fd);
}
static uint32_t FindCdfOffset()
{
cde_t cde;
unsigned char *buf;
unsigned char *p;
size_t ReadSize;
off_t end;
uint32_t found = (uint32_t)-1;
end = lseek(zip_fd, 0, SEEK_END);
if (end == -1) {
return (uint32_t)-1;
}
buf = malloc(FIND_CDF_BUF_SIZE);
end = MAX(0, end - FIND_CDF_BUF_SIZE);
lseek(zip_fd, end, SEEK_SET);
ReadSize = read(zip_fd, buf, FIND_CDF_BUF_SIZE);
p = buf;
while (p <= buf + ReadSize - sizeof(cde_t) - 4) {
if (*p != 'P') {
p++;
continue;
}
if (*(++p) != 'K')
continue;
if (*(++p) != 5)
continue;
if (*(++p) != 6)
continue;
memcpy(&cde, p + 1, sizeof(cde_t));
char *tmp = (char *)&cde.cdf_offset;
uint32_t cdf_offset = 0;
for (int i = 0; i < 4; i++)
cdf_offset |= (uint32_t)tmp[i] << (i * 8);
if (cdf_offset < end + (p - buf))
found = cdf_offset;
}
free(buf);
return found;
}
static uint32_t ReadNextCdf(uint32_t cdf_offset, CdfHdr_t *cdf_hdr)
{
uint32_t magic;
if (cdf_offset == (uint32_t)-1)
return (uint32_t)-1;
lseek(zip_fd, cdf_offset, SEEK_SET);
magic = read32Le(zip_fd);
if (magic == ZIP_CDE_MAGIC)
return 0;
ReadCdfHdr(cdf_hdr);
cdf_offset += 4 + sizeof(CdfHdr_t) +
cdf_hdr->filename_len +
cdf_hdr->extra_len +
cdf_hdr->file_comment_len;
return cdf_offset;
}
static int CreateLeadingDir(char *path) {
int len = strlen(path);
char tmp;
struct stat statbuf;
for (int i = 1; i < len; i++)
if (path[i] == '/') {
tmp = path[i];
path[i] = '\0';
if (stat(path, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) {
path[i] = tmp;
continue;
}
if (mkdir(path, 0777) < 0) {
path[i] = tmp;
return -1;
}
path[i] = tmp;
}
return 0;
}
static int ExtractUncompressedFile(int in_fd, int out_fd, uint32_t size)
{
uint32_t size_read = 0;
uint32_t size_written = 0;
char *buf = malloc(512);
if (buf == NULL)
return -1;
while (size > 0) {
size_read = read(in_fd, buf, MIN(size, 512));
size_written = write(out_fd, buf, size_read);
if (size_read != size_written) {
free(buf);
return -1;
}
size -= size_written;
}
free(buf);
return 0;
}
static int ExtractFile(ZipHdr_t *zip_hdr, int dst_fd)
{
switch (zip_hdr->method) {
case 0:
return ExtractUncompressedFile(zip_fd,
dst_fd, zip_hdr->cmpsize);
case 8:
return InflateUnzip(zip_fd, dst_fd, zip_hdr->cmpsize,
zip_hdr->ucmpsize, zip_hdr->crc32);
default:
return -1;
}
}
static int UnzipFile(char *path)
{
int ret = 0;
uint32_t cdf_offset;
char *filename_buf = NULL;
if ((zip_fd = open(path, O_RDONLY)) < 0)
return -1;
cdf_offset = FindCdfOffset();
if (cdf_offset == (uint32_t)-1) {
ret = -1;
}
while (1) {
if (cdf_offset == (uint32_t)-1)
break;
CdfHdr_t cdf_hdr;
ZipHdr_t zip_hdr;
cdf_offset = ReadNextCdf(cdf_offset, &cdf_hdr);
if (cdf_offset == 0)
break;
lseek(zip_fd, cdf_hdr.local_header_offset + 4, SEEK_SET);
ReadZipHdr(&zip_hdr);
if (zip_hdr.zip_flags & 0x8 || zip_hdr.zip_flags & 0x1) {
ret = -1;
break;
}
if (filename_buf)
free(filename_buf);
filename_buf = malloc(zip_hdr.filename_len + 1);
if (filename_buf == NULL) {
ret = -1;
break;
}
read(zip_fd, filename_buf, zip_hdr.filename_len);
filename_buf[zip_hdr.filename_len] = '\0';
lseek(zip_fd, zip_hdr.extra_len, SEEK_CUR);
if (filename_buf[zip_hdr.filename_len - 1] == '/') {
KPrintf(" creating: %s\n", filename_buf);
if (CreateLeadingDir(filename_buf) < 0) {
ret = -1;
break;
}
lseek(zip_fd, zip_hdr.cmpsize, SEEK_SET);
} else {
if (CreateLeadingDir(filename_buf) < 0) {
ret = -1;
break;
}
int dst_fd = open(filename_buf, O_WRONLY | O_CREAT | O_TRUNC);
if (dst_fd < 0) {
ret = -1;
break;
}
KPrintf(" inflating: %s\n", filename_buf);
ExtractFile(&zip_hdr, dst_fd);
close(dst_fd);
}
}
if (filename_buf)
free(filename_buf);
return ret;
}
static void UnzipPrintUsage()
{
KPrintf("Usage: unzip [FILES]...\n");
}
int unzip(int argc, char **argv)
{
if (argc < 2) {
UnzipPrintUsage();
return 0;
}
for (int i = 1; i < argc; i++) {
if (!IsSuffixedWith(argv[i], ".zip")) {
KPrintf("Unvalid extension: %s\n", argv[i]);
continue;
}
KPrintf("Decompressing zip file: %s\n", argv[i]);
if (UnzipFile(argv[i]) < 0)
KPrintf("Unable to extract zip file: %s\n", argv[i]);
}
return 0;
}
#endif

View File

@@ -0,0 +1,70 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#ifndef __INC_UNZIP_H__
#define __INC_UNZIP_H__
#include <stdint.h>
typedef struct cde {
uint16_t this_disk_no;
uint16_t disk_with_cdf_no;
uint16_t cdf_entries_on_this_disk;
uint16_t cdf_entries_total;
uint32_t cdf_size;
uint32_t cdf_offset;
} cde_t;
char BUILD_BUG_CDE_SIZE[sizeof(cde_t) == 16 ? 0 : -1];
typedef struct ZipHdr {
uint16_t version;
uint16_t zip_flags;
uint16_t method;
uint16_t modtime;
uint16_t moddate;
uint32_t crc32 __attribute__ ((__packed__));
uint32_t cmpsize __attribute__ ((__packed__));
uint32_t ucmpsize __attribute__ ((__packed__));
uint16_t filename_len;
uint16_t extra_len;
} __attribute__ ((__packed__)) ZipHdr_t;
char BUILD_BUG_ZIP_HDR_SIZE[sizeof(ZipHdr_t) == 26 ? 0 : -1];
typedef struct CdfHdr {
uint16_t version_made_by;
uint16_t version_needed;
uint16_t cdf_flags;
uint16_t method;
uint16_t modtime;
uint16_t moddate;
uint32_t crc32 __attribute__ ((__packed__));
uint32_t cmpsize __attribute__ ((__packed__));
uint32_t ucmpsize __attribute__ ((__packed__));
uint16_t filename_len;
uint16_t extra_len;
uint16_t file_comment_len;
uint16_t disk_number_start;
uint16_t internal_attributes;
uint32_t external_attributes __attribute__ ((__packed__));
uint32_t local_header_offset
__attribute__ ((__packed__));
} __attribute__ ((__packed__)) CdfHdr_t;
char BUILD_BUG_CDF_HDR_SIZE[sizeof(CdfHdr_t) == 42 ? 0 : -1];
#define FIND_CDF_BUF_SIZE 1024
#define ZIP_FILEHEADER_MAGIC 0x04034b50
#define ZIP_CDF_MAGIC 0x02014b50
#define ZIP_CDE_MAGIC 0x06054b50
#define ZIP_DD_MAGIC 0x08074b50
#endif

View File

@@ -0,0 +1,121 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include <xiuos.h>
#ifdef FS_VFS
#include <string.h>
#include <stdlib.h>
#include <iot-vfs_posix.h>
#include "utility.h"
int IsPrefixedWith(char *str, char *prefix)
{
while (*prefix != '\0') {
if (*str != *prefix)
return 0;
str++;
prefix++;
}
return 1;
}
char *RemoveUnsafePrefix(char *file_name)
{
char *ret = file_name;
while (1) {
if (*ret == '/') {
ret++;
continue;
}
if (IsPrefixedWith(ret, "/../" + 1)) {
ret += 3;
continue;
}
char *p = strstr(ret, "/../");
if (!p)
break;
ret = p + 4;
}
return ret;
}
int IsSuffixedWith(char *file_name, char *suffix)
{
int len = strlen(file_name);
int suff_len = strlen(suffix);
return len > suff_len &&
strcmp(&file_name[len - suff_len], suffix) == 0;
}
int TruncateExtension(char *file_name, char *ext)
{
int len = strlen(file_name);
int ext_len = strlen(ext);
if (!IsSuffixedWith(file_name, ext))
return -1;
file_name[len - ext_len] = '\0';
return 0;
}
unsigned char read8(int fd)
{
unsigned char ret;
read(fd, &ret, 1);
return ret;
}
uint16_t read16Le(int fd)
{
uint16_t ret = 0;
unsigned char buf[2];
read(fd, buf, 2);
for (int i = 0; i < 2; i++)
ret |= (uint16_t)buf[i] << (i * 8);
return ret;
}
uint32_t read32Le(int fd)
{
uint32_t ret = 0;
unsigned char buf[4];
read(fd, buf, 4);
for (int i = 0; i < 4; i++)
ret |= (uint32_t)buf[i] << (i * 8);
return ret;
}
uint64_t read64Le(int fd)
{
uint64_t ret = 0;
unsigned char buf[8];
read(fd, buf, 8);
for (int i = 0; i < 8; i++)
ret |= (uint32_t)buf[i] << (i * 8);
return ret;
}
#endif

View File

@@ -0,0 +1,36 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#ifndef __INC_UTILITY_H__
#define __INC_UTILITY_H__
#include <stdint.h>
#ifndef MAX
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
int IsPrefixedWith(char *str, char *prefix);
char *RemoveUnsafePrefix(char *file_name);
int IsSuffixedWith(char *file_name, char *suffix);
int TruncateExtension(char *file_name, char *ext);
unsigned char read8(int fd);
uint16_t read16Le(int fd);
uint32_t read32Le(int fd);
uint64_t read64Le(int fd);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,275 @@
/**
* @file shell.h
* @author Letter (NevermindZZT@gmail.com)
* @brief letter shell
* @version 3.0.0
* @date 2019-12-30
*
* @copyright (c) 2020 Letter
*
*/
#ifndef __SHELL_H__
#define __SHELL_H__
#include "xsconfig.h"
#include "stdlib.h"
#define SHELL_VERSION "3.0.5" /**< version */
/**
* @brief get system time (ms)
*
* @note When this macro is not defined,
* you cannot use double-clicking the tab to complete the command help,
* and you cannot use the shell timeout lock
*/
#define SHELL_GET_TICK() CalculteTimeMsFromTick(CurrentTicksGain())
/**
* @brief shell permitt
*
* @param permission permission level
*/
#define SHELL_CMD_PERMISSION(permission) \
(permission & 0x000000FF)
/**
* @brief shell COMMAND TYPE
*
* @param type type of command
*/
#define SHELL_CMD_TYPE(type) \
((type & 0x0000000F) << 8)
/**
* @brief Enable command without verifying the password
*/
#define SHELL_CMD_ENABLE_UNCHECKED \
(1 << 12)
/**
* @brief Disable print return value
*/
#define SHELL_CMD_DISABLE_RETURN \
(1 << 13)
/**
* @brief Read-only attributes (only valid for variables)
*/
#define SHELL_CMD_READ_ONLY \
(1 << 14)
/**
* @brief Number of command parameters
*/
#define SHELL_CMD_PARAM_NUM(num) \
((num & 0x0000000F)) << 16
/**
* @brief shell Command definition
*
* @param _attr Command attributes
* @param _name Command name
* @param _func Command function
* @param _desc Command description
*/
#define SHELL_EXPORT_CMD(_attr, _name, _func, _desc) \
const char shellCmd##_name[] = #_name; \
const char shellDesc##_name[] = #_desc; \
const ShellCommand \
shellCommand##_name SECTION("shellCommand") = \
{ \
.attr.value = _attr, \
.data.cmd.name = shellCmd##_name, \
.data.cmd.function = (int (*)())_func, \
.data.cmd.desc = shellDesc##_name \
}
/**
* @brief shell variable definition
*
* @param _attr Command attributes
* @param _name Command name
* @param _value Command function
* @param _desc Command description
*/
#define SHELL_EXPORT_VAR(_attr, _name, _value, _desc) \
const char shellCmd##_name[] = #_name; \
const char shellDesc##_name[] = #_desc; \
const ShellCommand \
shellVar##_name SECTION("shellCommand") = \
{ \
.attr.value = _attr, \
.data.var.name = shellCmd##_name, \
.data.var.value = (void *)_value, \
.data.var.desc = shellDesc##_name \
}
/**
* @brief shell Key definition
*
* @param _attr Key attributes
* @param _value Key value
* @param _func Key function
* @param _desc Key description
*/
#define SHELL_EXPORT_KEY(_attr, _value, _func, _desc) \
const char shellDesc##_value[] = #_desc; \
const ShellCommand \
shellKey##_value SECTION("shellCommand") = \
{ \
.attr.value = _attr|SHELL_CMD_TYPE(SHELL_TYPE_KEY), \
.data.key.value = _value, \
.data.key.function = (void (*)(Shell *))_func, \
.data.key.desc = shellDesc##_value \
}
/**
* @brief shell command type
*/
typedef enum
{
SHELL_TYPE_CMD_MAIN = 0, /**< main function form command */
SHELL_TYPE_CMD_FUNC, /**< C function form command */
SHELL_TYPE_VAR_INT, /**< int variable */
SHELL_TYPE_VAR_SHORT, /**< short variable */
SHELL_TYPE_VAR_CHAR, /**< char variable */
SHELL_TYPE_VAR_STRING, /**< string variable */
SHELL_TYPE_VAR_POINT, /**< point variable */
SHELL_TYPE_VAR_NODE, /**< node variable*/
SHELL_TYPE_USER, /**< user */
SHELL_TYPE_KEY, /**< Key */
} ShellCommandType;
/**
* @brief Shell definition
*/
typedef struct shell_def
{
struct
{
const struct shell_command *user; /**< Current user */
int activeTime; /**< shell activation time */
char *path; /**< Current shell path */
} info;
struct
{
unsigned short length; /**< Input data length */
unsigned short cursor; /**< Current cursor position */
char *buffer; /**< Input buffer */
char *param[SHELL_PARAMETER_MAX_NUMBER]; /**< parameter */
unsigned short bufferSize; /**< Input buffer size */
unsigned short paramCount; /**< Number of parameters */
int keyValue; /**< Enter key value */
} parser;
struct
{
char *item[SHELL_HISTORY_MAX_NUMBER]; /**< history record */
unsigned short number; /**< Number of history records */
unsigned short record; /**< Current record location */
signed short offset; /**< Current history offset */
} history;
struct
{
void *base; /**< Command table base address */
unsigned short count; /**< Number of commands */
} commandList;
struct
{
unsigned char isChecked : 1; /**< Password verification passed */
unsigned char isActive : 1; /**< Current active Shell */
unsigned char tabFlag : 1; /**< tab Flag */
} status;
signed char (*read)(char *); /**< shell read function */
void (*write)(const char); /**< shell write function */
} Shell;
/**
* @brief shell command definition
*/
typedef struct shell_command
{
union
{
struct
{
unsigned char permission : 8; /**< command permission */
ShellCommandType type : 4; /**< command type*/
unsigned char enableUnchecked : 1; /**< Enable when Unchecked */
unsigned char disableReturn : 1; /**< Disable return value output */
unsigned char readOnly : 1; /**< readOnly */
unsigned char reserve : 1; /**< reserve*/
unsigned char paramNum : 4; /**< Number of parameters */
} attrs;
int value;
} attr; /**< attribution */
union
{
struct
{
const char *name; /**< name */
int (*function)(); /**< function */
const char *desc; /**< Command description */
} cmd; /**< Command definition */
struct
{
const char *name; /**< varibale name */
void *value; /**< value of variable */
const char *desc; /**< Variable description */
} var; /**< variable definition */
struct
{
const char *name; /**< user name */
const char *password; /**< user's password */
const char *desc; /**< user's description */
} user; /**< user definition */
struct
{
int value; /**< key value */
void (*function)(Shell *); /**< funciton for key */
const char *desc; /**< key description */
} key; /**< key definition */
} data;
} ShellCommand;
/**
* @brief Shell node variable attributes
*/
typedef struct
{
void *var; /**< Variable reference */
int (*get)(); /**< Variable get method */
int (*set)(); /**< Variable set method */
} ShellNodeVarAttr;
#define shellSetPath(_shell, _path) (_shell)->info.path = _path
#define shellGetPath(_shell) ((_shell)->info.path)
void shellInit(Shell *shell, char *buffer, unsigned short size);
unsigned short shellWriteString(Shell *shell, const char *string);
Shell* shellGetCurrent(void);
void shellHandler(Shell *shell, char data);
void shellTask(void *param);
signed char shellCompanionAdd(Shell *shell, int id, void *object);
signed char shellCompanionDel(Shell *shell, int id);
void *shellCompanionGet(Shell *shell, int id);
#endif

View File

@@ -0,0 +1,351 @@
/**
* @file shell_ext.c
* @author Letter (NevermindZZT@gmail.com)
* @brief shell extensions
* @version 3.0.0
* @date 2019-12-31
*
* @copyright (c) 2019 Letter
*
*/
#include "shell.h"
#include "shell_ext.h"
extern ShellCommand* shellSeekCommand(Shell *shell,
const char *cmd,
ShellCommand *base,
unsigned short compareLength);
extern int shellGetVarValue(Shell *shell, ShellCommand *command);
/**
* @brief Judging the number base
*
* @param string Parameter string
* @return NUM_Type Base
*/
static NUM_Type shellExtNumType(char *string)
{
char *p = string;
NUM_Type type = NUM_TYPE_INT;
if ((*p == '0') && ((*(p + 1) == 'x') || (*(p + 1) == 'X')))
{
type = NUM_TYPE_HEX;
}
else if ((*p == '0') && ((*(p + 1) == 'b') || (*(p + 1) == 'B')))
{
type = NUM_TYPE_BIN;
}
else if (*p == '0')
{
type = NUM_TYPE_OCT;
}
while (*p++)
{
if (*p == '.' && *(p + 1) != 0)
{
type = NUM_TYPE_FLOAT;
break;
}
}
return type;
}
/**
* @brief character to number
*
* @param code character
* @return char number
*/
static char shellExtToNum(char code)
{
if ((code >= '0') && (code <= '9'))
{
return code -'0';
}
else if ((code >= 'a') && (code <= 'f'))
{
return code - 'a' + 10;
}
else if ((code >= 'A') && (code <= 'F'))
{
return code - 'A' + 10;
}
else
{
return 0;
}
}
/**
* @brief Parse character parameters
*
* @param string String parameter
* @return char Parsed character
*/
static char shellExtParseChar(char *string)
{
char *p = string + 1;
char value = 0;
if (*p == '\\')
{
switch (*(p + 1))
{
case 'b':
value = '\b';
break;
case 'r':
value = '\r';
break;
case 'n':
value = '\n';
break;
case 't':
value = '\t';
break;
case '0':
value = 0;
break;
default:
value = *(p + 1);
break;
}
}
else
{
value = *p;
}
return value;
}
/**
* @brief Parse string parameters
*
* @param string String parameter
* @return char* Parsed string
*/
static char* shellExtParseString(char *string)
{
char *p = string;
unsigned short index = 0;
if (*string == '\"')
{
p = ++string;
}
while (*p)
{
if (*p == '\\')
{
*(string + index) = shellExtParseChar(p - 1);
p++;
}
else if (*p == '\"')
{
*(string + index) = 0;
}
else
{
*(string + index) = *p;
}
p++;
index ++;
}
*(string + index) = 0;
return string;
}
/**
* @brief Parse numeric parameters
*
* @param string String parameter
* @return unsigned int Parsed number
*/
static unsigned int shellExtParseNumber(char *string)
{
NUM_Type type = NUM_TYPE_INT;
char radix = 10;
char *p = string;
char offset = 0;
signed char sign = 1;
unsigned int valueInt = 0;
float valueFloat = 0.0;
unsigned int devide = 0;
if (*string == '-')
{
sign = -1;
}
type = shellExtNumType(string + ((sign == -1) ? 1 : 0));
switch ((char)type)
{
case NUM_TYPE_HEX:
radix = 16;
offset = 2;
break;
case NUM_TYPE_OCT:
radix = 8;
offset = 1;
break;
case NUM_TYPE_BIN:
radix = 2;
offset = 2;
break;
default:
break;
}
p = string + offset + ((sign == -1) ? 1 : 0);
while (*p)
{
if (*p == '.')
{
devide = 1;
p++;
continue;
}
valueInt = valueInt * radix + shellExtToNum(*p);
devide *= 10;
p++;
}
if (type == NUM_TYPE_FLOAT && devide != 0)
{
valueFloat = (float)valueInt / devide * sign;
return *(unsigned int *)(&valueFloat);
}
else
{
return valueInt * sign;
}
}
/**
* @brief Analyze variable parameters
*
* @param shell shell object
* @param var variable
* @return unsigned int variable value
*/
static unsigned int shellExtParseVar(Shell *shell, char *var)
{
ShellCommand *command = shellSeekCommand(shell,
var + 1,
shell->commandList.base,
0);
if (command)
{
return shellGetVarValue(shell, command);
}
else
{
return 0;
}
}
/**
* @brief Parsing parameters
*
* @param shell shell
* @param string parameter
* @return unsigned int Analysis result
*/
unsigned int shellExtParsePara(Shell *shell, char *string)
{
if (*string == '\'' && *(string + 1))
{
return (unsigned int)shellExtParseChar(string);
}
else if (*string == '-' || (*string >= '0' && *string <= '9'))
{
return (unsigned int)shellExtParseNumber(string);
}
else if (*string == '$' && *(string + 1))
{
return shellExtParseVar(shell, string);
}
else if (*string)
{
return (unsigned long)shellExtParseString(string);
}
return 0;
}
/**
* @brief Excuting function
*
* @param shell shell
* @param command command
* @param argc Number of parameters
* @param argv parameter
* @return int return value
*/
int shellExtRun(Shell *shell, ShellCommand *command, int argc, char *argv[])
{
unsigned int params[8] = {0};
int paramNum = command->attr.attrs.paramNum > (argc - 1) ?
command->attr.attrs.paramNum : (argc - 1);
for (int i = 0; i < argc - 1; i++)
{
params[i] = shellExtParsePara(shell, argv[i + 1]);
}
switch (paramNum)
{
case 0:
return command->data.cmd.function();
// break;
case 1:
return command->data.cmd.function(params[0]);
// break;
case 2:
return command->data.cmd.function(params[0], params[1]);
// break;
case 3:
return command->data.cmd.function(params[0], params[1],
params[2]);
// break;
case 4:
return command->data.cmd.function(params[0], params[1],
params[2], params[3]);
// break;
case 5:
return command->data.cmd.function(params[0], params[1],
params[2], params[3],
params[4]);
// break;
case 6:
return command->data.cmd.function(params[0], params[1],
params[2], params[3],
params[4], params[5]);
// break;
case 7:
return command->data.cmd.function(params[0], params[1],
params[2], params[3],
params[4], params[5],
params[6]);
// break;
default:
return -1;
// break;
}
}

View File

@@ -0,0 +1,33 @@
/**
* @file shell_ext.h
* @author Letter (NevermindZZT@gmail.com)
* @brief shell extensions
* @version 3.0.0
* @date 2019-12-31
*
* @copyright (c) 2019 Letter
*
*/
#ifndef __SHELL_EXT_H__
#define __SHELL_EXT_H__
#include "shell.h"
/**
* @brief type of number
*
*/
typedef enum
{
NUM_TYPE_INT, /**< Decimal integer */
NUM_TYPE_BIN, /**< Binary integer */
NUM_TYPE_OCT, /**< Octal integer */
NUM_TYPE_HEX, /**< Hexadecimal integer */
NUM_TYPE_FLOAT /**< Floating point */
} NUM_Type;
unsigned int shellExtParsePara(Shell *shell, char *string);
int shellExtRun(Shell *shell, ShellCommand *command, int argc, char *argv[]);
#endif

View File

@@ -0,0 +1,126 @@
/**
* @file shell_port.c
* @author Letter (NevermindZZT@gmail.com)
* @brief
* @version 0.1
* @date 2019-02-22
*
* @copyright (c) 2019 Letter
*
*/
#include "xiuos.h"
#include "shell.h"
#include "shell_fs.h"
#include <stdio.h>
#ifdef FS_VFS
#include <iot-vfs_posix.h>
#endif
#include <stddef.h>
#include <string.h>
#include "xsconfig.h"
#include <device.h>
Shell shell;
char *shellBuffer;
ShellFs shellFs;
char *shellPathBuffer;
HardwareDevType console;
/**
* @brief Shell write
*
* @param data write data
*/
void userShellWrite(char data)
{
KPrintf("%c",data);
}
/**
* @brief shell read
*
* @param data read data
* @return char read status
*/
signed char userShellRead(char *data)
{
struct BusBlockReadParam read_param;
read_param.size = 1;
read_param.buffer = data;
BusDevReadData(console, &read_param);
return 0;
}
#ifdef SHELL_ENABLE_FILESYSTEM
/**
* @brief list file
*
* @param path path
* @param buffer result buffer
* @param maxLen the maximum buffer size
* @return size_t 0
*/
size_t userShellListDir(char *path, char *buffer, size_t maxLen)
{
DIR *dir;
struct dirent *ptr;
int i;
dir = opendir(path);
memset(buffer, 0, maxLen);
while((ptr = readdir(dir)) != NULL)
{
strcat(buffer, ptr->d_name);
strcat(buffer, "\t");
}
closedir(dir);
return 0;
}
#endif
/**
* @brief Initialize the shell
*
*/
int userShellInit(void)
{
shellBuffer = x_malloc(512*sizeof(char));
#ifdef SHELL_ENABLE_FILESYSTEM
shellPathBuffer = x_malloc(512*sizeof(char));
shellPathBuffer[0] = '/';
shellFs.getcwd = getcwd;
shellFs.chdir = chdir;
shellFs.listdir = userShellListDir;
shellFsInit(&shellFs, shellPathBuffer, 512);
shellSetPath(&shell, shellPathBuffer);
#endif
shell.write = userShellWrite;
shell.read = userShellRead;
console = ObtainConsole();
/*Open the serial device in interrupt receiving and polling sending mode */
struct SerialDevParam *serial_dev_param = (struct SerialDevParam *)console->private_data;
serial_dev_param->serial_set_mode = SIGN_OPER_INT_RX;
serial_dev_param->serial_stream_mode = SIGN_OPER_STREAM;
BusDevOpen(console);
shellInit(&shell, shellBuffer, 512);
int32 tid;
tid = KTaskCreate("letter-shell",
shellTask, &shell,
SHELL_TASK_STACK_SIZE, SHELL_TASK_PRIORITY);
StartupKTask(tid);
return 0;
}

View File

@@ -0,0 +1,21 @@
/**
* @file shell_port.h
* @author Letter (NevermindZZT@gmail.com)
* @brief
* @version 0.1
* @date 2019-02-22
*
* @copyright (c) 2019 Letter
*
*/
#ifndef __SHELL_PORT_H__
#define __SHELL_PORT_H__
#include "serial.h"
#include "shell.h"
extern Shell shell;
int userShellInit(void);
#endif