svn commit: r292127 - head/usr.bin/unzip

Alex Kozlov ak at FreeBSD.org
Fri Dec 11 23:52:10 UTC 2015


Author: ak (ports committer)
Date: Fri Dec 11 23:52:08 2015
New Revision: 292127
URL: https://svnweb.freebsd.org/changeset/base/292127

Log:
  - Allow to extract symlinks
  - Implement 4-digit year format listing (-y option)
  - Improve detection of text files
  - Use %ju for error_count as it is unsigned
  
  Obtained from:	NetBSD
  Approved by:	des

Modified:
  head/usr.bin/unzip/unzip.1
  head/usr.bin/unzip/unzip.c

Modified: head/usr.bin/unzip/unzip.1
==============================================================================
--- head/usr.bin/unzip/unzip.1	Fri Dec 11 23:46:33 2015	(r292126)
+++ head/usr.bin/unzip/unzip.1	Fri Dec 11 23:52:08 2015	(r292127)
@@ -25,7 +25,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd May 10, 2012
+.Dd December 12, 2015
 .Dt UNZIP 1
 .Os
 .Sh NAME
@@ -33,7 +33,7 @@
 .Nd extract files from a ZIP archive
 .Sh SYNOPSIS
 .Nm
-.Op Fl aCcfjLlnopqtuv
+.Op Fl aCcfjLlnopqtuvy
 .Op Fl d Ar dir
 .Ar zipfile
 .Sh DESCRIPTION
@@ -102,6 +102,8 @@ content of the archive.
 .It Fl x Ar pattern
 Exclude files matching the pattern
 .Ar pattern .
+.It Fl y
+Print four digit years in listings instead of two.
 .It Fl Z Ar mode
 Emulate
 .Xr zipinfo 1L

Modified: head/usr.bin/unzip/unzip.c
==============================================================================
--- head/usr.bin/unzip/unzip.c	Fri Dec 11 23:46:33 2015	(r292126)
+++ head/usr.bin/unzip/unzip.c	Fri Dec 11 23:52:08 2015	(r292127)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2009 Joerg Sonnenberger <joerg at NetBSD.org>
+ * Copyright (c) 2009, 2010 Joerg Sonnenberger <joerg at NetBSD.org>
  * Copyright (c) 2007-2008 Dag-Erling Smørgrav
  * All rights reserved.
  *
@@ -65,6 +65,7 @@ static int		 q_opt;		/* quiet */
 static int		 t_opt;		/* test */
 static int		 u_opt;		/* update */
 static int		 v_opt;		/* verbose/list */
+static const char	*y_str = "";	/* 4 digit year */
 static int		 Z1_opt;	/* zipinfo mode list files only */
 
 /* debug flag */
@@ -461,6 +462,34 @@ handle_existing_file(char **path)
 }
 
 /*
+ * Detect binary files by a combination of character white list and
+ * black list. NUL bytes and other control codes without use in text files
+ * result directly in switching the file to binary mode. Otherwise, at least
+ * one white-listed byte has to be found.
+ *
+ * Black-listed: 0..6, 14..25, 28..31
+ * White-listed: 9..10, 13, >= 32
+ *
+ * See the proginfo/txtvsbin.txt in the zip sources for a detailed discussion.
+ */
+#define BYTE_IS_BINARY(x)	((x) < 32 && (0xf3ffc07fU & (1U << (x))))
+#define	BYTE_IS_TEXT(x)		((x) >= 32 || (0x00002600U & (1U << (x))))
+
+static int
+check_binary(const unsigned char *buf, size_t len)
+{
+	int rv;
+	for (rv = 1; len--; ++buf) {
+		if (BYTE_IS_BINARY(*buf))
+			return 1;
+		if (BYTE_IS_TEXT(*buf))
+			rv = 0;
+	}
+
+	return rv;
+}
+
+/*
  * Extract a regular file.
  */
 static void
@@ -472,6 +501,7 @@ extract_file(struct archive *a, struct a
 	struct timespec ts[2];
 	int cr, fd, text, warn, check;
 	ssize_t len;
+	const char *linkname;
 	unsigned char *p, *q, *end;
 
 	mode = archive_entry_mode(e) & 0777;
@@ -485,7 +515,7 @@ recheck:
 	if (lstat(*path, &sb) == 0) {
 		if (u_opt || f_opt) {
 			/* check if up-to-date */
-			if (S_ISREG(sb.st_mode) &&
+			if ((S_ISREG(sb.st_mode) || S_ISLNK(sb.st_mode)) &&
 			    (sb.st_mtim.tv_sec > mtime.tv_sec ||
 			    (sb.st_mtim.tv_sec == mtime.tv_sec &&
 			    sb.st_mtim.tv_nsec >= mtime.tv_nsec)))
@@ -509,6 +539,15 @@ recheck:
 			return;
 	}
 
+	/* process symlinks */
+	linkname = archive_entry_symlink(e);
+	if (linkname != NULL) {
+		if (symlink(linkname, *path) < 0)
+			error("symlink('%s')", *path);
+		info(" extracting: %s -> %s\n", *path, linkname);
+		return;
+	}
+
 	if ((fd = open(*path, O_RDWR|O_CREAT|O_TRUNC, mode)) < 0)
 		error("open('%s')", *path);
 
@@ -550,12 +589,8 @@ recheck:
 		 * guess wrong, we print a warning message later.
 		 */
 		if (a_opt && n == 0) {
-			for (p = buffer; p < end; ++p) {
-				if (!isascii((unsigned char)*p)) {
-					text = 0;
-					break;
-				}
-			}
+			if (check_binary(buffer, len))
+				text = 0;
 		}
 
 		/* simple case */
@@ -568,7 +603,7 @@ recheck:
 		/* hard case: convert \r\n to \n (sigh...) */
 		for (p = buffer; p < end; p = q + 1) {
 			for (q = p; q < end; q++) {
-				if (!warn && !isascii(*q)) {
+				if (!warn && BYTE_IS_BINARY(*q)) {
 					warningx("%s may be corrupted due"
 					    " to weak text file detection"
 					    " heuristic", *path);
@@ -639,7 +674,7 @@ extract(struct archive *a, struct archiv
 	}
 
 	/* I don't think this can happen in a zipfile.. */
-	if (!S_ISDIR(filetype) && !S_ISREG(filetype)) {
+	if (!S_ISDIR(filetype) && !S_ISREG(filetype) && !S_ISLNK(filetype)) {
 		warningx("skipping non-regular entry '%s'", pathname);
 		ac(archive_read_data_skip(a));
 		free(pathname);
@@ -695,7 +730,7 @@ extract_stdout(struct archive *a, struct
 	filetype = archive_entry_filetype(e);
 
 	/* I don't think this can happen in a zipfile.. */
-	if (!S_ISDIR(filetype) && !S_ISREG(filetype)) {
+	if (!S_ISDIR(filetype) && !S_ISREG(filetype) && !S_ISLNK(filetype)) {
 		warningx("skipping non-regular entry '%s'", pathname);
 		ac(archive_read_data_skip(a));
 		free(pathname);
@@ -753,12 +788,8 @@ extract_stdout(struct archive *a, struct
 		 * guess wrong, we print a warning message later.
 		 */
 		if (a_opt && n == 0) {
-			for (p = buffer; p < end; ++p) {
-				if (!isascii((unsigned char)*p)) {
-					text = 0;
-					break;
-				}
-			}
+			if (check_binary(buffer, len))
+				text = 0;
 		}
 
 		/* simple case */
@@ -771,7 +802,7 @@ extract_stdout(struct archive *a, struct
 		/* hard case: convert \r\n to \n (sigh...) */
 		for (p = buffer; p < end; p = q + 1) {
 			for (q = p; q < end; q++) {
-				if (!warn && !isascii(*q)) {
+				if (!warn && BYTE_IS_BINARY(*q)) {
 					warningx("%s may be corrupted due"
 					    " to weak text file detection"
 					    " heuristic", pathname);
@@ -802,9 +833,14 @@ list(struct archive *a, struct archive_e
 {
 	char buf[20];
 	time_t mtime;
+	struct tm *tm;
 
 	mtime = archive_entry_mtime(e);
-	strftime(buf, sizeof(buf), "%m-%d-%g %R", localtime(&mtime));
+	tm = localtime(&mtime);
+	if (*y_str)
+		strftime(buf, sizeof(buf), "%m-%d-%G %R", tm);
+	else
+		strftime(buf, sizeof(buf), "%m-%d-%g %R", tm);
 
 	if (!zipinfo_mode) {
 		if (v_opt == 1) {
@@ -877,11 +913,11 @@ unzip(const char *fn)
 		if (!p_opt && !q_opt)
 			printf("Archive:  %s\n", fn);
 		if (v_opt == 1) {
-			printf("  Length     Date   Time    Name\n");
-			printf(" --------    ----   ----    ----\n");
+			printf("  Length     %sDate   Time    Name\n", y_str);
+			printf(" --------    %s----   ----    ----\n", y_str);
 		} else if (v_opt == 2) {
-			printf(" Length   Method    Size  Ratio   Date   Time   CRC-32    Name\n");
-			printf("--------  ------  ------- -----   ----   ----   ------    ----\n");
+			printf(" Length   Method    Size  Ratio   %sDate   Time   CRC-32    Name\n", y_str);
+			printf("--------  ------  ------- -----   %s----   ----   ------    ----\n", y_str);
 		}
 	}
 
@@ -913,13 +949,13 @@ unzip(const char *fn)
 
 	if (zipinfo_mode) {
 		if (v_opt == 1) {
-			printf(" --------                   -------\n");
-			printf(" %8ju                   %ju file%s\n",
-			    total_size, file_count, file_count != 1 ? "s" : "");
+			printf(" --------                   %s-------\n", y_str);
+			printf(" %8ju                   %s%ju file%s\n",
+			    total_size, y_str, file_count, file_count != 1 ? "s" : "");
 		} else if (v_opt == 2) {
-			printf("--------          -------  ---                            -------\n");
-			printf("%8ju          %7ju   0%%                            %ju file%s\n",
-			    total_size, total_size, file_count,
+			printf("--------          -------  ---                            %s-------\n", y_str);
+			printf("%8ju          %7ju   0%%                            %s%ju file%s\n",
+			    total_size, total_size, y_str, file_count,
 			    file_count != 1 ? "s" : "");
 		}
 	}
@@ -929,7 +965,7 @@ unzip(const char *fn)
 
 	if (t_opt) {
 		if (error_count > 0) {
-			errorx("%d checksum error(s) found.", error_count);
+			errorx("%ju checksum error(s) found.", error_count);
 		}
 		else {
 			printf("No errors detected in compressed data of %s.\n",
@@ -942,7 +978,7 @@ static void
 usage(void)
 {
 
-	fprintf(stderr, "usage: unzip [-aCcfjLlnopqtuvZ1] [-d dir] [-x pattern] zipfile\n");
+	fprintf(stderr, "Usage: unzip [-aCcfjLlnopqtuvyZ1] [-d dir] [-x pattern] zipfile\n");
 	exit(1);
 }
 
@@ -952,7 +988,7 @@ getopts(int argc, char *argv[])
 	int opt;
 
 	optreset = optind = 1;
-	while ((opt = getopt(argc, argv, "aCcd:fjLlnopqtuvx:Z1")) != -1)
+	while ((opt = getopt(argc, argv, "aCcd:fjLlnopqtuvx:yZ1")) != -1)
 		switch (opt) {
 		case '1':
 			Z1_opt = 1;
@@ -1007,6 +1043,9 @@ getopts(int argc, char *argv[])
 		case 'x':
 			add_pattern(&exclude, optarg);
 			break;
+		case 'y':
+			y_str = "  ";
+			break;
 		case 'Z':
 			zipinfo_mode = 1;
 			break;


More information about the svn-src-all mailing list