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);