8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / libpkg / common / pkgtrans.c
blobcfc4009b08c7e630d11e3bfe2fa4808ddc859042
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright (c) 2017 Peter Tribble.
27 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
28 * Use is subject to license terms.
31 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
32 /* All Rights Reserved */
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"
62 extern char *pkgdir; /* pkgparam.c */
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);
72 /* dstream.c */
73 extern int ds_ginit(char *device);
74 extern int ds_close(int pkgendflg);
76 #define CPIOPROC "/usr/bin/cpio"
78 #define CMDSIZE 512 /* command block size */
80 #define BLK_SIZE 512 /* size of logical block */
82 #define ENTRY_MAX 256 /* max size of entry for cpio cmd or header */
84 #define PKGINFO "pkginfo"
85 #define PKGMAP "pkgmap"
86 #define MAP_STAT_SIZE 60 /* 1st line of pkgmap (3 numbers & a : */
88 #define INSTALL "install"
89 #define RELOC "reloc"
90 #define ROOT "root"
91 #define ARCHIVE "archive"
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;
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);
109 static int cat_and_count(struct dm_buf *, char *);
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 **);
116 extern int ds_fd; /* open file descriptor for data stream WHERE? */
118 static char *root_names[] = {
119 "root",
120 "root.cpio",
121 "root.Z",
122 "root.cpio.Z",
126 static char *reloc_names[] = {
127 "reloc",
128 "reloc.cpio",
129 "reloc.Z",
130 "reloc.cpio.Z",
134 static int signal_received = 0;
136 char **xpkg; /* array of transferred packages */
137 int nxpkg;
139 static char *allpkg[] = {
140 "all",
141 NULL
144 static struct dm_buf hdrbuf;
145 static char *pinput, *nextpinput;
148 pkghead(char *device)
150 char *pt;
151 int n;
153 cleanup();
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);
166 /* check for datastream */
167 if (n = pkgtrans(device, (char *)0, allpkg, PT_SILENT|PT_INFO_ONLY)) {
168 cleanup();
169 return (n);
171 /* pkgtrans has set pkgdir */
172 return (0);
175 static char *
176 mgets(char *buf, int size)
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);
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.
201 static int
202 rd_map_size(FILE *fp, int *npts, int *maxpsz, int *cmpsize)
204 int n;
205 char line_buffer[MAP_STAT_SIZE];
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);
216 n = sscanf(line_buffer, ": %d %d %d", npts, maxpsz, cmpsize);
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);
230 return (n);
233 /* will return 0, 1, 3, or 99 */
234 static int
235 _pkgtrans(char *device1, char *device2, char **pkg, int options)
237 char *src, *dst;
238 int errflg, i, n;
239 struct dm_buf *hdr;
241 if (signal_received > 0) {
242 return (1);
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);
251 srcdev.rdonly++;
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);
265 if (ds_readbuf(srcdev.cdevice))
266 ids_name = srcdev.cdevice;
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);
280 if (!ids_name && device2 == (char *)0) {
281 if (n = pkgmount(&srcdev, NULL, 1, 0, 0)) {
282 cleanup();
283 return (n);
285 if (srcdev.mount && *srcdev.mount)
286 pkgdir = strdup(srcdev.mount);
287 return (0);
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);
298 if (mkdir(tmppath, 0755)) {
299 progerr(pkg_gt(ERR_TRANSFER));
300 logerr(pkg_gt(MSG_MKDIR), tmppath);
301 return (1);
303 device2 = tmppath;
306 if (devtype(device2, &dstdev)) {
307 progerr(pkg_gt(ERR_TRANSFER));
308 logerr(pkg_gt(MSG_BADDEV), device2);
309 return (1);
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);
319 ods_name = NULL;
320 if (dstdev.cdevice && !dstdev.bdevice || dstdev.pathname)
321 options |= PT_ODTSTREAM;
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);
330 if (ids_name) {
331 progerr(pkg_gt(ERR_TRANSFER));
332 logerr(pkg_gt(MSG_TWODSTREAM));
333 return (1);
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);
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);
351 if (signal_received > 0) {
352 return (1);
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);
366 if (srcdev.dirname = tmpnam(NULL))
367 tmpdir = srcdev.dirname = strdup(srcdev.dirname);
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);
376 if (ds_init(ids_name, pkg, srcdev.norewind)) {
377 cleanup();
378 return (1);
380 } else if (srcdev.mount) {
381 if (n = pkgmount(&srcdev, NULL, 1, 0, 0)) {
382 cleanup();
383 return (n);
387 src = srcdev.dirname;
388 dst = dstdev.dirname;
390 if (chdir(src)) {
391 progerr(pkg_gt(ERR_TRANSFER));
392 logerr(pkg_gt(MSG_CHDIR), src);
393 cleanup();
394 return (1);
397 if (signal_received > 0) {
398 return (1);
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);
409 for (nxpkg = 0; pkg[nxpkg]; /* void */) {
410 nxpkg++; /* count */
413 if (ids_name) {
414 ds_order(pkg); /* order requests */
417 if (signal_received > 0) {
418 return (1);
421 if (options & PT_ODTSTREAM) {
422 char line[128];
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);
434 if ((hdr = genheader(src, pkg)) == NULL) {
435 cleanup();
436 return (1);
439 /* write out header to stream */
440 if (wdsheader(hdr, ods_name, pkg)) {
441 cleanup();
442 return (1);
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);
451 if (signal_received > 0) {
452 return (1);
455 errflg = 0;
457 for (i = 0; pkg[i]; i++) {
459 if (signal_received > 0) {
460 return (1);
463 if (!(options & PT_ODTSTREAM) && dstdev.mount) {
464 if (n = pkgmount(&dstdev, NULL, 0, 0, 1)) {
465 cleanup();
466 return (n);
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);
477 if (!(options & PT_ODTSTREAM) && dst) {
478 pkgdir = strdup(dst);
482 * No cleanup of temporary directories created in this
483 * function is done here. The calling function must do
484 * the cleanup.
487 return (signal_received > 0 ? 1 : errflg);
491 pkgtrans(char *device1, char *device2, char **pkg, int options)
493 int r;
494 struct sigaction nact;
495 struct sigaction oact;
498 * setup signal handlers for SIGINT and SIGHUP and release hold
501 /* hold SIGINT/SIGHUP interrupts */
503 (void) sighold(SIGHUP);
504 (void) sighold(SIGINT);
506 /* hook SIGINT to sigtrap */
508 nact.sa_handler = sigtrap;
509 nact.sa_flags = SA_RESTART;
510 (void) sigemptyset(&nact.sa_mask);
512 if (sigaction(SIGINT, &nact, &oact) < 0) {
513 sigintHandler = SIG_DFL;
514 } else {
515 sigintHandler = oact.sa_handler;
518 /* hook SIGHUP to sigtrap */
520 nact.sa_handler = sigtrap;
521 nact.sa_flags = SA_RESTART;
522 (void) sigemptyset(&nact.sa_mask);
524 if (sigaction(SIGHUP, &nact, &oact) < 0) {
525 sighupHandler = SIG_DFL;
526 } else {
527 sighupHandler = oact.sa_handler;
530 /* reset signal received count */
532 signal_received = 0;
534 /* release hold on signals */
536 (void) sigrelse(SIGHUP);
537 (void) sigrelse(SIGINT);
540 * perform the package translation
543 r = _pkgtrans(device1, device2, pkg, options);
546 * reset signal handlers
549 /* hold SIGINT/SIGHUP interrupts */
551 (void) sighold(SIGHUP);
552 (void) sighold(SIGINT);
554 /* reset SIGINT */
556 nact.sa_handler = sigintHandler;
557 nact.sa_flags = SA_RESTART;
558 (void) sigemptyset(&nact.sa_mask);
560 (void) sigaction(SIGINT, &nact, (struct sigaction *)NULL);
562 /* reset SIGHUP */
564 nact.sa_handler = sighupHandler;
565 nact.sa_flags = SA_RESTART;
566 (void) sigemptyset(&nact.sa_mask);
568 (void) sigaction(SIGHUP, &nact, (struct sigaction *)NULL);
570 /* if signal received and pkgtrans returned error, call cleanup */
572 if (signal_received > 0) {
573 if (r != 0) {
574 cleanup();
576 (void) kill(getpid(), SIGINT);
579 /* release hold on signals */
581 (void) sigrelse(SIGHUP);
582 (void) sigrelse(SIGINT);
584 return (r);
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.
593 static int
594 cat_and_count(struct dm_buf *buf_ctrl, char *append)
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);
610 /* clear the new memory */
611 (void) memset(buf_ctrl->text_buffer +
612 buf_ctrl->allocation, '\0', BLK_SIZE);
614 /* adjust total allocation */
615 buf_ctrl->allocation += BLK_SIZE;
618 /* append new string to end of buffer */
619 while (*append) {
620 *(buf_ctrl->text_buffer + buf_ctrl->offset) = *append++;
621 (buf_ctrl->offset)++;
624 return (0);
627 static struct dm_buf *
628 genheader(char *src, char **pkg)
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;
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);
644 /* clear the new memory */
645 (void) memset(hdrbuf.text_buffer, '\0', BLK_SIZE);
647 /* set up the buffer control structure for the header */
648 hdrbuf.offset = 0;
649 hdrbuf.allocation = BLK_SIZE;
651 (void) cat_and_count(&hdrbuf, HDR_PREFIX);
652 (void) cat_and_count(&hdrbuf, "\n");
654 nparts = maxpsize = 0;
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);
666 totsize += statbuf.st_size/BLK_SIZE + 1;
670 * totsize contains number of blocks used by the pkginfo files
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);
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);
692 /* Evaluate the first entry in pkgmap */
693 n = rd_map_size(fp, &nparts, &maxpsize, &compressedsize);
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);
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);
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);
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);
727 totsize += nparts * maxpsize;
728 if (dstdev.capacity && dstdev.capacity < totsize) {
729 int lastpartcnt = 0;
731 if (totsize)
732 totsize -= nparts * maxpsize;
733 while (partcnt < nparts) {
734 while (totsize <= dstdev.capacity &&
735 partcnt <= nparts) {
736 totsize += maxpsize;
737 partcnt++;
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);
751 ds_volcnt++;
752 totsize = 0;
753 lastpartcnt = partcnt;
755 /* first parts/volume number does not count */
756 ds_volcnt--;
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);
767 (void) fclose(fp);
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);
778 return (&hdrbuf);
781 static int
782 wdsheader(struct dm_buf *hdr, char *device, char **pkg)
784 char tmp_entry[ENTRY_MAX], tmp_file[L_tmpnam+1];
785 int i, n;
786 int list_fd;
787 int block_cnt;
789 (void) ds_close(0);
790 if (dstdev.pathname)
791 ds_fd = creat(device, 0644);
792 else
793 ds_fd = open(device, 1);
795 if (ds_fd < 0) {
796 progerr(pkg_gt(ERR_TRANSFER));
797 logerr(pkg_gt(MSG_OPEN), device, errno);
798 return (1);
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);
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.
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);
819 * write the first cpio() archive to the datastream
820 * which should contain the pkginfo & pkgmap files
821 * for all packages
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);
831 * Create a cpio-compatible list of the requisite files in
832 * the temporary file.
834 for (i = 0; pkg[i]; i++) {
835 register ssize_t entry_size;
838 * Copy pkginfo and pkgmap filenames into the
839 * temporary string allowing for the first line
840 * as a special case.
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);
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);
856 (void) lseek(list_fd, 0, SEEK_SET);
858 (void) snprintf(tmp_entry, sizeof (tmp_entry),
859 "%s -ocD -C %d", CPIOPROC, (int)BLK_SIZE);
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);
871 (void) close(list_fd);
872 (void) unlink(tmp_file);
874 return (0);
877 static int
878 ckoverwrite(char *dir, char *inst, int options)
880 char path[PATH_MAX];
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);
890 return (0);
893 static int
894 pkgxfer(char *srcinst, int options)
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;
911 info.pkginst = NULL; /* required initialization */
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'
920 src = srcdev.dirname;
921 dst = dstdev.dirname;
923 if (!(options & PT_SILENT))
924 (void) fprintf(stderr, pkg_gt(MSG_TRANSFER), srcinst);
925 (void) strlcpy(dstinst, srcinst, sizeof (dstinst));
927 if (!(options & PT_ODTSTREAM)) {
928 /* destination is a (possibly mounted) directory */
929 (void) snprintf(dstdir, sizeof (dstdir),
930 "%s/%s", dst, dstinst);
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)
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);
945 pkgdir = dst;
947 (void) strlcpy(temp, srcinst, sizeof (temp));
948 if (pt = strchr(temp, '.'))
949 *pt = '\0';
950 (void) strlcat(temp, ".*", sizeof (temp));
952 if (pt = fpkginst(temp, info.arch, info.version)) {
954 * the same instance already exists, although
955 * its pkgid might be different
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);
968 } else if (options & PT_RENAME) {
970 * find next available instance by appending numbers
971 * to the package abbreviation until the instance
972 * does not exist in the destination directory
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);
982 } else if (options & PT_OVERWRITE) {
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!
992 options &= (~PT_OVERWRITE);
994 (void) fpkginfo(&info, NULL);
995 (void) fpkginst(NULL);
997 if (ckoverwrite(dst, dstinst, options))
998 return (2);
1000 if (isdir(dstdir) && mkdir(dstdir, 0755)) {
1001 progerr(pkg_gt(ERR_TRANSFER));
1002 logerr(pkg_gt(MSG_MKDIR), dstdir);
1003 return (1);
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);
1014 } else {
1015 progerr(pkg_gt(ERR_TRANSFER));
1016 logerr(pkg_gt(MSG_STATDIR), srcdir);
1017 return (1);
1021 if (!(options & PT_SILENT) && strcmp(dstinst, srcinst))
1022 (void) fprintf(stderr, pkg_gt(MSG_RENAME), dstinst);
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);
1031 if (ids_name) { /* unpack the datatstream into a directory */
1033 * transfer pkginfo & pkgmap first
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);
1043 (void) fprintf(pp, "%s\n%s\n", PKGINFO, PKGMAP);
1045 (void) sighold(SIGINT);
1046 (void) sighold(SIGHUP);
1047 r = epclose(pp);
1048 (void) sigrelse(SIGINT);
1049 (void) sigrelse(SIGHUP);
1051 if (r != 0) {
1052 rpterr();
1053 progerr(pkg_gt(ERR_TRANSFER));
1054 logerr(pkg_gt(MSG_PCLOSE), cmd, errno);
1055 return (1);
1058 if (options & PT_INFO_ONLY)
1059 return (0); /* don't transfer objects */
1061 if (chdir(dstdir)) {
1062 progerr(pkg_gt(ERR_TRANSFER));
1063 logerr(pkg_gt(MSG_CHDIR), dstdir);
1064 return (1);
1068 * for each part of the package, use cpio() to
1069 * unpack the archive into the destination directory
1071 nparts = ds_findpkg(srcdev.cdevice, srcinst);
1072 if (nparts < 0) {
1073 progerr(pkg_gt(ERR_TRANSFER));
1074 return (1);
1076 for (part = 1; part <= nparts; /* void */) {
1077 if (ds_getpkg(srcdev.cdevice, part, dstdir)) {
1078 progerr(pkg_gt(ERR_TRANSFER));
1079 return (1);
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);
1101 * since volume is removable, each part
1102 * must contain a duplicate of the
1103 * pkginfo file to properly identify the
1104 * volume
1106 if (chdir(srcdir)) {
1107 progerr(
1108 pkg_gt(ERR_TRANSFER));
1109 logerr(pkg_gt(MSG_CHDIR),
1110 srcdir);
1111 return (1);
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);
1121 (void) fprintf(pp, "pkginfo");
1123 (void) sighold(SIGINT);
1124 (void) sighold(SIGHUP);
1125 r = epclose(pp);
1126 (void) sigrelse(SIGINT);
1127 (void) sigrelse(SIGHUP);
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);
1137 if (chdir(dstdir)) {
1138 progerr(
1139 pkg_gt(ERR_TRANSFER));
1140 logerr(pkg_gt(MSG_CHDIR),
1141 dstdir);
1142 return (1);
1147 return (0);
1150 if ((fp = fopen(PKGMAP, "r")) == NULL) {
1151 progerr(pkg_gt(ERR_TRANSFER));
1152 logerr(pkg_gt(MSG_NOPKGMAP), srcinst);
1153 return (1);
1156 nparts = 1;
1157 if (!rd_map_size(fp, &nparts, &maxpartsize, &compressedsize))
1158 return (1);
1159 else
1160 (void) fclose(fp);
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);
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));
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);
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);
1209 (void) sscanf(volnos, "%d %[ 0-9]", &index, tmpvol);
1210 (void) strlcpy(volnos, tmpvol, sizeof (volnos));
1211 curpartcnt += index;
1214 if (options & PT_INFO_ONLY)
1215 nparts = 0;
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));
1224 } else
1225 (void) snprintf(cmd, sizeof (cmd), "find %s", PKGINFO);
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));
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));
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));
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));
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));
1263 if (isdir(ARCHIVE) == 0) {
1264 (void) strlcat(cmd, " ", sizeof (cmd));
1265 (void) strlcat(cmd, ARCHIVE, sizeof (cmd));
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);
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;
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);
1293 (void) snprintf(cmd + strlen(cmd),
1294 sizeof (cmd) - strlen(cmd),
1295 " -print | %s -pdum %s",
1296 CPIOPROC, dstdir);
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);
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;
1326 if (ckvolseq(srcdir, part, nparts)) {
1327 (void) chdir("/");
1328 (void) pkgumount(&srcdev);
1329 continue;
1331 break;
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;
1351 break;
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);
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);
1382 (void) sscanf(volnos, "%d %[ 0-9]", &index,
1383 tmpvol);
1384 (void) strlcpy(volnos, tmpvol, sizeof (volnos));
1385 curpartcnt += index;
1390 return (0);
1393 static void
1394 sigtrap(int signo)
1396 _NOTE(ARGUNUSED(signo));
1397 signal_received++;
1400 static void
1401 cleanup(void)
1403 (void) chdir("/");
1404 if (tmpdir) {
1405 (void) rrmdir(tmpdir);
1406 free(tmpdir);
1407 tmpdir = NULL;
1410 if (tmppath) {
1411 /* remove any previous tmppath stuff */
1412 (void) rrmdir(tmppath);
1413 free(tmppath);
1414 tmppath = NULL;
1417 if (tmpsymdir) {
1418 /* remove temp symbolic links made for signed pkg */
1419 (void) rrmdir(tmpsymdir);
1420 free(tmpsymdir);
1421 tmpsymdir = NULL;
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);