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);