Merge code from upstream libtar + bug fixes
All updates and fixes applied from upstream libtar as of
March 1, 2016.
Debug flag is disabled, however non-debug output now
provides 1 line of useful output per object extracted.
I've also merged some fixes from CyanogenMod's
fork of libtar:
From: Tom Marshall <tdm@cyngn.com>
Date: Thu, 11 Feb 2016 16:24:40 -0800
Subject: libtar: Cleanup, secure, and extend numeric fields
Commit: e18b457ea1cbf6be1adc3b75450ed1c737cd82ea
From: Tom Marshall <tdm@cyngn.com>
Date: Thu, 11 Feb 2016 12:49:30 -0800
Subject: libtar: Make file sizes 64-bit clean
Commit: e628c2025549a24018bc568351465130a05daafb
From: Tom Marshall <tdm@cyngn.com>
Date: Thu, 17 Apr 2014 09:39:25 -0700
Subject: libtar: Add methods for in-memory files
Commit: 8ec5627a8ff0a91724c6d5b344f0e887da922527
From: Tom Marshall <tdm@cyngn.com>
Date: Wed, 2 Jul 2014 09:34:40 -0700
Subject: libtar: Fix hardlink extract
Commit: 166d83a51e0c51abcea37694dbd7df92d03c1f56
From: philz-cwm6 <phytowardt@gmail.com>
Date: Sat, 26 Apr 2014 01:11:35 +0200
Subject: libtar: Various bug fixes and enhancements
Commit: a271d763e94235ccee9ecaabdb52bf4b9b2f8c06
(Some of this was not merged in, as better solutions were
available from upstream libtar)
From: Tom Marshall <tdm@cyngn.com>
Date: Wed, 9 Apr 2014 09:35:54 -0700
Subject: libtar: Add const qualifiers to reduce compile warnings
Commit: 0600afa19fe827d06d3fcf24a7aabd52dbf487b4
Change-Id: I6d008cb6fdf950f835bbed63aeb8727cc5c86083
diff --git a/libtar/libtar.h b/libtar/libtar.h
index d2c4d00..4a51375 100644
--- a/libtar/libtar.h
+++ b/libtar/libtar.h
@@ -26,6 +26,7 @@
/* useful constants */
+/* see FIXME note in block.c regarding T_BLOCKSIZE */
#define T_BLOCKSIZE 512
#define T_NAMELEN 100
#define T_PREFIXLEN 155
@@ -85,12 +86,15 @@
typedef struct
{
tartype_t *type;
- char *pathname;
+ const char *pathname;
long fd;
int oflags;
int options;
struct tar_header th_buf;
libtar_hash_t *h;
+
+ /* introduced in libtar 1.2.21 */
+ char *th_pathname;
}
TAR;
@@ -103,6 +107,7 @@
#define TAR_CHECK_VERSION 32 /* check version in file header */
#define TAR_IGNORE_CRC 64 /* ignore CRC in file header */
#define TAR_STORE_SELINUX 128 /* store selinux context */
+#define TAR_USE_NUMERIC_ID 256 /* favor numeric owner over names */
/* this is obsolete - it's here for backwards-compatibility only */
#define TAR_IGNORE_MAGIC 0
@@ -111,11 +116,11 @@
/* open a new tarfile handle */
-int tar_open(TAR **t, char *pathname, tartype_t *type,
+int tar_open(TAR **t, const char *pathname, tartype_t *type,
int oflags, int mode, int options);
/* make a tarfile handle out of a previously-opened descriptor */
-int tar_fdopen(TAR **t, int fd, char *pathname, tartype_t *type,
+int tar_fdopen(TAR **t, int fd, const char *pathname, tartype_t *type,
int oflags, int mode, int options);
/* returns the descriptor associated with t */
@@ -139,14 +144,27 @@
* realname = path of file to append
* savename = name to save the file under in the archive
*/
-int tar_append_file(TAR *t, char *realname, char *savename);
+int tar_append_file(TAR *t, const char *realname, const char *savename);
/* write EOF indicator */
int tar_append_eof(TAR *t);
/* add file contents to a tarchive */
-int tar_append_regfile(TAR *t, char *realname);
+int tar_append_regfile(TAR *t, const char *realname);
+/* Appends in-memory file contents to a tarchive.
+ * Arguments:
+ * t = TAR handle to append to
+ * savename = name to save the file under in the archive
+ * mode = mode
+ * uid, gid = owner
+ * buf, len = in-memory buffer
+ */
+int tar_append_file_contents(TAR *t, const char *savename, mode_t mode,
+ uid_t uid, gid_t gid, void *buf, size_t len);
+
+/* add buffer to a tarchive */
+int tar_append_buffer(TAR *t, void *buf, size_t len);
/***** block.c *************************************************************/
@@ -167,31 +185,32 @@
#define TH_ISREG(t) ((t)->th_buf.typeflag == REGTYPE \
|| (t)->th_buf.typeflag == AREGTYPE \
|| (t)->th_buf.typeflag == CONTTYPE \
- || (S_ISREG((mode_t)oct_to_int((t)->th_buf.mode)) \
+ || (S_ISREG((mode_t)oct_to_int((t)->th_buf.mode, sizeof((t)->th_buf.mode))) \
&& (t)->th_buf.typeflag != LNKTYPE))
#define TH_ISLNK(t) ((t)->th_buf.typeflag == LNKTYPE)
#define TH_ISSYM(t) ((t)->th_buf.typeflag == SYMTYPE \
- || S_ISLNK((mode_t)oct_to_int((t)->th_buf.mode)))
+ || S_ISLNK((mode_t)oct_to_int((t)->th_buf.mode, sizeof((t)->th_buf.mode))))
#define TH_ISCHR(t) ((t)->th_buf.typeflag == CHRTYPE \
- || S_ISCHR((mode_t)oct_to_int((t)->th_buf.mode)))
+ || S_ISCHR((mode_t)oct_to_int((t)->th_buf.mode, sizeof((t)->th_buf.mode))))
#define TH_ISBLK(t) ((t)->th_buf.typeflag == BLKTYPE \
- || S_ISBLK((mode_t)oct_to_int((t)->th_buf.mode)))
+ || S_ISBLK((mode_t)oct_to_int((t)->th_buf.mode, sizeof((t)->th_buf.mode))))
#define TH_ISDIR(t) ((t)->th_buf.typeflag == DIRTYPE \
- || S_ISDIR((mode_t)oct_to_int((t)->th_buf.mode)) \
+ || S_ISDIR((mode_t)oct_to_int((t)->th_buf.mode, sizeof((t)->th_buf.mode))) \
|| ((t)->th_buf.typeflag == AREGTYPE \
- && ((t)->th_buf.name[strlen((t)->th_buf.name) - 1] == '/')))
+ && strnlen((t)->th_buf.name, T_NAMELEN) \
+ && ((t)->th_buf.name[strnlen((t)->th_buf.name, T_NAMELEN) - 1] == '/')))
#define TH_ISFIFO(t) ((t)->th_buf.typeflag == FIFOTYPE \
- || S_ISFIFO((mode_t)oct_to_int((t)->th_buf.mode)))
+ || S_ISFIFO((mode_t)oct_to_int((t)->th_buf.mode, sizeof((t)->th_buf.mode))))
#define TH_ISLONGNAME(t) ((t)->th_buf.typeflag == GNU_LONGNAME_TYPE)
#define TH_ISLONGLINK(t) ((t)->th_buf.typeflag == GNU_LONGLINK_TYPE)
#define TH_ISEXTHEADER(t) ((t)->th_buf.typeflag == TH_EXT_TYPE)
/* decode tar header info */
-#define th_get_crc(t) oct_to_int((t)->th_buf.chksum)
-#define th_get_size(t) oct_to_int((t)->th_buf.size)
-#define th_get_mtime(t) oct_to_int((t)->th_buf.mtime)
-#define th_get_devmajor(t) oct_to_int((t)->th_buf.devmajor)
-#define th_get_devminor(t) oct_to_int((t)->th_buf.devminor)
+#define th_get_crc(t) oct_to_int((t)->th_buf.chksum, sizeof((t)->th_buf.chksum))
+#define th_get_size(t) oct_to_int_ex((t)->th_buf.size, sizeof((t)->th_buf.size))
+#define th_get_mtime(t) oct_to_int_ex((t)->th_buf.mtime, sizeof((t)->th_buf.mtime))
+#define th_get_devmajor(t) oct_to_int((t)->th_buf.devmajor, sizeof((t)->th_buf.devmajor))
+#define th_get_devminor(t) oct_to_int((t)->th_buf.devminor, sizeof((t)->th_buf.devminor))
#define th_get_linkname(t) ((t)->th_buf.gnu_longlink \
? (t)->th_buf.gnu_longlink \
: (t)->th_buf.linkname)
@@ -205,16 +224,16 @@
/* encode file info in th_header */
void th_set_type(TAR *t, mode_t mode);
-void th_set_path(TAR *t, char *pathname);
-void th_set_link(TAR *t, char *linkname);
+void th_set_path(TAR *t, const char *pathname);
+void th_set_link(TAR *t, const char *linkname);
void th_set_device(TAR *t, dev_t device);
void th_set_user(TAR *t, uid_t uid);
void th_set_group(TAR *t, gid_t gid);
void th_set_mode(TAR *t, mode_t fmode);
#define th_set_mtime(t, fmtime) \
- int_to_oct_nonull((fmtime), (t)->th_buf.mtime, 12)
+ int_to_oct_ex((fmtime), (t)->th_buf.mtime, sizeof((t)->th_buf.mtime))
#define th_set_size(t, fsize) \
- int_to_oct_nonull((fsize), (t)->th_buf.size, 12)
+ int_to_oct_ex((fsize), (t)->th_buf.size, sizeof((t)->th_buf.size))
/* encode everything at once (except the pathname and linkname) */
void th_set_from_stat(TAR *t, struct stat *s);
@@ -226,20 +245,22 @@
/***** extract.c ***********************************************************/
/* sequentially extract next file from t */
-int tar_extract_file(TAR *t, char *realname, char *prefix, const int *progress_fd);
+int tar_extract_file(TAR *t, const char *realname, const char *prefix, const int *progress_fd);
/* extract different file types */
-int tar_extract_dir(TAR *t, char *realname);
-int tar_extract_hardlink(TAR *t, char *realname, char *prefix);
-int tar_extract_symlink(TAR *t, char *realname);
-int tar_extract_chardev(TAR *t, char *realname);
-int tar_extract_blockdev(TAR *t, char *realname);
-int tar_extract_fifo(TAR *t, char *realname);
+int tar_extract_dir(TAR *t, const char *realname);
+int tar_extract_hardlink(TAR *t, const char *realname, const char *prefix);
+int tar_extract_symlink(TAR *t, const char *realname);
+int tar_extract_chardev(TAR *t, const char *realname);
+int tar_extract_blockdev(TAR *t, const char *realname);
+int tar_extract_fifo(TAR *t, const char *realname);
/* for regfiles, we need to extract the content blocks as well */
-int tar_extract_regfile(TAR *t, char *realname, const int *progress_fd);
+int tar_extract_regfile(TAR *t, const char *realname, const int *progress_fd);
int tar_skip_regfile(TAR *t);
+/* extract regfile to buffer */
+int tar_extract_file_contents(TAR *t, void *buf, size_t *lenp);
/***** output.c ************************************************************/
@@ -280,16 +301,17 @@
#define th_crc_ok(t) (th_get_crc(t) == th_crc_calc(t) || th_get_crc(t) == th_signed_crc_calc(t))
/* string-octal to integer conversion */
-int oct_to_int(char *oct);
+int64_t oct_to_int(char *oct, size_t len);
+
+/* string-octal or binary to integer conversion */
+int64_t oct_to_int_ex(char *oct, size_t len);
/* integer to NULL-terminated string-octal conversion */
-#define int_to_oct(num, oct, octlen) \
- snprintf((oct), (octlen), "%*lo ", (octlen) - 2, (unsigned long)(num))
+void int_to_oct(int64_t num, char *oct, size_t octlen);
-/* integer to string-octal conversion, no NULL */
-void int_to_oct_nonull(int num, char *oct, size_t octlen);
+/* integer to string-octal conversion, or binary as necessary */
+void int_to_oct_ex(int64_t num, char *oct, size_t octlen);
-#define tar_min(x, y) (x < y ? x : y)
/***** wrapper.c **********************************************************/
@@ -298,7 +320,7 @@
int tar_extract_all(TAR *t, char *prefix, const int *progress_fd);
/* add a whole tree of files */
-int tar_append_tree(TAR *t, char *realdir, char *savedir, char *exclude);
+int tar_append_tree(TAR *t, char *realdir, char *savedir);
/* find an entry */
int tar_find(TAR *t, char *searchstr);