xref: /titanic_50/usr/src/lib/libpkg/common/pkgtrans.c (revision 5c51f1241dbbdf2656d0e10011981411ed0c9673)
1*5c51f124SMoriah Waterland /*
2*5c51f124SMoriah Waterland  * CDDL HEADER START
3*5c51f124SMoriah Waterland  *
4*5c51f124SMoriah Waterland  * The contents of this file are subject to the terms of the
5*5c51f124SMoriah Waterland  * Common Development and Distribution License (the "License").
6*5c51f124SMoriah Waterland  * You may not use this file except in compliance with the License.
7*5c51f124SMoriah Waterland  *
8*5c51f124SMoriah Waterland  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*5c51f124SMoriah Waterland  * or http://www.opensolaris.org/os/licensing.
10*5c51f124SMoriah Waterland  * See the License for the specific language governing permissions
11*5c51f124SMoriah Waterland  * and limitations under the License.
12*5c51f124SMoriah Waterland  *
13*5c51f124SMoriah Waterland  * When distributing Covered Code, include this CDDL HEADER in each
14*5c51f124SMoriah Waterland  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*5c51f124SMoriah Waterland  * If applicable, add the following below this CDDL HEADER, with the
16*5c51f124SMoriah Waterland  * fields enclosed by brackets "[]" replaced with your own identifying
17*5c51f124SMoriah Waterland  * information: Portions Copyright [yyyy] [name of copyright owner]
18*5c51f124SMoriah Waterland  *
19*5c51f124SMoriah Waterland  * CDDL HEADER END
20*5c51f124SMoriah Waterland  */
21*5c51f124SMoriah Waterland 
22*5c51f124SMoriah Waterland /*
23*5c51f124SMoriah Waterland  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24*5c51f124SMoriah Waterland  * Use is subject to license terms.
25*5c51f124SMoriah Waterland  */
26*5c51f124SMoriah Waterland 
27*5c51f124SMoriah Waterland /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28*5c51f124SMoriah Waterland /* All Rights Reserved */
29*5c51f124SMoriah Waterland 
30*5c51f124SMoriah Waterland 
31*5c51f124SMoriah Waterland 
32*5c51f124SMoriah Waterland #include <stdio.h>
33*5c51f124SMoriah Waterland #include <errno.h>
34*5c51f124SMoriah Waterland #include <stdarg.h>
35*5c51f124SMoriah Waterland #include <limits.h>
36*5c51f124SMoriah Waterland #include <stdlib.h>
37*5c51f124SMoriah Waterland #include <unistd.h>
38*5c51f124SMoriah Waterland #include <fcntl.h>
39*5c51f124SMoriah Waterland #include <ctype.h>
40*5c51f124SMoriah Waterland #include <string.h>
41*5c51f124SMoriah Waterland #include <sys/types.h>
42*5c51f124SMoriah Waterland #include <sys/param.h>
43*5c51f124SMoriah Waterland #include <sys/stat.h>
44*5c51f124SMoriah Waterland #include <sys/statvfs.h>
45*5c51f124SMoriah Waterland #include <sys/sysmacros.h>
46*5c51f124SMoriah Waterland #include <dirent.h>
47*5c51f124SMoriah Waterland #include <signal.h>
48*5c51f124SMoriah Waterland #include <devmgmt.h>
49*5c51f124SMoriah Waterland #include <openssl/pkcs12.h>
50*5c51f124SMoriah Waterland #include <openssl/x509.h>
51*5c51f124SMoriah Waterland #include <openssl/pkcs7.h>
52*5c51f124SMoriah Waterland #include <openssl/err.h>
53*5c51f124SMoriah Waterland #include <openssl/pem.h>
54*5c51f124SMoriah Waterland #include "pkginfo.h"
55*5c51f124SMoriah Waterland #include "pkgstrct.h"
56*5c51f124SMoriah Waterland #include "pkgtrans.h"
57*5c51f124SMoriah Waterland #include "pkgdev.h"
58*5c51f124SMoriah Waterland #include "pkglib.h"
59*5c51f124SMoriah Waterland #include "pkglibmsgs.h"
60*5c51f124SMoriah Waterland #include "keystore.h"
61*5c51f124SMoriah Waterland #include "pkglocale.h"
62*5c51f124SMoriah Waterland #include "pkgerr.h"
63*5c51f124SMoriah Waterland 
64*5c51f124SMoriah Waterland extern char	*pkgdir; 		/* pkgparam.c */
65*5c51f124SMoriah Waterland 
66*5c51f124SMoriah Waterland /* libadm.a */
67*5c51f124SMoriah Waterland extern char	*devattr(char *device, char *attribute);
68*5c51f124SMoriah Waterland extern char	*fpkginst(char *pkg, ...);
69*5c51f124SMoriah Waterland extern int	fpkginfo(struct pkginfo *info, char *pkginst);
70*5c51f124SMoriah Waterland extern int	getvol(char *device, char *label, int options, char *prompt);
71*5c51f124SMoriah Waterland extern int	_getvol(char *device, char *label, int options, char *prompt,
72*5c51f124SMoriah Waterland 			char *norewind);
73*5c51f124SMoriah Waterland 
74*5c51f124SMoriah Waterland /* dstream.c */
75*5c51f124SMoriah Waterland extern int	ds_ginit(char *device);
76*5c51f124SMoriah Waterland extern int	ds_close(int pkgendflg);
77*5c51f124SMoriah Waterland 
78*5c51f124SMoriah Waterland #define	CPIOPROC	"/usr/bin/cpio"
79*5c51f124SMoriah Waterland 
80*5c51f124SMoriah Waterland #define	CMDSIZE	512	/* command block size */
81*5c51f124SMoriah Waterland 
82*5c51f124SMoriah Waterland #define	BLK_SIZE	512		/* size of logical block */
83*5c51f124SMoriah Waterland 
84*5c51f124SMoriah Waterland #define	ENTRY_MAX	256 /* max size of entry for cpio cmd or header */
85*5c51f124SMoriah Waterland 
86*5c51f124SMoriah Waterland #define	PKGINFO	"pkginfo"
87*5c51f124SMoriah Waterland #define	PKGMAP	"pkgmap"
88*5c51f124SMoriah Waterland #define	MAP_STAT_SIZE	60	/* 1st line of pkgmap (3 numbers & a : */
89*5c51f124SMoriah Waterland 
90*5c51f124SMoriah Waterland #define	INSTALL	"install"
91*5c51f124SMoriah Waterland #define	RELOC	"reloc"
92*5c51f124SMoriah Waterland #define	ROOT	"root"
93*5c51f124SMoriah Waterland #define	ARCHIVE	"archive"
94*5c51f124SMoriah Waterland 
95*5c51f124SMoriah Waterland static struct	pkgdev srcdev, dstdev;
96*5c51f124SMoriah Waterland static char	*tmpdir;
97*5c51f124SMoriah Waterland static char	*tmppath;
98*5c51f124SMoriah Waterland static char	*tmpsymdir = NULL;
99*5c51f124SMoriah Waterland static char	dstinst[NON_ABI_NAMELNGTH];
100*5c51f124SMoriah Waterland static char 	*ids_name, *ods_name;
101*5c51f124SMoriah Waterland static int	ds_volcnt;
102*5c51f124SMoriah Waterland static int	ds_volno;
103*5c51f124SMoriah Waterland static int	compressedsize, has_comp_size;
104*5c51f124SMoriah Waterland 
105*5c51f124SMoriah Waterland static void	(*sigintHandler)();
106*5c51f124SMoriah Waterland static void	(*sighupHandler)();
107*5c51f124SMoriah Waterland static void	cleanup(void);
108*5c51f124SMoriah Waterland static void	sigtrap(int signo);
109*5c51f124SMoriah Waterland static int	rd_map_size(FILE *fp, int *npts, int *maxpsz, int *cmpsize);
110*5c51f124SMoriah Waterland 
111*5c51f124SMoriah Waterland static int	cat_and_count(struct dm_buf *, char *);
112*5c51f124SMoriah Waterland 
113*5c51f124SMoriah Waterland static int	ckoverwrite(char *dir, char *inst, int options);
114*5c51f124SMoriah Waterland static int	pkgxfer(char *srcinst, int options);
115*5c51f124SMoriah Waterland static int	wdsheader(struct dm_buf *, char *src, char *device,
116*5c51f124SMoriah Waterland     char **pkg, PKCS7 *);
117*5c51f124SMoriah Waterland static struct dm_buf	*genheader(char *, char *, char **);
118*5c51f124SMoriah Waterland 
119*5c51f124SMoriah Waterland static int	dump_hdr_and_pkgs(BIO *, struct dm_buf *, char **);
120*5c51f124SMoriah Waterland 
121*5c51f124SMoriah Waterland extern int	ds_fd;	/* open file descriptor for data stream WHERE? */
122*5c51f124SMoriah Waterland 
123*5c51f124SMoriah Waterland static char *root_names[] = {
124*5c51f124SMoriah Waterland 	"root",
125*5c51f124SMoriah Waterland 	"root.cpio",
126*5c51f124SMoriah Waterland 	"root.Z",
127*5c51f124SMoriah Waterland 	"root.cpio.Z",
128*5c51f124SMoriah Waterland 	0
129*5c51f124SMoriah Waterland };
130*5c51f124SMoriah Waterland 
131*5c51f124SMoriah Waterland static char *reloc_names[] = {
132*5c51f124SMoriah Waterland 	"reloc",
133*5c51f124SMoriah Waterland 	"reloc.cpio",
134*5c51f124SMoriah Waterland 	"reloc.Z",
135*5c51f124SMoriah Waterland 	"reloc.cpio.Z",
136*5c51f124SMoriah Waterland 	0
137*5c51f124SMoriah Waterland };
138*5c51f124SMoriah Waterland 
139*5c51f124SMoriah Waterland static int	signal_received = 0;
140*5c51f124SMoriah Waterland 
141*5c51f124SMoriah Waterland char	**xpkg; 	/* array of transferred packages */
142*5c51f124SMoriah Waterland int	nxpkg;
143*5c51f124SMoriah Waterland 
144*5c51f124SMoriah Waterland static	char *allpkg[] = {
145*5c51f124SMoriah Waterland 	"all",
146*5c51f124SMoriah Waterland 	NULL
147*5c51f124SMoriah Waterland };
148*5c51f124SMoriah Waterland 
149*5c51f124SMoriah Waterland static struct dm_buf hdrbuf;
150*5c51f124SMoriah Waterland static char *pinput, *nextpinput;
151*5c51f124SMoriah Waterland 
152*5c51f124SMoriah Waterland int
153*5c51f124SMoriah Waterland pkghead(char *device)
154*5c51f124SMoriah Waterland {
155*5c51f124SMoriah Waterland 	char	*pt;
156*5c51f124SMoriah Waterland 	int	n;
157*5c51f124SMoriah Waterland 
158*5c51f124SMoriah Waterland 	cleanup();
159*5c51f124SMoriah Waterland 
160*5c51f124SMoriah Waterland 
161*5c51f124SMoriah Waterland 	if (device == NULL)
162*5c51f124SMoriah Waterland 		return (0);
163*5c51f124SMoriah Waterland 	else if ((device[0] == '/') && !isdir(device)) {
164*5c51f124SMoriah Waterland 		pkgdir = device;
165*5c51f124SMoriah Waterland 		return (0);
166*5c51f124SMoriah Waterland 	} else if ((pt = devattr(device, "pathname")) != NULL && !isdir(pt)) {
167*5c51f124SMoriah Waterland 		pkgdir = pt;
168*5c51f124SMoriah Waterland 		return (0);
169*5c51f124SMoriah Waterland 	}
170*5c51f124SMoriah Waterland 
171*5c51f124SMoriah Waterland 	/* check for datastream */
172*5c51f124SMoriah Waterland 	if (n = pkgtrans(device, (char *)0, allpkg, PT_SILENT|PT_INFO_ONLY,
173*5c51f124SMoriah Waterland 	    NULL, NULL)) {
174*5c51f124SMoriah Waterland 		cleanup();
175*5c51f124SMoriah Waterland 		return (n);
176*5c51f124SMoriah Waterland 	}
177*5c51f124SMoriah Waterland 		/* pkgtrans has set pkgdir */
178*5c51f124SMoriah Waterland 	return (0);
179*5c51f124SMoriah Waterland }
180*5c51f124SMoriah Waterland 
181*5c51f124SMoriah Waterland static char *
182*5c51f124SMoriah Waterland mgets(char *buf, int size)
183*5c51f124SMoriah Waterland {
184*5c51f124SMoriah Waterland 	nextpinput = strchr(pinput, '\n');
185*5c51f124SMoriah Waterland 	if (nextpinput == NULL)
186*5c51f124SMoriah Waterland 		return (0);
187*5c51f124SMoriah Waterland 	*nextpinput = '\0';
188*5c51f124SMoriah Waterland 	if ((int)strlen(pinput) > size)
189*5c51f124SMoriah Waterland 		return (0);
190*5c51f124SMoriah Waterland 	(void) strncpy(buf, pinput, strlen(pinput));
191*5c51f124SMoriah Waterland 	buf[strlen(pinput)] = '\0';
192*5c51f124SMoriah Waterland 	pinput = nextpinput + 1;
193*5c51f124SMoriah Waterland 	return (buf);
194*5c51f124SMoriah Waterland }
195*5c51f124SMoriah Waterland /*
196*5c51f124SMoriah Waterland  * Here we construct the package size summaries for the headers. The
197*5c51f124SMoriah Waterland  * pkgmap file associated with fp must be rewound to the beginning of the
198*5c51f124SMoriah Waterland  * file. Note that we read three values from pkgmap first line in order
199*5c51f124SMoriah Waterland  * to get the *actual* size if this package is compressed.
200*5c51f124SMoriah Waterland  * This returns
201*5c51f124SMoriah Waterland  *	0 : error
202*5c51f124SMoriah Waterland  *	2 : not a compressed package
203*5c51f124SMoriah Waterland  *	3 : compressed package
204*5c51f124SMoriah Waterland  * and sets has_comp_size to indicate whether or not this is a compressed
205*5c51f124SMoriah Waterland  * package.
206*5c51f124SMoriah Waterland  */
207*5c51f124SMoriah Waterland static int
208*5c51f124SMoriah Waterland rd_map_size(FILE *fp, int *npts, int *maxpsz, int *cmpsize)
209*5c51f124SMoriah Waterland {
210*5c51f124SMoriah Waterland 	int n;
211*5c51f124SMoriah Waterland 	char line_buffer[MAP_STAT_SIZE];
212*5c51f124SMoriah Waterland 
213*5c51f124SMoriah Waterland 	/* First read the null terminated first line */
214*5c51f124SMoriah Waterland 	if (fgets(line_buffer, MAP_STAT_SIZE, fp) == NULL) {
215*5c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
216*5c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_NOSIZE));
217*5c51f124SMoriah Waterland 		(void) fclose(fp);
218*5c51f124SMoriah Waterland 		ecleanup();
219*5c51f124SMoriah Waterland 		return (0);
220*5c51f124SMoriah Waterland 	}
221*5c51f124SMoriah Waterland 
222*5c51f124SMoriah Waterland 	n = sscanf(line_buffer, ": %d %d %d", npts, maxpsz, cmpsize);
223*5c51f124SMoriah Waterland 
224*5c51f124SMoriah Waterland 	if (n == 3)		/* A valid compressed package entry */
225*5c51f124SMoriah Waterland 		has_comp_size = 1;
226*5c51f124SMoriah Waterland 	else if (n == 2)	/* A valid standard package entry */
227*5c51f124SMoriah Waterland 		has_comp_size = 0;
228*5c51f124SMoriah Waterland 	else {			/* invalid entry */
229*5c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
230*5c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_NOSIZE));
231*5c51f124SMoriah Waterland 		(void) fclose(fp);
232*5c51f124SMoriah Waterland 		ecleanup();
233*5c51f124SMoriah Waterland 		return (0);
234*5c51f124SMoriah Waterland 	}
235*5c51f124SMoriah Waterland 
236*5c51f124SMoriah Waterland 	return (n);
237*5c51f124SMoriah Waterland }
238*5c51f124SMoriah Waterland 
239*5c51f124SMoriah Waterland /* will return 0, 1, 3, or 99 */
240*5c51f124SMoriah Waterland static int
241*5c51f124SMoriah Waterland _pkgtrans(char *device1, char *device2, char **pkg, int options,
242*5c51f124SMoriah Waterland     keystore_handle_t keystore, char *keystore_alias)
243*5c51f124SMoriah Waterland {
244*5c51f124SMoriah Waterland 	BIO			*p7_bio = NULL;
245*5c51f124SMoriah Waterland 	EVP_PKEY		*privkey = NULL;
246*5c51f124SMoriah Waterland 	PKCS7			*sec_pkcs7 = NULL;
247*5c51f124SMoriah Waterland 	PKCS7_SIGNER_INFO	*sec_signerinfo = NULL;
248*5c51f124SMoriah Waterland 	PKG_ERR			*err;
249*5c51f124SMoriah Waterland 	STACK_OF(X509)		*cacerts = NULL;
250*5c51f124SMoriah Waterland 	STACK_OF(X509)		*clcerts = NULL;
251*5c51f124SMoriah Waterland 	STACK_OF(X509)		*sec_chain = NULL;
252*5c51f124SMoriah Waterland 	X509			*pubcert = NULL;
253*5c51f124SMoriah Waterland 	boolean_t		making_sig = B_FALSE;
254*5c51f124SMoriah Waterland 	char			*src, *dst;
255*5c51f124SMoriah Waterland 	int			errflg, i, n;
256*5c51f124SMoriah Waterland 	struct			dm_buf *hdr;
257*5c51f124SMoriah Waterland 
258*5c51f124SMoriah Waterland 	making_sig = (keystore != NULL) ? B_TRUE : B_FALSE;
259*5c51f124SMoriah Waterland 
260*5c51f124SMoriah Waterland 	if (making_sig) {
261*5c51f124SMoriah Waterland 
262*5c51f124SMoriah Waterland 		/* new error object */
263*5c51f124SMoriah Waterland 		err = pkgerr_new();
264*5c51f124SMoriah Waterland 
265*5c51f124SMoriah Waterland 		/* find matching cert and key */
266*5c51f124SMoriah Waterland 		if (find_key_cert_pair(err, keystore,
267*5c51f124SMoriah Waterland 		    keystore_alias, &privkey, &pubcert) != 0) {
268*5c51f124SMoriah Waterland 			pkgerr(err);
269*5c51f124SMoriah Waterland 			pkgerr_free(err);
270*5c51f124SMoriah Waterland 			return (1);
271*5c51f124SMoriah Waterland 		}
272*5c51f124SMoriah Waterland 
273*5c51f124SMoriah Waterland 		/* get CA certificates */
274*5c51f124SMoriah Waterland 		if (find_ca_certs(err, keystore, &cacerts) != 0) {
275*5c51f124SMoriah Waterland 			pkgerr(err);
276*5c51f124SMoriah Waterland 			pkgerr_free(err);
277*5c51f124SMoriah Waterland 			return (1);
278*5c51f124SMoriah Waterland 		}
279*5c51f124SMoriah Waterland 
280*5c51f124SMoriah Waterland 		/* get CL (aka "chain") certificates */
281*5c51f124SMoriah Waterland 		if (find_cl_certs(err, keystore, &clcerts) != 0) {
282*5c51f124SMoriah Waterland 			pkgerr(err);
283*5c51f124SMoriah Waterland 			pkgerr_free(err);
284*5c51f124SMoriah Waterland 			return (1);
285*5c51f124SMoriah Waterland 		}
286*5c51f124SMoriah Waterland 
287*5c51f124SMoriah Waterland 		/* initialize PKCS7 object to be filled in later */
288*5c51f124SMoriah Waterland 		sec_pkcs7 = PKCS7_new();
289*5c51f124SMoriah Waterland 		PKCS7_set_type(sec_pkcs7, NID_pkcs7_signed);
290*5c51f124SMoriah Waterland 		sec_signerinfo = PKCS7_add_signature(sec_pkcs7,
291*5c51f124SMoriah Waterland 		    pubcert, privkey, EVP_sha1());
292*5c51f124SMoriah Waterland 
293*5c51f124SMoriah Waterland 		if (sec_signerinfo == NULL) {
294*5c51f124SMoriah Waterland 			progerr(gettext(ERR_SEC), keystore_alias);
295*5c51f124SMoriah Waterland 			ERR_print_errors_fp(stderr);
296*5c51f124SMoriah Waterland 			pkgerr_free(err);
297*5c51f124SMoriah Waterland 			return (1);
298*5c51f124SMoriah Waterland 		}
299*5c51f124SMoriah Waterland 
300*5c51f124SMoriah Waterland 		/* add signer cert into signature */
301*5c51f124SMoriah Waterland 		PKCS7_add_certificate(sec_pkcs7, pubcert);
302*5c51f124SMoriah Waterland 
303*5c51f124SMoriah Waterland 		/* attempt to resolve cert chain starting at the signer cert */
304*5c51f124SMoriah Waterland 		if (get_cert_chain(err, pubcert, clcerts, cacerts,
305*5c51f124SMoriah Waterland 		    &sec_chain) != 0) {
306*5c51f124SMoriah Waterland 			pkgerr(err);
307*5c51f124SMoriah Waterland 			pkgerr_free(err);
308*5c51f124SMoriah Waterland 			return (1);
309*5c51f124SMoriah Waterland 		}
310*5c51f124SMoriah Waterland 
311*5c51f124SMoriah Waterland 		/*
312*5c51f124SMoriah Waterland 		 * add the verification chain of certs into the signature.
313*5c51f124SMoriah Waterland 		 * The first cert is the user cert, which we don't need,
314*5c51f124SMoriah Waterland 		 * since it's baked in already, so skip it
315*5c51f124SMoriah Waterland 		 */
316*5c51f124SMoriah Waterland 		for (i = 1; i < sk_X509_num(sec_chain); i++) {
317*5c51f124SMoriah Waterland 			PKCS7_add_certificate(sec_pkcs7,
318*5c51f124SMoriah Waterland 			    sk_X509_value(sec_chain, i));
319*5c51f124SMoriah Waterland 		}
320*5c51f124SMoriah Waterland 
321*5c51f124SMoriah Waterland 		pkgerr_free(err);
322*5c51f124SMoriah Waterland 		err = NULL;
323*5c51f124SMoriah Waterland 	}
324*5c51f124SMoriah Waterland 
325*5c51f124SMoriah Waterland 	if (signal_received > 0) {
326*5c51f124SMoriah Waterland 		return (1);
327*5c51f124SMoriah Waterland 	}
328*5c51f124SMoriah Waterland 
329*5c51f124SMoriah Waterland 	/* transfer spool to appropriate device */
330*5c51f124SMoriah Waterland 	if (devtype(device1, &srcdev)) {
331*5c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
332*5c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_BADDEV), device1);
333*5c51f124SMoriah Waterland 		return (1);
334*5c51f124SMoriah Waterland 	}
335*5c51f124SMoriah Waterland 	srcdev.rdonly++;
336*5c51f124SMoriah Waterland 
337*5c51f124SMoriah Waterland 	/* check for datastream */
338*5c51f124SMoriah Waterland 	ids_name = NULL;
339*5c51f124SMoriah Waterland 	if (srcdev.bdevice) {
340*5c51f124SMoriah Waterland 		if (n = _getvol(srcdev.bdevice, NULL, NULL,
341*5c51f124SMoriah Waterland 		    pkg_gt("Insert %v into %p."), srcdev.norewind)) {
342*5c51f124SMoriah Waterland 			cleanup();
343*5c51f124SMoriah Waterland 			if (n == 3)
344*5c51f124SMoriah Waterland 				return (3);
345*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
346*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_GETVOL));
347*5c51f124SMoriah Waterland 			return (1);
348*5c51f124SMoriah Waterland 		}
349*5c51f124SMoriah Waterland 		if (ds_readbuf(srcdev.cdevice))
350*5c51f124SMoriah Waterland 			ids_name = srcdev.cdevice;
351*5c51f124SMoriah Waterland 	}
352*5c51f124SMoriah Waterland 
353*5c51f124SMoriah Waterland 	if (srcdev.cdevice && !srcdev.bdevice)
354*5c51f124SMoriah Waterland 		ids_name = srcdev.cdevice;
355*5c51f124SMoriah Waterland 	else if (srcdev.pathname) {
356*5c51f124SMoriah Waterland 		ids_name = srcdev.pathname;
357*5c51f124SMoriah Waterland 		if (access(ids_name, 0) == -1) {
358*5c51f124SMoriah Waterland 			progerr(ERR_TRANSFER);
359*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_GETVOL));
360*5c51f124SMoriah Waterland 			return (1);
361*5c51f124SMoriah Waterland 		}
362*5c51f124SMoriah Waterland 	}
363*5c51f124SMoriah Waterland 
364*5c51f124SMoriah Waterland 	if (!ids_name && device2 == (char *)0) {
365*5c51f124SMoriah Waterland 		if (n = pkgmount(&srcdev, NULL, 1, 0, 0)) {
366*5c51f124SMoriah Waterland 			cleanup();
367*5c51f124SMoriah Waterland 			return (n);
368*5c51f124SMoriah Waterland 		}
369*5c51f124SMoriah Waterland 		if (srcdev.mount && *srcdev.mount)
370*5c51f124SMoriah Waterland 			pkgdir = strdup(srcdev.mount);
371*5c51f124SMoriah Waterland 		return (0);
372*5c51f124SMoriah Waterland 	}
373*5c51f124SMoriah Waterland 
374*5c51f124SMoriah Waterland 	if (ids_name && device2 == (char *)0) {
375*5c51f124SMoriah Waterland 		tmppath = tmpnam(NULL);
376*5c51f124SMoriah Waterland 		tmppath = strdup(tmppath);
377*5c51f124SMoriah Waterland 		if (tmppath == NULL) {
378*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
379*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_MEM));
380*5c51f124SMoriah Waterland 			return (1);
381*5c51f124SMoriah Waterland 		}
382*5c51f124SMoriah Waterland 		if (mkdir(tmppath, 0755)) {
383*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
384*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_MKDIR), tmppath);
385*5c51f124SMoriah Waterland 			return (1);
386*5c51f124SMoriah Waterland 		}
387*5c51f124SMoriah Waterland 		device2 = tmppath;
388*5c51f124SMoriah Waterland 	}
389*5c51f124SMoriah Waterland 
390*5c51f124SMoriah Waterland 	if (devtype(device2, &dstdev)) {
391*5c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
392*5c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_BADDEV), device2);
393*5c51f124SMoriah Waterland 		return (1);
394*5c51f124SMoriah Waterland 	}
395*5c51f124SMoriah Waterland 
396*5c51f124SMoriah Waterland 	if ((srcdev.cdevice && dstdev.cdevice) &&
397*5c51f124SMoriah Waterland 	    strcmp(srcdev.cdevice, dstdev.cdevice) == 0) {
398*5c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
399*5c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_SAMEDEV));
400*5c51f124SMoriah Waterland 		return (1);
401*5c51f124SMoriah Waterland 	}
402*5c51f124SMoriah Waterland 
403*5c51f124SMoriah Waterland 	ods_name = NULL;
404*5c51f124SMoriah Waterland 	if (dstdev.cdevice && !dstdev.bdevice || dstdev.pathname)
405*5c51f124SMoriah Waterland 		options |= PT_ODTSTREAM;
406*5c51f124SMoriah Waterland 
407*5c51f124SMoriah Waterland 	if (options & PT_ODTSTREAM) {
408*5c51f124SMoriah Waterland 		if (!((ods_name = dstdev.cdevice) != NULL ||
409*5c51f124SMoriah Waterland 		    (ods_name = dstdev.pathname) != NULL)) {
410*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
411*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_BADDEV), device2);
412*5c51f124SMoriah Waterland 			return (1);
413*5c51f124SMoriah Waterland 		}
414*5c51f124SMoriah Waterland 		if (ids_name) {
415*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
416*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_TWODSTREAM));
417*5c51f124SMoriah Waterland 			return (1);
418*5c51f124SMoriah Waterland 		}
419*5c51f124SMoriah Waterland 	} else {
420*5c51f124SMoriah Waterland 		/*
421*5c51f124SMoriah Waterland 		 * output device isn't a stream.  If we're making a signed
422*5c51f124SMoriah Waterland 		 * package, then fail, since we can't make signed,
423*5c51f124SMoriah Waterland 		 * non-stream pkgs
424*5c51f124SMoriah Waterland 		 */
425*5c51f124SMoriah Waterland 		if (making_sig) {
426*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
427*5c51f124SMoriah Waterland 			logerr(pkg_gt(ERR_CANTSIGN));
428*5c51f124SMoriah Waterland 			return (1);
429*5c51f124SMoriah Waterland 		}
430*5c51f124SMoriah Waterland 	}
431*5c51f124SMoriah Waterland 
432*5c51f124SMoriah Waterland 	if ((srcdev.dirname && dstdev.dirname) &&
433*5c51f124SMoriah Waterland 	    strcmp(srcdev.dirname, dstdev.dirname) == 0) {
434*5c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
435*5c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_SAMEDEV));
436*5c51f124SMoriah Waterland 		return (1);
437*5c51f124SMoriah Waterland 	}
438*5c51f124SMoriah Waterland 
439*5c51f124SMoriah Waterland 	if ((srcdev.pathname && dstdev.pathname) &&
440*5c51f124SMoriah Waterland 	    strcmp(srcdev.pathname, dstdev.pathname) == 0) {
441*5c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
442*5c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_SAMEDEV));
443*5c51f124SMoriah Waterland 		return (1);
444*5c51f124SMoriah Waterland 	}
445*5c51f124SMoriah Waterland 
446*5c51f124SMoriah Waterland 	if (signal_received > 0) {
447*5c51f124SMoriah Waterland 		return (1);
448*5c51f124SMoriah Waterland 	}
449*5c51f124SMoriah Waterland 
450*5c51f124SMoriah Waterland 	if (ids_name) {
451*5c51f124SMoriah Waterland 		if (srcdev.cdevice && !srcdev.bdevice &&
452*5c51f124SMoriah Waterland 		(n = _getvol(srcdev.cdevice, NULL, NULL, NULL,
453*5c51f124SMoriah Waterland 		    srcdev.norewind))) {
454*5c51f124SMoriah Waterland 			cleanup();
455*5c51f124SMoriah Waterland 			if (n == 3)
456*5c51f124SMoriah Waterland 				return (3);
457*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
458*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_GETVOL));
459*5c51f124SMoriah Waterland 			return (1);
460*5c51f124SMoriah Waterland 		}
461*5c51f124SMoriah Waterland 		if (srcdev.dirname = tmpnam(NULL))
462*5c51f124SMoriah Waterland 			tmpdir = srcdev.dirname = strdup(srcdev.dirname);
463*5c51f124SMoriah Waterland 
464*5c51f124SMoriah Waterland 		if ((srcdev.dirname == NULL) || mkdir(srcdev.dirname, 0755) ||
465*5c51f124SMoriah Waterland 		    chdir(srcdev.dirname)) {
466*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
467*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_NOTEMP), srcdev.dirname);
468*5c51f124SMoriah Waterland 			cleanup();
469*5c51f124SMoriah Waterland 			return (1);
470*5c51f124SMoriah Waterland 		}
471*5c51f124SMoriah Waterland 		if (ds_init(ids_name, pkg, srcdev.norewind)) {
472*5c51f124SMoriah Waterland 			cleanup();
473*5c51f124SMoriah Waterland 			return (1);
474*5c51f124SMoriah Waterland 		}
475*5c51f124SMoriah Waterland 	} else if (srcdev.mount) {
476*5c51f124SMoriah Waterland 		if (n = pkgmount(&srcdev, NULL, 1, 0, 0)) {
477*5c51f124SMoriah Waterland 			cleanup();
478*5c51f124SMoriah Waterland 			return (n);
479*5c51f124SMoriah Waterland 		}
480*5c51f124SMoriah Waterland 	}
481*5c51f124SMoriah Waterland 
482*5c51f124SMoriah Waterland 	src = srcdev.dirname;
483*5c51f124SMoriah Waterland 	dst = dstdev.dirname;
484*5c51f124SMoriah Waterland 
485*5c51f124SMoriah Waterland 	if (chdir(src)) {
486*5c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
487*5c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_CHDIR), src);
488*5c51f124SMoriah Waterland 		cleanup();
489*5c51f124SMoriah Waterland 		return (1);
490*5c51f124SMoriah Waterland 	}
491*5c51f124SMoriah Waterland 
492*5c51f124SMoriah Waterland 	if (signal_received > 0) {
493*5c51f124SMoriah Waterland 		return (1);
494*5c51f124SMoriah Waterland 	}
495*5c51f124SMoriah Waterland 
496*5c51f124SMoriah Waterland 	xpkg = pkg = gpkglist(src, pkg, NULL);
497*5c51f124SMoriah Waterland 	if (!pkg) {
498*5c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
499*5c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_NOPKGS), src);
500*5c51f124SMoriah Waterland 		cleanup();
501*5c51f124SMoriah Waterland 		return (1);
502*5c51f124SMoriah Waterland 	}
503*5c51f124SMoriah Waterland 
504*5c51f124SMoriah Waterland 	for (nxpkg = 0; pkg[nxpkg]; /* void */) {
505*5c51f124SMoriah Waterland 		nxpkg++; /* count */
506*5c51f124SMoriah Waterland 	}
507*5c51f124SMoriah Waterland 
508*5c51f124SMoriah Waterland 	if (ids_name) {
509*5c51f124SMoriah Waterland 		ds_order(pkg); /* order requests */
510*5c51f124SMoriah Waterland 	}
511*5c51f124SMoriah Waterland 
512*5c51f124SMoriah Waterland 	if (signal_received > 0) {
513*5c51f124SMoriah Waterland 		return (1);
514*5c51f124SMoriah Waterland 	}
515*5c51f124SMoriah Waterland 
516*5c51f124SMoriah Waterland 	if (options & PT_ODTSTREAM) {
517*5c51f124SMoriah Waterland 		char line[128];
518*5c51f124SMoriah Waterland 
519*5c51f124SMoriah Waterland 		if (!dstdev.pathname &&
520*5c51f124SMoriah Waterland 		    (n = _getvol(ods_name, NULL, DM_FORMAT, NULL,
521*5c51f124SMoriah Waterland 		    dstdev.norewind))) {
522*5c51f124SMoriah Waterland 			cleanup();
523*5c51f124SMoriah Waterland 			if (n == 3)
524*5c51f124SMoriah Waterland 				return (3);
525*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
526*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_GETVOL));
527*5c51f124SMoriah Waterland 			return (1);
528*5c51f124SMoriah Waterland 		}
529*5c51f124SMoriah Waterland 		if ((hdr = genheader(src, ods_name, pkg)) == NULL) {
530*5c51f124SMoriah Waterland 			cleanup();
531*5c51f124SMoriah Waterland 			return (1);
532*5c51f124SMoriah Waterland 		}
533*5c51f124SMoriah Waterland 		if (making_sig) {
534*5c51f124SMoriah Waterland 			/* start up signature data stream */
535*5c51f124SMoriah Waterland 			PKCS7_content_new(sec_pkcs7, NID_pkcs7_data);
536*5c51f124SMoriah Waterland 			PKCS7_set_detached(sec_pkcs7, 1);
537*5c51f124SMoriah Waterland 			p7_bio = PKCS7_dataInit(sec_pkcs7, NULL);
538*5c51f124SMoriah Waterland 
539*5c51f124SMoriah Waterland 			/*
540*5c51f124SMoriah Waterland 			 * Here we generate all the data that will go into
541*5c51f124SMoriah Waterland 			 * the package, and send it through the signature
542*5c51f124SMoriah Waterland 			 * generator, essentially calculating the signature
543*5c51f124SMoriah Waterland 			 * of the entire package so we can place it in the
544*5c51f124SMoriah Waterland 			 * header.  Otherwise we'd have to place it at the end
545*5c51f124SMoriah Waterland 			 * of the pkg, which would break the ABI
546*5c51f124SMoriah Waterland 			 */
547*5c51f124SMoriah Waterland 			if (!(options & PT_SILENT)) {
548*5c51f124SMoriah Waterland 				(void) fprintf(stderr, pkg_gt(MSG_SIGNING),
549*5c51f124SMoriah Waterland 				    get_subject_display_name(pubcert));
550*5c51f124SMoriah Waterland 			}
551*5c51f124SMoriah Waterland 			if (dump_hdr_and_pkgs(p7_bio, hdr, pkg) != 0) {
552*5c51f124SMoriah Waterland 			    progerr(gettext(ERR_NOGEN));
553*5c51f124SMoriah Waterland 			    logerr(pkg_gt(MSG_GETVOL));
554*5c51f124SMoriah Waterland 			    cleanup();
555*5c51f124SMoriah Waterland 			    return (1);
556*5c51f124SMoriah Waterland 
557*5c51f124SMoriah Waterland 			}
558*5c51f124SMoriah Waterland 
559*5c51f124SMoriah Waterland 			BIO_flush(p7_bio);
560*5c51f124SMoriah Waterland 
561*5c51f124SMoriah Waterland 			/*
562*5c51f124SMoriah Waterland 			 * now generate PKCS7 signature
563*5c51f124SMoriah Waterland 			 */
564*5c51f124SMoriah Waterland 			if (!PKCS7_dataFinal(sec_pkcs7, p7_bio)) {
565*5c51f124SMoriah Waterland 			    progerr(gettext(ERR_NOGEN));
566*5c51f124SMoriah Waterland 			    logerr(pkg_gt(MSG_GETVOL));
567*5c51f124SMoriah Waterland 			    cleanup();
568*5c51f124SMoriah Waterland 			    return (1);
569*5c51f124SMoriah Waterland 			}
570*5c51f124SMoriah Waterland 
571*5c51f124SMoriah Waterland 			BIO_free(p7_bio);
572*5c51f124SMoriah Waterland 		}
573*5c51f124SMoriah Waterland 
574*5c51f124SMoriah Waterland 		/* write out header to stream, which includes signature */
575*5c51f124SMoriah Waterland 		if (wdsheader(hdr, src, ods_name, pkg, sec_pkcs7)) {
576*5c51f124SMoriah Waterland 			cleanup();
577*5c51f124SMoriah Waterland 			return (1);
578*5c51f124SMoriah Waterland 		}
579*5c51f124SMoriah Waterland 
580*5c51f124SMoriah Waterland 		if (sec_pkcs7 != NULL) {
581*5c51f124SMoriah Waterland 			/* nuke in-memory signature for safety */
582*5c51f124SMoriah Waterland 			PKCS7_free(sec_pkcs7);
583*5c51f124SMoriah Waterland 			sec_pkcs7 = NULL;
584*5c51f124SMoriah Waterland 		}
585*5c51f124SMoriah Waterland 
586*5c51f124SMoriah Waterland 		ds_volno = 1; /* number of volumes in datastream */
587*5c51f124SMoriah Waterland 		pinput = hdrbuf.text_buffer;
588*5c51f124SMoriah Waterland 		/* skip past first line in header */
589*5c51f124SMoriah Waterland 		(void) mgets(line, 128);
590*5c51f124SMoriah Waterland 	}
591*5c51f124SMoriah Waterland 
592*5c51f124SMoriah Waterland 	if (signal_received > 0) {
593*5c51f124SMoriah Waterland 		return (1);
594*5c51f124SMoriah Waterland 	}
595*5c51f124SMoriah Waterland 
596*5c51f124SMoriah Waterland 	errflg = 0;
597*5c51f124SMoriah Waterland 
598*5c51f124SMoriah Waterland 	for (i = 0; pkg[i]; i++) {
599*5c51f124SMoriah Waterland 
600*5c51f124SMoriah Waterland 		if (signal_received > 0) {
601*5c51f124SMoriah Waterland 			return (1);
602*5c51f124SMoriah Waterland 		}
603*5c51f124SMoriah Waterland 
604*5c51f124SMoriah Waterland 		if (!(options & PT_ODTSTREAM) && dstdev.mount) {
605*5c51f124SMoriah Waterland 			if (n = pkgmount(&dstdev, NULL, 0, 0, 1)) {
606*5c51f124SMoriah Waterland 				cleanup();
607*5c51f124SMoriah Waterland 				return (n);
608*5c51f124SMoriah Waterland 			}
609*5c51f124SMoriah Waterland 		}
610*5c51f124SMoriah Waterland 		if (errflg = pkgxfer(pkg[i], options)) {
611*5c51f124SMoriah Waterland 			pkg[i] = NULL;
612*5c51f124SMoriah Waterland 			if ((options & PT_ODTSTREAM) || (errflg != 2))
613*5c51f124SMoriah Waterland 				break;
614*5c51f124SMoriah Waterland 		} else if (strcmp(dstinst, pkg[i]))
615*5c51f124SMoriah Waterland 			pkg[i] = strdup(dstinst);
616*5c51f124SMoriah Waterland 	}
617*5c51f124SMoriah Waterland 
618*5c51f124SMoriah Waterland 	if (!(options & PT_ODTSTREAM) && dst) {
619*5c51f124SMoriah Waterland 		pkgdir = strdup(dst);
620*5c51f124SMoriah Waterland 	}
621*5c51f124SMoriah Waterland 
622*5c51f124SMoriah Waterland 	/*
623*5c51f124SMoriah Waterland 	 * No cleanup of temporary directories created in this
624*5c51f124SMoriah Waterland 	 * function is done here. The calling function must do
625*5c51f124SMoriah Waterland 	 * the cleanup.
626*5c51f124SMoriah Waterland 	 */
627*5c51f124SMoriah Waterland 
628*5c51f124SMoriah Waterland 	return (signal_received > 0 ? 1 : errflg);
629*5c51f124SMoriah Waterland }
630*5c51f124SMoriah Waterland 
631*5c51f124SMoriah Waterland int
632*5c51f124SMoriah Waterland pkgtrans(char *device1, char *device2, char **pkg, int options,
633*5c51f124SMoriah Waterland     keystore_handle_t keystore, char *keystore_alias)
634*5c51f124SMoriah Waterland {
635*5c51f124SMoriah Waterland 	int			r;
636*5c51f124SMoriah Waterland 	struct sigaction	nact;
637*5c51f124SMoriah Waterland 	struct sigaction	oact;
638*5c51f124SMoriah Waterland 
639*5c51f124SMoriah Waterland 	/*
640*5c51f124SMoriah Waterland 	 * setup signal handlers for SIGINT and SIGHUP and release hold
641*5c51f124SMoriah Waterland 	 */
642*5c51f124SMoriah Waterland 
643*5c51f124SMoriah Waterland 	/* hold SIGINT/SIGHUP interrupts */
644*5c51f124SMoriah Waterland 
645*5c51f124SMoriah Waterland 	(void) sighold(SIGHUP);
646*5c51f124SMoriah Waterland 	(void) sighold(SIGINT);
647*5c51f124SMoriah Waterland 
648*5c51f124SMoriah Waterland 	/* hook SIGINT to sigtrap */
649*5c51f124SMoriah Waterland 
650*5c51f124SMoriah Waterland 	nact.sa_handler = sigtrap;
651*5c51f124SMoriah Waterland 	nact.sa_flags = SA_RESTART;
652*5c51f124SMoriah Waterland 	(void) sigemptyset(&nact.sa_mask);
653*5c51f124SMoriah Waterland 
654*5c51f124SMoriah Waterland 	if (sigaction(SIGINT, &nact, &oact) < 0) {
655*5c51f124SMoriah Waterland 		sigintHandler = SIG_DFL;
656*5c51f124SMoriah Waterland 	} else {
657*5c51f124SMoriah Waterland 		sigintHandler = oact.sa_handler;
658*5c51f124SMoriah Waterland 	}
659*5c51f124SMoriah Waterland 
660*5c51f124SMoriah Waterland 	/* hook SIGHUP to sigtrap */
661*5c51f124SMoriah Waterland 
662*5c51f124SMoriah Waterland 	nact.sa_handler = sigtrap;
663*5c51f124SMoriah Waterland 	nact.sa_flags = SA_RESTART;
664*5c51f124SMoriah Waterland 	(void) sigemptyset(&nact.sa_mask);
665*5c51f124SMoriah Waterland 
666*5c51f124SMoriah Waterland 	if (sigaction(SIGHUP, &nact, &oact) < 0) {
667*5c51f124SMoriah Waterland 		sighupHandler = SIG_DFL;
668*5c51f124SMoriah Waterland 	} else {
669*5c51f124SMoriah Waterland 		sighupHandler = oact.sa_handler;
670*5c51f124SMoriah Waterland 	}
671*5c51f124SMoriah Waterland 
672*5c51f124SMoriah Waterland 	/* reset signal received count */
673*5c51f124SMoriah Waterland 
674*5c51f124SMoriah Waterland 	signal_received = 0;
675*5c51f124SMoriah Waterland 
676*5c51f124SMoriah Waterland 	/* release hold on signals */
677*5c51f124SMoriah Waterland 
678*5c51f124SMoriah Waterland 	(void) sigrelse(SIGHUP);
679*5c51f124SMoriah Waterland 	(void) sigrelse(SIGINT);
680*5c51f124SMoriah Waterland 
681*5c51f124SMoriah Waterland 	/*
682*5c51f124SMoriah Waterland 	 * perform the package translation
683*5c51f124SMoriah Waterland 	 */
684*5c51f124SMoriah Waterland 
685*5c51f124SMoriah Waterland 	r = _pkgtrans(device1, device2, pkg, options, keystore, keystore_alias);
686*5c51f124SMoriah Waterland 
687*5c51f124SMoriah Waterland 	/*
688*5c51f124SMoriah Waterland 	 * reset signal handlers
689*5c51f124SMoriah Waterland 	 */
690*5c51f124SMoriah Waterland 
691*5c51f124SMoriah Waterland 	/* hold SIGINT/SIGHUP interrupts */
692*5c51f124SMoriah Waterland 
693*5c51f124SMoriah Waterland 	(void) sighold(SIGHUP);
694*5c51f124SMoriah Waterland 	(void) sighold(SIGINT);
695*5c51f124SMoriah Waterland 
696*5c51f124SMoriah Waterland 	/* reset SIGINT */
697*5c51f124SMoriah Waterland 
698*5c51f124SMoriah Waterland 	nact.sa_handler = sigintHandler;
699*5c51f124SMoriah Waterland 	nact.sa_flags = SA_RESTART;
700*5c51f124SMoriah Waterland 	(void) sigemptyset(&nact.sa_mask);
701*5c51f124SMoriah Waterland 
702*5c51f124SMoriah Waterland 	(void) sigaction(SIGINT, &nact, (struct sigaction *)NULL);
703*5c51f124SMoriah Waterland 
704*5c51f124SMoriah Waterland 	/* reset SIGHUP */
705*5c51f124SMoriah Waterland 
706*5c51f124SMoriah Waterland 	nact.sa_handler = sighupHandler;
707*5c51f124SMoriah Waterland 	nact.sa_flags = SA_RESTART;
708*5c51f124SMoriah Waterland 	(void) sigemptyset(&nact.sa_mask);
709*5c51f124SMoriah Waterland 
710*5c51f124SMoriah Waterland 	(void) sigaction(SIGHUP, &nact, (struct sigaction *)NULL);
711*5c51f124SMoriah Waterland 
712*5c51f124SMoriah Waterland 	/* if signal received and pkgtrans returned error, call cleanup */
713*5c51f124SMoriah Waterland 
714*5c51f124SMoriah Waterland 	if (signal_received > 0) {
715*5c51f124SMoriah Waterland 		if (r != 0) {
716*5c51f124SMoriah Waterland 			cleanup();
717*5c51f124SMoriah Waterland 		}
718*5c51f124SMoriah Waterland 		(void) kill(getpid(), SIGINT);
719*5c51f124SMoriah Waterland 	}
720*5c51f124SMoriah Waterland 
721*5c51f124SMoriah Waterland 	/* release hold on signals */
722*5c51f124SMoriah Waterland 
723*5c51f124SMoriah Waterland 	(void) sigrelse(SIGHUP);
724*5c51f124SMoriah Waterland 	(void) sigrelse(SIGINT);
725*5c51f124SMoriah Waterland 
726*5c51f124SMoriah Waterland 	return (r);
727*5c51f124SMoriah Waterland }
728*5c51f124SMoriah Waterland 
729*5c51f124SMoriah Waterland /*
730*5c51f124SMoriah Waterland  * This function concatenates append to the text described in the buf_ctrl
731*5c51f124SMoriah Waterland  * structure. This code modifies data in this structure and handles all
732*5c51f124SMoriah Waterland  * allocation issues. It returns '0' if everything was successful and '1'
733*5c51f124SMoriah Waterland  * if not.
734*5c51f124SMoriah Waterland  */
735*5c51f124SMoriah Waterland static int
736*5c51f124SMoriah Waterland cat_and_count(struct dm_buf *buf_ctrl, char *append)
737*5c51f124SMoriah Waterland {
738*5c51f124SMoriah Waterland 
739*5c51f124SMoriah Waterland 	/* keep allocating until we have enough room to hold string */
740*5c51f124SMoriah Waterland 	while ((buf_ctrl->offset + (int)strlen(append))
741*5c51f124SMoriah Waterland 	    >= buf_ctrl->allocation) {
742*5c51f124SMoriah Waterland 		/* reallocate (and maybe move) text buffer */
743*5c51f124SMoriah Waterland 		if ((buf_ctrl->text_buffer =
744*5c51f124SMoriah Waterland 		    (char *)realloc(buf_ctrl->text_buffer,
745*5c51f124SMoriah Waterland 		    buf_ctrl->allocation + BLK_SIZE)) == NULL) {
746*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
747*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_MEM));
748*5c51f124SMoriah Waterland 			free(buf_ctrl->text_buffer);
749*5c51f124SMoriah Waterland 			return (1);
750*5c51f124SMoriah Waterland 		}
751*5c51f124SMoriah Waterland 
752*5c51f124SMoriah Waterland 		/* clear the new memory */
753*5c51f124SMoriah Waterland 		(void) memset(buf_ctrl->text_buffer +
754*5c51f124SMoriah Waterland 		    buf_ctrl->allocation, '\0', BLK_SIZE);
755*5c51f124SMoriah Waterland 
756*5c51f124SMoriah Waterland 		/* adjust total allocation */
757*5c51f124SMoriah Waterland 		buf_ctrl->allocation += BLK_SIZE;
758*5c51f124SMoriah Waterland 	}
759*5c51f124SMoriah Waterland 
760*5c51f124SMoriah Waterland 	/* append new string to end of buffer */
761*5c51f124SMoriah Waterland 	while (*append) {
762*5c51f124SMoriah Waterland 		*(buf_ctrl->text_buffer + buf_ctrl->offset) = *append++;
763*5c51f124SMoriah Waterland 		(buf_ctrl->offset)++;
764*5c51f124SMoriah Waterland 	}
765*5c51f124SMoriah Waterland 
766*5c51f124SMoriah Waterland 	return (0);
767*5c51f124SMoriah Waterland }
768*5c51f124SMoriah Waterland 
769*5c51f124SMoriah Waterland static struct dm_buf *
770*5c51f124SMoriah Waterland genheader(char *src, char *device, char **pkg)
771*5c51f124SMoriah Waterland {
772*5c51f124SMoriah Waterland 
773*5c51f124SMoriah Waterland 	FILE	*fp;
774*5c51f124SMoriah Waterland 	char	path[MAXPATHLEN], tmp_entry[ENTRY_MAX];
775*5c51f124SMoriah Waterland 	int	i, n, nparts, maxpsize;
776*5c51f124SMoriah Waterland 	int	partcnt, totsize;
777*5c51f124SMoriah Waterland 	struct stat statbuf;
778*5c51f124SMoriah Waterland 
779*5c51f124SMoriah Waterland 	if ((hdrbuf.text_buffer = (char *)malloc(BLK_SIZE)) == NULL) {
780*5c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
781*5c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_MEM));
782*5c51f124SMoriah Waterland 		return (NULL);
783*5c51f124SMoriah Waterland 	}
784*5c51f124SMoriah Waterland 
785*5c51f124SMoriah Waterland 	/* clear the new memory */
786*5c51f124SMoriah Waterland 	(void) memset(hdrbuf.text_buffer, '\0', BLK_SIZE);
787*5c51f124SMoriah Waterland 
788*5c51f124SMoriah Waterland 	/* set up the buffer control structure for the header */
789*5c51f124SMoriah Waterland 	hdrbuf.offset = 0;
790*5c51f124SMoriah Waterland 	hdrbuf.allocation = BLK_SIZE;
791*5c51f124SMoriah Waterland 
792*5c51f124SMoriah Waterland 	(void) cat_and_count(&hdrbuf, HDR_PREFIX);
793*5c51f124SMoriah Waterland 	(void) cat_and_count(&hdrbuf, "\n");
794*5c51f124SMoriah Waterland 
795*5c51f124SMoriah Waterland 	nparts = maxpsize = 0;
796*5c51f124SMoriah Waterland 
797*5c51f124SMoriah Waterland 	totsize = 0;
798*5c51f124SMoriah Waterland 	for (i = 0; pkg[i]; i++)  {
799*5c51f124SMoriah Waterland 		(void) snprintf(path, MAXPATHLEN, "%s/%s/%s",
800*5c51f124SMoriah Waterland 		    src, pkg[i], PKGINFO);
801*5c51f124SMoriah Waterland 		if (stat(path, &statbuf) < 0) {
802*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
803*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_BADPKGINFO));
804*5c51f124SMoriah Waterland 			ecleanup();
805*5c51f124SMoriah Waterland 			return (NULL);
806*5c51f124SMoriah Waterland 		}
807*5c51f124SMoriah Waterland 		totsize += statbuf.st_size/BLK_SIZE + 1;
808*5c51f124SMoriah Waterland 	}
809*5c51f124SMoriah Waterland 
810*5c51f124SMoriah Waterland 	/*
811*5c51f124SMoriah Waterland 	 * totsize contains number of blocks used by the pkginfo files
812*5c51f124SMoriah Waterland 	 */
813*5c51f124SMoriah Waterland 	totsize += i/4 + 1;
814*5c51f124SMoriah Waterland 	if (dstdev.capacity && totsize > dstdev.capacity) {
815*5c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
816*5c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_NOSPACE), totsize, dstdev.capacity);
817*5c51f124SMoriah Waterland 		ecleanup();
818*5c51f124SMoriah Waterland 		return (NULL);
819*5c51f124SMoriah Waterland 	}
820*5c51f124SMoriah Waterland 
821*5c51f124SMoriah Waterland 	ds_volcnt = 1;
822*5c51f124SMoriah Waterland 	for (i = 0; pkg[i]; i++) {
823*5c51f124SMoriah Waterland 		partcnt = 0;
824*5c51f124SMoriah Waterland 		(void) snprintf(path, MAXPATHLEN, "%s/%s/%s",
825*5c51f124SMoriah Waterland 		    src, pkg[i], PKGMAP);
826*5c51f124SMoriah Waterland 		if ((fp = fopen(path, "r")) == NULL) {
827*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
828*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_NOPKGMAP), pkg[i]);
829*5c51f124SMoriah Waterland 			ecleanup();
830*5c51f124SMoriah Waterland 			return (NULL);
831*5c51f124SMoriah Waterland 		}
832*5c51f124SMoriah Waterland 
833*5c51f124SMoriah Waterland 		/* Evaluate the first entry in pkgmap */
834*5c51f124SMoriah Waterland 		n = rd_map_size(fp, &nparts, &maxpsize, &compressedsize);
835*5c51f124SMoriah Waterland 
836*5c51f124SMoriah Waterland 		if (n == 3)	/* It's a compressed package */
837*5c51f124SMoriah Waterland 			/* The header needs the *real* size */
838*5c51f124SMoriah Waterland 			maxpsize = compressedsize;
839*5c51f124SMoriah Waterland 		else if (n == 0)	/* pkgmap is corrupt */
840*5c51f124SMoriah Waterland 			return (NULL);
841*5c51f124SMoriah Waterland 
842*5c51f124SMoriah Waterland 		if (dstdev.capacity && maxpsize > dstdev.capacity) {
843*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
844*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_NOSPACE));
845*5c51f124SMoriah Waterland 			(void) fclose(fp);
846*5c51f124SMoriah Waterland 			ecleanup();
847*5c51f124SMoriah Waterland 			return (NULL);
848*5c51f124SMoriah Waterland 		}
849*5c51f124SMoriah Waterland 
850*5c51f124SMoriah Waterland 		/* add pkg name, number of parts and the max part size */
851*5c51f124SMoriah Waterland 		if (snprintf(tmp_entry, ENTRY_MAX, "%s %d %d",
852*5c51f124SMoriah Waterland 				pkg[i], nparts, maxpsize) >= ENTRY_MAX) {
853*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
854*5c51f124SMoriah Waterland 			logerr(pkg_gt(ERR_MEM));
855*5c51f124SMoriah Waterland 			(void) fclose(fp);
856*5c51f124SMoriah Waterland 			ecleanup();
857*5c51f124SMoriah Waterland 			return (NULL);
858*5c51f124SMoriah Waterland 		}
859*5c51f124SMoriah Waterland 		if (cat_and_count(&hdrbuf, tmp_entry)) {
860*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
861*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_MEM));
862*5c51f124SMoriah Waterland 			(void) fclose(fp);
863*5c51f124SMoriah Waterland 			ecleanup();
864*5c51f124SMoriah Waterland 			return (NULL);
865*5c51f124SMoriah Waterland 		}
866*5c51f124SMoriah Waterland 
867*5c51f124SMoriah Waterland 		totsize += nparts * maxpsize;
868*5c51f124SMoriah Waterland 		if (dstdev.capacity && dstdev.capacity < totsize) {
869*5c51f124SMoriah Waterland 			int lastpartcnt = 0;
870*5c51f124SMoriah Waterland #if 0
871*5c51f124SMoriah Waterland 			if (i != 0) {
872*5c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_TRANSFER));
873*5c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_NOSPACE));
874*5c51f124SMoriah Waterland 				(void) fclose(fp);
875*5c51f124SMoriah Waterland 				ecleanup();
876*5c51f124SMoriah Waterland 				return (NULL);
877*5c51f124SMoriah Waterland 			}
878*5c51f124SMoriah Waterland #endif	/* 0 */
879*5c51f124SMoriah Waterland 
880*5c51f124SMoriah Waterland 			if (totsize)
881*5c51f124SMoriah Waterland 				totsize -= nparts * maxpsize;
882*5c51f124SMoriah Waterland 			while (partcnt < nparts) {
883*5c51f124SMoriah Waterland 				while (totsize <= dstdev.capacity &&
884*5c51f124SMoriah Waterland 				    partcnt <= nparts) {
885*5c51f124SMoriah Waterland 					totsize +=  maxpsize;
886*5c51f124SMoriah Waterland 					partcnt++;
887*5c51f124SMoriah Waterland 				}
888*5c51f124SMoriah Waterland 				/* partcnt == 0 means skip to next volume */
889*5c51f124SMoriah Waterland 				if (partcnt)
890*5c51f124SMoriah Waterland 					partcnt--;
891*5c51f124SMoriah Waterland 				(void) snprintf(tmp_entry, ENTRY_MAX,
892*5c51f124SMoriah Waterland 				    " %d", partcnt - lastpartcnt);
893*5c51f124SMoriah Waterland 				if (cat_and_count(&hdrbuf, tmp_entry)) {
894*5c51f124SMoriah Waterland 					progerr(pkg_gt(ERR_TRANSFER));
895*5c51f124SMoriah Waterland 					logerr(pkg_gt(MSG_MEM));
896*5c51f124SMoriah Waterland 					(void) fclose(fp);
897*5c51f124SMoriah Waterland 					ecleanup();
898*5c51f124SMoriah Waterland 					return (NULL);
899*5c51f124SMoriah Waterland 				}
900*5c51f124SMoriah Waterland 				ds_volcnt++;
901*5c51f124SMoriah Waterland 				totsize = 0;
902*5c51f124SMoriah Waterland 				lastpartcnt = partcnt;
903*5c51f124SMoriah Waterland 			}
904*5c51f124SMoriah Waterland 			/* first parts/volume number does not count */
905*5c51f124SMoriah Waterland 			ds_volcnt--;
906*5c51f124SMoriah Waterland 		}
907*5c51f124SMoriah Waterland 
908*5c51f124SMoriah Waterland 		if (cat_and_count(&hdrbuf, "\n")) {
909*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
910*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_MEM));
911*5c51f124SMoriah Waterland 			(void) fclose(fp);
912*5c51f124SMoriah Waterland 			ecleanup();
913*5c51f124SMoriah Waterland 			return (NULL);
914*5c51f124SMoriah Waterland 		}
915*5c51f124SMoriah Waterland 
916*5c51f124SMoriah Waterland 		(void) fclose(fp);
917*5c51f124SMoriah Waterland 	}
918*5c51f124SMoriah Waterland 
919*5c51f124SMoriah Waterland 	if (cat_and_count(&hdrbuf, HDR_SUFFIX) ||
920*5c51f124SMoriah Waterland 	    cat_and_count(&hdrbuf, "\n")) {
921*5c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
922*5c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_MEM));
923*5c51f124SMoriah Waterland 		(void) fclose(fp);
924*5c51f124SMoriah Waterland 		ecleanup();
925*5c51f124SMoriah Waterland 		return (NULL);
926*5c51f124SMoriah Waterland 	}
927*5c51f124SMoriah Waterland 	return (&hdrbuf);
928*5c51f124SMoriah Waterland }
929*5c51f124SMoriah Waterland 
930*5c51f124SMoriah Waterland static int
931*5c51f124SMoriah Waterland wdsheader(struct dm_buf *hdr, char *src, char *device, char **pkg, PKCS7 *sig)
932*5c51f124SMoriah Waterland {
933*5c51f124SMoriah Waterland 	FILE	*fp;
934*5c51f124SMoriah Waterland 	char	path[PATH_MAX], tmp_entry[ENTRY_MAX],
935*5c51f124SMoriah Waterland 	    tmp_file[L_tmpnam+1];
936*5c51f124SMoriah Waterland 	char	srcpath[PATH_MAX];
937*5c51f124SMoriah Waterland 	int	i, n;
938*5c51f124SMoriah Waterland 	int	list_fd;
939*5c51f124SMoriah Waterland 	int	block_cnt;
940*5c51f124SMoriah Waterland 	int 	len;
941*5c51f124SMoriah Waterland 	char	cwd[MAXPATHLEN + 1];
942*5c51f124SMoriah Waterland 	boolean_t	making_sig = B_FALSE;
943*5c51f124SMoriah Waterland 
944*5c51f124SMoriah Waterland 	making_sig = (sig != NULL) ? B_TRUE : B_FALSE;
945*5c51f124SMoriah Waterland 
946*5c51f124SMoriah Waterland 	(void) ds_close(0);
947*5c51f124SMoriah Waterland 	if (dstdev.pathname)
948*5c51f124SMoriah Waterland 		ds_fd = creat(device, 0644);
949*5c51f124SMoriah Waterland 	else
950*5c51f124SMoriah Waterland 		ds_fd = open(device, 1);
951*5c51f124SMoriah Waterland 
952*5c51f124SMoriah Waterland 	if (ds_fd < 0) {
953*5c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
954*5c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_OPEN), device, errno);
955*5c51f124SMoriah Waterland 		return (1);
956*5c51f124SMoriah Waterland 	}
957*5c51f124SMoriah Waterland 
958*5c51f124SMoriah Waterland 	if (ds_ginit(device) < 0) {
959*5c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
960*5c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_OPEN), device, errno);
961*5c51f124SMoriah Waterland 		(void) ds_close(0);
962*5c51f124SMoriah Waterland 		return (1);
963*5c51f124SMoriah Waterland 	}
964*5c51f124SMoriah Waterland 
965*5c51f124SMoriah Waterland 	/*
966*5c51f124SMoriah Waterland 	 * The loop below assures compatibility with tapes that don't
967*5c51f124SMoriah Waterland 	 * have a block size (e.g.: Exabyte) by forcing EOR at the end
968*5c51f124SMoriah Waterland 	 * of each 512 bytes.
969*5c51f124SMoriah Waterland 	 */
970*5c51f124SMoriah Waterland 	for (block_cnt = 0; block_cnt < hdr->allocation;
971*5c51f124SMoriah Waterland 		block_cnt += BLK_SIZE) {
972*5c51f124SMoriah Waterland 		write(ds_fd, (hdr->text_buffer + block_cnt), BLK_SIZE);
973*5c51f124SMoriah Waterland 	}
974*5c51f124SMoriah Waterland 
975*5c51f124SMoriah Waterland 	/*
976*5c51f124SMoriah Waterland 	 * write the first cpio() archive to the datastream
977*5c51f124SMoriah Waterland 	 * which should contain the pkginfo & pkgmap files
978*5c51f124SMoriah Waterland 	 * for all packages
979*5c51f124SMoriah Waterland 	 */
980*5c51f124SMoriah Waterland 	(void) tmpnam(tmp_file);	/* temporary file name */
981*5c51f124SMoriah Waterland 	if ((list_fd = open(tmp_file, O_RDWR | O_CREAT)) == -1) {
982*5c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
983*5c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_NOTMPFIL));
984*5c51f124SMoriah Waterland 		return (1);
985*5c51f124SMoriah Waterland 	}
986*5c51f124SMoriah Waterland 
987*5c51f124SMoriah Waterland 	/*
988*5c51f124SMoriah Waterland 	 * Create a cpio-compatible list of the requisite files in
989*5c51f124SMoriah Waterland 	 * the temporary file.
990*5c51f124SMoriah Waterland 	 */
991*5c51f124SMoriah Waterland 	if (!making_sig) {
992*5c51f124SMoriah Waterland 		for (i = 0; pkg[i]; i++) {
993*5c51f124SMoriah Waterland 			register ssize_t entry_size;
994*5c51f124SMoriah Waterland 
995*5c51f124SMoriah Waterland 			/*
996*5c51f124SMoriah Waterland 			 * Copy pkginfo and pkgmap filenames into the
997*5c51f124SMoriah Waterland 			 * temporary string allowing for the first line
998*5c51f124SMoriah Waterland 			 * as a special case.
999*5c51f124SMoriah Waterland 			 */
1000*5c51f124SMoriah Waterland 			entry_size = sprintf(tmp_entry,
1001*5c51f124SMoriah Waterland 			    (i == 0) ? "%s/%s\n%s/%s" : "\n%s/%s\n%s/%s",
1002*5c51f124SMoriah Waterland 			    pkg[i], PKGINFO, pkg[i], PKGMAP);
1003*5c51f124SMoriah Waterland 
1004*5c51f124SMoriah Waterland 			if (write(list_fd, tmp_entry,
1005*5c51f124SMoriah Waterland 			    entry_size) != entry_size) {
1006*5c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_TRANSFER));
1007*5c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_NOTMPFIL));
1008*5c51f124SMoriah Waterland 				(void) close(list_fd);
1009*5c51f124SMoriah Waterland 				ecleanup();
1010*5c51f124SMoriah Waterland 				return (1);
1011*5c51f124SMoriah Waterland 			}
1012*5c51f124SMoriah Waterland 		}
1013*5c51f124SMoriah Waterland 
1014*5c51f124SMoriah Waterland 	} else {
1015*5c51f124SMoriah Waterland 		register ssize_t entry_size;
1016*5c51f124SMoriah Waterland 
1017*5c51f124SMoriah Waterland 		/*
1018*5c51f124SMoriah Waterland 		 * if we're making a signature, we must make a
1019*5c51f124SMoriah Waterland 		 * temporary area full of symlinks to the requisite
1020*5c51f124SMoriah Waterland 		 * files, plus an extra entry for the signature, so
1021*5c51f124SMoriah Waterland 		 * that cpio will put all files and signature in the
1022*5c51f124SMoriah Waterland 		 * same archive in a single invocation of cpio.
1023*5c51f124SMoriah Waterland 		 */
1024*5c51f124SMoriah Waterland 		tmpsymdir = xstrdup(tmpnam(NULL));
1025*5c51f124SMoriah Waterland 
1026*5c51f124SMoriah Waterland 		if (mkdir(tmpsymdir,  S_IRWXU)) {
1027*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
1028*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_MKDIR), tmpsymdir);
1029*5c51f124SMoriah Waterland 			return (1);
1030*5c51f124SMoriah Waterland 		}
1031*5c51f124SMoriah Waterland 
1032*5c51f124SMoriah Waterland 		/* generate the signature */
1033*5c51f124SMoriah Waterland 		if (((len = snprintf(path, PATH_MAX, "%s/%s",
1034*5c51f124SMoriah Waterland 		    tmpsymdir, SIGNATURE_FILENAME)) >= PATH_MAX) ||
1035*5c51f124SMoriah Waterland 		    len < 0) {
1036*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
1037*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_NOTMPFIL), tmpsymdir);
1038*5c51f124SMoriah Waterland 			cleanup();
1039*5c51f124SMoriah Waterland 			return (1);
1040*5c51f124SMoriah Waterland 		}
1041*5c51f124SMoriah Waterland 
1042*5c51f124SMoriah Waterland 		if ((fp = fopen(path, "w")) == NULL) {
1043*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
1044*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_NOTMPFIL), path);
1045*5c51f124SMoriah Waterland 			cleanup();
1046*5c51f124SMoriah Waterland 			return (1);
1047*5c51f124SMoriah Waterland 		}
1048*5c51f124SMoriah Waterland 		PEM_write_PKCS7(fp, sig);
1049*5c51f124SMoriah Waterland 		(void) fclose(fp);
1050*5c51f124SMoriah Waterland 
1051*5c51f124SMoriah Waterland 		for (i = 0; pkg[i]; i++) {
1052*5c51f124SMoriah Waterland 			sprintf(path, "%s/%s", tmpsymdir, pkg[i]);
1053*5c51f124SMoriah Waterland 			if (mkdir(path, 0755)) {
1054*5c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_TRANSFER));
1055*5c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_MKDIR), path);
1056*5c51f124SMoriah Waterland 				cleanup();
1057*5c51f124SMoriah Waterland 				return (1);
1058*5c51f124SMoriah Waterland 			}
1059*5c51f124SMoriah Waterland 			sprintf(path, "%s/%s/%s", tmpsymdir,
1060*5c51f124SMoriah Waterland 			    pkg[i], PKGINFO);
1061*5c51f124SMoriah Waterland 			sprintf(srcpath, "%s/%s/%s", src, pkg[i], PKGINFO);
1062*5c51f124SMoriah Waterland 			if (symlink(srcpath, path) != 0) {
1063*5c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_TRANSFER));
1064*5c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_SYMLINK), path, srcpath);
1065*5c51f124SMoriah Waterland 				cleanup();
1066*5c51f124SMoriah Waterland 				return (1);
1067*5c51f124SMoriah Waterland 			}
1068*5c51f124SMoriah Waterland 
1069*5c51f124SMoriah Waterland 			sprintf(path, "%s/%s/%s", tmpsymdir,
1070*5c51f124SMoriah Waterland 			    pkg[i], PKGMAP);
1071*5c51f124SMoriah Waterland 			sprintf(srcpath, "%s/%s/%s", src, pkg[i], PKGMAP);
1072*5c51f124SMoriah Waterland 			if (symlink(srcpath, path) != 0) {
1073*5c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_TRANSFER));
1074*5c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_SYMLINK), path, srcpath);
1075*5c51f124SMoriah Waterland 				cleanup();
1076*5c51f124SMoriah Waterland 				return (1);
1077*5c51f124SMoriah Waterland 			}
1078*5c51f124SMoriah Waterland 
1079*5c51f124SMoriah Waterland 			/*
1080*5c51f124SMoriah Waterland 			 * Copy pkginfo and pkgmap filenames into the
1081*5c51f124SMoriah Waterland 			 * temporary string allowing for the first line
1082*5c51f124SMoriah Waterland 			 * as a special case.
1083*5c51f124SMoriah Waterland 			 */
1084*5c51f124SMoriah Waterland 			entry_size = sprintf(tmp_entry,
1085*5c51f124SMoriah Waterland 			    (i == 0) ? "%s/%s\n%s/%s" : "\n%s/%s\n%s/%s",
1086*5c51f124SMoriah Waterland 			    pkg[i], PKGINFO, pkg[i], PKGMAP);
1087*5c51f124SMoriah Waterland 
1088*5c51f124SMoriah Waterland 			if (write(list_fd, tmp_entry,
1089*5c51f124SMoriah Waterland 			    entry_size) != entry_size) {
1090*5c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_TRANSFER));
1091*5c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_NOTMPFIL));
1092*5c51f124SMoriah Waterland 				(void) close(list_fd);
1093*5c51f124SMoriah Waterland 				ecleanup();
1094*5c51f124SMoriah Waterland 				cleanup();
1095*5c51f124SMoriah Waterland 				return (1);
1096*5c51f124SMoriah Waterland 			}
1097*5c51f124SMoriah Waterland 		}
1098*5c51f124SMoriah Waterland 
1099*5c51f124SMoriah Waterland 		/* add signature to list of files */
1100*5c51f124SMoriah Waterland 		entry_size = sprintf(tmp_entry, "\n%s", SIGNATURE_FILENAME);
1101*5c51f124SMoriah Waterland 		if (write(list_fd, tmp_entry, entry_size) != entry_size) {
1102*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
1103*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_NOTMPFIL), tmp_file);
1104*5c51f124SMoriah Waterland 			(void) close(list_fd);
1105*5c51f124SMoriah Waterland 			ecleanup();
1106*5c51f124SMoriah Waterland 			cleanup();
1107*5c51f124SMoriah Waterland 			return (1);
1108*5c51f124SMoriah Waterland 		}
1109*5c51f124SMoriah Waterland 	}
1110*5c51f124SMoriah Waterland 
1111*5c51f124SMoriah Waterland 	(void) lseek(list_fd, 0, SEEK_SET);
1112*5c51f124SMoriah Waterland 
1113*5c51f124SMoriah Waterland 	if (!making_sig) {
1114*5c51f124SMoriah Waterland #ifndef SUNOS41
1115*5c51f124SMoriah Waterland 		(void) sprintf(tmp_entry, "%s -ocD -C %d",
1116*5c51f124SMoriah Waterland 		    CPIOPROC, (int)BLK_SIZE);
1117*5c51f124SMoriah Waterland #else
1118*5c51f124SMoriah Waterland 		(void) sprintf(tmp_entry, "%s -oc -C %d",
1119*5c51f124SMoriah Waterland 		    CPIOPROC, (int)BLK_SIZE);
1120*5c51f124SMoriah Waterland #endif
1121*5c51f124SMoriah Waterland 	} else {
1122*5c51f124SMoriah Waterland 		/*
1123*5c51f124SMoriah Waterland 		 * when making a signature, we must make sure to follow
1124*5c51f124SMoriah Waterland 		 * symlinks during the cpio so that we don't archive
1125*5c51f124SMoriah Waterland 		 * the links themselves
1126*5c51f124SMoriah Waterland 		 */
1127*5c51f124SMoriah Waterland #ifndef SUNOS41
1128*5c51f124SMoriah Waterland 		(void) sprintf(tmp_entry, "%s -ocDL -C %d",
1129*5c51f124SMoriah Waterland 		    CPIOPROC, (int)BLK_SIZE);
1130*5c51f124SMoriah Waterland #else
1131*5c51f124SMoriah Waterland 		(void) sprintf(tmp_entry, "%s -ocL -C %d",
1132*5c51f124SMoriah Waterland 		    CPIOPROC, (int)BLK_SIZE);
1133*5c51f124SMoriah Waterland #endif
1134*5c51f124SMoriah Waterland 	}
1135*5c51f124SMoriah Waterland 
1136*5c51f124SMoriah Waterland 	if (making_sig) {
1137*5c51f124SMoriah Waterland 		/* save cwd and change to symlink dir for cpio invocation */
1138*5c51f124SMoriah Waterland 		if (getcwd(cwd, MAXPATHLEN + 1) == NULL) {
1139*5c51f124SMoriah Waterland 			logerr(pkg_gt(ERR_GETWD));
1140*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
1141*5c51f124SMoriah Waterland 			cleanup();
1142*5c51f124SMoriah Waterland 			return (1);
1143*5c51f124SMoriah Waterland 		}
1144*5c51f124SMoriah Waterland 
1145*5c51f124SMoriah Waterland 		if (chdir(tmpsymdir)) {
1146*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
1147*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_CHDIR), tmpsymdir);
1148*5c51f124SMoriah Waterland 			cleanup();
1149*5c51f124SMoriah Waterland 			return (1);
1150*5c51f124SMoriah Waterland 		}
1151*5c51f124SMoriah Waterland 	}
1152*5c51f124SMoriah Waterland 
1153*5c51f124SMoriah Waterland 	if (n = esystem(tmp_entry, list_fd, ds_fd)) {
1154*5c51f124SMoriah Waterland 		rpterr();
1155*5c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
1156*5c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_CMDFAIL), tmp_entry, n);
1157*5c51f124SMoriah Waterland 		(void) close(list_fd);
1158*5c51f124SMoriah Waterland 		(void) unlink(tmp_file);
1159*5c51f124SMoriah Waterland 		cleanup();
1160*5c51f124SMoriah Waterland 		return (1);
1161*5c51f124SMoriah Waterland 	}
1162*5c51f124SMoriah Waterland 
1163*5c51f124SMoriah Waterland 	(void) close(list_fd);
1164*5c51f124SMoriah Waterland 	(void) unlink(tmp_file);
1165*5c51f124SMoriah Waterland 
1166*5c51f124SMoriah Waterland 	if (making_sig) {
1167*5c51f124SMoriah Waterland 		/* change to back to src dir for subsequent operations */
1168*5c51f124SMoriah Waterland 		if (chdir(cwd)) {
1169*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
1170*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_CHDIR), cwd);
1171*5c51f124SMoriah Waterland 			cleanup();
1172*5c51f124SMoriah Waterland 			return (1);
1173*5c51f124SMoriah Waterland 		}
1174*5c51f124SMoriah Waterland 	}
1175*5c51f124SMoriah Waterland 	return (0);
1176*5c51f124SMoriah Waterland }
1177*5c51f124SMoriah Waterland 
1178*5c51f124SMoriah Waterland static int
1179*5c51f124SMoriah Waterland ckoverwrite(char *dir, char *inst, int options)
1180*5c51f124SMoriah Waterland {
1181*5c51f124SMoriah Waterland 	char	path[PATH_MAX];
1182*5c51f124SMoriah Waterland 
1183*5c51f124SMoriah Waterland 	(void) sprintf(path, "%s/%s", dir, inst);
1184*5c51f124SMoriah Waterland 	if (access(path, 0) == 0) {
1185*5c51f124SMoriah Waterland 		if (options & PT_OVERWRITE)
1186*5c51f124SMoriah Waterland 			return (rrmdir(path));
1187*5c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
1188*5c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_EXISTS), path);
1189*5c51f124SMoriah Waterland 		return (1);
1190*5c51f124SMoriah Waterland 	}
1191*5c51f124SMoriah Waterland 	return (0);
1192*5c51f124SMoriah Waterland }
1193*5c51f124SMoriah Waterland 
1194*5c51f124SMoriah Waterland static int
1195*5c51f124SMoriah Waterland pkgxfer(char *srcinst, int options)
1196*5c51f124SMoriah Waterland {
1197*5c51f124SMoriah Waterland 	int	r;
1198*5c51f124SMoriah Waterland 	struct pkginfo info;
1199*5c51f124SMoriah Waterland 	FILE	*fp, *pp;
1200*5c51f124SMoriah Waterland 	char	*pt, *src, *dst;
1201*5c51f124SMoriah Waterland 	char	dstdir[PATH_MAX],
1202*5c51f124SMoriah Waterland 		temp[PATH_MAX],
1203*5c51f124SMoriah Waterland 		srcdir[PATH_MAX],
1204*5c51f124SMoriah Waterland 		cmd[CMDSIZE],
1205*5c51f124SMoriah Waterland 		pkgname[NON_ABI_NAMELNGTH];
1206*5c51f124SMoriah Waterland 	int	i, n, part, nparts, maxpartsize, curpartcnt, iscomp;
1207*5c51f124SMoriah Waterland 	char	volnos[128], tmpvol[128];
1208*5c51f124SMoriah Waterland 	struct	statvfs64 svfsb;
1209*5c51f124SMoriah Waterland 	longlong_t free_blocks;
1210*5c51f124SMoriah Waterland 	struct	stat	srcstat;
1211*5c51f124SMoriah Waterland 
1212*5c51f124SMoriah Waterland 	info.pkginst = NULL; /* required initialization */
1213*5c51f124SMoriah Waterland 
1214*5c51f124SMoriah Waterland 	/*
1215*5c51f124SMoriah Waterland 	 * when this routine is entered, the first part of
1216*5c51f124SMoriah Waterland 	 * the package to transfer is already available in
1217*5c51f124SMoriah Waterland 	 * the directory indicated by 'src' --- unless the
1218*5c51f124SMoriah Waterland 	 * source device is a datstream, in which case only
1219*5c51f124SMoriah Waterland 	 * the pkginfo and pkgmap files are available in 'src'
1220*5c51f124SMoriah Waterland 	 */
1221*5c51f124SMoriah Waterland 	src = srcdev.dirname;
1222*5c51f124SMoriah Waterland 	dst = dstdev.dirname;
1223*5c51f124SMoriah Waterland 
1224*5c51f124SMoriah Waterland 	if (!(options & PT_SILENT))
1225*5c51f124SMoriah Waterland 		(void) fprintf(stderr, pkg_gt(MSG_TRANSFER), srcinst);
1226*5c51f124SMoriah Waterland 	(void) strcpy(dstinst, srcinst);
1227*5c51f124SMoriah Waterland 
1228*5c51f124SMoriah Waterland 	if (!(options & PT_ODTSTREAM)) {
1229*5c51f124SMoriah Waterland 		/* destination is a (possibly mounted) directory */
1230*5c51f124SMoriah Waterland 		(void) sprintf(dstdir, "%s/%s", dst, dstinst);
1231*5c51f124SMoriah Waterland 
1232*5c51f124SMoriah Waterland 		/*
1233*5c51f124SMoriah Waterland 		 * need to check destination directory to assure
1234*5c51f124SMoriah Waterland 		 * that we will not be duplicating a package which
1235*5c51f124SMoriah Waterland 		 * already resides there (though we are allowed to
1236*5c51f124SMoriah Waterland 		 * overwrite the same version)
1237*5c51f124SMoriah Waterland 		 */
1238*5c51f124SMoriah Waterland 		pkgdir = src;
1239*5c51f124SMoriah Waterland 		if (fpkginfo(&info, srcinst)) {
1240*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
1241*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_NOEXISTS), srcinst);
1242*5c51f124SMoriah Waterland 			(void) fpkginfo(&info, NULL);
1243*5c51f124SMoriah Waterland 			return (1);
1244*5c51f124SMoriah Waterland 		}
1245*5c51f124SMoriah Waterland 		pkgdir = dst;
1246*5c51f124SMoriah Waterland 
1247*5c51f124SMoriah Waterland 		(void) strcpy(temp, srcinst);
1248*5c51f124SMoriah Waterland 		if (pt = strchr(temp, '.'))
1249*5c51f124SMoriah Waterland 			*pt = '\0';
1250*5c51f124SMoriah Waterland 		(void) strcat(temp, ".*");
1251*5c51f124SMoriah Waterland 
1252*5c51f124SMoriah Waterland 		if (pt = fpkginst(temp, info.arch, info.version)) {
1253*5c51f124SMoriah Waterland 			/*
1254*5c51f124SMoriah Waterland 			 * the same instance already exists, although
1255*5c51f124SMoriah Waterland 			 * its pkgid might be different
1256*5c51f124SMoriah Waterland 			 */
1257*5c51f124SMoriah Waterland 			if (options & PT_OVERWRITE) {
1258*5c51f124SMoriah Waterland 				(void) strcpy(dstinst, pt);
1259*5c51f124SMoriah Waterland 				(void) sprintf(dstdir, "%s/%s", dst, dstinst);
1260*5c51f124SMoriah Waterland 			} else {
1261*5c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_TRANSFER));
1262*5c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_DUPVERS), srcinst);
1263*5c51f124SMoriah Waterland 				(void) fpkginfo(&info, NULL);
1264*5c51f124SMoriah Waterland 				(void) fpkginst(NULL);
1265*5c51f124SMoriah Waterland 				return (2);
1266*5c51f124SMoriah Waterland 			}
1267*5c51f124SMoriah Waterland 		} else if (options & PT_RENAME) {
1268*5c51f124SMoriah Waterland 			/*
1269*5c51f124SMoriah Waterland 			 * find next available instance by appending numbers
1270*5c51f124SMoriah Waterland 			 * to the package abbreviation until the instance
1271*5c51f124SMoriah Waterland 			 * does not exist in the destination directory
1272*5c51f124SMoriah Waterland 			 */
1273*5c51f124SMoriah Waterland 			if (pt = strchr(temp, '.'))
1274*5c51f124SMoriah Waterland 				*pt = '\0';
1275*5c51f124SMoriah Waterland 			for (i = 2; (access(dstdir, 0) == 0); i++) {
1276*5c51f124SMoriah Waterland 				(void) sprintf(dstinst, "%s.%d", temp, i);
1277*5c51f124SMoriah Waterland 				(void) sprintf(dstdir, "%s/%s", dst, dstinst);
1278*5c51f124SMoriah Waterland 			}
1279*5c51f124SMoriah Waterland 		} else if (options & PT_OVERWRITE) {
1280*5c51f124SMoriah Waterland 			/*
1281*5c51f124SMoriah Waterland 			 * we're allowed to overwrite, but there seems
1282*5c51f124SMoriah Waterland 			 * to be no valid package to overwrite, and we are
1283*5c51f124SMoriah Waterland 			 * not allowed to rename the destination, so act
1284*5c51f124SMoriah Waterland 			 * as if we weren't given permission to overwrite
1285*5c51f124SMoriah Waterland 			 * --- this keeps us from removing a destination
1286*5c51f124SMoriah Waterland 			 * instance which is named the same as the source
1287*5c51f124SMoriah Waterland 			 * instance, but really reflects a different pkg!
1288*5c51f124SMoriah Waterland 			 */
1289*5c51f124SMoriah Waterland 			options &= (~PT_OVERWRITE);
1290*5c51f124SMoriah Waterland 		}
1291*5c51f124SMoriah Waterland 		(void) fpkginfo(&info, NULL);
1292*5c51f124SMoriah Waterland 		(void) fpkginst(NULL);
1293*5c51f124SMoriah Waterland 
1294*5c51f124SMoriah Waterland 		if (ckoverwrite(dst, dstinst, options))
1295*5c51f124SMoriah Waterland 			return (2);
1296*5c51f124SMoriah Waterland 
1297*5c51f124SMoriah Waterland 		if (isdir(dstdir) && mkdir(dstdir, 0755)) {
1298*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
1299*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_MKDIR), dstdir);
1300*5c51f124SMoriah Waterland 			return (1);
1301*5c51f124SMoriah Waterland 		}
1302*5c51f124SMoriah Waterland 
1303*5c51f124SMoriah Waterland 		(void) sprintf(srcdir, "%s/%s", src, srcinst);
1304*5c51f124SMoriah Waterland 		if (stat(srcdir, &srcstat) != -1) {
1305*5c51f124SMoriah Waterland 			if (chmod(dstdir, (srcstat.st_mode & S_IAMB)) == -1) {
1306*5c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_TRANSFER));
1307*5c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_CHMODDIR), dstdir);
1308*5c51f124SMoriah Waterland 				return (1);
1309*5c51f124SMoriah Waterland 			}
1310*5c51f124SMoriah Waterland 		} else {
1311*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
1312*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_STATDIR), srcdir);
1313*5c51f124SMoriah Waterland 			return (1);
1314*5c51f124SMoriah Waterland 		}
1315*5c51f124SMoriah Waterland 	}
1316*5c51f124SMoriah Waterland 
1317*5c51f124SMoriah Waterland 	if (!(options & PT_SILENT) && strcmp(dstinst, srcinst))
1318*5c51f124SMoriah Waterland 		(void) fprintf(stderr, pkg_gt(MSG_RENAME), dstinst);
1319*5c51f124SMoriah Waterland 
1320*5c51f124SMoriah Waterland 	(void) sprintf(srcdir, "%s/%s", src, srcinst);
1321*5c51f124SMoriah Waterland 	if (chdir(srcdir)) {
1322*5c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
1323*5c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_CHDIR), srcdir);
1324*5c51f124SMoriah Waterland 		return (1);
1325*5c51f124SMoriah Waterland 	}
1326*5c51f124SMoriah Waterland 
1327*5c51f124SMoriah Waterland 	if (ids_name) {	/* unpack the datatstream into a directory */
1328*5c51f124SMoriah Waterland 		/*
1329*5c51f124SMoriah Waterland 		 * transfer pkginfo & pkgmap first
1330*5c51f124SMoriah Waterland 		 */
1331*5c51f124SMoriah Waterland 		(void) sprintf(cmd, "%s -pudm %s", CPIOPROC, dstdir);
1332*5c51f124SMoriah Waterland 		if ((pp = epopen(cmd, "w")) == NULL) {
1333*5c51f124SMoriah Waterland 			rpterr();
1334*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
1335*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_POPEN), cmd, errno);
1336*5c51f124SMoriah Waterland 			return (1);
1337*5c51f124SMoriah Waterland 		}
1338*5c51f124SMoriah Waterland 		(void) fprintf(pp, "%s\n%s\n", PKGINFO, PKGMAP);
1339*5c51f124SMoriah Waterland 
1340*5c51f124SMoriah Waterland 		sighold(SIGINT);
1341*5c51f124SMoriah Waterland 		sighold(SIGHUP);
1342*5c51f124SMoriah Waterland 		r = epclose(pp);
1343*5c51f124SMoriah Waterland 		sigrelse(SIGINT);
1344*5c51f124SMoriah Waterland 		sigrelse(SIGHUP);
1345*5c51f124SMoriah Waterland 
1346*5c51f124SMoriah Waterland 		if (r != 0) {
1347*5c51f124SMoriah Waterland 			rpterr();
1348*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
1349*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_PCLOSE), cmd, errno);
1350*5c51f124SMoriah Waterland 			return (1);
1351*5c51f124SMoriah Waterland 		}
1352*5c51f124SMoriah Waterland 
1353*5c51f124SMoriah Waterland 		if (options & PT_INFO_ONLY)
1354*5c51f124SMoriah Waterland 			return (0); /* don't transfer objects */
1355*5c51f124SMoriah Waterland 
1356*5c51f124SMoriah Waterland 		if (chdir(dstdir)) {
1357*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
1358*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_CHDIR), dstdir);
1359*5c51f124SMoriah Waterland 			return (1);
1360*5c51f124SMoriah Waterland 		}
1361*5c51f124SMoriah Waterland 
1362*5c51f124SMoriah Waterland 		/*
1363*5c51f124SMoriah Waterland 		 * for each part of the package, use cpio() to
1364*5c51f124SMoriah Waterland 		 * unpack the archive into the destination directory
1365*5c51f124SMoriah Waterland 		 */
1366*5c51f124SMoriah Waterland 		nparts = ds_findpkg(srcdev.cdevice, srcinst);
1367*5c51f124SMoriah Waterland 		if (nparts < 0) {
1368*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
1369*5c51f124SMoriah Waterland 			return (1);
1370*5c51f124SMoriah Waterland 		}
1371*5c51f124SMoriah Waterland 		for (part = 1; part <= nparts; /* void */) {
1372*5c51f124SMoriah Waterland 			if (ds_getpkg(srcdev.cdevice, part, dstdir)) {
1373*5c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_TRANSFER));
1374*5c51f124SMoriah Waterland 				return (1);
1375*5c51f124SMoriah Waterland 			}
1376*5c51f124SMoriah Waterland 			part++;
1377*5c51f124SMoriah Waterland 			if (dstdev.mount) {
1378*5c51f124SMoriah Waterland 				(void) chdir("/");
1379*5c51f124SMoriah Waterland 				if (pkgumount(&dstdev))
1380*5c51f124SMoriah Waterland 					return (1);
1381*5c51f124SMoriah Waterland 				if (part <= nparts) {
1382*5c51f124SMoriah Waterland 					if (n = pkgmount(&dstdev, NULL, part+1,
1383*5c51f124SMoriah Waterland 					    nparts, 1))
1384*5c51f124SMoriah Waterland 						return (n);
1385*5c51f124SMoriah Waterland 					if (ckoverwrite(dst, dstinst, options))
1386*5c51f124SMoriah Waterland 						return (1);
1387*5c51f124SMoriah Waterland 					if (isdir(dstdir) &&
1388*5c51f124SMoriah Waterland 					    mkdir(dstdir, 0755)) {
1389*5c51f124SMoriah Waterland 						progerr(
1390*5c51f124SMoriah Waterland 						    pkg_gt(ERR_TRANSFER));
1391*5c51f124SMoriah Waterland 						logerr(pkg_gt(MSG_MKDIR),
1392*5c51f124SMoriah Waterland 						    dstdir);
1393*5c51f124SMoriah Waterland 						return (1);
1394*5c51f124SMoriah Waterland 					}
1395*5c51f124SMoriah Waterland 					/*
1396*5c51f124SMoriah Waterland 					 * since volume is removable, each part
1397*5c51f124SMoriah Waterland 					 * must contain a duplicate of the
1398*5c51f124SMoriah Waterland 					 * pkginfo file to properly identify the
1399*5c51f124SMoriah Waterland 					 * volume
1400*5c51f124SMoriah Waterland 					 */
1401*5c51f124SMoriah Waterland 					if (chdir(srcdir)) {
1402*5c51f124SMoriah Waterland 						progerr(
1403*5c51f124SMoriah Waterland 						    pkg_gt(ERR_TRANSFER));
1404*5c51f124SMoriah Waterland 						logerr(pkg_gt(MSG_CHDIR),
1405*5c51f124SMoriah Waterland 						    srcdir);
1406*5c51f124SMoriah Waterland 						return (1);
1407*5c51f124SMoriah Waterland 					}
1408*5c51f124SMoriah Waterland 					if ((pp = epopen(cmd, "w")) == NULL) {
1409*5c51f124SMoriah Waterland 						rpterr();
1410*5c51f124SMoriah Waterland 						progerr(
1411*5c51f124SMoriah Waterland 						    pkg_gt(ERR_TRANSFER));
1412*5c51f124SMoriah Waterland 						logerr(pkg_gt(MSG_POPEN),
1413*5c51f124SMoriah Waterland 						    cmd, errno);
1414*5c51f124SMoriah Waterland 						return (1);
1415*5c51f124SMoriah Waterland 					}
1416*5c51f124SMoriah Waterland 					(void) fprintf(pp, "pkginfo");
1417*5c51f124SMoriah Waterland 
1418*5c51f124SMoriah Waterland 					sighold(SIGINT);
1419*5c51f124SMoriah Waterland 					sighold(SIGHUP);
1420*5c51f124SMoriah Waterland 					r = epclose(pp);
1421*5c51f124SMoriah Waterland 					sigrelse(SIGINT);
1422*5c51f124SMoriah Waterland 					sigrelse(SIGHUP);
1423*5c51f124SMoriah Waterland 
1424*5c51f124SMoriah Waterland 					if (r != 0) {
1425*5c51f124SMoriah Waterland 						rpterr();
1426*5c51f124SMoriah Waterland 						progerr(
1427*5c51f124SMoriah Waterland 						    pkg_gt(ERR_TRANSFER));
1428*5c51f124SMoriah Waterland 						logerr(pkg_gt(MSG_PCLOSE),
1429*5c51f124SMoriah Waterland 						    cmd, errno);
1430*5c51f124SMoriah Waterland 						return (1);
1431*5c51f124SMoriah Waterland 					}
1432*5c51f124SMoriah Waterland 					if (chdir(dstdir)) {
1433*5c51f124SMoriah Waterland 						progerr(
1434*5c51f124SMoriah Waterland 						    pkg_gt(ERR_TRANSFER));
1435*5c51f124SMoriah Waterland 						logerr(pkg_gt(MSG_CHDIR),
1436*5c51f124SMoriah Waterland 						    dstdir);
1437*5c51f124SMoriah Waterland 						return (1);
1438*5c51f124SMoriah Waterland 					}
1439*5c51f124SMoriah Waterland 				}
1440*5c51f124SMoriah Waterland 			}
1441*5c51f124SMoriah Waterland 		}
1442*5c51f124SMoriah Waterland 		return (0);
1443*5c51f124SMoriah Waterland 	}
1444*5c51f124SMoriah Waterland 
1445*5c51f124SMoriah Waterland 	if ((fp = fopen(PKGMAP, "r")) == NULL) {
1446*5c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
1447*5c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_NOPKGMAP), srcinst);
1448*5c51f124SMoriah Waterland 		return (1);
1449*5c51f124SMoriah Waterland 	}
1450*5c51f124SMoriah Waterland 
1451*5c51f124SMoriah Waterland 	nparts = 1;
1452*5c51f124SMoriah Waterland 	if (!rd_map_size(fp, &nparts, &maxpartsize, &compressedsize))
1453*5c51f124SMoriah Waterland 		return (1);
1454*5c51f124SMoriah Waterland 	else
1455*5c51f124SMoriah Waterland 		(void) fclose(fp);
1456*5c51f124SMoriah Waterland 
1457*5c51f124SMoriah Waterland 	if (srcdev.mount) {
1458*5c51f124SMoriah Waterland 		if (ckvolseq(srcdir, 1, nparts)) {
1459*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
1460*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_SEQUENCE));
1461*5c51f124SMoriah Waterland 			return (1);
1462*5c51f124SMoriah Waterland 		}
1463*5c51f124SMoriah Waterland 	}
1464*5c51f124SMoriah Waterland 
1465*5c51f124SMoriah Waterland 	/* write each part of this package */
1466*5c51f124SMoriah Waterland 	if (options & PT_ODTSTREAM) {
1467*5c51f124SMoriah Waterland 		char line[128];
1468*5c51f124SMoriah Waterland 		(void) mgets(line, 128);
1469*5c51f124SMoriah Waterland 		curpartcnt = -1;
1470*5c51f124SMoriah Waterland 		if (sscanf(line, "%s %d %d %[ 0-9]", &pkgname, &nparts,
1471*5c51f124SMoriah Waterland 		    &maxpartsize, volnos) == 4) {
1472*5c51f124SMoriah Waterland 			sscanf(volnos, "%d %[ 0-9]", &curpartcnt, tmpvol);
1473*5c51f124SMoriah Waterland 			strcpy(volnos, tmpvol);
1474*5c51f124SMoriah Waterland 		}
1475*5c51f124SMoriah Waterland 	}
1476*5c51f124SMoriah Waterland 
1477*5c51f124SMoriah Waterland 	for (part = 1; part <= nparts; /* void */) {
1478*5c51f124SMoriah Waterland 		if (curpartcnt == 0 && (options & PT_ODTSTREAM)) {
1479*5c51f124SMoriah Waterland 			char prompt[128];
1480*5c51f124SMoriah Waterland 			int index;
1481*5c51f124SMoriah Waterland 			ds_volno++;
1482*5c51f124SMoriah Waterland 			(void) ds_close(0);
1483*5c51f124SMoriah Waterland 			(void) sprintf(prompt,
1484*5c51f124SMoriah Waterland 			    pkg_gt("Insert %%v %d of %d into %%p"),
1485*5c51f124SMoriah Waterland 			    ds_volno, ds_volcnt);
1486*5c51f124SMoriah Waterland 			if (n = getvol(ods_name, NULL, DM_FORMAT, prompt))
1487*5c51f124SMoriah Waterland 				return (n);
1488*5c51f124SMoriah Waterland 			if ((ds_fd = open(dstdev.cdevice, O_WRONLY)) < 0) {
1489*5c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_TRANSFER));
1490*5c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_OPEN), dstdev.cdevice,
1491*5c51f124SMoriah Waterland 				    errno);
1492*5c51f124SMoriah Waterland 				return (1);
1493*5c51f124SMoriah Waterland 			}
1494*5c51f124SMoriah Waterland 			if (ds_ginit(dstdev.cdevice) < 0) {
1495*5c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_TRANSFER));
1496*5c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_OPEN), dstdev.cdevice,
1497*5c51f124SMoriah Waterland 				    errno);
1498*5c51f124SMoriah Waterland 				(void) ds_close(0);
1499*5c51f124SMoriah Waterland 				return (1);
1500*5c51f124SMoriah Waterland 			}
1501*5c51f124SMoriah Waterland 
1502*5c51f124SMoriah Waterland 			(void) sscanf(volnos, "%d %[ 0-9]", &index, tmpvol);
1503*5c51f124SMoriah Waterland 			(void) strcpy(volnos, tmpvol);
1504*5c51f124SMoriah Waterland 			curpartcnt += index;
1505*5c51f124SMoriah Waterland 		}
1506*5c51f124SMoriah Waterland 
1507*5c51f124SMoriah Waterland 		if (options & PT_INFO_ONLY)
1508*5c51f124SMoriah Waterland 			nparts = 0;
1509*5c51f124SMoriah Waterland 
1510*5c51f124SMoriah Waterland 		if (part == 1) {
1511*5c51f124SMoriah Waterland 			(void) sprintf(cmd, "find %s %s", PKGINFO, PKGMAP);
1512*5c51f124SMoriah Waterland 			if (nparts && (isdir(INSTALL) == 0)) {
1513*5c51f124SMoriah Waterland 				(void) strcat(cmd, " ");
1514*5c51f124SMoriah Waterland 				(void) strcat(cmd, INSTALL);
1515*5c51f124SMoriah Waterland 			}
1516*5c51f124SMoriah Waterland 		} else
1517*5c51f124SMoriah Waterland 			(void) sprintf(cmd, "find %s", PKGINFO);
1518*5c51f124SMoriah Waterland 
1519*5c51f124SMoriah Waterland 		if (nparts > 1) {
1520*5c51f124SMoriah Waterland 			(void) sprintf(temp, "%s.%d", RELOC, part);
1521*5c51f124SMoriah Waterland 			if (iscpio(temp, &iscomp) || isdir(temp) == 0) {
1522*5c51f124SMoriah Waterland 				(void) strcat(cmd, " ");
1523*5c51f124SMoriah Waterland 				(void) strcat(cmd, temp);
1524*5c51f124SMoriah Waterland 			}
1525*5c51f124SMoriah Waterland 			(void) sprintf(temp, "%s.%d", ROOT, part);
1526*5c51f124SMoriah Waterland 			if (iscpio(temp, &iscomp) || isdir(temp) == 0) {
1527*5c51f124SMoriah Waterland 				(void) strcat(cmd, " ");
1528*5c51f124SMoriah Waterland 				(void) strcat(cmd, temp);
1529*5c51f124SMoriah Waterland 			}
1530*5c51f124SMoriah Waterland 			(void) sprintf(temp, "%s.%d", ARCHIVE, part);
1531*5c51f124SMoriah Waterland 			if (isdir(temp) == 0) {
1532*5c51f124SMoriah Waterland 				(void) strcat(cmd, " ");
1533*5c51f124SMoriah Waterland 				(void) strcat(cmd, temp);
1534*5c51f124SMoriah Waterland 			}
1535*5c51f124SMoriah Waterland 		} else if (nparts) {
1536*5c51f124SMoriah Waterland 			for (i = 0; reloc_names[i] != NULL; i++) {
1537*5c51f124SMoriah Waterland 				if (iscpio(reloc_names[i], &iscomp) ||
1538*5c51f124SMoriah Waterland 				    isdir(reloc_names[i]) == 0) {
1539*5c51f124SMoriah Waterland 					(void) strcat(cmd, " ");
1540*5c51f124SMoriah Waterland 					(void) strcat(cmd, reloc_names[i]);
1541*5c51f124SMoriah Waterland 				}
1542*5c51f124SMoriah Waterland 			}
1543*5c51f124SMoriah Waterland 			for (i = 0; root_names[i] != NULL; i++) {
1544*5c51f124SMoriah Waterland 				if (iscpio(root_names[i], &iscomp) ||
1545*5c51f124SMoriah Waterland 				    isdir(root_names[i]) == 0) {
1546*5c51f124SMoriah Waterland 					(void) strcat(cmd, " ");
1547*5c51f124SMoriah Waterland 					(void) strcat(cmd, root_names[i]);
1548*5c51f124SMoriah Waterland 				}
1549*5c51f124SMoriah Waterland 			}
1550*5c51f124SMoriah Waterland 			if (isdir(ARCHIVE) == 0) {
1551*5c51f124SMoriah Waterland 				(void) strcat(cmd, " ");
1552*5c51f124SMoriah Waterland 				(void) strcat(cmd, ARCHIVE);
1553*5c51f124SMoriah Waterland 			}
1554*5c51f124SMoriah Waterland 		}
1555*5c51f124SMoriah Waterland 		if (options & PT_ODTSTREAM) {
1556*5c51f124SMoriah Waterland #ifndef SUNOS41
1557*5c51f124SMoriah Waterland 			(void) sprintf(cmd+strlen(cmd),
1558*5c51f124SMoriah Waterland 			    " -print | %s -ocD -C %d",
1559*5c51f124SMoriah Waterland #else
1560*5c51f124SMoriah Waterland 			(void) sprintf(cmd+strlen(cmd),
1561*5c51f124SMoriah Waterland 			    " -print | %s -oc -C %d",
1562*5c51f124SMoriah Waterland #endif
1563*5c51f124SMoriah Waterland 				CPIOPROC, (int)BLK_SIZE);
1564*5c51f124SMoriah Waterland 		} else {
1565*5c51f124SMoriah Waterland 			if (statvfs64(dstdir, &svfsb) == -1) {
1566*5c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_TRANSFER));
1567*5c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_STATVFS), dstdir, errno);
1568*5c51f124SMoriah Waterland 				return (1);
1569*5c51f124SMoriah Waterland 			}
1570*5c51f124SMoriah Waterland 
1571*5c51f124SMoriah Waterland 			free_blocks = (((long)svfsb.f_frsize > 0) ?
1572*5c51f124SMoriah Waterland 			    howmany(svfsb.f_frsize, DEV_BSIZE) :
1573*5c51f124SMoriah Waterland 			    howmany(svfsb.f_bsize, DEV_BSIZE)) * svfsb.f_bavail;
1574*5c51f124SMoriah Waterland 
1575*5c51f124SMoriah Waterland 			if ((has_comp_size ? compressedsize : maxpartsize) >
1576*5c51f124SMoriah Waterland 			    free_blocks) {
1577*5c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_TRANSFER));
1578*5c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_NOSPACE));
1579*5c51f124SMoriah Waterland 				return (1);
1580*5c51f124SMoriah Waterland 			}
1581*5c51f124SMoriah Waterland 			(void) sprintf(cmd+strlen(cmd), " -print | %s -pdum %s",
1582*5c51f124SMoriah Waterland 				CPIOPROC, dstdir);
1583*5c51f124SMoriah Waterland 		}
1584*5c51f124SMoriah Waterland 
1585*5c51f124SMoriah Waterland 		n = esystem(cmd, -1, (options & PT_ODTSTREAM) ? ds_fd : -1);
1586*5c51f124SMoriah Waterland 		if (n) {
1587*5c51f124SMoriah Waterland 			rpterr();
1588*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
1589*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_CMDFAIL), cmd, n);
1590*5c51f124SMoriah Waterland 			return (1);
1591*5c51f124SMoriah Waterland 		}
1592*5c51f124SMoriah Waterland 
1593*5c51f124SMoriah Waterland 		part++;
1594*5c51f124SMoriah Waterland 		if (srcdev.mount && (nparts > 1)) {
1595*5c51f124SMoriah Waterland 			/* unmount current source volume */
1596*5c51f124SMoriah Waterland 			(void) chdir("/");
1597*5c51f124SMoriah Waterland 			if (pkgumount(&srcdev))
1598*5c51f124SMoriah Waterland 				return (1);
1599*5c51f124SMoriah Waterland 			/* loop until volume is mounted successfully */
1600*5c51f124SMoriah Waterland 			while (part <= nparts) {
1601*5c51f124SMoriah Waterland 				/* read only */
1602*5c51f124SMoriah Waterland 				n = pkgmount(&srcdev, NULL, part, nparts, 1);
1603*5c51f124SMoriah Waterland 				if (n)
1604*5c51f124SMoriah Waterland 					return (n);
1605*5c51f124SMoriah Waterland 				if (chdir(srcdir)) {
1606*5c51f124SMoriah Waterland 					progerr(pkg_gt(ERR_TRANSFER));
1607*5c51f124SMoriah Waterland 					logerr(pkg_gt(MSG_CORRUPT), srcdir);
1608*5c51f124SMoriah Waterland 					(void) chdir("/");
1609*5c51f124SMoriah Waterland 					pkgumount(&srcdev);
1610*5c51f124SMoriah Waterland 					continue;
1611*5c51f124SMoriah Waterland 				}
1612*5c51f124SMoriah Waterland 				if (ckvolseq(srcdir, part, nparts)) {
1613*5c51f124SMoriah Waterland 					(void) chdir("/");
1614*5c51f124SMoriah Waterland 					pkgumount(&srcdev);
1615*5c51f124SMoriah Waterland 					continue;
1616*5c51f124SMoriah Waterland 				}
1617*5c51f124SMoriah Waterland 				break;
1618*5c51f124SMoriah Waterland 			}
1619*5c51f124SMoriah Waterland 		}
1620*5c51f124SMoriah Waterland 		if (!(options & PT_ODTSTREAM) && dstdev.mount) {
1621*5c51f124SMoriah Waterland 			/* unmount current volume */
1622*5c51f124SMoriah Waterland 			if (pkgumount(&dstdev))
1623*5c51f124SMoriah Waterland 				return (1);
1624*5c51f124SMoriah Waterland 			/* loop until next volume is mounted successfully */
1625*5c51f124SMoriah Waterland 			while (part <= nparts) {
1626*5c51f124SMoriah Waterland 				/* writable */
1627*5c51f124SMoriah Waterland 				n = pkgmount(&dstdev, NULL, part, nparts, 1);
1628*5c51f124SMoriah Waterland 				if (n)
1629*5c51f124SMoriah Waterland 					return (n);
1630*5c51f124SMoriah Waterland 				if (ckoverwrite(dst, dstinst, options))
1631*5c51f124SMoriah Waterland 					continue;
1632*5c51f124SMoriah Waterland 				if (isdir(dstdir) && mkdir(dstdir, 0755)) {
1633*5c51f124SMoriah Waterland 					progerr(pkg_gt(ERR_TRANSFER));
1634*5c51f124SMoriah Waterland 					logerr(pkg_gt(MSG_MKDIR), dstdir);
1635*5c51f124SMoriah Waterland 					continue;
1636*5c51f124SMoriah Waterland 				}
1637*5c51f124SMoriah Waterland 				break;
1638*5c51f124SMoriah Waterland 			}
1639*5c51f124SMoriah Waterland 		}
1640*5c51f124SMoriah Waterland 
1641*5c51f124SMoriah Waterland 		if ((options & PT_ODTSTREAM) && part <= nparts) {
1642*5c51f124SMoriah Waterland 			if (curpartcnt >= 0 && part > curpartcnt) {
1643*5c51f124SMoriah Waterland 				char prompt[128];
1644*5c51f124SMoriah Waterland 				int index;
1645*5c51f124SMoriah Waterland 				ds_volno++;
1646*5c51f124SMoriah Waterland 				if (ds_close(0))
1647*5c51f124SMoriah Waterland 					return (1);
1648*5c51f124SMoriah Waterland 				(void) sprintf(prompt,
1649*5c51f124SMoriah Waterland 				    pkg_gt("Insert %%v %d of %d into %%p"),
1650*5c51f124SMoriah Waterland 				    ds_volno, ds_volcnt);
1651*5c51f124SMoriah Waterland 				if (n = getvol(ods_name, NULL, DM_FORMAT,
1652*5c51f124SMoriah Waterland 				    prompt))
1653*5c51f124SMoriah Waterland 					return (n);
1654*5c51f124SMoriah Waterland 				if ((ds_fd = open(dstdev.cdevice, 1)) < 0) {
1655*5c51f124SMoriah Waterland 					progerr(pkg_gt(ERR_TRANSFER));
1656*5c51f124SMoriah Waterland 					logerr(pkg_gt(MSG_OPEN),
1657*5c51f124SMoriah Waterland 					    dstdev.cdevice, errno);
1658*5c51f124SMoriah Waterland 					return (1);
1659*5c51f124SMoriah Waterland 				}
1660*5c51f124SMoriah Waterland 				if (ds_ginit(dstdev.cdevice) < 0) {
1661*5c51f124SMoriah Waterland 					progerr(pkg_gt(ERR_TRANSFER));
1662*5c51f124SMoriah Waterland 					logerr(pkg_gt(MSG_OPEN),
1663*5c51f124SMoriah Waterland 					    dstdev.cdevice, errno);
1664*5c51f124SMoriah Waterland 					(void) ds_close(0);
1665*5c51f124SMoriah Waterland 					return (1);
1666*5c51f124SMoriah Waterland 				}
1667*5c51f124SMoriah Waterland 
1668*5c51f124SMoriah Waterland 				(void) sscanf(volnos, "%d %[ 0-9]", &index,
1669*5c51f124SMoriah Waterland 				    tmpvol);
1670*5c51f124SMoriah Waterland 				(void) strcpy(volnos, tmpvol);
1671*5c51f124SMoriah Waterland 				curpartcnt += index;
1672*5c51f124SMoriah Waterland 			}
1673*5c51f124SMoriah Waterland 		}
1674*5c51f124SMoriah Waterland 
1675*5c51f124SMoriah Waterland 	}
1676*5c51f124SMoriah Waterland 	return (0);
1677*5c51f124SMoriah Waterland }
1678*5c51f124SMoriah Waterland 
1679*5c51f124SMoriah Waterland /*
1680*5c51f124SMoriah Waterland  * Name:		pkgdump
1681*5c51f124SMoriah Waterland  * Description:	Dump a cpio archive of a package's contents to a BIO.
1682*5c51f124SMoriah Waterland  *
1683*5c51f124SMoriah Waterland  * Arguments:	srcinst - Name of package, which resides on the
1684*5c51f124SMoriah Waterland  *		device pointed to by the static 'srcdev' variable,
1685*5c51f124SMoriah Waterland  *		to dump.
1686*5c51f124SMoriah Waterland  *		bio - BIO object to dump data to
1687*5c51f124SMoriah Waterland  *
1688*5c51f124SMoriah Waterland  * Returns :   	0 - success
1689*5c51f124SMoriah Waterland  *		nonzero - failure.  errors printed to screen.
1690*5c51f124SMoriah Waterland  */
1691*5c51f124SMoriah Waterland static int
1692*5c51f124SMoriah Waterland pkgdump(char *srcinst, BIO *bio)
1693*5c51f124SMoriah Waterland {
1694*5c51f124SMoriah Waterland 	FILE	*fp;
1695*5c51f124SMoriah Waterland 	char	*src;
1696*5c51f124SMoriah Waterland 	char	temp[MAXPATHLEN],
1697*5c51f124SMoriah Waterland 		srcdir[MAXPATHLEN],
1698*5c51f124SMoriah Waterland 		cmd[CMDSIZE];
1699*5c51f124SMoriah Waterland 	int	i, n, part, nparts, maxpartsize, iscomp;
1700*5c51f124SMoriah Waterland 
1701*5c51f124SMoriah Waterland 	/*
1702*5c51f124SMoriah Waterland 	 * when this routine is entered, the entire package
1703*5c51f124SMoriah Waterland 	 * is already available at 'src' - including the
1704*5c51f124SMoriah Waterland 	 * pkginfo/pkgmap files and the objects as well.
1705*5c51f124SMoriah Waterland 	 */
1706*5c51f124SMoriah Waterland 
1707*5c51f124SMoriah Waterland 	/* read the pkgmap to get it's size information */
1708*5c51f124SMoriah Waterland 	if ((fp = fopen(PKGMAP, "r")) == NULL) {
1709*5c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
1710*5c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_NOPKGMAP), srcinst);
1711*5c51f124SMoriah Waterland 		return (1);
1712*5c51f124SMoriah Waterland 	}
1713*5c51f124SMoriah Waterland 
1714*5c51f124SMoriah Waterland 	nparts = 1;
1715*5c51f124SMoriah Waterland 	if (!rd_map_size(fp, &nparts, &maxpartsize, &compressedsize))
1716*5c51f124SMoriah Waterland 		return (1);
1717*5c51f124SMoriah Waterland 	else
1718*5c51f124SMoriah Waterland 		(void) fclose(fp);
1719*5c51f124SMoriah Waterland 
1720*5c51f124SMoriah Waterland 	/* make sure the first volume is available */
1721*5c51f124SMoriah Waterland 	if (srcdev.mount) {
1722*5c51f124SMoriah Waterland 		src = srcdev.dirname;
1723*5c51f124SMoriah Waterland 		(void) snprintf(srcdir, MAXPATHLEN, "%s/%s", src, srcinst);
1724*5c51f124SMoriah Waterland 		if (ckvolseq(srcdir, 1, nparts)) {
1725*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
1726*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_SEQUENCE));
1727*5c51f124SMoriah Waterland 			return (1);
1728*5c51f124SMoriah Waterland 		}
1729*5c51f124SMoriah Waterland 	}
1730*5c51f124SMoriah Waterland 
1731*5c51f124SMoriah Waterland 	/*
1732*5c51f124SMoriah Waterland 	 * form cpio command that will output the contents of all of
1733*5c51f124SMoriah Waterland 	 * this package's parts
1734*5c51f124SMoriah Waterland 	 */
1735*5c51f124SMoriah Waterland 	for (part = 1; part <= nparts; /* void */) {
1736*5c51f124SMoriah Waterland 
1737*5c51f124SMoriah Waterland 		if (part == 1) {
1738*5c51f124SMoriah Waterland 			(void) snprintf(cmd, CMDSIZE, "find %s %s",
1739*5c51f124SMoriah Waterland 			    PKGINFO, PKGMAP);
1740*5c51f124SMoriah Waterland 			if (nparts && (isdir(INSTALL) == 0)) {
1741*5c51f124SMoriah Waterland 				(void) strcat(cmd, " ");
1742*5c51f124SMoriah Waterland 				(void) strcat(cmd, INSTALL);
1743*5c51f124SMoriah Waterland 			}
1744*5c51f124SMoriah Waterland 		} else
1745*5c51f124SMoriah Waterland 			(void) snprintf(cmd, CMDSIZE, "find %s", PKGINFO);
1746*5c51f124SMoriah Waterland 
1747*5c51f124SMoriah Waterland 		if (nparts > 1) {
1748*5c51f124SMoriah Waterland 			(void) snprintf(temp, MAXPATHLEN, "%s.%d", RELOC, part);
1749*5c51f124SMoriah Waterland 			if (iscpio(temp, &iscomp) || isdir(temp) == 0) {
1750*5c51f124SMoriah Waterland 				(void) strlcat(cmd, " ", CMDSIZE);
1751*5c51f124SMoriah Waterland 				(void) strlcat(cmd, temp, CMDSIZE);
1752*5c51f124SMoriah Waterland 			}
1753*5c51f124SMoriah Waterland 			(void) snprintf(temp, MAXPATHLEN, "%s.%d", ROOT, part);
1754*5c51f124SMoriah Waterland 			if (iscpio(temp, &iscomp) || isdir(temp) == 0) {
1755*5c51f124SMoriah Waterland 				(void) strlcat(cmd, " ", CMDSIZE);
1756*5c51f124SMoriah Waterland 				(void) strlcat(cmd, temp, CMDSIZE);
1757*5c51f124SMoriah Waterland 			}
1758*5c51f124SMoriah Waterland 			(void) snprintf(temp, MAXPATHLEN, "%s.%d",
1759*5c51f124SMoriah Waterland 			    ARCHIVE, part);
1760*5c51f124SMoriah Waterland 			if (isdir(temp) == 0) {
1761*5c51f124SMoriah Waterland 				(void) strlcat(cmd, " ", CMDSIZE);
1762*5c51f124SMoriah Waterland 				(void) strlcat(cmd, temp, CMDSIZE);
1763*5c51f124SMoriah Waterland 			}
1764*5c51f124SMoriah Waterland 		} else if (nparts) {
1765*5c51f124SMoriah Waterland 			for (i = 0; reloc_names[i] != NULL; i++) {
1766*5c51f124SMoriah Waterland 				if (iscpio(reloc_names[i], &iscomp) ||
1767*5c51f124SMoriah Waterland 				    isdir(reloc_names[i]) == 0) {
1768*5c51f124SMoriah Waterland 					(void) strlcat(cmd, " ", CMDSIZE);
1769*5c51f124SMoriah Waterland 					(void) strlcat(cmd, reloc_names[i],
1770*5c51f124SMoriah Waterland 					    CMDSIZE);
1771*5c51f124SMoriah Waterland 				}
1772*5c51f124SMoriah Waterland 			}
1773*5c51f124SMoriah Waterland 			for (i = 0; root_names[i] != NULL; i++) {
1774*5c51f124SMoriah Waterland 				if (iscpio(root_names[i], &iscomp) ||
1775*5c51f124SMoriah Waterland 				    isdir(root_names[i]) == 0) {
1776*5c51f124SMoriah Waterland 					(void) strlcat(cmd, " ", CMDSIZE);
1777*5c51f124SMoriah Waterland 					(void) strlcat(cmd, root_names[i],
1778*5c51f124SMoriah Waterland 					    CMDSIZE);
1779*5c51f124SMoriah Waterland 				}
1780*5c51f124SMoriah Waterland 			}
1781*5c51f124SMoriah Waterland 			if (isdir(ARCHIVE) == 0) {
1782*5c51f124SMoriah Waterland 				(void) strlcat(cmd, " ", CMDSIZE);
1783*5c51f124SMoriah Waterland 				(void) strlcat(cmd, ARCHIVE, CMDSIZE);
1784*5c51f124SMoriah Waterland 			}
1785*5c51f124SMoriah Waterland 		}
1786*5c51f124SMoriah Waterland 
1787*5c51f124SMoriah Waterland #ifndef SUNOS41
1788*5c51f124SMoriah Waterland 		(void) sprintf(cmd+strlen(cmd),
1789*5c51f124SMoriah Waterland 		    " -print | %s -ocD -C %d",
1790*5c51f124SMoriah Waterland #else
1791*5c51f124SMoriah Waterland 		    (void) sprintf(cmd+strlen(cmd),
1792*5c51f124SMoriah Waterland 			" -print | %s -oc -C %d",
1793*5c51f124SMoriah Waterland #endif
1794*5c51f124SMoriah Waterland 			CPIOPROC, (int)BLK_SIZE);
1795*5c51f124SMoriah Waterland 		/*
1796*5c51f124SMoriah Waterland 		 * execute the command, dumping all standard output
1797*5c51f124SMoriah Waterland 		 * to the BIO.
1798*5c51f124SMoriah Waterland 		 */
1799*5c51f124SMoriah Waterland 		n = BIO_dump_cmd(cmd, bio);
1800*5c51f124SMoriah Waterland 		if (n != 0) {
1801*5c51f124SMoriah Waterland 			rpterr();
1802*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
1803*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_CMDFAIL), cmd, n);
1804*5c51f124SMoriah Waterland 			return (1);
1805*5c51f124SMoriah Waterland 		}
1806*5c51f124SMoriah Waterland 
1807*5c51f124SMoriah Waterland 		part++;
1808*5c51f124SMoriah Waterland 	}
1809*5c51f124SMoriah Waterland 	return (0);
1810*5c51f124SMoriah Waterland }
1811*5c51f124SMoriah Waterland 
1812*5c51f124SMoriah Waterland static void
1813*5c51f124SMoriah Waterland sigtrap(int signo)
1814*5c51f124SMoriah Waterland {
1815*5c51f124SMoriah Waterland 	signal_received++;
1816*5c51f124SMoriah Waterland }
1817*5c51f124SMoriah Waterland 
1818*5c51f124SMoriah Waterland static void
1819*5c51f124SMoriah Waterland cleanup(void)
1820*5c51f124SMoriah Waterland {
1821*5c51f124SMoriah Waterland 	chdir("/");
1822*5c51f124SMoriah Waterland 	if (tmpdir) {
1823*5c51f124SMoriah Waterland 		rrmdir(tmpdir);
1824*5c51f124SMoriah Waterland 		free(tmpdir);
1825*5c51f124SMoriah Waterland 		tmpdir = NULL;
1826*5c51f124SMoriah Waterland 	}
1827*5c51f124SMoriah Waterland 
1828*5c51f124SMoriah Waterland 	if (tmppath) {
1829*5c51f124SMoriah Waterland 		/* remove any previous tmppath stuff */
1830*5c51f124SMoriah Waterland 		rrmdir(tmppath);
1831*5c51f124SMoriah Waterland 		free(tmppath);
1832*5c51f124SMoriah Waterland 		tmppath = NULL;
1833*5c51f124SMoriah Waterland 	}
1834*5c51f124SMoriah Waterland 
1835*5c51f124SMoriah Waterland 	if (tmpsymdir) {
1836*5c51f124SMoriah Waterland 		/* remove temp symbolic links made for signed pkg */
1837*5c51f124SMoriah Waterland 		rrmdir(tmpsymdir);
1838*5c51f124SMoriah Waterland 		free(tmpsymdir);
1839*5c51f124SMoriah Waterland 		tmpsymdir = NULL;
1840*5c51f124SMoriah Waterland 	}
1841*5c51f124SMoriah Waterland 
1842*5c51f124SMoriah Waterland 	if (srcdev.mount && !ids_name)
1843*5c51f124SMoriah Waterland 		pkgumount(&srcdev);
1844*5c51f124SMoriah Waterland 	if (dstdev.mount && !ods_name)
1845*5c51f124SMoriah Waterland 		pkgumount(&dstdev);
1846*5c51f124SMoriah Waterland 	(void) ds_close(1);
1847*5c51f124SMoriah Waterland }
1848*5c51f124SMoriah Waterland 
1849*5c51f124SMoriah Waterland /*
1850*5c51f124SMoriah Waterland  * Name:		dump_hdr_and_pkgs
1851*5c51f124SMoriah Waterland  * Description:	Dumps datastream header and each package's contents
1852*5c51f124SMoriah Waterland  *		to the supplied BIO
1853*5c51f124SMoriah Waterland  *
1854*5c51f124SMoriah Waterland  * Arguments:	bio - BIO object to dump data to
1855*5c51f124SMoriah Waterland  *		hdr - Header for the datastream being dumped
1856*5c51f124SMoriah Waterland  *		pkglist - NULL-terminated list of packages
1857*5c51f124SMoriah Waterland  *		to dump.  The location of the packages are stored
1858*5c51f124SMoriah Waterland  *		in the static 'srcdev' variable.
1859*5c51f124SMoriah Waterland  *
1860*5c51f124SMoriah Waterland  * Returns :   	0 - success
1861*5c51f124SMoriah Waterland  *		nonzero - failure.  errors printed to screen.
1862*5c51f124SMoriah Waterland  */
1863*5c51f124SMoriah Waterland static int
1864*5c51f124SMoriah Waterland dump_hdr_and_pkgs(BIO *bio, struct dm_buf *hdr, char **pkglist)
1865*5c51f124SMoriah Waterland {
1866*5c51f124SMoriah Waterland 	int	block_cnt, i;
1867*5c51f124SMoriah Waterland 	char	srcdir[MAXPATHLEN];
1868*5c51f124SMoriah Waterland 	char	cwd[MAXPATHLEN + 1];
1869*5c51f124SMoriah Waterland 	char	*src;
1870*5c51f124SMoriah Waterland 
1871*5c51f124SMoriah Waterland 	/* write out the header to the signature stream */
1872*5c51f124SMoriah Waterland 	for (block_cnt = 0; block_cnt < hdr->allocation;
1873*5c51f124SMoriah Waterland 		block_cnt += BLK_SIZE) {
1874*5c51f124SMoriah Waterland 		BIO_write(bio, (hdr->text_buffer + block_cnt), BLK_SIZE);
1875*5c51f124SMoriah Waterland 	}
1876*5c51f124SMoriah Waterland 
1877*5c51f124SMoriah Waterland 	/* save current directory */
1878*5c51f124SMoriah Waterland 	if (getcwd(cwd, MAXPATHLEN + 1) == NULL) {
1879*5c51f124SMoriah Waterland 		logerr(pkg_gt(ERR_GETWD));
1880*5c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
1881*5c51f124SMoriah Waterland 		return (1);
1882*5c51f124SMoriah Waterland 	}
1883*5c51f124SMoriah Waterland 
1884*5c51f124SMoriah Waterland 	/* now write out each package's contents */
1885*5c51f124SMoriah Waterland 	for (i = 0; pkglist[i]; i++) {
1886*5c51f124SMoriah Waterland 		/*
1887*5c51f124SMoriah Waterland 		 * change to the source dir, so we can find and dump
1888*5c51f124SMoriah Waterland 		 * the package(s) bits into the BIO
1889*5c51f124SMoriah Waterland 		 *
1890*5c51f124SMoriah Waterland 		 */
1891*5c51f124SMoriah Waterland 		src = srcdev.dirname;
1892*5c51f124SMoriah Waterland 
1893*5c51f124SMoriah Waterland 		/* change to the package source directory */
1894*5c51f124SMoriah Waterland 		(void) snprintf(srcdir, MAXPATHLEN, "%s/%s", src, pkglist[i]);
1895*5c51f124SMoriah Waterland 		if (chdir(srcdir)) {
1896*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
1897*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_CHDIR), srcdir);
1898*5c51f124SMoriah Waterland 			return (1);
1899*5c51f124SMoriah Waterland 		}
1900*5c51f124SMoriah Waterland 
1901*5c51f124SMoriah Waterland 		if (pkgdump(pkglist[i], bio)) {
1902*5c51f124SMoriah Waterland 			pkglist[i] = NULL;
1903*5c51f124SMoriah Waterland 			return (1);
1904*5c51f124SMoriah Waterland 		}
1905*5c51f124SMoriah Waterland 	}
1906*5c51f124SMoriah Waterland 
1907*5c51f124SMoriah Waterland 	/* change back to directory we were in upon entering this routine */
1908*5c51f124SMoriah Waterland 	if (chdir(cwd)) {
1909*5c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_TRANSFER));
1910*5c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_CHDIR), cwd);
1911*5c51f124SMoriah Waterland 		return (1);
1912*5c51f124SMoriah Waterland 	}
1913*5c51f124SMoriah Waterland 
1914*5c51f124SMoriah Waterland 	return (0);
1915*5c51f124SMoriah Waterland }
1916*5c51f124SMoriah Waterland 
1917*5c51f124SMoriah Waterland /*
1918*5c51f124SMoriah Waterland  * Name:		BIO_dump_cmd
1919*5c51f124SMoriah Waterland  * Description:	Dump the output of invoking a command
1920*5c51f124SMoriah Waterland  *		to a BIO.
1921*5c51f124SMoriah Waterland  *
1922*5c51f124SMoriah Waterland  * Arguments:	cmd - Command to invoke
1923*5c51f124SMoriah Waterland  *		bio - BIO to dump output of command to
1924*5c51f124SMoriah Waterland  *		only 'stdout' is dumped.
1925*5c51f124SMoriah Waterland  * Returns :   	0 - success
1926*5c51f124SMoriah Waterland  *		nonzero - failure.  errors printed to screen.
1927*5c51f124SMoriah Waterland  */
1928*5c51f124SMoriah Waterland int
1929*5c51f124SMoriah Waterland BIO_dump_cmd(char *cmd, BIO *bio)
1930*5c51f124SMoriah Waterland {
1931*5c51f124SMoriah Waterland 	char	buf[BLK_SIZE];
1932*5c51f124SMoriah Waterland 	FILE	*fp;
1933*5c51f124SMoriah Waterland 	int	rc;
1934*5c51f124SMoriah Waterland 
1935*5c51f124SMoriah Waterland 	/* start up the process */
1936*5c51f124SMoriah Waterland 	if ((fp = epopen(cmd, "r")) == NULL) {
1937*5c51f124SMoriah Waterland 		rpterr();
1938*5c51f124SMoriah Waterland 		return (1);
1939*5c51f124SMoriah Waterland 	}
1940*5c51f124SMoriah Waterland 
1941*5c51f124SMoriah Waterland 	/* read output in chunks, transfer to BIO */
1942*5c51f124SMoriah Waterland 	while (fread(buf, BLK_SIZE, 1, fp) == 1) {
1943*5c51f124SMoriah Waterland 		if (BIO_write(bio, buf, BLK_SIZE) != BLK_SIZE) {
1944*5c51f124SMoriah Waterland 			sighold(SIGINT);
1945*5c51f124SMoriah Waterland 			sighold(SIGHUP);
1946*5c51f124SMoriah Waterland 			(void) epclose(fp);
1947*5c51f124SMoriah Waterland 			sigrelse(SIGINT);
1948*5c51f124SMoriah Waterland 			sigrelse(SIGHUP);
1949*5c51f124SMoriah Waterland 			rpterr();
1950*5c51f124SMoriah Waterland 			return (1);
1951*5c51f124SMoriah Waterland 		}
1952*5c51f124SMoriah Waterland 	}
1953*5c51f124SMoriah Waterland 
1954*5c51f124SMoriah Waterland 	/* done with stream, make sure no errors were encountered */
1955*5c51f124SMoriah Waterland 	if (ferror(fp)) {
1956*5c51f124SMoriah Waterland 		(void) epclose(fp);
1957*5c51f124SMoriah Waterland 		rpterr();
1958*5c51f124SMoriah Waterland 		return (1);
1959*5c51f124SMoriah Waterland 	}
1960*5c51f124SMoriah Waterland 
1961*5c51f124SMoriah Waterland 	/* done, close stream, report any errors */
1962*5c51f124SMoriah Waterland 	sighold(SIGINT);
1963*5c51f124SMoriah Waterland 	sighold(SIGHUP);
1964*5c51f124SMoriah Waterland 	rc = epclose(fp);
1965*5c51f124SMoriah Waterland 	sigrelse(SIGINT);
1966*5c51f124SMoriah Waterland 	sigrelse(SIGHUP);
1967*5c51f124SMoriah Waterland 	if (rc != 0) {
1968*5c51f124SMoriah Waterland 		rpterr();
1969*5c51f124SMoriah Waterland 		return (1);
1970*5c51f124SMoriah Waterland 	}
1971*5c51f124SMoriah Waterland 
1972*5c51f124SMoriah Waterland 	return (rc);
1973*5c51f124SMoriah Waterland }
1974