From fd85cf1c6a5c96bbc3b848188f07a0cea85f8f87 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 23 Nov 2022 18:32:10 +0100 Subject: [PATCH] Full path is now metadata->path and basename metadata->name Shouldn't have rushed to 1.0.0 so quickly. Oh well, I guess I can allow 1.1.0... --- CMakeLists.txt | 2 +- README.md | 14 +++++++++++--- minitar.h | 4 +++- src/tar.c | 14 ++++++++++++++ src/util.c | 25 +++++++++++++++++-------- 5 files changed, 46 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cb6cbd1..ddd4e0e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.8..3.22) -project(minitar LANGUAGES C VERSION 1.0.0) +project(minitar LANGUAGES C VERSION 1.1.0) set(SOURCES src/tar.c diff --git a/README.md b/README.md index ab1e6ce..8d7771d 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ int main(int argc, char** argv) do { entry = minitar_read_entry(mp); if(entry) { - printf("%s\n", entry->metadata.name); + printf("%s\n", entry->metadata.path); minitar_free_entry(entry); } } while(entry); @@ -75,10 +75,16 @@ The state of `mp` after `minitar_find_by_name()` returns is unspecified, but a s In order to perform other minitar operations on the archive, `minitar_rewind()` should probably be called first, to get a known state. +### minitar_find_by_path +`struct minitar_entry* minitar_find_by_path(struct minitar* mp, const char* path)` + +Same as `minitar_find_by_name()`, but matches the full path inside the archive instead of the file name. + + ### minitar_find_any_of `struct minitar_entry* minitar_find_any_of(struct minitar* mp, enum minitar_file_type type)` -Does the same thing as `minitar_find_by_name()`, but matches the file type instead of the name. As with `minitar_find_by_name()`, this function starts searching from the current archive position and calling it in a loop until it returns NULL will return all matching entries. +Same as `minitar_find_by_name()`, but matches the file type instead of the name. As with `minitar_find_by_name()`, this function starts searching from the current archive position and calling it in a loop until it returns NULL will return all matching entries. ### minitar_read_contents `size_t minitar_read_contents(struct minitar* mp, struct minitar_entry* entry, char* buf, size_t max)` @@ -122,7 +128,9 @@ Other file types supported in tar archives, such as FIFOs or symlinks, are not s This structure represents an entry's metadata, with the following fields: -`name`: A string representing the full path of the entry within the archive. (`char[]`) +`path`: A string representing the full path of the entry within the archive. (`char[]`) + +`name`: A string representing the base name of the entry (the last component of its path). (`char[]`) `mode`: An integer representing the permissions of the entry. (`mode_t`) diff --git a/minitar.h b/minitar.h index 381b277..1fa47c5 100644 --- a/minitar.h +++ b/minitar.h @@ -22,7 +22,8 @@ enum minitar_file_type struct minitar_entry_metadata { - char name[257]; + char path[257]; + char name[128]; mode_t mode; uid_t uid; gid_t gid; @@ -49,6 +50,7 @@ extern "C" void minitar_free_entry(struct minitar_entry* entry); void minitar_rewind(struct minitar* mp); struct minitar_entry* minitar_find_by_name(struct minitar* mp, const char* name); + struct minitar_entry* minitar_find_by_path(struct minitar* mp, const char* path); struct minitar_entry* minitar_find_any_of(struct minitar* mp, enum minitar_file_type type); int minitar_close(struct minitar* mp); size_t minitar_read_contents(struct minitar* mp, struct minitar_entry* entry, char* buf, size_t max); diff --git a/src/tar.c b/src/tar.c index cbf1f12..75bea42 100644 --- a/src/tar.c +++ b/src/tar.c @@ -92,6 +92,20 @@ struct minitar_entry* minitar_find_by_name(struct minitar* mp, const char* name) return NULL; } +struct minitar_entry* minitar_find_by_path(struct minitar* mp, const char* path) +{ + struct minitar_entry* entry; + do { + entry = minitar_read_entry(mp); + if (entry) + { + if (!strcmp(entry->metadata.path, path)) return entry; + minitar_free_entry(entry); + } + } while (entry); + return NULL; +} + struct minitar_entry* minitar_find_any_of(struct minitar* mp, enum minitar_file_type type) { struct minitar_entry* entry; diff --git a/src/util.c b/src/util.c index d9d57e8..1b60f1c 100644 --- a/src/util.c +++ b/src/util.c @@ -3,6 +3,7 @@ #define _IN_MINITAR #include "minitar.h" #include "tar.h" +#include #include #include #include @@ -58,30 +59,38 @@ void minitar_parse_metadata_from_tar_header(const struct tar_header* hdr, struct { if (!strlen(hdr->prefix)) { - minitar_strlcpy(metadata->name, hdr->name, 100); - metadata->name[100] = '\0'; + size_t size = minitar_strlcpy(metadata->path, hdr->name, 100); + if (size >= 100) metadata->path[100] = '\0'; + else + metadata->path[size] = '\0'; } else { - minitar_strlcpy(metadata->name, hdr->prefix, 155); - minitar_append_char(metadata->name, '/'); - strncat(metadata->name, hdr->name, 100); - metadata->name[256] = '\0'; + minitar_strlcpy(metadata->path, hdr->prefix, 155); + minitar_append_char(metadata->path, '/'); + strncat(metadata->path, hdr->name, 100); + metadata->path[256] = '\0'; } + char* mut_path = strdup(metadata->path); + if (!mut_path) minitar_panic("Failed to allocate memory"); + char* bname = basename(mut_path); + minitar_strlcpy(metadata->name, bname, sizeof(metadata->name)); + free(mut_path); + metadata->mode = (mode_t)strtoul(hdr->mode, NULL, 8); metadata->uid = (uid_t)strtoul(hdr->uid, NULL, 8); metadata->gid = (gid_t)strtoul(hdr->gid, NULL, 8); char* sizeptr = strndup( 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 to duplicate a tar header's size field"); + if (!sizeptr) minitar_panic("Failed to allocate memory"); metadata->size = (size_t)strtoull(sizeptr, NULL, 8); free(sizeptr); char* timeptr = strndup( 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 to duplicate a tar header's mtime field"); + if (!timeptr) minitar_panic("Failed to allocate memory"); metadata->mtime = (time_t)strtoull(timeptr, NULL, 8); free(timeptr);