/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Huffman decompressor
* Usage: pcat filename...
* or unpack filename...
*/
#include <setjmp.h>
#include <signal.h>
#include <locale.h>
#include <utime.h>
#include <aclutils.h>
#include <libcmdutils.h>
/* rmflg, when set it's ok to rm arvk file on caught signals */
static int rmflg = 0;
/* variables associated with i/o */
static short infile;
static short outfile;
static short inleft;
static short is_eof = 0;
static char *inp;
static char *outp;
/* the dictionary */
static long origsize;
static short maxlev;
static char *eof;
static void putch(char c);
static int expand();
static int decode();
static int getwdsize();
static int getch();
static int getdict();
/* Extended system attribute support */
static int saflg = 0;
/* read in the dictionary portion and build decoding structures */
/* return 1 if successful, 0 otherwise */
int
getdict()
{
register int c, i, nchildren;
/*
* check two-byte header
* get size of original file,
* get number of levels in maxlev,
* get number of leaves on level i in intnodes[i],
* set tree[i] to point to leaves for level i
*/
eof = &characters[0];
if (inleft < 0) {
perror("");
return (0);
}
goto goof;
return (0);
return (expand());
}
goto goof;
origsize = 0;
for (i = 0; i < 4; i++)
if (maxlev > 24) {
return (0);
}
for (i = 1; i <= maxlev; i++)
for (i = 1; i <= maxlev; i++) {
for (c = intnodes[i]; c > 0; c--) {
goto goof;
}
}
if (inleft < 0)
goto goof;
/*
* convert intnodes[i] to be number of
* internal nodes possessed by level i
*/
nchildren = 0;
for (i = maxlev; i >= 1; i--) {
c = intnodes[i];
nchildren += c;
}
return (decode());
}
/* unpack the file */
/* return 1 if successful, 0 otherwise */
int
decode()
{
register int bitsleft, c, i;
char *p;
lev = 1;
i = 0;
while (cont) {
if (inleft <= 0) {
if (inleft < 0) {
"%s: %s: read error: "),
perror("");
return (0);
}
}
if (--inleft < 0) {
"%s: %s: unpacking error\n"),
return (0);
}
c = *inp++;
bitsleft = 8;
while (--bitsleft >= 0) {
i *= 2;
if (c & 0200)
i++;
c <<= 1;
if (p == eof) {
!= c) {
"%s: %s: write error: "),
perror("");
return (0);
}
origsize -= c;
if (origsize != 0)
goto uggh;
return (1);
}
*outp++ = *p;
goto wrerr;
}
lev = 1;
i = 0;
} else
lev++;
}
}
return (1); /* we won't get here , but lint is pleased */
}
int
{
extern int optind;
int i, k;
int error;
int max_name;
void onsig(int);
int c;
char *progname;
int sattr_exist = 0;
int xattr_exist = 0;
#ifdef __STDC__
#else
#endif
#ifdef __STDC__
#else
#endif
#ifdef __STDC__
#else
#endif
#if !defined(TEXT_DOMAIN)
#endif
(void) textdomain(TEXT_DOMAIN);
++progname;
else
while (*p1++) { }; /* Point p1 to end of argv[0] string */
if (*p1 == '/')break;
if (c == '/') {
if (pcat)
++errflg;
else
saflg++;
} else
++errflg;
}
/*
* Check for invalid option. Also check for missing
* file operand, ie: "unpack" or "pcat".
*/
if (!pcat)
else
argv0);
if (argc < 1) {
/*
* return 1 for usage error when no file was specified
*/
return (1);
}
}
/* loop through the file names */
for (k = 0; k < argc; k++) {
fcount++; /* expect the worst */
if (errflg) {
/*
* invalid option; just count the number of files not
* unpacked
*/
continue;
}
/* remove any .z suffix the user may have added */
;
}
sep = -1;
/* copy argv[k] to filename and count chars in base name */
if (*cp++ == '/')
sep = i;
/* add .z suffix to filename */
*cp = '\0';
"%s: %s: cannot open: "),
perror("");
goto done;
}
if (pcat)
else {
if (error != 0) {
"%s: %s: cannot retrieve ACL : %s\n"),
}
if (max_name == -1) {
/* no limit on length of filename */
}
"%s: %s: file name too long\n"),
goto done;
}
"%s: %s: already exists\n"),
goto done;
}
"%s: %s: Warning: file has links\n"),
}
"%s: %s: cannot create: "),
perror("");
goto done;
}
rmflg = 1;
}
if (getdict()) { /* unpack */
xattr_exist = 1;
_PC_SATTR_EXISTS) == 1)
sattr_exist = 1;
sattr_exist, 0)
!= 0) {
/* Move attributes back ... */
xattr_exist = 0;
sattr_exist = 0;
== 1)
xattr_exist = 1;
_PC_SATTR_EXISTS) == 1)
sattr_exist = 1;
if (!pcat && (xattr_exist ||
sattr_exist)) {
sattr_exist, 1);
goto done;
}
} else {
if (!pcat)
}
} else if (!pcat)
if (!pcat) {
/*
* preserve acc & mod dates
*/
errflg++;
"%s: cannot change times on %s: "),
perror("");
}
errflg++;
"%s: cannot change mode to %o on %s: "),
argvk);
perror("");
}
perror("");
}
rmflg = 0;
}
if (!errflg)
fcount--; /* success after all */
}
if (!pcat)
if (aclp) {
}
}
return (fcount);
}
/*
* This code is for unpacking files that
* were packed using the previous algorithm.
*/
/* return 1 if successful, 0 otherwise */
int
expand()
{
short word;
int keysize, i, *t;
inleft -= 2;
"%s: %s: not in packed format\n"),
return (0);
}
t = Tree;
if ((i = getch()) == 0377)
*t++ = getwdsize();
else {
/*
* reached EOF unexpectedly
*/
if (is_eof) {
"%s: %s: not in packed format\n"),
return (0);
}
*t++ = i & 0377;
}
}
/*
* reached EOF unexpectedly
*/
if (is_eof) {
"%s: %s: not in packed format\n"),
return (0);
}
for (;;) {
if (bit <= 0) {
/*
* reached EOF unexpectedly
*/
"%s: %s: not in packed format\n"),
return (0);
}
bit = 16;
}
word <<= 1;
bit--;
tp = 0;
if ((origsize -= 1) == 0) {
return (1);
}
}
}
}
int
getch()
{
if (inleft <= 0) {
if (inleft < 0) {
"%s: %s: read error: "),
perror("");
} else { /* reached EOF, report it */
if (inleft == 0) {
is_eof = 1;
return (EOF);
}
}
}
inleft--;
return (*inp++ & 0377);
}
int
{
char c;
int d;
c = getch();
d = getch();
if (is_eof)
return (0);
d <<= 8;
d |= c & 0377;
return (d);
}
void
{
/* could be running as unpack or pcat */
/* but rmflg is set only when running */
/* as unpack and only when file is */
/* created by unpack and not yet done */
if (rmflg == 1)
/* To quiet lint noise */
exit(1);
}
void
putch(char c)
{
int n;
*outp++ = c;
if (n < BUFSIZ) {
"%s: %s: write error: "),
perror("");
}
}
}