Adjust directory structure

This commit is contained in:
Zhao_Jiasheng
2021-06-03 17:38:11 +08:00
parent 92301257f3
commit 89a2236b18
1993 changed files with 40 additions and 0 deletions
@@ -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
@@ -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 = (int *)hufGroup->base - 1;
limit = (int *)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
@@ -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
@@ -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
@@ -0,0 +1,5 @@
SRC_FILES := blocksort.c bzlib.c compress.c huffman.c
include $(KERNEL_ROOT)/compiler.mk
@@ -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;
}
@@ -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
@@ -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);
@@ -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);
@@ -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
@@ -0,0 +1,179 @@
/* ------------------------------------------------------------------
This file is part of bzip2/libbzip2, a program and library for
lossless, block-sorting data compression.
bzip2/libbzip2 version 1.0.4 of 20 December 2006
Copyright (C) 1996-2006 Julian Seward <jseward@bzip.org>
Please read the WARNING, DISCLAIMER and PATENTS sections in the
README file.
This program is released under the terms of the license contained
in the file LICENSE.
------------------------------------------------------------------ */
#include <xiuos.h>
#if defined(FS_VFS) && defined(TOOL_SHELL)
#include "bzlib_private.h"
#define WEIGHTOF(zz0) ((zz0) & 0xffffff00)
#define DEPTHOF(zz1) ((zz1) & 0x000000ff)
#define MYMAX(zz2,zz3) ((zz2) > (zz3) ? (zz2) : (zz3))
#define ADDWEIGHTS(zw1,zw2) \
(WEIGHTOF(zw1)+WEIGHTOF(zw2)) | \
(1 + MYMAX(DEPTHOF(zw1),DEPTHOF(zw2)))
#define UPHEAP(z) { \
int32_t zz, tmp; \
zz = z; \
tmp = HEAP[zz]; \
while (WEIGHT[tmp] < WEIGHT[HEAP[zz >> 1]]) { \
HEAP[zz] = HEAP[zz >> 1]; \
zz >>= 1; \
} \
HEAP[zz] = tmp; \
}
#if BZIP2_SPEED >= 1
#define DOWNHEAP1(heap, weight, Heap) { \
int32_t zz, yy, tmp; \
zz = 1; \
tmp = heap[zz]; \
while (1) { \
yy = zz << 1; \
if (yy > nHeap) \
break; \
if (yy < nHeap \
&& weight[heap[yy+1]] < weight[heap[yy]]) \
yy++; \
if (weight[tmp] < weight[heap[yy]]) \
break; \
heap[zz] = heap[yy]; \
zz = yy; \
} \
heap[zz] = tmp; \
}
#else
static void DOWNHEAP1(int32_t *heap, int32_t *weight, int32_t nHeap)
{
int32_t zz, yy, tmp;
zz = 1;
tmp = heap[zz];
while (1) {
yy = zz << 1;
if (yy > nHeap)
break;
if (yy < nHeap
&& weight[heap[yy + 1]] < weight[heap[yy]])
yy++;
if (weight[tmp] < weight[heap[yy]])
break;
heap[zz] = heap[yy];
zz = yy;
}
heap[zz] = tmp;
}
#endif
void BZ2HbMakeCodeLengths(EState *s,
uint8_t *len,
int32_t *freq,
int32_t alphaSize,
int32_t maxLen)
{
int32_t nNodes, nHeap, n1, n2, i, j, k;
Bool tooLong;
#define HEAP (s->BZ2_hbMakeCodeLengths__heap)
#define WEIGHT (s->BZ2_hbMakeCodeLengths__weight)
#define PARENT (s->BZ2_hbMakeCodeLengths__parent)
for (i = 0; i < alphaSize; i++)
WEIGHT[i+1] = (freq[i] == 0 ? 1 : freq[i]) << 8;
while (1) {
nNodes = alphaSize;
nHeap = 0;
HEAP[0] = 0;
WEIGHT[0] = 0;
PARENT[0] = -2;
for (i = 1; i <= alphaSize; i++) {
PARENT[i] = -1;
nHeap++;
HEAP[nHeap] = i;
UPHEAP(nHeap);
}
ASSERTH(nHeap < (BZ_MAX_ALPHA_SIZE+2), 2001);
while (nHeap > 1) {
n1 = HEAP[1]; HEAP[1] = HEAP[nHeap]; nHeap--; DOWNHEAP1(HEAP, WEIGHT, nHeap);
n2 = HEAP[1]; HEAP[1] = HEAP[nHeap]; nHeap--; DOWNHEAP1(HEAP, WEIGHT, nHeap);
nNodes++;
PARENT[n1] = PARENT[n2] = nNodes;
WEIGHT[nNodes] = ADDWEIGHTS(WEIGHT[n1], WEIGHT[n2]);
PARENT[nNodes] = -1;
nHeap++;
HEAP[nHeap] = nNodes;
UPHEAP(nHeap);
}
ASSERTH(nNodes < (BZ_MAX_ALPHA_SIZE * 2), 2002);
tooLong = FALSE;
for (i = 1; i <= alphaSize; i++) {
j = 0;
k = i;
while (PARENT[k] >= 0) {
k = PARENT[k];
j++;
}
len[i-1] = j;
if (j > maxLen)
tooLong = TRUE;
}
if (!tooLong)
break;
for (i = 1; i <= alphaSize; i++) {
j = WEIGHT[i] >> 8;
j = 1 + (j / 2);
WEIGHT[i] = j << 8;
}
}
#undef HEAP
#undef WEIGHT
#undef PARENT
}
void BZ2HbAssignCodes(int32_t *code,
uint8_t *length,
int32_t minLen,
int32_t maxLen,
int32_t alphaSize)
{
int32_t n, vec, i;
vec = 0;
for (n = minLen; n <= maxLen; n++) {
for (i = 0; i < alphaSize; i++) {
if (length[i] == n) {
code[i] = vec;
vec++;
}
}
vec <<= 1;
}
}
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,48 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#ifndef __INC_GUNZIP_H__
#define __INC_GUNZIP_H__
typedef struct GzipHdr {
uint8_t gz_method;
uint8_t flags;
uint32_t mtime;
uint8_t extra_flags;
uint8_t os_flags;
} __attribute__((packed)) GzipHdr_t;
typedef struct huft {
unsigned char e;
unsigned char b;
union {
uint16_t n;
struct huft *t;
};
} huft_t;
#define GUNZIP_WSIZE (1 << 15)
#define GUNZIP_BYTEBUFFER_MAX (1 << 14)
#define BMAX 16
#define NMAX 288
enum methods {
STORED = 1,
CODES,
};
int InflateUnzip(int zip_fd, int dst_fd, uint32_t cmpsize,
uint32_t ucmpsize, uint32_t crc32);
#endif
File diff suppressed because it is too large Load Diff
@@ -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
@@ -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 *path);
abs_from = GetAbsolutePath(from);
abs_to = GetAbsolutePath(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 CmdCp(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,CmdCp, 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 CmdMv(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,CmdMv, 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 CmdPwd(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,CmdPwd, 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 CmdGzip(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,CmdGzip, creat or extart gzip compressed files);
int CmdGunzip(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,CmdGunzip,decompress gzip files.);
int CmdUnzip(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,CmdUnzip, 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
@@ -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);
}
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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