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
pkghead(char * device)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 *
mgets(char * buf,int size)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
rd_map_size(FILE * fp,int * npts,int * maxpsz,int * cmpsize)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
_pkgtrans(char * device1,char * device2,char ** pkg,int options)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, 0,
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, 0, 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
pkgtrans(char * device1,char * device2,char ** pkg,int options)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
cat_and_count(struct dm_buf * buf_ctrl,char * append)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 *
genheader(char * src,char ** pkg)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
wdsheader(struct dm_buf * hdr,char * device,char ** pkg)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
ckoverwrite(char * dir,char * inst,int options)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
pkgxfer(char * srcinst,int options)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], temp[PATH_MAX], srcdir[PATH_MAX];
901 char cmd[CMDSIZE], pkgname[NON_ABI_NAMELNGTH];
902 int i, n, part, nparts, maxpartsize, curpartcnt, iscomp;
903 char volnos[128], tmpvol[128];
904 struct statvfs64 svfsb;
905 longlong_t free_blocks;
906 struct stat srcstat;
907
908 info.pkginst = NULL; /* required initialization */
909
910 /*
911 * when this routine is entered, the first part of
912 * the package to transfer is already available in
913 * the directory indicated by 'src' --- unless the
914 * source device is a datstream, in which case only
915 * the pkginfo and pkgmap files are available in 'src'
916 */
917 src = srcdev.dirname;
918 dst = dstdev.dirname;
919
920 if (!(options & PT_SILENT))
921 (void) fprintf(stderr, pkg_gt(MSG_TRANSFER), srcinst);
922 (void) strlcpy(dstinst, srcinst, sizeof (dstinst));
923
924 if (!(options & PT_ODTSTREAM)) {
925 /* destination is a (possibly mounted) directory */
926 (void) snprintf(dstdir, sizeof (dstdir),
927 "%s/%s", dst, dstinst);
928
929 /*
930 * need to check destination directory to assure
931 * that we will not be duplicating a package which
932 * already resides there (though we are allowed to
933 * overwrite the same version)
934 */
935 pkgdir = src;
936 if (fpkginfo(&info, srcinst)) {
937 progerr(pkg_gt(ERR_TRANSFER));
938 logerr(pkg_gt(MSG_NOEXISTS), srcinst);
939 (void) fpkginfo(&info, NULL);
940 return (1);
941 }
942 pkgdir = dst;
943
944 (void) strlcpy(temp, srcinst, sizeof (temp));
945 if (pt = strchr(temp, '.'))
946 *pt = '\0';
947 (void) strlcat(temp, ".*", sizeof (temp));
948
949 if (pt = fpkginst(temp, info.arch, info.version)) {
950 /*
951 * the same instance already exists, although
952 * its pkgid might be different
953 */
954 if (options & PT_OVERWRITE) {
955 (void) strlcpy(dstinst, pt, sizeof (dstinst));
956 (void) snprintf(dstdir, sizeof (dstdir),
957 "%s/%s", dst, dstinst);
958 } else {
959 progerr(pkg_gt(ERR_TRANSFER));
960 logerr(pkg_gt(MSG_DUPVERS), srcinst);
961 (void) fpkginfo(&info, NULL);
962 (void) fpkginst(NULL);
963 return (2);
964 }
965 } else if (options & PT_RENAME) {
966 /*
967 * find next available instance by appending numbers
968 * to the package abbreviation until the instance
969 * does not exist in the destination directory
970 */
971 if (pt = strchr(temp, '.'))
972 *pt = '\0';
973 for (i = 2; (access(dstdir, 0) == 0); i++) {
974 (void) snprintf(dstinst, sizeof (dstinst),
975 "%s.%d", temp, i);
976 (void) snprintf(dstdir, sizeof (dstdir),
977 "%s/%s", dst, dstinst);
978 }
979 } else if (options & PT_OVERWRITE) {
980 /*
981 * we're allowed to overwrite, but there seems
982 * to be no valid package to overwrite, and we are
983 * not allowed to rename the destination, so act
984 * as if we weren't given permission to overwrite
985 * --- this keeps us from removing a destination
986 * instance which is named the same as the source
987 * instance, but really reflects a different pkg!
988 */
989 options &= (~PT_OVERWRITE);
990 }
991 (void) fpkginfo(&info, NULL);
992 (void) fpkginst(NULL);
993
994 if (ckoverwrite(dst, dstinst, options))
995 return (2);
996
997 if (isdir(dstdir) && mkdir(dstdir, 0755)) {
998 progerr(pkg_gt(ERR_TRANSFER));
999 logerr(pkg_gt(MSG_MKDIR), dstdir);
1000 return (1);
1001 }
1002
1003 (void) snprintf(srcdir, sizeof (srcdir),
1004 "%s/%s", src, srcinst);
1005 if (stat(srcdir, &srcstat) != -1) {
1006 if (chmod(dstdir, (srcstat.st_mode & S_IAMB)) == -1) {
1007 progerr(pkg_gt(ERR_TRANSFER));
1008 logerr(pkg_gt(MSG_CHMODDIR), dstdir);
1009 return (1);
1010 }
1011 } else {
1012 progerr(pkg_gt(ERR_TRANSFER));
1013 logerr(pkg_gt(MSG_STATDIR), srcdir);
1014 return (1);
1015 }
1016 }
1017
1018 if (!(options & PT_SILENT) && strcmp(dstinst, srcinst))
1019 (void) fprintf(stderr, pkg_gt(MSG_RENAME), dstinst);
1020
1021 (void) snprintf(srcdir, sizeof (srcdir), "%s/%s", src, srcinst);
1022 if (chdir(srcdir)) {
1023 progerr(pkg_gt(ERR_TRANSFER));
1024 logerr(pkg_gt(MSG_CHDIR), srcdir);
1025 return (1);
1026 }
1027
1028 if (ids_name) { /* unpack the datatstream into a directory */
1029 /*
1030 * transfer pkginfo & pkgmap first
1031 */
1032 (void) snprintf(cmd, sizeof (cmd),
1033 "%s -pudm %s", CPIOPROC, dstdir);
1034 if ((pp = epopen(cmd, "w")) == NULL) {
1035 rpterr();
1036 progerr(pkg_gt(ERR_TRANSFER));
1037 logerr(pkg_gt(MSG_POPEN), cmd, errno);
1038 return (1);
1039 }
1040 (void) fprintf(pp, "%s\n%s\n", PKGINFO, PKGMAP);
1041
1042 (void) sighold(SIGINT);
1043 (void) sighold(SIGHUP);
1044 r = epclose(pp);
1045 (void) sigrelse(SIGINT);
1046 (void) sigrelse(SIGHUP);
1047
1048 if (r != 0) {
1049 rpterr();
1050 progerr(pkg_gt(ERR_TRANSFER));
1051 logerr(pkg_gt(MSG_PCLOSE), cmd, errno);
1052 return (1);
1053 }
1054
1055 if (options & PT_INFO_ONLY)
1056 return (0); /* don't transfer objects */
1057
1058 if (chdir(dstdir)) {
1059 progerr(pkg_gt(ERR_TRANSFER));
1060 logerr(pkg_gt(MSG_CHDIR), dstdir);
1061 return (1);
1062 }
1063
1064 /*
1065 * for each part of the package, use cpio() to
1066 * unpack the archive into the destination directory
1067 */
1068 nparts = ds_findpkg(srcdev.cdevice, srcinst);
1069 if (nparts < 0) {
1070 progerr(pkg_gt(ERR_TRANSFER));
1071 return (1);
1072 }
1073 for (part = 1; part <= nparts; /* void */) {
1074 if (ds_getpkg(srcdev.cdevice, part, dstdir)) {
1075 progerr(pkg_gt(ERR_TRANSFER));
1076 return (1);
1077 }
1078 part++;
1079 if (dstdev.mount) {
1080 (void) chdir("/");
1081 if (pkgumount(&dstdev))
1082 return (1);
1083 if (part <= nparts) {
1084 if (n = pkgmount(&dstdev, NULL, part+1,
1085 nparts, 1))
1086 return (n);
1087 if (ckoverwrite(dst, dstinst, options))
1088 return (1);
1089 if (isdir(dstdir) &&
1090 mkdir(dstdir, 0755)) {
1091 progerr(
1092 pkg_gt(ERR_TRANSFER));
1093 logerr(pkg_gt(MSG_MKDIR),
1094 dstdir);
1095 return (1);
1096 }
1097 /*
1098 * since volume is removable, each part
1099 * must contain a duplicate of the
1100 * pkginfo file to properly identify the
1101 * volume
1102 */
1103 if (chdir(srcdir)) {
1104 progerr(
1105 pkg_gt(ERR_TRANSFER));
1106 logerr(pkg_gt(MSG_CHDIR),
1107 srcdir);
1108 return (1);
1109 }
1110 if ((pp = epopen(cmd, "w")) == NULL) {
1111 rpterr();
1112 progerr(
1113 pkg_gt(ERR_TRANSFER));
1114 logerr(pkg_gt(MSG_POPEN),
1115 cmd, errno);
1116 return (1);
1117 }
1118 (void) fprintf(pp, "pkginfo");
1119
1120 (void) sighold(SIGINT);
1121 (void) sighold(SIGHUP);
1122 r = epclose(pp);
1123 (void) sigrelse(SIGINT);
1124 (void) sigrelse(SIGHUP);
1125
1126 if (r != 0) {
1127 rpterr();
1128 progerr(
1129 pkg_gt(ERR_TRANSFER));
1130 logerr(pkg_gt(MSG_PCLOSE),
1131 cmd, errno);
1132 return (1);
1133 }
1134 if (chdir(dstdir)) {
1135 progerr(
1136 pkg_gt(ERR_TRANSFER));
1137 logerr(pkg_gt(MSG_CHDIR),
1138 dstdir);
1139 return (1);
1140 }
1141 }
1142 }
1143 }
1144 return (0);
1145 }
1146
1147 if ((fp = fopen(PKGMAP, "r")) == NULL) {
1148 progerr(pkg_gt(ERR_TRANSFER));
1149 logerr(pkg_gt(MSG_NOPKGMAP), srcinst);
1150 return (1);
1151 }
1152
1153 nparts = 1;
1154 if (!rd_map_size(fp, &nparts, &maxpartsize, &compressedsize))
1155 return (1);
1156 else
1157 (void) fclose(fp);
1158
1159 if (srcdev.mount) {
1160 if (ckvolseq(srcdir, 1, nparts)) {
1161 progerr(pkg_gt(ERR_TRANSFER));
1162 logerr(pkg_gt(MSG_SEQUENCE));
1163 return (1);
1164 }
1165 }
1166
1167 /* write each part of this package */
1168 if (options & PT_ODTSTREAM) {
1169 char line[128];
1170 (void) mgets(line, 128);
1171 curpartcnt = -1;
1172 /* LINTED E_SEC_SCANF_UNBOUNDED_COPY */
1173 if (sscanf(line, "%s %d %d %[ 0-9]", pkgname, &nparts,
1174 &maxpartsize, volnos) == 4) {
1175 (void) sscanf(volnos,
1176 "%d %[ 0-9]", &curpartcnt, tmpvol);
1177 (void) strlcpy(volnos, tmpvol, sizeof (volnos));
1178 }
1179 }
1180
1181 for (part = 1; part <= nparts; /* void */) {
1182 if (curpartcnt == 0 && (options & PT_ODTSTREAM)) {
1183 char prompt[128];
1184 int index;
1185 ds_volno++;
1186 (void) ds_close(0);
1187 (void) sprintf(prompt,
1188 pkg_gt("Insert %%v %d of %d into %%p"),
1189 ds_volno, ds_volcnt);
1190 if (n = getvol(ods_name, NULL, DM_FORMAT, prompt))
1191 return (n);
1192 if ((ds_fd = open(dstdev.cdevice, O_WRONLY)) < 0) {
1193 progerr(pkg_gt(ERR_TRANSFER));
1194 logerr(pkg_gt(MSG_OPEN), dstdev.cdevice,
1195 errno);
1196 return (1);
1197 }
1198 if (ds_ginit(dstdev.cdevice) < 0) {
1199 progerr(pkg_gt(ERR_TRANSFER));
1200 logerr(pkg_gt(MSG_OPEN), dstdev.cdevice,
1201 errno);
1202 (void) ds_close(0);
1203 return (1);
1204 }
1205
1206 (void) sscanf(volnos, "%d %[ 0-9]", &index, tmpvol);
1207 (void) strlcpy(volnos, tmpvol, sizeof (volnos));
1208 curpartcnt += index;
1209 }
1210
1211 if (options & PT_INFO_ONLY)
1212 nparts = 0;
1213
1214 if (part == 1) {
1215 (void) snprintf(cmd, sizeof (cmd),
1216 "find %s %s", PKGINFO, PKGMAP);
1217 if (nparts && (isdir(INSTALL) == 0)) {
1218 (void) strlcat(cmd, " ", sizeof (cmd));
1219 (void) strlcat(cmd, INSTALL, sizeof (cmd));
1220 }
1221 } else
1222 (void) snprintf(cmd, sizeof (cmd), "find %s", PKGINFO);
1223
1224 if (nparts > 1) {
1225 (void) snprintf(temp, sizeof (temp),
1226 "%s.%d", RELOC, part);
1227 if (iscpio(temp, &iscomp) || isdir(temp) == 0) {
1228 (void) strlcat(cmd, " ", sizeof (cmd));
1229 (void) strlcat(cmd, temp, sizeof (cmd));
1230 }
1231 (void) snprintf(temp, sizeof (temp),
1232 "%s.%d", ROOT, part);
1233 if (iscpio(temp, &iscomp) || isdir(temp) == 0) {
1234 (void) strlcat(cmd, " ", sizeof (cmd));
1235 (void) strlcat(cmd, temp, sizeof (cmd));
1236 }
1237 (void) snprintf(temp, sizeof (temp),
1238 "%s.%d", ARCHIVE, part);
1239 if (isdir(temp) == 0) {
1240 (void) strlcat(cmd, " ", sizeof (cmd));
1241 (void) strlcat(cmd, temp, sizeof (cmd));
1242 }
1243 } else if (nparts) {
1244 for (i = 0; reloc_names[i] != NULL; i++) {
1245 if (iscpio(reloc_names[i], &iscomp) ||
1246 isdir(reloc_names[i]) == 0) {
1247 (void) strlcat(cmd, " ", sizeof (cmd));
1248 (void) strlcat(cmd, reloc_names[i],
1249 sizeof (cmd));
1250 }
1251 }
1252 for (i = 0; root_names[i] != NULL; i++) {
1253 if (iscpio(root_names[i], &iscomp) ||
1254 isdir(root_names[i]) == 0) {
1255 (void) strlcat(cmd, " ", sizeof (cmd));
1256 (void) strlcat(cmd, root_names[i],
1257 sizeof (cmd));
1258 }
1259 }
1260 if (isdir(ARCHIVE) == 0) {
1261 (void) strlcat(cmd, " ", sizeof (cmd));
1262 (void) strlcat(cmd, ARCHIVE, sizeof (cmd));
1263 }
1264 }
1265 if (options & PT_ODTSTREAM) {
1266 (void) snprintf(cmd + strlen(cmd),
1267 sizeof (cmd) - strlen(cmd),
1268 " -print | %s -ocD -C %d",
1269 CPIOPROC, (int)BLK_SIZE);
1270 } else {
1271 if (statvfs64(dstdir, &svfsb) == -1) {
1272 progerr(pkg_gt(ERR_TRANSFER));
1273 logerr(pkg_gt(MSG_STATVFS), dstdir, errno);
1274 return (1);
1275 }
1276
1277 free_blocks = (((long)svfsb.f_frsize > 0) ?
1278 howmany(svfsb.f_frsize, DEV_BSIZE) :
1279 howmany(svfsb.f_bsize, DEV_BSIZE)) * svfsb.f_bavail;
1280
1281 if ((has_comp_size ? compressedsize : maxpartsize) >
1282 free_blocks) {
1283 progerr(pkg_gt(ERR_TRANSFER));
1284 logerr(pkg_gt(MSG_NOSPACE),
1285 has_comp_size ?
1286 (long)compressedsize : (long)maxpartsize,
1287 free_blocks);
1288 return (1);
1289 }
1290 (void) snprintf(cmd + strlen(cmd),
1291 sizeof (cmd) - strlen(cmd),
1292 " -print | %s -pdum %s",
1293 CPIOPROC, dstdir);
1294 }
1295
1296 n = esystem(cmd, -1, (options & PT_ODTSTREAM) ? ds_fd : -1);
1297 if (n) {
1298 rpterr();
1299 progerr(pkg_gt(ERR_TRANSFER));
1300 logerr(pkg_gt(MSG_CMDFAIL), cmd, n);
1301 return (1);
1302 }
1303
1304 part++;
1305 if (srcdev.mount && (nparts > 1)) {
1306 /* unmount current source volume */
1307 (void) chdir("/");
1308 if (pkgumount(&srcdev))
1309 return (1);
1310 /* loop until volume is mounted successfully */
1311 while (part <= nparts) {
1312 /* read only */
1313 n = pkgmount(&srcdev, NULL, part, nparts, 1);
1314 if (n)
1315 return (n);
1316 if (chdir(srcdir)) {
1317 progerr(pkg_gt(ERR_TRANSFER));
1318 logerr(pkg_gt(MSG_CORRUPT));
1319 (void) chdir("/");
1320 (void) pkgumount(&srcdev);
1321 continue;
1322 }
1323 if (ckvolseq(srcdir, part, nparts)) {
1324 (void) chdir("/");
1325 (void) pkgumount(&srcdev);
1326 continue;
1327 }
1328 break;
1329 }
1330 }
1331 if (!(options & PT_ODTSTREAM) && dstdev.mount) {
1332 /* unmount current volume */
1333 if (pkgumount(&dstdev))
1334 return (1);
1335 /* loop until next volume is mounted successfully */
1336 while (part <= nparts) {
1337 /* writable */
1338 n = pkgmount(&dstdev, NULL, part, nparts, 1);
1339 if (n)
1340 return (n);
1341 if (ckoverwrite(dst, dstinst, options))
1342 continue;
1343 if (isdir(dstdir) && mkdir(dstdir, 0755)) {
1344 progerr(pkg_gt(ERR_TRANSFER));
1345 logerr(pkg_gt(MSG_MKDIR), dstdir);
1346 continue;
1347 }
1348 break;
1349 }
1350 }
1351
1352 if ((options & PT_ODTSTREAM) && part <= nparts) {
1353 if (curpartcnt >= 0 && part > curpartcnt) {
1354 char prompt[128];
1355 int index;
1356 ds_volno++;
1357 if (ds_close(0))
1358 return (1);
1359 (void) sprintf(prompt,
1360 pkg_gt("Insert %%v %d of %d into %%p"),
1361 ds_volno, ds_volcnt);
1362 if (n = getvol(ods_name, NULL, DM_FORMAT,
1363 prompt))
1364 return (n);
1365 if ((ds_fd = open(dstdev.cdevice, 1)) < 0) {
1366 progerr(pkg_gt(ERR_TRANSFER));
1367 logerr(pkg_gt(MSG_OPEN),
1368 dstdev.cdevice, errno);
1369 return (1);
1370 }
1371 if (ds_ginit(dstdev.cdevice) < 0) {
1372 progerr(pkg_gt(ERR_TRANSFER));
1373 logerr(pkg_gt(MSG_OPEN),
1374 dstdev.cdevice, errno);
1375 (void) ds_close(0);
1376 return (1);
1377 }
1378
1379 (void) sscanf(volnos, "%d %[ 0-9]", &index,
1380 tmpvol);
1381 (void) strlcpy(volnos, tmpvol, sizeof (volnos));
1382 curpartcnt += index;
1383 }
1384 }
1385
1386 }
1387 return (0);
1388 }
1389
1390 static void
sigtrap(int signo)1391 sigtrap(int signo)
1392 {
1393 _NOTE(ARGUNUSED(signo));
1394 signal_received++;
1395 }
1396
1397 static void
cleanup(void)1398 cleanup(void)
1399 {
1400 (void) chdir("/");
1401 if (tmpdir) {
1402 (void) rrmdir(tmpdir);
1403 free(tmpdir);
1404 tmpdir = NULL;
1405 }
1406
1407 if (tmppath) {
1408 /* remove any previous tmppath stuff */
1409 (void) rrmdir(tmppath);
1410 free(tmppath);
1411 tmppath = NULL;
1412 }
1413
1414 if (tmpsymdir) {
1415 /* remove temp symbolic links made for signed pkg */
1416 (void) rrmdir(tmpsymdir);
1417 free(tmpsymdir);
1418 tmpsymdir = NULL;
1419 }
1420
1421 if (srcdev.mount && !ids_name)
1422 (void) pkgumount(&srcdev);
1423 if (dstdev.mount && !ods_name)
1424 (void) pkgumount(&dstdev);
1425 (void) ds_close(1);
1426 }
1427