xref: /titanic_44/usr/src/lib/libpkg/common/dstream.c (revision 4656d4747c8743290bfbe910c64cd75eb4e4af8d)
15c51f124SMoriah Waterland /*
25c51f124SMoriah Waterland  * CDDL HEADER START
35c51f124SMoriah Waterland  *
45c51f124SMoriah Waterland  * The contents of this file are subject to the terms of the
55c51f124SMoriah Waterland  * Common Development and Distribution License (the "License").
65c51f124SMoriah Waterland  * You may not use this file except in compliance with the License.
75c51f124SMoriah Waterland  *
85c51f124SMoriah Waterland  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95c51f124SMoriah Waterland  * or http://www.opensolaris.org/os/licensing.
105c51f124SMoriah Waterland  * See the License for the specific language governing permissions
115c51f124SMoriah Waterland  * and limitations under the License.
125c51f124SMoriah Waterland  *
135c51f124SMoriah Waterland  * When distributing Covered Code, include this CDDL HEADER in each
145c51f124SMoriah Waterland  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155c51f124SMoriah Waterland  * If applicable, add the following below this CDDL HEADER, with the
165c51f124SMoriah Waterland  * fields enclosed by brackets "[]" replaced with your own identifying
175c51f124SMoriah Waterland  * information: Portions Copyright [yyyy] [name of copyright owner]
185c51f124SMoriah Waterland  *
195c51f124SMoriah Waterland  * CDDL HEADER END
205c51f124SMoriah Waterland  */
215c51f124SMoriah Waterland 
225c51f124SMoriah Waterland /*
235c51f124SMoriah Waterland  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
245c51f124SMoriah Waterland  * Use is subject to license terms.
255c51f124SMoriah Waterland  */
265c51f124SMoriah Waterland 
275c51f124SMoriah Waterland /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
285c51f124SMoriah Waterland /* All Rights Reserved */
295c51f124SMoriah Waterland 
305c51f124SMoriah Waterland 
315c51f124SMoriah Waterland 
325c51f124SMoriah Waterland #include <stdio.h>
335c51f124SMoriah Waterland #include <string.h>
345c51f124SMoriah Waterland #include <signal.h>
355c51f124SMoriah Waterland #include <stdlib.h>
365c51f124SMoriah Waterland #include <unistd.h>
375c51f124SMoriah Waterland #include <sys/types.h>
385c51f124SMoriah Waterland #include <sys/param.h>
395c51f124SMoriah Waterland #include <sys/sysmacros.h>
405c51f124SMoriah Waterland #include <errno.h>
415c51f124SMoriah Waterland #include <sys/types.h>
425c51f124SMoriah Waterland #include <sys/stat.h>
435c51f124SMoriah Waterland #include <sys/statvfs.h>
445c51f124SMoriah Waterland #include <fcntl.h>
455c51f124SMoriah Waterland #include <openssl/err.h>
465c51f124SMoriah Waterland #include "pkglib.h"
475c51f124SMoriah Waterland #include "pkglibmsgs.h"
485c51f124SMoriah Waterland #include "pkglocale.h"
495c51f124SMoriah Waterland 
505c51f124SMoriah Waterland /* libadm.a */
515c51f124SMoriah Waterland extern char	*devattr(char *device, char *attribute);
525c51f124SMoriah Waterland extern int	pkgnmchk(register char *pkg, register char *spec,
535c51f124SMoriah Waterland 				int presvr4flg);
545c51f124SMoriah Waterland extern int	getvol(char *device, char *label, int options, char *prompt);
555c51f124SMoriah Waterland 
565c51f124SMoriah Waterland #define	CMDSIZ	512
575c51f124SMoriah Waterland #define	LSIZE	128
585c51f124SMoriah Waterland #define	DDPROC		"/usr/bin/dd"
595c51f124SMoriah Waterland #define	CPIOPROC	"/usr/bin/cpio"
605c51f124SMoriah Waterland 
615c51f124SMoriah Waterland /* device types */
625c51f124SMoriah Waterland 
635c51f124SMoriah Waterland #define	G_TM_TAPE	1   /* Tapemaster controller */
645c51f124SMoriah Waterland #define	G_XY_DISK	3   /* xy disks */
655c51f124SMoriah Waterland #define	G_SD_DISK	7   /* scsi sd disk */
665c51f124SMoriah Waterland #define	G_XT_TAPE	8   /* xt tapes */
675c51f124SMoriah Waterland #define	G_SF_FLOPPY	9   /* sf floppy */
685c51f124SMoriah Waterland #define	G_XD_DISK	10  /* xd disks */
695c51f124SMoriah Waterland #define	G_ST_TAPE	11  /* scsi tape */
705c51f124SMoriah Waterland #define	G_NS		12  /* noswap pseudo-dev */
715c51f124SMoriah Waterland #define	G_RAM		13  /* ram pseudo-dev */
725c51f124SMoriah Waterland #define	G_FT		14  /* tftp */
735c51f124SMoriah Waterland #define	G_HD		15  /* 386 network disk */
745c51f124SMoriah Waterland #define	G_FD		16  /* 386 AT disk */
755c51f124SMoriah Waterland #define	G_FILE		28  /* file, not a device */
765c51f124SMoriah Waterland #define	G_NO_DEV	29  /* device does not require special treatment */
775c51f124SMoriah Waterland #define	G_DEV_MAX	30  /* last valid device type */
785c51f124SMoriah Waterland 
795c51f124SMoriah Waterland struct dstoc {
805c51f124SMoriah Waterland 	int	cnt;
815c51f124SMoriah Waterland 	char	pkg[NON_ABI_NAMELNGTH];
825c51f124SMoriah Waterland 	int	nparts;
835c51f124SMoriah Waterland 	long	maxsiz;
845c51f124SMoriah Waterland 	char    volnos[128];
855c51f124SMoriah Waterland 	struct dstoc *next;
865c51f124SMoriah Waterland } *ds_head, *ds_toc;
875c51f124SMoriah Waterland 
885c51f124SMoriah Waterland #define	ds_nparts	ds_toc->nparts
895c51f124SMoriah Waterland #define	ds_maxsiz	ds_toc->maxsiz
905c51f124SMoriah Waterland 
915c51f124SMoriah Waterland int	ds_totread; 	/* total number of parts read */
925c51f124SMoriah Waterland int	ds_fd = -1;
935c51f124SMoriah Waterland int	ds_curpartcnt = -1;
945c51f124SMoriah Waterland 
955c51f124SMoriah Waterland int	ds_next(char *device, char *instdir);
965c51f124SMoriah Waterland int	ds_ginit(char *device);
975c51f124SMoriah Waterland int	ds_close(int pkgendflg);
985c51f124SMoriah Waterland 
995c51f124SMoriah Waterland static FILE	*ds_pp;
1005c51f124SMoriah Waterland static int	ds_realfd = -1; 	/* file descriptor for real device */
1015c51f124SMoriah Waterland static int	ds_read; 	/* number of parts read for current package */
1025c51f124SMoriah Waterland static int	ds_volno; 	/* volume number of current volume */
1035c51f124SMoriah Waterland static int	ds_volcnt; 	/* total number of volumes */
1045c51f124SMoriah Waterland static char	ds_volnos[128]; 	/* parts/volume info */
1055c51f124SMoriah Waterland static char	*ds_device;
1065c51f124SMoriah Waterland static int	ds_volpart;	/* number of parts read in current volume, */
1075c51f124SMoriah Waterland 						/* including skipped parts */
1085c51f124SMoriah Waterland static int	ds_bufsize;
1095c51f124SMoriah Waterland static int	ds_skippart; 	/* number of parts skipped in current volume */
1105c51f124SMoriah Waterland 
1115c51f124SMoriah Waterland static int	ds_getnextvol(char *device);
1125c51f124SMoriah Waterland static int	ds_skip(char *device, int nskip);
1135c51f124SMoriah Waterland 
1145c51f124SMoriah Waterland void
ds_order(char * list[])1155c51f124SMoriah Waterland ds_order(char *list[])
1165c51f124SMoriah Waterland {
1175c51f124SMoriah Waterland 	struct dstoc *toc_pt;
1185c51f124SMoriah Waterland 	register int j, n;
1195c51f124SMoriah Waterland 	char	*pt;
1205c51f124SMoriah Waterland 
1215c51f124SMoriah Waterland 	toc_pt = ds_head;
1225c51f124SMoriah Waterland 	n = 0;
1235c51f124SMoriah Waterland 	while (toc_pt) {
1245c51f124SMoriah Waterland 		for (j = n; list[j]; j++) {
1255c51f124SMoriah Waterland 			if (strcmp(list[j], toc_pt->pkg) == 0) {
1265c51f124SMoriah Waterland 				/* just swap places in the array */
1275c51f124SMoriah Waterland 				pt = list[n];
1285c51f124SMoriah Waterland 				list[n++] = list[j];
1295c51f124SMoriah Waterland 				list[j] = pt;
1305c51f124SMoriah Waterland 			}
1315c51f124SMoriah Waterland 		}
1325c51f124SMoriah Waterland 		toc_pt = toc_pt->next;
1335c51f124SMoriah Waterland 	}
1345c51f124SMoriah Waterland }
1355c51f124SMoriah Waterland 
1365c51f124SMoriah Waterland static char *pds_header;
1375c51f124SMoriah Waterland static char *ds_header;
1385c51f124SMoriah Waterland static char *ds_header_raw;
1395c51f124SMoriah Waterland static int ds_headsize;
1405c51f124SMoriah Waterland 
1415c51f124SMoriah Waterland static char *
ds_gets(char * buf,int size)1425c51f124SMoriah Waterland ds_gets(char *buf, int size)
1435c51f124SMoriah Waterland {
1445c51f124SMoriah Waterland 	int length;
1455c51f124SMoriah Waterland 	char *nextp;
1465c51f124SMoriah Waterland 
1475c51f124SMoriah Waterland 	nextp = strchr(pds_header, '\n');
1485c51f124SMoriah Waterland 	if (nextp == NULL) {
1495c51f124SMoriah Waterland 		length = strlen(pds_header);
1505c51f124SMoriah Waterland 		if (length > size)
1515c51f124SMoriah Waterland 			return (0);
1525c51f124SMoriah Waterland 		if ((ds_header = (char *)realloc(ds_header,
1535c51f124SMoriah Waterland 		    ds_headsize + BLK_SIZE)) == NULL)
1545c51f124SMoriah Waterland 			return (0);
1555c51f124SMoriah Waterland 		if (read(ds_fd, ds_header + ds_headsize, BLK_SIZE) < BLK_SIZE)
1565c51f124SMoriah Waterland 			return (0);
1575c51f124SMoriah Waterland 		ds_headsize += BLK_SIZE;
1585c51f124SMoriah Waterland 		nextp = strchr(pds_header, '\n');
1595c51f124SMoriah Waterland 		if (nextp == NULL)
1605c51f124SMoriah Waterland 			return (0);
1615c51f124SMoriah Waterland 		*nextp = '\0';
1625c51f124SMoriah Waterland 		if (length + (int)strlen(pds_header) > size)
1635c51f124SMoriah Waterland 			return (0);
1645c51f124SMoriah Waterland 		(void) strncpy(buf + length, pds_header, strlen(pds_header));
1655c51f124SMoriah Waterland 		buf[length + strlen(pds_header)] = '\0';
1665c51f124SMoriah Waterland 		pds_header = nextp + 1;
1675c51f124SMoriah Waterland 		return (buf);
1685c51f124SMoriah Waterland 	}
1695c51f124SMoriah Waterland 	*nextp = '\0';
1705c51f124SMoriah Waterland 	if ((int)strlen(pds_header) > size)
1715c51f124SMoriah Waterland 		return (0);
1725c51f124SMoriah Waterland 	(void) strncpy(buf, pds_header, strlen(pds_header));
1735c51f124SMoriah Waterland 	buf[strlen(pds_header)] = '\0';
1745c51f124SMoriah Waterland 	pds_header = nextp + 1;
1755c51f124SMoriah Waterland 	return (buf);
1765c51f124SMoriah Waterland }
1775c51f124SMoriah Waterland 
1785c51f124SMoriah Waterland /*
1795c51f124SMoriah Waterland  * function to determine if media is datastream or mounted
1805c51f124SMoriah Waterland  * floppy
1815c51f124SMoriah Waterland  */
1825c51f124SMoriah Waterland int
ds_readbuf(char * device)1835c51f124SMoriah Waterland ds_readbuf(char *device)
1845c51f124SMoriah Waterland {
1855c51f124SMoriah Waterland 	char buf[BLK_SIZE];
1865c51f124SMoriah Waterland 
1875c51f124SMoriah Waterland 	if (ds_fd >= 0)
1885c51f124SMoriah Waterland 		(void) close(ds_fd);
1895c51f124SMoriah Waterland 	if ((ds_fd = open(device, O_RDONLY)) >= 0 &&
1905c51f124SMoriah Waterland 	    read(ds_fd, buf, BLK_SIZE) == BLK_SIZE &&
1915c51f124SMoriah Waterland 	    strncmp(buf, HDR_PREFIX, 20) == 0) {
1925c51f124SMoriah Waterland 		if ((ds_header = (char *)calloc(BLK_SIZE, 1)) == NULL) {
1935c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
1945c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_MEM));
1955c51f124SMoriah Waterland 			(void) ds_close(0);
1965c51f124SMoriah Waterland 			return (0);
1975c51f124SMoriah Waterland 		}
198*4656d474SGarrett D'Amore 		(void) memcpy(ds_header, buf, BLK_SIZE);
1995c51f124SMoriah Waterland 		ds_headsize = BLK_SIZE;
2005c51f124SMoriah Waterland 
2015c51f124SMoriah Waterland 		if (ds_ginit(device) < 0) {
2025c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
2035c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_OPEN), device, errno);
2045c51f124SMoriah Waterland 			(void) ds_close(0);
2055c51f124SMoriah Waterland 			return (0);
2065c51f124SMoriah Waterland 		}
2075c51f124SMoriah Waterland 		return (1);
2085c51f124SMoriah Waterland 	} else if (ds_fd >= 0) {
2095c51f124SMoriah Waterland 		(void) close(ds_fd);
2105c51f124SMoriah Waterland 		ds_fd = -1;
2115c51f124SMoriah Waterland 	}
2125c51f124SMoriah Waterland 	return (0);
2135c51f124SMoriah Waterland }
2145c51f124SMoriah Waterland 
2155c51f124SMoriah Waterland /*
2165c51f124SMoriah Waterland  * Determine how many additional volumes are needed for current package.
2175c51f124SMoriah Waterland  * Note: a 0 will occur as first volume number when the package begins
2185c51f124SMoriah Waterland  * on the next volume.
2195c51f124SMoriah Waterland  */
2205c51f124SMoriah Waterland static int
ds_volsum(struct dstoc * toc)2215c51f124SMoriah Waterland ds_volsum(struct dstoc *toc)
2225c51f124SMoriah Waterland {
2235c51f124SMoriah Waterland 	int curpartcnt, volcnt;
2245c51f124SMoriah Waterland 	char volnos[128], tmpvol[128];
2255c51f124SMoriah Waterland 	if (toc->volnos[0]) {
2265c51f124SMoriah Waterland 		int index, sum;
227*4656d474SGarrett D'Amore 		(void) sscanf(toc->volnos, "%d %[ 0-9]", &curpartcnt, volnos);
2285c51f124SMoriah Waterland 		volcnt = 0;
2295c51f124SMoriah Waterland 		sum = curpartcnt;
2305c51f124SMoriah Waterland 		while (sum < toc->nparts && sscanf(volnos, "%d %[ 0-9]",
2315c51f124SMoriah Waterland 		    &index, tmpvol) >= 1) {
2325c51f124SMoriah Waterland 			(void) strcpy(volnos, tmpvol);
2335c51f124SMoriah Waterland 			volcnt++;
2345c51f124SMoriah Waterland 			sum += index;
2355c51f124SMoriah Waterland 		}
2365c51f124SMoriah Waterland 		/* side effect - set number of parts read on current volume */
2375c51f124SMoriah Waterland 		ds_volpart = index;
2385c51f124SMoriah Waterland 		return (volcnt);
2395c51f124SMoriah Waterland 	}
2405c51f124SMoriah Waterland 	ds_volpart += toc->nparts;
2415c51f124SMoriah Waterland 	return (0);
2425c51f124SMoriah Waterland }
2435c51f124SMoriah Waterland 
2445c51f124SMoriah Waterland /* initialize ds_curpartcnt and ds_volnos */
2455c51f124SMoriah Waterland static void
ds_pkginit(void)2465c51f124SMoriah Waterland ds_pkginit(void)
2475c51f124SMoriah Waterland {
2485c51f124SMoriah Waterland 	if (ds_toc->volnos[0])
249*4656d474SGarrett D'Amore 		(void) sscanf(ds_toc->volnos, "%d %[ 0-9]", &ds_curpartcnt,
250*4656d474SGarrett D'Amore 		    ds_volnos);
2515c51f124SMoriah Waterland 	else
2525c51f124SMoriah Waterland 		ds_curpartcnt = -1;
2535c51f124SMoriah Waterland }
2545c51f124SMoriah Waterland 
2555c51f124SMoriah Waterland /*
2565c51f124SMoriah Waterland  * functions to pass current package info to exec'ed program
2575c51f124SMoriah Waterland  */
2585c51f124SMoriah Waterland void
ds_putinfo(char * buf,size_t sz)259*4656d474SGarrett D'Amore ds_putinfo(char *buf, size_t sz)
2605c51f124SMoriah Waterland {
261*4656d474SGarrett D'Amore 	(void) snprintf(buf, sz, "%d %d %d %d %d %d %d %d %d %d %s",
2625c51f124SMoriah Waterland 	    ds_fd, ds_realfd, ds_volcnt, ds_volno, ds_totread, ds_volpart,
2635c51f124SMoriah Waterland 	    ds_skippart, ds_bufsize, ds_toc->nparts, ds_toc->maxsiz,
2645c51f124SMoriah Waterland 	    ds_toc->volnos);
2655c51f124SMoriah Waterland }
2665c51f124SMoriah Waterland 
2675c51f124SMoriah Waterland int
ds_getinfo(char * string)2685c51f124SMoriah Waterland ds_getinfo(char *string)
2695c51f124SMoriah Waterland {
2705c51f124SMoriah Waterland 	ds_toc = (struct dstoc *)calloc(1, sizeof (struct dstoc));
2715c51f124SMoriah Waterland 	(void) sscanf(string, "%d %d %d %d %d %d %d %d %d %d %[ 0-9]",
2725c51f124SMoriah Waterland 	    &ds_fd, &ds_realfd, &ds_volcnt, &ds_volno, &ds_totread,
2735c51f124SMoriah Waterland 	    &ds_volpart, &ds_skippart, &ds_bufsize, &ds_toc->nparts,
2745c51f124SMoriah Waterland 	    &ds_toc->maxsiz, ds_toc->volnos);
2755c51f124SMoriah Waterland 	ds_pkginit();
2765c51f124SMoriah Waterland 	return (ds_toc->nparts);
2775c51f124SMoriah Waterland }
2785c51f124SMoriah Waterland 
2795c51f124SMoriah Waterland /*
2805c51f124SMoriah Waterland  * Return true if the file descriptor (ds_fd) is open on the package stream.
2815c51f124SMoriah Waterland  */
2825c51f124SMoriah Waterland boolean_t
ds_fd_open(void)2835c51f124SMoriah Waterland ds_fd_open(void)
2845c51f124SMoriah Waterland {
2855c51f124SMoriah Waterland 	return (ds_fd >= 0 ? B_TRUE : B_FALSE);
2865c51f124SMoriah Waterland }
2875c51f124SMoriah Waterland 
2885c51f124SMoriah Waterland /*
2895c51f124SMoriah Waterland  * Read the source device. Acquire the header data and check it for validity.
2905c51f124SMoriah Waterland  */
2915c51f124SMoriah Waterland int
ds_init(char * device,char ** pkg,char * norewind)2925c51f124SMoriah Waterland ds_init(char *device, char **pkg, char *norewind)
2935c51f124SMoriah Waterland {
2945c51f124SMoriah Waterland 	struct dstoc *tail, *toc_pt;
2955c51f124SMoriah Waterland 	char	*ret;
2965c51f124SMoriah Waterland 	char	cmd[CMDSIZ];
2975c51f124SMoriah Waterland 	char	line[LSIZE+1];
2985c51f124SMoriah Waterland 	int	i, n, count = 0, header_size = BLK_SIZE;
2995c51f124SMoriah Waterland 
3005c51f124SMoriah Waterland 	if (!ds_header) { 	/* If the header hasn't been read yet */
3015c51f124SMoriah Waterland 		if (ds_fd >= 0)
3025c51f124SMoriah Waterland 			(void) ds_close(0);
3035c51f124SMoriah Waterland 
3045c51f124SMoriah Waterland 		/* always start with rewind device */
3055c51f124SMoriah Waterland 		if ((ds_fd = open(device, O_RDONLY)) < 0) {
3065c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
3075c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_OPEN), device, errno);
3085c51f124SMoriah Waterland 			return (-1);
3095c51f124SMoriah Waterland 		}
3105c51f124SMoriah Waterland 
3115c51f124SMoriah Waterland 		/* allocate room for the header equivalent to a block */
3125c51f124SMoriah Waterland 		if ((ds_header = (char *)calloc(BLK_SIZE, 1)) == NULL) {
3135c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
3145c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_MEM));
3155c51f124SMoriah Waterland 			return (-1);
3165c51f124SMoriah Waterland 		}
3175c51f124SMoriah Waterland 
3185c51f124SMoriah Waterland 		/* initialize the device */
3195c51f124SMoriah Waterland 		if (ds_ginit(device) < 0) {
3205c51f124SMoriah Waterland 			(void) ds_close(0);
3215c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
3225c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_OPEN), device, errno);
3235c51f124SMoriah Waterland 			return (-1);
3245c51f124SMoriah Waterland 		}
3255c51f124SMoriah Waterland 
3265c51f124SMoriah Waterland 		/* read a logical block from the source device */
3275c51f124SMoriah Waterland 		if (read(ds_fd, ds_header, BLK_SIZE) != BLK_SIZE) {
3285c51f124SMoriah Waterland 			rpterr();
3295c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
3305c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_TOC));
3315c51f124SMoriah Waterland 			(void) ds_close(0);
3325c51f124SMoriah Waterland 			return (-1);
3335c51f124SMoriah Waterland 		}
3345c51f124SMoriah Waterland 
3355c51f124SMoriah Waterland 		/*
3365c51f124SMoriah Waterland 		 * This loop scans the medium for the start of the header.
3375c51f124SMoriah Waterland 		 * If the above read worked, we skip this. If it did't, this
3385c51f124SMoriah Waterland 		 * loop will retry the read ten times looking for the header
3395c51f124SMoriah Waterland 		 * marker string.
3405c51f124SMoriah Waterland 		 */
3415c51f124SMoriah Waterland 		while (strncmp(ds_header, HDR_PREFIX, 20) != 0) {
3425c51f124SMoriah Waterland 			/* only ten tries iff the device rewinds */
3435c51f124SMoriah Waterland 			if (!norewind || count++ > 10) {
3445c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_UNPACK));
3455c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_TOC));
3465c51f124SMoriah Waterland 				(void) ds_close(0);
3475c51f124SMoriah Waterland 				return (-1);
3485c51f124SMoriah Waterland 			}
3495c51f124SMoriah Waterland 
3505c51f124SMoriah Waterland 			/* read through to the last block */
3515c51f124SMoriah Waterland 			if (count > 1)
3525c51f124SMoriah Waterland 				while (read(ds_fd, ds_header, BLK_SIZE) > 0)
3535c51f124SMoriah Waterland 					;
3545c51f124SMoriah Waterland 
3555c51f124SMoriah Waterland 			/* then close the device */
3565c51f124SMoriah Waterland 			(void) ds_close(0);
3575c51f124SMoriah Waterland 
3585c51f124SMoriah Waterland 			/* and reopen it */
3595c51f124SMoriah Waterland 			if ((ds_fd = open(norewind, O_RDONLY)) < 0) {
3605c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_UNPACK));
3615c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_OPEN), device, errno);
3625c51f124SMoriah Waterland 				(void) free(ds_header);
3635c51f124SMoriah Waterland 				return (-1);
3645c51f124SMoriah Waterland 			}
3655c51f124SMoriah Waterland 
3665c51f124SMoriah Waterland 			/* initialize the device */
3675c51f124SMoriah Waterland 			if (ds_ginit(device) < 0) {
3685c51f124SMoriah Waterland 				(void) ds_close(0);
3695c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_UNPACK));
3705c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_OPEN), device, errno);
3715c51f124SMoriah Waterland 				return (-1);
3725c51f124SMoriah Waterland 			}
3735c51f124SMoriah Waterland 
3745c51f124SMoriah Waterland 			/* read the block again */
3755c51f124SMoriah Waterland 			if (read(ds_fd, ds_header, BLK_SIZE) != BLK_SIZE) {
3765c51f124SMoriah Waterland 				rpterr();
3775c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_UNPACK));
3785c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_TOC));
3795c51f124SMoriah Waterland 				(void) ds_close(0);
3805c51f124SMoriah Waterland 				return (-1);
3815c51f124SMoriah Waterland 			}
3825c51f124SMoriah Waterland 		}
3835c51f124SMoriah Waterland 
3845c51f124SMoriah Waterland 		/* Now keep scanning until the whole header is in place. */
3855c51f124SMoriah Waterland 		while (strstr(ds_header, HDR_SUFFIX) == NULL) {
3865c51f124SMoriah Waterland 			/* We need a bigger buffer */
3875c51f124SMoriah Waterland 			if ((ds_header = (char *)realloc(ds_header,
3885c51f124SMoriah Waterland 			    header_size + BLK_SIZE)) == NULL) {
3895c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_UNPACK));
3905c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_MEM));
3915c51f124SMoriah Waterland 				(void) ds_close(0);
3925c51f124SMoriah Waterland 				return (1);
3935c51f124SMoriah Waterland 			}
3945c51f124SMoriah Waterland 
3955c51f124SMoriah Waterland 			/* clear the new memory */
3965c51f124SMoriah Waterland 			(void) memset(ds_header + header_size, '\0',
3975c51f124SMoriah Waterland 			    BLK_SIZE);
3985c51f124SMoriah Waterland 
3995c51f124SMoriah Waterland 
4005c51f124SMoriah Waterland 			/* read a logical block from the source device */
4015c51f124SMoriah Waterland 			if (read(ds_fd, ds_header + header_size, BLK_SIZE) !=
4025c51f124SMoriah Waterland 			    BLK_SIZE) {
4035c51f124SMoriah Waterland 				rpterr();
4045c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_UNPACK));
4055c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_TOC));
4065c51f124SMoriah Waterland 				(void) ds_close(0);
4075c51f124SMoriah Waterland 				return (-1);
4085c51f124SMoriah Waterland 			} else
4095c51f124SMoriah Waterland 				header_size += BLK_SIZE;	/* new size */
4105c51f124SMoriah Waterland 		}
4115c51f124SMoriah Waterland 
4125c51f124SMoriah Waterland 		/*
4135c51f124SMoriah Waterland 		 * remember rewind device for ds_close to rewind at
4145c51f124SMoriah Waterland 		 * close
4155c51f124SMoriah Waterland 		 */
4165c51f124SMoriah Waterland 		if (count >= 1)
4175c51f124SMoriah Waterland 			ds_device = device;
4185c51f124SMoriah Waterland 		ds_headsize = header_size;
4195c51f124SMoriah Waterland 
4205c51f124SMoriah Waterland 	}
4215c51f124SMoriah Waterland 
4225c51f124SMoriah Waterland 	pds_header = ds_header;
4235c51f124SMoriah Waterland 
4245c51f124SMoriah Waterland 	/* save raw copy of header for later use in BIO_dump_header */
4255c51f124SMoriah Waterland 	if ((ds_header_raw = (char *)malloc(header_size)) == NULL) {
4265c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_UNPACK));
4275c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_MEM));
4285c51f124SMoriah Waterland 		(void) ds_close(0);
4295c51f124SMoriah Waterland 		return (1);
4305c51f124SMoriah Waterland 	}
431*4656d474SGarrett D'Amore 	(void) memcpy(ds_header_raw, ds_header, header_size);
4325c51f124SMoriah Waterland 
4335c51f124SMoriah Waterland 	/* read datastream table of contents */
4345c51f124SMoriah Waterland 	ds_head = tail = (struct dstoc *)0;
4355c51f124SMoriah Waterland 	ds_volcnt = 1;
4365c51f124SMoriah Waterland 
4375c51f124SMoriah Waterland 	while (ret = ds_gets(line, LSIZE)) {
4385c51f124SMoriah Waterland 		if (strcmp(line, HDR_SUFFIX) == 0)
4395c51f124SMoriah Waterland 			break;
4405c51f124SMoriah Waterland 		if (!line[0] || line[0] == '#')
4415c51f124SMoriah Waterland 			continue;
4425c51f124SMoriah Waterland 		toc_pt = (struct dstoc *)calloc(1, sizeof (struct dstoc));
4435c51f124SMoriah Waterland 		if (!toc_pt) {
4445c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
4455c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_MEM));
4465c51f124SMoriah Waterland 			ecleanup();
4475c51f124SMoriah Waterland 			(void) free(ds_header);
4485c51f124SMoriah Waterland 			return (-1);
4495c51f124SMoriah Waterland 		}
450*4656d474SGarrett D'Amore 		/* LINTED E_SEC_SCANF_UNBOUNDED_COPY */
4515c51f124SMoriah Waterland 		if (sscanf(line, "%s %d %d %[ 0-9]", toc_pt->pkg,
4525c51f124SMoriah Waterland 		    &toc_pt->nparts, &toc_pt->maxsiz, toc_pt->volnos) < 3) {
4535c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
4545c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_TOC));
4555c51f124SMoriah Waterland 			free(toc_pt);
4565c51f124SMoriah Waterland 			(void) free(ds_header);
4575c51f124SMoriah Waterland 			ecleanup();
4585c51f124SMoriah Waterland 			return (-1);
4595c51f124SMoriah Waterland 		}
4605c51f124SMoriah Waterland 		if (tail) {
4615c51f124SMoriah Waterland 			tail->next = toc_pt;
4625c51f124SMoriah Waterland 			tail = toc_pt;
4635c51f124SMoriah Waterland 		} else
4645c51f124SMoriah Waterland 			ds_head = tail = toc_pt;
4655c51f124SMoriah Waterland 		ds_volcnt += ds_volsum(toc_pt);
4665c51f124SMoriah Waterland 	}
4675c51f124SMoriah Waterland 	if (!ret) {
4685c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_UNPACK));
4695c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_TOC));
4705c51f124SMoriah Waterland 		(void) free(ds_header);
4715c51f124SMoriah Waterland 		return (-1);
4725c51f124SMoriah Waterland 	}
473*4656d474SGarrett D'Amore 	(void) sighold(SIGINT);
474*4656d474SGarrett D'Amore 	(void) sigrelse(SIGINT);
4755c51f124SMoriah Waterland 	if (!ds_head) {
4765c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_UNPACK));
4775c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_EMPTY));
4785c51f124SMoriah Waterland 		(void) free(ds_header);
4795c51f124SMoriah Waterland 		return (-1);
4805c51f124SMoriah Waterland 	}
4815c51f124SMoriah Waterland 	/* this could break, thanks to cpio command limit */
482*4656d474SGarrett D'Amore 	(void) snprintf(cmd, sizeof (cmd), "%s -icdumD -C %d",
483*4656d474SGarrett D'Amore 	    CPIOPROC, (int)BLK_SIZE);
4845c51f124SMoriah Waterland 	n = 0;
4855c51f124SMoriah Waterland 	for (i = 0; pkg[i]; i++) {
4865c51f124SMoriah Waterland 		if (strcmp(pkg[i], "all") == 0)
4875c51f124SMoriah Waterland 			continue;
4885c51f124SMoriah Waterland 		if (n == 0) {
489*4656d474SGarrett D'Amore 			(void) strlcat(cmd, " ", CMDSIZ);
4905c51f124SMoriah Waterland 			n = 1;
4915c51f124SMoriah Waterland 		}
492*4656d474SGarrett D'Amore 		(void) strlcat(cmd, pkg[i], CMDSIZ);
493*4656d474SGarrett D'Amore 		(void) strlcat(cmd, "'/*' ", CMDSIZ);
4945c51f124SMoriah Waterland 
4955c51f124SMoriah Waterland 		/* extract signature too, if present. */
496*4656d474SGarrett D'Amore 		(void) strlcat(cmd, SIGNATURE_FILENAME, CMDSIZ);
497*4656d474SGarrett D'Amore 		(void) strlcat(cmd, " ", CMDSIZ);
4985c51f124SMoriah Waterland 	}
4995c51f124SMoriah Waterland 
5005c51f124SMoriah Waterland 	/*
5015c51f124SMoriah Waterland 	 * if we are extracting all packages (pkgs == NULL),
5025c51f124SMoriah Waterland 	 * signature will automatically be extracted
5035c51f124SMoriah Waterland 	 */
5045c51f124SMoriah Waterland 	if (n = esystem(cmd, ds_fd, -1)) {
5055c51f124SMoriah Waterland 		rpterr();
5065c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_UNPACK));
5075c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_CMDFAIL), cmd, n);
5085c51f124SMoriah Waterland 		(void) free(ds_header);
5095c51f124SMoriah Waterland 		return (-1);
5105c51f124SMoriah Waterland 	}
5115c51f124SMoriah Waterland 
5125c51f124SMoriah Waterland 	ds_toc = ds_head;
5135c51f124SMoriah Waterland 	ds_totread = 0;
5145c51f124SMoriah Waterland 	ds_volno = 1;
5155c51f124SMoriah Waterland 	return (0);
5165c51f124SMoriah Waterland }
5175c51f124SMoriah Waterland 
5185c51f124SMoriah Waterland int
ds_findpkg(char * device,char * pkg)5195c51f124SMoriah Waterland ds_findpkg(char *device, char *pkg)
5205c51f124SMoriah Waterland {
5215c51f124SMoriah Waterland 	char	*pkglist[2];
5225c51f124SMoriah Waterland 	int	nskip, ods_volpart;
5235c51f124SMoriah Waterland 
5245c51f124SMoriah Waterland 	if (ds_head == NULL) {
5255c51f124SMoriah Waterland 		pkglist[0] = pkg;
5265c51f124SMoriah Waterland 		pkglist[1] = NULL;
5275c51f124SMoriah Waterland 		if (ds_init(device, pkglist, NULL))
5285c51f124SMoriah Waterland 			return (-1);
5295c51f124SMoriah Waterland 	}
5305c51f124SMoriah Waterland 
5315c51f124SMoriah Waterland 	if (!pkg || pkgnmchk(pkg, "all", 0)) {
5325c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_UNPACK));
5335c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_PKGNAME));
5345c51f124SMoriah Waterland 		return (-1);
5355c51f124SMoriah Waterland 	}
5365c51f124SMoriah Waterland 
5375c51f124SMoriah Waterland 	nskip = 0;
5385c51f124SMoriah Waterland 	ds_volno = 1;
5395c51f124SMoriah Waterland 	ds_volpart = 0;
5405c51f124SMoriah Waterland 	ds_toc = ds_head;
5415c51f124SMoriah Waterland 	while (ds_toc) {
5425c51f124SMoriah Waterland 		if (strcmp(ds_toc->pkg, pkg) == 0)
5435c51f124SMoriah Waterland 			break;
5445c51f124SMoriah Waterland 		nskip += ds_toc->nparts;
5455c51f124SMoriah Waterland 		ds_volno += ds_volsum(ds_toc);
5465c51f124SMoriah Waterland 		ds_toc = ds_toc->next;
5475c51f124SMoriah Waterland 	}
5485c51f124SMoriah Waterland 	if (!ds_toc) {
5495c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_UNPACK));
5505c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_NOPKG), pkg);
5515c51f124SMoriah Waterland 		return (-1);
5525c51f124SMoriah Waterland 	}
5535c51f124SMoriah Waterland 
5545c51f124SMoriah Waterland 	ds_pkginit();
5555c51f124SMoriah Waterland 	ds_skippart = 0;
5565c51f124SMoriah Waterland 	if (ds_curpartcnt > 0) {
5575c51f124SMoriah Waterland 		ods_volpart = ds_volpart;
5585c51f124SMoriah Waterland 		/*
5595c51f124SMoriah Waterland 		 * skip past archives belonging to last package on current
5605c51f124SMoriah Waterland 		 * volume
5615c51f124SMoriah Waterland 		 */
5625c51f124SMoriah Waterland 		if (ds_volpart > 0 && ds_getnextvol(device))
5635c51f124SMoriah Waterland 			return (-1);
5645c51f124SMoriah Waterland 		ds_totread = nskip - ods_volpart;
5655c51f124SMoriah Waterland 		if (ds_skip(device, ods_volpart))
5665c51f124SMoriah Waterland 			return (-1);
5675c51f124SMoriah Waterland 	} else if (ds_curpartcnt < 0) {
5685c51f124SMoriah Waterland 		if (ds_skip(device, nskip - ds_totread))
5695c51f124SMoriah Waterland 			return (-1);
5705c51f124SMoriah Waterland 	} else
5715c51f124SMoriah Waterland 		ds_totread = nskip;
5725c51f124SMoriah Waterland 	ds_read = 0;
5735c51f124SMoriah Waterland 	return (ds_nparts);
5745c51f124SMoriah Waterland }
5755c51f124SMoriah Waterland 
5765c51f124SMoriah Waterland /*
5775c51f124SMoriah Waterland  * Get datastream part
5785c51f124SMoriah Waterland  * Call for first part should be preceded by
5795c51f124SMoriah Waterland  * call to ds_findpkg
5805c51f124SMoriah Waterland  */
5815c51f124SMoriah Waterland 
5825c51f124SMoriah Waterland int
ds_getpkg(char * device,int n,char * dstdir)5835c51f124SMoriah Waterland ds_getpkg(char *device, int n, char *dstdir)
5845c51f124SMoriah Waterland {
5855c51f124SMoriah Waterland 	struct statvfs64 svfsb;
5865c51f124SMoriah Waterland 	u_longlong_t free_blocks;
5875c51f124SMoriah Waterland 
5885c51f124SMoriah Waterland 	if (ds_read >= ds_nparts)
5895c51f124SMoriah Waterland 		return (2);
5905c51f124SMoriah Waterland 
5915c51f124SMoriah Waterland 	if (ds_read == n)
5925c51f124SMoriah Waterland 		return (0);
5935c51f124SMoriah Waterland 	else if ((ds_read > n) || (n > ds_nparts))
5945c51f124SMoriah Waterland 		return (2);
5955c51f124SMoriah Waterland 
5965c51f124SMoriah Waterland 	if (ds_maxsiz > 0) {
5975c51f124SMoriah Waterland 		if (statvfs64(".", &svfsb)) {
5985c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
5995c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_STATFS), errno);
6005c51f124SMoriah Waterland 			return (-1);
6015c51f124SMoriah Waterland 		}
6025c51f124SMoriah Waterland 		free_blocks = (((long)svfsb.f_frsize > 0) ?
6035c51f124SMoriah Waterland 		    howmany(svfsb.f_frsize, DEV_BSIZE) :
6045c51f124SMoriah Waterland 		    howmany(svfsb.f_bsize, DEV_BSIZE)) * svfsb.f_bfree;
6055c51f124SMoriah Waterland 		if ((ds_maxsiz + 50) > free_blocks) {
6065c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
6075c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_NOSPACE), ds_maxsiz+50, free_blocks);
6085c51f124SMoriah Waterland 			return (-1);
6095c51f124SMoriah Waterland 		}
6105c51f124SMoriah Waterland 	}
6115c51f124SMoriah Waterland 	return (ds_next(device, dstdir));
6125c51f124SMoriah Waterland }
6135c51f124SMoriah Waterland 
6145c51f124SMoriah Waterland static int
ds_getnextvol(char * device)6155c51f124SMoriah Waterland ds_getnextvol(char *device)
6165c51f124SMoriah Waterland {
6175c51f124SMoriah Waterland 	char prompt[128];
6185c51f124SMoriah Waterland 	int n;
6195c51f124SMoriah Waterland 
6205c51f124SMoriah Waterland 	if (ds_close(0))
6215c51f124SMoriah Waterland 		return (-1);
6225c51f124SMoriah Waterland 	(void) sprintf(prompt,
6235c51f124SMoriah Waterland 	    pkg_gt("Insert %%v %d of %d into %%p"),
6245c51f124SMoriah Waterland 	    ds_volno, ds_volcnt);
6255c51f124SMoriah Waterland 	if (n = getvol(device, NULL, NULL, prompt))
6265c51f124SMoriah Waterland 		return (n);
6275c51f124SMoriah Waterland 	if ((ds_fd = open(device, O_RDONLY)) < 0)
6285c51f124SMoriah Waterland 		return (-1);
6295c51f124SMoriah Waterland 	if (ds_ginit(device) < 0) {
6305c51f124SMoriah Waterland 		(void) ds_close(0);
6315c51f124SMoriah Waterland 		return (-1);
6325c51f124SMoriah Waterland 	}
6335c51f124SMoriah Waterland 	ds_volpart = 0;
6345c51f124SMoriah Waterland 	return (0);
6355c51f124SMoriah Waterland }
6365c51f124SMoriah Waterland 
6375c51f124SMoriah Waterland /*
6385c51f124SMoriah Waterland  * called by ds_findpkg to skip past archives for unwanted packages
6395c51f124SMoriah Waterland  * in current volume
6405c51f124SMoriah Waterland  */
6415c51f124SMoriah Waterland static int
ds_skip(char * device,int nskip)6425c51f124SMoriah Waterland ds_skip(char *device, int nskip)
6435c51f124SMoriah Waterland {
6445c51f124SMoriah Waterland 	char	cmd[CMDSIZ];
6455c51f124SMoriah Waterland 	int	n, onskip = nskip;
6465c51f124SMoriah Waterland 
6475c51f124SMoriah Waterland 	while (nskip--) {
6485c51f124SMoriah Waterland 		/* skip this one */
649*4656d474SGarrett D'Amore 		(void) snprintf(cmd, sizeof (cmd),
650*4656d474SGarrett D'Amore 		    "%s -ictD -C %d > /dev/null", CPIOPROC, (int)BLK_SIZE);
6515c51f124SMoriah Waterland 		if (n = esystem(cmd, ds_fd, -1)) {
6525c51f124SMoriah Waterland 			rpterr();
6535c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
6545c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_CMDFAIL), cmd, n);
6555c51f124SMoriah Waterland 			nskip = onskip;
6565c51f124SMoriah Waterland 			if (ds_volno == 1 || ds_volpart > 0)
6575c51f124SMoriah Waterland 				return (n);
6585c51f124SMoriah Waterland 			if (n = ds_getnextvol(device))
6595c51f124SMoriah Waterland 				return (n);
6605c51f124SMoriah Waterland 		}
6615c51f124SMoriah Waterland 	}
6625c51f124SMoriah Waterland 	ds_totread += onskip;
6635c51f124SMoriah Waterland 	ds_volpart = onskip;
6645c51f124SMoriah Waterland 	ds_skippart = onskip;
6655c51f124SMoriah Waterland 	return (0);
6665c51f124SMoriah Waterland }
6675c51f124SMoriah Waterland 
6685c51f124SMoriah Waterland /* skip to end of package if necessary */
6695c51f124SMoriah Waterland void
ds_skiptoend(char * device)6705c51f124SMoriah Waterland ds_skiptoend(char *device)
6715c51f124SMoriah Waterland {
6725c51f124SMoriah Waterland 	if (ds_read < ds_nparts && ds_curpartcnt < 0)
6735c51f124SMoriah Waterland 		(void) ds_skip(device, ds_nparts - ds_read);
6745c51f124SMoriah Waterland }
6755c51f124SMoriah Waterland 
6765c51f124SMoriah Waterland int
ds_next(char * device,char * instdir)6775c51f124SMoriah Waterland ds_next(char *device, char *instdir)
6785c51f124SMoriah Waterland {
6795c51f124SMoriah Waterland 	char	cmd[CMDSIZ], tmpvol[128];
6805c51f124SMoriah Waterland 	int	nparts, n, index;
6815c51f124SMoriah Waterland 
6825c51f124SMoriah Waterland 	/*CONSTCOND*/
6835c51f124SMoriah Waterland 	while (1) {
6845c51f124SMoriah Waterland 		if (ds_read + 1 > ds_curpartcnt && ds_curpartcnt >= 0) {
6855c51f124SMoriah Waterland 			ds_volno++;
6865c51f124SMoriah Waterland 			if (n = ds_getnextvol(device))
6875c51f124SMoriah Waterland 				return (n);
6885c51f124SMoriah Waterland 			(void) sscanf(ds_volnos, "%d %[ 0-9]", &index, tmpvol);
6895c51f124SMoriah Waterland 			(void) strcpy(ds_volnos, tmpvol);
6905c51f124SMoriah Waterland 			ds_curpartcnt += index;
6915c51f124SMoriah Waterland 		}
692*4656d474SGarrett D'Amore 		(void) snprintf(cmd, sizeof (cmd), "%s -icdumD -C %d",
6935c51f124SMoriah Waterland 		    CPIOPROC, (int)BLK_SIZE);
6945c51f124SMoriah Waterland 		if (n = esystem(cmd, ds_fd, -1)) {
6955c51f124SMoriah Waterland 			rpterr();
6965c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
6975c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_CMDFAIL), cmd, n);
6985c51f124SMoriah Waterland 		}
6995c51f124SMoriah Waterland 		if (ds_read == 0)
7005c51f124SMoriah Waterland 			nparts = 0;
7015c51f124SMoriah Waterland 		else
7025c51f124SMoriah Waterland 			nparts = ds_toc->nparts;
7035c51f124SMoriah Waterland 		if (n || (n = ckvolseq(instdir, ds_read + 1, nparts))) {
7045c51f124SMoriah Waterland 			if (ds_volno == 1 || ds_volpart > ds_skippart)
7055c51f124SMoriah Waterland 				return (-1);
7065c51f124SMoriah Waterland 
7075c51f124SMoriah Waterland 			if (n = ds_getnextvol(device))
7085c51f124SMoriah Waterland 				return (n);
7095c51f124SMoriah Waterland 			continue;
7105c51f124SMoriah Waterland 		}
7115c51f124SMoriah Waterland 		ds_read++;
7125c51f124SMoriah Waterland 		ds_totread++;
7135c51f124SMoriah Waterland 		ds_volpart++;
7145c51f124SMoriah Waterland 
7155c51f124SMoriah Waterland 		return (0);
7165c51f124SMoriah Waterland 	}
7175c51f124SMoriah Waterland 	/*NOTREACHED*/
7185c51f124SMoriah Waterland }
7195c51f124SMoriah Waterland 
7205c51f124SMoriah Waterland /*
7215c51f124SMoriah Waterland  * Name:		BIO_ds_dump
7225c51f124SMoriah Waterland  * Description:	Dumps all data from the static 'ds_fd' file handle into
7235c51f124SMoriah Waterland  *		the supplied BIO.
7245c51f124SMoriah Waterland  *
7255c51f124SMoriah Waterland  * Arguments:	err - where to record any errors.
7265c51f124SMoriah Waterland  *		device - Description of device being dumped into,
7275c51f124SMoriah Waterland  *			for error reporting
7285c51f124SMoriah Waterland  *		bio - BIO object to dump data into
7295c51f124SMoriah Waterland  *
7305c51f124SMoriah Waterland  * Returns :	zero - successfully dumped all data to EOF
7315c51f124SMoriah Waterland  *		non-zero - some failure occurred.
7325c51f124SMoriah Waterland  */
7335c51f124SMoriah Waterland int
BIO_ds_dump(PKG_ERR * err,char * device,BIO * bio)7345c51f124SMoriah Waterland BIO_ds_dump(PKG_ERR *err, char *device, BIO *bio)
7355c51f124SMoriah Waterland {
7365c51f124SMoriah Waterland 	int	amtread;
7375c51f124SMoriah Waterland 	char	readbuf[BLK_SIZE];
7385c51f124SMoriah Waterland 
7395c51f124SMoriah Waterland 	/*
7405c51f124SMoriah Waterland 	 * note this will read to the end of the device, so it won't
7415c51f124SMoriah Waterland 	 * work for character devices since we don't know when the
7425c51f124SMoriah Waterland 	 * end of the CPIO archive is
7435c51f124SMoriah Waterland 	 */
7445c51f124SMoriah Waterland 	while ((amtread = read(ds_fd, readbuf, BLK_SIZE)) != 0) {
7455c51f124SMoriah Waterland 		if (BIO_write(bio, readbuf, amtread) != amtread) {
7465c51f124SMoriah Waterland 			pkgerr_add(err, PKGERR_WRITE, ERR_WRITE, device,
7475c51f124SMoriah Waterland 			    ERR_error_string(ERR_get_error(), NULL));
7485c51f124SMoriah Waterland 			return (1);
7495c51f124SMoriah Waterland 		}
7505c51f124SMoriah Waterland 	}
7515c51f124SMoriah Waterland 
7525c51f124SMoriah Waterland 	return (0);
7535c51f124SMoriah Waterland 	/*NOTREACHED*/
7545c51f124SMoriah Waterland }
7555c51f124SMoriah Waterland 
7565c51f124SMoriah Waterland 
7575c51f124SMoriah Waterland /*
7585c51f124SMoriah Waterland  * Name:		BIO_ds_dump_header
7595c51f124SMoriah Waterland  * Description:	Dumps all ds_headsize bytes from the
7605c51f124SMoriah Waterland  *		static 'ds_header_raw' character array
7615c51f124SMoriah Waterland  *		to the supplied BIO.
7625c51f124SMoriah Waterland  *
7635c51f124SMoriah Waterland  * Arguments:	err - where to record any errors.
7645c51f124SMoriah Waterland  *		bio - BIO object to dump data into
7655c51f124SMoriah Waterland  *
7665c51f124SMoriah Waterland  * Returns :	zero - successfully dumped all raw
7675c51f124SMoriah Waterland  *		header characters
7685c51f124SMoriah Waterland  *		non-zero - some failure occurred.
7695c51f124SMoriah Waterland  */
7705c51f124SMoriah Waterland int
BIO_ds_dump_header(PKG_ERR * err,BIO * bio)7715c51f124SMoriah Waterland BIO_ds_dump_header(PKG_ERR *err, BIO *bio)
7725c51f124SMoriah Waterland {
7735c51f124SMoriah Waterland 
7745c51f124SMoriah Waterland 	char	zeros[BLK_SIZE];
7755c51f124SMoriah Waterland 
776*4656d474SGarrett D'Amore 	(void) memset(zeros, 0, BLK_SIZE);
7775c51f124SMoriah Waterland 
7785c51f124SMoriah Waterland 	if (BIO_write(bio, ds_header_raw, ds_headsize) != ds_headsize) {
7795c51f124SMoriah Waterland 		pkgerr_add(err, PKGERR_WRITE, ERR_WRITE, "bio",
7805c51f124SMoriah Waterland 		    ERR_error_string(ERR_get_error(), NULL));
7815c51f124SMoriah Waterland 		return (1);
7825c51f124SMoriah Waterland 	}
7835c51f124SMoriah Waterland 
7845c51f124SMoriah Waterland 	return (0);
7855c51f124SMoriah Waterland }
7865c51f124SMoriah Waterland 
7875c51f124SMoriah Waterland /*
7885c51f124SMoriah Waterland  * ds_ginit: Determine the device being accessed, set the buffer size,
789*4656d474SGarrett D'Amore  * and perform any device specific initialization.
7905c51f124SMoriah Waterland  */
7915c51f124SMoriah Waterland 
7925c51f124SMoriah Waterland int
ds_ginit(char * device)7935c51f124SMoriah Waterland ds_ginit(char *device)
7945c51f124SMoriah Waterland {
7955c51f124SMoriah Waterland 	int oflag;
7965c51f124SMoriah Waterland 	char *pbufsize, cmd[CMDSIZ];
7975c51f124SMoriah Waterland 	int fd2, fd;
7985c51f124SMoriah Waterland 
7995c51f124SMoriah Waterland 	if ((pbufsize = devattr(device, "bufsize")) != NULL) {
8005c51f124SMoriah Waterland 		ds_bufsize = atoi(pbufsize);
8015c51f124SMoriah Waterland 		(void) free(pbufsize);
8025c51f124SMoriah Waterland 	} else
8035c51f124SMoriah Waterland 		ds_bufsize = BLK_SIZE;
8045c51f124SMoriah Waterland 	oflag = fcntl(ds_fd, F_GETFL, 0);
8055c51f124SMoriah Waterland 
8065c51f124SMoriah Waterland 	if (ds_bufsize > BLK_SIZE) {
8075c51f124SMoriah Waterland 		if (oflag & O_WRONLY)
8085c51f124SMoriah Waterland 			fd = 1;
8095c51f124SMoriah Waterland 		else
8105c51f124SMoriah Waterland 			fd = 0;
8115c51f124SMoriah Waterland 		fd2 = fcntl(fd, F_DUPFD, fd);
8125c51f124SMoriah Waterland 		(void) close(fd);
813*4656d474SGarrett D'Amore 		(void) fcntl(ds_fd, F_DUPFD, fd);
8145c51f124SMoriah Waterland 		if (fd)
815*4656d474SGarrett D'Amore 			(void) snprintf(cmd, sizeof (cmd),
816*4656d474SGarrett D'Amore 			    "%s obs=%d 2>/dev/null", DDPROC, ds_bufsize);
8175c51f124SMoriah Waterland 		else
818*4656d474SGarrett D'Amore 			(void) snprintf(cmd, sizeof (cmd),
819*4656d474SGarrett D'Amore 			    "%s ibs=%d 2>/dev/null", DDPROC, ds_bufsize);
8205c51f124SMoriah Waterland 		if ((ds_pp = popen(cmd, fd ? "w" : "r")) == NULL) {
8215c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
8225c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_POPEN), cmd, errno);
8235c51f124SMoriah Waterland 			return (-1);
8245c51f124SMoriah Waterland 		}
8255c51f124SMoriah Waterland 		(void) close(fd);
826*4656d474SGarrett D'Amore 		(void) fcntl(fd2, F_DUPFD, fd);
8275c51f124SMoriah Waterland 		(void) close(fd2);
8285c51f124SMoriah Waterland 		ds_realfd = ds_fd;
8295c51f124SMoriah Waterland 		ds_fd = fileno(ds_pp);
8305c51f124SMoriah Waterland 	}
8315c51f124SMoriah Waterland 	return (ds_bufsize);
8325c51f124SMoriah Waterland }
8335c51f124SMoriah Waterland 
8345c51f124SMoriah Waterland int
ds_close(int pkgendflg)8355c51f124SMoriah Waterland ds_close(int pkgendflg)
8365c51f124SMoriah Waterland {
8375c51f124SMoriah Waterland 	int n, ret = 0;
8385c51f124SMoriah Waterland 
8395c51f124SMoriah Waterland 	if (pkgendflg) {
8405c51f124SMoriah Waterland 		if (ds_header)
8415c51f124SMoriah Waterland 			(void) free(ds_header);
8425c51f124SMoriah Waterland 		ds_header = (char *)NULL;
8435c51f124SMoriah Waterland 		ds_totread = 0;
8445c51f124SMoriah Waterland 	}
8455c51f124SMoriah Waterland 
8465c51f124SMoriah Waterland 	if (ds_pp) {
8475c51f124SMoriah Waterland 		(void) pclose(ds_pp);
8485c51f124SMoriah Waterland 		ds_pp = 0;
8495c51f124SMoriah Waterland 		(void) close(ds_realfd);
8505c51f124SMoriah Waterland 		ds_realfd = -1;
8515c51f124SMoriah Waterland 		ds_fd = -1;
8525c51f124SMoriah Waterland 	} else if (ds_fd >= 0) {
8535c51f124SMoriah Waterland 		(void) close(ds_fd);
8545c51f124SMoriah Waterland 		ds_fd = -1;
8555c51f124SMoriah Waterland 	}
8565c51f124SMoriah Waterland 
8575c51f124SMoriah Waterland 	if (ds_device) {
8585c51f124SMoriah Waterland 		/* rewind device */
8595c51f124SMoriah Waterland 		if ((n = open(ds_device, 0)) >= 0)
8605c51f124SMoriah Waterland 			(void) close(n);
8615c51f124SMoriah Waterland 		ds_device = NULL;
8625c51f124SMoriah Waterland 	}
8635c51f124SMoriah Waterland 	return (ret);
8645c51f124SMoriah Waterland }
865