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 <jo...@netbsd.org>
+ * Copyright (c) 2009, 2010 Joerg Sonnenberger <jo...@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;
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to