feat: Add support for hard links
This commit is contained in:
parent
94324c502e
commit
3772e9e3a6
@ -77,7 +77,9 @@ This enum lists all supported file types:
|
|||||||
|
|
||||||
`MTAR_SYMLINK`: Symbolic links
|
`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.
|
`MTAR_HARDLINK`: Hard links
|
||||||
|
|
||||||
|
Other file types supported in tar archives, such as block/character devices or FIFOs, 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
|
### minitar_entry_metadata
|
||||||
`struct minitar_entry_metadata`
|
`struct minitar_entry_metadata`
|
||||||
@ -88,7 +90,7 @@ 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[]`)
|
`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[]`)
|
`link`: A string representing the file being linked to. (Only applies to symlinks/hard links) (`char[]`)
|
||||||
|
|
||||||
`mode`: An integer representing the permissions of the entry. (`mode_t`)
|
`mode`: An integer representing the permissions of the entry. (`mode_t`)
|
||||||
|
|
||||||
|
@ -98,6 +98,18 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
printf("symlink %s -> %s\n", entry.metadata.path, entry.metadata.link);
|
printf("symlink %s -> %s\n", entry.metadata.path, entry.metadata.link);
|
||||||
}
|
}
|
||||||
|
else if (entry.metadata.type == MTAR_HARDLINK)
|
||||||
|
{
|
||||||
|
int status = link(entry.metadata.link, entry.metadata.path);
|
||||||
|
|
||||||
|
if (status != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to create hard link %s: %s\n", entry.metadata.path, strerror(errno));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("link %s -> %s\n", entry.metadata.path, entry.metadata.link);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
|
@ -21,7 +21,8 @@ enum minitar_file_type
|
|||||||
{
|
{
|
||||||
MTAR_REGULAR,
|
MTAR_REGULAR,
|
||||||
MTAR_DIRECTORY,
|
MTAR_DIRECTORY,
|
||||||
MTAR_SYMLINK
|
MTAR_SYMLINK,
|
||||||
|
MTAR_HARDLINK,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct minitar_entry_internal
|
struct minitar_entry_internal
|
||||||
|
@ -174,6 +174,8 @@ void minitar_parse_metadata_from_tar_header(const struct tar_header* hdr, struct
|
|||||||
metadata->uid = (uid_t)minitar_parse_octal(hdr->uid);
|
metadata->uid = (uid_t)minitar_parse_octal(hdr->uid);
|
||||||
metadata->gid = (gid_t)minitar_parse_octal(hdr->gid);
|
metadata->gid = (gid_t)minitar_parse_octal(hdr->gid);
|
||||||
|
|
||||||
|
// These two fields aren't null-terminated.
|
||||||
|
|
||||||
char* sizeptr = minitar_static_dup(hdr->size, 12);
|
char* sizeptr = minitar_static_dup(hdr->size, 12);
|
||||||
metadata->size = (size_t)minitar_parse_octal(sizeptr);
|
metadata->size = (size_t)minitar_parse_octal(sizeptr);
|
||||||
|
|
||||||
@ -186,12 +188,13 @@ void minitar_parse_metadata_from_tar_header(const struct tar_header* hdr, struct
|
|||||||
{
|
{
|
||||||
case '\0':
|
case '\0':
|
||||||
case '0': metadata->type = MTAR_REGULAR; break;
|
case '0': metadata->type = MTAR_REGULAR; break;
|
||||||
case '1': minitar_handle_panic("Links to other files within a tar archive are unsupported");
|
case '1': metadata->type = MTAR_HARDLINK; break;
|
||||||
case '2': metadata->type = MTAR_SYMLINK; break;
|
case '2': metadata->type = MTAR_SYMLINK; break;
|
||||||
case '3': minitar_handle_panic("Character devices are unsupported");
|
case '3': minitar_handle_panic("Character devices are unsupported");
|
||||||
case '4': minitar_handle_panic("Block devices are unsupported");
|
case '4': minitar_handle_panic("Block devices are unsupported");
|
||||||
case '5': metadata->type = MTAR_DIRECTORY; break;
|
case '5': metadata->type = MTAR_DIRECTORY; break;
|
||||||
case '6': minitar_handle_panic("FIFOs are unsupported");
|
case '6': minitar_handle_panic("FIFOs are unsupported");
|
||||||
|
// This case should have been previously handled by minitar_validate_header().
|
||||||
default: minitar_handle_panic("Unknown entry type in tar header");
|
default: minitar_handle_panic("Unknown entry type in tar header");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,7 +231,9 @@ uint32_t minitar_checksum_header(const struct tar_header* hdr)
|
|||||||
int minitar_validate_header(const struct tar_header* hdr)
|
int minitar_validate_header(const struct tar_header* hdr)
|
||||||
{
|
{
|
||||||
#ifdef MINITAR_IGNORE_UNSUPPORTED_TYPES
|
#ifdef MINITAR_IGNORE_UNSUPPORTED_TYPES
|
||||||
if (hdr->typeflag != '\0' && hdr->typeflag != '0' && hdr->typeflag != '2' && hdr->typeflag != '5') return 0;
|
if (hdr->typeflag != '\0' && hdr->typeflag != '0' && hdr->typeflag != '1' && hdr->typeflag != '2' &&
|
||||||
|
hdr->typeflag != '5')
|
||||||
|
return 0;
|
||||||
#else
|
#else
|
||||||
if (hdr->typeflag != '\0' && hdr->typeflag != '0' && hdr->typeflag != '1' && hdr->typeflag != '2' &&
|
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')
|
hdr->typeflag != '3' && hdr->typeflag != '4' && hdr->typeflag != '5' && hdr->typeflag != '6')
|
||||||
|
Loading…
Reference in New Issue
Block a user