feat: Add support for symbolic links
All the pieces were in place, we just needed to put them together. Sorry, but sub-500 LoC isn't gonna work anymore...
This commit is contained in:
parent
4c90f9078b
commit
599cac5811
@ -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.
|
||||
|
||||
|
@ -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`)
|
||||
|
@ -6,6 +6,7 @@
|
||||
* untar.c: Example utility which extracts files from a tar archive (POSIX only).
|
||||
*/
|
||||
|
||||
#define _XOPEN_SOURCE 700
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <minitar.h>
|
||||
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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')
|
||||
|
Loading…
Reference in New Issue
Block a user