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