Skip to content

Commit

Permalink
(Re)add support for tar-writing to microtar
Browse files Browse the repository at this point in the history
  • Loading branch information
milot-mirdita committed Sep 20, 2022
1 parent fea8d20 commit dcd180b
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 4 deletions.
92 changes: 90 additions & 2 deletions lib/microtar/microtar.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ const char* mtar_strerror(int err) {
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";
Expand All @@ -72,6 +73,11 @@ const char* mtar_strerror(int err) {
return "unknown error";
}

static int file_write(mtar_t *tar, const void *data, size_t size) {
size_t res = fwrite(data, 1, size, (FILE*)tar->stream);
return (res == size) ? MTAR_ESUCCESS : MTAR_EWRITEFAIL;
}

static int file_read(mtar_t *tar, void *data, size_t size) {
size_t res = fread(data, 1, size, (FILE*)tar->stream);
return (res == size) ? MTAR_ESUCCESS : MTAR_EREADFAIL;
Expand All @@ -87,15 +93,19 @@ static int file_close(mtar_t *tar) {
return MTAR_ESUCCESS;
}

int mtar_open(mtar_t *tar, const char *filename) {
int mtar_open(mtar_t *tar, const char *filename, const char* mode) {
/* Init tar struct and functions */
memset(tar, 0, sizeof(*tar));
tar->read = file_read;
tar->write = file_write;
tar->seek = file_seek;
tar->close = file_close;

/* Open file */
tar->stream = fopen(filename, "rb");
if ( strchr(mode, 'r') ) mode = "rb";
if ( strchr(mode, 'w') ) mode = "wb";
if ( strchr(mode, 'a') ) mode = "ab";
tar->stream = fopen(filename, mode);
if (!tar->stream) {
return MTAR_EOPENFAIL;
}
Expand Down Expand Up @@ -173,3 +183,81 @@ int mtar_read_data(mtar_t *tar, void *ptr, size_t size) {
}
return MTAR_ESUCCESS;
}

int mtar_write_header(mtar_t *tar, const mtar_header_t *h) {
/* Build raw header and write */
mtar_raw_header_t rh;
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 */
unsigned chksum = checksum(&rh);
sprintf(rh.checksum, "%06o", chksum);
rh.checksum[7] = ' ';

tar->remaining_data = h->size;
int err = tar->write(tar, &rh, sizeof(rh));
tar->pos += sizeof(rh);
return err;
}

int mtar_write_file_header(mtar_t *tar, const char *name, size_t size) {
mtar_header_t h;
/* Build header */
memset(&h, 0, sizeof(h));
strcpy(h.name, name);
h.size = size;
h.type = MTAR_TREG;
h.mode = 0644;
/* 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 */
memset(&h, 0, sizeof(h));
strcpy(h.name, name);
h.type = MTAR_TDIR;
h.mode = 0755;
/* Write header */
return mtar_write_header(tar, &h);
}

static int write_null_bytes(mtar_t *tar, int n) {
char nul = '\0';
for (int i = 0; i < n; i++) {
int err = tar->write(tar, &nul, 1);
tar->pos++;
if (err) {
return err;
}
}
return MTAR_ESUCCESS;
}

int mtar_write_data(mtar_t *tar, const void *data, size_t size) {
/* Write data */
int err = tar->write(tar, data, size);
tar->pos += 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_write_finalize(mtar_t *tar) {
/* Write two NULL records */
return write_null_bytes(tar, sizeof(mtar_raw_header_t) * 2);
}
12 changes: 11 additions & 1 deletion lib/microtar/microtar.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ enum {
MTAR_EFAILURE = -1,
MTAR_EOPENFAIL = -2,
MTAR_EREADFAIL = -3,
MTAR_EWRITEFAIL = -4,
MTAR_ESEEKFAIL = -5,
MTAR_EBADCHKSUM = -6,
MTAR_ENULLRECORD = -7,
Expand Down Expand Up @@ -58,23 +59,32 @@ typedef struct mtar_t mtar_t;

struct mtar_t {
int (*read)(mtar_t *tar, void *data, size_t size);
int (*write)(mtar_t *tar, const void *data, size_t size);
int (*seek)(mtar_t *tar, long pos, int whence);
int (*close)(mtar_t *tar);
void *stream;
size_t curr_size;
size_t pos;
size_t remaining_data;
int isFinished;
};


const char* mtar_strerror(int err);

int mtar_open(mtar_t *tar, const char *filename);
int mtar_open(mtar_t *tar, const char *filename, const char* mode);
int mtar_close(mtar_t *tar);

int mtar_read_header(mtar_t *tar, mtar_header_t *h);
int mtar_read_data(mtar_t *tar, void *ptr, size_t size);
int mtar_skip_data(mtar_t *tar);

int mtar_write_header(mtar_t *tar, const mtar_header_t *h);
int mtar_write_file_header(mtar_t *tar, const char *name, size_t size);
int mtar_write_dir_header(mtar_t *tar, const char *name);
int mtar_write_data(mtar_t *tar, const void *data, size_t size);
int mtar_write_finalize(mtar_t *tar);

#ifdef __cplusplus
}
#endif
Expand Down
2 changes: 1 addition & 1 deletion src/util/tar2db.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ int tar2db(int argc, const char **argv, const Command& command) {
EXIT(EXIT_FAILURE);
#endif
} else {
if (mtar_open(&tar, filenames[i].c_str()) != MTAR_ESUCCESS) {
if (mtar_open(&tar, filenames[i].c_str(), "r") != MTAR_ESUCCESS) {
Debug(Debug::ERROR) << "Cannot open file " << filenames[i] << "\n";
EXIT(EXIT_FAILURE);
}
Expand Down

0 comments on commit dcd180b

Please sign in to comment.