Skip to content

Commit

Permalink
fix: muntar with subdir generation pass first
Browse files Browse the repository at this point in the history
use tar command flag --format compatible with osx

muntar mkdir compat windows

only check checksum of donut for muntar test

correct _WIN32 define

include windows.h on createdirectory
  • Loading branch information
jaromil committed Dec 15, 2024
1 parent 5da9aad commit ba51b90
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 63 deletions.
156 changes: 101 additions & 55 deletions src/muntar.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,10 +140,111 @@ static int mtar_seek(mtar_t *tar, size_t pos) {
return(MTAR_ESUCCESS);
}

static int mtar_rewind(mtar_t *tar) {
int err;
tar->iterator.offset = UINT64_MAX;
tar->iterator.cursor = UINT64_MAX;
err = mtar_seek(tar, 0);
if (err != MTAR_ESUCCESS) return err;
err = mtar_read_header(tar, &(tar->iterator.header));
if (err != MTAR_ESUCCESS) return err;
tar->iterator.offset = 0;
tar->iterator.cursor = 512;
return(MTAR_ESUCCESS);
}
///////////////////
// PUBLIC FUNCTIONS
///////////////////


#include <sys/stat.h> // for mkdir(2)
#if defined(_WIN32
#include <windows.h>
#define makedir(path) CreateDirectory(path, NULL)
#else
#define makedir(path) mkdir(path,0755)
#endif
// used by extract_embeddings(char *tmpdir)
int untar_to_path(const char *path, const uint8_t *buf,
const unsigned int len) {
int res;
mtar_t tar;
char tpath[512];
const size_t pathlen = strlen(path);
if(pathlen>100) return(MTAR_EFAILURE);
char *p;
const mtar_header_t *header = NULL;
strcpy(tpath, path);
res = mtar_load(&tar, path, buf, len);
if(res != MTAR_ESUCCESS) return(MTAR_EOPENFAIL);
// first create extract dir if doesn't exist
makedir(tpath);
while(!mtar_eof(&tar)) {
// then create every other subdir
p = tpath+pathlen;
*p = '/'; p++;
mtar_header(&tar, &header);
switch(header->type) {
case MTAR_TDIR:
if(header->path[0]!=0) { // subdir
const size_t subdirlen = strlen(header->path);
if(p-tpath+subdirlen>1023) return(MTAR_EOPENFAIL);
strcpy(p,header->path);
p += subdirlen;
*p = '/'; p++;
}
const size_t namelen = strlen(header->name);
if(p-tpath+namelen>1023) return(MTAR_EOPENFAIL);
strcpy(p,header->name);
makedir(tpath);
break;
}
mtar_next(&tar);
}
mtar_rewind(&tar);
while(!mtar_eof(&tar)) {
// and at last create the files
p = tpath+pathlen;
*p = '/'; p++;
mtar_header(&tar, &header);
switch(header->type) {
case MTAR_TREG:
if(header->path[0]!=0) { // subdir
const size_t subdirlen = strlen(header->path);
if(p-tpath+subdirlen>1023) return(MTAR_EOPENFAIL);
strcpy(p,header->path);
p += subdirlen;
*p = '/'; p++;
}
const size_t namelen = strlen(header->name);
if(p-tpath+namelen>1023) return(MTAR_EOPENFAIL);
strcpy(p,header->name);
FILE *fp = fopen(tpath,"w");
if(!fp) {
fprintf(stderr,
"Error open file for write: %s\n",
tpath);
perror("Reason: ");
return(MTAR_EWRITEFAIL);
}
fwrite(&tar.buffer[tar.iterator.cursor],
1,header->size,fp);
fclose(fp);
break;
}
mtar_next(&tar);
}
return(MTAR_ESUCCESS);
}

// gunzip and untar all in one
#include <tinf.h>
int untargz_to_path(const char *path, const uint8_t *buf,
const unsigned int len) {
return(0);
}


int mtar_load(mtar_t *tar, const char *name,
const uint8_t *buf, size_t size) {
int err = 0;
Expand Down Expand Up @@ -237,58 +338,3 @@ int mtar_entry_read(mtar_t *tar, void *ptr, int size)
tar->iterator.cursor += (size_t) size;
return size;
}

#include <sys/stat.h> // for mkdir(2)

// used by extract_embeddings(char *tmpdir)
int untar_to_path(const char *path, const uint8_t *buf,
const unsigned int len) {
int res;
mtar_t tar;
char tpath[512];
const size_t pathlen = strlen(path);
if(pathlen>100) return(MTAR_EFAILURE);
char *p;
const mtar_header_t *header = NULL;
strcpy(tpath, path);
res = mtar_load(&tar, path, buf, len);
if(res != MTAR_ESUCCESS) return(MTAR_EOPENFAIL);
while(!mtar_eof(&tar)) {
p = tpath+pathlen;
*p = '/'; p++;
mtar_header(&tar, &header);
if(header->path[0]!=0) { // subdir
const size_t subdirlen = strlen(header->path);
if(p-tpath+subdirlen>1023) return(MTAR_EOPENFAIL);
strcpy(p,header->path);
p += subdirlen;
*p = '/'; p++;
}
const size_t namelen = strlen(header->name);
if(p-tpath+namelen>1023) return(MTAR_EOPENFAIL);
strcpy(p,header->name);
switch(header->type) {
case MTAR_TDIR:
printf("untar_to_path mkdir %s (type %i)\n",
tpath,header->type);
mkdir(tpath,0755);
break;
case MTAR_TREG:
FILE *fp;
printf("untar_to_path file %s\n", tpath);
fp = fopen(tpath,"w");
if(!fp) {
fprintf(stderr,
"Error open file for write: %s",
strerror(errno));
return(MTAR_EWRITEFAIL);
}
fwrite(&tar.buffer[tar.iterator.cursor],
1,header->size,fp);
fclose(fp);
break;
}
mtar_next(&tar);
}
return(MTAR_ESUCCESS);
}
21 changes: 13 additions & 8 deletions test/muntar.bats
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ setup() {
bats_require_minimum_version 1.5.0
T="$BATS_TEST_DIRNAME"
TMP="$BATS_TEST_TMPDIR"
R=`pwd`
R=`pwd`
load "$T"/test_helper/bats_support/load
load "$T"/test_helper/bats_assert/load
load "$T"/test_helper/bats_file/load
tar -Hustar -cf examples.tar examples
tar --format ustar -cf ${TMP}/examples.tar examples
cd ${TMP}
xxd -i examples.tar > examples.c
gzip -c examples.tar > examples.tar.gz
xxd -i examples.tar.gz > examples_gzip.c
Expand All @@ -18,7 +19,7 @@ setup() {
@test "muntar list contents" {
cat << EOF > muntar_list.c
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <muntar.h>
extern unsigned char examples_tar[];
extern unsigned int examples_tar_len;
Expand All @@ -40,7 +41,7 @@ int main(int argc, char **argv) {
}
EOF
gcc -o muntar_list -I ${R}/src \
${R}/src/muntar.c ${R}/src/io.c examples.c muntar_list.c
${R}/src/muntar.c ${R}/src/io.c examples.c muntar_list.c
run ./muntar_list
assert_success
assert_line --partial "examples/"
Expand All @@ -63,11 +64,15 @@ int main(int argc, char **argv) {
}
EOF
gcc -o muntar_extract -I ${R}/src \
${R}/src/muntar.c ${R}/src/io.c examples.c muntar_extract.c
run ./muntar_extract extracted
>&3 cat extracted/examples/donut.c
${R}/src/muntar.c examples.c muntar_extract.c
run ./muntar_extract ${TMP}/extracted
>&3 cat ${TMP}/extracted/examples/donut.c
assert_success
assert_line --partial "untar_to_path file extracted/examples/donut.c"
# assert_file_size_equals ${TMP}/extracted/examples/donut.c \
# `ls -l ${R}/examples/donut.c | cut -d' ' -f5`
l=`sha256sum ${TMP}/extracted/examples/donut.c | cut -d' ' -f1`
r=`sha256sum ${R}/examples/donut.c | cut -d' ' -f1`
assert_equal $l $r
}

@test "tinf decompress gzip" {
Expand Down

0 comments on commit ba51b90

Please sign in to comment.