forked from xuos/xiuos
First commit XiUOS
This commit is contained in:
96
tool/shell/Kconfig
Normal file
96
tool/shell/Kconfig
Normal 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
3
tool/shell/Makefile
Normal file
@@ -0,0 +1,3 @@
|
||||
SRC_DIR := letter-shell
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
21
tool/shell/letter-shell/LICENSE
Normal file
21
tool/shell/letter-shell/LICENSE
Normal 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.
|
||||
7
tool/shell/letter-shell/Makefile
Normal file
7
tool/shell/letter-shell/Makefile
Normal 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
|
||||
214
tool/shell/letter-shell/README.md
Normal file
214
tool/shell/letter-shell/README.md
Normal file
@@ -0,0 +1,214 @@
|
||||
# letter shell 3.0
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
一个功能强大的嵌入式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"
|
||||
```
|
||||
823
tool/shell/letter-shell/cmd.c
Normal file
823
tool/shell/letter-shell/cmd.c
Normal 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
|
||||
5
tool/shell/letter-shell/file_ext/Makefile
Normal file
5
tool/shell/letter-shell/file_ext/Makefile
Normal 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
|
||||
656
tool/shell/letter-shell/file_ext/bunzip2.c
Normal file
656
tool/shell/letter-shell/file_ext/bunzip2.c
Normal 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
|
||||
162
tool/shell/letter-shell/file_ext/bzip2.c
Normal file
162
tool/shell/letter-shell/file_ext/bzip2.c
Normal 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
|
||||
18
tool/shell/letter-shell/file_ext/bzip2.h
Normal file
18
tool/shell/letter-shell/file_ext/bzip2.h
Normal 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
|
||||
5
tool/shell/letter-shell/file_ext/bzlib/Makefile
Normal file
5
tool/shell/letter-shell/file_ext/bzlib/Makefile
Normal file
@@ -0,0 +1,5 @@
|
||||
SRC_FILES := blocksort.c bzlib.c compress.c huffman.c
|
||||
|
||||
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
838
tool/shell/letter-shell/file_ext/bzlib/blocksort.c
Normal file
838
tool/shell/letter-shell/file_ext/bzlib/blocksort.c
Normal 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;
|
||||
}
|
||||
338
tool/shell/letter-shell/file_ext/bzlib/bzlib.c
Normal file
338
tool/shell/letter-shell/file_ext/bzlib/bzlib.c
Normal 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
|
||||
47
tool/shell/letter-shell/file_ext/bzlib/bzlib.h
Normal file
47
tool/shell/letter-shell/file_ext/bzlib/bzlib.h
Normal 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);
|
||||
|
||||
165
tool/shell/letter-shell/file_ext/bzlib/bzlib_private.h
Normal file
165
tool/shell/letter-shell/file_ext/bzlib/bzlib_private.h
Normal 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);
|
||||
|
||||
577
tool/shell/letter-shell/file_ext/bzlib/compress.c
Normal file
577
tool/shell/letter-shell/file_ext/bzlib/compress.c
Normal 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
|
||||
179
tool/shell/letter-shell/file_ext/bzlib/huffman.c
Normal file
179
tool/shell/letter-shell/file_ext/bzlib/huffman.c
Normal 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
|
||||
1025
tool/shell/letter-shell/file_ext/gunzip.c
Normal file
1025
tool/shell/letter-shell/file_ext/gunzip.c
Normal file
File diff suppressed because it is too large
Load Diff
48
tool/shell/letter-shell/file_ext/gunzip.h
Normal file
48
tool/shell/letter-shell/file_ext/gunzip.h
Normal 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
|
||||
1020
tool/shell/letter-shell/file_ext/gzip.c
Normal file
1020
tool/shell/letter-shell/file_ext/gzip.c
Normal file
File diff suppressed because it is too large
Load Diff
90
tool/shell/letter-shell/file_ext/gzip.h
Normal file
90
tool/shell/letter-shell/file_ext/gzip.h
Normal 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
|
||||
601
tool/shell/letter-shell/file_ext/msh_file.c
Normal file
601
tool/shell/letter-shell/file_ext/msh_file.c
Normal 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
|
||||
|
||||
29
tool/shell/letter-shell/file_ext/shell_fs.c
Normal file
29
tool/shell/letter-shell/file_ext/shell_fs.c
Normal 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);
|
||||
}
|
||||
38
tool/shell/letter-shell/file_ext/shell_fs.h
Normal file
38
tool/shell/letter-shell/file_ext/shell_fs.h
Normal 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
|
||||
467
tool/shell/letter-shell/file_ext/tar.c
Normal file
467
tool/shell/letter-shell/file_ext/tar.c
Normal 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
|
||||
59
tool/shell/letter-shell/file_ext/tar.h
Normal file
59
tool/shell/letter-shell/file_ext/tar.h
Normal 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
|
||||
283
tool/shell/letter-shell/file_ext/unzip.c
Normal file
283
tool/shell/letter-shell/file_ext/unzip.c
Normal 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
|
||||
70
tool/shell/letter-shell/file_ext/unzip.h
Normal file
70
tool/shell/letter-shell/file_ext/unzip.h
Normal 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
|
||||
121
tool/shell/letter-shell/file_ext/utility.c
Normal file
121
tool/shell/letter-shell/file_ext/utility.c
Normal 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
|
||||
36
tool/shell/letter-shell/file_ext/utility.h
Normal file
36
tool/shell/letter-shell/file_ext/utility.h
Normal 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
|
||||
1729
tool/shell/letter-shell/shell.c
Normal file
1729
tool/shell/letter-shell/shell.c
Normal file
File diff suppressed because it is too large
Load Diff
275
tool/shell/letter-shell/shell.h
Normal file
275
tool/shell/letter-shell/shell.h
Normal 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
|
||||
|
||||
351
tool/shell/letter-shell/shell_ext.c
Normal file
351
tool/shell/letter-shell/shell_ext.c
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
33
tool/shell/letter-shell/shell_ext.h
Normal file
33
tool/shell/letter-shell/shell_ext.h
Normal 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
|
||||
126
tool/shell/letter-shell/shell_port.c
Normal file
126
tool/shell/letter-shell/shell_port.c
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
21
tool/shell/letter-shell/shell_port.h
Normal file
21
tool/shell/letter-shell/shell_port.h
Normal 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
|
||||
Reference in New Issue
Block a user