aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tar/read_header.c92
-rw-r--r--tar/tar.h7
-rw-r--r--tar/tar2sqfs.c29
3 files changed, 71 insertions, 57 deletions
diff --git a/tar/read_header.c b/tar/read_header.c
index 099a9ce..bdb2d20 100644
--- a/tar/read_header.c
+++ b/tar/read_header.c
@@ -2,19 +2,23 @@
#include "util.h"
#include "tar.h"
+#include <sys/sysmacros.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>
enum {
- PAX_SIZE = 0x01,
- PAX_UID = 0x02,
- PAX_GID = 0x04,
- PAX_DEV_MAJ = 0x08,
- PAX_DEV_MIN = 0x10,
- PAX_NAME = 0x20,
- PAX_SLINK_TARGET = 0x40,
+ PAX_SIZE = 0x001,
+ PAX_UID = 0x002,
+ PAX_GID = 0x004,
+ PAX_DEV_MAJ = 0x008,
+ PAX_DEV_MIN = 0x010,
+ PAX_NAME = 0x020,
+ PAX_SLINK_TARGET = 0x040,
+ PAX_ATIME = 0x080,
+ PAX_MTIME = 0x100,
+ PAX_CTIME = 0x200,
};
static int read_octal(const char *str, int digits, uint64_t *out)
@@ -124,6 +128,7 @@ static int read_pax_header(int fd, uint64_t entsize, unsigned int *set_by_pax,
tar_header_decoded_t *out)
{
char *buffer, *line;
+ uint64_t field;
ssize_t ret;
uint64_t i;
@@ -160,10 +165,12 @@ static int read_pax_header(int fd, uint64_t entsize, unsigned int *set_by_pax,
buffer[i] = '\0';
if (!strncmp(line, "uid=", 4)) {
- pax_read_decimal(line + 4, &out->uid);
+ pax_read_decimal(line + 4, &field);
+ out->sb.st_uid = field;
*set_by_pax |= PAX_UID;
} else if (!strncmp(line, "gid=", 4)) {
- pax_read_decimal(line + 4, &out->gid);
+ pax_read_decimal(line + 4, &field);
+ out->sb.st_gid = field;
*set_by_pax |= PAX_GID;
} else if (!strncmp(line, "path=", 5)) {
free(out->name);
@@ -172,7 +179,8 @@ static int read_pax_header(int fd, uint64_t entsize, unsigned int *set_by_pax,
goto fail_errno;
*set_by_pax |= PAX_NAME;
} else if (!strncmp(line, "size=", 5)) {
- pax_read_decimal(line + 5, &out->size);
+ pax_read_decimal(line + 5, &field);
+ out->sb.st_size = field;
*set_by_pax |= PAX_SIZE;
} else if (!strncmp(line, "linkpath=", 9)) {
free(out->link_target);
@@ -180,6 +188,18 @@ static int read_pax_header(int fd, uint64_t entsize, unsigned int *set_by_pax,
if (out->link_target == NULL)
goto fail_errno;
*set_by_pax |= PAX_SLINK_TARGET;
+ } else if (!strncmp(line, "atime=", 6)) {
+ pax_read_decimal(line + 6, &field);
+ out->sb.st_atime = field;
+ *set_by_pax |= PAX_ATIME;
+ } else if (!strncmp(line, "mtime=", 6)) {
+ pax_read_decimal(line + 6, &field);
+ out->sb.st_mtime = field;
+ *set_by_pax |= PAX_MTIME;
+ } else if (!strncmp(line, "ctime=", 6)) {
+ pax_read_decimal(line + 6, &field);
+ out->sb.st_ctime = field;
+ *set_by_pax |= PAX_CTIME;
}
}
@@ -199,6 +219,7 @@ fail:
static int decode_header(const tar_header_t *hdr, unsigned int set_by_pax,
tar_header_decoded_t *out)
{
+ uint64_t field;
size_t count;
if (!(set_by_pax & PAX_NAME)) {
@@ -223,38 +244,53 @@ static int decode_header(const tar_header_t *hdr, unsigned int set_by_pax,
}
if (!(set_by_pax & PAX_SIZE)) {
- if (read_number(hdr->size, sizeof(hdr->size), &out->size))
+ if (read_number(hdr->size, sizeof(hdr->size), &field))
return -1;
+ out->sb.st_size = field;
}
if (!(set_by_pax & PAX_UID)) {
- if (read_number(hdr->uid, sizeof(hdr->uid), &out->uid))
+ if (read_number(hdr->uid, sizeof(hdr->uid), &field))
return -1;
+ out->sb.st_uid = field;
}
if (!(set_by_pax & PAX_GID)) {
- if (read_number(hdr->gid, sizeof(hdr->gid), &out->gid))
+ if (read_number(hdr->gid, sizeof(hdr->gid), &field))
return -1;
+ out->sb.st_gid = field;
}
if (!(set_by_pax & PAX_DEV_MAJ)) {
- if (read_number(hdr->devmajor, sizeof(hdr->devmajor),
- &out->dev_maj)) {
+ if (read_number(hdr->devmajor, sizeof(hdr->devmajor), &field))
return -1;
- }
+
+ out->sb.st_rdev = makedev(field, minor(out->sb.st_rdev));
}
if (!(set_by_pax & PAX_DEV_MIN)) {
- if (read_number(hdr->devminor, sizeof(hdr->devminor),
- &out->dev_min)) {
+ if (read_number(hdr->devminor, sizeof(hdr->devminor), &field))
return -1;
- }
+
+ out->sb.st_rdev = makedev(major(out->sb.st_rdev), field);
}
- if (read_octal(hdr->mode, sizeof(hdr->mode), &out->mode))
+ if (!(set_by_pax & PAX_MTIME)) {
+ if (read_number(hdr->mtime, sizeof(hdr->mtime), &field))
+ return -1;
+ out->sb.st_mtime = field;
+ }
+
+ if (!(set_by_pax & PAX_ATIME))
+ out->sb.st_atime = out->sb.st_mtime;
+
+ if (!(set_by_pax & PAX_CTIME))
+ out->sb.st_ctime = out->sb.st_mtime;
+
+ if (read_octal(hdr->mode, sizeof(hdr->mode), &field))
return -1;
- out->mode &= 07777;
+ out->sb.st_mode = field & 07777;
if (hdr->typeflag == TAR_TYPE_LINK ||
hdr->typeflag == TAR_TYPE_SLINK) {
@@ -272,26 +308,26 @@ static int decode_header(const tar_header_t *hdr, unsigned int set_by_pax,
switch (hdr->typeflag) {
case '\0':
case TAR_TYPE_FILE:
- out->mode |= S_IFREG;
+ out->sb.st_mode |= S_IFREG;
break;
case TAR_TYPE_LINK:
/* XXX: hard links are not support yet */
- out->mode = S_IFLNK | 0777;
+ out->sb.st_mode = S_IFLNK | 0777;
break;
case TAR_TYPE_SLINK:
- out->mode = S_IFLNK | 0777;
+ out->sb.st_mode = S_IFLNK | 0777;
break;
case TAR_TYPE_CHARDEV:
- out->mode |= S_IFCHR;
+ out->sb.st_mode |= S_IFCHR;
break;
case TAR_TYPE_BLOCKDEV:
- out->mode |= S_IFBLK;
+ out->sb.st_mode |= S_IFBLK;
break;
case TAR_TYPE_DIR:
- out->mode |= S_IFDIR;
+ out->sb.st_mode |= S_IFDIR;
break;
case TAR_TYPE_FIFO:
- out->mode |= S_IFIFO;
+ out->sb.st_mode |= S_IFIFO;
break;
default:
out->unknown_record = true;
diff --git a/tar/tar.h b/tar/tar.h
index 35c4fe0..7862235 100644
--- a/tar/tar.h
+++ b/tar/tar.h
@@ -26,12 +26,7 @@ typedef struct {
} tar_header_t;
typedef struct {
- uint64_t size;
- uint64_t mode;
- uint64_t uid;
- uint64_t gid;
- uint64_t dev_maj;
- uint64_t dev_min;
+ struct stat sb;
char *name;
char *link_target;
bool unknown_record;
diff --git a/tar/tar2sqfs.c b/tar/tar2sqfs.c
index f00f281..0c23b61 100644
--- a/tar/tar2sqfs.c
+++ b/tar/tar2sqfs.c
@@ -93,17 +93,12 @@ static int create_node_and_repack_data(tar_header_decoded_t *hdr, fstree_t *fs,
data_writer_t *data)
{
tree_node_t *node;
- size_t extra = 0;
- if (S_ISLNK(hdr->mode))
- extra = strlen(hdr->link_target) + 1;
-
- if (S_ISREG(hdr->mode)) {
- node = fstree_add_file(fs, hdr->name, hdr->mode,
- hdr->uid, hdr->gid, hdr->size, NULL);
- if (node == NULL)
- goto fail_errno;
+ node = fstree_add_generic(fs, hdr->name, &hdr->sb, hdr->link_target);
+ if (node == NULL)
+ goto fail_errno;
+ if (S_ISREG(hdr->sb.st_mode)) {
if (write_data_from_fd(data, node->data.file,
STDIN_FILENO)) {
return -1;
@@ -111,18 +106,6 @@ static int create_node_and_repack_data(tar_header_decoded_t *hdr, fstree_t *fs,
if (skip_padding(STDIN_FILENO, node->data.file->size))
return -1;
- } else {
- node = fstree_add(fs, hdr->name, hdr->mode,
- hdr->uid, hdr->gid, extra);
- if (node == NULL)
- goto fail_errno;
-
- if (S_ISLNK(hdr->mode)) {
- strcpy(node->data.slink_target,
- hdr->link_target);
- } else if (S_ISBLK(hdr->mode) || S_ISCHR(hdr->mode)) {
- node->data.devno = makedev(hdr->dev_maj, hdr->dev_min);
- }
}
return 0;
@@ -146,7 +129,7 @@ static int process_tar_ball(fstree_t *fs, data_writer_t *data)
if (hdr.unknown_record) {
fprintf(stderr, "skipping '%s' (unknown entry type)\n",
hdr.name);
- if (skip_entry(STDIN_FILENO, hdr.size))
+ if (skip_entry(STDIN_FILENO, hdr.sb.st_size))
goto fail;
continue;
}
@@ -154,7 +137,7 @@ static int process_tar_ball(fstree_t *fs, data_writer_t *data)
if (canonicalize_name(hdr.name)) {
fprintf(stderr, "skipping '%s' (invalid name)\n",
hdr.name);
- if (skip_entry(STDIN_FILENO, hdr.size))
+ if (skip_entry(STDIN_FILENO, hdr.sb.st_size))
goto fail;
continue;
}