Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/usr.bin/unzip Add -p and -q support.
details: https://anonhg.NetBSD.org/src/rev/71f9fc259378
branches: trunk
changeset: 746881:71f9fc259378
user: joerg <joerg%NetBSD.org@localhost>
date: Sat Aug 22 02:19:42 2009 +0000
description:
Add -p and -q support.
diffstat:
usr.bin/unzip/unzip.1 | 22 +++++-
usr.bin/unzip/unzip.c | 153 +++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 164 insertions(+), 11 deletions(-)
diffs (289 lines):
diff -r f1ce47042a2f -r 71f9fc259378 usr.bin/unzip/unzip.1
--- a/usr.bin/unzip/unzip.1 Sat Aug 22 01:44:58 2009 +0000
+++ b/usr.bin/unzip/unzip.1 Sat Aug 22 02:19:42 2009 +0000
@@ -1,4 +1,5 @@
.\"-
+.\" Copyright (c) 2009 Joerg Sonnenberger <joerg%NetBSD.org@localhost>
.\" Copyright (c) 2007-2008 Dag-Erling Coïdan Smørgrav
.\" All rights reserved.
.\"
@@ -24,9 +25,9 @@
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD: revision 180125$
-.\" $NetBSD: unzip.1,v 1.2 2009/06/26 09:31:04 wiz Exp $
+.\" $NetBSD: unzip.1,v 1.3 2009/08/22 02:19:42 joerg Exp $
.\"
-.Dd June 30, 2008
+.Dd August 22, 2009
.Dt UNZIP 1
.Os
.Sh NAME
@@ -34,7 +35,7 @@
.Nd extract files from a ZIP archive
.Sh SYNOPSIS
.Nm
-.Op Fl afjLlnoqtu
+.Op Fl afjLlnopqtuv
.Op Fl d Ar dir
.Op Fl x Ar pattern
.Ar zipfile
@@ -65,9 +66,15 @@
already exists on disk, the file is silently skipped.
.It Fl o
Overwrite.
-When extacting a file from the zipfile, if a file with the same name
+When extracting a file from the zipfile, if a file with the same name
already exists on disk, the existing file is replaced with the file
from the zipfile.
+.It Fl p
+Extract to stdout.
+When extracting files from the zipfile, they are written to stdout.
+The normal output is suppressed as if
+.Fl q
+was specified.
.It Fl q
Quiet: print less information while extracting.
.It Fl t
@@ -79,6 +86,13 @@
already exists on disk, the existing file is replaced with the file
from the zipfile if and only if the latter is newer than the former.
Otherwise, the file is silently skipped.
+.It Fl v
+List verbosely, rather than extract, the contents of the zipfile.
+This differs from
+.Fl l
+by using the long listening.
+Note that most of the data is currently fake and does not reflect the
+content of the archive.
.It Fl x Ar pattern
Exclude files matching the pattern
.Ar pattern .
diff -r f1ce47042a2f -r 71f9fc259378 usr.bin/unzip/unzip.c
--- a/usr.bin/unzip/unzip.c Sat Aug 22 01:44:58 2009 +0000
+++ b/usr.bin/unzip/unzip.c Sat Aug 22 02:19:42 2009 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: unzip.c,v 1.1 2009/06/25 20:27:05 joerg Exp $ */
+/* $NetBSD: unzip.c,v 1.2 2009/08/22 02:19:42 joerg Exp $ */
/*-
* Copyright (c) 2009 Joerg Sonnenberger <joerg%NetBSD.org@localhost>
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: unzip.c,v 1.1 2009/06/25 20:27:05 joerg Exp $");
+__RCSID("$NetBSD: unzip.c,v 1.2 2009/08/22 02:19:42 joerg Exp $");
#include <sys/queue.h>
#include <sys/stat.h>
@@ -61,12 +61,13 @@
static int f_opt; /* update existing files only */
static int j_opt; /* junk directories */
static int L_opt; /* lowercase names */
-static int l_opt; /* list */
static int n_opt; /* never overwrite */
static int o_opt; /* always overwrite */
+static int p_opt; /* extract to stdout */
static int q_opt; /* quiet */
static int t_opt; /* test */
static int u_opt; /* update */
+static int v_opt; /* verbose */
/* time when unzip started */
static time_t now;
@@ -631,14 +632,142 @@
free(pathname);
}
+static void
+extract_stdout(struct archive *a, struct archive_entry *e)
+{
+ 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);
+
+ /* I don't think this can happen in a zipfile.. */
+ if (!S_ISDIR(filetype) && !S_ISREG(filetype)) {
+ warningx("skipping non-regular entry '%s'", pathname);
+ ac(archive_read_data_skip(a));
+ free(pathname);
+ return;
+ }
+
+ /* skip directories in -j case */
+ if (S_ISDIR(filetype)) {
+ ac(archive_read_data_skip(a));
+ free(pathname);
+ return;
+ }
+
+ /* apply include / exclude patterns */
+ if (!accept_pathname(pathname)) {
+ ac(archive_read_data_skip(a));
+ free(pathname);
+ return;
+ }
+
+ 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 (write(STDOUT_FILENO, "\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 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) {
+ for (p = buffer; p < end; ++p) {
+ if (!isascii((unsigned char)*p)) {
+ text = 0;
+ break;
+ }
+ }
+ }
+
+ /* simple case */
+ if (!a_opt || !text) {
+ if (write(STDOUT_FILENO, 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 && !isascii(*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(STDOUT_FILENO, p, q - p) != q - p)
+ error("write('%s')", pathname);
+ }
+ }
+
+ free(pathname);
+}
+
/*
* Print the name of an entry to stdout.
*/
static void
list(struct archive *a, struct archive_entry *e)
{
+ static int printed_header;
+ char buf[20];
+ time_t mtime;
- printf("%s\n", archive_entry_pathname(e));
+ if (!printed_header && !q_opt) {
+ printed_header = 1;
+ printf(" Length Method Size Ratio Date Time CRC-32 Name\n");
+ printf("-------- ------ ------- ----- ---- ---- ------ ----\n");
+ }
+
+ if (v_opt == 2) {
+ mtime = archive_entry_mtime(e);
+ strftime(buf, sizeof(buf), "%m-%d-%g %R", localtime(&mtime));
+ printf("%8ju Stored %7ju 0%% %s %08x %s\n",
+ (uintmax_t)archive_entry_size(e),
+ (uintmax_t)archive_entry_size(e),
+ buf,
+ 0U,
+ archive_entry_pathname(e));
+ } else {
+ printf("%s\n", archive_entry_pathname(e));
+ }
ac(archive_read_data_skip(a));
}
@@ -693,8 +822,10 @@
ac(ret);
if (t_opt)
test(a, e);
- else if (l_opt)
+ else if (v_opt)
list(a, e);
+ else if (p_opt)
+ extract_stdout(a, e);
else
extract(a, e);
}
@@ -722,7 +853,7 @@
int opt;
optreset = optind = 1;
- while ((opt = getopt(argc, argv, "ad:fjLlnoqtux:")) != -1)
+ while ((opt = getopt(argc, argv, "ad:fjLlnopqtuvx:")) != -1)
switch (opt) {
case 'a':
a_opt = 1;
@@ -740,13 +871,18 @@
L_opt = 1;
break;
case 'l':
- l_opt = 1;
+ if (v_opt == 0)
+ v_opt = 1;
break;
case 'n':
n_opt = 1;
break;
case 'o':
o_opt = 1;
+ q_opt = 1;
+ break;
+ case 'p':
+ p_opt = 1;
break;
case 'q':
q_opt = 1;
@@ -757,6 +893,9 @@
case 'u':
u_opt = 1;
break;
+ case 'v':
+ v_opt = 2;
+ break;
case 'x':
add_pattern(&exclude, optarg);
break;
Home |
Main Index |
Thread Index |
Old Index