diff options
author | Aidan MacDonald <amachronic@protonmail.com> | 2021-11-04 23:07:31 +0300 |
---|---|---|
committer | Aidan MacDonald <amachronic@protonmail.com> | 2021-11-05 03:24:35 +0300 |
commit | 348f4c8aa4a0ffa041f6cef9a1f2eb0e57681098 (patch) | |
tree | dc336a6f964270d9240ab05aa54ddd83bb13e9a3 | |
parent | e53e099d41eb0b069300de80a22cc9cda579df82 (diff) |
Add mtar_seek_data()
This allows users to seek within a file without accidentally
skipping over the file's boundaries.
-rw-r--r-- | src/microtar.c | 46 | ||||
-rw-r--r-- | src/microtar.h | 12 |
2 files changed, 52 insertions, 6 deletions
diff --git a/src/microtar.c b/src/microtar.c index 5ae7eeb..d304e6d 100644 --- a/src/microtar.c +++ b/src/microtar.c @@ -244,9 +244,14 @@ static int ensure_header(mtar_t* tar) return MTAR_ESUCCESS; } +static unsigned data_beg_pos(const mtar_t* tar) +{ + return tar->header_pos + HEADER_LEN; +} + static unsigned data_end_pos(const mtar_t* tar) { - return tar->header_pos + HEADER_LEN + tar->header.size; + return data_beg_pos(tar) + tar->header.size; } const char* mtar_strerror(int err) @@ -373,6 +378,45 @@ int mtar_read_data(mtar_t* tar, void* ptr, unsigned size) return (int)size; } +int mtar_seek_data(mtar_t* tar, int offset, int whence) +{ + if(!(tar->state & S_HEADER_VALID)) + return MTAR_EAPI; + + unsigned data_beg = data_beg_pos(tar); + unsigned data_end = data_end_pos(tar); + unsigned newpos; + + switch(whence) { + case SEEK_SET: + if(offset < 0) + return MTAR_ESEEKRANGE; + + newpos = data_beg + offset; + break; + + case SEEK_CUR: + if((offset > 0 && (unsigned) offset > data_end - tar->pos) || + (offset < 0 && (unsigned)-offset > tar->pos - data_beg)) + return MTAR_ESEEKRANGE; + + newpos = tar->pos + offset; + break; + + case SEEK_END: + if(offset > 0) + return MTAR_ESEEKRANGE; + + newpos = data_end + offset; + break; + + default: + return MTAR_EAPI; + } + + return tseek(tar, newpos); +} + int mtar_eof_data(mtar_t* tar) { /* API usage error, but just claim EOF. */ diff --git a/src/microtar.h b/src/microtar.h index b3ff05f..b6de153 100644 --- a/src/microtar.h +++ b/src/microtar.h @@ -38,11 +38,12 @@ enum { MTAR_EREADFAIL = -3, MTAR_EWRITEFAIL = -4, MTAR_ESEEKFAIL = -5, - MTAR_EBADCHKSUM = -6, - MTAR_ENULLRECORD = -7, - MTAR_ENOTFOUND = -8, - MTAR_EOVERFLOW = -9, - MTAR_EAPI = -10, + MTAR_ESEEKRANGE = -6, + MTAR_EBADCHKSUM = -7, + MTAR_ENULLRECORD = -9, + MTAR_ENOTFOUND = -10, + MTAR_EOVERFLOW = -11, + MTAR_EAPI = -12, MTAR_ELAST = MTAR_EAPI, }; @@ -106,6 +107,7 @@ int mtar_next(mtar_t* tar); int mtar_foreach(mtar_t* tar, mtar_foreach_cb cb, void* arg); int mtar_find(mtar_t* tar, const char* name); int mtar_read_data(mtar_t* tar, void* ptr, unsigned size); +int mtar_seek_data(mtar_t* tar, int offset, int whence); int mtar_eof_data(mtar_t* tar); #ifdef __cplusplus |