Merge pull request #897 from phillipberndt/master

Add test for #870 / #869
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 49537ce..4c818b0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1203,7 +1203,6 @@
 CHECK_FUNCTION_EXISTS_GLIBC(chown HAVE_CHOWN)
 CHECK_FUNCTION_EXISTS_GLIBC(chroot HAVE_CHROOT)
 CHECK_FUNCTION_EXISTS_GLIBC(ctime_r HAVE_CTIME_R)
-CHECK_FUNCTION_EXISTS_GLIBC(dirfd HAVE_DIRFD)
 CHECK_FUNCTION_EXISTS_GLIBC(fchdir HAVE_FCHDIR)
 CHECK_FUNCTION_EXISTS_GLIBC(fchflags HAVE_FCHFLAGS)
 CHECK_FUNCTION_EXISTS_GLIBC(fchmod HAVE_FCHMOD)
@@ -1303,6 +1302,10 @@
   "#include <dirent.h>\nint main() {DIR *d = opendir(\".\"); struct dirent e,*r; return readdir_r(d,&e,&r);}"
   HAVE_READDIR_R)
 
+# dirfd can be either a function or a macro.
+CHECK_C_SOURCE_COMPILES(
+  "#include <dirent.h>\nint main() {DIR *d = opendir(\".\"); return dirfd(d);}"
+  HAVE_DIRFD)
 
 # Only detect readlinkat() if we also have AT_FDCWD in unistd.h.
 # NOTE: linux requires fcntl.h for AT_FDCWD.
diff --git a/configure.ac b/configure.ac
index 2545299..1730f45 100644
--- a/configure.ac
+++ b/configure.ac
@@ -605,7 +605,7 @@
 # To avoid necessity for including windows.h or special forward declaration
 # workarounds, we use 'void *' for 'struct SECURITY_ATTRIBUTES *'
 AC_CHECK_STDCALL_FUNC([CreateHardLinkA],[const char *, const char *, void *])
-AC_CHECK_FUNCS([arc4random_buf chflags chown chroot ctime_r dirfd])
+AC_CHECK_FUNCS([arc4random_buf chflags chown chroot ctime_r])
 AC_CHECK_FUNCS([fchdir fchflags fchmod fchown fcntl fdopendir fork])
 AC_CHECK_FUNCS([fstat fstatat fstatfs fstatvfs ftruncate])
 AC_CHECK_FUNCS([futimens futimes futimesat])
@@ -648,6 +648,13 @@
 		    return(readdir_r(dir, &e, &r));]])],
  [AC_DEFINE(HAVE_READDIR_R,1,[Define to 1 if you have a POSIX compatible readdir_r])]
 )
+# dirfd can be either a function or a macro.
+AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([[#include <dirent.h>
+                    DIR *dir;]],
+                  [[return(dirfd(dir));]])],
+ [AC_DEFINE(HAVE_DIRFD,1,[Define to 1 if you have a dirfd function or macro])]
+)
 
 # FreeBSD's nl_langinfo supports an option to specify whether the
 # current locale uses month/day or day/month ordering.  It makes the
diff --git a/libarchive/archive_getdate.c b/libarchive/archive_getdate.c
index fe43ae8..030c083 100644
--- a/libarchive/archive_getdate.c
+++ b/libarchive/archive_getdate.c
@@ -691,7 +691,7 @@
 	time_t Hours, time_t Minutes, time_t Seconds,
 	time_t Timezone, enum DSTMODE DSTmode)
 {
-	int DaysInMonth[12] = {
+	signed char DaysInMonth[12] = {
 		31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
 	};
 	time_t	Julian;
diff --git a/libarchive/archive_read_disk.3 b/libarchive/archive_read_disk.3
index 55e4bbb..027f63c 100644
--- a/libarchive/archive_read_disk.3
+++ b/libarchive/archive_read_disk.3
@@ -24,11 +24,12 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd December 30, 2016
+.Dd April 3, 2017
 .Dt ARCHIVE_READ_DISK 3
 .Os
 .Sh NAME
 .Nm archive_read_disk_new ,
+.Nm archive_read_disk_set_behavior ,
 .Nm archive_read_disk_set_symlink_logical ,
 .Nm archive_read_disk_set_symlink_physical ,
 .Nm archive_read_disk_set_symlink_hybrid ,
@@ -46,6 +47,8 @@
 .Ft struct archive *
 .Fn archive_read_disk_new "void"
 .Ft int
+.Fn archive_read_disk_set_behavior "struct archive *" "int"
+.Ft int
 .Fn archive_read_disk_set_symlink_logical "struct archive *"
 .Ft int
 .Fn archive_read_disk_set_symlink_physical "struct archive *"
@@ -89,6 +92,51 @@
 Allocates and initializes a
 .Tn struct archive
 object suitable for reading object information from disk.
+.It Fn archive_read_disk_set_behavior
+Configures various behavior options when reading entries from disk.
+The flags field consists of a bitwise OR of one or more of the
+following values:
+.Bl -tag -compact -width "indent"
+.It Cm ARCHIVE_READDISK_HONOR_NODUMP
+Skip files and directories with the nodump file attribute (file flag) set.
+By default, the nodump file atrribute is ignored.
+.It Cm ARCHIVE_READDISK_MAC_COPYFILE
+Mac OS X specific. Read metadata (ACLs and extended attributes) with
+.Xr copyfile 3 .
+By default, metadata is read using
+.Xr copyfile 3 .
+.It Cm ARCHIVE_READDISK_NO_ACL
+Do not read Access Control Lists.
+By default, ACLs are read from disk.
+.It Cm ARCHIVE_READDISK_NO_FFLAGS
+Do not read file attributes (file flags).
+By default, file attributes are read from disk.
+See
+.Xr chattr 1
+.Pq Linux
+or
+.Xr chflags 1
+.Pq FreeBSD, Mac OS X
+for more information on file attributes.
+.It Cm ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS
+Do not traverse mount points.
+By defaut, moint points are traversed.
+.It Cm ARCHIVE_READDISK_NO_XATTR
+Do not read extended file attributes (xattrs).
+By default, extended file attributes are read from disk.
+See
+.Xr xattr 7
+.Pq Linux ,
+.Xr xattr 2
+.Pq Mac OS X ,
+or
+.Xr getextattr 8
+.Pq FreeBSD
+for more information on extended file attributes.
+.It Cm ARCHIVE_READDISK_RESTORE_ATIME
+Restore access time of traversed files.
+By default, access time of traversed files is not restored.
+.El
 .It Xo
 .Fn archive_read_disk_set_symlink_logical ,
 .Fn archive_read_disk_set_symlink_physical ,
diff --git a/libarchive/archive_write_disk.3 b/libarchive/archive_write_disk.3
index 4891b85..949c9ef 100644
--- a/libarchive/archive_write_disk.3
+++ b/libarchive/archive_write_disk.3
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd February 28, 2017
+.Dd April 3, 2017
 .Dt ARCHIVE_WRITE_DISK 3
 .Os
 .Sh NAME
@@ -96,6 +96,33 @@
 The options field consists of a bitwise OR of one or more of the
 following values:
 .Bl -tag -compact -width "indent"
+.It Cm ARCHIVE_EXTRACT_ACL
+Attempt to restore Access Control Lists.
+By default, extended ACLs are ignored.
+.It Cm ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS
+Before removing a file system object prior to replacing it, clear
+platform-specific file flags which might prevent its removal.
+.It Cm ARCHIVE_EXTRACT_FFLAGS
+Attempt to restore file attributes (file flags).
+By default, file attributes are ignored.
+See
+.Xr chattr 1
+.Pq Linux
+or
+.Xr chflags 1
+.Pq FreeBSD, Mac OS X
+for more information on file attributes.
+.It Cm ARCHIVE_EXTRACT_MAC_METADATA
+Mac OS X specific. Restore metadata using
+.Xr copyfile 3 .
+By default,
+.Xr copyfile 3
+metadata is ignored.
+.It Cm ARCHIVE_EXTRACT_NO_OVERWRITE
+Existing files on disk will not be overwritten.
+By default, existing regular files are truncated and overwritten;
+existing directories will have their permissions updated;
+other pre-existing objects are unlinked and recreated from scratch.
 .It Cm ARCHIVE_EXTRACT_OWNER
 The user and group IDs should be set on the restored file.
 By default, the user and group IDs are not restored.
@@ -111,43 +138,9 @@
 if the default user and group IDs of newly-created objects on disk
 happen to match those specified in the archive entry.
 By default, only basic permissions are restored, and umask is obeyed.
-.It Cm ARCHIVE_EXTRACT_TIME
-The timestamps (mtime, ctime, and atime) should be restored.
-By default, they are ignored.
-Note that restoring of atime is not currently supported.
-.It Cm ARCHIVE_EXTRACT_NO_OVERWRITE
-Existing files on disk will not be overwritten.
-By default, existing regular files are truncated and overwritten;
-existing directories will have their permissions updated;
-other pre-existing objects are unlinked and recreated from scratch.
-.It Cm ARCHIVE_EXTRACT_UNLINK
-Existing files on disk will be unlinked before any attempt to
-create them.
-In some cases, this can prove to be a significant performance improvement.
-By default, existing files are truncated and rewritten, but
-the file is not recreated.
-In particular, the default behavior does not break existing hard links.
-.It Cm ARCHIVE_EXTRACT_ACL
-Attempt to restore ACLs.
-By default, extended ACLs are ignored.
-.It Cm ARCHIVE_EXTRACT_FFLAGS
-Attempt to restore extended file flags.
-By default, file flags are ignored.
-.It Cm ARCHIVE_EXTRACT_XATTR
-Attempt to restore POSIX.1e extended attributes.
-By default, they are ignored.
-.It Cm ARCHIVE_EXTRACT_SECURE_SYMLINKS
-Refuse to extract any object whose final location would be altered
-by a symlink on disk.
-This is intended to help guard against a variety of mischief
-caused by archives that (deliberately or otherwise) extract
-files outside of the current directory.
-The default is not to perform this check.
-If
-.Cm ARCHIVE_EXTRACT_UNLINK
-is specified together with this option, the library will
-remove any intermediate symlinks it finds and return an
-error only if such symlink could not be removed.
+.It Cm ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS
+Refuse to extract an absolute path.
+The default is to not refuse such paths.
 .It Cm ARCHIVE_EXTRACT_SECURE_NODOTDOT
 Refuse to extract a path that contains a
 .Pa ..
@@ -156,16 +149,45 @@
 Note that paths ending in
 .Pa ..
 always cause an error, regardless of this flag.
-.It Cm ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS
-Refuse to extract an absolute path.
-The default is to not refuse such paths.
+.It Cm ARCHIVE_EXTRACT_SECURE_SYMLINKS
+Refuse to extract any object whose final location would be altered
+by a symlink on disk.
+This is intended to help guard against a variety of mischief
+caused by archives that (deliberately or otherwise) extract
+files outside of the current directory.
+The default is not to perform this check.
+If
 .It Cm ARCHIVE_EXTRACT_SPARSE
 Scan data for blocks of NUL bytes and try to recreate them with holes.
 This results in sparse files, independent of whether the archive format
 supports or uses them.
-.It Cm ARCHIVE_EXTRACT_CLEAR_NOCHANGE_FFLAGS
-Before removing a file system object prior to replacing it, clear
-platform-specific file flags which might prevent its removal.
+.Cm ARCHIVE_EXTRACT_UNLINK
+is specified together with this option, the library will
+remove any intermediate symlinks it finds and return an
+error only if such symlink could not be removed.
+.It Cm ARCHIVE_EXTRACT_TIME
+The timestamps (mtime, ctime, and atime) should be restored.
+By default, they are ignored.
+Note that restoring of atime is not currently supported.
+.It Cm ARCHIVE_EXTRACT_UNLINK
+Existing files on disk will be unlinked before any attempt to
+create them.
+In some cases, this can prove to be a significant performance improvement.
+By default, existing files are truncated and rewritten, but
+the file is not recreated.
+In particular, the default behavior does not break existing hard links.
+.It Cm ARCHIVE_EXTRACT_XATTR
+Attempt to restore extended file attributes.
+By default, they are ignored.
+See
+.Xr xattr 7
+.Pq Linux ,
+.Xr xattr 2
+.Pq Mac OS X ,
+or
+.Xr getextattr 8
+.Pq FreeBSD
+for more information on extended file attributes.
 .El
 .It Xo
 .Fn archive_write_disk_set_group_lookup ,
diff --git a/libarchive/test/test_xattr_platform.c b/libarchive/test/test_xattr_platform.c
index ebb265e..df3f81a 100644
--- a/libarchive/test/test_xattr_platform.c
+++ b/libarchive/test/test_xattr_platform.c
@@ -35,6 +35,7 @@
 	struct archive_entry *ae;
 	const char *name;
 	const void *value;
+	void *rvalue;
 	size_t size, insize;
 	int e, r;
 	const char *attrname = "user.libarchive.test";
@@ -95,8 +96,9 @@
 	assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
 	assertEqualInt(ARCHIVE_OK, archive_write_free(a));
 
-	value = getXattr("writetest", attrname, &insize);
+	rvalue = getXattr("writetest", attrname, &insize);
 	if (assertEqualInt(insize, strlen(writeval) + 1) != 0)
-		assertEqualMem(value, writeval, insize);
+		assertEqualMem(rvalue, writeval, insize);
+	free(rvalue);
 #endif
 }
diff --git a/tar/test/test_option_acls.c b/tar/test/test_option_acls.c
index be0db44..f2d51d6 100644
--- a/tar/test/test_option_acls.c
+++ b/tar/test/test_option_acls.c
@@ -360,8 +360,10 @@
 	if (richacl_a != NULL) {
 		richacl_b = richacl_get_file(path_b);
 		if (richacl_b == NULL &&
-		    (errno == ENODATA || errno == ENOTSUP || errno == ENOSYS))
+		    (errno == ENODATA || errno == ENOTSUP || errno == ENOSYS)) {
+			richacl_free(richacl_a);
 			return (0);
+		}
 		failure("richacl_get_file() error: %s (%s)", path_b,
 		    strerror(errno));
 		if (assert(richacl_b != NULL) == 0) {
diff --git a/tar/test/test_option_xattrs.c b/tar/test/test_option_xattrs.c
index 5095ce3..bce8a94 100644
--- a/tar/test/test_option_xattrs.c
+++ b/tar/test/test_option_xattrs.c
@@ -33,7 +33,7 @@
 
 	const char *testattr = "user.libarchive.test";
 	const char *testval = "testval";
-	const void *readval;
+	void *readval;
 	size_t size;
 	int r;
 
@@ -62,6 +62,7 @@
 	readval = getXattr("xattrs_xattrs/f", testattr, &size);
 	if(assertEqualInt(size, strlen(testval) + 1) != 0)
 		assertEqualMem(readval, testval, size);
+	free(readval);
 
 	/* Extract xattrs without xattrs */
 	assertMakeDir("xattrs_noxattrs", 0755);
diff --git a/test_utils/test_common.h b/test_utils/test_common.h
index fa726bf..1425dd8 100644
--- a/test_utils/test_common.h
+++ b/test_utils/test_common.h
@@ -348,7 +348,7 @@
 int setTestAcl(const char *path);
 
 /* Get extended attribute */
-const void *getXattr(const char *, const char *, size_t *);
+void *getXattr(const char *, const char *, size_t *);
 
 /* Set extended attribute */
 int setXattr(const char *, const char *, const void *, size_t);
diff --git a/test_utils/test_main.c b/test_utils/test_main.c
index 36dfc82..d740459 100644
--- a/test_utils/test_main.c
+++ b/test_utils/test_main.c
@@ -2451,8 +2451,8 @@
 	return (0);
 }
 
-/* Get extended attribute from a path */
-const void *
+/* Get extended attribute value from a path */
+void *
 getXattr(const char *path, const char *name, size_t *sizep)
 { 
 	void *value = NULL;