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-04 23:07:31 +0300
committerAidan MacDonald <amachronic@protonmail.com>2021-11-05 03:24:35 +0300
commit348f4c8aa4a0ffa041f6cef9a1f2eb0e57681098 (patch)
treedc336a6f964270d9240ab05aa54ddd83bb13e9a3
parente53e099d41eb0b069300de80a22cc9cda579df82 (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.c46
-rw-r--r--src/microtar.h12
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