Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/amachronic/microtar.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAidan MacDonald <amachronic@protonmail.com>2021-11-06 16:55:18 +0300
committerAidan MacDonald <amachronic@protonmail.com>2021-11-06 16:55:18 +0300
commita88dfe430bb40703a172e580156de031ccbd5987 (patch)
treec9bb5e897af800542a231b80ae8b19963417c74e
parentfda3309e0b1c9591e766c38dfbb7556ee9eb7467 (diff)
Bugfixes and rework write API
The code ends up simpler by having callers explicitly end the data stream and finalize the archive instead of trying to do it implicitly. Also fix multiple write related bugs.
-rw-r--r--README.md24
-rw-r--r--src/microtar.c63
-rw-r--r--src/microtar.h2
3 files changed, 35 insertions, 54 deletions
diff --git a/README.md b/README.md
index 8d8a02b..7526ef0 100644
--- a/README.md
+++ b/README.md
@@ -178,29 +178,25 @@ included in the interest of simplicity.
The main functions are:
-- `mtar_write_header(tar, header)` writes out a new record. The amount
- of data that follows is dictated by `header->size` and you will have
- to write it out before moving to the next record.
+- `mtar_write_header(tar, header)` writes out the header for a new member.
+ The amount of data that follows is dictated by `header->size` and you
+ will have to write it out before moving to the next member.
- `mtar_write_data(tar, buf, count)` will write up to `count` bytes from
- `buf` into the current record. Returns the number of bytes actually
+ `buf` to the current member's data. Returns the number of bytes actually
written or a negative error code. If you provide too much data, a short
count is returned.
-- `mtar_end_record(tar)` will end the current record. It will complain
+- `mtar_end_data(tar)` will end the current member. It will complain
if you did not write the correct amount data provided in the header.
+ This must be called before writing the next header.
-- `mtar_finalize(tar)` is called after you have written all records to
+- `mtar_finalize(tar)` is called after you have written all members to
the archive. It writes out some null records which mark the end of the
- archive, so you cannot write any more records after calling this.
+ archive, so you cannot write any more archive members after this.
-It isn't necessary to call `mtar_end_record()` explicitly since it will
-be called automatically by `mtar_write_header()` and `mtar_finalize()`.
-Similarily, `mtar_finalize()` is implicitly called by `mtar_close()` if
-you don't do so yourself.
-
-Also note that `mtar_close()` can fail independently if there was a problem
-flushing buffered data to disk, so its return value should always be checked.
+Note that `mtar_close()` can fail if there was a problem flushing buffered
+data to disk, so its return value should always be checked.
## Error handling
diff --git a/src/microtar.c b/src/microtar.c
index 193c3c8..e9a84ef 100644
--- a/src/microtar.c
+++ b/src/microtar.c
@@ -280,23 +280,6 @@ static unsigned data_end_pos(const mtar_t* tar)
return data_beg_pos(tar) + tar->header.size;
}
-static int ensure_eof(mtar_t* tar)
-{
- if(!(tar->state & S_WROTE_DATA) || (tar->state & S_WROTE_DATA_EOF))
- return MTAR_ESUCCESS;
-
- /* make sure the caller wrote out the expected amount of data */
- if(tar->pos < data_end_pos(tar))
- return MTAR_ETOOSHORT;
-
- int err = write_null_bytes(tar, round_up_512(tar->pos) - tar->pos);
- if(err)
- return err;
-
- tar->state |= S_WROTE_DATA_EOF;
- return MTAR_ESUCCESS;
-}
-
const char* mtar_strerror(int err)
{
switch(err) {
@@ -328,16 +311,10 @@ void mtar_init(mtar_t* tar, int access, const mtar_ops_t* ops, void* stream)
int mtar_close(mtar_t* tar)
{
- int err1 = tar->access == MTAR_WRITE ? mtar_finalize(tar) : MTAR_ESUCCESS;
- int err2 = tar->ops->close(tar->stream);
-
+ int err = tar->ops->close(tar->stream);
tar->ops = NULL;
tar->stream = NULL;
-
- if(err1)
- return err1;
- else
- return err2;
+ return err;
}
int mtar_is_open(mtar_t* tar)
@@ -498,18 +475,16 @@ int mtar_write_header(mtar_t* tar, const mtar_header_t* h)
{
if(tar->access != MTAR_WRITE)
return MTAR_EAPI;
- if(tar->state & S_WROTE_FINALIZE)
+ if(((tar->state & S_WROTE_DATA) && !(tar->state & S_WROTE_DATA_EOF)) ||
+ (tar->state & S_WROTE_FINALIZE))
return MTAR_EAPI;
- int err = ensure_eof(tar);
- if(err)
- return err;
-
tar->state &= ~(S_WROTE_HEADER | S_WROTE_DATA | S_WROTE_DATA_EOF);
+ tar->header_pos = tar->pos;
if(h != &tar->header)
tar->header = *h;
- err = header_to_raw(tar->buffer, h);
+ int err = header_to_raw(tar->buffer, h);
if(err)
return err;
@@ -561,7 +536,9 @@ int mtar_write_dir_header(mtar_t* tar, const char* name)
int mtar_write_data(mtar_t* tar, const void* ptr, unsigned size)
{
- if(!(tar->state & S_WROTE_HEADER) || (tar->state & S_WROTE_FINALIZE))
+ if(!(tar->state & S_WROTE_HEADER) ||
+ (tar->state & S_WROTE_DATA_EOF) ||
+ (tar->state & S_WROTE_FINALIZE))
return MTAR_EAPI;
/* don't allow writing more than was specified in the header,
@@ -570,7 +547,7 @@ int mtar_write_data(mtar_t* tar, const void* ptr, unsigned size)
if(tar->pos >= data_end)
return 0;
- unsigned data_left = tar->pos - data_end;
+ unsigned data_left = data_end - tar->pos;
if(size > data_left)
size = data_left;
@@ -578,12 +555,24 @@ int mtar_write_data(mtar_t* tar, const void* ptr, unsigned size)
return twrite(tar, ptr, size);
}
-int mtar_end_record(mtar_t* tar)
+int mtar_end_data(mtar_t* tar)
{
if(tar->access != MTAR_WRITE)
return MTAR_EAPI;
+ if((tar->state & S_WROTE_DATA_EOF) ||
+ (tar->state & S_WROTE_FINALIZE))
+ return MTAR_EAPI;
+
+ /* make sure the caller wrote out the expected amount of data */
+ if(tar->pos < data_end_pos(tar))
+ return MTAR_ETOOSHORT;
- return ensure_eof(tar);
+ int err = write_null_bytes(tar, round_up_512(tar->pos) - tar->pos);
+ if(err)
+ return err;
+
+ tar->state |= S_WROTE_DATA_EOF;
+ return MTAR_ESUCCESS;
}
int mtar_finalize(mtar_t* tar)
@@ -593,10 +582,6 @@ int mtar_finalize(mtar_t* tar)
if(tar->state & S_WROTE_FINALIZE)
return MTAR_ESUCCESS;
- int err = ensure_eof(tar);
- if(err)
- return err;
-
tar->state |= S_WROTE_FINALIZE;
return write_null_bytes(tar, 1024);
}
diff --git a/src/microtar.h b/src/microtar.h
index 7051c18..6197a3d 100644
--- a/src/microtar.h
+++ b/src/microtar.h
@@ -121,7 +121,7 @@ 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* ptr, unsigned size);
-int mtar_end_record(mtar_t* tar);
+int mtar_end_data(mtar_t* tar);
int mtar_finalize(mtar_t* tar);
#ifdef __cplusplus