10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 220Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 230Sstevel@tonic-gate /* All Rights Reserved */ 240Sstevel@tonic-gate 250Sstevel@tonic-gate 260Sstevel@tonic-gate /* 27*789Sahrens * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 280Sstevel@tonic-gate * Use is subject to license terms. 290Sstevel@tonic-gate */ 300Sstevel@tonic-gate 310Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.21 */ 320Sstevel@tonic-gate 330Sstevel@tonic-gate /* 340Sstevel@tonic-gate * Huffman decompressor 350Sstevel@tonic-gate * Usage: pcat filename... 360Sstevel@tonic-gate * or unpack filename... 370Sstevel@tonic-gate */ 380Sstevel@tonic-gate 390Sstevel@tonic-gate #include <stdio.h> 400Sstevel@tonic-gate #include <fcntl.h> 410Sstevel@tonic-gate #include <setjmp.h> 420Sstevel@tonic-gate #include <signal.h> 430Sstevel@tonic-gate #include <sys/types.h> 440Sstevel@tonic-gate #include <sys/stat.h> 450Sstevel@tonic-gate #include <unistd.h> 460Sstevel@tonic-gate #include <locale.h> 470Sstevel@tonic-gate #include <utime.h> 480Sstevel@tonic-gate #include <stdlib.h> 490Sstevel@tonic-gate #include <limits.h> 500Sstevel@tonic-gate #include <sys/param.h> 510Sstevel@tonic-gate #include <dirent.h> 52*789Sahrens #include <sys/acl.h> 53*789Sahrens #include <aclutils.h> 540Sstevel@tonic-gate 550Sstevel@tonic-gate static struct utimbuf u_times; 560Sstevel@tonic-gate 570Sstevel@tonic-gate static jmp_buf env; 580Sstevel@tonic-gate static struct stat status; 590Sstevel@tonic-gate static char *argv0, *argvk; 600Sstevel@tonic-gate 610Sstevel@tonic-gate /* rmflg, when set it's ok to rm arvk file on caught signals */ 620Sstevel@tonic-gate static int rmflg = 0; 630Sstevel@tonic-gate 640Sstevel@tonic-gate #define SUF0 '.' 650Sstevel@tonic-gate #define SUF1 'z' 660Sstevel@tonic-gate #define US 037 670Sstevel@tonic-gate #define RS 036 680Sstevel@tonic-gate 690Sstevel@tonic-gate /* variables associated with i/o */ 700Sstevel@tonic-gate static char filename[MAXPATHLEN]; 710Sstevel@tonic-gate 720Sstevel@tonic-gate static short infile; 730Sstevel@tonic-gate static short outfile; 740Sstevel@tonic-gate static short inleft; 750Sstevel@tonic-gate static short is_eof = 0; 760Sstevel@tonic-gate static char *inp; 770Sstevel@tonic-gate static char *outp; 780Sstevel@tonic-gate static char inbuff[BUFSIZ]; 790Sstevel@tonic-gate static char outbuff[BUFSIZ]; 800Sstevel@tonic-gate 810Sstevel@tonic-gate /* the dictionary */ 820Sstevel@tonic-gate static long origsize; 830Sstevel@tonic-gate static short maxlev; 840Sstevel@tonic-gate static short intnodes[25]; 850Sstevel@tonic-gate static char *tree[25]; 860Sstevel@tonic-gate static char characters[256]; 870Sstevel@tonic-gate static char *eof; 880Sstevel@tonic-gate 890Sstevel@tonic-gate static void putch(char c); 900Sstevel@tonic-gate static int expand(); 910Sstevel@tonic-gate static int decode(); 920Sstevel@tonic-gate static int getwdsize(); 930Sstevel@tonic-gate static int getch(); 940Sstevel@tonic-gate static int getdict(); 950Sstevel@tonic-gate static int mv_xattrs(); 960Sstevel@tonic-gate 970Sstevel@tonic-gate /* read in the dictionary portion and build decoding structures */ 980Sstevel@tonic-gate /* return 1 if successful, 0 otherwise */ 990Sstevel@tonic-gate int 1000Sstevel@tonic-gate getdict() 1010Sstevel@tonic-gate { 1020Sstevel@tonic-gate register int c, i, nchildren; 1030Sstevel@tonic-gate 1040Sstevel@tonic-gate /* 1050Sstevel@tonic-gate * check two-byte header 1060Sstevel@tonic-gate * get size of original file, 1070Sstevel@tonic-gate * get number of levels in maxlev, 1080Sstevel@tonic-gate * get number of leaves on level i in intnodes[i], 1090Sstevel@tonic-gate * set tree[i] to point to leaves for level i 1100Sstevel@tonic-gate */ 1110Sstevel@tonic-gate eof = &characters[0]; 1120Sstevel@tonic-gate 1130Sstevel@tonic-gate inbuff[6] = 25; 1140Sstevel@tonic-gate inleft = read(infile, &inbuff[0], BUFSIZ); 1150Sstevel@tonic-gate if (inleft < 0) { 1160Sstevel@tonic-gate (void) fprintf(stderr, gettext( 1170Sstevel@tonic-gate "%s: %s: read error: "), argv0, filename); 1180Sstevel@tonic-gate perror(""); 1190Sstevel@tonic-gate return (0); 1200Sstevel@tonic-gate } 1210Sstevel@tonic-gate if (inbuff[0] != US) 1220Sstevel@tonic-gate goto goof; 1230Sstevel@tonic-gate 1240Sstevel@tonic-gate if (inbuff[1] == US) { /* oldstyle packing */ 1250Sstevel@tonic-gate if (setjmp(env)) 1260Sstevel@tonic-gate return (0); 1270Sstevel@tonic-gate return (expand()); 1280Sstevel@tonic-gate } 1290Sstevel@tonic-gate if (inbuff[1] != RS) 1300Sstevel@tonic-gate goto goof; 1310Sstevel@tonic-gate 1320Sstevel@tonic-gate inp = &inbuff[2]; 1330Sstevel@tonic-gate origsize = 0; 1340Sstevel@tonic-gate for (i = 0; i < 4; i++) 1350Sstevel@tonic-gate origsize = origsize*256 + ((*inp++) & 0377); 1360Sstevel@tonic-gate maxlev = *inp++ & 0377; 1370Sstevel@tonic-gate if (maxlev > 24) { 1380Sstevel@tonic-gate goof: (void) fprintf(stderr, gettext( 1390Sstevel@tonic-gate "%s: %s: not in packed format\n"), argv0, filename); 1400Sstevel@tonic-gate return (0); 1410Sstevel@tonic-gate } 1420Sstevel@tonic-gate for (i = 1; i <= maxlev; i++) 1430Sstevel@tonic-gate intnodes[i] = *inp++ & 0377; 1440Sstevel@tonic-gate for (i = 1; i <= maxlev; i++) { 1450Sstevel@tonic-gate tree[i] = eof; 1460Sstevel@tonic-gate for (c = intnodes[i]; c > 0; c--) { 1470Sstevel@tonic-gate if (eof >= &characters[255]) 1480Sstevel@tonic-gate goto goof; 1490Sstevel@tonic-gate *eof++ = *inp++; 1500Sstevel@tonic-gate } 1510Sstevel@tonic-gate } 1520Sstevel@tonic-gate *eof++ = *inp++; 1530Sstevel@tonic-gate intnodes[maxlev] += 2; 1540Sstevel@tonic-gate inleft -= inp - &inbuff[0]; 1550Sstevel@tonic-gate if (inleft < 0) 1560Sstevel@tonic-gate goto goof; 1570Sstevel@tonic-gate 1580Sstevel@tonic-gate /* 1590Sstevel@tonic-gate * convert intnodes[i] to be number of 1600Sstevel@tonic-gate * internal nodes possessed by level i 1610Sstevel@tonic-gate */ 1620Sstevel@tonic-gate 1630Sstevel@tonic-gate nchildren = 0; 1640Sstevel@tonic-gate for (i = maxlev; i >= 1; i--) { 1650Sstevel@tonic-gate c = intnodes[i]; 1660Sstevel@tonic-gate intnodes[i] = nchildren /= 2; 1670Sstevel@tonic-gate nchildren += c; 1680Sstevel@tonic-gate } 1690Sstevel@tonic-gate return (decode()); 1700Sstevel@tonic-gate } 1710Sstevel@tonic-gate 1720Sstevel@tonic-gate /* unpack the file */ 1730Sstevel@tonic-gate /* return 1 if successful, 0 otherwise */ 1740Sstevel@tonic-gate int 1750Sstevel@tonic-gate decode() 1760Sstevel@tonic-gate { 1770Sstevel@tonic-gate register int bitsleft, c, i; 1780Sstevel@tonic-gate int j, lev, cont = 1; 1790Sstevel@tonic-gate char *p; 1800Sstevel@tonic-gate 1810Sstevel@tonic-gate outp = &outbuff[0]; 1820Sstevel@tonic-gate lev = 1; 1830Sstevel@tonic-gate i = 0; 1840Sstevel@tonic-gate while (cont) { 1850Sstevel@tonic-gate if (inleft <= 0) { 1860Sstevel@tonic-gate inleft = read(infile, inp = &inbuff[0], BUFSIZ); 1870Sstevel@tonic-gate if (inleft < 0) { 1880Sstevel@tonic-gate (void) fprintf(stderr, gettext( 1890Sstevel@tonic-gate "%s: %s: read error: "), 1900Sstevel@tonic-gate argv0, filename); 1910Sstevel@tonic-gate perror(""); 1920Sstevel@tonic-gate return (0); 1930Sstevel@tonic-gate } 1940Sstevel@tonic-gate } 1950Sstevel@tonic-gate if (--inleft < 0) { 1960Sstevel@tonic-gate uggh: (void) fprintf(stderr, gettext( 1970Sstevel@tonic-gate "%s: %s: unpacking error\n"), 1980Sstevel@tonic-gate argv0, filename); 1990Sstevel@tonic-gate return (0); 2000Sstevel@tonic-gate } 2010Sstevel@tonic-gate c = *inp++; 2020Sstevel@tonic-gate bitsleft = 8; 2030Sstevel@tonic-gate while (--bitsleft >= 0) { 2040Sstevel@tonic-gate i *= 2; 2050Sstevel@tonic-gate if (c & 0200) 2060Sstevel@tonic-gate i++; 2070Sstevel@tonic-gate c <<= 1; 2080Sstevel@tonic-gate if ((j = i - intnodes[lev]) >= 0) { 2090Sstevel@tonic-gate p = &tree[lev][j]; 2100Sstevel@tonic-gate if (p == eof) { 2110Sstevel@tonic-gate c = outp - &outbuff[0]; 2120Sstevel@tonic-gate if (write(outfile, &outbuff[0], c) != c) { 2130Sstevel@tonic-gate wrerr: (void) fprintf(stderr, gettext( 2140Sstevel@tonic-gate "%s: %s: write error: "), 2150Sstevel@tonic-gate argv0, argvk); 2160Sstevel@tonic-gate perror(""); 2170Sstevel@tonic-gate return (0); 2180Sstevel@tonic-gate } 2190Sstevel@tonic-gate origsize -= c; 2200Sstevel@tonic-gate if (origsize != 0) 2210Sstevel@tonic-gate goto uggh; 2220Sstevel@tonic-gate return (1); 2230Sstevel@tonic-gate } 2240Sstevel@tonic-gate *outp++ = *p; 2250Sstevel@tonic-gate if (outp == &outbuff[BUFSIZ]) { 2260Sstevel@tonic-gate if (write(outfile, outp = &outbuff[0], 2270Sstevel@tonic-gate BUFSIZ) != BUFSIZ) 2280Sstevel@tonic-gate goto wrerr; 2290Sstevel@tonic-gate origsize -= BUFSIZ; 2300Sstevel@tonic-gate } 2310Sstevel@tonic-gate lev = 1; 2320Sstevel@tonic-gate i = 0; 2330Sstevel@tonic-gate } else 2340Sstevel@tonic-gate lev++; 2350Sstevel@tonic-gate } 2360Sstevel@tonic-gate } 2370Sstevel@tonic-gate return (1); /* we won't get here , but lint is pleased */ 2380Sstevel@tonic-gate } 2390Sstevel@tonic-gate 2400Sstevel@tonic-gate int 2410Sstevel@tonic-gate main(int argc, char *argv[]) 2420Sstevel@tonic-gate { 2430Sstevel@tonic-gate extern int optind; 2440Sstevel@tonic-gate int i, k; 245*789Sahrens int error; 2460Sstevel@tonic-gate int sep, errflg = 0, pcat = 0; 2470Sstevel@tonic-gate register char *p1, *cp; 2480Sstevel@tonic-gate int fcount = 0; /* failure count */ 2490Sstevel@tonic-gate int max_name; 2500Sstevel@tonic-gate void onsig(int); 251*789Sahrens acl_t *aclp; 2520Sstevel@tonic-gate 2530Sstevel@tonic-gate 2540Sstevel@tonic-gate if (signal(SIGHUP, SIG_IGN) != SIG_IGN) 2550Sstevel@tonic-gate #ifdef __STDC__ 2560Sstevel@tonic-gate signal((int)SIGHUP, onsig); 2570Sstevel@tonic-gate #else 2580Sstevel@tonic-gate signal((int)SIGHUP, onsig); 2590Sstevel@tonic-gate #endif 2600Sstevel@tonic-gate if (signal(SIGINT, SIG_IGN) != SIG_IGN) 2610Sstevel@tonic-gate #ifdef __STDC__ 2620Sstevel@tonic-gate signal((int)SIGINT, onsig); 2630Sstevel@tonic-gate #else 2640Sstevel@tonic-gate signal((int)SIGINT, onsig); 2650Sstevel@tonic-gate #endif 2660Sstevel@tonic-gate if (signal(SIGTERM, SIG_IGN) != SIG_IGN) 2670Sstevel@tonic-gate #ifdef __STDC__ 2680Sstevel@tonic-gate signal((int)SIGTERM, onsig); 2690Sstevel@tonic-gate #else 2700Sstevel@tonic-gate signal(SIGTERM, onsig); 2710Sstevel@tonic-gate #endif 2720Sstevel@tonic-gate 2730Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 2740Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 2750Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 2760Sstevel@tonic-gate #endif 2770Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 2780Sstevel@tonic-gate 2790Sstevel@tonic-gate p1 = *argv; 2800Sstevel@tonic-gate while (*p1++); /* Point p1 to end of argv[0] string */ 2810Sstevel@tonic-gate while (--p1 >= *argv) 2820Sstevel@tonic-gate if (*p1 == '/')break; 2830Sstevel@tonic-gate *argv = p1 + 1; 2840Sstevel@tonic-gate argv0 = argv[0]; 2850Sstevel@tonic-gate if (**argv == 'p')pcat++; /* User entered pcat (or /xx/xx/pcat) */ 2860Sstevel@tonic-gate 2870Sstevel@tonic-gate while (getopt(argc, argv, "") != EOF) 2880Sstevel@tonic-gate ++errflg; 2890Sstevel@tonic-gate /* 2900Sstevel@tonic-gate * Check for invalid option. Also check for missing 2910Sstevel@tonic-gate * file operand, ie: "unpack" or "pcat". 2920Sstevel@tonic-gate */ 2930Sstevel@tonic-gate argc -= optind; 2940Sstevel@tonic-gate argv = &argv[optind]; 2950Sstevel@tonic-gate if (errflg || argc < 1) { 2960Sstevel@tonic-gate (void) fprintf(stderr, gettext("usage: %s file...\n"), argv0); 2970Sstevel@tonic-gate if (argc < 1) { 2980Sstevel@tonic-gate /* 2990Sstevel@tonic-gate * return 1 for usage error when no file was specified 3000Sstevel@tonic-gate */ 3010Sstevel@tonic-gate return (1); 3020Sstevel@tonic-gate } 3030Sstevel@tonic-gate } 3040Sstevel@tonic-gate /* loop through the file names */ 3050Sstevel@tonic-gate for (k = 0; k < argc; k++) { 3060Sstevel@tonic-gate fcount++; /* expect the worst */ 3070Sstevel@tonic-gate if (errflg) { 3080Sstevel@tonic-gate /* 3090Sstevel@tonic-gate * invalid option; just count the number of files not 3100Sstevel@tonic-gate * unpacked 3110Sstevel@tonic-gate */ 3120Sstevel@tonic-gate continue; 3130Sstevel@tonic-gate } 3140Sstevel@tonic-gate /* remove any .z suffix the user may have added */ 3150Sstevel@tonic-gate for (cp = argv[k]; *cp != '\0'; ++cp) 3160Sstevel@tonic-gate ; 3170Sstevel@tonic-gate if (cp[-1] == SUF1 && cp[-2] == SUF0) { 3180Sstevel@tonic-gate *cp-- = '\0'; *cp-- = '\0'; *cp = '\0'; 3190Sstevel@tonic-gate } 3200Sstevel@tonic-gate sep = -1; 3210Sstevel@tonic-gate cp = filename; 3220Sstevel@tonic-gate argvk = argv[k]; 3230Sstevel@tonic-gate /* copy argv[k] to filename and count chars in base name */ 3240Sstevel@tonic-gate for (i = 0; i < (MAXPATHLEN-3) && (*cp = argvk[i]); i++) 3250Sstevel@tonic-gate if (*cp++ == '/') 3260Sstevel@tonic-gate sep = i; 3270Sstevel@tonic-gate /* add .z suffix to filename */ 3280Sstevel@tonic-gate *cp++ = SUF0; 3290Sstevel@tonic-gate *cp++ = SUF1; 3300Sstevel@tonic-gate *cp = '\0'; 3310Sstevel@tonic-gate if ((infile = open(filename, O_RDONLY)) == -1) { 3320Sstevel@tonic-gate (void) fprintf(stderr, gettext( 3330Sstevel@tonic-gate "%s: %s: cannot open: "), 3340Sstevel@tonic-gate argv0, filename); 3350Sstevel@tonic-gate perror(""); 3360Sstevel@tonic-gate goto done; 3370Sstevel@tonic-gate } 3380Sstevel@tonic-gate if (pcat) 3390Sstevel@tonic-gate outfile = 1; /* standard output */ 3400Sstevel@tonic-gate else { 341*789Sahrens 342*789Sahrens error = facl_get(infile, ACL_NO_TRIVIAL, &aclp); 343*789Sahrens if (error != 0) { 344*789Sahrens (void) printf(gettext( 345*789Sahrens "%s: %s: cannot retrieve ACL : %s\n"), 346*789Sahrens argv0, filename, acl_strerror(error)); 347*789Sahrens } 348*789Sahrens 3490Sstevel@tonic-gate max_name = pathconf(filename, _PC_NAME_MAX); 3500Sstevel@tonic-gate if (max_name == -1) { 3510Sstevel@tonic-gate /* no limit on length of filename */ 3520Sstevel@tonic-gate max_name = _POSIX_NAME_MAX; 3530Sstevel@tonic-gate } 3540Sstevel@tonic-gate if (i >= (MAXPATHLEN-1) || (i - sep - 1) > max_name) { 3550Sstevel@tonic-gate (void) fprintf(stderr, gettext( 3560Sstevel@tonic-gate "%s: %s: file name too long\n"), 3570Sstevel@tonic-gate argv0, argvk); 3580Sstevel@tonic-gate goto done; 3590Sstevel@tonic-gate } 3600Sstevel@tonic-gate if (stat(argvk, &status) != -1) { 3610Sstevel@tonic-gate (void) fprintf(stderr, gettext( 3620Sstevel@tonic-gate "%s: %s: already exists\n"), 3630Sstevel@tonic-gate argv0, argvk); 3640Sstevel@tonic-gate goto done; 3650Sstevel@tonic-gate } 3660Sstevel@tonic-gate (void) fstat(infile, &status); 3670Sstevel@tonic-gate if (status.st_nlink != 1) { 3680Sstevel@tonic-gate (void) printf(gettext( 3690Sstevel@tonic-gate "%s: %s: Warning: file has links\n"), 3700Sstevel@tonic-gate argv0, filename); 3710Sstevel@tonic-gate } 3720Sstevel@tonic-gate if ((outfile = creat(argvk, status.st_mode)) == -1) { 3730Sstevel@tonic-gate (void) fprintf(stderr, gettext( 3740Sstevel@tonic-gate "%s: %s: cannot create: "), 3750Sstevel@tonic-gate argv0, argvk); 3760Sstevel@tonic-gate perror(""); 3770Sstevel@tonic-gate goto done; 3780Sstevel@tonic-gate } 3790Sstevel@tonic-gate rmflg = 1; 3800Sstevel@tonic-gate } 3810Sstevel@tonic-gate 3820Sstevel@tonic-gate if (getdict() && /* unpack */ 3830Sstevel@tonic-gate (pcat || 3840Sstevel@tonic-gate (pathconf(filename, _PC_XATTR_EXISTS) != 1) || 3850Sstevel@tonic-gate (mv_xattrs(infile, outfile, 3860Sstevel@tonic-gate filename, 0) == 0))) { 3870Sstevel@tonic-gate if (!pcat) { 3880Sstevel@tonic-gate /* 3890Sstevel@tonic-gate * preserve acc & mod dates 3900Sstevel@tonic-gate */ 3910Sstevel@tonic-gate u_times.actime = status.st_atime; 3920Sstevel@tonic-gate u_times.modtime = status.st_mtime; 3930Sstevel@tonic-gate if (utime(argvk, &u_times) != 0) { 3940Sstevel@tonic-gate errflg++; 3950Sstevel@tonic-gate (void) fprintf(stderr, gettext( 3960Sstevel@tonic-gate "%s: cannot change times on %s: "), 3970Sstevel@tonic-gate argv0, argvk); 3980Sstevel@tonic-gate perror(""); 3990Sstevel@tonic-gate } 4000Sstevel@tonic-gate if (chmod(argvk, status.st_mode) != 0) { 4010Sstevel@tonic-gate errflg++; 4020Sstevel@tonic-gate (void) fprintf(stderr, gettext( 4030Sstevel@tonic-gate "%s: cannot change mode to %o on %s: "), 4040Sstevel@tonic-gate argv0, (uint_t)status.st_mode, 4050Sstevel@tonic-gate argvk); 4060Sstevel@tonic-gate perror(""); 4070Sstevel@tonic-gate } 4080Sstevel@tonic-gate (void) chown(argvk, 4090Sstevel@tonic-gate status.st_uid, status.st_gid); 410*789Sahrens if (aclp && (facl_set(outfile, aclp) < 0)) { 411*789Sahrens (void) printf(gettext("%s: cannot " 412*789Sahrens "set ACL on %s: "), argv0, argvk); 413*789Sahrens perror(""); 414*789Sahrens } 415*789Sahrens 4160Sstevel@tonic-gate rmflg = 0; 4170Sstevel@tonic-gate (void) printf(gettext("%s: %s: unpacked\n"), 4180Sstevel@tonic-gate argv0, argvk); 4190Sstevel@tonic-gate (void) unlink(filename); 4200Sstevel@tonic-gate 4210Sstevel@tonic-gate } 4220Sstevel@tonic-gate if (!errflg) 4230Sstevel@tonic-gate fcount--; /* success after all */ 4240Sstevel@tonic-gate } 4250Sstevel@tonic-gate else 4260Sstevel@tonic-gate if (!pcat) { 4270Sstevel@tonic-gate if (pathconf(argvk, _PC_XATTR_EXISTS) == 1) { 4280Sstevel@tonic-gate (void) mv_xattrs(outfile, infile, 4290Sstevel@tonic-gate argvk, 1); 4300Sstevel@tonic-gate } 4310Sstevel@tonic-gate (void) unlink(argvk); 4320Sstevel@tonic-gate } 4330Sstevel@tonic-gate done: (void) close(infile); 4340Sstevel@tonic-gate if (!pcat) 4350Sstevel@tonic-gate (void) close(outfile); 436*789Sahrens 437*789Sahrens if (aclp) 438*789Sahrens acl_free(aclp); 4390Sstevel@tonic-gate } 4400Sstevel@tonic-gate return (fcount); 4410Sstevel@tonic-gate } 4420Sstevel@tonic-gate 4430Sstevel@tonic-gate /* 4440Sstevel@tonic-gate * This code is for unpacking files that 4450Sstevel@tonic-gate * were packed using the previous algorithm. 4460Sstevel@tonic-gate */ 4470Sstevel@tonic-gate 4480Sstevel@tonic-gate static int Tree[1024]; 4490Sstevel@tonic-gate 4500Sstevel@tonic-gate /* return 1 if successful, 0 otherwise */ 4510Sstevel@tonic-gate 4520Sstevel@tonic-gate int 4530Sstevel@tonic-gate expand() 4540Sstevel@tonic-gate { 4550Sstevel@tonic-gate int tp, bit; 4560Sstevel@tonic-gate short word; 4570Sstevel@tonic-gate int keysize, i, *t; 4580Sstevel@tonic-gate 4590Sstevel@tonic-gate outp = outbuff; 4600Sstevel@tonic-gate inp = &inbuff[2]; 4610Sstevel@tonic-gate inleft -= 2; 4620Sstevel@tonic-gate 4630Sstevel@tonic-gate origsize = ((long)(unsigned)getwdsize())*256*256; 4640Sstevel@tonic-gate origsize += (unsigned)getwdsize(); 4650Sstevel@tonic-gate if (origsize == 0 || is_eof) { 4660Sstevel@tonic-gate (void) fprintf(stderr, gettext( 4670Sstevel@tonic-gate "%s: %s: not in packed format\n"), 4680Sstevel@tonic-gate argv0, filename); 4690Sstevel@tonic-gate return (0); 4700Sstevel@tonic-gate } 4710Sstevel@tonic-gate t = Tree; 4720Sstevel@tonic-gate for (keysize = getwdsize(); keysize--; ) { 4730Sstevel@tonic-gate if ((i = getch()) == 0377) 4740Sstevel@tonic-gate *t++ = getwdsize(); 4750Sstevel@tonic-gate else { 4760Sstevel@tonic-gate /* 4770Sstevel@tonic-gate * reached EOF unexpectedly 4780Sstevel@tonic-gate */ 4790Sstevel@tonic-gate if (is_eof) { 4800Sstevel@tonic-gate (void) fprintf(stderr, gettext( 4810Sstevel@tonic-gate "%s: %s: not in packed format\n"), 4820Sstevel@tonic-gate argv0, filename); 4830Sstevel@tonic-gate return (0); 4840Sstevel@tonic-gate } 4850Sstevel@tonic-gate *t++ = i & 0377; 4860Sstevel@tonic-gate } 4870Sstevel@tonic-gate } 4880Sstevel@tonic-gate /* 4890Sstevel@tonic-gate * reached EOF unexpectedly 4900Sstevel@tonic-gate */ 4910Sstevel@tonic-gate if (is_eof) { 4920Sstevel@tonic-gate (void) fprintf(stderr, gettext( 4930Sstevel@tonic-gate "%s: %s: not in packed format\n"), 4940Sstevel@tonic-gate argv0, filename); 4950Sstevel@tonic-gate return (0); 4960Sstevel@tonic-gate } 4970Sstevel@tonic-gate 4980Sstevel@tonic-gate 4990Sstevel@tonic-gate bit = tp = 0; 5000Sstevel@tonic-gate for (;;) { 5010Sstevel@tonic-gate if (bit <= 0) { 5020Sstevel@tonic-gate word = getwdsize(); 5030Sstevel@tonic-gate /* 5040Sstevel@tonic-gate * reached EOF unexpectedly 5050Sstevel@tonic-gate */ 5060Sstevel@tonic-gate if (word == 0 && is_eof && origsize > 0) { 5070Sstevel@tonic-gate (void) fprintf(stderr, gettext( 5080Sstevel@tonic-gate "%s: %s: not in packed format\n"), 5090Sstevel@tonic-gate argv0, filename); 5100Sstevel@tonic-gate return (0); 5110Sstevel@tonic-gate } 5120Sstevel@tonic-gate bit = 16; 5130Sstevel@tonic-gate } 5140Sstevel@tonic-gate tp += Tree[tp + (word < 0)]; 5150Sstevel@tonic-gate word <<= 1; 5160Sstevel@tonic-gate bit--; 5170Sstevel@tonic-gate if (Tree[tp] == 0) { 5180Sstevel@tonic-gate putch(Tree[tp+1]); 5190Sstevel@tonic-gate tp = 0; 5200Sstevel@tonic-gate if ((origsize -= 1) == 0) { 5210Sstevel@tonic-gate (void) write(outfile, outbuff, outp - outbuff); 5220Sstevel@tonic-gate return (1); 5230Sstevel@tonic-gate } 5240Sstevel@tonic-gate } 5250Sstevel@tonic-gate } 5260Sstevel@tonic-gate } 5270Sstevel@tonic-gate 5280Sstevel@tonic-gate int 5290Sstevel@tonic-gate getch() 5300Sstevel@tonic-gate { 5310Sstevel@tonic-gate if (inleft <= 0) { 5320Sstevel@tonic-gate inleft = read(infile, inp = inbuff, BUFSIZ); 5330Sstevel@tonic-gate if (inleft < 0) { 5340Sstevel@tonic-gate (void) fprintf(stderr, gettext( 5350Sstevel@tonic-gate "%s: %s: read error: "), 5360Sstevel@tonic-gate argv0, filename); 5370Sstevel@tonic-gate perror(""); 5380Sstevel@tonic-gate longjmp(env, 1); 5390Sstevel@tonic-gate } else { /* reached EOF, report it */ 5400Sstevel@tonic-gate if (inleft == 0) { 5410Sstevel@tonic-gate is_eof = 1; 5420Sstevel@tonic-gate return (EOF); 5430Sstevel@tonic-gate } 5440Sstevel@tonic-gate } 5450Sstevel@tonic-gate } 5460Sstevel@tonic-gate inleft--; 5470Sstevel@tonic-gate return (*inp++ & 0377); 5480Sstevel@tonic-gate } 5490Sstevel@tonic-gate 5500Sstevel@tonic-gate int 5510Sstevel@tonic-gate getwdsize() 5520Sstevel@tonic-gate { 5530Sstevel@tonic-gate char c; 5540Sstevel@tonic-gate int d; 5550Sstevel@tonic-gate 5560Sstevel@tonic-gate c = getch(); 5570Sstevel@tonic-gate d = getch(); 5580Sstevel@tonic-gate if (is_eof) 5590Sstevel@tonic-gate return (0); 5600Sstevel@tonic-gate d <<= 8; 5610Sstevel@tonic-gate d |= c & 0377; 5620Sstevel@tonic-gate return (d); 5630Sstevel@tonic-gate } 5640Sstevel@tonic-gate 5650Sstevel@tonic-gate void 5660Sstevel@tonic-gate onsig(int sig) 5670Sstevel@tonic-gate { 5680Sstevel@tonic-gate /* could be running as unpack or pcat */ 5690Sstevel@tonic-gate /* but rmflg is set only when running */ 5700Sstevel@tonic-gate /* as unpack and only when file is */ 5710Sstevel@tonic-gate /* created by unpack and not yet done */ 5720Sstevel@tonic-gate if (rmflg == 1) 5730Sstevel@tonic-gate (void) unlink(argvk); 5740Sstevel@tonic-gate exit(1); 5750Sstevel@tonic-gate } 5760Sstevel@tonic-gate 5770Sstevel@tonic-gate void 5780Sstevel@tonic-gate putch(char c) 5790Sstevel@tonic-gate { 5800Sstevel@tonic-gate int n; 5810Sstevel@tonic-gate 5820Sstevel@tonic-gate *outp++ = c; 5830Sstevel@tonic-gate if (outp == &outbuff[BUFSIZ]) { 5840Sstevel@tonic-gate n = write(outfile, outp = outbuff, BUFSIZ); 5850Sstevel@tonic-gate if (n < BUFSIZ) { 5860Sstevel@tonic-gate (void) fprintf(stderr, gettext( 5870Sstevel@tonic-gate "%s: %s: write error: "), 5880Sstevel@tonic-gate argv0, argvk); 5890Sstevel@tonic-gate perror(""); 5900Sstevel@tonic-gate longjmp(env, 2); 5910Sstevel@tonic-gate } 5920Sstevel@tonic-gate } 5930Sstevel@tonic-gate } 5940Sstevel@tonic-gate 5950Sstevel@tonic-gate /* 5960Sstevel@tonic-gate * mv_xattrs - move (via renameat) all of the extended attributes 5970Sstevel@tonic-gate * associated with the file referenced by infd to the file 5980Sstevel@tonic-gate * referenced by outfd. The infile and silent arguments are 5990Sstevel@tonic-gate * provided for error message processing. This function 6000Sstevel@tonic-gate * returns 0 on success and -1 on error. 6010Sstevel@tonic-gate */ 6020Sstevel@tonic-gate static int 6030Sstevel@tonic-gate mv_xattrs(int infd, int outfd, char *infile, int silent) 6040Sstevel@tonic-gate { 6050Sstevel@tonic-gate int indfd, outdfd, tmpfd; 6060Sstevel@tonic-gate DIR *dirp = NULL; 6070Sstevel@tonic-gate struct dirent *dp = NULL; 6080Sstevel@tonic-gate int error = 0; 6090Sstevel@tonic-gate char *etext; 6100Sstevel@tonic-gate 6110Sstevel@tonic-gate indfd = outdfd = tmpfd = -1; 6120Sstevel@tonic-gate 6130Sstevel@tonic-gate if ((indfd = openat(infd, ".", O_RDONLY|O_XATTR)) == -1) { 6140Sstevel@tonic-gate etext = gettext("cannot open source"); 6150Sstevel@tonic-gate error = -1; 6160Sstevel@tonic-gate goto out; 6170Sstevel@tonic-gate } 6180Sstevel@tonic-gate 6190Sstevel@tonic-gate if ((outdfd = openat(outfd, ".", O_RDONLY|O_XATTR)) == -1) { 6200Sstevel@tonic-gate etext = gettext("cannot open target"); 6210Sstevel@tonic-gate error = -1; 6220Sstevel@tonic-gate goto out; 6230Sstevel@tonic-gate } 6240Sstevel@tonic-gate 6250Sstevel@tonic-gate if ((tmpfd = dup(indfd)) == -1) { 6260Sstevel@tonic-gate etext = gettext("cannot dup descriptor"); 6270Sstevel@tonic-gate error = -1; 6280Sstevel@tonic-gate goto out; 6290Sstevel@tonic-gate 6300Sstevel@tonic-gate } 6310Sstevel@tonic-gate if ((dirp = fdopendir(tmpfd)) == NULL) { 6320Sstevel@tonic-gate etext = gettext("cannot access source"); 6330Sstevel@tonic-gate error = -1; 6340Sstevel@tonic-gate goto out; 6350Sstevel@tonic-gate } 6360Sstevel@tonic-gate 6370Sstevel@tonic-gate while (dp = readdir(dirp)) { 6380Sstevel@tonic-gate if ((dp->d_name[0] == '.' && dp->d_name[1] == '\0') || 6390Sstevel@tonic-gate (dp->d_name[0] == '.' && dp->d_name[1] == '.' && 6400Sstevel@tonic-gate dp->d_name[2] == '\0')) 6410Sstevel@tonic-gate continue; 6420Sstevel@tonic-gate if ((renameat(indfd, dp->d_name, outdfd, dp->d_name)) == -1) { 6430Sstevel@tonic-gate etext = dp->d_name; 6440Sstevel@tonic-gate error = -1; 6450Sstevel@tonic-gate goto out; 6460Sstevel@tonic-gate } 6470Sstevel@tonic-gate } 6480Sstevel@tonic-gate out: 6490Sstevel@tonic-gate if (error == -1 && silent == 0) { 6500Sstevel@tonic-gate fprintf(stderr, gettext( 6510Sstevel@tonic-gate "unpack: %s: cannot move extended attributes, "), 6520Sstevel@tonic-gate infile); 6530Sstevel@tonic-gate perror(etext); 6540Sstevel@tonic-gate } 6550Sstevel@tonic-gate if (dirp) 6560Sstevel@tonic-gate closedir(dirp); 6570Sstevel@tonic-gate if (indfd != -1) 6580Sstevel@tonic-gate close(indfd); 6590Sstevel@tonic-gate if (outdfd != -1) 6600Sstevel@tonic-gate close(outdfd); 6610Sstevel@tonic-gate return (error); 6620Sstevel@tonic-gate } 663