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