diff options
-rw-r--r-- | tar/read_header.c | 92 | ||||
-rw-r--r-- | tar/tar.h | 7 | ||||
-rw-r--r-- | tar/tar2sqfs.c | 29 |
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; @@ -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; } |