xref: /illumos-gate/usr/src/lib/libpkg/common/pkgtrans.c (revision 5f82aa32fbc5dc2c59bca6ff315f44a4c4c9ea86)
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 (c) 2017 Peter Tribble.
24  */
25 
26 /*
27  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
28  * Use is subject to license terms.
29  */
30 
31 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
32 /* All Rights Reserved */
33 
34 
35 
36 #include <stdio.h>
37 #include <errno.h>
38 #include <stdarg.h>
39 #include <limits.h>
40 #include <stdlib.h>
41 #include <unistd.h>
42 #include <fcntl.h>
43 #include <ctype.h>
44 #include <string.h>
45 #include <sys/types.h>
46 #include <sys/param.h>
47 #include <sys/stat.h>
48 #include <sys/statvfs.h>
49 #include <sys/sysmacros.h>
50 #include <dirent.h>
51 #include <signal.h>
52 #include <devmgmt.h>
53 #include <note.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 "pkglocale.h"
61 
62 extern char	*pkgdir; 		/* pkgparam.c */
63 
64 /* libadm.a */
65 extern char	*devattr(char *device, char *attribute);
66 extern char	*fpkginst(char *pkg, ...);
67 extern int	fpkginfo(struct pkginfo *info, char *pkginst);
68 extern int	getvol(char *device, char *label, int options, char *prompt);
69 extern int	_getvol(char *device, char *label, int options, char *prompt,
70 			char *norewind);
71 
72 /* dstream.c */
73 extern int	ds_ginit(char *device);
74 extern int	ds_close(int pkgendflg);
75 
76 #define	CPIOPROC	"/usr/bin/cpio"
77 
78 #define	CMDSIZE	512	/* command block size */
79 
80 #define	BLK_SIZE	512		/* size of logical block */
81 
82 #define	ENTRY_MAX	256 /* max size of entry for cpio cmd or header */
83 
84 #define	PKGINFO	"pkginfo"
85 #define	PKGMAP	"pkgmap"
86 #define	MAP_STAT_SIZE	60	/* 1st line of pkgmap (3 numbers & a : */
87 
88 #define	INSTALL	"install"
89 #define	RELOC	"reloc"
90 #define	ROOT	"root"
91 #define	ARCHIVE	"archive"
92 
93 static struct	pkgdev srcdev, dstdev;
94 static char	*tmpdir;
95 static char	*tmppath;
96 static char	*tmpsymdir = NULL;
97 static char	dstinst[NON_ABI_NAMELNGTH];
98 static char 	*ids_name, *ods_name;
99 static int	ds_volcnt;
100 static int	ds_volno;
101 static int	compressedsize, has_comp_size;
102 
103 static void	(*sigintHandler)();
104 static void	(*sighupHandler)();
105 static void	cleanup(void);
106 static void	sigtrap(int signo);
107 static int	rd_map_size(FILE *fp, int *npts, int *maxpsz, int *cmpsize);
108 
109 static int	cat_and_count(struct dm_buf *, char *);
110 
111 static int	ckoverwrite(char *dir, char *inst, int options);
112 static int	pkgxfer(char *srcinst, int options);
113 static int	wdsheader(struct dm_buf *, char *device, char **pkg);
114 static struct dm_buf	*genheader(char *, char **);
115 
116 extern int	ds_fd;	/* open file descriptor for data stream WHERE? */
117 
118 static char *root_names[] = {
119 	"root",
120 	"root.cpio",
121 	"root.Z",
122 	"root.cpio.Z",
123 	0
124 };
125 
126 static char *reloc_names[] = {
127 	"reloc",
128 	"reloc.cpio",
129 	"reloc.Z",
130 	"reloc.cpio.Z",
131 	0
132 };
133 
134 static int	signal_received = 0;
135 
136 char	**xpkg; 	/* array of transferred packages */
137 int	nxpkg;
138 
139 static	char *allpkg[] = {
140 	"all",
141 	NULL
142 };
143 
144 static struct dm_buf hdrbuf;
145 static char *pinput, *nextpinput;
146 
147 int
148 pkghead(char *device)
149 {
150 	char	*pt;
151 	int	n;
152 
153 	cleanup();
154 
155 
156 	if (device == NULL)
157 		return (0);
158 	else if ((device[0] == '/') && !isdir(device)) {
159 		pkgdir = device;
160 		return (0);
161 	} else if ((pt = devattr(device, "pathname")) != NULL && !isdir(pt)) {
162 		pkgdir = pt;
163 		return (0);
164 	}
165 
166 	/* check for datastream */
167 	if (n = pkgtrans(device, (char *)0, allpkg, PT_SILENT|PT_INFO_ONLY)) {
168 		cleanup();
169 		return (n);
170 	}
171 		/* pkgtrans has set pkgdir */
172 	return (0);
173 }
174 
175 static char *
176 mgets(char *buf, int size)
177 {
178 	nextpinput = strchr(pinput, '\n');
179 	if (nextpinput == NULL)
180 		return (0);
181 	*nextpinput = '\0';
182 	if ((int)strlen(pinput) > size)
183 		return (0);
184 	(void) strncpy(buf, pinput, strlen(pinput));
185 	buf[strlen(pinput)] = '\0';
186 	pinput = nextpinput + 1;
187 	return (buf);
188 }
189 /*
190  * Here we construct the package size summaries for the headers. The
191  * pkgmap file associated with fp must be rewound to the beginning of the
192  * file. Note that we read three values from pkgmap first line in order
193  * to get the *actual* size if this package is compressed.
194  * This returns
195  *	0 : error
196  *	2 : not a compressed package
197  *	3 : compressed package
198  * and sets has_comp_size to indicate whether or not this is a compressed
199  * package.
200  */
201 static int
202 rd_map_size(FILE *fp, int *npts, int *maxpsz, int *cmpsize)
203 {
204 	int n;
205 	char line_buffer[MAP_STAT_SIZE];
206 
207 	/* First read the null terminated first line */
208 	if (fgets(line_buffer, MAP_STAT_SIZE, fp) == NULL) {
209 		progerr(pkg_gt(ERR_TRANSFER));
210 		logerr(pkg_gt(MSG_NOSIZE));
211 		(void) fclose(fp);
212 		ecleanup();
213 		return (0);
214 	}
215 
216 	n = sscanf(line_buffer, ": %d %d %d", npts, maxpsz, cmpsize);
217 
218 	if (n == 3)		/* A valid compressed package entry */
219 		has_comp_size = 1;
220 	else if (n == 2)	/* A valid standard package entry */
221 		has_comp_size = 0;
222 	else {			/* invalid entry */
223 		progerr(pkg_gt(ERR_TRANSFER));
224 		logerr(pkg_gt(MSG_NOSIZE));
225 		(void) fclose(fp);
226 		ecleanup();
227 		return (0);
228 	}
229 
230 	return (n);
231 }
232 
233 /* will return 0, 1, 3, or 99 */
234 static int
235 _pkgtrans(char *device1, char *device2, char **pkg, int options)
236 {
237 	char			*src, *dst;
238 	int			errflg, i, n;
239 	struct			dm_buf *hdr;
240 
241 	if (signal_received > 0) {
242 		return (1);
243 	}
244 
245 	/* transfer spool to appropriate device */
246 	if (devtype(device1, &srcdev)) {
247 		progerr(pkg_gt(ERR_TRANSFER));
248 		logerr(pkg_gt(MSG_BADDEV), device1);
249 		return (1);
250 	}
251 	srcdev.rdonly++;
252 
253 	/* check for datastream */
254 	ids_name = NULL;
255 	if (srcdev.bdevice) {
256 		if (n = _getvol(srcdev.bdevice, NULL, NULL,
257 		    pkg_gt("Insert %v into %p."), srcdev.norewind)) {
258 			cleanup();
259 			if (n == 3)
260 				return (3);
261 			progerr(pkg_gt(ERR_TRANSFER));
262 			logerr(pkg_gt(MSG_GETVOL));
263 			return (1);
264 		}
265 		if (ds_readbuf(srcdev.cdevice))
266 			ids_name = srcdev.cdevice;
267 	}
268 
269 	if (srcdev.cdevice && !srcdev.bdevice)
270 		ids_name = srcdev.cdevice;
271 	else if (srcdev.pathname) {
272 		ids_name = srcdev.pathname;
273 		if (access(ids_name, 0) == -1) {
274 			progerr(ERR_TRANSFER);
275 			logerr(pkg_gt(MSG_GETVOL));
276 			return (1);
277 		}
278 	}
279 
280 	if (!ids_name && device2 == (char *)0) {
281 		if (n = pkgmount(&srcdev, NULL, 1, 0, 0)) {
282 			cleanup();
283 			return (n);
284 		}
285 		if (srcdev.mount && *srcdev.mount)
286 			pkgdir = strdup(srcdev.mount);
287 		return (0);
288 	}
289 
290 	if (ids_name && device2 == (char *)0) {
291 		tmppath = tmpnam(NULL);
292 		tmppath = strdup(tmppath);
293 		if (tmppath == NULL) {
294 			progerr(pkg_gt(ERR_TRANSFER));
295 			logerr(pkg_gt(MSG_MEM));
296 			return (1);
297 		}
298 		if (mkdir(tmppath, 0755)) {
299 			progerr(pkg_gt(ERR_TRANSFER));
300 			logerr(pkg_gt(MSG_MKDIR), tmppath);
301 			return (1);
302 		}
303 		device2 = tmppath;
304 	}
305 
306 	if (devtype(device2, &dstdev)) {
307 		progerr(pkg_gt(ERR_TRANSFER));
308 		logerr(pkg_gt(MSG_BADDEV), device2);
309 		return (1);
310 	}
311 
312 	if ((srcdev.cdevice && dstdev.cdevice) &&
313 	    strcmp(srcdev.cdevice, dstdev.cdevice) == 0) {
314 		progerr(pkg_gt(ERR_TRANSFER));
315 		logerr(pkg_gt(MSG_SAMEDEV));
316 		return (1);
317 	}
318 
319 	ods_name = NULL;
320 	if (dstdev.cdevice && !dstdev.bdevice || dstdev.pathname)
321 		options |= PT_ODTSTREAM;
322 
323 	if (options & PT_ODTSTREAM) {
324 		if (!((ods_name = dstdev.cdevice) != NULL ||
325 		    (ods_name = dstdev.pathname) != NULL)) {
326 			progerr(pkg_gt(ERR_TRANSFER));
327 			logerr(pkg_gt(MSG_BADDEV), device2);
328 			return (1);
329 		}
330 		if (ids_name) {
331 			progerr(pkg_gt(ERR_TRANSFER));
332 			logerr(pkg_gt(MSG_TWODSTREAM));
333 			return (1);
334 		}
335 	}
336 
337 	if ((srcdev.dirname && dstdev.dirname) &&
338 	    strcmp(srcdev.dirname, dstdev.dirname) == 0) {
339 		progerr(pkg_gt(ERR_TRANSFER));
340 		logerr(pkg_gt(MSG_SAMEDEV));
341 		return (1);
342 	}
343 
344 	if ((srcdev.pathname && dstdev.pathname) &&
345 	    strcmp(srcdev.pathname, dstdev.pathname) == 0) {
346 		progerr(pkg_gt(ERR_TRANSFER));
347 		logerr(pkg_gt(MSG_SAMEDEV));
348 		return (1);
349 	}
350 
351 	if (signal_received > 0) {
352 		return (1);
353 	}
354 
355 	if (ids_name) {
356 		if (srcdev.cdevice && !srcdev.bdevice &&
357 		(n = _getvol(srcdev.cdevice, NULL, NULL, NULL,
358 		    srcdev.norewind))) {
359 			cleanup();
360 			if (n == 3)
361 				return (3);
362 			progerr(pkg_gt(ERR_TRANSFER));
363 			logerr(pkg_gt(MSG_GETVOL));
364 			return (1);
365 		}
366 		if (srcdev.dirname = tmpnam(NULL))
367 			tmpdir = srcdev.dirname = strdup(srcdev.dirname);
368 
369 		if ((srcdev.dirname == NULL) || mkdir(srcdev.dirname, 0755) ||
370 		    chdir(srcdev.dirname)) {
371 			progerr(pkg_gt(ERR_TRANSFER));
372 			logerr(pkg_gt(MSG_NOTEMP), srcdev.dirname);
373 			cleanup();
374 			return (1);
375 		}
376 		if (ds_init(ids_name, pkg, srcdev.norewind)) {
377 			cleanup();
378 			return (1);
379 		}
380 	} else if (srcdev.mount) {
381 		if (n = pkgmount(&srcdev, NULL, 1, 0, 0)) {
382 			cleanup();
383 			return (n);
384 		}
385 	}
386 
387 	src = srcdev.dirname;
388 	dst = dstdev.dirname;
389 
390 	if (chdir(src)) {
391 		progerr(pkg_gt(ERR_TRANSFER));
392 		logerr(pkg_gt(MSG_CHDIR), src);
393 		cleanup();
394 		return (1);
395 	}
396 
397 	if (signal_received > 0) {
398 		return (1);
399 	}
400 
401 	xpkg = pkg = gpkglist(src, pkg, NULL);
402 	if (!pkg) {
403 		progerr(pkg_gt(ERR_TRANSFER));
404 		logerr(pkg_gt(MSG_NOPKGS), src);
405 		cleanup();
406 		return (1);
407 	}
408 
409 	for (nxpkg = 0; pkg[nxpkg]; /* void */) {
410 		nxpkg++; /* count */
411 	}
412 
413 	if (ids_name) {
414 		ds_order(pkg); /* order requests */
415 	}
416 
417 	if (signal_received > 0) {
418 		return (1);
419 	}
420 
421 	if (options & PT_ODTSTREAM) {
422 		char line[128];
423 
424 		if (!dstdev.pathname &&
425 		    (n = _getvol(ods_name, NULL, DM_FORMAT, NULL,
426 		    dstdev.norewind))) {
427 			cleanup();
428 			if (n == 3)
429 				return (3);
430 			progerr(pkg_gt(ERR_TRANSFER));
431 			logerr(pkg_gt(MSG_GETVOL));
432 			return (1);
433 		}
434 		if ((hdr = genheader(src, pkg)) == NULL) {
435 			cleanup();
436 			return (1);
437 		}
438 
439 		/* write out header to stream */
440 		if (wdsheader(hdr, ods_name, pkg)) {
441 			cleanup();
442 			return (1);
443 		}
444 
445 		ds_volno = 1; /* number of volumes in datastream */
446 		pinput = hdrbuf.text_buffer;
447 		/* skip past first line in header */
448 		(void) mgets(line, 128);
449 	}
450 
451 	if (signal_received > 0) {
452 		return (1);
453 	}
454 
455 	errflg = 0;
456 
457 	for (i = 0; pkg[i]; i++) {
458 
459 		if (signal_received > 0) {
460 			return (1);
461 		}
462 
463 		if (!(options & PT_ODTSTREAM) && dstdev.mount) {
464 			if (n = pkgmount(&dstdev, NULL, 0, 0, 1)) {
465 				cleanup();
466 				return (n);
467 			}
468 		}
469 		if (errflg = pkgxfer(pkg[i], options)) {
470 			pkg[i] = NULL;
471 			if ((options & PT_ODTSTREAM) || (errflg != 2))
472 				break;
473 		} else if (strcmp(dstinst, pkg[i]))
474 			pkg[i] = strdup(dstinst);
475 	}
476 
477 	if (!(options & PT_ODTSTREAM) && dst) {
478 		pkgdir = strdup(dst);
479 	}
480 
481 	/*
482 	 * No cleanup of temporary directories created in this
483 	 * function is done here. The calling function must do
484 	 * the cleanup.
485 	 */
486 
487 	return (signal_received > 0 ? 1 : errflg);
488 }
489 
490 int
491 pkgtrans(char *device1, char *device2, char **pkg, int options)
492 {
493 	int			r;
494 	struct sigaction	nact;
495 	struct sigaction	oact;
496 
497 	/*
498 	 * setup signal handlers for SIGINT and SIGHUP and release hold
499 	 */
500 
501 	/* hold SIGINT/SIGHUP interrupts */
502 
503 	(void) sighold(SIGHUP);
504 	(void) sighold(SIGINT);
505 
506 	/* hook SIGINT to sigtrap */
507 
508 	nact.sa_handler = sigtrap;
509 	nact.sa_flags = SA_RESTART;
510 	(void) sigemptyset(&nact.sa_mask);
511 
512 	if (sigaction(SIGINT, &nact, &oact) < 0) {
513 		sigintHandler = SIG_DFL;
514 	} else {
515 		sigintHandler = oact.sa_handler;
516 	}
517 
518 	/* hook SIGHUP to sigtrap */
519 
520 	nact.sa_handler = sigtrap;
521 	nact.sa_flags = SA_RESTART;
522 	(void) sigemptyset(&nact.sa_mask);
523 
524 	if (sigaction(SIGHUP, &nact, &oact) < 0) {
525 		sighupHandler = SIG_DFL;
526 	} else {
527 		sighupHandler = oact.sa_handler;
528 	}
529 
530 	/* reset signal received count */
531 
532 	signal_received = 0;
533 
534 	/* release hold on signals */
535 
536 	(void) sigrelse(SIGHUP);
537 	(void) sigrelse(SIGINT);
538 
539 	/*
540 	 * perform the package translation
541 	 */
542 
543 	r = _pkgtrans(device1, device2, pkg, options);
544 
545 	/*
546 	 * reset signal handlers
547 	 */
548 
549 	/* hold SIGINT/SIGHUP interrupts */
550 
551 	(void) sighold(SIGHUP);
552 	(void) sighold(SIGINT);
553 
554 	/* reset SIGINT */
555 
556 	nact.sa_handler = sigintHandler;
557 	nact.sa_flags = SA_RESTART;
558 	(void) sigemptyset(&nact.sa_mask);
559 
560 	(void) sigaction(SIGINT, &nact, (struct sigaction *)NULL);
561 
562 	/* reset SIGHUP */
563 
564 	nact.sa_handler = sighupHandler;
565 	nact.sa_flags = SA_RESTART;
566 	(void) sigemptyset(&nact.sa_mask);
567 
568 	(void) sigaction(SIGHUP, &nact, (struct sigaction *)NULL);
569 
570 	/* if signal received and pkgtrans returned error, call cleanup */
571 
572 	if (signal_received > 0) {
573 		if (r != 0) {
574 			cleanup();
575 		}
576 		(void) kill(getpid(), SIGINT);
577 	}
578 
579 	/* release hold on signals */
580 
581 	(void) sigrelse(SIGHUP);
582 	(void) sigrelse(SIGINT);
583 
584 	return (r);
585 }
586 
587 /*
588  * This function concatenates append to the text described in the buf_ctrl
589  * structure. This code modifies data in this structure and handles all
590  * allocation issues. It returns '0' if everything was successful and '1'
591  * if not.
592  */
593 static int
594 cat_and_count(struct dm_buf *buf_ctrl, char *append)
595 {
596 
597 	/* keep allocating until we have enough room to hold string */
598 	while ((buf_ctrl->offset + (int)strlen(append))
599 	    >= buf_ctrl->allocation) {
600 		/* reallocate (and maybe move) text buffer */
601 		if ((buf_ctrl->text_buffer =
602 		    (char *)realloc(buf_ctrl->text_buffer,
603 		    buf_ctrl->allocation + BLK_SIZE)) == NULL) {
604 			progerr(pkg_gt(ERR_TRANSFER));
605 			logerr(pkg_gt(MSG_MEM));
606 			free(buf_ctrl->text_buffer);
607 			return (1);
608 		}
609 
610 		/* clear the new memory */
611 		(void) memset(buf_ctrl->text_buffer +
612 		    buf_ctrl->allocation, '\0', BLK_SIZE);
613 
614 		/* adjust total allocation */
615 		buf_ctrl->allocation += BLK_SIZE;
616 	}
617 
618 	/* append new string to end of buffer */
619 	while (*append) {
620 		*(buf_ctrl->text_buffer + buf_ctrl->offset) = *append++;
621 		(buf_ctrl->offset)++;
622 	}
623 
624 	return (0);
625 }
626 
627 static struct dm_buf *
628 genheader(char *src, char **pkg)
629 {
630 
631 	FILE	*fp;
632 	char	path[MAXPATHLEN], tmp_entry[ENTRY_MAX];
633 	int	i, n, nparts, maxpsize;
634 	int	partcnt;
635 	long	totsize;
636 	struct stat statbuf;
637 
638 	if ((hdrbuf.text_buffer = (char *)malloc(BLK_SIZE)) == NULL) {
639 		progerr(pkg_gt(ERR_TRANSFER));
640 		logerr(pkg_gt(MSG_MEM));
641 		return (NULL);
642 	}
643 
644 	/* clear the new memory */
645 	(void) memset(hdrbuf.text_buffer, '\0', BLK_SIZE);
646 
647 	/* set up the buffer control structure for the header */
648 	hdrbuf.offset = 0;
649 	hdrbuf.allocation = BLK_SIZE;
650 
651 	(void) cat_and_count(&hdrbuf, HDR_PREFIX);
652 	(void) cat_and_count(&hdrbuf, "\n");
653 
654 	nparts = maxpsize = 0;
655 
656 	totsize = 0;
657 	for (i = 0; pkg[i]; i++)  {
658 		(void) snprintf(path, MAXPATHLEN, "%s/%s/%s",
659 		    src, pkg[i], PKGINFO);
660 		if (stat(path, &statbuf) < 0) {
661 			progerr(pkg_gt(ERR_TRANSFER));
662 			logerr(pkg_gt(MSG_BADPKGINFO));
663 			ecleanup();
664 			return (NULL);
665 		}
666 		totsize += statbuf.st_size/BLK_SIZE + 1;
667 	}
668 
669 	/*
670 	 * totsize contains number of blocks used by the pkginfo files
671 	 */
672 	totsize += i/4 + 1;
673 	if (dstdev.capacity && totsize > dstdev.capacity) {
674 		progerr(pkg_gt(ERR_TRANSFER));
675 		logerr(pkg_gt(MSG_NOSPACE), totsize, dstdev.capacity);
676 		ecleanup();
677 		return (NULL);
678 	}
679 
680 	ds_volcnt = 1;
681 	for (i = 0; pkg[i]; i++) {
682 		partcnt = 0;
683 		(void) snprintf(path, MAXPATHLEN, "%s/%s/%s",
684 		    src, pkg[i], PKGMAP);
685 		if ((fp = fopen(path, "r")) == NULL) {
686 			progerr(pkg_gt(ERR_TRANSFER));
687 			logerr(pkg_gt(MSG_NOPKGMAP), pkg[i]);
688 			ecleanup();
689 			return (NULL);
690 		}
691 
692 		/* Evaluate the first entry in pkgmap */
693 		n = rd_map_size(fp, &nparts, &maxpsize, &compressedsize);
694 
695 		if (n == 3)	/* It's a compressed package */
696 			/* The header needs the *real* size */
697 			maxpsize = compressedsize;
698 		else if (n == 0)	/* pkgmap is corrupt */
699 			return (NULL);
700 
701 		if (dstdev.capacity && maxpsize > dstdev.capacity) {
702 			progerr(pkg_gt(ERR_TRANSFER));
703 			logerr(pkg_gt(MSG_NOSPACE), (long)maxpsize,
704 			    dstdev.capacity);
705 			(void) fclose(fp);
706 			ecleanup();
707 			return (NULL);
708 		}
709 
710 		/* add pkg name, number of parts and the max part size */
711 		if (snprintf(tmp_entry, ENTRY_MAX, "%s %d %d",
712 				pkg[i], nparts, maxpsize) >= ENTRY_MAX) {
713 			progerr(pkg_gt(ERR_TRANSFER));
714 			logerr(pkg_gt(ERR_MEM));
715 			(void) fclose(fp);
716 			ecleanup();
717 			return (NULL);
718 		}
719 		if (cat_and_count(&hdrbuf, tmp_entry)) {
720 			progerr(pkg_gt(ERR_TRANSFER));
721 			logerr(pkg_gt(MSG_MEM));
722 			(void) fclose(fp);
723 			ecleanup();
724 			return (NULL);
725 		}
726 
727 		totsize += nparts * maxpsize;
728 		if (dstdev.capacity && dstdev.capacity < totsize) {
729 			int lastpartcnt = 0;
730 
731 			if (totsize)
732 				totsize -= nparts * maxpsize;
733 			while (partcnt < nparts) {
734 				while (totsize <= dstdev.capacity &&
735 				    partcnt <= nparts) {
736 					totsize +=  maxpsize;
737 					partcnt++;
738 				}
739 				/* partcnt == 0 means skip to next volume */
740 				if (partcnt)
741 					partcnt--;
742 				(void) snprintf(tmp_entry, ENTRY_MAX,
743 				    " %d", partcnt - lastpartcnt);
744 				if (cat_and_count(&hdrbuf, tmp_entry)) {
745 					progerr(pkg_gt(ERR_TRANSFER));
746 					logerr(pkg_gt(MSG_MEM));
747 					(void) fclose(fp);
748 					ecleanup();
749 					return (NULL);
750 				}
751 				ds_volcnt++;
752 				totsize = 0;
753 				lastpartcnt = partcnt;
754 			}
755 			/* first parts/volume number does not count */
756 			ds_volcnt--;
757 		}
758 
759 		if (cat_and_count(&hdrbuf, "\n")) {
760 			progerr(pkg_gt(ERR_TRANSFER));
761 			logerr(pkg_gt(MSG_MEM));
762 			(void) fclose(fp);
763 			ecleanup();
764 			return (NULL);
765 		}
766 
767 		(void) fclose(fp);
768 	}
769 
770 	if (cat_and_count(&hdrbuf, HDR_SUFFIX) ||
771 	    cat_and_count(&hdrbuf, "\n")) {
772 		progerr(pkg_gt(ERR_TRANSFER));
773 		logerr(pkg_gt(MSG_MEM));
774 		(void) fclose(fp);
775 		ecleanup();
776 		return (NULL);
777 	}
778 	return (&hdrbuf);
779 }
780 
781 static int
782 wdsheader(struct dm_buf *hdr, char *device, char **pkg)
783 {
784 	char	tmp_entry[ENTRY_MAX], tmp_file[L_tmpnam+1];
785 	int	i, n;
786 	int	list_fd;
787 	int	block_cnt;
788 
789 	(void) ds_close(0);
790 	if (dstdev.pathname)
791 		ds_fd = creat(device, 0644);
792 	else
793 		ds_fd = open(device, 1);
794 
795 	if (ds_fd < 0) {
796 		progerr(pkg_gt(ERR_TRANSFER));
797 		logerr(pkg_gt(MSG_OPEN), device, errno);
798 		return (1);
799 	}
800 
801 	if (ds_ginit(device) < 0) {
802 		progerr(pkg_gt(ERR_TRANSFER));
803 		logerr(pkg_gt(MSG_OPEN), device, errno);
804 		(void) ds_close(0);
805 		return (1);
806 	}
807 
808 	/*
809 	 * The loop below assures compatibility with tapes that don't
810 	 * have a block size (e.g.: Exabyte) by forcing EOR at the end
811 	 * of each 512 bytes.
812 	 */
813 	for (block_cnt = 0; block_cnt < hdr->allocation;
814 		block_cnt += BLK_SIZE) {
815 		(void) write(ds_fd, (hdr->text_buffer + block_cnt), BLK_SIZE);
816 	}
817 
818 	/*
819 	 * write the first cpio() archive to the datastream
820 	 * which should contain the pkginfo & pkgmap files
821 	 * for all packages
822 	 */
823 	(void) tmpnam(tmp_file);	/* temporary file name */
824 	if ((list_fd = open(tmp_file, O_RDWR | O_CREAT, 0644)) == -1) {
825 		progerr(pkg_gt(ERR_TRANSFER));
826 		logerr(pkg_gt(MSG_NOTMPFIL), tmp_file);
827 		return (1);
828 	}
829 
830 	/*
831 	 * Create a cpio-compatible list of the requisite files in
832 	 * the temporary file.
833 	 */
834 	for (i = 0; pkg[i]; i++) {
835 		register ssize_t entry_size;
836 
837 		/*
838 		 * Copy pkginfo and pkgmap filenames into the
839 		 * temporary string allowing for the first line
840 		 * as a special case.
841 		 */
842 		entry_size = sprintf(tmp_entry,
843 		    (i == 0) ? "%s/%s\n%s/%s" : "\n%s/%s\n%s/%s",
844 		    pkg[i], PKGINFO, pkg[i], PKGMAP);
845 
846 		if (write(list_fd, tmp_entry,
847 		    entry_size) != entry_size) {
848 			progerr(pkg_gt(ERR_TRANSFER));
849 			logerr(pkg_gt(MSG_NOTMPFIL), tmp_file);
850 			(void) close(list_fd);
851 			ecleanup();
852 			return (1);
853 		}
854 	}
855 
856 	(void) lseek(list_fd, 0, SEEK_SET);
857 
858 	(void) snprintf(tmp_entry, sizeof (tmp_entry),
859 	    "%s -ocD -C %d", CPIOPROC, (int)BLK_SIZE);
860 
861 	if (n = esystem(tmp_entry, list_fd, ds_fd)) {
862 		rpterr();
863 		progerr(pkg_gt(ERR_TRANSFER));
864 		logerr(pkg_gt(MSG_CMDFAIL), tmp_entry, n);
865 		(void) close(list_fd);
866 		(void) unlink(tmp_file);
867 		cleanup();
868 		return (1);
869 	}
870 
871 	(void) close(list_fd);
872 	(void) unlink(tmp_file);
873 
874 	return (0);
875 }
876 
877 static int
878 ckoverwrite(char *dir, char *inst, int options)
879 {
880 	char	path[PATH_MAX];
881 
882 	(void) snprintf(path, sizeof (path), "%s/%s", dir, inst);
883 	if (access(path, 0) == 0) {
884 		if (options & PT_OVERWRITE)
885 			return (rrmdir(path));
886 		progerr(pkg_gt(ERR_TRANSFER));
887 		logerr(pkg_gt(MSG_EXISTS), path);
888 		return (1);
889 	}
890 	return (0);
891 }
892 
893 static int
894 pkgxfer(char *srcinst, int options)
895 {
896 	int	r;
897 	struct pkginfo info;
898 	FILE	*fp, *pp;
899 	char	*pt, *src, *dst;
900 	char	dstdir[PATH_MAX],
901 		temp[PATH_MAX],
902 		srcdir[PATH_MAX],
903 		cmd[CMDSIZE],
904 		pkgname[NON_ABI_NAMELNGTH];
905 	int	i, n, part, nparts, maxpartsize, curpartcnt, iscomp;
906 	char	volnos[128], tmpvol[128];
907 	struct	statvfs64 svfsb;
908 	longlong_t free_blocks;
909 	struct	stat	srcstat;
910 
911 	info.pkginst = NULL; /* required initialization */
912 
913 	/*
914 	 * when this routine is entered, the first part of
915 	 * the package to transfer is already available in
916 	 * the directory indicated by 'src' --- unless the
917 	 * source device is a datstream, in which case only
918 	 * the pkginfo and pkgmap files are available in 'src'
919 	 */
920 	src = srcdev.dirname;
921 	dst = dstdev.dirname;
922 
923 	if (!(options & PT_SILENT))
924 		(void) fprintf(stderr, pkg_gt(MSG_TRANSFER), srcinst);
925 	(void) strlcpy(dstinst, srcinst, sizeof (dstinst));
926 
927 	if (!(options & PT_ODTSTREAM)) {
928 		/* destination is a (possibly mounted) directory */
929 		(void) snprintf(dstdir, sizeof (dstdir),
930 		    "%s/%s", dst, dstinst);
931 
932 		/*
933 		 * need to check destination directory to assure
934 		 * that we will not be duplicating a package which
935 		 * already resides there (though we are allowed to
936 		 * overwrite the same version)
937 		 */
938 		pkgdir = src;
939 		if (fpkginfo(&info, srcinst)) {
940 			progerr(pkg_gt(ERR_TRANSFER));
941 			logerr(pkg_gt(MSG_NOEXISTS), srcinst);
942 			(void) fpkginfo(&info, NULL);
943 			return (1);
944 		}
945 		pkgdir = dst;
946 
947 		(void) strlcpy(temp, srcinst, sizeof (temp));
948 		if (pt = strchr(temp, '.'))
949 			*pt = '\0';
950 		(void) strlcat(temp, ".*", sizeof (temp));
951 
952 		if (pt = fpkginst(temp, info.arch, info.version)) {
953 			/*
954 			 * the same instance already exists, although
955 			 * its pkgid might be different
956 			 */
957 			if (options & PT_OVERWRITE) {
958 				(void) strlcpy(dstinst, pt, sizeof (dstinst));
959 				(void) snprintf(dstdir, sizeof (dstdir),
960 				    "%s/%s", dst, dstinst);
961 			} else {
962 				progerr(pkg_gt(ERR_TRANSFER));
963 				logerr(pkg_gt(MSG_DUPVERS), srcinst);
964 				(void) fpkginfo(&info, NULL);
965 				(void) fpkginst(NULL);
966 				return (2);
967 			}
968 		} else if (options & PT_RENAME) {
969 			/*
970 			 * find next available instance by appending numbers
971 			 * to the package abbreviation until the instance
972 			 * does not exist in the destination directory
973 			 */
974 			if (pt = strchr(temp, '.'))
975 				*pt = '\0';
976 			for (i = 2; (access(dstdir, 0) == 0); i++) {
977 				(void) snprintf(dstinst, sizeof (dstinst),
978 				    "%s.%d", temp, i);
979 				(void) snprintf(dstdir, sizeof (dstdir),
980 				    "%s/%s", dst, dstinst);
981 			}
982 		} else if (options & PT_OVERWRITE) {
983 			/*
984 			 * we're allowed to overwrite, but there seems
985 			 * to be no valid package to overwrite, and we are
986 			 * not allowed to rename the destination, so act
987 			 * as if we weren't given permission to overwrite
988 			 * --- this keeps us from removing a destination
989 			 * instance which is named the same as the source
990 			 * instance, but really reflects a different pkg!
991 			 */
992 			options &= (~PT_OVERWRITE);
993 		}
994 		(void) fpkginfo(&info, NULL);
995 		(void) fpkginst(NULL);
996 
997 		if (ckoverwrite(dst, dstinst, options))
998 			return (2);
999 
1000 		if (isdir(dstdir) && mkdir(dstdir, 0755)) {
1001 			progerr(pkg_gt(ERR_TRANSFER));
1002 			logerr(pkg_gt(MSG_MKDIR), dstdir);
1003 			return (1);
1004 		}
1005 
1006 		(void) snprintf(srcdir, sizeof (srcdir),
1007 		    "%s/%s", src, srcinst);
1008 		if (stat(srcdir, &srcstat) != -1) {
1009 			if (chmod(dstdir, (srcstat.st_mode & S_IAMB)) == -1) {
1010 				progerr(pkg_gt(ERR_TRANSFER));
1011 				logerr(pkg_gt(MSG_CHMODDIR), dstdir);
1012 				return (1);
1013 			}
1014 		} else {
1015 			progerr(pkg_gt(ERR_TRANSFER));
1016 			logerr(pkg_gt(MSG_STATDIR), srcdir);
1017 			return (1);
1018 		}
1019 	}
1020 
1021 	if (!(options & PT_SILENT) && strcmp(dstinst, srcinst))
1022 		(void) fprintf(stderr, pkg_gt(MSG_RENAME), dstinst);
1023 
1024 	(void) snprintf(srcdir, sizeof (srcdir), "%s/%s", src, srcinst);
1025 	if (chdir(srcdir)) {
1026 		progerr(pkg_gt(ERR_TRANSFER));
1027 		logerr(pkg_gt(MSG_CHDIR), srcdir);
1028 		return (1);
1029 	}
1030 
1031 	if (ids_name) {	/* unpack the datatstream into a directory */
1032 		/*
1033 		 * transfer pkginfo & pkgmap first
1034 		 */
1035 		(void) snprintf(cmd, sizeof (cmd),
1036 		    "%s -pudm %s", CPIOPROC, dstdir);
1037 		if ((pp = epopen(cmd, "w")) == NULL) {
1038 			rpterr();
1039 			progerr(pkg_gt(ERR_TRANSFER));
1040 			logerr(pkg_gt(MSG_POPEN), cmd, errno);
1041 			return (1);
1042 		}
1043 		(void) fprintf(pp, "%s\n%s\n", PKGINFO, PKGMAP);
1044 
1045 		(void) sighold(SIGINT);
1046 		(void) sighold(SIGHUP);
1047 		r = epclose(pp);
1048 		(void) sigrelse(SIGINT);
1049 		(void) sigrelse(SIGHUP);
1050 
1051 		if (r != 0) {
1052 			rpterr();
1053 			progerr(pkg_gt(ERR_TRANSFER));
1054 			logerr(pkg_gt(MSG_PCLOSE), cmd, errno);
1055 			return (1);
1056 		}
1057 
1058 		if (options & PT_INFO_ONLY)
1059 			return (0); /* don't transfer objects */
1060 
1061 		if (chdir(dstdir)) {
1062 			progerr(pkg_gt(ERR_TRANSFER));
1063 			logerr(pkg_gt(MSG_CHDIR), dstdir);
1064 			return (1);
1065 		}
1066 
1067 		/*
1068 		 * for each part of the package, use cpio() to
1069 		 * unpack the archive into the destination directory
1070 		 */
1071 		nparts = ds_findpkg(srcdev.cdevice, srcinst);
1072 		if (nparts < 0) {
1073 			progerr(pkg_gt(ERR_TRANSFER));
1074 			return (1);
1075 		}
1076 		for (part = 1; part <= nparts; /* void */) {
1077 			if (ds_getpkg(srcdev.cdevice, part, dstdir)) {
1078 				progerr(pkg_gt(ERR_TRANSFER));
1079 				return (1);
1080 			}
1081 			part++;
1082 			if (dstdev.mount) {
1083 				(void) chdir("/");
1084 				if (pkgumount(&dstdev))
1085 					return (1);
1086 				if (part <= nparts) {
1087 					if (n = pkgmount(&dstdev, NULL, part+1,
1088 					    nparts, 1))
1089 						return (n);
1090 					if (ckoverwrite(dst, dstinst, options))
1091 						return (1);
1092 					if (isdir(dstdir) &&
1093 					    mkdir(dstdir, 0755)) {
1094 						progerr(
1095 						    pkg_gt(ERR_TRANSFER));
1096 						logerr(pkg_gt(MSG_MKDIR),
1097 						    dstdir);
1098 						return (1);
1099 					}
1100 					/*
1101 					 * since volume is removable, each part
1102 					 * must contain a duplicate of the
1103 					 * pkginfo file to properly identify the
1104 					 * volume
1105 					 */
1106 					if (chdir(srcdir)) {
1107 						progerr(
1108 						    pkg_gt(ERR_TRANSFER));
1109 						logerr(pkg_gt(MSG_CHDIR),
1110 						    srcdir);
1111 						return (1);
1112 					}
1113 					if ((pp = epopen(cmd, "w")) == NULL) {
1114 						rpterr();
1115 						progerr(
1116 						    pkg_gt(ERR_TRANSFER));
1117 						logerr(pkg_gt(MSG_POPEN),
1118 						    cmd, errno);
1119 						return (1);
1120 					}
1121 					(void) fprintf(pp, "pkginfo");
1122 
1123 					(void) sighold(SIGINT);
1124 					(void) sighold(SIGHUP);
1125 					r = epclose(pp);
1126 					(void) sigrelse(SIGINT);
1127 					(void) sigrelse(SIGHUP);
1128 
1129 					if (r != 0) {
1130 						rpterr();
1131 						progerr(
1132 						    pkg_gt(ERR_TRANSFER));
1133 						logerr(pkg_gt(MSG_PCLOSE),
1134 						    cmd, errno);
1135 						return (1);
1136 					}
1137 					if (chdir(dstdir)) {
1138 						progerr(
1139 						    pkg_gt(ERR_TRANSFER));
1140 						logerr(pkg_gt(MSG_CHDIR),
1141 						    dstdir);
1142 						return (1);
1143 					}
1144 				}
1145 			}
1146 		}
1147 		return (0);
1148 	}
1149 
1150 	if ((fp = fopen(PKGMAP, "r")) == NULL) {
1151 		progerr(pkg_gt(ERR_TRANSFER));
1152 		logerr(pkg_gt(MSG_NOPKGMAP), srcinst);
1153 		return (1);
1154 	}
1155 
1156 	nparts = 1;
1157 	if (!rd_map_size(fp, &nparts, &maxpartsize, &compressedsize))
1158 		return (1);
1159 	else
1160 		(void) fclose(fp);
1161 
1162 	if (srcdev.mount) {
1163 		if (ckvolseq(srcdir, 1, nparts)) {
1164 			progerr(pkg_gt(ERR_TRANSFER));
1165 			logerr(pkg_gt(MSG_SEQUENCE));
1166 			return (1);
1167 		}
1168 	}
1169 
1170 	/* write each part of this package */
1171 	if (options & PT_ODTSTREAM) {
1172 		char line[128];
1173 		(void) mgets(line, 128);
1174 		curpartcnt = -1;
1175 		/* LINTED E_SEC_SCANF_UNBOUNDED_COPY */
1176 		if (sscanf(line, "%s %d %d %[ 0-9]", pkgname, &nparts,
1177 		    &maxpartsize, volnos) == 4) {
1178 			(void) sscanf(volnos,
1179 			    "%d %[ 0-9]", &curpartcnt, tmpvol);
1180 			(void) strlcpy(volnos, tmpvol, sizeof (volnos));
1181 		}
1182 	}
1183 
1184 	for (part = 1; part <= nparts; /* void */) {
1185 		if (curpartcnt == 0 && (options & PT_ODTSTREAM)) {
1186 			char prompt[128];
1187 			int index;
1188 			ds_volno++;
1189 			(void) ds_close(0);
1190 			(void) sprintf(prompt,
1191 			    pkg_gt("Insert %%v %d of %d into %%p"),
1192 			    ds_volno, ds_volcnt);
1193 			if (n = getvol(ods_name, NULL, DM_FORMAT, prompt))
1194 				return (n);
1195 			if ((ds_fd = open(dstdev.cdevice, O_WRONLY)) < 0) {
1196 				progerr(pkg_gt(ERR_TRANSFER));
1197 				logerr(pkg_gt(MSG_OPEN), dstdev.cdevice,
1198 				    errno);
1199 				return (1);
1200 			}
1201 			if (ds_ginit(dstdev.cdevice) < 0) {
1202 				progerr(pkg_gt(ERR_TRANSFER));
1203 				logerr(pkg_gt(MSG_OPEN), dstdev.cdevice,
1204 				    errno);
1205 				(void) ds_close(0);
1206 				return (1);
1207 			}
1208 
1209 			(void) sscanf(volnos, "%d %[ 0-9]", &index, tmpvol);
1210 			(void) strlcpy(volnos, tmpvol, sizeof (volnos));
1211 			curpartcnt += index;
1212 		}
1213 
1214 		if (options & PT_INFO_ONLY)
1215 			nparts = 0;
1216 
1217 		if (part == 1) {
1218 			(void) snprintf(cmd, sizeof (cmd),
1219 			    "find %s %s", PKGINFO, PKGMAP);
1220 			if (nparts && (isdir(INSTALL) == 0)) {
1221 				(void) strlcat(cmd, " ", sizeof (cmd));
1222 				(void) strlcat(cmd, INSTALL, sizeof (cmd));
1223 			}
1224 		} else
1225 			(void) snprintf(cmd, sizeof (cmd), "find %s", PKGINFO);
1226 
1227 		if (nparts > 1) {
1228 			(void) snprintf(temp, sizeof (temp),
1229 			    "%s.%d", RELOC, part);
1230 			if (iscpio(temp, &iscomp) || isdir(temp) == 0) {
1231 				(void) strlcat(cmd, " ", sizeof (cmd));
1232 				(void) strlcat(cmd, temp, sizeof (cmd));
1233 			}
1234 			(void) snprintf(temp, sizeof (temp),
1235 			    "%s.%d", ROOT, part);
1236 			if (iscpio(temp, &iscomp) || isdir(temp) == 0) {
1237 				(void) strlcat(cmd, " ", sizeof (cmd));
1238 				(void) strlcat(cmd, temp, sizeof (cmd));
1239 			}
1240 			(void) snprintf(temp, sizeof (temp),
1241 			    "%s.%d", ARCHIVE, part);
1242 			if (isdir(temp) == 0) {
1243 				(void) strlcat(cmd, " ", sizeof (cmd));
1244 				(void) strlcat(cmd, temp, sizeof (cmd));
1245 			}
1246 		} else if (nparts) {
1247 			for (i = 0; reloc_names[i] != NULL; i++) {
1248 				if (iscpio(reloc_names[i], &iscomp) ||
1249 				    isdir(reloc_names[i]) == 0) {
1250 					(void) strlcat(cmd, " ", sizeof (cmd));
1251 					(void) strlcat(cmd, reloc_names[i],
1252 					    sizeof (cmd));
1253 				}
1254 			}
1255 			for (i = 0; root_names[i] != NULL; i++) {
1256 				if (iscpio(root_names[i], &iscomp) ||
1257 				    isdir(root_names[i]) == 0) {
1258 					(void) strlcat(cmd, " ", sizeof (cmd));
1259 					(void) strlcat(cmd, root_names[i],
1260 					    sizeof (cmd));
1261 				}
1262 			}
1263 			if (isdir(ARCHIVE) == 0) {
1264 				(void) strlcat(cmd, " ", sizeof (cmd));
1265 				(void) strlcat(cmd, ARCHIVE, sizeof (cmd));
1266 			}
1267 		}
1268 		if (options & PT_ODTSTREAM) {
1269 			(void) snprintf(cmd + strlen(cmd),
1270 			    sizeof (cmd) - strlen(cmd),
1271 			    " -print | %s -ocD -C %d",
1272 			    CPIOPROC, (int)BLK_SIZE);
1273 		} else {
1274 			if (statvfs64(dstdir, &svfsb) == -1) {
1275 				progerr(pkg_gt(ERR_TRANSFER));
1276 				logerr(pkg_gt(MSG_STATVFS), dstdir, errno);
1277 				return (1);
1278 			}
1279 
1280 			free_blocks = (((long)svfsb.f_frsize > 0) ?
1281 			    howmany(svfsb.f_frsize, DEV_BSIZE) :
1282 			    howmany(svfsb.f_bsize, DEV_BSIZE)) * svfsb.f_bavail;
1283 
1284 			if ((has_comp_size ? compressedsize : maxpartsize) >
1285 			    free_blocks) {
1286 				progerr(pkg_gt(ERR_TRANSFER));
1287 				logerr(pkg_gt(MSG_NOSPACE),
1288 				    has_comp_size ?
1289 				    (long)compressedsize : (long)maxpartsize,
1290 				    free_blocks);
1291 				return (1);
1292 			}
1293 			(void) snprintf(cmd + strlen(cmd),
1294 			    sizeof (cmd) - strlen(cmd),
1295 			    " -print | %s -pdum %s",
1296 			    CPIOPROC, dstdir);
1297 		}
1298 
1299 		n = esystem(cmd, -1, (options & PT_ODTSTREAM) ? ds_fd : -1);
1300 		if (n) {
1301 			rpterr();
1302 			progerr(pkg_gt(ERR_TRANSFER));
1303 			logerr(pkg_gt(MSG_CMDFAIL), cmd, n);
1304 			return (1);
1305 		}
1306 
1307 		part++;
1308 		if (srcdev.mount && (nparts > 1)) {
1309 			/* unmount current source volume */
1310 			(void) chdir("/");
1311 			if (pkgumount(&srcdev))
1312 				return (1);
1313 			/* loop until volume is mounted successfully */
1314 			while (part <= nparts) {
1315 				/* read only */
1316 				n = pkgmount(&srcdev, NULL, part, nparts, 1);
1317 				if (n)
1318 					return (n);
1319 				if (chdir(srcdir)) {
1320 					progerr(pkg_gt(ERR_TRANSFER));
1321 					logerr(pkg_gt(MSG_CORRUPT));
1322 					(void) chdir("/");
1323 					(void) pkgumount(&srcdev);
1324 					continue;
1325 				}
1326 				if (ckvolseq(srcdir, part, nparts)) {
1327 					(void) chdir("/");
1328 					(void) pkgumount(&srcdev);
1329 					continue;
1330 				}
1331 				break;
1332 			}
1333 		}
1334 		if (!(options & PT_ODTSTREAM) && dstdev.mount) {
1335 			/* unmount current volume */
1336 			if (pkgumount(&dstdev))
1337 				return (1);
1338 			/* loop until next volume is mounted successfully */
1339 			while (part <= nparts) {
1340 				/* writable */
1341 				n = pkgmount(&dstdev, NULL, part, nparts, 1);
1342 				if (n)
1343 					return (n);
1344 				if (ckoverwrite(dst, dstinst, options))
1345 					continue;
1346 				if (isdir(dstdir) && mkdir(dstdir, 0755)) {
1347 					progerr(pkg_gt(ERR_TRANSFER));
1348 					logerr(pkg_gt(MSG_MKDIR), dstdir);
1349 					continue;
1350 				}
1351 				break;
1352 			}
1353 		}
1354 
1355 		if ((options & PT_ODTSTREAM) && part <= nparts) {
1356 			if (curpartcnt >= 0 && part > curpartcnt) {
1357 				char prompt[128];
1358 				int index;
1359 				ds_volno++;
1360 				if (ds_close(0))
1361 					return (1);
1362 				(void) sprintf(prompt,
1363 				    pkg_gt("Insert %%v %d of %d into %%p"),
1364 				    ds_volno, ds_volcnt);
1365 				if (n = getvol(ods_name, NULL, DM_FORMAT,
1366 				    prompt))
1367 					return (n);
1368 				if ((ds_fd = open(dstdev.cdevice, 1)) < 0) {
1369 					progerr(pkg_gt(ERR_TRANSFER));
1370 					logerr(pkg_gt(MSG_OPEN),
1371 					    dstdev.cdevice, errno);
1372 					return (1);
1373 				}
1374 				if (ds_ginit(dstdev.cdevice) < 0) {
1375 					progerr(pkg_gt(ERR_TRANSFER));
1376 					logerr(pkg_gt(MSG_OPEN),
1377 					    dstdev.cdevice, errno);
1378 					(void) ds_close(0);
1379 					return (1);
1380 				}
1381 
1382 				(void) sscanf(volnos, "%d %[ 0-9]", &index,
1383 				    tmpvol);
1384 				(void) strlcpy(volnos, tmpvol, sizeof (volnos));
1385 				curpartcnt += index;
1386 			}
1387 		}
1388 
1389 	}
1390 	return (0);
1391 }
1392 
1393 static void
1394 sigtrap(int signo)
1395 {
1396 	_NOTE(ARGUNUSED(signo));
1397 	signal_received++;
1398 }
1399 
1400 static void
1401 cleanup(void)
1402 {
1403 	(void) chdir("/");
1404 	if (tmpdir) {
1405 		(void) rrmdir(tmpdir);
1406 		free(tmpdir);
1407 		tmpdir = NULL;
1408 	}
1409 
1410 	if (tmppath) {
1411 		/* remove any previous tmppath stuff */
1412 		(void) rrmdir(tmppath);
1413 		free(tmppath);
1414 		tmppath = NULL;
1415 	}
1416 
1417 	if (tmpsymdir) {
1418 		/* remove temp symbolic links made for signed pkg */
1419 		(void) rrmdir(tmpsymdir);
1420 		free(tmpsymdir);
1421 		tmpsymdir = NULL;
1422 	}
1423 
1424 	if (srcdev.mount && !ids_name)
1425 		(void) pkgumount(&srcdev);
1426 	if (dstdev.mount && !ods_name)
1427 		(void) pkgumount(&dstdev);
1428 	(void) ds_close(1);
1429 }
1430