Module Name:    src
Committed By:   christos
Date:           Thu Dec  3 20:00:12 UTC 2015

Modified Files:
        src/usr.bin/unzip: unzip.c

Log Message:
PR/50496: Alex Kozlov: teach unzip to extract symlinks

Our libarchive does not handle symliks yet, but later versions do.
Set mode and times for symlinks. Finally handle hardlinks for
completion although they are not handled yet by librarchive.


To generate a diff of this commit:
cvs rdiff -u -r1.19 -r1.20 src/usr.bin/unzip/unzip.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.bin/unzip/unzip.c
diff -u src/usr.bin/unzip/unzip.c:1.19 src/usr.bin/unzip/unzip.c:1.20
--- src/usr.bin/unzip/unzip.c:1.19	Tue Sep  6 14:43:41 2011
+++ src/usr.bin/unzip/unzip.c	Thu Dec  3 15:00:12 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: unzip.c,v 1.19 2011/09/06 18:43:41 joerg Exp $ */
+/* $NetBSD: unzip.c,v 1.20 2015/12/03 20:00:12 christos Exp $ */
 
 /*-
  * Copyright (c) 2009, 2010 Joerg Sonnenberger <jo...@netbsd.org>
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: unzip.c,v 1.19 2011/09/06 18:43:41 joerg Exp $");
+__RCSID("$NetBSD: unzip.c,v 1.20 2015/12/03 20:00:12 christos Exp $");
 
 #include <sys/queue.h>
 #include <sys/stat.h>
@@ -131,7 +131,6 @@ errorx(const char *fmt, ...)
 	exit(1);
 }
 
-#if 0
 /* non-fatal error message + errno */
 __printflike(1, 2) static void
 warning(const char *fmt, ...)
@@ -147,7 +146,7 @@ warning(const char *fmt, ...)
 	va_end(ap);
 	fprintf(stderr, ": %s\n", strerror(errno));
 }
-#endif
+
 /* non-fatal error message, no errno */
 __printflike(1, 2) static void
 warningx(const char *fmt, ...)
@@ -499,6 +498,7 @@ extract_file(struct archive *a, struct a
 	int cr, fd, text, warn, check;
 	ssize_t len;
 	unsigned char *p, *q, *end;
+	const char *linkname;
 
 	mode = archive_entry_mode(e) & 0777;
 	if (mode == 0)
@@ -531,6 +531,32 @@ recheck:
 			return;
 	}
 
+	/* process symlinks */
+	linkname = archive_entry_symlink(e);
+	if (linkname != NULL) {
+		if (symlink(linkname, *path) == -1)
+			error("symlink('%s', '%s')", linkname, *path);
+		info(" extracting: %s -> %s\n", *path, linkname);
+		if (lchmod(*path, mode) == -1)
+			warning("Cannot set mode for '%s'", *path);
+		tv[0].tv_sec = now;
+		tv[0].tv_usec = 0;
+		tv[1].tv_sec = mtime;
+		tv[1].tv_usec = 0;
+		if (lutimes(*path, tv) == -1)
+			warning("utimes('%s')", *path);
+		return;
+	}
+
+	/* process hardlinks */
+	linkname = archive_entry_hardlink(e);
+	if (linkname != NULL) {
+		if (link(linkname, *path) == -1)
+			error("link('%s', '%s')", linkname, *path);
+		info(" extracting: %s link to %s\n", *path, linkname);
+		return;
+	}
+
 	if ((fd = open(*path, O_RDWR|O_CREAT|O_TRUNC, mode)) < 0)
 		error("open('%s')", *path);
 
@@ -658,7 +684,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);
@@ -714,7 +740,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);

Reply via email to