diff --git a/README.md b/README.md index 862b461..bfd1944 100644 --- a/README.md +++ b/README.md @@ -4,7 +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 (pretty much only requires a basic subset of the C FILE API, apart from other simple functions). -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)). +Aims to be bloat-free (currently just above 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)). 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. diff --git a/docs/API.md b/docs/API.md index 21c917f..a9050c5 100644 --- a/docs/API.md +++ b/docs/API.md @@ -75,7 +75,9 @@ This enum lists all supported file types: `MTAR_DIRECTORY`: Directories -Other file types supported in tar archives, such as block/character devices, FIFOs, or symlinks, are not supported and minitar will throw an error when encountering one of them. This behavior can be controlled by passing `-DMINITAR_IGNORE_UNSUPPORTED_TYPES=ON` to CMake when configuring, which will make minitar silently ignore such entries instead of panicking. +`MTAR_SYMLINK`: Symbolic links + +Other file types supported in tar archives, such as block/character devices, FIFOs, or hard links, are not supported and minitar will throw an error when encountering one of them. This behavior can be controlled by passing `-DMINITAR_IGNORE_UNSUPPORTED_TYPES=ON` to CMake when configuring, which will make minitar silently ignore such entries instead of panicking. ### minitar_entry_metadata `struct minitar_entry_metadata` @@ -86,6 +88,8 @@ This structure represents an entry's metadata, with the following fields: `name`: A string representing the base name of the entry (the last component of its path). (`char[]`) +`link`: A string representing the file being linked to. (Only applies to symlinks) (`char[]`) + `mode`: An integer representing the permissions of the entry. (`mode_t`) `uid`: An integer representing the user ID of the entry's owner. (`uid_t`) diff --git a/examples/untar.c b/examples/untar.c index 040942d..e1b23d9 100644 --- a/examples/untar.c +++ b/examples/untar.c @@ -6,6 +6,7 @@ * untar.c: Example utility which extracts files from a tar archive (POSIX only). */ +#define _XOPEN_SOURCE 700 #include #include #include @@ -85,6 +86,18 @@ int main(int argc, char** argv) printf("untar %s\n", entry.metadata.path); } + else if (entry.metadata.type == MTAR_SYMLINK) + { + int status = symlink(entry.metadata.link, entry.metadata.path); + + if (status != 0) + { + fprintf(stderr, "Failed to create symlink %s: %s\n", entry.metadata.path, strerror(errno)); + break; + } + + printf("symlink %s -> %s\n", entry.metadata.path, entry.metadata.link); + } } else break; diff --git a/minitar.h b/minitar.h index 2fbf1f3..6f673ab 100644 --- a/minitar.h +++ b/minitar.h @@ -20,7 +20,8 @@ struct minitar enum minitar_file_type { MTAR_REGULAR, - MTAR_DIRECTORY + MTAR_DIRECTORY, + MTAR_SYMLINK }; struct minitar_entry_internal @@ -32,6 +33,7 @@ struct minitar_entry_metadata { char path[257]; char name[128]; + char link[101]; mode_t mode; uid_t uid; gid_t gid; diff --git a/src/util.c b/src/util.c index 445f242..703b4dd 100644 --- a/src/util.c +++ b/src/util.c @@ -162,6 +162,8 @@ void minitar_parse_metadata_from_tar_header(const struct tar_header* hdr, struct metadata->path[256] = '\0'; } + minitar_strlcpy(metadata->link, hdr->linkname, 101); + minitar_parse_basename(metadata->path, metadata->name, sizeof(metadata->name)); // Numeric fields in tar archives are stored as octal-encoded ASCII strings. Weird decision (supposedly for @@ -185,7 +187,7 @@ void minitar_parse_metadata_from_tar_header(const struct tar_header* hdr, struct case '\0': case '0': metadata->type = MTAR_REGULAR; break; case '1': minitar_handle_panic("Links to other files within a tar archive are unsupported"); - case '2': minitar_handle_panic("Symbolic links are unsupported"); + case '2': metadata->type = MTAR_SYMLINK; break; case '3': minitar_handle_panic("Character devices are unsupported"); case '4': minitar_handle_panic("Block devices are unsupported"); case '5': metadata->type = MTAR_DIRECTORY; break; @@ -226,7 +228,7 @@ uint32_t minitar_checksum_header(const struct tar_header* hdr) int minitar_validate_header(const struct tar_header* hdr) { #ifdef MINITAR_IGNORE_UNSUPPORTED_TYPES - if (hdr->typeflag != '\0' && hdr->typeflag != '0' && hdr->typeflag != '5') return 0; + if (hdr->typeflag != '\0' && hdr->typeflag != '0' && hdr->typeflag != '2' && hdr->typeflag != '5') return 0; #else if (hdr->typeflag != '\0' && hdr->typeflag != '0' && hdr->typeflag != '1' && hdr->typeflag != '2' && hdr->typeflag != '3' && hdr->typeflag != '4' && hdr->typeflag != '5' && hdr->typeflag != '6')