From 813dc9abc75e1d1825f795a999f68af837ebd91f Mon Sep 17 00:00:00 2001 From: turbocat Date: Thu, 10 Jun 2021 12:17:09 +0000 Subject: [PATCH] Added microtar library(mtar.obj) (Library for working with tar archives) git-svn-id: svn://kolibrios.org@8791 a494cfbc-eb01-0410-851d-a64ba20cac60 --- programs/develop/libraries/microtar/LICENSE | 19 + programs/develop/libraries/microtar/README.md | 99 ++++ .../develop/libraries/microtar/Tupfile.lua | 8 + .../libraries/microtar/example/read.asm | 78 +++ .../libraries/microtar/example/write.asm | 70 +++ .../develop/libraries/microtar/microtar.c | 456 ++++++++++++++++++ .../develop/libraries/microtar/microtar.h | 91 ++++ programs/develop/libraries/microtar/mtar.inc | 38 ++ 8 files changed, 859 insertions(+) create mode 100644 programs/develop/libraries/microtar/LICENSE create mode 100644 programs/develop/libraries/microtar/README.md create mode 100755 programs/develop/libraries/microtar/Tupfile.lua create mode 100644 programs/develop/libraries/microtar/example/read.asm create mode 100644 programs/develop/libraries/microtar/example/write.asm create mode 100644 programs/develop/libraries/microtar/microtar.c create mode 100644 programs/develop/libraries/microtar/microtar.h create mode 100644 programs/develop/libraries/microtar/mtar.inc diff --git a/programs/develop/libraries/microtar/LICENSE b/programs/develop/libraries/microtar/LICENSE new file mode 100644 index 0000000000..7e3bf17ccb --- /dev/null +++ b/programs/develop/libraries/microtar/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2017 rxi + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/programs/develop/libraries/microtar/README.md b/programs/develop/libraries/microtar/README.md new file mode 100644 index 0000000000..42acf49ca1 --- /dev/null +++ b/programs/develop/libraries/microtar/README.md @@ -0,0 +1,99 @@ +# microtar +A lightweight tar library written in ANSI C + + +## Basic Usage +The library consists of `microtar.c` and `microtar.h`. These two files can be +dropped into an existing project and compiled along with it. + + +#### Reading +```c +mtar_t tar; +mtar_header_t h; +char *p; + +/* Open archive for reading */ +mtar_open(&tar, "test.tar", "r"); + +/* Print all file names and sizes */ +while ( (mtar_read_header(&tar, &h)) != MTAR_ENULLRECORD ) { + printf("%s (%d bytes)\n", h.name, h.size); + mtar_next(&tar); +} + +/* Load and print contents of file "test.txt" */ +mtar_find(&tar, "test.txt", &h); +p = calloc(1, h.size + 1); +mtar_read_data(&tar, p, h.size); +printf("%s", p); +free(p); + +/* Close archive */ +mtar_close(&tar); +``` + +#### Writing +```c +mtar_t tar; +const char *str1 = "Hello world"; +const char *str2 = "Goodbye world"; + +/* Open archive for writing */ +mtar_open(&tar, "test.tar", "w"); + +/* Write strings to files `test1.txt` and `test2.txt` */ +mtar_write_file_header(&tar, "test1.txt", strlen(str1)); +mtar_write_data(&tar, str1, strlen(str1)); +mtar_write_file_header(&tar, "test2.txt", strlen(str2)); +mtar_write_data(&tar, str2, strlen(str2)); + +/* Finalize -- this needs to be the last thing done before closing */ +mtar_finalize(&tar); + +/* Close archive */ +mtar_close(&tar); +``` + + +## Error handling +All functions which return an `int` will return `MTAR_ESUCCESS` if the operation +is successful. If an error occurs an error value less-than-zero will be +returned; this value can be passed to the function `mtar_strerror()` to get its +corresponding error string. + + +## Wrapping a stream +If you want to read or write from something other than a file, the `mtar_t` +struct can be manually initialized with your own callback functions and a +`stream` pointer. + +All callback functions are passed a pointer to the `mtar_t` struct as their +first argument. They should return `MTAR_ESUCCESS` if the operation succeeds +without an error, or an integer below zero if an error occurs. + +After the `stream` field has been set, all required callbacks have been set and +all unused fields have been zeroset the `mtar_t` struct can be safely used with +the microtar functions. `mtar_open` *should not* be called if the `mtar_t` +struct was initialized manually. + +#### Reading +The following callbacks should be set for reading an archive from a stream: + +Name | Arguments | Description +--------|------------------------------------------|--------------------------- +`read` | `mtar_t *tar, void *data, unsigned size` | Read data from the stream +`seek` | `mtar_t *tar, unsigned pos` | Set the position indicator +`close` | `mtar_t *tar` | Close the stream + +#### Writing +The following callbacks should be set for writing an archive to a stream: + +Name | Arguments | Description +--------|------------------------------------------------|--------------------- +`write` | `mtar_t *tar, const void *data, unsigned size` | Write data to the stream + + +## License +This library is free software; you can redistribute it and/or modify it under +the terms of the MIT license. See [LICENSE](LICENSE) for details. diff --git a/programs/develop/libraries/microtar/Tupfile.lua b/programs/develop/libraries/microtar/Tupfile.lua new file mode 100755 index 0000000000..809a16b13c --- /dev/null +++ b/programs/develop/libraries/microtar/Tupfile.lua @@ -0,0 +1,8 @@ +if tup.getconfig("NO_GCC") ~= "" then return end +HELPERDIR = (tup.getconfig("HELPERDIR") == "") and "../../../" or tup.getconfig("HELPERDIR") +tup.include(HELPERDIR .. "/use_gcc.lua") + +CFLAGS = " -c -w -nostdinc -DGNUC -DMTAR_OBJ -Os -fno-common -fno-builtin -fno-leading-underscore -fno-pie" +INCLUDES = " -I../include -I../kolibri-libc/include" + +tup.rule("microtar.c", "kos32-gcc" .. CFLAGS .. INCLUDES .. " -o %o %f " .. tup.getconfig("KPACK_CMD"), "mtar.obj") diff --git a/programs/develop/libraries/microtar/example/read.asm b/programs/develop/libraries/microtar/example/read.asm new file mode 100644 index 0000000000..fdc0c6fb8e --- /dev/null +++ b/programs/develop/libraries/microtar/example/read.asm @@ -0,0 +1,78 @@ +format binary as "kex" + +use32 + org 0x0 + db 'MENUET01' + dd 0x01 + dd START + dd IM_END + dd MEM + dd MEM + dd 0 + dd 0 + +include '../../../../macros.inc' +include '../../../../proc32.inc' +include '../../../../KOSfuncs.inc' +include '../../../../dll.inc' +include '../mtar.inc' +;include '../../../../debug-fdo.inc' + +;__DEBUG__ = 1 +;__DEBUG_LEVEL__ = 2 + + +START: + stdcall dll.Load, @IMPORT ; Имортироуем функции из mtar.obj + test eax, eax + jnz exit + + ccall [mtar_init] ; Инициализируем библиотеку (на самом деле подгружается libc.obj + ccall [mtar_open], tar, tar_fname, tar_fmode ; Открываем для чтения файл 'test.tar' + + ; DEBUGF 2, "%d", eax + +print_next: + ccall [mtar_read_header], tar, header ; Читаем заголовок + cmp eax, MTAR_ENULLRECORD ; Если заголовок не был прочитан (return -7) выходим из цикла + je exit + ccall [printf], format_str, header+mtar_header_t.name, dword[header+mtar_header_t.size] ; Выводим в консоль имя файла и размер в байтах + ccall [mtar_next], tar ; Переходим к следующему заголовку + jmp print_next ; прыгаем в начало цикла + +exit: + ccall [mtar_close], tar ; Закрываем 'test.tar' + mcall SF_TERMINATE_PROCESS ; Выходим из программы + +; data + +tar_fname db 'test.tar', 0 +tar_fmode db 'r', 0 + +tar rb sizeof.mtar_t +header rb sizeof.mtar_header_t + +format_str db '%-10s (%-4d bytes)', 0x0A,0 + +align 4 + +@IMPORT: +library mtar, 'mtar.obj', libc , 'libc.obj' +import mtar, \ + mtar_init, 'mtar_init', \ + mtar_open, 'mtar_open', \ + mtar_next, 'mtar_next', \ + mtar_strerror, 'mtar_strerror', \ + mtar_read_header, 'mtar_read_header', \ + mtar_write_data, 'mtar_write_data', \ + mtar_finalize, 'mtar_finalize', \ + mtar_close, 'mtar_finalize' + +import libc, \ + printf, 'printf' + + +IM_END: +align 4 +rb 4096 ; stack +MEM: diff --git a/programs/develop/libraries/microtar/example/write.asm b/programs/develop/libraries/microtar/example/write.asm new file mode 100644 index 0000000000..f68b72f4a3 --- /dev/null +++ b/programs/develop/libraries/microtar/example/write.asm @@ -0,0 +1,70 @@ +format binary as "kex" + +use32 + org 0x0 + db 'MENUET01' + dd 0x01 + dd START + dd IM_END + dd MEM + dd MEM + dd 0 + dd 0 + +include '../../../../macros.inc' +include '../../../../proc32.inc' +include '../../../../KOSfuncs.inc' +include '../../../../dll.inc' +include '../mtar.inc' +;include '../../../../debug-fdo.inc' + +;__DEBUG__ = 1 +;__DEBUG_LEVEL__ = 2 + +START: + stdcall dll.Load, @IMPORT ; Имортироуем функции из mtar.obj + test eax, eax + jnz exit + + ccall [mtar_init] ; Инициализируем библиотеку (на самом деле подгружается libc.obj + ccall [mtar_open], tar, tar_fname, tar_fmode ; Создаём новый файл 'test.tar' + ccall [mtar_write_file_header], tar, test1_txt , str1_len ; Создаём внутри 'test.tar' пустрой файл 'test1.txt' + + ccall [mtar_write_data], tar, str1, str1_len ; Записываем данныев в этот файл + + ccall [mtar_finalize], tar ; Указываем что больше с tar работать не будем + ccall [mtar_close], tar ; Закрываем 'test.tar' + +exit: + mcall SF_TERMINATE_PROCESS ; Выходим из программы + +; data + +str1 db 'Hello world!', 0 +str1_len = $ - str1 + +str2 db 'Goodbye world!', 0 + +tar_fname db 'test.tar', 0 +tar_fmode db 'w', 0 + +test1_txt db 'test1.txt', 0 + +tar rb 32 + +align 4 + +@IMPORT: +library mtar, 'mtar.obj' +import mtar, \ + mtar_init, 'mtar_init', \ + mtar_open, 'mtar_open', \ + mtar_write_file_header, 'mtar_write_file_header', \ + mtar_write_data, 'mtar_write_data', \ + mtar_finalize, 'mtar_finalize', \ + mtar_close, 'mtar_finalize' + +IM_END: +align 4 +rb 4096 ; stack +MEM: diff --git a/programs/develop/libraries/microtar/microtar.c b/programs/develop/libraries/microtar/microtar.c new file mode 100644 index 0000000000..4970017fdd --- /dev/null +++ b/programs/develop/libraries/microtar/microtar.c @@ -0,0 +1,456 @@ +/* + * Copyright (c) 2017 rxi + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include +#include +#include +#include + +#include + +#include "microtar.h" + +typedef struct { + char name[100]; + char mode[8]; + char owner[8]; + char group[8]; + char size[12]; + char mtime[12]; + char checksum[8]; + char type; + char linkname[100]; + char _padding[255]; +} mtar_raw_header_t; + +static void * mtar_memset( void * s, int c, size_t n ){ + unsigned char * p = ( unsigned char * ) s; + while ( n-- ){ + *p++ = ( unsigned char ) c; + } + return s; +} + +#ifdef MTAR_OBJ + +size_t (*fread)(void *restrict, size_t size, size_t count, FILE *restrict)=NULL; +size_t (*fwrite)(const void *restrict, size_t size, size_t count, FILE *restrict)=NULL; +int (*fclose)(FILE *)=NULL; +FILE* (*fopen)(const char *restrict, const char *restrict)=NULL; +int (*fseek)(FILE *, long, int)=NULL; +long (*ftell)(FILE *)=NULL; +int (*sprintf)(char* buffer, const char* format, ...)=NULL; +int (*sscanf)(const char*, const char *restrict, ...)=NULL; +int (*strcmp)(const char * s1, const char* s2)=NULL; +char* (*strchr)(const char* s, int c)=NULL; +char* (*strcpy)(char* s1, const char* s2)=NULL; + +#endif + +static unsigned round_up(unsigned n, unsigned incr) { + return n + (incr - n % incr) % incr; +} + + +static unsigned checksum(const mtar_raw_header_t* rh) { + unsigned i; + unsigned char *p = (unsigned char*) rh; + unsigned res = 256; + for (i = 0; i < offsetof(mtar_raw_header_t, checksum); i++) { + res += p[i]; + } + for (i = offsetof(mtar_raw_header_t, type); i < sizeof(*rh); i++) { + res += p[i]; + } + return res; +} + + +static int tread(mtar_t *tar, void *data, unsigned size) { + int err = tar->read(tar, data, size); + tar->pos += size; + return err; +} + + +static int twrite(mtar_t *tar, const void *data, unsigned size) { + + int err = tar->write(tar, data, size); + tar->pos += size; + return err; +} + + +static int write_null_bytes(mtar_t *tar, int n) { + int i, err; + char nul = '\0'; + for (i = 0; i < n; i++) { + err = twrite(tar, &nul, 1); + if (err) { + return err; + } + } + return MTAR_ESUCCESS; +} + + +static int raw_to_header(mtar_header_t *h, const mtar_raw_header_t *rh) { + unsigned chksum1, chksum2; + + /* If the checksum starts with a null byte we assume the record is NULL */ + if (*rh->checksum == '\0') { + return MTAR_ENULLRECORD; + } + + /* Build and compare checksum */ + chksum1 = checksum(rh); + sscanf(rh->checksum, "%o", &chksum2); + if (chksum1 != chksum2) { + return MTAR_EBADCHKSUM; + } + + /* Load raw header into header */ + sscanf(rh->mode, "%o", &h->mode); + sscanf(rh->owner, "%o", &h->owner); + sscanf(rh->size, "%o", &h->size); + sscanf(rh->mtime, "%o", &h->mtime); + h->type = rh->type; + strcpy(h->name, rh->name); + strcpy(h->linkname, rh->linkname); + + return MTAR_ESUCCESS; +} + + +static int header_to_raw(mtar_raw_header_t *rh, const mtar_header_t *h) { + unsigned chksum; + + /* Load header into raw header */ + mtar_memset(rh, 0, sizeof(*rh)); + sprintf(rh->mode, "%o", h->mode); + sprintf(rh->owner, "%o", h->owner); + sprintf(rh->size, "%o", h->size); + sprintf(rh->mtime, "%o", h->mtime); + rh->type = h->type ? h->type : MTAR_TREG; + strcpy(rh->name, h->name); + strcpy(rh->linkname, h->linkname); + + /* Calculate and write checksum */ + chksum = checksum(rh); + sprintf(rh->checksum, "%06o", chksum); + rh->checksum[7] = ' '; + + return MTAR_ESUCCESS; +} + + +const char* mtar_strerror(int err) { + switch (err) { + case MTAR_ESUCCESS : return "success"; + case MTAR_EFAILURE : return "failure"; + case MTAR_EOPENFAIL : return "could not open"; + case MTAR_EREADFAIL : return "could not read"; + case MTAR_EWRITEFAIL : return "could not write"; + case MTAR_ESEEKFAIL : return "could not seek"; + case MTAR_EBADCHKSUM : return "bad checksum"; + case MTAR_ENULLRECORD : return "null record"; + case MTAR_ENOTFOUND : return "file not found"; + } + return "unknown error"; +} + + +static int file_write(mtar_t *tar, const void *data, unsigned size) { + unsigned res = fwrite(data, 1, size, tar->stream); + return (res == size) ? MTAR_ESUCCESS : MTAR_EWRITEFAIL; +} + +static int file_read(mtar_t *tar, void *data, unsigned size) { + unsigned res = fread(data, 1, size, tar->stream); + return (res == size) ? MTAR_ESUCCESS : MTAR_EREADFAIL; +} + +static int file_seek(mtar_t *tar, unsigned offset) { + int res = fseek(tar->stream, offset, SEEK_SET); + return (res == 0) ? MTAR_ESUCCESS : MTAR_ESEEKFAIL; +} + +static int file_close(mtar_t *tar) { + fclose(tar->stream); + return MTAR_ESUCCESS; +} + + +int mtar_open(mtar_t *tar, const char *filename, const char *mode) { + int err; + mtar_header_t h; + + /* Init tar struct and functions */ + mtar_memset(tar, 0, sizeof(*tar)); + tar->write = file_write; + tar->read = file_read; + tar->seek = file_seek; + tar->close = file_close; + + /* Assure mode is always binary */ + if ( strchr(mode, 'r') ) mode = "rb"; + if ( strchr(mode, 'w') ) mode = "wb"; + if ( strchr(mode, 'a') ) mode = "ab"; + /* Open file */ + tar->stream = fopen(filename, mode); + if (!tar->stream) { + return MTAR_EOPENFAIL; + } + /* Read first header to check it is valid if mode is `r` */ + if (*mode == 'r') { + err = mtar_read_header(tar, &h); + if (err != MTAR_ESUCCESS) { + mtar_close(tar); + return err; + } + } + + /* Return ok */ + return MTAR_ESUCCESS; +} + + +int mtar_close(mtar_t *tar) { + return tar->close(tar); +} + + +int mtar_seek(mtar_t *tar, unsigned pos) { + int err = tar->seek(tar, pos); + tar->pos = pos; + return err; +} + + +int mtar_rewind(mtar_t *tar) { + tar->remaining_data = 0; + tar->last_header = 0; + return mtar_seek(tar, 0); +} + + +int mtar_next(mtar_t *tar) { + int err, n; + mtar_header_t h; + /* Load header */ + err = mtar_read_header(tar, &h); + if (err) { + return err; + } + /* Seek to next record */ + n = round_up(h.size, 512) + sizeof(mtar_raw_header_t); + return mtar_seek(tar, tar->pos + n); +} + + +int mtar_find(mtar_t *tar, const char *name, mtar_header_t *h) { + int err; + mtar_header_t header; + /* Start at beginning */ + err = mtar_rewind(tar); + if (err) { + return err; + } + /* Iterate all files until we hit an error or find the file */ + while ( (err = mtar_read_header(tar, &header)) == MTAR_ESUCCESS ) { + if ( !strcmp(header.name, name) ) { + if (h) { + *h = header; + } + return MTAR_ESUCCESS; + } + mtar_next(tar); + } + /* Return error */ + if (err == MTAR_ENULLRECORD) { + err = MTAR_ENOTFOUND; + } + return err; +} + + +int mtar_read_header(mtar_t *tar, mtar_header_t *h) { + int err; + mtar_raw_header_t rh; + /* Save header position */ + tar->last_header = tar->pos; + /* Read raw header */ + err = tread(tar, &rh, sizeof(rh)); + if (err) { + return err; + } + /* Seek back to start of header */ + err = mtar_seek(tar, tar->last_header); + if (err) { + return err; + } + /* Load raw header into header struct and return */ + return raw_to_header(h, &rh); +} + + +int mtar_read_data(mtar_t *tar, void *ptr, unsigned size) { + int err; + /* If we have no remaining data then this is the first read, we get the size, + * set the remaining data and seek to the beginning of the data */ + if (tar->remaining_data == 0) { + mtar_header_t h; + /* Read header */ + err = mtar_read_header(tar, &h); + if (err) { + return err; + } + /* Seek past header and init remaining data */ + err = mtar_seek(tar, tar->pos + sizeof(mtar_raw_header_t)); + if (err) { + return err; + } + tar->remaining_data = h.size; + } + /* Read data */ + err = tread(tar, ptr, size); + if (err) { + return err; + } + tar->remaining_data -= size; + /* If there is no remaining data we've finished reading and seek back to the + * header */ + if (tar->remaining_data == 0) { + return mtar_seek(tar, tar->last_header); + } + return MTAR_ESUCCESS; +} + + +int mtar_write_header(mtar_t *tar, const mtar_header_t *h) { + mtar_raw_header_t rh; + /* Build raw header and write */ + header_to_raw(&rh, h); + tar->remaining_data = h->size; + return twrite(tar, &rh, sizeof(rh)); +} + +int mtar_write_file_header(mtar_t *tar, const char *name, unsigned size) { + mtar_header_t h; + /* Build header */ + mtar_memset(&h, 0, sizeof(h)); + strcpy(h.name, name); + h.size = size; + h.type = MTAR_TREG; + h.mode = 0664; + /* Write header */ + return mtar_write_header(tar, &h); +} + + +int mtar_write_dir_header(mtar_t *tar, const char *name) { + mtar_header_t h; + /* Build header */ + mtar_memset(&h, 0, sizeof(h)); + strcpy(h.name, name); + h.type = MTAR_TDIR; + h.mode = 0775; + /* Write header */ + return mtar_write_header(tar, &h); +} + + +int mtar_write_data(mtar_t *tar, const void *data, unsigned size) { + int err; + /* Write data */ + err = twrite(tar, data, size); + if (err) { + return err; + } + tar->remaining_data -= size; + /* Write padding if we've written all the data for this file */ + if (tar->remaining_data == 0) { + return write_null_bytes(tar, round_up(tar->pos, 512) - tar->pos); + } + return MTAR_ESUCCESS; +} + + +int mtar_finalize(mtar_t *tar) { + /* Write two NULL records */ + return write_null_bytes(tar, sizeof(mtar_raw_header_t) * 2); +} + +/* Load libc.obj */ + +#ifdef MTAR_OBJ + +#include + +void mtar_panic(char* func_name){ + _ksys_debug_puts("mtar.obj: "); + _ksys_debug_puts(func_name); + _ksys_debug_puts(" = NULL!\n"); +} + +int mtar_init(){ + ksys_coff_etable_t *libc = _ksys_load_coff("/sys/lib/libc.obj"); + if(!libc){ + _ksys_debug_puts("mtar.obj: libc.obj not loaded!"); + return 1; + } + + fread = _ksys_get_coff_func(libc, "fread", mtar_panic); + fwrite = _ksys_get_coff_func(libc, "fwrite", mtar_panic); + fclose = _ksys_get_coff_func(libc, "fclose", mtar_panic); + fopen = _ksys_get_coff_func(libc, "fopen", mtar_panic); + fseek = _ksys_get_coff_func(libc, "fseek", mtar_panic); + ftell = _ksys_get_coff_func(libc, "ftell", mtar_panic); + sprintf= _ksys_get_coff_func(libc, "sprintf", mtar_panic); + sscanf = _ksys_get_coff_func(libc, "sscanf", mtar_panic); + strcmp = _ksys_get_coff_func(libc, "strcmp", mtar_panic); + strchr = _ksys_get_coff_func(libc, "strchr", mtar_panic); + strcpy = _ksys_get_coff_func(libc, "strcpy", mtar_panic); + return 0; +} + + +ksys_coff_etable_t EXPORTS[] = { + {"mtar_init", mtar_init}, + {"mtar_open", mtar_open}, + {"mtar_close", mtar_close}, + {"mtar_seek", mtar_seek}, + {"mtar_rewind", mtar_rewind}, + {"mtar_next", mtar_next}, + {"mtar_find", mtar_find}, + {"mtar_read_header", mtar_read_header}, + {"mtar_read_data", mtar_read_data}, + {"mtar_write_header", mtar_write_header}, + {"mtar_write_file_header", mtar_write_file_header}, + {"mtar_write_dir_header", mtar_write_dir_header}, + {"mtar_write_data",mtar_write_data}, + {"mtar_finalize", mtar_finalize}, + {"mtar_strerror", mtar_strerror}, + NULL +}; + +#endif diff --git a/programs/develop/libraries/microtar/microtar.h b/programs/develop/libraries/microtar/microtar.h new file mode 100644 index 0000000000..9c6d39c208 --- /dev/null +++ b/programs/develop/libraries/microtar/microtar.h @@ -0,0 +1,91 @@ +/** + * Copyright (c) 2017 rxi + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the MIT license. See `microtar.c` for details. + */ + +#ifndef MICROTAR_H +#define MICROTAR_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include + +#define MTAR_VERSION "0.1.0" + +enum { + MTAR_ESUCCESS = 0, + MTAR_EFAILURE = -1, + MTAR_EOPENFAIL = -2, + MTAR_EREADFAIL = -3, + MTAR_EWRITEFAIL = -4, + MTAR_ESEEKFAIL = -5, + MTAR_EBADCHKSUM = -6, + MTAR_ENULLRECORD = -7, + MTAR_ENOTFOUND = -8 +}; + +enum { + MTAR_TREG = '0', + MTAR_TLNK = '1', + MTAR_TSYM = '2', + MTAR_TCHR = '3', + MTAR_TBLK = '4', + MTAR_TDIR = '5', + MTAR_TFIFO = '6' +}; + +typedef struct { + unsigned mode; + unsigned owner; + unsigned size; + unsigned mtime; + unsigned type; + char name[100]; + char linkname[100]; +} mtar_header_t; + + +typedef struct mtar_t mtar_t; + +#pragma pack(push,1) +struct mtar_t { + int (*read)(mtar_t *tar, void *data, unsigned size); + int (*write)(mtar_t *tar, const void *data, unsigned size); + int (*seek)(mtar_t *tar, unsigned pos); + int (*close)(mtar_t *tar); + void *stream; + unsigned pos; + unsigned remaining_data; + unsigned last_header; +}; +#pragma pack(pop) + +const char* mtar_strerror(int err); + +int mtar_open(mtar_t *tar, const char *filename, const char *mode); +int mtar_close(mtar_t *tar); + +int mtar_seek(mtar_t *tar, unsigned pos); +int mtar_rewind(mtar_t *tar); +int mtar_next(mtar_t *tar); +int mtar_find(mtar_t *tar, const char *name, mtar_header_t *h); +int mtar_read_header(mtar_t *tar, mtar_header_t *h); +int mtar_read_data(mtar_t *tar, void *ptr, unsigned size); + +int mtar_write_header(mtar_t *tar, const mtar_header_t *h); +int mtar_write_file_header(mtar_t *tar, const char *name, unsigned size); +int mtar_write_dir_header(mtar_t *tar, const char *name); +int mtar_write_data(mtar_t *tar, const void *data, unsigned size); +int mtar_finalize(mtar_t *tar); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/programs/develop/libraries/microtar/mtar.inc b/programs/develop/libraries/microtar/mtar.inc new file mode 100644 index 0000000000..210f99eeb9 --- /dev/null +++ b/programs/develop/libraries/microtar/mtar.inc @@ -0,0 +1,38 @@ +MTAR_ESUCCESS = 0 +MTAR_EFAILURE = -1 +MTAR_EOPENFAIL = -2 +MTAR_EREADFAIL = -3 +MTAR_EWRITEFAIL = -4 +MTAR_ESEEKFAIL = -5 +MTAR_EBADCHKSUM = -6 +MTAR_ENULLRECORD = -7 +MTAR_ENOTFOUND = -8 + +MTAR_TREG = '0' +MTAR_TLNK = '1' +MTAR_TSYM = '2' +MTAR_TCHR = '3' +MTAR_TBLK = '4' +MTAR_TDIR = '5' +MTAR_TFIFO = '6' + +struct mtar_header_t + mode dd ? + owner dd ? + size dd ? + mtime dd ? + type dd ? + name rb 100 + linkname rb 100 +ends + +struct mtar_t + read_func dd ? + write_func dd ? + seek_func dd ? + close_func dd ? + stream dd ? + pos dd ? + remaining_data dd ? + last_header dd ? +ends \ No newline at end of file