summaryrefslogtreecommitdiff
path: root/include/tar
diff options
context:
space:
mode:
Diffstat (limited to 'include/tar')
-rw-r--r--include/tar/format.h105
-rw-r--r--include/tar/tar.h92
2 files changed, 197 insertions, 0 deletions
diff --git a/include/tar/format.h b/include/tar/format.h
new file mode 100644
index 0000000..53a4665
--- /dev/null
+++ b/include/tar/format.h
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+/*
+ * format.h
+ *
+ * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
+ */
+#ifndef TAR_FORMAT_H
+#define TAR_FORMAT_H
+
+#include "sqfs/predef.h"
+
+typedef struct {
+ char name[100];
+ char mode[8];
+ char uid[8];
+ char gid[8];
+ char size[12];
+ char mtime[12];
+ char chksum[8];
+ char typeflag;
+ char linkname[100];
+ char magic[6];
+ char version[2];
+ char uname[32];
+ char gname[32];
+ char devmajor[8];
+ char devminor[8];
+ union {
+ struct {
+ char prefix[155];
+ char padding[12];
+ } posix;
+
+ struct {
+ char atime[12];
+ char ctime[12];
+ char offset[12];
+ char deprecated[4];
+ char unused;
+ struct {
+ char offset[12];
+ char numbytes[12];
+ } sparse[4];
+ char isextended;
+ char realsize[12];
+ char padding[17];
+ } gnu;
+ } tail;
+} tar_header_t;
+
+typedef struct {
+ struct {
+ char offset[12];
+ char numbytes[12];
+ } sparse[21];
+ char isextended;
+ char padding[7];
+} gnu_sparse_t;
+
+#define TAR_TYPE_FILE '0'
+#define TAR_TYPE_LINK '1'
+#define TAR_TYPE_SLINK '2'
+#define TAR_TYPE_CHARDEV '3'
+#define TAR_TYPE_BLOCKDEV '4'
+#define TAR_TYPE_DIR '5'
+#define TAR_TYPE_FIFO '6'
+
+#define TAR_TYPE_GNU_SLINK 'K'
+#define TAR_TYPE_GNU_PATH 'L'
+#define TAR_TYPE_GNU_SPARSE 'S'
+
+#define TAR_TYPE_PAX 'x'
+#define TAR_TYPE_PAX_GLOBAL 'g'
+
+#define TAR_MAGIC "ustar"
+#define TAR_VERSION "00"
+
+#define TAR_MAGIC_OLD "ustar "
+#define TAR_VERSION_OLD " "
+
+#define TAR_RECORD_SIZE (512)
+
+/* artificially imposed implementation limits */
+#define TAR_MAX_SYMLINK_LEN (65536)
+#define TAR_MAX_PATH_LEN (65536)
+#define TAR_MAX_PAX_LEN (65536)
+#define TAR_MAX_SPARSE_ENT (65536)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int read_octal(const char *str, int digits, sqfs_u64 *out);
+
+int read_number(const char *str, int digits, sqfs_u64 *out);
+
+void update_checksum(tar_header_t *hdr);
+
+bool is_checksum_valid(const tar_header_t *hdr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TAR_FORMAT_H */
diff --git a/include/tar/tar.h b/include/tar/tar.h
new file mode 100644
index 0000000..128464e
--- /dev/null
+++ b/include/tar/tar.h
@@ -0,0 +1,92 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+/*
+ * tar.h
+ *
+ * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
+ */
+#ifndef TAR_H
+#define TAR_H
+
+#include "config.h"
+#include "compat.h"
+#include "io/istream.h"
+#include "io/ostream.h"
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+
+typedef struct sparse_map_t {
+ struct sparse_map_t *next;
+ sqfs_u64 offset;
+ sqfs_u64 count;
+} sparse_map_t;
+
+typedef struct tar_xattr_t {
+ struct tar_xattr_t *next;
+ char *key;
+ sqfs_u8 *value;
+ size_t value_len;
+ char data[];
+} tar_xattr_t;
+
+typedef struct {
+ char *name;
+ char *link_target;
+ sparse_map_t *sparse;
+ sqfs_u64 actual_size;
+ sqfs_u64 record_size;
+ bool unknown_record;
+ bool is_hard_link;
+ tar_xattr_t *xattr;
+
+ sqfs_u16 mode;
+ sqfs_u64 uid;
+ sqfs_u64 gid;
+ sqfs_u64 devno;
+ sqfs_s64 mtime;
+} tar_header_decoded_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ Returns < 0 on failure, > 0 if cannot encode, 0 on success.
+ Prints error/warning messages to stderr.
+
+ The counter is an incremental record counter used if additional
+ headers need to be generated.
+*/
+int write_tar_header(ostream_t *fp, const struct stat *sb, const char *name,
+ const char *slink_target, const tar_xattr_t *xattr,
+ unsigned int counter);
+
+int write_hard_link(ostream_t *fp, const struct stat *sb, const char *name,
+ const char *target, unsigned int counter);
+
+/* calcuate and skip the zero padding */
+int skip_padding(istream_t *fp, sqfs_u64 size);
+
+/* round up to block size and skip the entire entry */
+int skip_entry(istream_t *fp, sqfs_u64 size);
+
+int read_header(istream_t *fp, tar_header_decoded_t *out);
+
+void clear_header(tar_header_decoded_t *hdr);
+
+/*
+ Write zero bytes to an output file to padd it to the tar record size.
+ Returns 0 on success. On failure, prints error message to stderr.
+*/
+int padd_file(ostream_t *fp, sqfs_u64 size);
+
+void free_sparse_list(sparse_map_t *sparse);
+
+void free_xattr_list(tar_xattr_t *list);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TAR_H */