Author: ak (ports committer)
Date: Fri Jan 15 22:58:23 2016
New Revision: 294107
URL: https://svnweb.freebsd.org/changeset/base/294107

Log:
  - Extract common code from extract()/extract_stdout() to extract2fd()
  - Update information about central directory handling
  
  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 Jan 15 22:49:20 2016        (r294106)
+++ head/usr.bin/unzip/unzip.1  Fri Jan 15 22:58:23 2016        (r294107)
@@ -154,8 +154,8 @@ option should only affect files which ar
 zipfile's central directory.
 Since the
 .Xr archive 3
-library reads zipfiles sequentially, and does not use the central
-directory, that information is not available to the
+library does not provide access to that information, it is not available
+to the
 .Nm
 utility.
 Instead, the

Modified: head/usr.bin/unzip/unzip.c
==============================================================================
--- head/usr.bin/unzip/unzip.c  Fri Jan 15 22:49:20 2016        (r294106)
+++ head/usr.bin/unzip/unzip.c  Fri Jan 15 22:58:23 2016        (r294107)
@@ -488,6 +488,92 @@ check_binary(const unsigned char *buf, s
 }
 
 /*
+ * Extract to a file descriptor
+ */
+static int
+extract2fd(struct archive *a, char *pathname, int fd)
+{
+       int cr, text, warn;
+       ssize_t len;
+       unsigned char *p, *q, *end;
+
+       text = a_opt;
+       warn = 0;
+       cr = 0;
+
+       /* loop over file contents and write to fd */
+       for (int n = 0; ; n++) {
+               if (fd != STDOUT_FILENO)
+                       if (tty && (n % 4) == 0)
+                               info(" %c\b\b", spinner[(n / 4) % sizeof 
spinner]);
+
+               len = archive_read_data(a, buffer, sizeof buffer);
+
+               if (len < 0)
+                       ac(len);
+
+               /* left over CR from previous buffer */
+               if (a_opt && cr) {
+                       if (len == 0 || buffer[0] != '\n')
+                               if (write(fd, "\r", 1) != 1)
+                                       error("write('%s')", pathname);
+                       cr = 0;
+               }
+
+               /* EOF */
+               if (len == 0)
+                       break;
+               end = buffer + len;
+
+               /*
+                * Detect whether this is a text file.  The correct way to
+                * do this is to check the least significant bit of the
+                * "internal file attributes" field of the corresponding
+                * file header in the central directory, but libarchive
+                * does not provide access to this field, so we have to
+                * guess by looking for non-ASCII characters in the
+                * buffer.  Hopefully we won't guess wrong.  If we do
+                * guess wrong, we print a warning message later.
+                */
+               if (a_opt && n == 0) {
+                       if (check_binary(buffer, len))
+                               text = 0;
+               }
+
+               /* simple case */
+               if (!a_opt || !text) {
+                       if (write(fd, buffer, len) != len)
+                               error("write('%s')", pathname);
+                       continue;
+               }
+
+               /* hard case: convert \r\n to \n (sigh...) */
+               for (p = buffer; p < end; p = q + 1) {
+                       for (q = p; q < end; q++) {
+                               if (!warn && BYTE_IS_BINARY(*q)) {
+                                       warningx("%s may be corrupted due"
+                                           " to weak text file detection"
+                                           " heuristic", pathname);
+                                       warn = 1;
+                               }
+                               if (q[0] != '\r')
+                                       continue;
+                               if (&q[1] == end) {
+                                       cr = 1;
+                                       break;
+                               }
+                               if (q[1] == '\n')
+                                       break;
+                       }
+                       if (write(fd, p, q - p) != q - p)
+                               error("write('%s')", pathname);
+               }
+       }
+
+       return text;
+}
+
+/*
  * Extract a regular file.
  */
 static void
@@ -497,10 +583,8 @@ extract_file(struct archive *a, struct a
        struct timespec mtime;
        struct stat sb;
        struct timespec ts[2];
-       int cr, fd, text, warn, check;
-       ssize_t len;
+       int fd, check, text;
        const char *linkname;
-       unsigned char *p, *q, *end;
 
        mode = archive_entry_mode(e) & 0777;
        if (mode == 0)
@@ -558,77 +642,10 @@ recheck:
        if ((fd = open(*path, O_RDWR|O_CREAT|O_TRUNC, mode)) < 0)
                error("open('%s')", *path);
 
-       /* loop over file contents and write to disk */
        info(" extracting: %s", *path);
-       text = a_opt;
-       warn = 0;
-       cr = 0;
-       for (int n = 0; ; n++) {
-               if (tty && (n % 4) == 0)
-                       info(" %c\b\b", spinner[(n / 4) % sizeof spinner]);
 
-               len = archive_read_data(a, buffer, sizeof buffer);
+       text = extract2fd(a, *path, fd);
 
-               if (len < 0)
-                       ac(len);
-
-               /* left over CR from previous buffer */
-               if (a_opt && cr) {
-                       if (len == 0 || buffer[0] != '\n')
-                               if (write(fd, "\r", 1) != 1)
-                                       error("write('%s')", *path);
-                       cr = 0;
-               }
-
-               /* EOF */
-               if (len == 0)
-                       break;
-               end = buffer + len;
-
-               /*
-                * Detect whether this is a text file.  The correct way to
-                * do this is to check the least significant bit of the
-                * "internal file attributes" field of the corresponding
-                * file header in the central directory, but libarchive
-                * does not read the central directory, so we have to
-                * guess by looking for non-ASCII characters in the
-                * buffer.  Hopefully we won't guess wrong.  If we do
-                * guess wrong, we print a warning message later.
-                */
-               if (a_opt && n == 0) {
-                       if (check_binary(buffer, len))
-                               text = 0;
-               }
-
-               /* simple case */
-               if (!a_opt || !text) {
-                       if (write(fd, buffer, len) != len)
-                               error("write('%s')", *path);
-                       continue;
-               }
-
-               /* hard case: convert \r\n to \n (sigh...) */
-               for (p = buffer; p < end; p = q + 1) {
-                       for (q = p; q < end; q++) {
-                               if (!warn && BYTE_IS_BINARY(*q)) {
-                                       warningx("%s may be corrupted due"
-                                           " to weak text file detection"
-                                           " heuristic", *path);
-                                       warn = 1;
-                               }
-                               if (q[0] != '\r')
-                                       continue;
-                               if (&q[1] == end) {
-                                       cr = 1;
-                                       break;
-                               }
-                               if (q[1] == '\n')
-                                       break;
-                       }
-                       if (write(fd, p, q - p) != q - p)
-                               error("write('%s')", *path);
-               }
-       }
        if (tty)
                info("  \b\b");
        if (text)
@@ -726,9 +743,6 @@ extract_stdout(struct archive *a, struct
 {
        char *pathname;
        mode_t filetype;
-       int cr, text, warn;
-       ssize_t len;
-       unsigned char *p, *q, *end;
 
        pathname = pathdup(archive_entry_pathname(e));
        filetype = archive_entry_filetype(e);
@@ -758,73 +772,7 @@ extract_stdout(struct archive *a, struct
        if (c_opt)
                info("x %s\n", pathname);
 
-       text = a_opt;
-       warn = 0;
-       cr = 0;
-       for (int n = 0; ; n++) {
-               len = archive_read_data(a, buffer, sizeof buffer);
-
-               if (len < 0)
-                       ac(len);
-
-               /* left over CR from previous buffer */
-               if (a_opt && cr) {
-                       if (len == 0 || buffer[0] != '\n') {
-                               if (fwrite("\r", 1, 1, stderr) != 1)
-                                       error("write('%s')", pathname);
-                       }
-                       cr = 0;
-               }
-
-               /* EOF */
-               if (len == 0)
-                       break;
-               end = buffer + len;
-
-               /*
-                * Detect whether this is a text file.  The correct way to
-                * do this is to check the least significant bit of the
-                * "internal file attributes" field of the corresponding
-                * file header in the central directory, but libarchive
-                * does not read the central directory, so we have to
-                * guess by looking for non-ASCII characters in the
-                * buffer.  Hopefully we won't guess wrong.  If we do
-                * guess wrong, we print a warning message later.
-                */
-               if (a_opt && n == 0) {
-                       if (check_binary(buffer, len))
-                               text = 0;
-               }
-
-               /* simple case */
-               if (!a_opt || !text) {
-                       if (fwrite(buffer, 1, len, stdout) != (size_t)len)
-                               error("write('%s')", pathname);
-                       continue;
-               }
-
-               /* hard case: convert \r\n to \n (sigh...) */
-               for (p = buffer; p < end; p = q + 1) {
-                       for (q = p; q < end; q++) {
-                               if (!warn && BYTE_IS_BINARY(*q)) {
-                                       warningx("%s may be corrupted due"
-                                           " to weak text file detection"
-                                           " heuristic", pathname);
-                                       warn = 1;
-                               }
-                               if (q[0] != '\r')
-                                       continue;
-                               if (&q[1] == end) {
-                                       cr = 1;
-                                       break;
-                               }
-                               if (q[1] == '\n')
-                                       break;
-                       }
-                       if (fwrite(p, 1, q - p, stdout) != (size_t)(q - p))
-                               error("write('%s')", pathname);
-               }
-       }
+       (void)extract2fd(a, pathname, STDOUT_FILENO);
 
        free(pathname);
 }
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to