svn commit: r307229 - in user/cperciva/freebsd-update-build/patches: 10.1-RELEASE 10.2-RELEASE 10.3-RELEASE 11.0-RELEASE 9.3-RELEASE
Gleb Smirnoff
glebius at FreeBSD.org
Thu Oct 13 18:34:41 UTC 2016
Author: glebius
Date: Thu Oct 13 18:34:39 2016
New Revision: 307229
URL: https://svnweb.freebsd.org/changeset/base/307229
Log:
Save the latest patch queue.
Added:
user/cperciva/freebsd-update-build/patches/10.1-RELEASE/40-SA-16:29.bspatch
user/cperciva/freebsd-update-build/patches/10.1-RELEASE/40-SA-16:30.portsnap
user/cperciva/freebsd-update-build/patches/10.1-RELEASE/40-SA-16:31.libarchive
user/cperciva/freebsd-update-build/patches/10.2-RELEASE/23-SA-16:29.bspatch
user/cperciva/freebsd-update-build/patches/10.2-RELEASE/23-SA-16:30.portsnap
user/cperciva/freebsd-update-build/patches/10.2-RELEASE/23-SA-16:31.libarchive
user/cperciva/freebsd-update-build/patches/10.3-RELEASE/10-SA-16:29.bspatch
user/cperciva/freebsd-update-build/patches/10.3-RELEASE/10-SA-16:30.portsnap
user/cperciva/freebsd-update-build/patches/10.3-RELEASE/10-SA-16:31.libarchive
user/cperciva/freebsd-update-build/patches/11.0-RELEASE/
user/cperciva/freebsd-update-build/patches/11.0-RELEASE/0-EN-16:99.newvers
user/cperciva/freebsd-update-build/patches/9.3-RELEASE/48-SA-16:28.bind
user/cperciva/freebsd-update-build/patches/9.3-RELEASE/48-SA-16:29.bspatch
user/cperciva/freebsd-update-build/patches/9.3-RELEASE/48-SA-16:30.portsnap
Added: user/cperciva/freebsd-update-build/patches/10.1-RELEASE/40-SA-16:29.bspatch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ user/cperciva/freebsd-update-build/patches/10.1-RELEASE/40-SA-16:29.bspatch Thu Oct 13 18:34:39 2016 (r307229)
@@ -0,0 +1,325 @@
+--- usr.bin/bsdiff/bspatch/bspatch.c.orig
++++ usr.bin/bsdiff/bspatch/bspatch.c
+@@ -27,56 +27,133 @@
+ #include <sys/cdefs.h>
+ __FBSDID("$FreeBSD$");
+
++#if defined(__FreeBSD__)
++#include <sys/param.h>
++#if __FreeBSD_version >= 1001511
++#include <sys/capsicum.h>
++#define HAVE_CAPSICUM
++#endif
++#endif
++
+ #include <bzlib.h>
+-#include <stdlib.h>
++#include <err.h>
++#include <errno.h>
++#include <fcntl.h>
++#include <libgen.h>
++#include <limits.h>
++#include <stdint.h>
+ #include <stdio.h>
++#include <stdlib.h>
+ #include <string.h>
+-#include <err.h>
+ #include <unistd.h>
+-#include <fcntl.h>
+
+ #ifndef O_BINARY
+ #define O_BINARY 0
+ #endif
++#define HEADER_SIZE 32
++
++static char *newfile;
++static int dirfd = -1;
++
++static void
++exit_cleanup(void)
++{
++
++ if (dirfd != -1 && newfile != NULL)
++ if (unlinkat(dirfd, newfile, 0))
++ warn("unlinkat");
++}
+
+ static off_t offtin(u_char *buf)
+ {
+ off_t y;
+
+- y=buf[7]&0x7F;
+- y=y*256;y+=buf[6];
+- y=y*256;y+=buf[5];
+- y=y*256;y+=buf[4];
+- y=y*256;y+=buf[3];
+- y=y*256;y+=buf[2];
+- y=y*256;y+=buf[1];
+- y=y*256;y+=buf[0];
++ y = buf[7] & 0x7F;
++ y = y * 256; y += buf[6];
++ y = y * 256; y += buf[5];
++ y = y * 256; y += buf[4];
++ y = y * 256; y += buf[3];
++ y = y * 256; y += buf[2];
++ y = y * 256; y += buf[1];
++ y = y * 256; y += buf[0];
+
+- if(buf[7]&0x80) y=-y;
++ if (buf[7] & 0x80)
++ y = -y;
+
+- return y;
++ return (y);
+ }
+
+-int main(int argc,char * argv[])
++int main(int argc, char *argv[])
+ {
+- FILE * f, * cpf, * dpf, * epf;
+- BZFILE * cpfbz2, * dpfbz2, * epfbz2;
++ FILE *f, *cpf, *dpf, *epf;
++ BZFILE *cpfbz2, *dpfbz2, *epfbz2;
++ char *directory, *namebuf;
+ int cbz2err, dbz2err, ebz2err;
+- int fd;
+- ssize_t oldsize,newsize;
+- ssize_t bzctrllen,bzdatalen;
+- u_char header[32],buf[8];
++ int newfd, oldfd;
++ off_t oldsize, newsize;
++ off_t bzctrllen, bzdatalen;
++ u_char header[HEADER_SIZE], buf[8];
+ u_char *old, *new;
+- off_t oldpos,newpos;
++ off_t oldpos, newpos;
+ off_t ctrl[3];
+- off_t lenread;
+- off_t i;
++ off_t i, lenread, offset;
++#ifdef HAVE_CAPSICUM
++ cap_rights_t rights_dir, rights_ro, rights_wr;
++#endif
+
+ if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]);
+
+ /* Open patch file */
+ if ((f = fopen(argv[3], "rb")) == NULL)
+ err(1, "fopen(%s)", argv[3]);
++ /* Open patch file for control block */
++ if ((cpf = fopen(argv[3], "rb")) == NULL)
++ err(1, "fopen(%s)", argv[3]);
++ /* open patch file for diff block */
++ if ((dpf = fopen(argv[3], "rb")) == NULL)
++ err(1, "fopen(%s)", argv[3]);
++ /* open patch file for extra block */
++ if ((epf = fopen(argv[3], "rb")) == NULL)
++ err(1, "fopen(%s)", argv[3]);
++ /* open oldfile */
++ if ((oldfd = open(argv[1], O_RDONLY | O_BINARY, 0)) < 0)
++ err(1, "open(%s)", argv[1]);
++ /* open directory where we'll write newfile */
++ if ((namebuf = strdup(argv[2])) == NULL ||
++ (directory = dirname(namebuf)) == NULL ||
++ (dirfd = open(directory, O_DIRECTORY)) < 0)
++ err(1, "open %s", argv[2]);
++ free(namebuf);
++ if ((newfile = basename(argv[2])) == NULL)
++ err(1, "basename");
++ /* open newfile */
++ if ((newfd = openat(dirfd, newfile,
++ O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0666)) < 0)
++ err(1, "open(%s)", argv[2]);
++ atexit(exit_cleanup);
++
++#ifdef HAVE_CAPSICUM
++ if (cap_enter() < 0) {
++ /* Failed to sandbox, fatal if CAPABILITY_MODE enabled */
++ if (errno != ENOSYS)
++ err(1, "failed to enter security sandbox");
++ } else {
++ /* Capsicum Available */
++ cap_rights_init(&rights_ro, CAP_READ, CAP_FSTAT, CAP_SEEK);
++ cap_rights_init(&rights_wr, CAP_WRITE);
++ cap_rights_init(&rights_dir, CAP_UNLINKAT);
++
++ if (cap_rights_limit(fileno(f), &rights_ro) < 0 ||
++ cap_rights_limit(fileno(cpf), &rights_ro) < 0 ||
++ cap_rights_limit(fileno(dpf), &rights_ro) < 0 ||
++ cap_rights_limit(fileno(epf), &rights_ro) < 0 ||
++ cap_rights_limit(oldfd, &rights_ro) < 0 ||
++ cap_rights_limit(newfd, &rights_wr) < 0 ||
++ cap_rights_limit(dirfd, &rights_dir) < 0)
++ err(1, "cap_rights_limit() failed, could not restrict"
++ " capabilities");
++ }
++#endif
+
+ /*
+ File format:
+@@ -93,99 +170,99 @@
+ */
+
+ /* Read header */
+- if (fread(header, 1, 32, f) < 32) {
++ if (fread(header, 1, HEADER_SIZE, f) < HEADER_SIZE) {
+ if (feof(f))
+- errx(1, "Corrupt patch\n");
++ errx(1, "Corrupt patch");
+ err(1, "fread(%s)", argv[3]);
+ }
+
+ /* Check for appropriate magic */
+ if (memcmp(header, "BSDIFF40", 8) != 0)
+- errx(1, "Corrupt patch\n");
++ errx(1, "Corrupt patch");
+
+ /* Read lengths from header */
+- bzctrllen=offtin(header+8);
+- bzdatalen=offtin(header+16);
+- newsize=offtin(header+24);
+- if((bzctrllen<0) || (bzdatalen<0) || (newsize<0))
+- errx(1,"Corrupt patch\n");
++ bzctrllen = offtin(header + 8);
++ bzdatalen = offtin(header + 16);
++ newsize = offtin(header + 24);
++ if (bzctrllen < 0 || bzctrllen > OFF_MAX - HEADER_SIZE ||
++ bzdatalen < 0 || bzctrllen + HEADER_SIZE > OFF_MAX - bzdatalen ||
++ newsize < 0 || newsize > SSIZE_MAX)
++ errx(1, "Corrupt patch");
+
+ /* Close patch file and re-open it via libbzip2 at the right places */
+ if (fclose(f))
+ err(1, "fclose(%s)", argv[3]);
+- if ((cpf = fopen(argv[3], "rb")) == NULL)
+- err(1, "fopen(%s)", argv[3]);
+- if (fseeko(cpf, 32, SEEK_SET))
+- err(1, "fseeko(%s, %lld)", argv[3],
+- (long long)32);
++ offset = HEADER_SIZE;
++ if (fseeko(cpf, offset, SEEK_SET))
++ err(1, "fseeko(%s, %jd)", argv[3], (intmax_t)offset);
+ if ((cpfbz2 = BZ2_bzReadOpen(&cbz2err, cpf, 0, 0, NULL, 0)) == NULL)
+ errx(1, "BZ2_bzReadOpen, bz2err = %d", cbz2err);
+- if ((dpf = fopen(argv[3], "rb")) == NULL)
+- err(1, "fopen(%s)", argv[3]);
+- if (fseeko(dpf, 32 + bzctrllen, SEEK_SET))
+- err(1, "fseeko(%s, %lld)", argv[3],
+- (long long)(32 + bzctrllen));
++ offset += bzctrllen;
++ if (fseeko(dpf, offset, SEEK_SET))
++ err(1, "fseeko(%s, %jd)", argv[3], (intmax_t)offset);
+ if ((dpfbz2 = BZ2_bzReadOpen(&dbz2err, dpf, 0, 0, NULL, 0)) == NULL)
+ errx(1, "BZ2_bzReadOpen, bz2err = %d", dbz2err);
+- if ((epf = fopen(argv[3], "rb")) == NULL)
+- err(1, "fopen(%s)", argv[3]);
+- if (fseeko(epf, 32 + bzctrllen + bzdatalen, SEEK_SET))
+- err(1, "fseeko(%s, %lld)", argv[3],
+- (long long)(32 + bzctrllen + bzdatalen));
++ offset += bzdatalen;
++ if (fseeko(epf, offset, SEEK_SET))
++ err(1, "fseeko(%s, %jd)", argv[3], (intmax_t)offset);
+ if ((epfbz2 = BZ2_bzReadOpen(&ebz2err, epf, 0, 0, NULL, 0)) == NULL)
+ errx(1, "BZ2_bzReadOpen, bz2err = %d", ebz2err);
+
+- if(((fd=open(argv[1],O_RDONLY|O_BINARY,0))<0) ||
+- ((oldsize=lseek(fd,0,SEEK_END))==-1) ||
+- ((old=malloc(oldsize+1))==NULL) ||
+- (lseek(fd,0,SEEK_SET)!=0) ||
+- (read(fd,old,oldsize)!=oldsize) ||
+- (close(fd)==-1)) err(1,"%s",argv[1]);
+- if((new=malloc(newsize+1))==NULL) err(1,NULL);
++ if ((oldsize = lseek(oldfd, 0, SEEK_END)) == -1 ||
++ oldsize > SSIZE_MAX ||
++ (old = malloc(oldsize)) == NULL ||
++ lseek(oldfd, 0, SEEK_SET) != 0 ||
++ read(oldfd, old, oldsize) != oldsize ||
++ close(oldfd) == -1)
++ err(1, "%s", argv[1]);
++ if ((new = malloc(newsize)) == NULL)
++ err(1, NULL);
+
+- oldpos=0;newpos=0;
+- while(newpos<newsize) {
++ oldpos = 0;
++ newpos = 0;
++ while (newpos < newsize) {
+ /* Read control data */
+- for(i=0;i<=2;i++) {
++ for (i = 0; i <= 2; i++) {
+ lenread = BZ2_bzRead(&cbz2err, cpfbz2, buf, 8);
+ if ((lenread < 8) || ((cbz2err != BZ_OK) &&
+ (cbz2err != BZ_STREAM_END)))
+- errx(1, "Corrupt patch\n");
+- ctrl[i]=offtin(buf);
++ errx(1, "Corrupt patch");
++ ctrl[i] = offtin(buf);
+ };
+
+ /* Sanity-check */
+- if ((ctrl[0] < 0) || (ctrl[1] < 0))
+- errx(1,"Corrupt patch\n");
++ if (ctrl[0] < 0 || ctrl[0] > INT_MAX ||
++ ctrl[1] < 0 || ctrl[1] > INT_MAX)
++ errx(1, "Corrupt patch");
+
+ /* Sanity-check */
+- if(newpos+ctrl[0]>newsize)
+- errx(1,"Corrupt patch\n");
++ if (newpos + ctrl[0] > newsize)
++ errx(1, "Corrupt patch");
+
+ /* Read diff string */
+ lenread = BZ2_bzRead(&dbz2err, dpfbz2, new + newpos, ctrl[0]);
+ if ((lenread < ctrl[0]) ||
+ ((dbz2err != BZ_OK) && (dbz2err != BZ_STREAM_END)))
+- errx(1, "Corrupt patch\n");
++ errx(1, "Corrupt patch");
+
+ /* Add old data to diff string */
+- for(i=0;i<ctrl[0];i++)
+- if((oldpos+i>=0) && (oldpos+i<oldsize))
+- new[newpos+i]+=old[oldpos+i];
++ for (i = 0; i < ctrl[0]; i++)
++ if ((oldpos + i >= 0) && (oldpos + i < oldsize))
++ new[newpos + i] += old[oldpos + i];
+
+ /* Adjust pointers */
+- newpos+=ctrl[0];
+- oldpos+=ctrl[0];
++ newpos += ctrl[0];
++ oldpos += ctrl[0];
+
+ /* Sanity-check */
+- if(newpos+ctrl[1]>newsize)
+- errx(1,"Corrupt patch\n");
++ if (newpos + ctrl[1] > newsize)
++ errx(1, "Corrupt patch");
+
+ /* Read extra string */
+ lenread = BZ2_bzRead(&ebz2err, epfbz2, new + newpos, ctrl[1]);
+ if ((lenread < ctrl[1]) ||
+ ((ebz2err != BZ_OK) && (ebz2err != BZ_STREAM_END)))
+- errx(1, "Corrupt patch\n");
++ errx(1, "Corrupt patch");
+
+ /* Adjust pointers */
+ newpos+=ctrl[1];
+@@ -200,12 +277,13 @@
+ err(1, "fclose(%s)", argv[3]);
+
+ /* Write the new file */
+- if(((fd=open(argv[2],O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,0666))<0) ||
+- (write(fd,new,newsize)!=newsize) || (close(fd)==-1))
+- err(1,"%s",argv[2]);
++ if (write(newfd, new, newsize) != newsize || close(newfd) == -1)
++ err(1, "%s", argv[2]);
++ /* Disable atexit cleanup */
++ newfile = NULL;
+
+ free(new);
+ free(old);
+
+- return 0;
++ return (0);
+ }
Added: user/cperciva/freebsd-update-build/patches/10.1-RELEASE/40-SA-16:30.portsnap
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ user/cperciva/freebsd-update-build/patches/10.1-RELEASE/40-SA-16:30.portsnap Thu Oct 13 18:34:39 2016 (r307229)
@@ -0,0 +1,49 @@
+--- usr.sbin/portsnap/portsnap/portsnap.sh.orig
++++ usr.sbin/portsnap/portsnap/portsnap.sh
+@@ -646,7 +646,7 @@
+ # Verify a list of files
+ fetch_snapshot_verify() {
+ while read F; do
+- if [ "`gunzip -c snap/${F} | ${SHA256} -q`" != ${F} ]; then
++ if [ "`gunzip -c < snap/${F}.gz | ${SHA256} -q`" != ${F} ]; then
+ echo "snapshot corrupt."
+ return 1
+ fi
+@@ -681,11 +681,18 @@
+ cut -f 2 -d '|' tINDEX.new | fetch_snapshot_verify || return 1
+ # Extract the index
+ rm -f INDEX.new
+- gunzip -c snap/`look INDEX tINDEX.new |
++ gunzip -c < snap/`look INDEX tINDEX.new |
+ cut -f 2 -d '|'`.gz > INDEX.new
+ fetch_index_sanity || return 1
+ # Verify the snapshot contents
+ cut -f 2 -d '|' INDEX.new | fetch_snapshot_verify || return 1
++ cut -f 2 -d '|' tINDEX.new INDEX.new | sort -u > files.expected
++ find snap -mindepth 1 | sed -E 's^snap/(.*)\.gz^\1^' | sort > files.snap
++ if ! cmp -s files.expected files.snap; then
++ echo "unexpected files in snapshot."
++ return 1
++ fi
++ rm files.expected files.snap
+ echo "done."
+
+ # Move files into their proper locations
+@@ -777,7 +784,7 @@
+
+ # Extract the index
+ echo -n "Extracting index... " 1>${QUIETREDIR}
+- gunzip -c files/`look INDEX tINDEX.new |
++ gunzip -c < files/`look INDEX tINDEX.new |
+ cut -f 2 -d '|'`.gz > INDEX.new
+ fetch_index_sanity || return 1
+
+@@ -897,7 +904,7 @@
+ echo -n "$1 not provided by portsnap server; "
+ echo "$2 not being generated."
+ else
+- gunzip -c "${WORKDIR}/files/`look $1 ${WORKDIR}/tINDEX |
++ gunzip -c < "${WORKDIR}/files/`look $1 ${WORKDIR}/tINDEX |
+ cut -f 2 -d '|'`.gz" |
+ cat - ${LOCALDESC} |
+ ${MKINDEX} /dev/stdin > ${PORTSDIR}/$2
Added: user/cperciva/freebsd-update-build/patches/10.1-RELEASE/40-SA-16:31.libarchive
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ user/cperciva/freebsd-update-build/patches/10.1-RELEASE/40-SA-16:31.libarchive Thu Oct 13 18:34:39 2016 (r307229)
@@ -0,0 +1,1270 @@
+--- contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c.orig
++++ contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c
+@@ -409,9 +409,7 @@
+ {
+ const char *accpath;
+ acl_t acl;
+-#if HAVE_ACL_IS_TRIVIAL_NP
+ int r;
+-#endif
+
+ accpath = archive_entry_sourcepath(entry);
+ if (accpath == NULL)
+@@ -443,9 +441,13 @@
+ }
+ #endif
+ if (acl != NULL) {
+- translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
++ r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
+ acl_free(acl);
+- return (ARCHIVE_OK);
++ if (r != ARCHIVE_OK) {
++ archive_set_error(&a->archive, errno,
++ "Couldn't translate NFSv4 ACLs: %s", accpath);
++ }
++ return (r);
+ }
+
+ /* Retrieve access ACL from file. */
+@@ -464,18 +466,29 @@
+ else
+ acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
+ if (acl != NULL) {
+- translate_acl(a, entry, acl,
++ r = translate_acl(a, entry, acl,
+ ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
+ acl_free(acl);
++ if (r != ARCHIVE_OK) {
++ archive_set_error(&a->archive, errno,
++ "Couldn't translate access ACLs: %s", accpath);
++ return (r);
++ }
+ }
+
+ /* Only directories can have default ACLs. */
+ if (S_ISDIR(archive_entry_mode(entry))) {
+ acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
+ if (acl != NULL) {
+- translate_acl(a, entry, acl,
++ r = translate_acl(a, entry, acl,
+ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
+ acl_free(acl);
++ if (r != ARCHIVE_OK) {
++ archive_set_error(&a->archive, errno,
++ "Couldn't translate default ACLs: %s",
++ accpath);
++ return (r);
++ }
+ }
+ }
+ return (ARCHIVE_OK);
+@@ -536,7 +549,11 @@
+ // FreeBSD "brands" ACLs as POSIX.1e or NFSv4
+ // Make sure the "brand" on this ACL is consistent
+ // with the default_entry_acl_type bits provided.
+- acl_get_brand_np(acl, &brand);
++ if (acl_get_brand_np(acl, &brand) != 0) {
++ archive_set_error(&a->archive, errno,
++ "Failed to read ACL brand");
++ return (ARCHIVE_WARN);
++ }
+ switch (brand) {
+ case ACL_BRAND_POSIX:
+ switch (default_entry_acl_type) {
+@@ -544,30 +561,42 @@
+ case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
+ break;
+ default:
+- // XXX set warning message?
+- return ARCHIVE_FAILED;
++ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
++ "Invalid ACL entry type for POSIX.1e ACL");
++ return (ARCHIVE_WARN);
+ }
+ break;
+ case ACL_BRAND_NFS4:
+ if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
+- // XXX set warning message?
+- return ARCHIVE_FAILED;
++ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
++ "Invalid ACL entry type for NFSv4 ACL");
++ return (ARCHIVE_WARN);
+ }
+ break;
+ default:
+- // XXX set warning message?
+- return ARCHIVE_FAILED;
++ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
++ "Unknown ACL brand");
++ return (ARCHIVE_WARN);
+ break;
+ }
+
+
+ s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
++ if (s == -1) {
++ archive_set_error(&a->archive, errno,
++ "Failed to get first ACL entry");
++ return (ARCHIVE_WARN);
++ }
+ while (s == 1) {
+ ae_id = -1;
+ ae_name = NULL;
+ ae_perm = 0;
+
+- acl_get_tag_type(acl_entry, &acl_tag);
++ if (acl_get_tag_type(acl_entry, &acl_tag) != 0) {
++ archive_set_error(&a->archive, errno,
++ "Failed to get ACL tag type");
++ return (ARCHIVE_WARN);
++ }
+ switch (acl_tag) {
+ case ACL_USER:
+ ae_id = (int)*(uid_t *)acl_get_qualifier(acl_entry);
+@@ -600,12 +629,17 @@
+ continue;
+ }
+
+- // XXX acl type maps to allow/deny/audit/YYYY bits
+- // XXX acl_get_entry_type_np on FreeBSD returns EINVAL for
+- // non-NFSv4 ACLs
++ // XXX acl_type maps to allow/deny/audit/YYYY bits
+ entry_acl_type = default_entry_acl_type;
+- r = acl_get_entry_type_np(acl_entry, &acl_type);
+- if (r == 0) {
++ if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
++ /*
++ * acl_get_entry_type_np() falis with non-NFSv4 ACLs
++ */
++ if (acl_get_entry_type_np(acl_entry, &acl_type) != 0) {
++ archive_set_error(&a->archive, errno, "Failed "
++ "to get ACL type from a NFSv4 ACL entry");
++ return (ARCHIVE_WARN);
++ }
+ switch (acl_type) {
+ case ACL_ENTRY_TYPE_ALLOW:
+ entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
+@@ -619,28 +653,52 @@
+ case ACL_ENTRY_TYPE_ALARM:
+ entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
+ break;
++ default:
++ archive_set_error(&a->archive, errno,
++ "Invalid NFSv4 ACL entry type");
++ return (ARCHIVE_WARN);
+ }
+- }
+-
+- /*
+- * Libarchive stores "flag" (NFSv4 inheritance bits)
+- * in the ae_perm bitmap.
+- */
+- acl_get_flagset_np(acl_entry, &acl_flagset);
+- for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) {
+- if (acl_get_flag_np(acl_flagset,
+- acl_inherit_map[i].platform_inherit))
+- ae_perm |= acl_inherit_map[i].archive_inherit;
+
+- }
++ /*
++ * Libarchive stores "flag" (NFSv4 inheritance bits)
++ * in the ae_perm bitmap.
++ *
++ * acl_get_flagset_np() fails with non-NFSv4 ACLs
++ */
++ if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
++ archive_set_error(&a->archive, errno,
++ "Failed to get flagset from a NFSv4 ACL entry");
++ return (ARCHIVE_WARN);
++ }
++ for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) {
++ r = acl_get_flag_np(acl_flagset,
++ acl_inherit_map[i].platform_inherit);
++ if (r == -1) {
++ archive_set_error(&a->archive, errno,
++ "Failed to check flag in a NFSv4 "
++ "ACL flagset");
++ return (ARCHIVE_WARN);
++ } else if (r)
++ ae_perm |= acl_inherit_map[i].archive_inherit;
++ }
++ }
+
+- acl_get_permset(acl_entry, &acl_permset);
+- for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
++ if (acl_get_permset(acl_entry, &acl_permset) != 0) {
++ archive_set_error(&a->archive, errno,
++ "Failed to get ACL permission set");
++ return (ARCHIVE_WARN);
++ }
++ for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
+ /*
+ * acl_get_perm() is spelled differently on different
+ * platforms; see above.
+ */
+- if (ACL_GET_PERM(acl_permset, acl_perm_map[i].platform_perm))
++ r = ACL_GET_PERM(acl_permset, acl_perm_map[i].platform_perm);
++ if (r == -1) {
++ archive_set_error(&a->archive, errno,
++ "Failed to check permission in an ACL permission set");
++ return (ARCHIVE_WARN);
++ } else if (r)
+ ae_perm |= acl_perm_map[i].archive_perm;
+ }
+
+@@ -649,6 +707,11 @@
+ ae_id, ae_name);
+
+ s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
++ if (s == -1) {
++ archive_set_error(&a->archive, errno,
++ "Failed to get next ACL entry");
++ return (ARCHIVE_WARN);
++ }
+ }
+ return (ARCHIVE_OK);
+ }
+--- contrib/libarchive/libarchive/archive_read_support_format_tar.c.orig
++++ contrib/libarchive/libarchive/archive_read_support_format_tar.c
+@@ -136,6 +136,7 @@
+ int64_t entry_padding;
+ int64_t entry_bytes_unconsumed;
+ int64_t realsize;
++ int sparse_allowed;
+ struct sparse_block *sparse_list;
+ struct sparse_block *sparse_last;
+ int64_t sparse_offset;
+@@ -1216,6 +1217,14 @@
+ * sparse information in the extended area.
+ */
+ /* FALLTHROUGH */
++ case '0':
++ /*
++ * Enable sparse file "read" support only for regular
++ * files and explicit GNU sparse files. However, we
++ * don't allow non-standard file types to be sparse.
++ */
++ tar->sparse_allowed = 1;
++ /* FALLTHROUGH */
+ default: /* Regular file and non-standard types */
+ /*
+ * Per POSIX: non-recognized types should always be
+@@ -1675,6 +1684,14 @@
+ #endif
+ switch (key[0]) {
+ case 'G':
++ /* Reject GNU.sparse.* headers on non-regular files. */
++ if (strncmp(key, "GNU.sparse", 10) == 0 &&
++ !tar->sparse_allowed) {
++ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
++ "Non-regular file cannot be sparse");
++ return (ARCHIVE_FATAL);
++ }
++
+ /* GNU "0.0" sparse pax format. */
+ if (strcmp(key, "GNU.sparse.numblocks") == 0) {
+ tar->sparse_offset = -1;
+--- contrib/libarchive/libarchive/archive_write_disk_acl.c.orig
++++ contrib/libarchive/libarchive/archive_write_disk_acl.c
+@@ -131,6 +131,7 @@
+ acl_entry_t acl_entry;
+ acl_permset_t acl_permset;
+ acl_flagset_t acl_flagset;
++ int r;
+ int ret;
+ int ae_type, ae_permset, ae_tag, ae_id;
+ uid_t ae_uid;
+@@ -144,9 +145,19 @@
+ if (entries == 0)
+ return (ARCHIVE_OK);
+ acl = acl_init(entries);
++ if (acl == (acl_t)NULL) {
++ archive_set_error(a, errno,
++ "Failed to initialize ACL working storage");
++ return (ARCHIVE_FAILED);
++ }
+ while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
+ &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
+- acl_create_entry(&acl, &acl_entry);
++ if (acl_create_entry(&acl, &acl_entry) != 0) {
++ archive_set_error(a, errno,
++ "Failed to create a new ACL entry");
++ ret = ARCHIVE_FAILED;
++ goto exit_free;
++ }
+
+ switch (ae_tag) {
+ case ARCHIVE_ENTRY_ACL_USER:
+@@ -175,47 +186,95 @@
+ acl_set_tag_type(acl_entry, ACL_EVERYONE);
+ break;
+ default:
+- /* XXX */
+- break;
++ archive_set_error(a, ARCHIVE_ERRNO_MISC,
++ "Unknown ACL tag");
++ ret = ARCHIVE_FAILED;
++ goto exit_free;
+ }
+
++ r = 0;
+ switch (ae_type) {
+ case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
+- acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALLOW);
++ r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALLOW);
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_DENY:
+- acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_DENY);
++ r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_DENY);
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
+- acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_AUDIT);
++ r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_AUDIT);
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
+- acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALARM);
++ r = acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALARM);
+ break;
+ case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
+ case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
+ // These don't translate directly into the system ACL.
+ break;
+ default:
+- // XXX error handling here.
+- break;
++ archive_set_error(a, ARCHIVE_ERRNO_MISC,
++ "Unknown ACL entry type");
++ ret = ARCHIVE_FAILED;
++ goto exit_free;
++ }
++ if (r != 0) {
++ archive_set_error(a, errno,
++ "Failed to set ACL entry type");
++ ret = ARCHIVE_FAILED;
++ goto exit_free;
+ }
+
+- acl_get_permset(acl_entry, &acl_permset);
+- acl_clear_perms(acl_permset);
++ if (acl_get_permset(acl_entry, &acl_permset) != 0) {
++ archive_set_error(a, errno,
++ "Failed to get ACL permission set");
++ ret = ARCHIVE_FAILED;
++ goto exit_free;
++ }
++ if (acl_clear_perms(acl_permset) != 0) {
++ archive_set_error(a, errno,
++ "Failed to clear ACL permissions");
++ ret = ARCHIVE_FAILED;
++ goto exit_free;
++ }
+
+ for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
+ if (ae_permset & acl_perm_map[i].archive_perm)
+- acl_add_perm(acl_permset,
+- acl_perm_map[i].platform_perm);
++ if (acl_add_perm(acl_permset,
++ acl_perm_map[i].platform_perm) != 0) {
++ archive_set_error(a, errno,
++ "Failed to add ACL permission");
++ ret = ARCHIVE_FAILED;
++ goto exit_free;
++ }
+ }
+
+ acl_get_flagset_np(acl_entry, &acl_flagset);
+- acl_clear_flags_np(acl_flagset);
+- for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) {
+- if (ae_permset & acl_inherit_map[i].archive_inherit)
+- acl_add_flag_np(acl_flagset,
+- acl_inherit_map[i].platform_inherit);
++ if (acl_type == ACL_TYPE_NFS4) {
++ /*
++ * acl_get_flagset_np() fails with non-NFSv4 ACLs
++ */
++ if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
++ archive_set_error(a, errno,
++ "Failed to get flagset from an NFSv4 ACL entry");
++ ret = ARCHIVE_FAILED;
++ goto exit_free;
++ }
++ if (acl_clear_flags_np(acl_flagset) != 0) {
++ archive_set_error(a, errno,
++ "Failed to clear flags from an NFSv4 ACL flagset");
++ ret = ARCHIVE_FAILED;
++ goto exit_free;
++ }
++ for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) {
++ if (ae_permset & acl_inherit_map[i].archive_inherit) {
++ if (acl_add_flag_np(acl_flagset,
++ acl_inherit_map[i].platform_inherit) != 0) {
++ archive_set_error(a, errno,
++ "Failed to add flag to NFSv4 ACL flagset");
++ ret = ARCHIVE_FAILED;
++ goto exit_free;
++ }
++ }
++ }
+ }
+ }
+
+@@ -243,6 +302,7 @@
+ ret = ARCHIVE_WARN;
+ }
+ #endif
++exit_free:
+ acl_free(acl);
+ return (ret);
+ }
+--- contrib/libarchive/libarchive/archive_write_disk_posix.c.orig
++++ contrib/libarchive/libarchive/archive_write_disk_posix.c
+@@ -140,7 +140,17 @@
+ #define O_BINARY 0
+ #endif
+ #ifndef O_CLOEXEC
+-#define O_CLOEXEC 0
++#define O_CLOEXEC 0
++#endif
++
++/* Ignore non-int O_NOFOLLOW constant. */
++/* gnulib's fcntl.h does this on AIX, but it seems practical everywhere */
++#if defined O_NOFOLLOW && !(INT_MIN <= O_NOFOLLOW && O_NOFOLLOW <= INT_MAX)
++#undef O_NOFOLLOW
++#endif
++
++#ifndef O_NOFOLLOW
++#define O_NOFOLLOW 0
+ #endif
+
+ struct fixup_entry {
+@@ -326,12 +336,14 @@
+
+ #define HFS_BLOCKS(s) ((s) >> 12)
+
++static int check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error_string, int flags);
+ static int check_symlinks(struct archive_write_disk *);
+ static int create_filesystem_object(struct archive_write_disk *);
+ static struct fixup_entry *current_fixup(struct archive_write_disk *, const char *pathname);
+ #if defined(HAVE_FCHDIR) && defined(PATH_MAX)
+ static void edit_deep_directories(struct archive_write_disk *ad);
+ #endif
++static int cleanup_pathname_fsobj(char *path, int *error_number, struct archive_string *error_string, int flags);
+ static int cleanup_pathname(struct archive_write_disk *);
+ static int create_dir(struct archive_write_disk *, char *);
+ static int create_parent_dir(struct archive_write_disk *, char *);
+@@ -1791,7 +1803,7 @@
+ char *tail = a->name;
+
+ /* If path is short, avoid the open() below. */
+- if (strlen(tail) <= PATH_MAX)
++ if (strlen(tail) < PATH_MAX)
+ return;
+
+ /* Try to record our starting dir. */
+@@ -1801,7 +1813,7 @@
+ return;
+
+ /* As long as the path is too long... */
+- while (strlen(tail) > PATH_MAX) {
++ while (strlen(tail) >= PATH_MAX) {
+ /* Locate a dir prefix shorter than PATH_MAX. */
+ tail += PATH_MAX - 8;
+ while (tail > a->name && *tail != '/')
+@@ -1996,6 +2008,10 @@
+ const char *linkname;
+ mode_t final_mode, mode;
+ int r;
++ /* these for check_symlinks_fsobj */
++ char *linkname_copy; /* non-const copy of linkname */
++ struct archive_string error_string;
++ int error_number;
+
+ /* We identify hard/symlinks according to the link names. */
+ /* Since link(2) and symlink(2) don't handle modes, we're done here. */
+@@ -2004,6 +2020,27 @@
+ #if !HAVE_LINK
+ return (EPERM);
+ #else
++ archive_string_init(&error_string);
++ linkname_copy = strdup(linkname);
++ if (linkname_copy == NULL) {
++ return (EPERM);
++ }
++ /* TODO: consider using the cleaned-up path as the link target? */
++ r = cleanup_pathname_fsobj(linkname_copy, &error_number, &error_string, a->flags);
++ if (r != ARCHIVE_OK) {
++ archive_set_error(&a->archive, error_number, "%s", error_string.s);
++ free(linkname_copy);
++ /* EPERM is more appropriate than error_number for our callers */
++ return (EPERM);
++ }
++ r = check_symlinks_fsobj(linkname_copy, &error_number, &error_string, a->flags);
++ if (r != ARCHIVE_OK) {
++ archive_set_error(&a->archive, error_number, "%s", error_string.s);
++ free(linkname_copy);
++ /* EPERM is more appropriate than error_number for our callers */
++ return (EPERM);
++ }
++ free(linkname_copy);
+ r = link(linkname, a->name) ? errno : 0;
+ /*
+ * New cpio and pax formats allow hardlink entries
+@@ -2022,7 +2059,7 @@
+ a->deferred = 0;
+ } else if (r == 0 && a->filesize > 0) {
+ a->fd = open(a->name,
+- O_WRONLY | O_TRUNC | O_BINARY | O_CLOEXEC);
++ O_WRONLY | O_TRUNC | O_BINARY | O_CLOEXEC | O_NOFOLLOW);
+ __archive_ensure_cloexec_flag(a->fd);
+ if (a->fd < 0)
+ r = errno;
+@@ -2332,110 +2369,233 @@
+ return (a->current_fixup);
+ }
+
+-/* TODO: Make this work. */
+-/*
+- * TODO: The deep-directory support bypasses this; disable deep directory
+- * support if we're doing symlink checks.
+- */
+ /*
+ * TODO: Someday, integrate this with the deep dir support; they both
+ * scan the path and both can be optimized by comparing against other
+ * recent paths.
+ */
+ /* TODO: Extend this to support symlinks on Windows Vista and later. */
++
++/*
++ * Checks the given path to see if any elements along it are symlinks. Returns
++ * ARCHIVE_OK if there are none, otherwise puts an error in errmsg.
++ */
+ static int
+-check_symlinks(struct archive_write_disk *a)
++check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error_string, int flags)
+ {
+ #if !defined(HAVE_LSTAT)
+ /* Platform doesn't have lstat, so we can't look for symlinks. */
+- (void)a; /* UNUSED */
++ (void)path; /* UNUSED */
++ (void)error_number; /* UNUSED */
++ (void)error_string; /* UNUSED */
++ (void)flags; /* UNUSED */
+ return (ARCHIVE_OK);
+ #else
+- char *pn;
++ int res = ARCHIVE_OK;
++ char *tail;
++ char *head;
++ int last;
+ char c;
+ int r;
+ struct stat st;
++ int restore_pwd;
++
++ /* Nothing to do here if name is empty */
++ if(path[0] == '\0')
++ return (ARCHIVE_OK);
+
+ /*
+ * Guard against symlink tricks. Reject any archive entry whose
+ * destination would be altered by a symlink.
++ *
++ * Walk the filename in chunks separated by '/'. For each segment:
++ * - if it doesn't exist, continue
++ * - if it's symlink, abort or remove it
++ * - if it's a directory and it's not the last chunk, cd into it
++ * As we go:
++ * head points to the current (relative) path
++ * tail points to the temporary \0 terminating the segment we're currently examining
++ * c holds what used to be in *tail
++ * last is 1 if this is the last tail
++ */
++ restore_pwd = open(".", O_RDONLY | O_BINARY | O_CLOEXEC);
++ __archive_ensure_cloexec_flag(restore_pwd);
++ if (restore_pwd < 0)
++ return (ARCHIVE_FATAL);
++ head = path;
++ tail = path;
++ last = 0;
++ /* TODO: reintroduce a safe cache here? */
++ /* Skip the root directory if the path is absolute. */
++ if(tail == path && tail[0] == '/')
++ ++tail;
++ /* Keep going until we've checked the entire name.
++ * head, tail, path all alias the same string, which is
++ * temporarily zeroed at tail, so be careful restoring the
++ * stashed (c=tail[0]) for error messages.
++ * Exiting the loop with break is okay; continue is not.
+ */
+- /* Whatever we checked last time doesn't need to be re-checked. */
+- pn = a->name;
+- if (archive_strlen(&(a->path_safe)) > 0) {
+- char *p = a->path_safe.s;
+- while ((*pn != '\0') && (*p == *pn))
+- ++p, ++pn;
+- }
+- c = pn[0];
+- /* Keep going until we've checked the entire name. */
+- while (pn[0] != '\0' && (pn[0] != '/' || pn[1] != '\0')) {
++ while (!last) {
++ /* Skip the separator we just consumed, plus any adjacent ones */
++ while (*tail == '/')
++ ++tail;
+ /* Skip the next path element. */
+- while (*pn != '\0' && *pn != '/')
+- ++pn;
+- c = pn[0];
+- pn[0] = '\0';
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-user
mailing list