xref: /titanic_41/usr/src/lib/libpkg/common/pkgtrans.c (revision 4656d4747c8743290bfbe910c64cd75eb4e4af8d)
15c51f124SMoriah Waterland /*
25c51f124SMoriah Waterland  * CDDL HEADER START
35c51f124SMoriah Waterland  *
45c51f124SMoriah Waterland  * The contents of this file are subject to the terms of the
55c51f124SMoriah Waterland  * Common Development and Distribution License (the "License").
65c51f124SMoriah Waterland  * You may not use this file except in compliance with the License.
75c51f124SMoriah Waterland  *
85c51f124SMoriah Waterland  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95c51f124SMoriah Waterland  * or http://www.opensolaris.org/os/licensing.
105c51f124SMoriah Waterland  * See the License for the specific language governing permissions
115c51f124SMoriah Waterland  * and limitations under the License.
125c51f124SMoriah Waterland  *
135c51f124SMoriah Waterland  * When distributing Covered Code, include this CDDL HEADER in each
145c51f124SMoriah Waterland  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155c51f124SMoriah Waterland  * If applicable, add the following below this CDDL HEADER, with the
165c51f124SMoriah Waterland  * fields enclosed by brackets "[]" replaced with your own identifying
175c51f124SMoriah Waterland  * information: Portions Copyright [yyyy] [name of copyright owner]
185c51f124SMoriah Waterland  *
195c51f124SMoriah Waterland  * CDDL HEADER END
205c51f124SMoriah Waterland  */
215c51f124SMoriah Waterland 
225c51f124SMoriah Waterland /*
235c51f124SMoriah Waterland  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
245c51f124SMoriah Waterland  * Use is subject to license terms.
255c51f124SMoriah Waterland  */
265c51f124SMoriah Waterland 
275c51f124SMoriah Waterland /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
285c51f124SMoriah Waterland /* All Rights Reserved */
295c51f124SMoriah Waterland 
305c51f124SMoriah Waterland 
315c51f124SMoriah Waterland 
325c51f124SMoriah Waterland #include <stdio.h>
335c51f124SMoriah Waterland #include <errno.h>
345c51f124SMoriah Waterland #include <stdarg.h>
355c51f124SMoriah Waterland #include <limits.h>
365c51f124SMoriah Waterland #include <stdlib.h>
375c51f124SMoriah Waterland #include <unistd.h>
385c51f124SMoriah Waterland #include <fcntl.h>
395c51f124SMoriah Waterland #include <ctype.h>
405c51f124SMoriah Waterland #include <string.h>
415c51f124SMoriah Waterland #include <sys/types.h>
425c51f124SMoriah Waterland #include <sys/param.h>
435c51f124SMoriah Waterland #include <sys/stat.h>
445c51f124SMoriah Waterland #include <sys/statvfs.h>
455c51f124SMoriah Waterland #include <sys/sysmacros.h>
465c51f124SMoriah Waterland #include <dirent.h>
475c51f124SMoriah Waterland #include <signal.h>
485c51f124SMoriah Waterland #include <devmgmt.h>
495c51f124SMoriah Waterland #include <openssl/pkcs12.h>
505c51f124SMoriah Waterland #include <openssl/x509.h>
515c51f124SMoriah Waterland #include <openssl/pkcs7.h>
525c51f124SMoriah Waterland #include <openssl/err.h>
535c51f124SMoriah Waterland #include <openssl/pem.h>
54*4656d474SGarrett D'Amore #include <note.h>
555c51f124SMoriah Waterland #include "pkginfo.h"
565c51f124SMoriah Waterland #include "pkgstrct.h"
575c51f124SMoriah Waterland #include "pkgtrans.h"
585c51f124SMoriah Waterland #include "pkgdev.h"
595c51f124SMoriah Waterland #include "pkglib.h"
605c51f124SMoriah Waterland #include "pkglibmsgs.h"
615c51f124SMoriah Waterland #include "keystore.h"
625c51f124SMoriah Waterland #include "pkglocale.h"
635c51f124SMoriah Waterland #include "pkgerr.h"
645c51f124SMoriah Waterland 
655c51f124SMoriah Waterland extern char	*pkgdir; 		/* pkgparam.c */
665c51f124SMoriah Waterland 
675c51f124SMoriah Waterland /* libadm.a */
685c51f124SMoriah Waterland extern char	*devattr(char *device, char *attribute);
695c51f124SMoriah Waterland extern char	*fpkginst(char *pkg, ...);
705c51f124SMoriah Waterland extern int	fpkginfo(struct pkginfo *info, char *pkginst);
715c51f124SMoriah Waterland extern int	getvol(char *device, char *label, int options, char *prompt);
725c51f124SMoriah Waterland extern int	_getvol(char *device, char *label, int options, char *prompt,
735c51f124SMoriah Waterland 			char *norewind);
745c51f124SMoriah Waterland 
755c51f124SMoriah Waterland /* dstream.c */
765c51f124SMoriah Waterland extern int	ds_ginit(char *device);
775c51f124SMoriah Waterland extern int	ds_close(int pkgendflg);
785c51f124SMoriah Waterland 
795c51f124SMoriah Waterland #define	CPIOPROC	"/usr/bin/cpio"
805c51f124SMoriah Waterland 
815c51f124SMoriah Waterland #define	CMDSIZE	512	/* command block size */
825c51f124SMoriah Waterland 
835c51f124SMoriah Waterland #define	BLK_SIZE	512		/* size of logical block */
845c51f124SMoriah Waterland 
855c51f124SMoriah Waterland #define	ENTRY_MAX	256 /* max size of entry for cpio cmd or header */
865c51f124SMoriah Waterland 
875c51f124SMoriah Waterland #define	PKGINFO	"pkginfo"
885c51f124SMoriah Waterland #define	PKGMAP	"pkgmap"
895c51f124SMoriah Waterland #define	MAP_STAT_SIZE	60	/* 1st line of pkgmap (3 numbers & a : */
905c51f124SMoriah Waterland 
915c51f124SMoriah Waterland #define	INSTALL	"install"
925c51f124SMoriah Waterland #define	RELOC	"reloc"
935c51f124SMoriah Waterland #define	ROOT	"root"
945c51f124SMoriah Waterland #define	ARCHIVE	"archive"
955c51f124SMoriah Waterland 
965c51f124SMoriah Waterland static struct	pkgdev srcdev, dstdev;
975c51f124SMoriah Waterland static char	*tmpdir;
985c51f124SMoriah Waterland static char	*tmppath;
995c51f124SMoriah Waterland static char	*tmpsymdir = NULL;
1005c51f124SMoriah Waterland static char	dstinst[NON_ABI_NAMELNGTH];
1015c51f124SMoriah Waterland static char 	*ids_name, *ods_name;
1025c51f124SMoriah Waterland static int	ds_volcnt;
1035c51f124SMoriah Waterland static int	ds_volno;
1045c51f124SMoriah Waterland static int	compressedsize, has_comp_size;
1055c51f124SMoriah Waterland 
1065c51f124SMoriah Waterland static void	(*sigintHandler)();
1075c51f124SMoriah Waterland static void	(*sighupHandler)();
1085c51f124SMoriah Waterland static void	cleanup(void);
1095c51f124SMoriah Waterland static void	sigtrap(int signo);
1105c51f124SMoriah Waterland static int	rd_map_size(FILE *fp, int *npts, int *maxpsz, int *cmpsize);
1115c51f124SMoriah Waterland 
1125c51f124SMoriah Waterland static int	cat_and_count(struct dm_buf *, char *);
1135c51f124SMoriah Waterland 
1145c51f124SMoriah Waterland static int	ckoverwrite(char *dir, char *inst, int options);
1155c51f124SMoriah Waterland static int	pkgxfer(char *srcinst, int options);
1165c51f124SMoriah Waterland static int	wdsheader(struct dm_buf *, char *src, char *device,
1175c51f124SMoriah Waterland     char **pkg, PKCS7 *);
118*4656d474SGarrett D'Amore static struct dm_buf	*genheader(char *, char **);
1195c51f124SMoriah Waterland 
1205c51f124SMoriah Waterland static int	dump_hdr_and_pkgs(BIO *, struct dm_buf *, char **);
1215c51f124SMoriah Waterland 
1225c51f124SMoriah Waterland extern int	ds_fd;	/* open file descriptor for data stream WHERE? */
1235c51f124SMoriah Waterland 
1245c51f124SMoriah Waterland static char *root_names[] = {
1255c51f124SMoriah Waterland 	"root",
1265c51f124SMoriah Waterland 	"root.cpio",
1275c51f124SMoriah Waterland 	"root.Z",
1285c51f124SMoriah Waterland 	"root.cpio.Z",
1295c51f124SMoriah Waterland 	0
1305c51f124SMoriah Waterland };
1315c51f124SMoriah Waterland 
1325c51f124SMoriah Waterland static char *reloc_names[] = {
1335c51f124SMoriah Waterland 	"reloc",
1345c51f124SMoriah Waterland 	"reloc.cpio",
1355c51f124SMoriah Waterland 	"reloc.Z",
1365c51f124SMoriah Waterland 	"reloc.cpio.Z",
1375c51f124SMoriah Waterland 	0
1385c51f124SMoriah Waterland };
1395c51f124SMoriah Waterland 
1405c51f124SMoriah Waterland static int	signal_received = 0;
1415c51f124SMoriah Waterland 
1425c51f124SMoriah Waterland char	**xpkg; 	/* array of transferred packages */
1435c51f124SMoriah Waterland int	nxpkg;
1445c51f124SMoriah Waterland 
1455c51f124SMoriah Waterland static	char *allpkg[] = {
1465c51f124SMoriah Waterland 	"all",
1475c51f124SMoriah Waterland 	NULL
1485c51f124SMoriah Waterland };
1495c51f124SMoriah Waterland 
1505c51f124SMoriah Waterland static struct dm_buf hdrbuf;
1515c51f124SMoriah Waterland static char *pinput, *nextpinput;
1525c51f124SMoriah Waterland 
1535c51f124SMoriah Waterland int
pkghead(char * device)1545c51f124SMoriah Waterland pkghead(char *device)
1555c51f124SMoriah Waterland {
1565c51f124SMoriah Waterland 	char	*pt;
1575c51f124SMoriah Waterland 	int	n;
1585c51f124SMoriah Waterland 
1595c51f124SMoriah Waterland 	cleanup();
1605c51f124SMoriah Waterland 
1615c51f124SMoriah Waterland 
1625c51f124SMoriah Waterland 	if (device == NULL)
1635c51f124SMoriah Waterland 		return (0);
1645c51f124SMoriah Waterland 	else if ((device[0] == '/') && !isdir(device)) {
1655c51f124SMoriah Waterland 		pkgdir = device;
1665c51f124SMoriah Waterland 		return (0);
1675c51f124SMoriah Waterland 	} else if ((pt = devattr(device, "pathname")) != NULL && !isdir(pt)) {
1685c51f124SMoriah Waterland 		pkgdir = pt;
1695c51f124SMoriah Waterland 		return (0);
1705c51f124SMoriah Waterland 	}
1715c51f124SMoriah Waterland 
1725c51f124SMoriah Waterland 	/* check for datastream */
1735c51f124SMoriah Waterland 	if (n = pkgtrans(device, (char *)0, allpkg, PT_SILENT|PT_INFO_ONLY,
1745c51f124SMoriah Waterland 	    NULL, NULL)) {
1755c51f124SMoriah Waterland 		cleanup();
1765c51f124SMoriah Waterland 		return (n);
1775c51f124SMoriah Waterland 	}
1785c51f124SMoriah Waterland 		/* pkgtrans has set pkgdir */
1795c51f124SMoriah Waterland 	return (0);
1805c51f124SMoriah Waterland }
1815c51f124SMoriah Waterland 
1825c51f124SMoriah Waterland static char *
mgets(char * buf,int size)1835c51f124SMoriah Waterland mgets(char *buf, int size)
1845c51f124SMoriah Waterland {
1855c51f124SMoriah Waterland 	nextpinput = strchr(pinput, '\n');
1865c51f124SMoriah Waterland 	if (nextpinput == NULL)
1875c51f124SMoriah Waterland 		return (0);
1885c51f124SMoriah Waterland 	*nextpinput = '\0';
1895c51f124SMoriah Waterland 	if ((int)strlen(pinput) > size)
1905c51f124SMoriah Waterland 		return (0);
1915c51f124SMoriah Waterland 	(void) strncpy(buf, pinput, strlen(pinput));
1925c51f124SMoriah Waterland 	buf[strlen(pinput)] = '\0';
1935c51f124SMoriah Waterland 	pinput = nextpinput + 1;
1945c51f124SMoriah Waterland 	return (buf);
1955c51f124SMoriah Waterland }
1965c51f124SMoriah Waterland /*
1975c51f124SMoriah Waterland  * Here we construct the package size summaries for the headers. The
1985c51f124SMoriah Waterland  * pkgmap file associated with fp must be rewound to the beginning of the
1995c51f124SMoriah Waterland  * file. Note that we read three values from pkgmap first line in order
2005c51f124SMoriah Waterland  * to get the *actual* size if this package is compressed.
2015c51f124SMoriah Waterland  * This returns
2025c51f124SMoriah Waterland  *	0 : error
2035c51f124SMoriah Waterland  *	2 : not a compressed package
2045c51f124SMoriah Waterland  *	3 : compressed package
2055c51f124SMoriah Waterland  * and sets has_comp_size to indicate whether or not this is a compressed
2065c51f124SMoriah Waterland  * package.
2075c51f124SMoriah Waterland  */
2085c51f124SMoriah Waterland static int
rd_map_size(FILE * fp,int * npts,int * maxpsz,int * cmpsize)2095c51f124SMoriah Waterland rd_map_size(FILE *fp, int *npts, int *maxpsz, int *cmpsize)
2105c51f124SMoriah Waterland {
2115c51f124SMoriah Waterland 	int n;
2125c51f124SMoriah Waterland 	char line_buffer[MAP_STAT_SIZE];
2135c51f124SMoriah Waterland 
2145c51f124SMoriah Waterland 	/* First read the null terminated first line */
2155c51f124SMoriah Waterland 	if (fgets(line_buffer, MAP_STAT_SIZE, fp) == NULL) {
2165c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
2175c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_NOSIZE));
2185c51f124SMoriah Waterland 		(void) fclose(fp);
2195c51f124SMoriah Waterland 		ecleanup();
2205c51f124SMoriah Waterland 		return (0);
2215c51f124SMoriah Waterland 	}
2225c51f124SMoriah Waterland 
2235c51f124SMoriah Waterland 	n = sscanf(line_buffer, ": %d %d %d", npts, maxpsz, cmpsize);
2245c51f124SMoriah Waterland 
2255c51f124SMoriah Waterland 	if (n == 3)		/* A valid compressed package entry */
2265c51f124SMoriah Waterland 		has_comp_size = 1;
2275c51f124SMoriah Waterland 	else if (n == 2)	/* A valid standard package entry */
2285c51f124SMoriah Waterland 		has_comp_size = 0;
2295c51f124SMoriah Waterland 	else {			/* invalid entry */
2305c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
2315c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_NOSIZE));
2325c51f124SMoriah Waterland 		(void) fclose(fp);
2335c51f124SMoriah Waterland 		ecleanup();
2345c51f124SMoriah Waterland 		return (0);
2355c51f124SMoriah Waterland 	}
2365c51f124SMoriah Waterland 
2375c51f124SMoriah Waterland 	return (n);
2385c51f124SMoriah Waterland }
2395c51f124SMoriah Waterland 
2405c51f124SMoriah Waterland /* will return 0, 1, 3, or 99 */
2415c51f124SMoriah Waterland static int
_pkgtrans(char * device1,char * device2,char ** pkg,int options,keystore_handle_t keystore,char * keystore_alias)2425c51f124SMoriah Waterland _pkgtrans(char *device1, char *device2, char **pkg, int options,
2435c51f124SMoriah Waterland     keystore_handle_t keystore, char *keystore_alias)
2445c51f124SMoriah Waterland {
2455c51f124SMoriah Waterland 	BIO			*p7_bio = NULL;
2465c51f124SMoriah Waterland 	EVP_PKEY		*privkey = NULL;
2475c51f124SMoriah Waterland 	PKCS7			*sec_pkcs7 = NULL;
2485c51f124SMoriah Waterland 	PKCS7_SIGNER_INFO	*sec_signerinfo = NULL;
2495c51f124SMoriah Waterland 	PKG_ERR			*err;
2505c51f124SMoriah Waterland 	STACK_OF(X509)		*cacerts = NULL;
2515c51f124SMoriah Waterland 	STACK_OF(X509)		*clcerts = NULL;
2525c51f124SMoriah Waterland 	STACK_OF(X509)		*sec_chain = NULL;
2535c51f124SMoriah Waterland 	X509			*pubcert = NULL;
2545c51f124SMoriah Waterland 	boolean_t		making_sig = B_FALSE;
2555c51f124SMoriah Waterland 	char			*src, *dst;
2565c51f124SMoriah Waterland 	int			errflg, i, n;
2575c51f124SMoriah Waterland 	struct			dm_buf *hdr;
2585c51f124SMoriah Waterland 
2595c51f124SMoriah Waterland 	making_sig = (keystore != NULL) ? B_TRUE : B_FALSE;
2605c51f124SMoriah Waterland 
2615c51f124SMoriah Waterland 	if (making_sig) {
2625c51f124SMoriah Waterland 
2635c51f124SMoriah Waterland 		/* new error object */
2645c51f124SMoriah Waterland 		err = pkgerr_new();
2655c51f124SMoriah Waterland 
2665c51f124SMoriah Waterland 		/* find matching cert and key */
2675c51f124SMoriah Waterland 		if (find_key_cert_pair(err, keystore,
2685c51f124SMoriah Waterland 		    keystore_alias, &privkey, &pubcert) != 0) {
2695c51f124SMoriah Waterland 			pkgerr(err);
2705c51f124SMoriah Waterland 			pkgerr_free(err);
2715c51f124SMoriah Waterland 			return (1);
2725c51f124SMoriah Waterland 		}
2735c51f124SMoriah Waterland 
2745c51f124SMoriah Waterland 		/* get CA certificates */
2755c51f124SMoriah Waterland 		if (find_ca_certs(err, keystore, &cacerts) != 0) {
2765c51f124SMoriah Waterland 			pkgerr(err);
2775c51f124SMoriah Waterland 			pkgerr_free(err);
2785c51f124SMoriah Waterland 			return (1);
2795c51f124SMoriah Waterland 		}
2805c51f124SMoriah Waterland 
2815c51f124SMoriah Waterland 		/* get CL (aka "chain") certificates */
2825c51f124SMoriah Waterland 		if (find_cl_certs(err, keystore, &clcerts) != 0) {
2835c51f124SMoriah Waterland 			pkgerr(err);
2845c51f124SMoriah Waterland 			pkgerr_free(err);
2855c51f124SMoriah Waterland 			return (1);
2865c51f124SMoriah Waterland 		}
2875c51f124SMoriah Waterland 
2885c51f124SMoriah Waterland 		/* initialize PKCS7 object to be filled in later */
2895c51f124SMoriah Waterland 		sec_pkcs7 = PKCS7_new();
290*4656d474SGarrett D'Amore 		(void) PKCS7_set_type(sec_pkcs7, NID_pkcs7_signed);
2915c51f124SMoriah Waterland 		sec_signerinfo = PKCS7_add_signature(sec_pkcs7,
2925c51f124SMoriah Waterland 		    pubcert, privkey, EVP_sha1());
2935c51f124SMoriah Waterland 
2945c51f124SMoriah Waterland 		if (sec_signerinfo == NULL) {
2955c51f124SMoriah Waterland 			progerr(gettext(ERR_SEC), keystore_alias);
2965c51f124SMoriah Waterland 			ERR_print_errors_fp(stderr);
2975c51f124SMoriah Waterland 			pkgerr_free(err);
2985c51f124SMoriah Waterland 			return (1);
2995c51f124SMoriah Waterland 		}
3005c51f124SMoriah Waterland 
3015c51f124SMoriah Waterland 		/* add signer cert into signature */
302*4656d474SGarrett D'Amore 		(void) PKCS7_add_certificate(sec_pkcs7, pubcert);
3035c51f124SMoriah Waterland 
3045c51f124SMoriah Waterland 		/* attempt to resolve cert chain starting at the signer cert */
3055c51f124SMoriah Waterland 		if (get_cert_chain(err, pubcert, clcerts, cacerts,
3065c51f124SMoriah Waterland 		    &sec_chain) != 0) {
3075c51f124SMoriah Waterland 			pkgerr(err);
3085c51f124SMoriah Waterland 			pkgerr_free(err);
3095c51f124SMoriah Waterland 			return (1);
3105c51f124SMoriah Waterland 		}
3115c51f124SMoriah Waterland 
3125c51f124SMoriah Waterland 		/*
3135c51f124SMoriah Waterland 		 * add the verification chain of certs into the signature.
3145c51f124SMoriah Waterland 		 * The first cert is the user cert, which we don't need,
3155c51f124SMoriah Waterland 		 * since it's baked in already, so skip it
3165c51f124SMoriah Waterland 		 */
3175c51f124SMoriah Waterland 		for (i = 1; i < sk_X509_num(sec_chain); i++) {
318*4656d474SGarrett D'Amore 			(void) PKCS7_add_certificate(sec_pkcs7,
3195c51f124SMoriah Waterland 			    sk_X509_value(sec_chain, i));
3205c51f124SMoriah Waterland 		}
3215c51f124SMoriah Waterland 
3225c51f124SMoriah Waterland 		pkgerr_free(err);
3235c51f124SMoriah Waterland 		err = NULL;
3245c51f124SMoriah Waterland 	}
3255c51f124SMoriah Waterland 
3265c51f124SMoriah Waterland 	if (signal_received > 0) {
3275c51f124SMoriah Waterland 		return (1);
3285c51f124SMoriah Waterland 	}
3295c51f124SMoriah Waterland 
3305c51f124SMoriah Waterland 	/* transfer spool to appropriate device */
3315c51f124SMoriah Waterland 	if (devtype(device1, &srcdev)) {
3325c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
3335c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_BADDEV), device1);
3345c51f124SMoriah Waterland 		return (1);
3355c51f124SMoriah Waterland 	}
3365c51f124SMoriah Waterland 	srcdev.rdonly++;
3375c51f124SMoriah Waterland 
3385c51f124SMoriah Waterland 	/* check for datastream */
3395c51f124SMoriah Waterland 	ids_name = NULL;
3405c51f124SMoriah Waterland 	if (srcdev.bdevice) {
3415c51f124SMoriah Waterland 		if (n = _getvol(srcdev.bdevice, NULL, NULL,
3425c51f124SMoriah Waterland 		    pkg_gt("Insert %v into %p."), srcdev.norewind)) {
3435c51f124SMoriah Waterland 			cleanup();
3445c51f124SMoriah Waterland 			if (n == 3)
3455c51f124SMoriah Waterland 				return (3);
3465c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
3475c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_GETVOL));
3485c51f124SMoriah Waterland 			return (1);
3495c51f124SMoriah Waterland 		}
3505c51f124SMoriah Waterland 		if (ds_readbuf(srcdev.cdevice))
3515c51f124SMoriah Waterland 			ids_name = srcdev.cdevice;
3525c51f124SMoriah Waterland 	}
3535c51f124SMoriah Waterland 
3545c51f124SMoriah Waterland 	if (srcdev.cdevice && !srcdev.bdevice)
3555c51f124SMoriah Waterland 		ids_name = srcdev.cdevice;
3565c51f124SMoriah Waterland 	else if (srcdev.pathname) {
3575c51f124SMoriah Waterland 		ids_name = srcdev.pathname;
3585c51f124SMoriah Waterland 		if (access(ids_name, 0) == -1) {
3595c51f124SMoriah Waterland 			progerr(ERR_TRANSFER);
3605c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_GETVOL));
3615c51f124SMoriah Waterland 			return (1);
3625c51f124SMoriah Waterland 		}
3635c51f124SMoriah Waterland 	}
3645c51f124SMoriah Waterland 
3655c51f124SMoriah Waterland 	if (!ids_name && device2 == (char *)0) {
3665c51f124SMoriah Waterland 		if (n = pkgmount(&srcdev, NULL, 1, 0, 0)) {
3675c51f124SMoriah Waterland 			cleanup();
3685c51f124SMoriah Waterland 			return (n);
3695c51f124SMoriah Waterland 		}
3705c51f124SMoriah Waterland 		if (srcdev.mount && *srcdev.mount)
3715c51f124SMoriah Waterland 			pkgdir = strdup(srcdev.mount);
3725c51f124SMoriah Waterland 		return (0);
3735c51f124SMoriah Waterland 	}
3745c51f124SMoriah Waterland 
3755c51f124SMoriah Waterland 	if (ids_name && device2 == (char *)0) {
3765c51f124SMoriah Waterland 		tmppath = tmpnam(NULL);
3775c51f124SMoriah Waterland 		tmppath = strdup(tmppath);
3785c51f124SMoriah Waterland 		if (tmppath == NULL) {
3795c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
3805c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_MEM));
3815c51f124SMoriah Waterland 			return (1);
3825c51f124SMoriah Waterland 		}
3835c51f124SMoriah Waterland 		if (mkdir(tmppath, 0755)) {
3845c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
3855c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_MKDIR), tmppath);
3865c51f124SMoriah Waterland 			return (1);
3875c51f124SMoriah Waterland 		}
3885c51f124SMoriah Waterland 		device2 = tmppath;
3895c51f124SMoriah Waterland 	}
3905c51f124SMoriah Waterland 
3915c51f124SMoriah Waterland 	if (devtype(device2, &dstdev)) {
3925c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
3935c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_BADDEV), device2);
3945c51f124SMoriah Waterland 		return (1);
3955c51f124SMoriah Waterland 	}
3965c51f124SMoriah Waterland 
3975c51f124SMoriah Waterland 	if ((srcdev.cdevice && dstdev.cdevice) &&
3985c51f124SMoriah Waterland 	    strcmp(srcdev.cdevice, dstdev.cdevice) == 0) {
3995c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
4005c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_SAMEDEV));
4015c51f124SMoriah Waterland 		return (1);
4025c51f124SMoriah Waterland 	}
4035c51f124SMoriah Waterland 
4045c51f124SMoriah Waterland 	ods_name = NULL;
4055c51f124SMoriah Waterland 	if (dstdev.cdevice && !dstdev.bdevice || dstdev.pathname)
4065c51f124SMoriah Waterland 		options |= PT_ODTSTREAM;
4075c51f124SMoriah Waterland 
4085c51f124SMoriah Waterland 	if (options & PT_ODTSTREAM) {
4095c51f124SMoriah Waterland 		if (!((ods_name = dstdev.cdevice) != NULL ||
4105c51f124SMoriah Waterland 		    (ods_name = dstdev.pathname) != NULL)) {
4115c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
4125c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_BADDEV), device2);
4135c51f124SMoriah Waterland 			return (1);
4145c51f124SMoriah Waterland 		}
4155c51f124SMoriah Waterland 		if (ids_name) {
4165c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
4175c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_TWODSTREAM));
4185c51f124SMoriah Waterland 			return (1);
4195c51f124SMoriah Waterland 		}
4205c51f124SMoriah Waterland 	} else {
4215c51f124SMoriah Waterland 		/*
4225c51f124SMoriah Waterland 		 * output device isn't a stream.  If we're making a signed
4235c51f124SMoriah Waterland 		 * package, then fail, since we can't make signed,
4245c51f124SMoriah Waterland 		 * non-stream pkgs
4255c51f124SMoriah Waterland 		 */
4265c51f124SMoriah Waterland 		if (making_sig) {
4275c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
4285c51f124SMoriah Waterland 			logerr(pkg_gt(ERR_CANTSIGN));
4295c51f124SMoriah Waterland 			return (1);
4305c51f124SMoriah Waterland 		}
4315c51f124SMoriah Waterland 	}
4325c51f124SMoriah Waterland 
4335c51f124SMoriah Waterland 	if ((srcdev.dirname && dstdev.dirname) &&
4345c51f124SMoriah Waterland 	    strcmp(srcdev.dirname, dstdev.dirname) == 0) {
4355c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
4365c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_SAMEDEV));
4375c51f124SMoriah Waterland 		return (1);
4385c51f124SMoriah Waterland 	}
4395c51f124SMoriah Waterland 
4405c51f124SMoriah Waterland 	if ((srcdev.pathname && dstdev.pathname) &&
4415c51f124SMoriah Waterland 	    strcmp(srcdev.pathname, dstdev.pathname) == 0) {
4425c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
4435c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_SAMEDEV));
4445c51f124SMoriah Waterland 		return (1);
4455c51f124SMoriah Waterland 	}
4465c51f124SMoriah Waterland 
4475c51f124SMoriah Waterland 	if (signal_received > 0) {
4485c51f124SMoriah Waterland 		return (1);
4495c51f124SMoriah Waterland 	}
4505c51f124SMoriah Waterland 
4515c51f124SMoriah Waterland 	if (ids_name) {
4525c51f124SMoriah Waterland 		if (srcdev.cdevice && !srcdev.bdevice &&
4535c51f124SMoriah Waterland 		(n = _getvol(srcdev.cdevice, NULL, NULL, NULL,
4545c51f124SMoriah Waterland 		    srcdev.norewind))) {
4555c51f124SMoriah Waterland 			cleanup();
4565c51f124SMoriah Waterland 			if (n == 3)
4575c51f124SMoriah Waterland 				return (3);
4585c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
4595c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_GETVOL));
4605c51f124SMoriah Waterland 			return (1);
4615c51f124SMoriah Waterland 		}
4625c51f124SMoriah Waterland 		if (srcdev.dirname = tmpnam(NULL))
4635c51f124SMoriah Waterland 			tmpdir = srcdev.dirname = strdup(srcdev.dirname);
4645c51f124SMoriah Waterland 
4655c51f124SMoriah Waterland 		if ((srcdev.dirname == NULL) || mkdir(srcdev.dirname, 0755) ||
4665c51f124SMoriah Waterland 		    chdir(srcdev.dirname)) {
4675c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
4685c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_NOTEMP), srcdev.dirname);
4695c51f124SMoriah Waterland 			cleanup();
4705c51f124SMoriah Waterland 			return (1);
4715c51f124SMoriah Waterland 		}
4725c51f124SMoriah Waterland 		if (ds_init(ids_name, pkg, srcdev.norewind)) {
4735c51f124SMoriah Waterland 			cleanup();
4745c51f124SMoriah Waterland 			return (1);
4755c51f124SMoriah Waterland 		}
4765c51f124SMoriah Waterland 	} else if (srcdev.mount) {
4775c51f124SMoriah Waterland 		if (n = pkgmount(&srcdev, NULL, 1, 0, 0)) {
4785c51f124SMoriah Waterland 			cleanup();
4795c51f124SMoriah Waterland 			return (n);
4805c51f124SMoriah Waterland 		}
4815c51f124SMoriah Waterland 	}
4825c51f124SMoriah Waterland 
4835c51f124SMoriah Waterland 	src = srcdev.dirname;
4845c51f124SMoriah Waterland 	dst = dstdev.dirname;
4855c51f124SMoriah Waterland 
4865c51f124SMoriah Waterland 	if (chdir(src)) {
4875c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
4885c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_CHDIR), src);
4895c51f124SMoriah Waterland 		cleanup();
4905c51f124SMoriah Waterland 		return (1);
4915c51f124SMoriah Waterland 	}
4925c51f124SMoriah Waterland 
4935c51f124SMoriah Waterland 	if (signal_received > 0) {
4945c51f124SMoriah Waterland 		return (1);
4955c51f124SMoriah Waterland 	}
4965c51f124SMoriah Waterland 
4975c51f124SMoriah Waterland 	xpkg = pkg = gpkglist(src, pkg, NULL);
4985c51f124SMoriah Waterland 	if (!pkg) {
4995c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
5005c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_NOPKGS), src);
5015c51f124SMoriah Waterland 		cleanup();
5025c51f124SMoriah Waterland 		return (1);
5035c51f124SMoriah Waterland 	}
5045c51f124SMoriah Waterland 
5055c51f124SMoriah Waterland 	for (nxpkg = 0; pkg[nxpkg]; /* void */) {
5065c51f124SMoriah Waterland 		nxpkg++; /* count */
5075c51f124SMoriah Waterland 	}
5085c51f124SMoriah Waterland 
5095c51f124SMoriah Waterland 	if (ids_name) {
5105c51f124SMoriah Waterland 		ds_order(pkg); /* order requests */
5115c51f124SMoriah Waterland 	}
5125c51f124SMoriah Waterland 
5135c51f124SMoriah Waterland 	if (signal_received > 0) {
5145c51f124SMoriah Waterland 		return (1);
5155c51f124SMoriah Waterland 	}
5165c51f124SMoriah Waterland 
5175c51f124SMoriah Waterland 	if (options & PT_ODTSTREAM) {
5185c51f124SMoriah Waterland 		char line[128];
5195c51f124SMoriah Waterland 
5205c51f124SMoriah Waterland 		if (!dstdev.pathname &&
5215c51f124SMoriah Waterland 		    (n = _getvol(ods_name, NULL, DM_FORMAT, NULL,
5225c51f124SMoriah Waterland 		    dstdev.norewind))) {
5235c51f124SMoriah Waterland 			cleanup();
5245c51f124SMoriah Waterland 			if (n == 3)
5255c51f124SMoriah Waterland 				return (3);
5265c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
5275c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_GETVOL));
5285c51f124SMoriah Waterland 			return (1);
5295c51f124SMoriah Waterland 		}
530*4656d474SGarrett D'Amore 		if ((hdr = genheader(src, pkg)) == NULL) {
5315c51f124SMoriah Waterland 			cleanup();
5325c51f124SMoriah Waterland 			return (1);
5335c51f124SMoriah Waterland 		}
5345c51f124SMoriah Waterland 		if (making_sig) {
5355c51f124SMoriah Waterland 			/* start up signature data stream */
536*4656d474SGarrett D'Amore 			(void) PKCS7_content_new(sec_pkcs7, NID_pkcs7_data);
537*4656d474SGarrett D'Amore 			(void) PKCS7_set_detached(sec_pkcs7, 1);
5385c51f124SMoriah Waterland 			p7_bio = PKCS7_dataInit(sec_pkcs7, NULL);
5395c51f124SMoriah Waterland 
5405c51f124SMoriah Waterland 			/*
5415c51f124SMoriah Waterland 			 * Here we generate all the data that will go into
5425c51f124SMoriah Waterland 			 * the package, and send it through the signature
5435c51f124SMoriah Waterland 			 * generator, essentially calculating the signature
5445c51f124SMoriah Waterland 			 * of the entire package so we can place it in the
5455c51f124SMoriah Waterland 			 * header.  Otherwise we'd have to place it at the end
5465c51f124SMoriah Waterland 			 * of the pkg, which would break the ABI
5475c51f124SMoriah Waterland 			 */
5485c51f124SMoriah Waterland 			if (!(options & PT_SILENT)) {
5495c51f124SMoriah Waterland 				(void) fprintf(stderr, pkg_gt(MSG_SIGNING),
5505c51f124SMoriah Waterland 				    get_subject_display_name(pubcert));
5515c51f124SMoriah Waterland 			}
5525c51f124SMoriah Waterland 			if (dump_hdr_and_pkgs(p7_bio, hdr, pkg) != 0) {
5535c51f124SMoriah Waterland 			    progerr(gettext(ERR_NOGEN));
5545c51f124SMoriah Waterland 			    logerr(pkg_gt(MSG_GETVOL));
5555c51f124SMoriah Waterland 			    cleanup();
5565c51f124SMoriah Waterland 			    return (1);
5575c51f124SMoriah Waterland 
5585c51f124SMoriah Waterland 			}
5595c51f124SMoriah Waterland 
5605c51f124SMoriah Waterland 			BIO_flush(p7_bio);
5615c51f124SMoriah Waterland 
5625c51f124SMoriah Waterland 			/*
5635c51f124SMoriah Waterland 			 * now generate PKCS7 signature
5645c51f124SMoriah Waterland 			 */
5655c51f124SMoriah Waterland 			if (!PKCS7_dataFinal(sec_pkcs7, p7_bio)) {
5665c51f124SMoriah Waterland 			    progerr(gettext(ERR_NOGEN));
5675c51f124SMoriah Waterland 			    logerr(pkg_gt(MSG_GETVOL));
5685c51f124SMoriah Waterland 			    cleanup();
5695c51f124SMoriah Waterland 			    return (1);
5705c51f124SMoriah Waterland 			}
5715c51f124SMoriah Waterland 
572*4656d474SGarrett D'Amore 			(void) BIO_free(p7_bio);
5735c51f124SMoriah Waterland 		}
5745c51f124SMoriah Waterland 
5755c51f124SMoriah Waterland 		/* write out header to stream, which includes signature */
5765c51f124SMoriah Waterland 		if (wdsheader(hdr, src, ods_name, pkg, sec_pkcs7)) {
5775c51f124SMoriah Waterland 			cleanup();
5785c51f124SMoriah Waterland 			return (1);
5795c51f124SMoriah Waterland 		}
5805c51f124SMoriah Waterland 
5815c51f124SMoriah Waterland 		if (sec_pkcs7 != NULL) {
5825c51f124SMoriah Waterland 			/* nuke in-memory signature for safety */
5835c51f124SMoriah Waterland 			PKCS7_free(sec_pkcs7);
5845c51f124SMoriah Waterland 			sec_pkcs7 = NULL;
5855c51f124SMoriah Waterland 		}
5865c51f124SMoriah Waterland 
5875c51f124SMoriah Waterland 		ds_volno = 1; /* number of volumes in datastream */
5885c51f124SMoriah Waterland 		pinput = hdrbuf.text_buffer;
5895c51f124SMoriah Waterland 		/* skip past first line in header */
5905c51f124SMoriah Waterland 		(void) mgets(line, 128);
5915c51f124SMoriah Waterland 	}
5925c51f124SMoriah Waterland 
5935c51f124SMoriah Waterland 	if (signal_received > 0) {
5945c51f124SMoriah Waterland 		return (1);
5955c51f124SMoriah Waterland 	}
5965c51f124SMoriah Waterland 
5975c51f124SMoriah Waterland 	errflg = 0;
5985c51f124SMoriah Waterland 
5995c51f124SMoriah Waterland 	for (i = 0; pkg[i]; i++) {
6005c51f124SMoriah Waterland 
6015c51f124SMoriah Waterland 		if (signal_received > 0) {
6025c51f124SMoriah Waterland 			return (1);
6035c51f124SMoriah Waterland 		}
6045c51f124SMoriah Waterland 
6055c51f124SMoriah Waterland 		if (!(options & PT_ODTSTREAM) && dstdev.mount) {
6065c51f124SMoriah Waterland 			if (n = pkgmount(&dstdev, NULL, 0, 0, 1)) {
6075c51f124SMoriah Waterland 				cleanup();
6085c51f124SMoriah Waterland 				return (n);
6095c51f124SMoriah Waterland 			}
6105c51f124SMoriah Waterland 		}
6115c51f124SMoriah Waterland 		if (errflg = pkgxfer(pkg[i], options)) {
6125c51f124SMoriah Waterland 			pkg[i] = NULL;
6135c51f124SMoriah Waterland 			if ((options & PT_ODTSTREAM) || (errflg != 2))
6145c51f124SMoriah Waterland 				break;
6155c51f124SMoriah Waterland 		} else if (strcmp(dstinst, pkg[i]))
6165c51f124SMoriah Waterland 			pkg[i] = strdup(dstinst);
6175c51f124SMoriah Waterland 	}
6185c51f124SMoriah Waterland 
6195c51f124SMoriah Waterland 	if (!(options & PT_ODTSTREAM) && dst) {
6205c51f124SMoriah Waterland 		pkgdir = strdup(dst);
6215c51f124SMoriah Waterland 	}
6225c51f124SMoriah Waterland 
6235c51f124SMoriah Waterland 	/*
6245c51f124SMoriah Waterland 	 * No cleanup of temporary directories created in this
6255c51f124SMoriah Waterland 	 * function is done here. The calling function must do
6265c51f124SMoriah Waterland 	 * the cleanup.
6275c51f124SMoriah Waterland 	 */
6285c51f124SMoriah Waterland 
6295c51f124SMoriah Waterland 	return (signal_received > 0 ? 1 : errflg);
6305c51f124SMoriah Waterland }
6315c51f124SMoriah Waterland 
6325c51f124SMoriah Waterland int
pkgtrans(char * device1,char * device2,char ** pkg,int options,keystore_handle_t keystore,char * keystore_alias)6335c51f124SMoriah Waterland pkgtrans(char *device1, char *device2, char **pkg, int options,
6345c51f124SMoriah Waterland     keystore_handle_t keystore, char *keystore_alias)
6355c51f124SMoriah Waterland {
6365c51f124SMoriah Waterland 	int			r;
6375c51f124SMoriah Waterland 	struct sigaction	nact;
6385c51f124SMoriah Waterland 	struct sigaction	oact;
6395c51f124SMoriah Waterland 
6405c51f124SMoriah Waterland 	/*
6415c51f124SMoriah Waterland 	 * setup signal handlers for SIGINT and SIGHUP and release hold
6425c51f124SMoriah Waterland 	 */
6435c51f124SMoriah Waterland 
6445c51f124SMoriah Waterland 	/* hold SIGINT/SIGHUP interrupts */
6455c51f124SMoriah Waterland 
6465c51f124SMoriah Waterland 	(void) sighold(SIGHUP);
6475c51f124SMoriah Waterland 	(void) sighold(SIGINT);
6485c51f124SMoriah Waterland 
6495c51f124SMoriah Waterland 	/* hook SIGINT to sigtrap */
6505c51f124SMoriah Waterland 
6515c51f124SMoriah Waterland 	nact.sa_handler = sigtrap;
6525c51f124SMoriah Waterland 	nact.sa_flags = SA_RESTART;
6535c51f124SMoriah Waterland 	(void) sigemptyset(&nact.sa_mask);
6545c51f124SMoriah Waterland 
6555c51f124SMoriah Waterland 	if (sigaction(SIGINT, &nact, &oact) < 0) {
6565c51f124SMoriah Waterland 		sigintHandler = SIG_DFL;
6575c51f124SMoriah Waterland 	} else {
6585c51f124SMoriah Waterland 		sigintHandler = oact.sa_handler;
6595c51f124SMoriah Waterland 	}
6605c51f124SMoriah Waterland 
6615c51f124SMoriah Waterland 	/* hook SIGHUP to sigtrap */
6625c51f124SMoriah Waterland 
6635c51f124SMoriah Waterland 	nact.sa_handler = sigtrap;
6645c51f124SMoriah Waterland 	nact.sa_flags = SA_RESTART;
6655c51f124SMoriah Waterland 	(void) sigemptyset(&nact.sa_mask);
6665c51f124SMoriah Waterland 
6675c51f124SMoriah Waterland 	if (sigaction(SIGHUP, &nact, &oact) < 0) {
6685c51f124SMoriah Waterland 		sighupHandler = SIG_DFL;
6695c51f124SMoriah Waterland 	} else {
6705c51f124SMoriah Waterland 		sighupHandler = oact.sa_handler;
6715c51f124SMoriah Waterland 	}
6725c51f124SMoriah Waterland 
6735c51f124SMoriah Waterland 	/* reset signal received count */
6745c51f124SMoriah Waterland 
6755c51f124SMoriah Waterland 	signal_received = 0;
6765c51f124SMoriah Waterland 
6775c51f124SMoriah Waterland 	/* release hold on signals */
6785c51f124SMoriah Waterland 
6795c51f124SMoriah Waterland 	(void) sigrelse(SIGHUP);
6805c51f124SMoriah Waterland 	(void) sigrelse(SIGINT);
6815c51f124SMoriah Waterland 
6825c51f124SMoriah Waterland 	/*
6835c51f124SMoriah Waterland 	 * perform the package translation
6845c51f124SMoriah Waterland 	 */
6855c51f124SMoriah Waterland 
6865c51f124SMoriah Waterland 	r = _pkgtrans(device1, device2, pkg, options, keystore, keystore_alias);
6875c51f124SMoriah Waterland 
6885c51f124SMoriah Waterland 	/*
6895c51f124SMoriah Waterland 	 * reset signal handlers
6905c51f124SMoriah Waterland 	 */
6915c51f124SMoriah Waterland 
6925c51f124SMoriah Waterland 	/* hold SIGINT/SIGHUP interrupts */
6935c51f124SMoriah Waterland 
6945c51f124SMoriah Waterland 	(void) sighold(SIGHUP);
6955c51f124SMoriah Waterland 	(void) sighold(SIGINT);
6965c51f124SMoriah Waterland 
6975c51f124SMoriah Waterland 	/* reset SIGINT */
6985c51f124SMoriah Waterland 
6995c51f124SMoriah Waterland 	nact.sa_handler = sigintHandler;
7005c51f124SMoriah Waterland 	nact.sa_flags = SA_RESTART;
7015c51f124SMoriah Waterland 	(void) sigemptyset(&nact.sa_mask);
7025c51f124SMoriah Waterland 
7035c51f124SMoriah Waterland 	(void) sigaction(SIGINT, &nact, (struct sigaction *)NULL);
7045c51f124SMoriah Waterland 
7055c51f124SMoriah Waterland 	/* reset SIGHUP */
7065c51f124SMoriah Waterland 
7075c51f124SMoriah Waterland 	nact.sa_handler = sighupHandler;
7085c51f124SMoriah Waterland 	nact.sa_flags = SA_RESTART;
7095c51f124SMoriah Waterland 	(void) sigemptyset(&nact.sa_mask);
7105c51f124SMoriah Waterland 
7115c51f124SMoriah Waterland 	(void) sigaction(SIGHUP, &nact, (struct sigaction *)NULL);
7125c51f124SMoriah Waterland 
7135c51f124SMoriah Waterland 	/* if signal received and pkgtrans returned error, call cleanup */
7145c51f124SMoriah Waterland 
7155c51f124SMoriah Waterland 	if (signal_received > 0) {
7165c51f124SMoriah Waterland 		if (r != 0) {
7175c51f124SMoriah Waterland 			cleanup();
7185c51f124SMoriah Waterland 		}
7195c51f124SMoriah Waterland 		(void) kill(getpid(), SIGINT);
7205c51f124SMoriah Waterland 	}
7215c51f124SMoriah Waterland 
7225c51f124SMoriah Waterland 	/* release hold on signals */
7235c51f124SMoriah Waterland 
7245c51f124SMoriah Waterland 	(void) sigrelse(SIGHUP);
7255c51f124SMoriah Waterland 	(void) sigrelse(SIGINT);
7265c51f124SMoriah Waterland 
7275c51f124SMoriah Waterland 	return (r);
7285c51f124SMoriah Waterland }
7295c51f124SMoriah Waterland 
7305c51f124SMoriah Waterland /*
7315c51f124SMoriah Waterland  * This function concatenates append to the text described in the buf_ctrl
7325c51f124SMoriah Waterland  * structure. This code modifies data in this structure and handles all
7335c51f124SMoriah Waterland  * allocation issues. It returns '0' if everything was successful and '1'
7345c51f124SMoriah Waterland  * if not.
7355c51f124SMoriah Waterland  */
7365c51f124SMoriah Waterland static int
cat_and_count(struct dm_buf * buf_ctrl,char * append)7375c51f124SMoriah Waterland cat_and_count(struct dm_buf *buf_ctrl, char *append)
7385c51f124SMoriah Waterland {
7395c51f124SMoriah Waterland 
7405c51f124SMoriah Waterland 	/* keep allocating until we have enough room to hold string */
7415c51f124SMoriah Waterland 	while ((buf_ctrl->offset + (int)strlen(append))
7425c51f124SMoriah Waterland 	    >= buf_ctrl->allocation) {
7435c51f124SMoriah Waterland 		/* reallocate (and maybe move) text buffer */
7445c51f124SMoriah Waterland 		if ((buf_ctrl->text_buffer =
7455c51f124SMoriah Waterland 		    (char *)realloc(buf_ctrl->text_buffer,
7465c51f124SMoriah Waterland 		    buf_ctrl->allocation + BLK_SIZE)) == NULL) {
7475c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
7485c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_MEM));
7495c51f124SMoriah Waterland 			free(buf_ctrl->text_buffer);
7505c51f124SMoriah Waterland 			return (1);
7515c51f124SMoriah Waterland 		}
7525c51f124SMoriah Waterland 
7535c51f124SMoriah Waterland 		/* clear the new memory */
7545c51f124SMoriah Waterland 		(void) memset(buf_ctrl->text_buffer +
7555c51f124SMoriah Waterland 		    buf_ctrl->allocation, '\0', BLK_SIZE);
7565c51f124SMoriah Waterland 
7575c51f124SMoriah Waterland 		/* adjust total allocation */
7585c51f124SMoriah Waterland 		buf_ctrl->allocation += BLK_SIZE;
7595c51f124SMoriah Waterland 	}
7605c51f124SMoriah Waterland 
7615c51f124SMoriah Waterland 	/* append new string to end of buffer */
7625c51f124SMoriah Waterland 	while (*append) {
7635c51f124SMoriah Waterland 		*(buf_ctrl->text_buffer + buf_ctrl->offset) = *append++;
7645c51f124SMoriah Waterland 		(buf_ctrl->offset)++;
7655c51f124SMoriah Waterland 	}
7665c51f124SMoriah Waterland 
7675c51f124SMoriah Waterland 	return (0);
7685c51f124SMoriah Waterland }
7695c51f124SMoriah Waterland 
7705c51f124SMoriah Waterland static struct dm_buf *
genheader(char * src,char ** pkg)771*4656d474SGarrett D'Amore genheader(char *src, char **pkg)
7725c51f124SMoriah Waterland {
7735c51f124SMoriah Waterland 
7745c51f124SMoriah Waterland 	FILE	*fp;
7755c51f124SMoriah Waterland 	char	path[MAXPATHLEN], tmp_entry[ENTRY_MAX];
7765c51f124SMoriah Waterland 	int	i, n, nparts, maxpsize;
777*4656d474SGarrett D'Amore 	int	partcnt;
778*4656d474SGarrett D'Amore 	long	totsize;
7795c51f124SMoriah Waterland 	struct stat statbuf;
7805c51f124SMoriah Waterland 
7815c51f124SMoriah Waterland 	if ((hdrbuf.text_buffer = (char *)malloc(BLK_SIZE)) == NULL) {
7825c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
7835c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_MEM));
7845c51f124SMoriah Waterland 		return (NULL);
7855c51f124SMoriah Waterland 	}
7865c51f124SMoriah Waterland 
7875c51f124SMoriah Waterland 	/* clear the new memory */
7885c51f124SMoriah Waterland 	(void) memset(hdrbuf.text_buffer, '\0', BLK_SIZE);
7895c51f124SMoriah Waterland 
7905c51f124SMoriah Waterland 	/* set up the buffer control structure for the header */
7915c51f124SMoriah Waterland 	hdrbuf.offset = 0;
7925c51f124SMoriah Waterland 	hdrbuf.allocation = BLK_SIZE;
7935c51f124SMoriah Waterland 
7945c51f124SMoriah Waterland 	(void) cat_and_count(&hdrbuf, HDR_PREFIX);
7955c51f124SMoriah Waterland 	(void) cat_and_count(&hdrbuf, "\n");
7965c51f124SMoriah Waterland 
7975c51f124SMoriah Waterland 	nparts = maxpsize = 0;
7985c51f124SMoriah Waterland 
7995c51f124SMoriah Waterland 	totsize = 0;
8005c51f124SMoriah Waterland 	for (i = 0; pkg[i]; i++)  {
8015c51f124SMoriah Waterland 		(void) snprintf(path, MAXPATHLEN, "%s/%s/%s",
8025c51f124SMoriah Waterland 		    src, pkg[i], PKGINFO);
8035c51f124SMoriah Waterland 		if (stat(path, &statbuf) < 0) {
8045c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
8055c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_BADPKGINFO));
8065c51f124SMoriah Waterland 			ecleanup();
8075c51f124SMoriah Waterland 			return (NULL);
8085c51f124SMoriah Waterland 		}
8095c51f124SMoriah Waterland 		totsize += statbuf.st_size/BLK_SIZE + 1;
8105c51f124SMoriah Waterland 	}
8115c51f124SMoriah Waterland 
8125c51f124SMoriah Waterland 	/*
8135c51f124SMoriah Waterland 	 * totsize contains number of blocks used by the pkginfo files
8145c51f124SMoriah Waterland 	 */
8155c51f124SMoriah Waterland 	totsize += i/4 + 1;
8165c51f124SMoriah Waterland 	if (dstdev.capacity && totsize > dstdev.capacity) {
8175c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
8185c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_NOSPACE), totsize, dstdev.capacity);
8195c51f124SMoriah Waterland 		ecleanup();
8205c51f124SMoriah Waterland 		return (NULL);
8215c51f124SMoriah Waterland 	}
8225c51f124SMoriah Waterland 
8235c51f124SMoriah Waterland 	ds_volcnt = 1;
8245c51f124SMoriah Waterland 	for (i = 0; pkg[i]; i++) {
8255c51f124SMoriah Waterland 		partcnt = 0;
8265c51f124SMoriah Waterland 		(void) snprintf(path, MAXPATHLEN, "%s/%s/%s",
8275c51f124SMoriah Waterland 		    src, pkg[i], PKGMAP);
8285c51f124SMoriah Waterland 		if ((fp = fopen(path, "r")) == NULL) {
8295c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
8305c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_NOPKGMAP), pkg[i]);
8315c51f124SMoriah Waterland 			ecleanup();
8325c51f124SMoriah Waterland 			return (NULL);
8335c51f124SMoriah Waterland 		}
8345c51f124SMoriah Waterland 
8355c51f124SMoriah Waterland 		/* Evaluate the first entry in pkgmap */
8365c51f124SMoriah Waterland 		n = rd_map_size(fp, &nparts, &maxpsize, &compressedsize);
8375c51f124SMoriah Waterland 
8385c51f124SMoriah Waterland 		if (n == 3)	/* It's a compressed package */
8395c51f124SMoriah Waterland 			/* The header needs the *real* size */
8405c51f124SMoriah Waterland 			maxpsize = compressedsize;
8415c51f124SMoriah Waterland 		else if (n == 0)	/* pkgmap is corrupt */
8425c51f124SMoriah Waterland 			return (NULL);
8435c51f124SMoriah Waterland 
8445c51f124SMoriah Waterland 		if (dstdev.capacity && maxpsize > dstdev.capacity) {
8455c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
846*4656d474SGarrett D'Amore 			logerr(pkg_gt(MSG_NOSPACE), (long)maxpsize,
847*4656d474SGarrett D'Amore 			    dstdev.capacity);
8485c51f124SMoriah Waterland 			(void) fclose(fp);
8495c51f124SMoriah Waterland 			ecleanup();
8505c51f124SMoriah Waterland 			return (NULL);
8515c51f124SMoriah Waterland 		}
8525c51f124SMoriah Waterland 
8535c51f124SMoriah Waterland 		/* add pkg name, number of parts and the max part size */
8545c51f124SMoriah Waterland 		if (snprintf(tmp_entry, ENTRY_MAX, "%s %d %d",
8555c51f124SMoriah Waterland 				pkg[i], nparts, maxpsize) >= ENTRY_MAX) {
8565c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
8575c51f124SMoriah Waterland 			logerr(pkg_gt(ERR_MEM));
8585c51f124SMoriah Waterland 			(void) fclose(fp);
8595c51f124SMoriah Waterland 			ecleanup();
8605c51f124SMoriah Waterland 			return (NULL);
8615c51f124SMoriah Waterland 		}
8625c51f124SMoriah Waterland 		if (cat_and_count(&hdrbuf, tmp_entry)) {
8635c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
8645c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_MEM));
8655c51f124SMoriah Waterland 			(void) fclose(fp);
8665c51f124SMoriah Waterland 			ecleanup();
8675c51f124SMoriah Waterland 			return (NULL);
8685c51f124SMoriah Waterland 		}
8695c51f124SMoriah Waterland 
8705c51f124SMoriah Waterland 		totsize += nparts * maxpsize;
8715c51f124SMoriah Waterland 		if (dstdev.capacity && dstdev.capacity < totsize) {
8725c51f124SMoriah Waterland 			int lastpartcnt = 0;
8735c51f124SMoriah Waterland 
8745c51f124SMoriah Waterland 			if (totsize)
8755c51f124SMoriah Waterland 				totsize -= nparts * maxpsize;
8765c51f124SMoriah Waterland 			while (partcnt < nparts) {
8775c51f124SMoriah Waterland 				while (totsize <= dstdev.capacity &&
8785c51f124SMoriah Waterland 				    partcnt <= nparts) {
8795c51f124SMoriah Waterland 					totsize +=  maxpsize;
8805c51f124SMoriah Waterland 					partcnt++;
8815c51f124SMoriah Waterland 				}
8825c51f124SMoriah Waterland 				/* partcnt == 0 means skip to next volume */
8835c51f124SMoriah Waterland 				if (partcnt)
8845c51f124SMoriah Waterland 					partcnt--;
8855c51f124SMoriah Waterland 				(void) snprintf(tmp_entry, ENTRY_MAX,
8865c51f124SMoriah Waterland 				    " %d", partcnt - lastpartcnt);
8875c51f124SMoriah Waterland 				if (cat_and_count(&hdrbuf, tmp_entry)) {
8885c51f124SMoriah Waterland 					progerr(pkg_gt(ERR_TRANSFER));
8895c51f124SMoriah Waterland 					logerr(pkg_gt(MSG_MEM));
8905c51f124SMoriah Waterland 					(void) fclose(fp);
8915c51f124SMoriah Waterland 					ecleanup();
8925c51f124SMoriah Waterland 					return (NULL);
8935c51f124SMoriah Waterland 				}
8945c51f124SMoriah Waterland 				ds_volcnt++;
8955c51f124SMoriah Waterland 				totsize = 0;
8965c51f124SMoriah Waterland 				lastpartcnt = partcnt;
8975c51f124SMoriah Waterland 			}
8985c51f124SMoriah Waterland 			/* first parts/volume number does not count */
8995c51f124SMoriah Waterland 			ds_volcnt--;
9005c51f124SMoriah Waterland 		}
9015c51f124SMoriah Waterland 
9025c51f124SMoriah Waterland 		if (cat_and_count(&hdrbuf, "\n")) {
9035c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
9045c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_MEM));
9055c51f124SMoriah Waterland 			(void) fclose(fp);
9065c51f124SMoriah Waterland 			ecleanup();
9075c51f124SMoriah Waterland 			return (NULL);
9085c51f124SMoriah Waterland 		}
9095c51f124SMoriah Waterland 
9105c51f124SMoriah Waterland 		(void) fclose(fp);
9115c51f124SMoriah Waterland 	}
9125c51f124SMoriah Waterland 
9135c51f124SMoriah Waterland 	if (cat_and_count(&hdrbuf, HDR_SUFFIX) ||
9145c51f124SMoriah Waterland 	    cat_and_count(&hdrbuf, "\n")) {
9155c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
9165c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_MEM));
9175c51f124SMoriah Waterland 		(void) fclose(fp);
9185c51f124SMoriah Waterland 		ecleanup();
9195c51f124SMoriah Waterland 		return (NULL);
9205c51f124SMoriah Waterland 	}
9215c51f124SMoriah Waterland 	return (&hdrbuf);
9225c51f124SMoriah Waterland }
9235c51f124SMoriah Waterland 
9245c51f124SMoriah Waterland static int
wdsheader(struct dm_buf * hdr,char * src,char * device,char ** pkg,PKCS7 * sig)9255c51f124SMoriah Waterland wdsheader(struct dm_buf *hdr, char *src, char *device, char **pkg, PKCS7 *sig)
9265c51f124SMoriah Waterland {
9275c51f124SMoriah Waterland 	FILE	*fp;
9285c51f124SMoriah Waterland 	char	path[PATH_MAX], tmp_entry[ENTRY_MAX],
9295c51f124SMoriah Waterland 	    tmp_file[L_tmpnam+1];
9305c51f124SMoriah Waterland 	char	srcpath[PATH_MAX];
9315c51f124SMoriah Waterland 	int	i, n;
9325c51f124SMoriah Waterland 	int	list_fd;
9335c51f124SMoriah Waterland 	int	block_cnt;
9345c51f124SMoriah Waterland 	int 	len;
9355c51f124SMoriah Waterland 	char	cwd[MAXPATHLEN + 1];
9365c51f124SMoriah Waterland 	boolean_t	making_sig = B_FALSE;
9375c51f124SMoriah Waterland 
9385c51f124SMoriah Waterland 	making_sig = (sig != NULL) ? B_TRUE : B_FALSE;
9395c51f124SMoriah Waterland 
9405c51f124SMoriah Waterland 	(void) ds_close(0);
9415c51f124SMoriah Waterland 	if (dstdev.pathname)
9425c51f124SMoriah Waterland 		ds_fd = creat(device, 0644);
9435c51f124SMoriah Waterland 	else
9445c51f124SMoriah Waterland 		ds_fd = open(device, 1);
9455c51f124SMoriah Waterland 
9465c51f124SMoriah Waterland 	if (ds_fd < 0) {
9475c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
9485c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_OPEN), device, errno);
9495c51f124SMoriah Waterland 		return (1);
9505c51f124SMoriah Waterland 	}
9515c51f124SMoriah Waterland 
9525c51f124SMoriah Waterland 	if (ds_ginit(device) < 0) {
9535c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
9545c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_OPEN), device, errno);
9555c51f124SMoriah Waterland 		(void) ds_close(0);
9565c51f124SMoriah Waterland 		return (1);
9575c51f124SMoriah Waterland 	}
9585c51f124SMoriah Waterland 
9595c51f124SMoriah Waterland 	/*
9605c51f124SMoriah Waterland 	 * The loop below assures compatibility with tapes that don't
9615c51f124SMoriah Waterland 	 * have a block size (e.g.: Exabyte) by forcing EOR at the end
9625c51f124SMoriah Waterland 	 * of each 512 bytes.
9635c51f124SMoriah Waterland 	 */
9645c51f124SMoriah Waterland 	for (block_cnt = 0; block_cnt < hdr->allocation;
9655c51f124SMoriah Waterland 		block_cnt += BLK_SIZE) {
966*4656d474SGarrett D'Amore 		(void) write(ds_fd, (hdr->text_buffer + block_cnt), BLK_SIZE);
9675c51f124SMoriah Waterland 	}
9685c51f124SMoriah Waterland 
9695c51f124SMoriah Waterland 	/*
9705c51f124SMoriah Waterland 	 * write the first cpio() archive to the datastream
9715c51f124SMoriah Waterland 	 * which should contain the pkginfo & pkgmap files
9725c51f124SMoriah Waterland 	 * for all packages
9735c51f124SMoriah Waterland 	 */
9745c51f124SMoriah Waterland 	(void) tmpnam(tmp_file);	/* temporary file name */
975*4656d474SGarrett D'Amore 	if ((list_fd = open(tmp_file, O_RDWR | O_CREAT, 0644)) == -1) {
9765c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
977*4656d474SGarrett D'Amore 		logerr(pkg_gt(MSG_NOTMPFIL), tmp_file);
9785c51f124SMoriah Waterland 		return (1);
9795c51f124SMoriah Waterland 	}
9805c51f124SMoriah Waterland 
9815c51f124SMoriah Waterland 	/*
9825c51f124SMoriah Waterland 	 * Create a cpio-compatible list of the requisite files in
9835c51f124SMoriah Waterland 	 * the temporary file.
9845c51f124SMoriah Waterland 	 */
9855c51f124SMoriah Waterland 	if (!making_sig) {
9865c51f124SMoriah Waterland 		for (i = 0; pkg[i]; i++) {
9875c51f124SMoriah Waterland 			register ssize_t entry_size;
9885c51f124SMoriah Waterland 
9895c51f124SMoriah Waterland 			/*
9905c51f124SMoriah Waterland 			 * Copy pkginfo and pkgmap filenames into the
9915c51f124SMoriah Waterland 			 * temporary string allowing for the first line
9925c51f124SMoriah Waterland 			 * as a special case.
9935c51f124SMoriah Waterland 			 */
9945c51f124SMoriah Waterland 			entry_size = sprintf(tmp_entry,
9955c51f124SMoriah Waterland 			    (i == 0) ? "%s/%s\n%s/%s" : "\n%s/%s\n%s/%s",
9965c51f124SMoriah Waterland 			    pkg[i], PKGINFO, pkg[i], PKGMAP);
9975c51f124SMoriah Waterland 
9985c51f124SMoriah Waterland 			if (write(list_fd, tmp_entry,
9995c51f124SMoriah Waterland 			    entry_size) != entry_size) {
10005c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_TRANSFER));
1001*4656d474SGarrett D'Amore 				logerr(pkg_gt(MSG_NOTMPFIL), tmp_file);
10025c51f124SMoriah Waterland 				(void) close(list_fd);
10035c51f124SMoriah Waterland 				ecleanup();
10045c51f124SMoriah Waterland 				return (1);
10055c51f124SMoriah Waterland 			}
10065c51f124SMoriah Waterland 		}
10075c51f124SMoriah Waterland 
10085c51f124SMoriah Waterland 	} else {
10095c51f124SMoriah Waterland 		register ssize_t entry_size;
10105c51f124SMoriah Waterland 
10115c51f124SMoriah Waterland 		/*
10125c51f124SMoriah Waterland 		 * if we're making a signature, we must make a
10135c51f124SMoriah Waterland 		 * temporary area full of symlinks to the requisite
10145c51f124SMoriah Waterland 		 * files, plus an extra entry for the signature, so
10155c51f124SMoriah Waterland 		 * that cpio will put all files and signature in the
10165c51f124SMoriah Waterland 		 * same archive in a single invocation of cpio.
10175c51f124SMoriah Waterland 		 */
10185c51f124SMoriah Waterland 		tmpsymdir = xstrdup(tmpnam(NULL));
10195c51f124SMoriah Waterland 
10205c51f124SMoriah Waterland 		if (mkdir(tmpsymdir,  S_IRWXU)) {
10215c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
10225c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_MKDIR), tmpsymdir);
10235c51f124SMoriah Waterland 			return (1);
10245c51f124SMoriah Waterland 		}
10255c51f124SMoriah Waterland 
10265c51f124SMoriah Waterland 		/* generate the signature */
10275c51f124SMoriah Waterland 		if (((len = snprintf(path, PATH_MAX, "%s/%s",
10285c51f124SMoriah Waterland 		    tmpsymdir, SIGNATURE_FILENAME)) >= PATH_MAX) ||
10295c51f124SMoriah Waterland 		    len < 0) {
10305c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
10315c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_NOTMPFIL), tmpsymdir);
10325c51f124SMoriah Waterland 			cleanup();
10335c51f124SMoriah Waterland 			return (1);
10345c51f124SMoriah Waterland 		}
10355c51f124SMoriah Waterland 
10365c51f124SMoriah Waterland 		if ((fp = fopen(path, "w")) == NULL) {
10375c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
10385c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_NOTMPFIL), path);
10395c51f124SMoriah Waterland 			cleanup();
10405c51f124SMoriah Waterland 			return (1);
10415c51f124SMoriah Waterland 		}
1042*4656d474SGarrett D'Amore 		(void) PEM_write_PKCS7(fp, sig);
10435c51f124SMoriah Waterland 		(void) fclose(fp);
10445c51f124SMoriah Waterland 
10455c51f124SMoriah Waterland 		for (i = 0; pkg[i]; i++) {
1046*4656d474SGarrett D'Amore 			(void) snprintf(path, sizeof (path),
1047*4656d474SGarrett D'Amore 			    "%s/%s", tmpsymdir, pkg[i]);
10485c51f124SMoriah Waterland 			if (mkdir(path, 0755)) {
10495c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_TRANSFER));
10505c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_MKDIR), path);
10515c51f124SMoriah Waterland 				cleanup();
10525c51f124SMoriah Waterland 				return (1);
10535c51f124SMoriah Waterland 			}
1054*4656d474SGarrett D'Amore 			(void) snprintf(path, sizeof (path),
1055*4656d474SGarrett D'Amore 			    "%s/%s/%s", tmpsymdir, pkg[i], PKGINFO);
1056*4656d474SGarrett D'Amore 			(void) snprintf(srcpath, sizeof (srcpath),
1057*4656d474SGarrett D'Amore 			    "%s/%s/%s", src, pkg[i], PKGINFO);
10585c51f124SMoriah Waterland 			if (symlink(srcpath, path) != 0) {
10595c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_TRANSFER));
10605c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_SYMLINK), path, srcpath);
10615c51f124SMoriah Waterland 				cleanup();
10625c51f124SMoriah Waterland 				return (1);
10635c51f124SMoriah Waterland 			}
10645c51f124SMoriah Waterland 
1065*4656d474SGarrett D'Amore 			(void) snprintf(path, sizeof (path),
1066*4656d474SGarrett D'Amore 			    "%s/%s/%s", tmpsymdir, pkg[i], PKGMAP);
1067*4656d474SGarrett D'Amore 			(void) snprintf(srcpath, sizeof (srcpath),
1068*4656d474SGarrett D'Amore 			    "%s/%s/%s", src, pkg[i], PKGMAP);
10695c51f124SMoriah Waterland 			if (symlink(srcpath, path) != 0) {
10705c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_TRANSFER));
10715c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_SYMLINK), path, srcpath);
10725c51f124SMoriah Waterland 				cleanup();
10735c51f124SMoriah Waterland 				return (1);
10745c51f124SMoriah Waterland 			}
10755c51f124SMoriah Waterland 
10765c51f124SMoriah Waterland 			/*
10775c51f124SMoriah Waterland 			 * Copy pkginfo and pkgmap filenames into the
10785c51f124SMoriah Waterland 			 * temporary string allowing for the first line
10795c51f124SMoriah Waterland 			 * as a special case.
10805c51f124SMoriah Waterland 			 */
1081*4656d474SGarrett D'Amore 			entry_size = snprintf(tmp_entry, sizeof (tmp_entry),
10825c51f124SMoriah Waterland 			    (i == 0) ? "%s/%s\n%s/%s" : "\n%s/%s\n%s/%s",
10835c51f124SMoriah Waterland 			    pkg[i], PKGINFO, pkg[i], PKGMAP);
10845c51f124SMoriah Waterland 
10855c51f124SMoriah Waterland 			if (write(list_fd, tmp_entry,
10865c51f124SMoriah Waterland 			    entry_size) != entry_size) {
10875c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_TRANSFER));
1088*4656d474SGarrett D'Amore 				logerr(pkg_gt(MSG_NOTMPFIL), tmp_file);
10895c51f124SMoriah Waterland 				(void) close(list_fd);
10905c51f124SMoriah Waterland 				ecleanup();
10915c51f124SMoriah Waterland 				cleanup();
10925c51f124SMoriah Waterland 				return (1);
10935c51f124SMoriah Waterland 			}
10945c51f124SMoriah Waterland 		}
10955c51f124SMoriah Waterland 
10965c51f124SMoriah Waterland 		/* add signature to list of files */
1097*4656d474SGarrett D'Amore 		entry_size = snprintf(tmp_entry, sizeof (tmp_entry), "\n%s",
1098*4656d474SGarrett D'Amore 		    SIGNATURE_FILENAME);
10995c51f124SMoriah Waterland 		if (write(list_fd, tmp_entry, entry_size) != entry_size) {
11005c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
11015c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_NOTMPFIL), tmp_file);
11025c51f124SMoriah Waterland 			(void) close(list_fd);
11035c51f124SMoriah Waterland 			ecleanup();
11045c51f124SMoriah Waterland 			cleanup();
11055c51f124SMoriah Waterland 			return (1);
11065c51f124SMoriah Waterland 		}
11075c51f124SMoriah Waterland 	}
11085c51f124SMoriah Waterland 
11095c51f124SMoriah Waterland 	(void) lseek(list_fd, 0, SEEK_SET);
11105c51f124SMoriah Waterland 
11115c51f124SMoriah Waterland 	if (!making_sig) {
1112*4656d474SGarrett D'Amore 		(void) snprintf(tmp_entry, sizeof (tmp_entry),
1113*4656d474SGarrett D'Amore 		    "%s -ocD -C %d", CPIOPROC, (int)BLK_SIZE);
11145c51f124SMoriah Waterland 	} else {
11155c51f124SMoriah Waterland 		/*
11165c51f124SMoriah Waterland 		 * when making a signature, we must make sure to follow
11175c51f124SMoriah Waterland 		 * symlinks during the cpio so that we don't archive
11185c51f124SMoriah Waterland 		 * the links themselves
11195c51f124SMoriah Waterland 		 */
1120*4656d474SGarrett D'Amore 		(void) snprintf(tmp_entry, sizeof (tmp_entry),
1121*4656d474SGarrett D'Amore 		    "%s -ocDL -C %d", CPIOPROC, (int)BLK_SIZE);
11225c51f124SMoriah Waterland 	}
11235c51f124SMoriah Waterland 
11245c51f124SMoriah Waterland 	if (making_sig) {
11255c51f124SMoriah Waterland 		/* save cwd and change to symlink dir for cpio invocation */
11265c51f124SMoriah Waterland 		if (getcwd(cwd, MAXPATHLEN + 1) == NULL) {
11275c51f124SMoriah Waterland 			logerr(pkg_gt(ERR_GETWD));
11285c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
11295c51f124SMoriah Waterland 			cleanup();
11305c51f124SMoriah Waterland 			return (1);
11315c51f124SMoriah Waterland 		}
11325c51f124SMoriah Waterland 
11335c51f124SMoriah Waterland 		if (chdir(tmpsymdir)) {
11345c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
11355c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_CHDIR), tmpsymdir);
11365c51f124SMoriah Waterland 			cleanup();
11375c51f124SMoriah Waterland 			return (1);
11385c51f124SMoriah Waterland 		}
11395c51f124SMoriah Waterland 	}
11405c51f124SMoriah Waterland 
11415c51f124SMoriah Waterland 	if (n = esystem(tmp_entry, list_fd, ds_fd)) {
11425c51f124SMoriah Waterland 		rpterr();
11435c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
11445c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_CMDFAIL), tmp_entry, n);
11455c51f124SMoriah Waterland 		(void) close(list_fd);
11465c51f124SMoriah Waterland 		(void) unlink(tmp_file);
11475c51f124SMoriah Waterland 		cleanup();
11485c51f124SMoriah Waterland 		return (1);
11495c51f124SMoriah Waterland 	}
11505c51f124SMoriah Waterland 
11515c51f124SMoriah Waterland 	(void) close(list_fd);
11525c51f124SMoriah Waterland 	(void) unlink(tmp_file);
11535c51f124SMoriah Waterland 
11545c51f124SMoriah Waterland 	if (making_sig) {
11555c51f124SMoriah Waterland 		/* change to back to src dir for subsequent operations */
11565c51f124SMoriah Waterland 		if (chdir(cwd)) {
11575c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
11585c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_CHDIR), cwd);
11595c51f124SMoriah Waterland 			cleanup();
11605c51f124SMoriah Waterland 			return (1);
11615c51f124SMoriah Waterland 		}
11625c51f124SMoriah Waterland 	}
11635c51f124SMoriah Waterland 	return (0);
11645c51f124SMoriah Waterland }
11655c51f124SMoriah Waterland 
11665c51f124SMoriah Waterland static int
ckoverwrite(char * dir,char * inst,int options)11675c51f124SMoriah Waterland ckoverwrite(char *dir, char *inst, int options)
11685c51f124SMoriah Waterland {
11695c51f124SMoriah Waterland 	char	path[PATH_MAX];
11705c51f124SMoriah Waterland 
1171*4656d474SGarrett D'Amore 	(void) snprintf(path, sizeof (path), "%s/%s", dir, inst);
11725c51f124SMoriah Waterland 	if (access(path, 0) == 0) {
11735c51f124SMoriah Waterland 		if (options & PT_OVERWRITE)
11745c51f124SMoriah Waterland 			return (rrmdir(path));
11755c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
11765c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_EXISTS), path);
11775c51f124SMoriah Waterland 		return (1);
11785c51f124SMoriah Waterland 	}
11795c51f124SMoriah Waterland 	return (0);
11805c51f124SMoriah Waterland }
11815c51f124SMoriah Waterland 
11825c51f124SMoriah Waterland static int
pkgxfer(char * srcinst,int options)11835c51f124SMoriah Waterland pkgxfer(char *srcinst, int options)
11845c51f124SMoriah Waterland {
11855c51f124SMoriah Waterland 	int	r;
11865c51f124SMoriah Waterland 	struct pkginfo info;
11875c51f124SMoriah Waterland 	FILE	*fp, *pp;
11885c51f124SMoriah Waterland 	char	*pt, *src, *dst;
11895c51f124SMoriah Waterland 	char	dstdir[PATH_MAX],
11905c51f124SMoriah Waterland 		temp[PATH_MAX],
11915c51f124SMoriah Waterland 		srcdir[PATH_MAX],
11925c51f124SMoriah Waterland 		cmd[CMDSIZE],
11935c51f124SMoriah Waterland 		pkgname[NON_ABI_NAMELNGTH];
11945c51f124SMoriah Waterland 	int	i, n, part, nparts, maxpartsize, curpartcnt, iscomp;
11955c51f124SMoriah Waterland 	char	volnos[128], tmpvol[128];
11965c51f124SMoriah Waterland 	struct	statvfs64 svfsb;
11975c51f124SMoriah Waterland 	longlong_t free_blocks;
11985c51f124SMoriah Waterland 	struct	stat	srcstat;
11995c51f124SMoriah Waterland 
12005c51f124SMoriah Waterland 	info.pkginst = NULL; /* required initialization */
12015c51f124SMoriah Waterland 
12025c51f124SMoriah Waterland 	/*
12035c51f124SMoriah Waterland 	 * when this routine is entered, the first part of
12045c51f124SMoriah Waterland 	 * the package to transfer is already available in
12055c51f124SMoriah Waterland 	 * the directory indicated by 'src' --- unless the
12065c51f124SMoriah Waterland 	 * source device is a datstream, in which case only
12075c51f124SMoriah Waterland 	 * the pkginfo and pkgmap files are available in 'src'
12085c51f124SMoriah Waterland 	 */
12095c51f124SMoriah Waterland 	src = srcdev.dirname;
12105c51f124SMoriah Waterland 	dst = dstdev.dirname;
12115c51f124SMoriah Waterland 
12125c51f124SMoriah Waterland 	if (!(options & PT_SILENT))
12135c51f124SMoriah Waterland 		(void) fprintf(stderr, pkg_gt(MSG_TRANSFER), srcinst);
1214*4656d474SGarrett D'Amore 	(void) strlcpy(dstinst, srcinst, sizeof (dstinst));
12155c51f124SMoriah Waterland 
12165c51f124SMoriah Waterland 	if (!(options & PT_ODTSTREAM)) {
12175c51f124SMoriah Waterland 		/* destination is a (possibly mounted) directory */
1218*4656d474SGarrett D'Amore 		(void) snprintf(dstdir, sizeof (dstdir),
1219*4656d474SGarrett D'Amore 		    "%s/%s", dst, dstinst);
12205c51f124SMoriah Waterland 
12215c51f124SMoriah Waterland 		/*
12225c51f124SMoriah Waterland 		 * need to check destination directory to assure
12235c51f124SMoriah Waterland 		 * that we will not be duplicating a package which
12245c51f124SMoriah Waterland 		 * already resides there (though we are allowed to
12255c51f124SMoriah Waterland 		 * overwrite the same version)
12265c51f124SMoriah Waterland 		 */
12275c51f124SMoriah Waterland 		pkgdir = src;
12285c51f124SMoriah Waterland 		if (fpkginfo(&info, srcinst)) {
12295c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
12305c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_NOEXISTS), srcinst);
12315c51f124SMoriah Waterland 			(void) fpkginfo(&info, NULL);
12325c51f124SMoriah Waterland 			return (1);
12335c51f124SMoriah Waterland 		}
12345c51f124SMoriah Waterland 		pkgdir = dst;
12355c51f124SMoriah Waterland 
1236*4656d474SGarrett D'Amore 		(void) strlcpy(temp, srcinst, sizeof (temp));
12375c51f124SMoriah Waterland 		if (pt = strchr(temp, '.'))
12385c51f124SMoriah Waterland 			*pt = '\0';
1239*4656d474SGarrett D'Amore 		(void) strlcat(temp, ".*", sizeof (temp));
12405c51f124SMoriah Waterland 
12415c51f124SMoriah Waterland 		if (pt = fpkginst(temp, info.arch, info.version)) {
12425c51f124SMoriah Waterland 			/*
12435c51f124SMoriah Waterland 			 * the same instance already exists, although
12445c51f124SMoriah Waterland 			 * its pkgid might be different
12455c51f124SMoriah Waterland 			 */
12465c51f124SMoriah Waterland 			if (options & PT_OVERWRITE) {
1247*4656d474SGarrett D'Amore 				(void) strlcpy(dstinst, pt, sizeof (dstinst));
1248*4656d474SGarrett D'Amore 				(void) snprintf(dstdir, sizeof (dstdir),
1249*4656d474SGarrett D'Amore 				    "%s/%s", dst, dstinst);
12505c51f124SMoriah Waterland 			} else {
12515c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_TRANSFER));
12525c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_DUPVERS), srcinst);
12535c51f124SMoriah Waterland 				(void) fpkginfo(&info, NULL);
12545c51f124SMoriah Waterland 				(void) fpkginst(NULL);
12555c51f124SMoriah Waterland 				return (2);
12565c51f124SMoriah Waterland 			}
12575c51f124SMoriah Waterland 		} else if (options & PT_RENAME) {
12585c51f124SMoriah Waterland 			/*
12595c51f124SMoriah Waterland 			 * find next available instance by appending numbers
12605c51f124SMoriah Waterland 			 * to the package abbreviation until the instance
12615c51f124SMoriah Waterland 			 * does not exist in the destination directory
12625c51f124SMoriah Waterland 			 */
12635c51f124SMoriah Waterland 			if (pt = strchr(temp, '.'))
12645c51f124SMoriah Waterland 				*pt = '\0';
12655c51f124SMoriah Waterland 			for (i = 2; (access(dstdir, 0) == 0); i++) {
1266*4656d474SGarrett D'Amore 				(void) snprintf(dstinst, sizeof (dstinst),
1267*4656d474SGarrett D'Amore 				    "%s.%d", temp, i);
1268*4656d474SGarrett D'Amore 				(void) snprintf(dstdir, sizeof (dstdir),
1269*4656d474SGarrett D'Amore 				    "%s/%s", dst, dstinst);
12705c51f124SMoriah Waterland 			}
12715c51f124SMoriah Waterland 		} else if (options & PT_OVERWRITE) {
12725c51f124SMoriah Waterland 			/*
12735c51f124SMoriah Waterland 			 * we're allowed to overwrite, but there seems
12745c51f124SMoriah Waterland 			 * to be no valid package to overwrite, and we are
12755c51f124SMoriah Waterland 			 * not allowed to rename the destination, so act
12765c51f124SMoriah Waterland 			 * as if we weren't given permission to overwrite
12775c51f124SMoriah Waterland 			 * --- this keeps us from removing a destination
12785c51f124SMoriah Waterland 			 * instance which is named the same as the source
12795c51f124SMoriah Waterland 			 * instance, but really reflects a different pkg!
12805c51f124SMoriah Waterland 			 */
12815c51f124SMoriah Waterland 			options &= (~PT_OVERWRITE);
12825c51f124SMoriah Waterland 		}
12835c51f124SMoriah Waterland 		(void) fpkginfo(&info, NULL);
12845c51f124SMoriah Waterland 		(void) fpkginst(NULL);
12855c51f124SMoriah Waterland 
12865c51f124SMoriah Waterland 		if (ckoverwrite(dst, dstinst, options))
12875c51f124SMoriah Waterland 			return (2);
12885c51f124SMoriah Waterland 
12895c51f124SMoriah Waterland 		if (isdir(dstdir) && mkdir(dstdir, 0755)) {
12905c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
12915c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_MKDIR), dstdir);
12925c51f124SMoriah Waterland 			return (1);
12935c51f124SMoriah Waterland 		}
12945c51f124SMoriah Waterland 
1295*4656d474SGarrett D'Amore 		(void) snprintf(srcdir, sizeof (srcdir),
1296*4656d474SGarrett D'Amore 		    "%s/%s", src, srcinst);
12975c51f124SMoriah Waterland 		if (stat(srcdir, &srcstat) != -1) {
12985c51f124SMoriah Waterland 			if (chmod(dstdir, (srcstat.st_mode & S_IAMB)) == -1) {
12995c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_TRANSFER));
13005c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_CHMODDIR), dstdir);
13015c51f124SMoriah Waterland 				return (1);
13025c51f124SMoriah Waterland 			}
13035c51f124SMoriah Waterland 		} else {
13045c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
13055c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_STATDIR), srcdir);
13065c51f124SMoriah Waterland 			return (1);
13075c51f124SMoriah Waterland 		}
13085c51f124SMoriah Waterland 	}
13095c51f124SMoriah Waterland 
13105c51f124SMoriah Waterland 	if (!(options & PT_SILENT) && strcmp(dstinst, srcinst))
13115c51f124SMoriah Waterland 		(void) fprintf(stderr, pkg_gt(MSG_RENAME), dstinst);
13125c51f124SMoriah Waterland 
1313*4656d474SGarrett D'Amore 	(void) snprintf(srcdir, sizeof (srcdir), "%s/%s", src, srcinst);
13145c51f124SMoriah Waterland 	if (chdir(srcdir)) {
13155c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
13165c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_CHDIR), srcdir);
13175c51f124SMoriah Waterland 		return (1);
13185c51f124SMoriah Waterland 	}
13195c51f124SMoriah Waterland 
13205c51f124SMoriah Waterland 	if (ids_name) {	/* unpack the datatstream into a directory */
13215c51f124SMoriah Waterland 		/*
13225c51f124SMoriah Waterland 		 * transfer pkginfo & pkgmap first
13235c51f124SMoriah Waterland 		 */
1324*4656d474SGarrett D'Amore 		(void) snprintf(cmd, sizeof (cmd),
1325*4656d474SGarrett D'Amore 		    "%s -pudm %s", CPIOPROC, dstdir);
13265c51f124SMoriah Waterland 		if ((pp = epopen(cmd, "w")) == NULL) {
13275c51f124SMoriah Waterland 			rpterr();
13285c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
13295c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_POPEN), cmd, errno);
13305c51f124SMoriah Waterland 			return (1);
13315c51f124SMoriah Waterland 		}
13325c51f124SMoriah Waterland 		(void) fprintf(pp, "%s\n%s\n", PKGINFO, PKGMAP);
13335c51f124SMoriah Waterland 
1334*4656d474SGarrett D'Amore 		(void) sighold(SIGINT);
1335*4656d474SGarrett D'Amore 		(void) sighold(SIGHUP);
13365c51f124SMoriah Waterland 		r = epclose(pp);
1337*4656d474SGarrett D'Amore 		(void) sigrelse(SIGINT);
1338*4656d474SGarrett D'Amore 		(void) sigrelse(SIGHUP);
13395c51f124SMoriah Waterland 
13405c51f124SMoriah Waterland 		if (r != 0) {
13415c51f124SMoriah Waterland 			rpterr();
13425c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
13435c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_PCLOSE), cmd, errno);
13445c51f124SMoriah Waterland 			return (1);
13455c51f124SMoriah Waterland 		}
13465c51f124SMoriah Waterland 
13475c51f124SMoriah Waterland 		if (options & PT_INFO_ONLY)
13485c51f124SMoriah Waterland 			return (0); /* don't transfer objects */
13495c51f124SMoriah Waterland 
13505c51f124SMoriah Waterland 		if (chdir(dstdir)) {
13515c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
13525c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_CHDIR), dstdir);
13535c51f124SMoriah Waterland 			return (1);
13545c51f124SMoriah Waterland 		}
13555c51f124SMoriah Waterland 
13565c51f124SMoriah Waterland 		/*
13575c51f124SMoriah Waterland 		 * for each part of the package, use cpio() to
13585c51f124SMoriah Waterland 		 * unpack the archive into the destination directory
13595c51f124SMoriah Waterland 		 */
13605c51f124SMoriah Waterland 		nparts = ds_findpkg(srcdev.cdevice, srcinst);
13615c51f124SMoriah Waterland 		if (nparts < 0) {
13625c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
13635c51f124SMoriah Waterland 			return (1);
13645c51f124SMoriah Waterland 		}
13655c51f124SMoriah Waterland 		for (part = 1; part <= nparts; /* void */) {
13665c51f124SMoriah Waterland 			if (ds_getpkg(srcdev.cdevice, part, dstdir)) {
13675c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_TRANSFER));
13685c51f124SMoriah Waterland 				return (1);
13695c51f124SMoriah Waterland 			}
13705c51f124SMoriah Waterland 			part++;
13715c51f124SMoriah Waterland 			if (dstdev.mount) {
13725c51f124SMoriah Waterland 				(void) chdir("/");
13735c51f124SMoriah Waterland 				if (pkgumount(&dstdev))
13745c51f124SMoriah Waterland 					return (1);
13755c51f124SMoriah Waterland 				if (part <= nparts) {
13765c51f124SMoriah Waterland 					if (n = pkgmount(&dstdev, NULL, part+1,
13775c51f124SMoriah Waterland 					    nparts, 1))
13785c51f124SMoriah Waterland 						return (n);
13795c51f124SMoriah Waterland 					if (ckoverwrite(dst, dstinst, options))
13805c51f124SMoriah Waterland 						return (1);
13815c51f124SMoriah Waterland 					if (isdir(dstdir) &&
13825c51f124SMoriah Waterland 					    mkdir(dstdir, 0755)) {
13835c51f124SMoriah Waterland 						progerr(
13845c51f124SMoriah Waterland 						    pkg_gt(ERR_TRANSFER));
13855c51f124SMoriah Waterland 						logerr(pkg_gt(MSG_MKDIR),
13865c51f124SMoriah Waterland 						    dstdir);
13875c51f124SMoriah Waterland 						return (1);
13885c51f124SMoriah Waterland 					}
13895c51f124SMoriah Waterland 					/*
13905c51f124SMoriah Waterland 					 * since volume is removable, each part
13915c51f124SMoriah Waterland 					 * must contain a duplicate of the
13925c51f124SMoriah Waterland 					 * pkginfo file to properly identify the
13935c51f124SMoriah Waterland 					 * volume
13945c51f124SMoriah Waterland 					 */
13955c51f124SMoriah Waterland 					if (chdir(srcdir)) {
13965c51f124SMoriah Waterland 						progerr(
13975c51f124SMoriah Waterland 						    pkg_gt(ERR_TRANSFER));
13985c51f124SMoriah Waterland 						logerr(pkg_gt(MSG_CHDIR),
13995c51f124SMoriah Waterland 						    srcdir);
14005c51f124SMoriah Waterland 						return (1);
14015c51f124SMoriah Waterland 					}
14025c51f124SMoriah Waterland 					if ((pp = epopen(cmd, "w")) == NULL) {
14035c51f124SMoriah Waterland 						rpterr();
14045c51f124SMoriah Waterland 						progerr(
14055c51f124SMoriah Waterland 						    pkg_gt(ERR_TRANSFER));
14065c51f124SMoriah Waterland 						logerr(pkg_gt(MSG_POPEN),
14075c51f124SMoriah Waterland 						    cmd, errno);
14085c51f124SMoriah Waterland 						return (1);
14095c51f124SMoriah Waterland 					}
14105c51f124SMoriah Waterland 					(void) fprintf(pp, "pkginfo");
14115c51f124SMoriah Waterland 
1412*4656d474SGarrett D'Amore 					(void) sighold(SIGINT);
1413*4656d474SGarrett D'Amore 					(void) sighold(SIGHUP);
14145c51f124SMoriah Waterland 					r = epclose(pp);
1415*4656d474SGarrett D'Amore 					(void) sigrelse(SIGINT);
1416*4656d474SGarrett D'Amore 					(void) sigrelse(SIGHUP);
14175c51f124SMoriah Waterland 
14185c51f124SMoriah Waterland 					if (r != 0) {
14195c51f124SMoriah Waterland 						rpterr();
14205c51f124SMoriah Waterland 						progerr(
14215c51f124SMoriah Waterland 						    pkg_gt(ERR_TRANSFER));
14225c51f124SMoriah Waterland 						logerr(pkg_gt(MSG_PCLOSE),
14235c51f124SMoriah Waterland 						    cmd, errno);
14245c51f124SMoriah Waterland 						return (1);
14255c51f124SMoriah Waterland 					}
14265c51f124SMoriah Waterland 					if (chdir(dstdir)) {
14275c51f124SMoriah Waterland 						progerr(
14285c51f124SMoriah Waterland 						    pkg_gt(ERR_TRANSFER));
14295c51f124SMoriah Waterland 						logerr(pkg_gt(MSG_CHDIR),
14305c51f124SMoriah Waterland 						    dstdir);
14315c51f124SMoriah Waterland 						return (1);
14325c51f124SMoriah Waterland 					}
14335c51f124SMoriah Waterland 				}
14345c51f124SMoriah Waterland 			}
14355c51f124SMoriah Waterland 		}
14365c51f124SMoriah Waterland 		return (0);
14375c51f124SMoriah Waterland 	}
14385c51f124SMoriah Waterland 
14395c51f124SMoriah Waterland 	if ((fp = fopen(PKGMAP, "r")) == NULL) {
14405c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
14415c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_NOPKGMAP), srcinst);
14425c51f124SMoriah Waterland 		return (1);
14435c51f124SMoriah Waterland 	}
14445c51f124SMoriah Waterland 
14455c51f124SMoriah Waterland 	nparts = 1;
14465c51f124SMoriah Waterland 	if (!rd_map_size(fp, &nparts, &maxpartsize, &compressedsize))
14475c51f124SMoriah Waterland 		return (1);
14485c51f124SMoriah Waterland 	else
14495c51f124SMoriah Waterland 		(void) fclose(fp);
14505c51f124SMoriah Waterland 
14515c51f124SMoriah Waterland 	if (srcdev.mount) {
14525c51f124SMoriah Waterland 		if (ckvolseq(srcdir, 1, nparts)) {
14535c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
14545c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_SEQUENCE));
14555c51f124SMoriah Waterland 			return (1);
14565c51f124SMoriah Waterland 		}
14575c51f124SMoriah Waterland 	}
14585c51f124SMoriah Waterland 
14595c51f124SMoriah Waterland 	/* write each part of this package */
14605c51f124SMoriah Waterland 	if (options & PT_ODTSTREAM) {
14615c51f124SMoriah Waterland 		char line[128];
14625c51f124SMoriah Waterland 		(void) mgets(line, 128);
14635c51f124SMoriah Waterland 		curpartcnt = -1;
1464*4656d474SGarrett D'Amore 		/* LINTED E_SEC_SCANF_UNBOUNDED_COPY */
1465*4656d474SGarrett D'Amore 		if (sscanf(line, "%s %d %d %[ 0-9]", pkgname, &nparts,
14665c51f124SMoriah Waterland 		    &maxpartsize, volnos) == 4) {
1467*4656d474SGarrett D'Amore 			(void) sscanf(volnos,
1468*4656d474SGarrett D'Amore 			    "%d %[ 0-9]", &curpartcnt, tmpvol);
1469*4656d474SGarrett D'Amore 			(void) strlcpy(volnos, tmpvol, sizeof (volnos));
14705c51f124SMoriah Waterland 		}
14715c51f124SMoriah Waterland 	}
14725c51f124SMoriah Waterland 
14735c51f124SMoriah Waterland 	for (part = 1; part <= nparts; /* void */) {
14745c51f124SMoriah Waterland 		if (curpartcnt == 0 && (options & PT_ODTSTREAM)) {
14755c51f124SMoriah Waterland 			char prompt[128];
14765c51f124SMoriah Waterland 			int index;
14775c51f124SMoriah Waterland 			ds_volno++;
14785c51f124SMoriah Waterland 			(void) ds_close(0);
14795c51f124SMoriah Waterland 			(void) sprintf(prompt,
14805c51f124SMoriah Waterland 			    pkg_gt("Insert %%v %d of %d into %%p"),
14815c51f124SMoriah Waterland 			    ds_volno, ds_volcnt);
14825c51f124SMoriah Waterland 			if (n = getvol(ods_name, NULL, DM_FORMAT, prompt))
14835c51f124SMoriah Waterland 				return (n);
14845c51f124SMoriah Waterland 			if ((ds_fd = open(dstdev.cdevice, O_WRONLY)) < 0) {
14855c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_TRANSFER));
14865c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_OPEN), dstdev.cdevice,
14875c51f124SMoriah Waterland 				    errno);
14885c51f124SMoriah Waterland 				return (1);
14895c51f124SMoriah Waterland 			}
14905c51f124SMoriah Waterland 			if (ds_ginit(dstdev.cdevice) < 0) {
14915c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_TRANSFER));
14925c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_OPEN), dstdev.cdevice,
14935c51f124SMoriah Waterland 				    errno);
14945c51f124SMoriah Waterland 				(void) ds_close(0);
14955c51f124SMoriah Waterland 				return (1);
14965c51f124SMoriah Waterland 			}
14975c51f124SMoriah Waterland 
14985c51f124SMoriah Waterland 			(void) sscanf(volnos, "%d %[ 0-9]", &index, tmpvol);
1499*4656d474SGarrett D'Amore 			(void) strlcpy(volnos, tmpvol, sizeof (volnos));
15005c51f124SMoriah Waterland 			curpartcnt += index;
15015c51f124SMoriah Waterland 		}
15025c51f124SMoriah Waterland 
15035c51f124SMoriah Waterland 		if (options & PT_INFO_ONLY)
15045c51f124SMoriah Waterland 			nparts = 0;
15055c51f124SMoriah Waterland 
15065c51f124SMoriah Waterland 		if (part == 1) {
1507*4656d474SGarrett D'Amore 			(void) snprintf(cmd, sizeof (cmd),
1508*4656d474SGarrett D'Amore 			    "find %s %s", PKGINFO, PKGMAP);
15095c51f124SMoriah Waterland 			if (nparts && (isdir(INSTALL) == 0)) {
1510*4656d474SGarrett D'Amore 				(void) strlcat(cmd, " ", sizeof (cmd));
1511*4656d474SGarrett D'Amore 				(void) strlcat(cmd, INSTALL, sizeof (cmd));
15125c51f124SMoriah Waterland 			}
15135c51f124SMoriah Waterland 		} else
1514*4656d474SGarrett D'Amore 			(void) snprintf(cmd, sizeof (cmd), "find %s", PKGINFO);
15155c51f124SMoriah Waterland 
15165c51f124SMoriah Waterland 		if (nparts > 1) {
1517*4656d474SGarrett D'Amore 			(void) snprintf(temp, sizeof (temp),
1518*4656d474SGarrett D'Amore 			    "%s.%d", RELOC, part);
15195c51f124SMoriah Waterland 			if (iscpio(temp, &iscomp) || isdir(temp) == 0) {
1520*4656d474SGarrett D'Amore 				(void) strlcat(cmd, " ", sizeof (cmd));
1521*4656d474SGarrett D'Amore 				(void) strlcat(cmd, temp, sizeof (cmd));
15225c51f124SMoriah Waterland 			}
1523*4656d474SGarrett D'Amore 			(void) snprintf(temp, sizeof (temp),
1524*4656d474SGarrett D'Amore 			    "%s.%d", ROOT, part);
15255c51f124SMoriah Waterland 			if (iscpio(temp, &iscomp) || isdir(temp) == 0) {
1526*4656d474SGarrett D'Amore 				(void) strlcat(cmd, " ", sizeof (cmd));
1527*4656d474SGarrett D'Amore 				(void) strlcat(cmd, temp, sizeof (cmd));
15285c51f124SMoriah Waterland 			}
1529*4656d474SGarrett D'Amore 			(void) snprintf(temp, sizeof (temp),
1530*4656d474SGarrett D'Amore 			    "%s.%d", ARCHIVE, part);
15315c51f124SMoriah Waterland 			if (isdir(temp) == 0) {
1532*4656d474SGarrett D'Amore 				(void) strlcat(cmd, " ", sizeof (cmd));
1533*4656d474SGarrett D'Amore 				(void) strlcat(cmd, temp, sizeof (cmd));
15345c51f124SMoriah Waterland 			}
15355c51f124SMoriah Waterland 		} else if (nparts) {
15365c51f124SMoriah Waterland 			for (i = 0; reloc_names[i] != NULL; i++) {
15375c51f124SMoriah Waterland 				if (iscpio(reloc_names[i], &iscomp) ||
15385c51f124SMoriah Waterland 				    isdir(reloc_names[i]) == 0) {
1539*4656d474SGarrett D'Amore 					(void) strlcat(cmd, " ", sizeof (cmd));
1540*4656d474SGarrett D'Amore 					(void) strlcat(cmd, reloc_names[i],
1541*4656d474SGarrett D'Amore 					    sizeof (cmd));
15425c51f124SMoriah Waterland 				}
15435c51f124SMoriah Waterland 			}
15445c51f124SMoriah Waterland 			for (i = 0; root_names[i] != NULL; i++) {
15455c51f124SMoriah Waterland 				if (iscpio(root_names[i], &iscomp) ||
15465c51f124SMoriah Waterland 				    isdir(root_names[i]) == 0) {
1547*4656d474SGarrett D'Amore 					(void) strlcat(cmd, " ", sizeof (cmd));
1548*4656d474SGarrett D'Amore 					(void) strlcat(cmd, root_names[i],
1549*4656d474SGarrett D'Amore 					    sizeof (cmd));
15505c51f124SMoriah Waterland 				}
15515c51f124SMoriah Waterland 			}
15525c51f124SMoriah Waterland 			if (isdir(ARCHIVE) == 0) {
1553*4656d474SGarrett D'Amore 				(void) strlcat(cmd, " ", sizeof (cmd));
1554*4656d474SGarrett D'Amore 				(void) strlcat(cmd, ARCHIVE, sizeof (cmd));
15555c51f124SMoriah Waterland 			}
15565c51f124SMoriah Waterland 		}
15575c51f124SMoriah Waterland 		if (options & PT_ODTSTREAM) {
1558*4656d474SGarrett D'Amore 			(void) snprintf(cmd + strlen(cmd),
1559*4656d474SGarrett D'Amore 			    sizeof (cmd) - strlen(cmd),
15605c51f124SMoriah Waterland 			    " -print | %s -ocD -C %d",
15615c51f124SMoriah Waterland 			    CPIOPROC, (int)BLK_SIZE);
15625c51f124SMoriah Waterland 		} else {
15635c51f124SMoriah Waterland 			if (statvfs64(dstdir, &svfsb) == -1) {
15645c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_TRANSFER));
15655c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_STATVFS), dstdir, errno);
15665c51f124SMoriah Waterland 				return (1);
15675c51f124SMoriah Waterland 			}
15685c51f124SMoriah Waterland 
15695c51f124SMoriah Waterland 			free_blocks = (((long)svfsb.f_frsize > 0) ?
15705c51f124SMoriah Waterland 			    howmany(svfsb.f_frsize, DEV_BSIZE) :
15715c51f124SMoriah Waterland 			    howmany(svfsb.f_bsize, DEV_BSIZE)) * svfsb.f_bavail;
15725c51f124SMoriah Waterland 
15735c51f124SMoriah Waterland 			if ((has_comp_size ? compressedsize : maxpartsize) >
15745c51f124SMoriah Waterland 			    free_blocks) {
15755c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_TRANSFER));
1576*4656d474SGarrett D'Amore 				logerr(pkg_gt(MSG_NOSPACE),
1577*4656d474SGarrett D'Amore 				    has_comp_size ?
1578*4656d474SGarrett D'Amore 				    (long)compressedsize : (long)maxpartsize,
1579*4656d474SGarrett D'Amore 				    free_blocks);
15805c51f124SMoriah Waterland 				return (1);
15815c51f124SMoriah Waterland 			}
1582*4656d474SGarrett D'Amore 			(void) snprintf(cmd + strlen(cmd),
1583*4656d474SGarrett D'Amore 			    sizeof (cmd) - strlen(cmd),
1584*4656d474SGarrett D'Amore 			    " -print | %s -pdum %s",
15855c51f124SMoriah Waterland 			    CPIOPROC, dstdir);
15865c51f124SMoriah Waterland 		}
15875c51f124SMoriah Waterland 
15885c51f124SMoriah Waterland 		n = esystem(cmd, -1, (options & PT_ODTSTREAM) ? ds_fd : -1);
15895c51f124SMoriah Waterland 		if (n) {
15905c51f124SMoriah Waterland 			rpterr();
15915c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
15925c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_CMDFAIL), cmd, n);
15935c51f124SMoriah Waterland 			return (1);
15945c51f124SMoriah Waterland 		}
15955c51f124SMoriah Waterland 
15965c51f124SMoriah Waterland 		part++;
15975c51f124SMoriah Waterland 		if (srcdev.mount && (nparts > 1)) {
15985c51f124SMoriah Waterland 			/* unmount current source volume */
15995c51f124SMoriah Waterland 			(void) chdir("/");
16005c51f124SMoriah Waterland 			if (pkgumount(&srcdev))
16015c51f124SMoriah Waterland 				return (1);
16025c51f124SMoriah Waterland 			/* loop until volume is mounted successfully */
16035c51f124SMoriah Waterland 			while (part <= nparts) {
16045c51f124SMoriah Waterland 				/* read only */
16055c51f124SMoriah Waterland 				n = pkgmount(&srcdev, NULL, part, nparts, 1);
16065c51f124SMoriah Waterland 				if (n)
16075c51f124SMoriah Waterland 					return (n);
16085c51f124SMoriah Waterland 				if (chdir(srcdir)) {
16095c51f124SMoriah Waterland 					progerr(pkg_gt(ERR_TRANSFER));
1610*4656d474SGarrett D'Amore 					logerr(pkg_gt(MSG_CORRUPT));
16115c51f124SMoriah Waterland 					(void) chdir("/");
1612*4656d474SGarrett D'Amore 					(void) pkgumount(&srcdev);
16135c51f124SMoriah Waterland 					continue;
16145c51f124SMoriah Waterland 				}
16155c51f124SMoriah Waterland 				if (ckvolseq(srcdir, part, nparts)) {
16165c51f124SMoriah Waterland 					(void) chdir("/");
1617*4656d474SGarrett D'Amore 					(void) pkgumount(&srcdev);
16185c51f124SMoriah Waterland 					continue;
16195c51f124SMoriah Waterland 				}
16205c51f124SMoriah Waterland 				break;
16215c51f124SMoriah Waterland 			}
16225c51f124SMoriah Waterland 		}
16235c51f124SMoriah Waterland 		if (!(options & PT_ODTSTREAM) && dstdev.mount) {
16245c51f124SMoriah Waterland 			/* unmount current volume */
16255c51f124SMoriah Waterland 			if (pkgumount(&dstdev))
16265c51f124SMoriah Waterland 				return (1);
16275c51f124SMoriah Waterland 			/* loop until next volume is mounted successfully */
16285c51f124SMoriah Waterland 			while (part <= nparts) {
16295c51f124SMoriah Waterland 				/* writable */
16305c51f124SMoriah Waterland 				n = pkgmount(&dstdev, NULL, part, nparts, 1);
16315c51f124SMoriah Waterland 				if (n)
16325c51f124SMoriah Waterland 					return (n);
16335c51f124SMoriah Waterland 				if (ckoverwrite(dst, dstinst, options))
16345c51f124SMoriah Waterland 					continue;
16355c51f124SMoriah Waterland 				if (isdir(dstdir) && mkdir(dstdir, 0755)) {
16365c51f124SMoriah Waterland 					progerr(pkg_gt(ERR_TRANSFER));
16375c51f124SMoriah Waterland 					logerr(pkg_gt(MSG_MKDIR), dstdir);
16385c51f124SMoriah Waterland 					continue;
16395c51f124SMoriah Waterland 				}
16405c51f124SMoriah Waterland 				break;
16415c51f124SMoriah Waterland 			}
16425c51f124SMoriah Waterland 		}
16435c51f124SMoriah Waterland 
16445c51f124SMoriah Waterland 		if ((options & PT_ODTSTREAM) && part <= nparts) {
16455c51f124SMoriah Waterland 			if (curpartcnt >= 0 && part > curpartcnt) {
16465c51f124SMoriah Waterland 				char prompt[128];
16475c51f124SMoriah Waterland 				int index;
16485c51f124SMoriah Waterland 				ds_volno++;
16495c51f124SMoriah Waterland 				if (ds_close(0))
16505c51f124SMoriah Waterland 					return (1);
16515c51f124SMoriah Waterland 				(void) sprintf(prompt,
16525c51f124SMoriah Waterland 				    pkg_gt("Insert %%v %d of %d into %%p"),
16535c51f124SMoriah Waterland 				    ds_volno, ds_volcnt);
16545c51f124SMoriah Waterland 				if (n = getvol(ods_name, NULL, DM_FORMAT,
16555c51f124SMoriah Waterland 				    prompt))
16565c51f124SMoriah Waterland 					return (n);
16575c51f124SMoriah Waterland 				if ((ds_fd = open(dstdev.cdevice, 1)) < 0) {
16585c51f124SMoriah Waterland 					progerr(pkg_gt(ERR_TRANSFER));
16595c51f124SMoriah Waterland 					logerr(pkg_gt(MSG_OPEN),
16605c51f124SMoriah Waterland 					    dstdev.cdevice, errno);
16615c51f124SMoriah Waterland 					return (1);
16625c51f124SMoriah Waterland 				}
16635c51f124SMoriah Waterland 				if (ds_ginit(dstdev.cdevice) < 0) {
16645c51f124SMoriah Waterland 					progerr(pkg_gt(ERR_TRANSFER));
16655c51f124SMoriah Waterland 					logerr(pkg_gt(MSG_OPEN),
16665c51f124SMoriah Waterland 					    dstdev.cdevice, errno);
16675c51f124SMoriah Waterland 					(void) ds_close(0);
16685c51f124SMoriah Waterland 					return (1);
16695c51f124SMoriah Waterland 				}
16705c51f124SMoriah Waterland 
16715c51f124SMoriah Waterland 				(void) sscanf(volnos, "%d %[ 0-9]", &index,
16725c51f124SMoriah Waterland 				    tmpvol);
1673*4656d474SGarrett D'Amore 				(void) strlcpy(volnos, tmpvol, sizeof (volnos));
16745c51f124SMoriah Waterland 				curpartcnt += index;
16755c51f124SMoriah Waterland 			}
16765c51f124SMoriah Waterland 		}
16775c51f124SMoriah Waterland 
16785c51f124SMoriah Waterland 	}
16795c51f124SMoriah Waterland 	return (0);
16805c51f124SMoriah Waterland }
16815c51f124SMoriah Waterland 
16825c51f124SMoriah Waterland /*
16835c51f124SMoriah Waterland  * Name:		pkgdump
16845c51f124SMoriah Waterland  * Description:	Dump a cpio archive of a package's contents to a BIO.
16855c51f124SMoriah Waterland  *
16865c51f124SMoriah Waterland  * Arguments:	srcinst - Name of package, which resides on the
16875c51f124SMoriah Waterland  *		device pointed to by the static 'srcdev' variable,
16885c51f124SMoriah Waterland  *		to dump.
16895c51f124SMoriah Waterland  *		bio - BIO object to dump data to
16905c51f124SMoriah Waterland  *
16915c51f124SMoriah Waterland  * Returns :   	0 - success
16925c51f124SMoriah Waterland  *		nonzero - failure.  errors printed to screen.
16935c51f124SMoriah Waterland  */
16945c51f124SMoriah Waterland static int
pkgdump(char * srcinst,BIO * bio)16955c51f124SMoriah Waterland pkgdump(char *srcinst, BIO *bio)
16965c51f124SMoriah Waterland {
16975c51f124SMoriah Waterland 	FILE	*fp;
16985c51f124SMoriah Waterland 	char	*src;
16995c51f124SMoriah Waterland 	char	temp[MAXPATHLEN],
17005c51f124SMoriah Waterland 		srcdir[MAXPATHLEN],
17015c51f124SMoriah Waterland 		cmd[CMDSIZE];
17025c51f124SMoriah Waterland 	int	i, n, part, nparts, maxpartsize, iscomp;
17035c51f124SMoriah Waterland 
17045c51f124SMoriah Waterland 	/*
17055c51f124SMoriah Waterland 	 * when this routine is entered, the entire package
17065c51f124SMoriah Waterland 	 * is already available at 'src' - including the
17075c51f124SMoriah Waterland 	 * pkginfo/pkgmap files and the objects as well.
17085c51f124SMoriah Waterland 	 */
17095c51f124SMoriah Waterland 
17105c51f124SMoriah Waterland 	/* read the pkgmap to get it's size information */
17115c51f124SMoriah Waterland 	if ((fp = fopen(PKGMAP, "r")) == NULL) {
17125c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
17135c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_NOPKGMAP), srcinst);
17145c51f124SMoriah Waterland 		return (1);
17155c51f124SMoriah Waterland 	}
17165c51f124SMoriah Waterland 
17175c51f124SMoriah Waterland 	nparts = 1;
17185c51f124SMoriah Waterland 	if (!rd_map_size(fp, &nparts, &maxpartsize, &compressedsize))
17195c51f124SMoriah Waterland 		return (1);
17205c51f124SMoriah Waterland 	else
17215c51f124SMoriah Waterland 		(void) fclose(fp);
17225c51f124SMoriah Waterland 
17235c51f124SMoriah Waterland 	/* make sure the first volume is available */
17245c51f124SMoriah Waterland 	if (srcdev.mount) {
17255c51f124SMoriah Waterland 		src = srcdev.dirname;
17265c51f124SMoriah Waterland 		(void) snprintf(srcdir, MAXPATHLEN, "%s/%s", src, srcinst);
17275c51f124SMoriah Waterland 		if (ckvolseq(srcdir, 1, nparts)) {
17285c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
17295c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_SEQUENCE));
17305c51f124SMoriah Waterland 			return (1);
17315c51f124SMoriah Waterland 		}
17325c51f124SMoriah Waterland 	}
17335c51f124SMoriah Waterland 
17345c51f124SMoriah Waterland 	/*
17355c51f124SMoriah Waterland 	 * form cpio command that will output the contents of all of
17365c51f124SMoriah Waterland 	 * this package's parts
17375c51f124SMoriah Waterland 	 */
17385c51f124SMoriah Waterland 	for (part = 1; part <= nparts; /* void */) {
17395c51f124SMoriah Waterland 
17405c51f124SMoriah Waterland 		if (part == 1) {
17415c51f124SMoriah Waterland 			(void) snprintf(cmd, CMDSIZE, "find %s %s",
17425c51f124SMoriah Waterland 			    PKGINFO, PKGMAP);
17435c51f124SMoriah Waterland 			if (nparts && (isdir(INSTALL) == 0)) {
1744*4656d474SGarrett D'Amore 				(void) strlcat(cmd, " ", sizeof (cmd));
1745*4656d474SGarrett D'Amore 				(void) strlcat(cmd, INSTALL, sizeof (cmd));
17465c51f124SMoriah Waterland 			}
17475c51f124SMoriah Waterland 		} else
17485c51f124SMoriah Waterland 			(void) snprintf(cmd, CMDSIZE, "find %s", PKGINFO);
17495c51f124SMoriah Waterland 
17505c51f124SMoriah Waterland 		if (nparts > 1) {
17515c51f124SMoriah Waterland 			(void) snprintf(temp, MAXPATHLEN, "%s.%d", RELOC, part);
17525c51f124SMoriah Waterland 			if (iscpio(temp, &iscomp) || isdir(temp) == 0) {
17535c51f124SMoriah Waterland 				(void) strlcat(cmd, " ", CMDSIZE);
17545c51f124SMoriah Waterland 				(void) strlcat(cmd, temp, CMDSIZE);
17555c51f124SMoriah Waterland 			}
17565c51f124SMoriah Waterland 			(void) snprintf(temp, MAXPATHLEN, "%s.%d", ROOT, part);
17575c51f124SMoriah Waterland 			if (iscpio(temp, &iscomp) || isdir(temp) == 0) {
17585c51f124SMoriah Waterland 				(void) strlcat(cmd, " ", CMDSIZE);
17595c51f124SMoriah Waterland 				(void) strlcat(cmd, temp, CMDSIZE);
17605c51f124SMoriah Waterland 			}
17615c51f124SMoriah Waterland 			(void) snprintf(temp, MAXPATHLEN, "%s.%d",
17625c51f124SMoriah Waterland 			    ARCHIVE, part);
17635c51f124SMoriah Waterland 			if (isdir(temp) == 0) {
17645c51f124SMoriah Waterland 				(void) strlcat(cmd, " ", CMDSIZE);
17655c51f124SMoriah Waterland 				(void) strlcat(cmd, temp, CMDSIZE);
17665c51f124SMoriah Waterland 			}
17675c51f124SMoriah Waterland 		} else if (nparts) {
17685c51f124SMoriah Waterland 			for (i = 0; reloc_names[i] != NULL; i++) {
17695c51f124SMoriah Waterland 				if (iscpio(reloc_names[i], &iscomp) ||
17705c51f124SMoriah Waterland 				    isdir(reloc_names[i]) == 0) {
17715c51f124SMoriah Waterland 					(void) strlcat(cmd, " ", CMDSIZE);
17725c51f124SMoriah Waterland 					(void) strlcat(cmd, reloc_names[i],
17735c51f124SMoriah Waterland 					    CMDSIZE);
17745c51f124SMoriah Waterland 				}
17755c51f124SMoriah Waterland 			}
17765c51f124SMoriah Waterland 			for (i = 0; root_names[i] != NULL; i++) {
17775c51f124SMoriah Waterland 				if (iscpio(root_names[i], &iscomp) ||
17785c51f124SMoriah Waterland 				    isdir(root_names[i]) == 0) {
17795c51f124SMoriah Waterland 					(void) strlcat(cmd, " ", CMDSIZE);
17805c51f124SMoriah Waterland 					(void) strlcat(cmd, root_names[i],
17815c51f124SMoriah Waterland 					    CMDSIZE);
17825c51f124SMoriah Waterland 				}
17835c51f124SMoriah Waterland 			}
17845c51f124SMoriah Waterland 			if (isdir(ARCHIVE) == 0) {
17855c51f124SMoriah Waterland 				(void) strlcat(cmd, " ", CMDSIZE);
17865c51f124SMoriah Waterland 				(void) strlcat(cmd, ARCHIVE, CMDSIZE);
17875c51f124SMoriah Waterland 			}
17885c51f124SMoriah Waterland 		}
17895c51f124SMoriah Waterland 
1790*4656d474SGarrett D'Amore 		(void) snprintf(cmd + strlen(cmd),
1791*4656d474SGarrett D'Amore 		    sizeof (cmd) - strlen(cmd),
17925c51f124SMoriah Waterland 		    " -print | %s -ocD -C %d",
17935c51f124SMoriah Waterland 		    CPIOPROC, (int)BLK_SIZE);
17945c51f124SMoriah Waterland 		/*
17955c51f124SMoriah Waterland 		 * execute the command, dumping all standard output
17965c51f124SMoriah Waterland 		 * to the BIO.
17975c51f124SMoriah Waterland 		 */
17985c51f124SMoriah Waterland 		n = BIO_dump_cmd(cmd, bio);
17995c51f124SMoriah Waterland 		if (n != 0) {
18005c51f124SMoriah Waterland 			rpterr();
18015c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
18025c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_CMDFAIL), cmd, n);
18035c51f124SMoriah Waterland 			return (1);
18045c51f124SMoriah Waterland 		}
18055c51f124SMoriah Waterland 
18065c51f124SMoriah Waterland 		part++;
18075c51f124SMoriah Waterland 	}
18085c51f124SMoriah Waterland 	return (0);
18095c51f124SMoriah Waterland }
18105c51f124SMoriah Waterland 
18115c51f124SMoriah Waterland static void
sigtrap(int signo)18125c51f124SMoriah Waterland sigtrap(int signo)
18135c51f124SMoriah Waterland {
1814*4656d474SGarrett D'Amore 	_NOTE(ARGUNUSED(signo));
18155c51f124SMoriah Waterland 	signal_received++;
18165c51f124SMoriah Waterland }
18175c51f124SMoriah Waterland 
18185c51f124SMoriah Waterland static void
cleanup(void)18195c51f124SMoriah Waterland cleanup(void)
18205c51f124SMoriah Waterland {
1821*4656d474SGarrett D'Amore 	(void) chdir("/");
18225c51f124SMoriah Waterland 	if (tmpdir) {
1823*4656d474SGarrett D'Amore 		(void) rrmdir(tmpdir);
18245c51f124SMoriah Waterland 		free(tmpdir);
18255c51f124SMoriah Waterland 		tmpdir = NULL;
18265c51f124SMoriah Waterland 	}
18275c51f124SMoriah Waterland 
18285c51f124SMoriah Waterland 	if (tmppath) {
18295c51f124SMoriah Waterland 		/* remove any previous tmppath stuff */
1830*4656d474SGarrett D'Amore 		(void) rrmdir(tmppath);
18315c51f124SMoriah Waterland 		free(tmppath);
18325c51f124SMoriah Waterland 		tmppath = NULL;
18335c51f124SMoriah Waterland 	}
18345c51f124SMoriah Waterland 
18355c51f124SMoriah Waterland 	if (tmpsymdir) {
18365c51f124SMoriah Waterland 		/* remove temp symbolic links made for signed pkg */
1837*4656d474SGarrett D'Amore 		(void) rrmdir(tmpsymdir);
18385c51f124SMoriah Waterland 		free(tmpsymdir);
18395c51f124SMoriah Waterland 		tmpsymdir = NULL;
18405c51f124SMoriah Waterland 	}
18415c51f124SMoriah Waterland 
18425c51f124SMoriah Waterland 	if (srcdev.mount && !ids_name)
1843*4656d474SGarrett D'Amore 		(void) pkgumount(&srcdev);
18445c51f124SMoriah Waterland 	if (dstdev.mount && !ods_name)
1845*4656d474SGarrett D'Amore 		(void) pkgumount(&dstdev);
18465c51f124SMoriah Waterland 	(void) ds_close(1);
18475c51f124SMoriah Waterland }
18485c51f124SMoriah Waterland 
18495c51f124SMoriah Waterland /*
18505c51f124SMoriah Waterland  * Name:		dump_hdr_and_pkgs
18515c51f124SMoriah Waterland  * Description:	Dumps datastream header and each package's contents
18525c51f124SMoriah Waterland  *		to the supplied BIO
18535c51f124SMoriah Waterland  *
18545c51f124SMoriah Waterland  * Arguments:	bio - BIO object to dump data to
18555c51f124SMoriah Waterland  *		hdr - Header for the datastream being dumped
18565c51f124SMoriah Waterland  *		pkglist - NULL-terminated list of packages
18575c51f124SMoriah Waterland  *		to dump.  The location of the packages are stored
18585c51f124SMoriah Waterland  *		in the static 'srcdev' variable.
18595c51f124SMoriah Waterland  *
18605c51f124SMoriah Waterland  * Returns :   	0 - success
18615c51f124SMoriah Waterland  *		nonzero - failure.  errors printed to screen.
18625c51f124SMoriah Waterland  */
18635c51f124SMoriah Waterland static int
dump_hdr_and_pkgs(BIO * bio,struct dm_buf * hdr,char ** pkglist)18645c51f124SMoriah Waterland dump_hdr_and_pkgs(BIO *bio, struct dm_buf *hdr, char **pkglist)
18655c51f124SMoriah Waterland {
18665c51f124SMoriah Waterland 	int	block_cnt, i;
18675c51f124SMoriah Waterland 	char	srcdir[MAXPATHLEN];
18685c51f124SMoriah Waterland 	char	cwd[MAXPATHLEN + 1];
18695c51f124SMoriah Waterland 	char	*src;
18705c51f124SMoriah Waterland 
18715c51f124SMoriah Waterland 	/* write out the header to the signature stream */
18725c51f124SMoriah Waterland 	for (block_cnt = 0; block_cnt < hdr->allocation;
18735c51f124SMoriah Waterland 		block_cnt += BLK_SIZE) {
1874*4656d474SGarrett D'Amore 		(void) BIO_write(bio, (hdr->text_buffer + block_cnt), BLK_SIZE);
18755c51f124SMoriah Waterland 	}
18765c51f124SMoriah Waterland 
18775c51f124SMoriah Waterland 	/* save current directory */
18785c51f124SMoriah Waterland 	if (getcwd(cwd, MAXPATHLEN + 1) == NULL) {
18795c51f124SMoriah Waterland 		logerr(pkg_gt(ERR_GETWD));
18805c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
18815c51f124SMoriah Waterland 		return (1);
18825c51f124SMoriah Waterland 	}
18835c51f124SMoriah Waterland 
18845c51f124SMoriah Waterland 	/* now write out each package's contents */
18855c51f124SMoriah Waterland 	for (i = 0; pkglist[i]; i++) {
18865c51f124SMoriah Waterland 		/*
18875c51f124SMoriah Waterland 		 * change to the source dir, so we can find and dump
18885c51f124SMoriah Waterland 		 * the package(s) bits into the BIO
18895c51f124SMoriah Waterland 		 *
18905c51f124SMoriah Waterland 		 */
18915c51f124SMoriah Waterland 		src = srcdev.dirname;
18925c51f124SMoriah Waterland 
18935c51f124SMoriah Waterland 		/* change to the package source directory */
18945c51f124SMoriah Waterland 		(void) snprintf(srcdir, MAXPATHLEN, "%s/%s", src, pkglist[i]);
18955c51f124SMoriah Waterland 		if (chdir(srcdir)) {
18965c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
18975c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_CHDIR), srcdir);
18985c51f124SMoriah Waterland 			return (1);
18995c51f124SMoriah Waterland 		}
19005c51f124SMoriah Waterland 
19015c51f124SMoriah Waterland 		if (pkgdump(pkglist[i], bio)) {
19025c51f124SMoriah Waterland 			pkglist[i] = NULL;
19035c51f124SMoriah Waterland 			return (1);
19045c51f124SMoriah Waterland 		}
19055c51f124SMoriah Waterland 	}
19065c51f124SMoriah Waterland 
19075c51f124SMoriah Waterland 	/* change back to directory we were in upon entering this routine */
19085c51f124SMoriah Waterland 	if (chdir(cwd)) {
19095c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
19105c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_CHDIR), cwd);
19115c51f124SMoriah Waterland 		return (1);
19125c51f124SMoriah Waterland 	}
19135c51f124SMoriah Waterland 
19145c51f124SMoriah Waterland 	return (0);
19155c51f124SMoriah Waterland }
19165c51f124SMoriah Waterland 
19175c51f124SMoriah Waterland /*
19185c51f124SMoriah Waterland  * Name:		BIO_dump_cmd
19195c51f124SMoriah Waterland  * Description:	Dump the output of invoking a command
19205c51f124SMoriah Waterland  *		to a BIO.
19215c51f124SMoriah Waterland  *
19225c51f124SMoriah Waterland  * Arguments:	cmd - Command to invoke
19235c51f124SMoriah Waterland  *		bio - BIO to dump output of command to
19245c51f124SMoriah Waterland  *		only 'stdout' is dumped.
19255c51f124SMoriah Waterland  * Returns :   	0 - success
19265c51f124SMoriah Waterland  *		nonzero - failure.  errors printed to screen.
19275c51f124SMoriah Waterland  */
19285c51f124SMoriah Waterland int
BIO_dump_cmd(char * cmd,BIO * bio)19295c51f124SMoriah Waterland BIO_dump_cmd(char *cmd, BIO *bio)
19305c51f124SMoriah Waterland {
19315c51f124SMoriah Waterland 	char	buf[BLK_SIZE];
19325c51f124SMoriah Waterland 	FILE	*fp;
19335c51f124SMoriah Waterland 	int	rc;
19345c51f124SMoriah Waterland 
19355c51f124SMoriah Waterland 	/* start up the process */
19365c51f124SMoriah Waterland 	if ((fp = epopen(cmd, "r")) == NULL) {
19375c51f124SMoriah Waterland 		rpterr();
19385c51f124SMoriah Waterland 		return (1);
19395c51f124SMoriah Waterland 	}
19405c51f124SMoriah Waterland 
19415c51f124SMoriah Waterland 	/* read output in chunks, transfer to BIO */
19425c51f124SMoriah Waterland 	while (fread(buf, BLK_SIZE, 1, fp) == 1) {
19435c51f124SMoriah Waterland 		if (BIO_write(bio, buf, BLK_SIZE) != BLK_SIZE) {
1944*4656d474SGarrett D'Amore 			(void) sighold(SIGINT);
1945*4656d474SGarrett D'Amore 			(void) sighold(SIGHUP);
19465c51f124SMoriah Waterland 			(void) epclose(fp);
1947*4656d474SGarrett D'Amore 			(void) sigrelse(SIGINT);
1948*4656d474SGarrett D'Amore 			(void) sigrelse(SIGHUP);
19495c51f124SMoriah Waterland 			rpterr();
19505c51f124SMoriah Waterland 			return (1);
19515c51f124SMoriah Waterland 		}
19525c51f124SMoriah Waterland 	}
19535c51f124SMoriah Waterland 
19545c51f124SMoriah Waterland 	/* done with stream, make sure no errors were encountered */
19555c51f124SMoriah Waterland 	if (ferror(fp)) {
19565c51f124SMoriah Waterland 		(void) epclose(fp);
19575c51f124SMoriah Waterland 		rpterr();
19585c51f124SMoriah Waterland 		return (1);
19595c51f124SMoriah Waterland 	}
19605c51f124SMoriah Waterland 
19615c51f124SMoriah Waterland 	/* done, close stream, report any errors */
1962*4656d474SGarrett D'Amore 	(void) sighold(SIGINT);
1963*4656d474SGarrett D'Amore 	(void) sighold(SIGHUP);
19645c51f124SMoriah Waterland 	rc = epclose(fp);
1965*4656d474SGarrett D'Amore 	(void) sigrelse(SIGINT);
1966*4656d474SGarrett D'Amore 	(void) sigrelse(SIGHUP);
19675c51f124SMoriah Waterland 	if (rc != 0) {
19685c51f124SMoriah Waterland 		rpterr();
19695c51f124SMoriah Waterland 		return (1);
19705c51f124SMoriah Waterland 	}
19715c51f124SMoriah Waterland 
19725c51f124SMoriah Waterland 	return (rc);
19735c51f124SMoriah Waterland }
1974