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 20:52:35 +0300
committerAidan MacDonald <amachronic@protonmail.com>2021-11-05 02:50:26 +0300
commit33a25800d55f2d15357832af392528bb860aa3bf (patch)
treee11a10a724a46fe9f88cdff3095eb8576609164c
parentff8eddfb9c6b0d1ada8dd325b34baa742e87aba5 (diff)
Remove mtar_raw_header_t
Prefer accessing the raw data as a plain char array, this makes the code immune to bugs induced by a compiler adding padding between struct fields. (The alternative is to add ugliness to the header to ensure the struct is packed.)
-rw-r--r--src/microtar.c118
-rw-r--r--src/microtar.h16
2 files changed, 65 insertions, 69 deletions
diff --git a/src/microtar.c b/src/microtar.c
index 2f5f781..f14e5e5 100644
--- a/src/microtar.c
+++ b/src/microtar.c
@@ -82,21 +82,6 @@ static unsigned round_up(unsigned n, unsigned incr)
return n + (incr - n % incr) % incr;
}
-static unsigned checksum(const mtar_raw_header_t* rh)
-{
- unsigned i;
- unsigned char* p = (unsigned char*) rh;
- unsigned res = 256;
-
- for(i = 0; i < offsetof(mtar_raw_header_t, checksum); i++)
- res += p[i];
-
- for(i = offsetof(mtar_raw_header_t, type); i < sizeof(*rh); i++)
- res += p[i];
-
- return res;
-}
-
static int tread(mtar_t* tar, void* data, unsigned size)
{
int err = tar->ops->read(tar->stream, data, size);
@@ -104,7 +89,6 @@ static int tread(mtar_t* tar, void* data, unsigned size)
return err;
}
-
static int twrite(mtar_t* tar, const void* data, unsigned size)
{
int err = tar->ops->write(tar->stream, data, size);
@@ -119,7 +103,6 @@ static int write_null_bytes(mtar_t* tar, int n)
for(i = 0; i < n; i++) {
err = twrite(tar, &nul, 1);
-
if(err)
return err;
}
@@ -127,74 +110,101 @@ static int write_null_bytes(mtar_t* tar, int n)
return MTAR_ESUCCESS;
}
-static int raw_to_header(mtar_header_t* h, const mtar_raw_header_t* rh)
+enum {
+ NAME_OFF = 0, NAME_LEN = 100,
+ MODE_OFF = NAME_OFF+NAME_LEN, MODE_LEN = 8,
+ OWNER_OFF = MODE_OFF+MODE_LEN, OWNER_LEN = 8,
+ GROUP_OFF = OWNER_OFF+OWNER_LEN, GROUP_LEN = 8,
+ SIZE_OFF = GROUP_OFF+GROUP_LEN, SIZE_LEN = 12,
+ MTIME_OFF = SIZE_OFF+SIZE_LEN, MTIME_LEN = 12,
+ CHKSUM_OFF = MTIME_OFF+MTIME_LEN, CHKSUM_LEN = 8,
+ TYPE_OFF = CHKSUM_OFF+CHKSUM_LEN,
+ LINKNAME_OFF = TYPE_OFF+1, LINKNAME_LEN = 100,
+
+ HEADER_LEN = 512,
+};
+
+static unsigned checksum(const char* raw)
{
- unsigned chksum1, chksum2;
+ unsigned i;
+ unsigned char* p = (unsigned char*)raw;
+ unsigned res = 256;
+
+ for(i = 0; i < CHKSUM_OFF; i++)
+ res += p[i];
+ for(i = TYPE_OFF; i < HEADER_LEN; i++)
+ res += p[i];
+
+ return res;
+}
+
+static int raw_to_header(mtar_header_t* h, const char* raw)
+{
+ unsigned chksum;
int rc;
/* If the checksum starts with a null byte we assume the record is NULL */
- if(*rh->checksum == '\0')
+ if(raw[CHKSUM_OFF] == '\0')
return MTAR_ENULLRECORD;
- /* Build and compare checksum */
- chksum1 = checksum(rh);
- if((rc = parse_octal(rh->checksum, sizeof(rh->checksum), &chksum2)))
- return rc;
- if(chksum1 != chksum2)
+ /* Compare the checksum */
+ if((rc = parse_octal(&raw[CHKSUM_OFF], CHKSUM_LEN, &chksum)))
+ return rc;
+ if(chksum != checksum(raw))
return MTAR_EBADCHKSUM;
/* Load raw header into header */
- if((rc = parse_octal(rh->mode, sizeof(rh->mode), &h->mode)))
+ if((rc = parse_octal(&raw[MODE_OFF], MODE_LEN, &h->mode)))
return rc;
- if((rc = parse_octal(rh->owner, sizeof(rh->owner), &h->owner)))
+ if((rc = parse_octal(&raw[OWNER_OFF], OWNER_LEN, &h->owner)))
return rc;
- if((rc = parse_octal(rh->group, sizeof(rh->group), &h->group)))
+ if((rc = parse_octal(&raw[GROUP_OFF], GROUP_LEN, &h->group)))
return rc;
- if((rc = parse_octal(rh->size, sizeof(rh->size), &h->size)))
+ if((rc = parse_octal(&raw[SIZE_OFF], SIZE_LEN, &h->size)))
return rc;
- if((rc = parse_octal(rh->mtime, sizeof(rh->mtime), &h->mtime)))
+ if((rc = parse_octal(&raw[MTIME_OFF], MTIME_LEN, &h->mtime)))
return rc;
- h->type = rh->type;
+ h->type = raw[TYPE_OFF];
- memcpy(h->name, rh->name, sizeof(rh->name));
+ memcpy(h->name, &raw[NAME_OFF], NAME_LEN);
h->name[sizeof(h->name) - 1] = 0;
- memcpy(h->linkname, rh->linkname, sizeof(rh->linkname));
+ memcpy(h->linkname, &raw[LINKNAME_OFF], LINKNAME_LEN);
h->linkname[sizeof(h->linkname) - 1] = 0;
return MTAR_ESUCCESS;
}
-static int header_to_raw(mtar_raw_header_t* rh, const mtar_header_t* h)
+static int header_to_raw(char* raw, const mtar_header_t* h)
{
unsigned chksum;
int rc;
- /* Load header into raw header */
- memset(rh, 0, sizeof(*rh));
+ memset(raw, 0, HEADER_LEN);
- if((rc = print_octal(rh->mode, sizeof(rh->mode), h->mode)))
+ /* Load header into raw header */
+ if((rc = print_octal(&raw[MODE_OFF], MODE_LEN, h->mode)))
return rc;
- if((rc = print_octal(rh->owner, sizeof(rh->owner), h->owner)))
+ if((rc = print_octal(&raw[OWNER_OFF], OWNER_LEN, h->owner)))
return rc;
- if((rc = print_octal(rh->group, sizeof(rh->group), h->group)))
+ if((rc = print_octal(&raw[GROUP_OFF], GROUP_LEN, h->group)))
return rc;
- if((rc = print_octal(rh->size, sizeof(rh->size), h->size)))
+ if((rc = print_octal(&raw[SIZE_OFF], SIZE_LEN, h->size)))
return rc;
- if((rc = print_octal(rh->mtime, sizeof(rh->mtime), h->mtime)))
+ if((rc = print_octal(&raw[MTIME_OFF], MTIME_LEN, h->mtime)))
return rc;
- rh->type = h->type ? h->type : MTAR_TREG;
- strncpy(rh->name, h->name, sizeof(rh->name));
- strncpy(rh->linkname, h->linkname, sizeof(rh->linkname));
+ raw[TYPE_OFF] = h->type ? h->type : MTAR_TREG;
+ strncpy(&raw[NAME_OFF], h->name, NAME_LEN);
+ strncpy(&raw[LINKNAME_OFF], h->linkname, NAME_LEN);
/* Calculate and write checksum */
- chksum = checksum(rh);
- if((rc = print_octal(rh->checksum, 7, chksum)))
+ chksum = checksum(raw);
+ if((rc = print_octal(&raw[CHKSUM_OFF], CHKSUM_LEN-1, chksum)))
return rc;
- rh->checksum[7] = ' ';
+ raw[CHKSUM_OFF + CHKSUM_LEN - 1] = ' ';
return MTAR_ESUCCESS;
}
@@ -261,7 +271,7 @@ int mtar_next(mtar_t* tar)
return err;
/* Seek to next record */
- n = round_up(tar->header.size, 512) + sizeof(mtar_raw_header_t);
+ n = round_up(tar->header.size, 512) + HEADER_LEN;
return mtar_seek(tar, tar->pos + n);
}
@@ -302,7 +312,7 @@ int mtar_read_header(mtar_t* tar, mtar_header_t* h)
tar->last_header = tar->pos;
/* Read raw header */
- err = tread(tar, &tar->raw_header, sizeof(tar->raw_header));
+ err = tread(tar, tar->buffer, HEADER_LEN);
if(err)
return err;
@@ -312,7 +322,7 @@ int mtar_read_header(mtar_t* tar, mtar_header_t* h)
return err;
/* Load raw header into header struct and return */
- return raw_to_header(h, &tar->raw_header);
+ return raw_to_header(h, tar->buffer);
}
int mtar_read_data(mtar_t* tar, void* ptr, unsigned size)
@@ -329,7 +339,7 @@ int mtar_read_data(mtar_t* tar, void* ptr, unsigned size)
return err;
/* Seek past header and init remaining data */
- err = mtar_seek(tar, tar->pos + sizeof(mtar_raw_header_t));
+ err = mtar_seek(tar, tar->pos + HEADER_LEN);
if(err)
return err;
@@ -358,9 +368,9 @@ int mtar_read_data(mtar_t* tar, void* ptr, unsigned size)
int mtar_write_header(mtar_t* tar, const mtar_header_t* h)
{
/* Build raw header and write */
- header_to_raw(&tar->raw_header, h);
+ header_to_raw(tar->buffer, h);
tar->remaining_data = h->size;
- return twrite(tar, &tar->raw_header, sizeof(tar->raw_header));
+ return twrite(tar, tar->buffer, HEADER_LEN);
}
int mtar_write_file_header(mtar_t* tar, const char* name, unsigned size)
@@ -423,5 +433,5 @@ int mtar_write_data(mtar_t* tar, const void* data, unsigned size)
int mtar_finalize(mtar_t* tar)
{
/* Write two NULL records */
- return write_null_bytes(tar, sizeof(mtar_raw_header_t) * 2);
+ return write_null_bytes(tar, HEADER_LEN * 2);
}
diff --git a/src/microtar.h b/src/microtar.h
index b24c8dc..f1c2270 100644
--- a/src/microtar.h
+++ b/src/microtar.h
@@ -55,7 +55,6 @@ enum {
};
typedef struct mtar_header mtar_header_t;
-typedef struct mtar_raw_header mtar_raw_header_t;
typedef struct mtar mtar_t;
typedef struct mtar_ops mtar_ops_t;
@@ -70,19 +69,6 @@ struct mtar_header {
char linkname[101];
};
-struct mtar_raw_header {
- char name[100];
- char mode[8];
- char owner[8];
- char group[8];
- char size[12];
- char mtime[12];
- char checksum[8];
- char type;
- char linkname[100];
- char _padding[255];
-};
-
struct mtar_ops {
int(*read)(void* stream, void* data, unsigned size);
int(*write)(void* stream, const void* data, unsigned size);
@@ -98,7 +84,7 @@ struct mtar {
unsigned remaining_data;
unsigned last_header;
mtar_header_t header;
- mtar_raw_header_t raw_header;
+ char buffer[512];
};
const char* mtar_strerror(int err);