More optimization and heap elimination

This commit is contained in:
apio 2022-12-25 13:31:11 +01:00
parent 555059a742
commit ab5ed0eaf0
Signed by: apio
GPG Key ID: B8A7D06E42258954
2 changed files with 14 additions and 24 deletions

View File

@ -4,9 +4,7 @@ Tiny and easy-to-use C library to parse tar (specifically, the newer [USTAR](htt
No third-party dependencies, only a minimally capable standard C library (file IO, number parsing, malloc() and friends, string functions). No third-party dependencies, only a minimally capable standard C library (file IO, number parsing, malloc() and friends, string functions).
Aims to be as portable between systems as possible (has its own implementation of some non-standard functions, such as [strlcpy](https://linux.die.net/man/3/strlcpy), [strndup](https://linux.die.net/man/3/strndup) or [basename](https://linux.die.net/man/3/basename)). Aims to be bloat-free (currently less than 500 LoC), fast and optimized, and as portable between systems as possible (has its own implementation of some non-standard functions, such as [strlcpy](https://linux.die.net/man/3/strlcpy) or [basename](https://linux.die.net/man/3/basename)).
Very minimal and bloat-free, currently less than 500 lines :)
Does not include support for compressed archives. You'll have to pass those through another program or library to decompress them before minitar can handle them. Does not include support for compressed archives. You'll have to pass those through another program or library to decompress them before minitar can handle them.

View File

@ -45,19 +45,6 @@ static size_t minitar_strlcpy(char* dest, const char* src, size_t size)
return full_len; return full_len;
} }
// strdup() but copies at most max bytes of orig, always null-terminating the result. This function is non-standard and
// as such, we provide our own implementation, to be as portable as possible.
// https://linux.die.net/man/3/strndup
static char* minitar_strndup(const char* orig, size_t max)
{
size_t len = strnlen(orig, max);
char* ptr =
calloc(len + 1, 1); // Use calloc so everything is automatically zeroed and we get a null-terminator for free :)
if (!ptr) return NULL;
for (size_t i = 0; i < len; ++i) { *(ptr + i) = *(orig + i); }
return ptr;
}
static char dot[] = "."; static char dot[] = ".";
// POSIX function to extract the basename from a path. Not present on non-POSIX, but since paths inside a tar archive // POSIX function to extract the basename from a path. Not present on non-POSIX, but since paths inside a tar archive
@ -101,6 +88,17 @@ static size_t minitar_align_down_to_block_size(size_t size)
return size - (size % 512); return size - (size % 512);
} }
// Return a static string formed by 'size' bytes copied from str, and a null terminator. This function is useful for
// when you have a fixed-size field without a null-terminator, and you need a null-terminated string to pass to a
// library function. The pointer returned WILL be overwritten by subsequent calls to this function.
static char* minitar_static_dup(const char* str, size_t size)
{
static char result[1024];
memcpy(result, str, size);
result[size] = 0;
return result;
}
size_t minitar_align_up_to_block_size(size_t size) size_t minitar_align_up_to_block_size(size_t size)
{ {
return minitar_is_aligned_to_block_size(size) ? size : minitar_align_down_to_block_size(size) + 512; return minitar_is_aligned_to_block_size(size) ? size : minitar_align_down_to_block_size(size) + 512;
@ -144,17 +142,11 @@ void minitar_parse_metadata_from_tar_header(const struct tar_header* hdr, struct
// FIXME: Maybe avoid heap allocations (strndup) for simply parsing non-null-terminated fields? // FIXME: Maybe avoid heap allocations (strndup) for simply parsing non-null-terminated fields?
char* sizeptr = minitar_strndup( char* sizeptr = minitar_static_dup(hdr->size, 12);
hdr->size, 12); // The hdr->size field is not null-terminated, yet strndup returns a null-terminated string.
if (!sizeptr) minitar_panic("Failed to allocate memory");
metadata->size = (size_t)strtoull(sizeptr, NULL, 8); metadata->size = (size_t)strtoull(sizeptr, NULL, 8);
free(sizeptr);
char* timeptr = minitar_strndup( char* timeptr = minitar_static_dup(hdr->mtime, 12);
hdr->mtime, 12); // The hdr->mtime field is not null-terminated, yet strndup returns a null-terminated string.
if (!timeptr) minitar_panic("Failed to allocate memory");
metadata->mtime = (time_t)strtoull(timeptr, NULL, 8); metadata->mtime = (time_t)strtoull(timeptr, NULL, 8);
free(timeptr);
// The type is stored as a character instead of an integer. // The type is stored as a character instead of an integer.