feat: Add support for block and character devices
This commit is contained in:
parent
1f08cf4b31
commit
5b0d597c09
@ -14,6 +14,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/sysmacros.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
static int untar_file(const struct minitar_entry* entry, const void* buf)
|
static int untar_file(const struct minitar_entry* entry, const void* buf)
|
||||||
@ -48,6 +49,7 @@ int main(int argc, char** argv)
|
|||||||
perror(argv[1]);
|
perror(argv[1]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
int exit_status = 0;
|
||||||
struct minitar_entry entry;
|
struct minitar_entry entry;
|
||||||
do {
|
do {
|
||||||
if (minitar_read_entry(&mp, &entry) == 0)
|
if (minitar_read_entry(&mp, &entry) == 0)
|
||||||
@ -58,6 +60,7 @@ int main(int argc, char** argv)
|
|||||||
if (status != 0)
|
if (status != 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Failed to create directory %s: %s\n", entry.metadata.path, strerror(errno));
|
fprintf(stderr, "Failed to create directory %s: %s\n", entry.metadata.path, strerror(errno));
|
||||||
|
exit_status = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,6 +72,7 @@ int main(int argc, char** argv)
|
|||||||
if (!ptr)
|
if (!ptr)
|
||||||
{
|
{
|
||||||
perror("malloc");
|
perror("malloc");
|
||||||
|
exit_status = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,6 +85,7 @@ int main(int argc, char** argv)
|
|||||||
if (status != 0)
|
if (status != 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Failed to extract file %s: %s\n", entry.metadata.path, strerror(errno));
|
fprintf(stderr, "Failed to extract file %s: %s\n", entry.metadata.path, strerror(errno));
|
||||||
|
exit_status = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,6 +98,7 @@ int main(int argc, char** argv)
|
|||||||
if (status != 0)
|
if (status != 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Failed to create symlink %s: %s\n", entry.metadata.path, strerror(errno));
|
fprintf(stderr, "Failed to create symlink %s: %s\n", entry.metadata.path, strerror(errno));
|
||||||
|
exit_status = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,6 +111,7 @@ int main(int argc, char** argv)
|
|||||||
if (status != 0)
|
if (status != 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Failed to create hard link %s: %s\n", entry.metadata.path, strerror(errno));
|
fprintf(stderr, "Failed to create hard link %s: %s\n", entry.metadata.path, strerror(errno));
|
||||||
|
exit_status = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,14 +124,50 @@ int main(int argc, char** argv)
|
|||||||
if (status != 0)
|
if (status != 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Failed to create FIFO %s: %s\n", entry.metadata.path, strerror(errno));
|
fprintf(stderr, "Failed to create FIFO %s: %s\n", entry.metadata.path, strerror(errno));
|
||||||
|
exit_status = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("fifo %s\n", entry.metadata.path);
|
printf("fifo %s\n", entry.metadata.path);
|
||||||
}
|
}
|
||||||
|
else if (entry.metadata.type == MTAR_BLKDEV)
|
||||||
|
{
|
||||||
|
int status = mknod(entry.metadata.path, entry.metadata.mode | S_IFBLK,
|
||||||
|
makedev(entry.metadata.devmajor, entry.metadata.devminor));
|
||||||
|
|
||||||
|
if (status != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to create block device %s: %s\n", entry.metadata.path, strerror(errno));
|
||||||
|
exit_status = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("blkdev %s (%u:%u)\n", entry.metadata.path, entry.metadata.devmajor, entry.metadata.devminor);
|
||||||
|
}
|
||||||
|
else if (entry.metadata.type == MTAR_CHRDEV)
|
||||||
|
{
|
||||||
|
int status = mknod(entry.metadata.path, entry.metadata.mode | S_IFCHR,
|
||||||
|
makedev(entry.metadata.devmajor, entry.metadata.devminor));
|
||||||
|
|
||||||
|
if (status != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to create character device %s: %s\n", entry.metadata.path, strerror(errno));
|
||||||
|
exit_status = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("chrdev %s (%u:%u)\n", entry.metadata.path, entry.metadata.devmajor, entry.metadata.devminor);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "error: unknown entry type: %d", entry.metadata.type);
|
||||||
|
exit_status = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
} while (1);
|
} while (1);
|
||||||
minitar_close(&mp);
|
minitar_close(&mp);
|
||||||
|
return exit_status;
|
||||||
}
|
}
|
@ -24,6 +24,8 @@ enum minitar_file_type
|
|||||||
MTAR_SYMLINK,
|
MTAR_SYMLINK,
|
||||||
MTAR_HARDLINK,
|
MTAR_HARDLINK,
|
||||||
MTAR_FIFO,
|
MTAR_FIFO,
|
||||||
|
MTAR_CHRDEV,
|
||||||
|
MTAR_BLKDEV
|
||||||
};
|
};
|
||||||
|
|
||||||
struct minitar_entry_internal
|
struct minitar_entry_internal
|
||||||
@ -44,6 +46,8 @@ struct minitar_entry_metadata
|
|||||||
enum minitar_file_type type;
|
enum minitar_file_type type;
|
||||||
char uname[32];
|
char uname[32];
|
||||||
char gname[32];
|
char gname[32];
|
||||||
|
unsigned devminor;
|
||||||
|
unsigned devmajor;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct minitar_entry
|
struct minitar_entry
|
||||||
|
16
src/util.c
16
src/util.c
@ -190,8 +190,8 @@ void minitar_parse_metadata_from_tar_header(const struct tar_header* hdr, struct
|
|||||||
case '0': metadata->type = MTAR_REGULAR; break;
|
case '0': metadata->type = MTAR_REGULAR; break;
|
||||||
case '1': metadata->type = MTAR_HARDLINK; break;
|
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': metadata->type = MTAR_CHRDEV; break;
|
||||||
case '4': minitar_handle_panic("Block devices are unsupported");
|
case '4': metadata->type = MTAR_BLKDEV; break;
|
||||||
case '5': metadata->type = MTAR_DIRECTORY; break;
|
case '5': metadata->type = MTAR_DIRECTORY; break;
|
||||||
case '6': metadata->type = MTAR_FIFO; break;
|
case '6': metadata->type = MTAR_FIFO; break;
|
||||||
// This case should have been previously handled by minitar_validate_header().
|
// This case should have been previously handled by minitar_validate_header().
|
||||||
@ -200,6 +200,12 @@ void minitar_parse_metadata_from_tar_header(const struct tar_header* hdr, struct
|
|||||||
|
|
||||||
minitar_strlcpy(metadata->uname, hdr->uname, 32);
|
minitar_strlcpy(metadata->uname, hdr->uname, 32);
|
||||||
minitar_strlcpy(metadata->gname, hdr->gname, 32);
|
minitar_strlcpy(metadata->gname, hdr->gname, 32);
|
||||||
|
|
||||||
|
if (metadata->type == MTAR_CHRDEV || metadata->type == MTAR_BLKDEV)
|
||||||
|
{
|
||||||
|
metadata->devminor = minitar_parse_octal(hdr->devminor);
|
||||||
|
metadata->devmajor = minitar_parse_octal(hdr->devmajor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t minitar_checksum_header(const struct tar_header* hdr)
|
uint32_t minitar_checksum_header(const struct tar_header* hdr)
|
||||||
@ -230,15 +236,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
|
|
||||||
if (hdr->typeflag != '\0' && hdr->typeflag != '0' && hdr->typeflag != '1' && hdr->typeflag != '2' &&
|
|
||||||
hdr->typeflag != '5')
|
|
||||||
return 0;
|
|
||||||
#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')
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
|
||||||
// FIXME: Warn on checksum mismatch unless header is all blanks?
|
// FIXME: Warn on checksum mismatch unless header is all blanks?
|
||||||
if (minitar_checksum_header(hdr) != minitar_parse_octal(hdr->chksum)) return 0;
|
if (minitar_checksum_header(hdr) != minitar_parse_octal(hdr->chksum)) return 0;
|
||||||
return !strncmp(hdr->magic, "ustar", 5);
|
return !strncmp(hdr->magic, "ustar", 5);
|
||||||
|
Loading…
Reference in New Issue
Block a user