summaryrefslogtreecommitdiff
path: root/usr/src/cmd/unpack/unpack.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/unpack/unpack.c')
-rw-r--r--usr/src/cmd/unpack/unpack.c265
1 files changed, 118 insertions, 147 deletions
diff --git a/usr/src/cmd/unpack/unpack.c b/usr/src/cmd/unpack/unpack.c
index 44f70ac51b..b95909d4a3 100644
--- a/usr/src/cmd/unpack/unpack.c
+++ b/usr/src/cmd/unpack/unpack.c
@@ -23,11 +23,11 @@
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.21 */
+#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Huffman decompressor
@@ -35,24 +35,16 @@
* or unpack filename...
*/
-#include <stdio.h>
-#include <fcntl.h>
#include <setjmp.h>
#include <signal.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
#include <locale.h>
#include <utime.h>
-#include <stdlib.h>
-#include <limits.h>
#include <sys/param.h>
-#include <dirent.h>
#include <sys/acl.h>
#include <aclutils.h>
+#include <libcmdutils.h>
static struct utimbuf u_times;
-
static jmp_buf env;
static struct stat status;
static char *argv0, *argvk;
@@ -91,7 +83,11 @@ static int decode();
static int getwdsize();
static int getch();
static int getdict();
-static int mv_xattrs();
+
+/* Extended system attribute support */
+
+static int saflg = 0;
+
/* read in the dictionary portion and build decoding structures */
/* return 1 if successful, 0 otherwise */
@@ -113,7 +109,7 @@ getdict()
inleft = read(infile, &inbuff[0], BUFSIZ);
if (inleft < 0) {
(void) fprintf(stderr, gettext(
- "%s: %s: read error: "), argv0, filename);
+ "%s: %s: read error: "), argv0, filename);
perror("");
return (0);
}
@@ -135,7 +131,7 @@ getdict()
maxlev = *inp++ & 0377;
if (maxlev > 24) {
goof: (void) fprintf(stderr, gettext(
- "%s: %s: not in packed format\n"), argv0, filename);
+ "%s: %s: not in packed format\n"), argv0, filename);
return (0);
}
for (i = 1; i <= maxlev; i++)
@@ -185,16 +181,16 @@ decode()
inleft = read(infile, inp = &inbuff[0], BUFSIZ);
if (inleft < 0) {
(void) fprintf(stderr, gettext(
- "%s: %s: read error: "),
- argv0, filename);
+ "%s: %s: read error: "),
+ argv0, filename);
perror("");
return (0);
}
}
if (--inleft < 0) {
uggh: (void) fprintf(stderr, gettext(
- "%s: %s: unpacking error\n"),
- argv0, filename);
+ "%s: %s: unpacking error\n"),
+ argv0, filename);
return (0);
}
c = *inp++;
@@ -208,10 +204,12 @@ uggh: (void) fprintf(stderr, gettext(
p = &tree[lev][j];
if (p == eof) {
c = outp - &outbuff[0];
- if (write(outfile, &outbuff[0], c) != c) {
-wrerr: (void) fprintf(stderr, gettext(
- "%s: %s: write error: "),
- argv0, argvk);
+ if (write(outfile, &outbuff[0], c)
+ != c) {
+wrerr: (void) fprintf(stderr,
+ gettext(
+ "%s: %s: write error: "),
+ argv0, argvk);
perror("");
return (0);
}
@@ -223,7 +221,7 @@ wrerr: (void) fprintf(stderr, gettext(
*outp++ = *p;
if (outp == &outbuff[BUFSIZ]) {
if (write(outfile, outp = &outbuff[0],
- BUFSIZ) != BUFSIZ)
+ BUFSIZ) != BUFSIZ)
goto wrerr;
origsize -= BUFSIZ;
}
@@ -248,25 +246,28 @@ main(int argc, char *argv[])
int max_name;
void onsig(int);
acl_t *aclp = NULL;
-
+ int c;
+ char *progname;
+ int sattr_exist = 0;
+ int xattr_exist = 0;
if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
#ifdef __STDC__
- signal((int)SIGHUP, onsig);
+ (void) signal((int)SIGHUP, onsig);
#else
- signal((int)SIGHUP, onsig);
+ (void) signal((int)SIGHUP, onsig);
#endif
if (signal(SIGINT, SIG_IGN) != SIG_IGN)
#ifdef __STDC__
- signal((int)SIGINT, onsig);
+ (void) signal((int)SIGINT, onsig);
#else
- signal((int)SIGINT, onsig);
+ (void) signal((int)SIGINT, onsig);
#endif
if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
#ifdef __STDC__
- signal((int)SIGTERM, onsig);
+ (void) signal((int)SIGTERM, onsig);
#else
- signal(SIGTERM, onsig);
+ (void) signal(SIGTERM, onsig);
#endif
(void) setlocale(LC_ALL, "");
@@ -275,16 +276,28 @@ main(int argc, char *argv[])
#endif
(void) textdomain(TEXT_DOMAIN);
+ if (progname = strrchr(argv[0], '/'))
+ ++progname;
+ else
+ progname = argv[0];
+
p1 = *argv;
- while (*p1++); /* Point p1 to end of argv[0] string */
+ while (*p1++) { }; /* Point p1 to end of argv[0] string */
while (--p1 >= *argv)
if (*p1 == '/')break;
*argv = p1 + 1;
argv0 = argv[0];
if (**argv == 'p')pcat++; /* User entered pcat (or /xx/xx/pcat) */
- while (getopt(argc, argv, "") != EOF)
- ++errflg;
+ while ((c = getopt(argc, argv, "/")) != EOF) {
+ if (c == '/') {
+ if (pcat)
+ ++errflg;
+ else
+ saflg++;
+ } else
+ ++errflg;
+ }
/*
* Check for invalid option. Also check for missing
* file operand, ie: "unpack" or "pcat".
@@ -292,7 +305,13 @@ main(int argc, char *argv[])
argc -= optind;
argv = &argv[optind];
if (errflg || argc < 1) {
- (void) fprintf(stderr, gettext("usage: %s file...\n"), argv0);
+ if (!pcat)
+ (void) fprintf(stderr,
+ gettext("usage: %s [-/] file...\n"), argv0);
+ else
+ (void) fprintf(stderr, gettext("usage: %s file...\n"),
+ argv0);
+
if (argc < 1) {
/*
* return 1 for usage error when no file was specified
@@ -329,8 +348,8 @@ main(int argc, char *argv[])
*cp = '\0';
if ((infile = open(filename, O_RDONLY)) == -1) {
(void) fprintf(stderr, gettext(
- "%s: %s: cannot open: "),
- argv0, filename);
+ "%s: %s: cannot open: "),
+ argv0, filename);
perror("");
goto done;
}
@@ -342,7 +361,7 @@ main(int argc, char *argv[])
if (error != 0) {
(void) printf(gettext(
"%s: %s: cannot retrieve ACL : %s\n"),
- argv0, filename, acl_strerror(error));
+ argv0, filename, acl_strerror(error));
}
max_name = pathconf(filename, _PC_NAME_MAX);
@@ -352,38 +371,69 @@ main(int argc, char *argv[])
}
if (i >= (MAXPATHLEN-1) || (i - sep - 1) > max_name) {
(void) fprintf(stderr, gettext(
- "%s: %s: file name too long\n"),
- argv0, argvk);
+ "%s: %s: file name too long\n"),
+ argv0, argvk);
goto done;
}
if (stat(argvk, &status) != -1) {
(void) fprintf(stderr, gettext(
- "%s: %s: already exists\n"),
- argv0, argvk);
+ "%s: %s: already exists\n"),
+ argv0, argvk);
goto done;
}
(void) fstat(infile, &status);
if (status.st_nlink != 1) {
(void) printf(gettext(
- "%s: %s: Warning: file has links\n"),
- argv0, filename);
+ "%s: %s: Warning: file has links\n"),
+ argv0, filename);
}
if ((outfile = creat(argvk, status.st_mode)) == -1) {
(void) fprintf(stderr, gettext(
- "%s: %s: cannot create: "),
- argv0, argvk);
+ "%s: %s: cannot create: "),
+ argv0, argvk);
perror("");
goto done;
}
rmflg = 1;
}
- if (getdict() && /* unpack */
- (pcat ||
- (pathconf(filename, _PC_XATTR_EXISTS) != 1) ||
- (mv_xattrs(infile, outfile,
- filename, 0) == 0))) {
+ if (getdict()) { /* unpack */
+ if (pathconf(filename, _PC_XATTR_EXISTS) == 1)
+ xattr_exist = 1;
+ if (saflg && sysattr_support(filename,
+ _PC_SATTR_EXISTS) == 1)
+ sattr_exist = 1;
+ if (pcat || xattr_exist || sattr_exist) {
+ if (mv_xattrs(progname, filename, argv[k],
+ sattr_exist, 0)
+ != 0) {
+ /* Move attributes back ... */
+ xattr_exist = 0;
+ sattr_exist = 0;
+ if (pathconf(argvk, _PC_XATTR_EXISTS)
+ == 1)
+ xattr_exist = 1;
+ if (saflg && sysattr_support(argvk,
+ _PC_SATTR_EXISTS) == 1)
+ sattr_exist = 1;
+ if (!pcat && (xattr_exist ||
+ sattr_exist)) {
+ (void) mv_xattrs(progname,
+ argv[k], filename,
+ sattr_exist, 1);
+ (void) unlink(argvk);
+ goto done;
+ }
+ } else {
+ if (!pcat)
+ (void) unlink(filename);
+ }
+ } else if (!pcat)
+ (void) unlink(filename);
+
if (!pcat) {
+ (void) printf(gettext("%s: %s: unpacked\n"),
+ argv0, argvk);
/*
* preserve acc & mod dates
*/
@@ -392,8 +442,8 @@ main(int argc, char *argv[])
if (utime(argvk, &u_times) != 0) {
errflg++;
(void) fprintf(stderr, gettext(
- "%s: cannot change times on %s: "),
- argv0, argvk);
+ "%s: cannot change times on %s: "),
+ argv0, argvk);
perror("");
}
if (chmod(argvk, status.st_mode) != 0) {
@@ -405,7 +455,7 @@ main(int argc, char *argv[])
perror("");
}
(void) chown(argvk,
- status.st_uid, status.st_gid);
+ status.st_uid, status.st_gid);
if (aclp && (facl_set(outfile, aclp) < 0)) {
(void) printf(gettext("%s: cannot "
"set ACL on %s: "), argv0, argvk);
@@ -413,22 +463,10 @@ main(int argc, char *argv[])
}
rmflg = 0;
- (void) printf(gettext("%s: %s: unpacked\n"),
- argv0, argvk);
- (void) unlink(filename);
-
}
if (!errflg)
fcount--; /* success after all */
}
- else
- if (!pcat) {
- if (pathconf(argvk, _PC_XATTR_EXISTS) == 1) {
- (void) mv_xattrs(outfile, infile,
- argvk, 1);
- }
- (void) unlink(argvk);
- }
done: (void) close(infile);
if (!pcat)
(void) close(outfile);
@@ -465,8 +503,8 @@ expand()
origsize += (unsigned)getwdsize();
if (origsize == 0 || is_eof) {
(void) fprintf(stderr, gettext(
- "%s: %s: not in packed format\n"),
- argv0, filename);
+ "%s: %s: not in packed format\n"),
+ argv0, filename);
return (0);
}
t = Tree;
@@ -479,8 +517,8 @@ expand()
*/
if (is_eof) {
(void) fprintf(stderr, gettext(
- "%s: %s: not in packed format\n"),
- argv0, filename);
+ "%s: %s: not in packed format\n"),
+ argv0, filename);
return (0);
}
*t++ = i & 0377;
@@ -491,8 +529,8 @@ expand()
*/
if (is_eof) {
(void) fprintf(stderr, gettext(
- "%s: %s: not in packed format\n"),
- argv0, filename);
+ "%s: %s: not in packed format\n"),
+ argv0, filename);
return (0);
}
@@ -506,8 +544,8 @@ expand()
*/
if (word == 0 && is_eof && origsize > 0) {
(void) fprintf(stderr, gettext(
- "%s: %s: not in packed format\n"),
- argv0, filename);
+ "%s: %s: not in packed format\n"),
+ argv0, filename);
return (0);
}
bit = 16;
@@ -533,8 +571,8 @@ getch()
inleft = read(infile, inp = inbuff, BUFSIZ);
if (inleft < 0) {
(void) fprintf(stderr, gettext(
- "%s: %s: read error: "),
- argv0, filename);
+ "%s: %s: read error: "),
+ argv0, filename);
perror("");
longjmp(env, 1);
} else { /* reached EOF, report it */
@@ -572,7 +610,9 @@ onsig(int sig)
/* created by unpack and not yet done */
if (rmflg == 1)
(void) unlink(argvk);
- exit(1);
+ /* To quiet lint noise */
+ if (sig == SIGTERM || sig == SIGHUP || sig == SIGINT)
+ exit(1);
}
void
@@ -585,79 +625,10 @@ putch(char c)
n = write(outfile, outp = outbuff, BUFSIZ);
if (n < BUFSIZ) {
(void) fprintf(stderr, gettext(
- "%s: %s: write error: "),
- argv0, argvk);
+ "%s: %s: write error: "),
+ argv0, argvk);
perror("");
longjmp(env, 2);
}
}
}
-
-/*
- * mv_xattrs - move (via renameat) all of the extended attributes
- * associated with the file referenced by infd to the file
- * referenced by outfd. The infile and silent arguments are
- * provided for error message processing. This function
- * returns 0 on success and -1 on error.
- */
-static int
-mv_xattrs(int infd, int outfd, char *infile, int silent)
-{
- int indfd, outdfd, tmpfd;
- DIR *dirp = NULL;
- struct dirent *dp = NULL;
- int error = 0;
- char *etext;
-
- indfd = outdfd = tmpfd = -1;
-
- if ((indfd = openat(infd, ".", O_RDONLY|O_XATTR)) == -1) {
- etext = gettext("cannot open source");
- error = -1;
- goto out;
- }
-
- if ((outdfd = openat(outfd, ".", O_RDONLY|O_XATTR)) == -1) {
- etext = gettext("cannot open target");
- error = -1;
- goto out;
- }
-
- if ((tmpfd = dup(indfd)) == -1) {
- etext = gettext("cannot dup descriptor");
- error = -1;
- goto out;
-
- }
- if ((dirp = fdopendir(tmpfd)) == NULL) {
- etext = gettext("cannot access source");
- error = -1;
- goto out;
- }
-
- while (dp = readdir(dirp)) {
- if ((dp->d_name[0] == '.' && dp->d_name[1] == '\0') ||
- (dp->d_name[0] == '.' && dp->d_name[1] == '.' &&
- dp->d_name[2] == '\0'))
- continue;
- if ((renameat(indfd, dp->d_name, outdfd, dp->d_name)) == -1) {
- etext = dp->d_name;
- error = -1;
- goto out;
- }
- }
-out:
- if (error == -1 && silent == 0) {
- fprintf(stderr, gettext(
- "unpack: %s: cannot move extended attributes, "),
- infile);
- perror(etext);
- }
- if (dirp)
- closedir(dirp);
- if (indfd != -1)
- close(indfd);
- if (outdfd != -1)
- close(outdfd);
- return (error);
-}