xiuos/tool/shell/letter-shell/file_ext/bzip2.c

163 lines
3.6 KiB
C

/*
* 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