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