xref: /illumos-gate/usr/src/lib/libpkg/common/dstream.c (revision 3970c098)
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 
2232991bedSPeter Tribble /*
2332991bedSPeter Tribble  * Copyright (c) 2017 Peter Tribble.
2432991bedSPeter Tribble  */
2532991bedSPeter Tribble 
265c51f124SMoriah Waterland /*
275c51f124SMoriah Waterland  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
285c51f124SMoriah Waterland  * Use is subject to license terms.
295c51f124SMoriah Waterland  */
305c51f124SMoriah Waterland 
315c51f124SMoriah Waterland /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
325c51f124SMoriah Waterland /* All Rights Reserved */
335c51f124SMoriah Waterland 
345c51f124SMoriah Waterland 
355c51f124SMoriah Waterland 
365c51f124SMoriah Waterland #include <stdio.h>
375c51f124SMoriah Waterland #include <string.h>
385c51f124SMoriah Waterland #include <signal.h>
395c51f124SMoriah Waterland #include <stdlib.h>
405c51f124SMoriah Waterland #include <unistd.h>
415c51f124SMoriah Waterland #include <sys/types.h>
425c51f124SMoriah Waterland #include <sys/param.h>
435c51f124SMoriah Waterland #include <sys/sysmacros.h>
445c51f124SMoriah Waterland #include <errno.h>
455c51f124SMoriah Waterland #include <sys/types.h>
465c51f124SMoriah Waterland #include <sys/stat.h>
475c51f124SMoriah Waterland #include <sys/statvfs.h>
485c51f124SMoriah Waterland #include <fcntl.h>
495c51f124SMoriah Waterland #include "pkglib.h"
505c51f124SMoriah Waterland #include "pkglibmsgs.h"
515c51f124SMoriah Waterland #include "pkglocale.h"
525c51f124SMoriah Waterland 
535c51f124SMoriah Waterland /* libadm.a */
545c51f124SMoriah Waterland extern char	*devattr(char *device, char *attribute);
555c51f124SMoriah Waterland extern int	pkgnmchk(register char *pkg, register char *spec,
565c51f124SMoriah Waterland 				int presvr4flg);
575c51f124SMoriah Waterland extern int	getvol(char *device, char *label, int options, char *prompt);
585c51f124SMoriah Waterland 
595c51f124SMoriah Waterland #define	CMDSIZ	512
605c51f124SMoriah Waterland #define	LSIZE	128
615c51f124SMoriah Waterland #define	DDPROC		"/usr/bin/dd"
625c51f124SMoriah Waterland #define	CPIOPROC	"/usr/bin/cpio"
635c51f124SMoriah Waterland 
645c51f124SMoriah Waterland /* device types */
655c51f124SMoriah Waterland 
665c51f124SMoriah Waterland #define	G_TM_TAPE	1   /* Tapemaster controller */
675c51f124SMoriah Waterland #define	G_XY_DISK	3   /* xy disks */
685c51f124SMoriah Waterland #define	G_SD_DISK	7   /* scsi sd disk */
695c51f124SMoriah Waterland #define	G_XT_TAPE	8   /* xt tapes */
705c51f124SMoriah Waterland #define	G_SF_FLOPPY	9   /* sf floppy */
715c51f124SMoriah Waterland #define	G_XD_DISK	10  /* xd disks */
725c51f124SMoriah Waterland #define	G_ST_TAPE	11  /* scsi tape */
735c51f124SMoriah Waterland #define	G_NS		12  /* noswap pseudo-dev */
745c51f124SMoriah Waterland #define	G_RAM		13  /* ram pseudo-dev */
755c51f124SMoriah Waterland #define	G_FT		14  /* tftp */
765c51f124SMoriah Waterland #define	G_HD		15  /* 386 network disk */
775c51f124SMoriah Waterland #define	G_FD		16  /* 386 AT disk */
785c51f124SMoriah Waterland #define	G_FILE		28  /* file, not a device */
795c51f124SMoriah Waterland #define	G_NO_DEV	29  /* device does not require special treatment */
805c51f124SMoriah Waterland #define	G_DEV_MAX	30  /* last valid device type */
815c51f124SMoriah Waterland 
825c51f124SMoriah Waterland struct dstoc {
835c51f124SMoriah Waterland 	int	cnt;
845c51f124SMoriah Waterland 	char	pkg[NON_ABI_NAMELNGTH];
855c51f124SMoriah Waterland 	int	nparts;
865c51f124SMoriah Waterland 	long	maxsiz;
875c51f124SMoriah Waterland 	char    volnos[128];
885c51f124SMoriah Waterland 	struct dstoc *next;
895c51f124SMoriah Waterland } *ds_head, *ds_toc;
905c51f124SMoriah Waterland 
915c51f124SMoriah Waterland #define	ds_nparts	ds_toc->nparts
925c51f124SMoriah Waterland #define	ds_maxsiz	ds_toc->maxsiz
935c51f124SMoriah Waterland 
94*3970c098SToomas Soome int	ds_totread;	/* total number of parts read */
955c51f124SMoriah Waterland int	ds_fd = -1;
965c51f124SMoriah Waterland int	ds_curpartcnt = -1;
975c51f124SMoriah Waterland 
985c51f124SMoriah Waterland int	ds_next(char *device, char *instdir);
995c51f124SMoriah Waterland int	ds_ginit(char *device);
1005c51f124SMoriah Waterland int	ds_close(int pkgendflg);
1015c51f124SMoriah Waterland 
1025c51f124SMoriah Waterland static FILE	*ds_pp;
103*3970c098SToomas Soome static int	ds_realfd = -1;	/* file descriptor for real device */
104*3970c098SToomas Soome static int	ds_read;	/* number of parts read for current package */
105*3970c098SToomas Soome static int	ds_volno;	/* volume number of current volume */
106*3970c098SToomas Soome static int	ds_volcnt;	/* total number of volumes */
107*3970c098SToomas Soome static char	ds_volnos[128];	/* parts/volume info */
1085c51f124SMoriah Waterland static char	*ds_device;
1095c51f124SMoriah Waterland static int	ds_volpart;	/* number of parts read in current volume, */
1105c51f124SMoriah Waterland 						/* including skipped parts */
1115c51f124SMoriah Waterland static int	ds_bufsize;
112*3970c098SToomas Soome static int	ds_skippart;	/* number of parts skipped in current volume */
1135c51f124SMoriah Waterland 
1145c51f124SMoriah Waterland static int	ds_getnextvol(char *device);
1155c51f124SMoriah Waterland static int	ds_skip(char *device, int nskip);
1165c51f124SMoriah Waterland 
1175c51f124SMoriah Waterland void
ds_order(char * list[])1185c51f124SMoriah Waterland ds_order(char *list[])
1195c51f124SMoriah Waterland {
1205c51f124SMoriah Waterland 	struct dstoc *toc_pt;
1215c51f124SMoriah Waterland 	register int j, n;
1225c51f124SMoriah Waterland 	char	*pt;
1235c51f124SMoriah Waterland 
1245c51f124SMoriah Waterland 	toc_pt = ds_head;
1255c51f124SMoriah Waterland 	n = 0;
1265c51f124SMoriah Waterland 	while (toc_pt) {
1275c51f124SMoriah Waterland 		for (j = n; list[j]; j++) {
1285c51f124SMoriah Waterland 			if (strcmp(list[j], toc_pt->pkg) == 0) {
1295c51f124SMoriah Waterland 				/* just swap places in the array */
1305c51f124SMoriah Waterland 				pt = list[n];
1315c51f124SMoriah Waterland 				list[n++] = list[j];
1325c51f124SMoriah Waterland 				list[j] = pt;
1335c51f124SMoriah Waterland 			}
1345c51f124SMoriah Waterland 		}
1355c51f124SMoriah Waterland 		toc_pt = toc_pt->next;
1365c51f124SMoriah Waterland 	}
1375c51f124SMoriah Waterland }
1385c51f124SMoriah Waterland 
1395c51f124SMoriah Waterland static char *pds_header;
1405c51f124SMoriah Waterland static char *ds_header;
1415c51f124SMoriah Waterland static int ds_headsize;
1425c51f124SMoriah Waterland 
1435c51f124SMoriah Waterland static char *
ds_gets(char * buf,int size)1445c51f124SMoriah Waterland ds_gets(char *buf, int size)
1455c51f124SMoriah Waterland {
1465c51f124SMoriah Waterland 	int length;
1475c51f124SMoriah Waterland 	char *nextp;
1485c51f124SMoriah Waterland 
1495c51f124SMoriah Waterland 	nextp = strchr(pds_header, '\n');
1505c51f124SMoriah Waterland 	if (nextp == NULL) {
1515c51f124SMoriah Waterland 		length = strlen(pds_header);
1525c51f124SMoriah Waterland 		if (length > size)
1535c51f124SMoriah Waterland 			return (0);
1545c51f124SMoriah Waterland 		if ((ds_header = (char *)realloc(ds_header,
1555c51f124SMoriah Waterland 		    ds_headsize + BLK_SIZE)) == NULL)
1565c51f124SMoriah Waterland 			return (0);
1575c51f124SMoriah Waterland 		if (read(ds_fd, ds_header + ds_headsize, BLK_SIZE) < BLK_SIZE)
1585c51f124SMoriah Waterland 			return (0);
1595c51f124SMoriah Waterland 		ds_headsize += BLK_SIZE;
1605c51f124SMoriah Waterland 		nextp = strchr(pds_header, '\n');
1615c51f124SMoriah Waterland 		if (nextp == NULL)
1625c51f124SMoriah Waterland 			return (0);
1635c51f124SMoriah Waterland 		*nextp = '\0';
1645c51f124SMoriah Waterland 		if (length + (int)strlen(pds_header) > size)
1655c51f124SMoriah Waterland 			return (0);
1665c51f124SMoriah Waterland 		(void) strncpy(buf + length, pds_header, strlen(pds_header));
1675c51f124SMoriah Waterland 		buf[length + strlen(pds_header)] = '\0';
1685c51f124SMoriah Waterland 		pds_header = nextp + 1;
1695c51f124SMoriah Waterland 		return (buf);
1705c51f124SMoriah Waterland 	}
1715c51f124SMoriah Waterland 	*nextp = '\0';
1725c51f124SMoriah Waterland 	if ((int)strlen(pds_header) > size)
1735c51f124SMoriah Waterland 		return (0);
1745c51f124SMoriah Waterland 	(void) strncpy(buf, pds_header, strlen(pds_header));
1755c51f124SMoriah Waterland 	buf[strlen(pds_header)] = '\0';
1765c51f124SMoriah Waterland 	pds_header = nextp + 1;
1775c51f124SMoriah Waterland 	return (buf);
1785c51f124SMoriah Waterland }
1795c51f124SMoriah Waterland 
1805c51f124SMoriah Waterland /*
1815c51f124SMoriah Waterland  * function to determine if media is datastream or mounted
1825c51f124SMoriah Waterland  * floppy
1835c51f124SMoriah Waterland  */
1845c51f124SMoriah Waterland int
ds_readbuf(char * device)1855c51f124SMoriah Waterland ds_readbuf(char *device)
1865c51f124SMoriah Waterland {
1875c51f124SMoriah Waterland 	char buf[BLK_SIZE];
1885c51f124SMoriah Waterland 
1895c51f124SMoriah Waterland 	if (ds_fd >= 0)
1905c51f124SMoriah Waterland 		(void) close(ds_fd);
1915c51f124SMoriah Waterland 	if ((ds_fd = open(device, O_RDONLY)) >= 0 &&
1925c51f124SMoriah Waterland 	    read(ds_fd, buf, BLK_SIZE) == BLK_SIZE &&
1935c51f124SMoriah Waterland 	    strncmp(buf, HDR_PREFIX, 20) == 0) {
1945c51f124SMoriah Waterland 		if ((ds_header = (char *)calloc(BLK_SIZE, 1)) == NULL) {
1955c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
1965c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_MEM));
1975c51f124SMoriah Waterland 			(void) ds_close(0);
1985c51f124SMoriah Waterland 			return (0);
1995c51f124SMoriah Waterland 		}
2004656d474SGarrett D'Amore 		(void) memcpy(ds_header, buf, BLK_SIZE);
2015c51f124SMoriah Waterland 		ds_headsize = BLK_SIZE;
2025c51f124SMoriah Waterland 
2035c51f124SMoriah Waterland 		if (ds_ginit(device) < 0) {
2045c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
2055c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_OPEN), device, errno);
2065c51f124SMoriah Waterland 			(void) ds_close(0);
2075c51f124SMoriah Waterland 			return (0);
2085c51f124SMoriah Waterland 		}
2095c51f124SMoriah Waterland 		return (1);
2105c51f124SMoriah Waterland 	} else if (ds_fd >= 0) {
2115c51f124SMoriah Waterland 		(void) close(ds_fd);
2125c51f124SMoriah Waterland 		ds_fd = -1;
2135c51f124SMoriah Waterland 	}
2145c51f124SMoriah Waterland 	return (0);
2155c51f124SMoriah Waterland }
2165c51f124SMoriah Waterland 
2175c51f124SMoriah Waterland /*
2185c51f124SMoriah Waterland  * Determine how many additional volumes are needed for current package.
2195c51f124SMoriah Waterland  * Note: a 0 will occur as first volume number when the package begins
2205c51f124SMoriah Waterland  * on the next volume.
2215c51f124SMoriah Waterland  */
2225c51f124SMoriah Waterland static int
ds_volsum(struct dstoc * toc)2235c51f124SMoriah Waterland ds_volsum(struct dstoc *toc)
2245c51f124SMoriah Waterland {
2255c51f124SMoriah Waterland 	int curpartcnt, volcnt;
2265c51f124SMoriah Waterland 	char volnos[128], tmpvol[128];
2275c51f124SMoriah Waterland 	if (toc->volnos[0]) {
2285c51f124SMoriah Waterland 		int index, sum;
2294656d474SGarrett D'Amore 		(void) sscanf(toc->volnos, "%d %[ 0-9]", &curpartcnt, volnos);
2305c51f124SMoriah Waterland 		volcnt = 0;
2315c51f124SMoriah Waterland 		sum = curpartcnt;
2325c51f124SMoriah Waterland 		while (sum < toc->nparts && sscanf(volnos, "%d %[ 0-9]",
2335c51f124SMoriah Waterland 		    &index, tmpvol) >= 1) {
2345c51f124SMoriah Waterland 			(void) strcpy(volnos, tmpvol);
2355c51f124SMoriah Waterland 			volcnt++;
2365c51f124SMoriah Waterland 			sum += index;
2375c51f124SMoriah Waterland 		}
2385c51f124SMoriah Waterland 		/* side effect - set number of parts read on current volume */
2395c51f124SMoriah Waterland 		ds_volpart = index;
2405c51f124SMoriah Waterland 		return (volcnt);
2415c51f124SMoriah Waterland 	}
2425c51f124SMoriah Waterland 	ds_volpart += toc->nparts;
2435c51f124SMoriah Waterland 	return (0);
2445c51f124SMoriah Waterland }
2455c51f124SMoriah Waterland 
2465c51f124SMoriah Waterland /* initialize ds_curpartcnt and ds_volnos */
2475c51f124SMoriah Waterland static void
ds_pkginit(void)2485c51f124SMoriah Waterland ds_pkginit(void)
2495c51f124SMoriah Waterland {
2505c51f124SMoriah Waterland 	if (ds_toc->volnos[0])
2514656d474SGarrett D'Amore 		(void) sscanf(ds_toc->volnos, "%d %[ 0-9]", &ds_curpartcnt,
2524656d474SGarrett D'Amore 		    ds_volnos);
2535c51f124SMoriah Waterland 	else
2545c51f124SMoriah Waterland 		ds_curpartcnt = -1;
2555c51f124SMoriah Waterland }
2565c51f124SMoriah Waterland 
2575c51f124SMoriah Waterland /*
2585c51f124SMoriah Waterland  * functions to pass current package info to exec'ed program
2595c51f124SMoriah Waterland  */
2605c51f124SMoriah Waterland void
ds_putinfo(char * buf,size_t sz)2614656d474SGarrett D'Amore ds_putinfo(char *buf, size_t sz)
2625c51f124SMoriah Waterland {
2634656d474SGarrett D'Amore 	(void) snprintf(buf, sz, "%d %d %d %d %d %d %d %d %d %d %s",
2645c51f124SMoriah Waterland 	    ds_fd, ds_realfd, ds_volcnt, ds_volno, ds_totread, ds_volpart,
2655c51f124SMoriah Waterland 	    ds_skippart, ds_bufsize, ds_toc->nparts, ds_toc->maxsiz,
2665c51f124SMoriah Waterland 	    ds_toc->volnos);
2675c51f124SMoriah Waterland }
2685c51f124SMoriah Waterland 
2695c51f124SMoriah Waterland int
ds_getinfo(char * string)2705c51f124SMoriah Waterland ds_getinfo(char *string)
2715c51f124SMoriah Waterland {
2725c51f124SMoriah Waterland 	ds_toc = (struct dstoc *)calloc(1, sizeof (struct dstoc));
2735c51f124SMoriah Waterland 	(void) sscanf(string, "%d %d %d %d %d %d %d %d %d %d %[ 0-9]",
2745c51f124SMoriah Waterland 	    &ds_fd, &ds_realfd, &ds_volcnt, &ds_volno, &ds_totread,
2755c51f124SMoriah Waterland 	    &ds_volpart, &ds_skippart, &ds_bufsize, &ds_toc->nparts,
2765c51f124SMoriah Waterland 	    &ds_toc->maxsiz, ds_toc->volnos);
2775c51f124SMoriah Waterland 	ds_pkginit();
2785c51f124SMoriah Waterland 	return (ds_toc->nparts);
2795c51f124SMoriah Waterland }
2805c51f124SMoriah Waterland 
2815c51f124SMoriah Waterland /*
2825c51f124SMoriah Waterland  * Return true if the file descriptor (ds_fd) is open on the package stream.
2835c51f124SMoriah Waterland  */
2845c51f124SMoriah Waterland boolean_t
ds_fd_open(void)2855c51f124SMoriah Waterland ds_fd_open(void)
2865c51f124SMoriah Waterland {
2875c51f124SMoriah Waterland 	return (ds_fd >= 0 ? B_TRUE : B_FALSE);
2885c51f124SMoriah Waterland }
2895c51f124SMoriah Waterland 
2905c51f124SMoriah Waterland /*
2915c51f124SMoriah Waterland  * Read the source device. Acquire the header data and check it for validity.
2925c51f124SMoriah Waterland  */
2935c51f124SMoriah Waterland int
ds_init(char * device,char ** pkg,char * norewind)2945c51f124SMoriah Waterland ds_init(char *device, char **pkg, char *norewind)
2955c51f124SMoriah Waterland {
2965c51f124SMoriah Waterland 	struct dstoc *tail, *toc_pt;
2975c51f124SMoriah Waterland 	char	*ret;
2985c51f124SMoriah Waterland 	char	cmd[CMDSIZ];
2995c51f124SMoriah Waterland 	char	line[LSIZE+1];
3005c51f124SMoriah Waterland 	int	i, n, count = 0, header_size = BLK_SIZE;
3015c51f124SMoriah Waterland 
302*3970c098SToomas Soome 	if (!ds_header) {	/* If the header hasn't been read yet */
3035c51f124SMoriah Waterland 		if (ds_fd >= 0)
3045c51f124SMoriah Waterland 			(void) ds_close(0);
3055c51f124SMoriah Waterland 
3065c51f124SMoriah Waterland 		/* always start with rewind device */
3075c51f124SMoriah Waterland 		if ((ds_fd = open(device, O_RDONLY)) < 0) {
3085c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
3095c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_OPEN), device, errno);
3105c51f124SMoriah Waterland 			return (-1);
3115c51f124SMoriah Waterland 		}
3125c51f124SMoriah Waterland 
3135c51f124SMoriah Waterland 		/* allocate room for the header equivalent to a block */
3145c51f124SMoriah Waterland 		if ((ds_header = (char *)calloc(BLK_SIZE, 1)) == NULL) {
3155c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
3165c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_MEM));
3175c51f124SMoriah Waterland 			return (-1);
3185c51f124SMoriah Waterland 		}
3195c51f124SMoriah Waterland 
3205c51f124SMoriah Waterland 		/* initialize the device */
3215c51f124SMoriah Waterland 		if (ds_ginit(device) < 0) {
3225c51f124SMoriah Waterland 			(void) ds_close(0);
3235c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
3245c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_OPEN), device, errno);
3255c51f124SMoriah Waterland 			return (-1);
3265c51f124SMoriah Waterland 		}
3275c51f124SMoriah Waterland 
3285c51f124SMoriah Waterland 		/* read a logical block from the source device */
3295c51f124SMoriah Waterland 		if (read(ds_fd, ds_header, BLK_SIZE) != BLK_SIZE) {
3305c51f124SMoriah Waterland 			rpterr();
3315c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
3325c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_TOC));
3335c51f124SMoriah Waterland 			(void) ds_close(0);
3345c51f124SMoriah Waterland 			return (-1);
3355c51f124SMoriah Waterland 		}
3365c51f124SMoriah Waterland 
3375c51f124SMoriah Waterland 		/*
3385c51f124SMoriah Waterland 		 * This loop scans the medium for the start of the header.
3395c51f124SMoriah Waterland 		 * If the above read worked, we skip this. If it did't, this
3405c51f124SMoriah Waterland 		 * loop will retry the read ten times looking for the header
3415c51f124SMoriah Waterland 		 * marker string.
3425c51f124SMoriah Waterland 		 */
3435c51f124SMoriah Waterland 		while (strncmp(ds_header, HDR_PREFIX, 20) != 0) {
3445c51f124SMoriah Waterland 			/* only ten tries iff the device rewinds */
3455c51f124SMoriah Waterland 			if (!norewind || count++ > 10) {
3465c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_UNPACK));
3475c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_TOC));
3485c51f124SMoriah Waterland 				(void) ds_close(0);
3495c51f124SMoriah Waterland 				return (-1);
3505c51f124SMoriah Waterland 			}
3515c51f124SMoriah Waterland 
3525c51f124SMoriah Waterland 			/* read through to the last block */
3535c51f124SMoriah Waterland 			if (count > 1)
3545c51f124SMoriah Waterland 				while (read(ds_fd, ds_header, BLK_SIZE) > 0)
3555c51f124SMoriah Waterland 					;
3565c51f124SMoriah Waterland 
3575c51f124SMoriah Waterland 			/* then close the device */
3585c51f124SMoriah Waterland 			(void) ds_close(0);
3595c51f124SMoriah Waterland 
3605c51f124SMoriah Waterland 			/* and reopen it */
3615c51f124SMoriah Waterland 			if ((ds_fd = open(norewind, O_RDONLY)) < 0) {
3625c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_UNPACK));
3635c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_OPEN), device, errno);
3645c51f124SMoriah Waterland 				(void) free(ds_header);
3655c51f124SMoriah Waterland 				return (-1);
3665c51f124SMoriah Waterland 			}
3675c51f124SMoriah Waterland 
3685c51f124SMoriah Waterland 			/* initialize the device */
3695c51f124SMoriah Waterland 			if (ds_ginit(device) < 0) {
3705c51f124SMoriah Waterland 				(void) ds_close(0);
3715c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_UNPACK));
3725c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_OPEN), device, errno);
3735c51f124SMoriah Waterland 				return (-1);
3745c51f124SMoriah Waterland 			}
3755c51f124SMoriah Waterland 
3765c51f124SMoriah Waterland 			/* read the block again */
3775c51f124SMoriah Waterland 			if (read(ds_fd, ds_header, BLK_SIZE) != BLK_SIZE) {
3785c51f124SMoriah Waterland 				rpterr();
3795c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_UNPACK));
3805c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_TOC));
3815c51f124SMoriah Waterland 				(void) ds_close(0);
3825c51f124SMoriah Waterland 				return (-1);
3835c51f124SMoriah Waterland 			}
3845c51f124SMoriah Waterland 		}
3855c51f124SMoriah Waterland 
3865c51f124SMoriah Waterland 		/* Now keep scanning until the whole header is in place. */
3875c51f124SMoriah Waterland 		while (strstr(ds_header, HDR_SUFFIX) == NULL) {
3885c51f124SMoriah Waterland 			/* We need a bigger buffer */
3895c51f124SMoriah Waterland 			if ((ds_header = (char *)realloc(ds_header,
3905c51f124SMoriah Waterland 			    header_size + BLK_SIZE)) == NULL) {
3915c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_UNPACK));
3925c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_MEM));
3935c51f124SMoriah Waterland 				(void) ds_close(0);
3945c51f124SMoriah Waterland 				return (1);
3955c51f124SMoriah Waterland 			}
3965c51f124SMoriah Waterland 
3975c51f124SMoriah Waterland 			/* clear the new memory */
3985c51f124SMoriah Waterland 			(void) memset(ds_header + header_size, '\0',
3995c51f124SMoriah Waterland 			    BLK_SIZE);
4005c51f124SMoriah Waterland 
4015c51f124SMoriah Waterland 
4025c51f124SMoriah Waterland 			/* read a logical block from the source device */
4035c51f124SMoriah Waterland 			if (read(ds_fd, ds_header + header_size, BLK_SIZE) !=
4045c51f124SMoriah Waterland 			    BLK_SIZE) {
4055c51f124SMoriah Waterland 				rpterr();
4065c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_UNPACK));
4075c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_TOC));
4085c51f124SMoriah Waterland 				(void) ds_close(0);
4095c51f124SMoriah Waterland 				return (-1);
4105c51f124SMoriah Waterland 			} else
4115c51f124SMoriah Waterland 				header_size += BLK_SIZE;	/* new size */
4125c51f124SMoriah Waterland 		}
4135c51f124SMoriah Waterland 
4145c51f124SMoriah Waterland 		/*
4155c51f124SMoriah Waterland 		 * remember rewind device for ds_close to rewind at
4165c51f124SMoriah Waterland 		 * close
4175c51f124SMoriah Waterland 		 */
4185c51f124SMoriah Waterland 		if (count >= 1)
4195c51f124SMoriah Waterland 			ds_device = device;
4205c51f124SMoriah Waterland 		ds_headsize = header_size;
4215c51f124SMoriah Waterland 
4225c51f124SMoriah Waterland 	}
4235c51f124SMoriah Waterland 
4245c51f124SMoriah Waterland 	pds_header = ds_header;
4255c51f124SMoriah Waterland 
4265c51f124SMoriah Waterland 	/* read datastream table of contents */
4275c51f124SMoriah Waterland 	ds_head = tail = (struct dstoc *)0;
4285c51f124SMoriah Waterland 	ds_volcnt = 1;
4295c51f124SMoriah Waterland 
4305c51f124SMoriah Waterland 	while (ret = ds_gets(line, LSIZE)) {
4315c51f124SMoriah Waterland 		if (strcmp(line, HDR_SUFFIX) == 0)
4325c51f124SMoriah Waterland 			break;
4335c51f124SMoriah Waterland 		if (!line[0] || line[0] == '#')
4345c51f124SMoriah Waterland 			continue;
4355c51f124SMoriah Waterland 		toc_pt = (struct dstoc *)calloc(1, sizeof (struct dstoc));
4365c51f124SMoriah Waterland 		if (!toc_pt) {
4375c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
4385c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_MEM));
4395c51f124SMoriah Waterland 			ecleanup();
4405c51f124SMoriah Waterland 			(void) free(ds_header);
4415c51f124SMoriah Waterland 			return (-1);
4425c51f124SMoriah Waterland 		}
4434656d474SGarrett D'Amore 		/* LINTED E_SEC_SCANF_UNBOUNDED_COPY */
4445c51f124SMoriah Waterland 		if (sscanf(line, "%s %d %d %[ 0-9]", toc_pt->pkg,
4455c51f124SMoriah Waterland 		    &toc_pt->nparts, &toc_pt->maxsiz, toc_pt->volnos) < 3) {
4465c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
4475c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_TOC));
4485c51f124SMoriah Waterland 			free(toc_pt);
4495c51f124SMoriah Waterland 			(void) free(ds_header);
4505c51f124SMoriah Waterland 			ecleanup();
4515c51f124SMoriah Waterland 			return (-1);
4525c51f124SMoriah Waterland 		}
4535c51f124SMoriah Waterland 		if (tail) {
4545c51f124SMoriah Waterland 			tail->next = toc_pt;
4555c51f124SMoriah Waterland 			tail = toc_pt;
4565c51f124SMoriah Waterland 		} else
4575c51f124SMoriah Waterland 			ds_head = tail = toc_pt;
4585c51f124SMoriah Waterland 		ds_volcnt += ds_volsum(toc_pt);
4595c51f124SMoriah Waterland 	}
4605c51f124SMoriah Waterland 	if (!ret) {
4615c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_UNPACK));
4625c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_TOC));
4635c51f124SMoriah Waterland 		(void) free(ds_header);
4645c51f124SMoriah Waterland 		return (-1);
4655c51f124SMoriah Waterland 	}
4664656d474SGarrett D'Amore 	(void) sighold(SIGINT);
4674656d474SGarrett D'Amore 	(void) sigrelse(SIGINT);
4685c51f124SMoriah Waterland 	if (!ds_head) {
4695c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_UNPACK));
4705c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_EMPTY));
4715c51f124SMoriah Waterland 		(void) free(ds_header);
4725c51f124SMoriah Waterland 		return (-1);
4735c51f124SMoriah Waterland 	}
4745c51f124SMoriah Waterland 	/* this could break, thanks to cpio command limit */
4754656d474SGarrett D'Amore 	(void) snprintf(cmd, sizeof (cmd), "%s -icdumD -C %d",
4764656d474SGarrett D'Amore 	    CPIOPROC, (int)BLK_SIZE);
4775c51f124SMoriah Waterland 	n = 0;
4785c51f124SMoriah Waterland 	for (i = 0; pkg[i]; i++) {
4795c51f124SMoriah Waterland 		if (strcmp(pkg[i], "all") == 0)
4805c51f124SMoriah Waterland 			continue;
4815c51f124SMoriah Waterland 		if (n == 0) {
4824656d474SGarrett D'Amore 			(void) strlcat(cmd, " ", CMDSIZ);
4835c51f124SMoriah Waterland 			n = 1;
4845c51f124SMoriah Waterland 		}
4854656d474SGarrett D'Amore 		(void) strlcat(cmd, pkg[i], CMDSIZ);
4864656d474SGarrett D'Amore 		(void) strlcat(cmd, "'/*' ", CMDSIZ);
4874656d474SGarrett D'Amore 		(void) strlcat(cmd, " ", CMDSIZ);
4885c51f124SMoriah Waterland 	}
4895c51f124SMoriah Waterland 
4905c51f124SMoriah Waterland 	if (n = esystem(cmd, ds_fd, -1)) {
4915c51f124SMoriah Waterland 		rpterr();
4925c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_UNPACK));
4935c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_CMDFAIL), cmd, n);
4945c51f124SMoriah Waterland 		(void) free(ds_header);
4955c51f124SMoriah Waterland 		return (-1);
4965c51f124SMoriah Waterland 	}
4975c51f124SMoriah Waterland 
4985c51f124SMoriah Waterland 	ds_toc = ds_head;
4995c51f124SMoriah Waterland 	ds_totread = 0;
5005c51f124SMoriah Waterland 	ds_volno = 1;
5015c51f124SMoriah Waterland 	return (0);
5025c51f124SMoriah Waterland }
5035c51f124SMoriah Waterland 
5045c51f124SMoriah Waterland int
ds_findpkg(char * device,char * pkg)5055c51f124SMoriah Waterland ds_findpkg(char *device, char *pkg)
5065c51f124SMoriah Waterland {
5075c51f124SMoriah Waterland 	char	*pkglist[2];
5085c51f124SMoriah Waterland 	int	nskip, ods_volpart;
5095c51f124SMoriah Waterland 
5105c51f124SMoriah Waterland 	if (ds_head == NULL) {
5115c51f124SMoriah Waterland 		pkglist[0] = pkg;
5125c51f124SMoriah Waterland 		pkglist[1] = NULL;
5135c51f124SMoriah Waterland 		if (ds_init(device, pkglist, NULL))
5145c51f124SMoriah Waterland 			return (-1);
5155c51f124SMoriah Waterland 	}
5165c51f124SMoriah Waterland 
5175c51f124SMoriah Waterland 	if (!pkg || pkgnmchk(pkg, "all", 0)) {
5185c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_UNPACK));
5195c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_PKGNAME));
5205c51f124SMoriah Waterland 		return (-1);
5215c51f124SMoriah Waterland 	}
5225c51f124SMoriah Waterland 
5235c51f124SMoriah Waterland 	nskip = 0;
5245c51f124SMoriah Waterland 	ds_volno = 1;
5255c51f124SMoriah Waterland 	ds_volpart = 0;
5265c51f124SMoriah Waterland 	ds_toc = ds_head;
5275c51f124SMoriah Waterland 	while (ds_toc) {
5285c51f124SMoriah Waterland 		if (strcmp(ds_toc->pkg, pkg) == 0)
5295c51f124SMoriah Waterland 			break;
5305c51f124SMoriah Waterland 		nskip += ds_toc->nparts;
5315c51f124SMoriah Waterland 		ds_volno += ds_volsum(ds_toc);
5325c51f124SMoriah Waterland 		ds_toc = ds_toc->next;
5335c51f124SMoriah Waterland 	}
5345c51f124SMoriah Waterland 	if (!ds_toc) {
5355c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_UNPACK));
5365c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_NOPKG), pkg);
5375c51f124SMoriah Waterland 		return (-1);
5385c51f124SMoriah Waterland 	}
5395c51f124SMoriah Waterland 
5405c51f124SMoriah Waterland 	ds_pkginit();
5415c51f124SMoriah Waterland 	ds_skippart = 0;
5425c51f124SMoriah Waterland 	if (ds_curpartcnt > 0) {
5435c51f124SMoriah Waterland 		ods_volpart = ds_volpart;
5445c51f124SMoriah Waterland 		/*
5455c51f124SMoriah Waterland 		 * skip past archives belonging to last package on current
5465c51f124SMoriah Waterland 		 * volume
5475c51f124SMoriah Waterland 		 */
5485c51f124SMoriah Waterland 		if (ds_volpart > 0 && ds_getnextvol(device))
5495c51f124SMoriah Waterland 			return (-1);
5505c51f124SMoriah Waterland 		ds_totread = nskip - ods_volpart;
5515c51f124SMoriah Waterland 		if (ds_skip(device, ods_volpart))
5525c51f124SMoriah Waterland 			return (-1);
5535c51f124SMoriah Waterland 	} else if (ds_curpartcnt < 0) {
5545c51f124SMoriah Waterland 		if (ds_skip(device, nskip - ds_totread))
5555c51f124SMoriah Waterland 			return (-1);
5565c51f124SMoriah Waterland 	} else
5575c51f124SMoriah Waterland 		ds_totread = nskip;
5585c51f124SMoriah Waterland 	ds_read = 0;
5595c51f124SMoriah Waterland 	return (ds_nparts);
5605c51f124SMoriah Waterland }
5615c51f124SMoriah Waterland 
5625c51f124SMoriah Waterland /*
5635c51f124SMoriah Waterland  * Get datastream part
5645c51f124SMoriah Waterland  * Call for first part should be preceded by
5655c51f124SMoriah Waterland  * call to ds_findpkg
5665c51f124SMoriah Waterland  */
5675c51f124SMoriah Waterland 
5685c51f124SMoriah Waterland int
ds_getpkg(char * device,int n,char * dstdir)5695c51f124SMoriah Waterland ds_getpkg(char *device, int n, char *dstdir)
5705c51f124SMoriah Waterland {
5715c51f124SMoriah Waterland 	struct statvfs64 svfsb;
5725c51f124SMoriah Waterland 	u_longlong_t free_blocks;
5735c51f124SMoriah Waterland 
5745c51f124SMoriah Waterland 	if (ds_read >= ds_nparts)
5755c51f124SMoriah Waterland 		return (2);
5765c51f124SMoriah Waterland 
5775c51f124SMoriah Waterland 	if (ds_read == n)
5785c51f124SMoriah Waterland 		return (0);
5795c51f124SMoriah Waterland 	else if ((ds_read > n) || (n > ds_nparts))
5805c51f124SMoriah Waterland 		return (2);
5815c51f124SMoriah Waterland 
5825c51f124SMoriah Waterland 	if (ds_maxsiz > 0) {
5835c51f124SMoriah Waterland 		if (statvfs64(".", &svfsb)) {
5845c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
5855c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_STATFS), errno);
5865c51f124SMoriah Waterland 			return (-1);
5875c51f124SMoriah Waterland 		}
5885c51f124SMoriah Waterland 		free_blocks = (((long)svfsb.f_frsize > 0) ?
5894656d474SGarrett D'Amore 		    howmany(svfsb.f_frsize, DEV_BSIZE) :
5904656d474SGarrett D'Amore 		    howmany(svfsb.f_bsize, DEV_BSIZE)) * svfsb.f_bfree;
5915c51f124SMoriah Waterland 		if ((ds_maxsiz + 50) > free_blocks) {
5925c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
5935c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_NOSPACE), ds_maxsiz+50, free_blocks);
5945c51f124SMoriah Waterland 			return (-1);
5955c51f124SMoriah Waterland 		}
5965c51f124SMoriah Waterland 	}
5975c51f124SMoriah Waterland 	return (ds_next(device, dstdir));
5985c51f124SMoriah Waterland }
5995c51f124SMoriah Waterland 
6005c51f124SMoriah Waterland static int
ds_getnextvol(char * device)6015c51f124SMoriah Waterland ds_getnextvol(char *device)
6025c51f124SMoriah Waterland {
6035c51f124SMoriah Waterland 	char prompt[128];
6045c51f124SMoriah Waterland 	int n;
6055c51f124SMoriah Waterland 
6065c51f124SMoriah Waterland 	if (ds_close(0))
6075c51f124SMoriah Waterland 		return (-1);
6085c51f124SMoriah Waterland 	(void) sprintf(prompt,
6095c51f124SMoriah Waterland 	    pkg_gt("Insert %%v %d of %d into %%p"),
6105c51f124SMoriah Waterland 	    ds_volno, ds_volcnt);
611*3970c098SToomas Soome 	if (n = getvol(device, NULL, 0, prompt))
6125c51f124SMoriah Waterland 		return (n);
6135c51f124SMoriah Waterland 	if ((ds_fd = open(device, O_RDONLY)) < 0)
6145c51f124SMoriah Waterland 		return (-1);
6155c51f124SMoriah Waterland 	if (ds_ginit(device) < 0) {
6165c51f124SMoriah Waterland 		(void) ds_close(0);
6175c51f124SMoriah Waterland 		return (-1);
6185c51f124SMoriah Waterland 	}
6195c51f124SMoriah Waterland 	ds_volpart = 0;
6205c51f124SMoriah Waterland 	return (0);
6215c51f124SMoriah Waterland }
6225c51f124SMoriah Waterland 
6235c51f124SMoriah Waterland /*
6245c51f124SMoriah Waterland  * called by ds_findpkg to skip past archives for unwanted packages
6255c51f124SMoriah Waterland  * in current volume
6265c51f124SMoriah Waterland  */
6275c51f124SMoriah Waterland static int
ds_skip(char * device,int nskip)6285c51f124SMoriah Waterland ds_skip(char *device, int nskip)
6295c51f124SMoriah Waterland {
6305c51f124SMoriah Waterland 	char	cmd[CMDSIZ];
6315c51f124SMoriah Waterland 	int	n, onskip = nskip;
6325c51f124SMoriah Waterland 
6335c51f124SMoriah Waterland 	while (nskip--) {
6345c51f124SMoriah Waterland 		/* skip this one */
6354656d474SGarrett D'Amore 		(void) snprintf(cmd, sizeof (cmd),
6364656d474SGarrett D'Amore 		    "%s -ictD -C %d > /dev/null", CPIOPROC, (int)BLK_SIZE);
6375c51f124SMoriah Waterland 		if (n = esystem(cmd, ds_fd, -1)) {
6385c51f124SMoriah Waterland 			rpterr();
6395c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
6405c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_CMDFAIL), cmd, n);
6415c51f124SMoriah Waterland 			nskip = onskip;
6425c51f124SMoriah Waterland 			if (ds_volno == 1 || ds_volpart > 0)
6435c51f124SMoriah Waterland 				return (n);
6445c51f124SMoriah Waterland 			if (n = ds_getnextvol(device))
6455c51f124SMoriah Waterland 				return (n);
6465c51f124SMoriah Waterland 		}
6475c51f124SMoriah Waterland 	}
6485c51f124SMoriah Waterland 	ds_totread += onskip;
6495c51f124SMoriah Waterland 	ds_volpart = onskip;
6505c51f124SMoriah Waterland 	ds_skippart = onskip;
6515c51f124SMoriah Waterland 	return (0);
6525c51f124SMoriah Waterland }
6535c51f124SMoriah Waterland 
6545c51f124SMoriah Waterland /* skip to end of package if necessary */
6555c51f124SMoriah Waterland void
ds_skiptoend(char * device)6565c51f124SMoriah Waterland ds_skiptoend(char *device)
6575c51f124SMoriah Waterland {
6585c51f124SMoriah Waterland 	if (ds_read < ds_nparts && ds_curpartcnt < 0)
6595c51f124SMoriah Waterland 		(void) ds_skip(device, ds_nparts - ds_read);
6605c51f124SMoriah Waterland }
6615c51f124SMoriah Waterland 
6625c51f124SMoriah Waterland int
ds_next(char * device,char * instdir)6635c51f124SMoriah Waterland ds_next(char *device, char *instdir)
6645c51f124SMoriah Waterland {
6655c51f124SMoriah Waterland 	char	cmd[CMDSIZ], tmpvol[128];
6665c51f124SMoriah Waterland 	int	nparts, n, index;
6675c51f124SMoriah Waterland 
6685c51f124SMoriah Waterland 	/*CONSTCOND*/
6695c51f124SMoriah Waterland 	while (1) {
6705c51f124SMoriah Waterland 		if (ds_read + 1 > ds_curpartcnt && ds_curpartcnt >= 0) {
6715c51f124SMoriah Waterland 			ds_volno++;
6725c51f124SMoriah Waterland 			if (n = ds_getnextvol(device))
6735c51f124SMoriah Waterland 				return (n);
6745c51f124SMoriah Waterland 			(void) sscanf(ds_volnos, "%d %[ 0-9]", &index, tmpvol);
6755c51f124SMoriah Waterland 			(void) strcpy(ds_volnos, tmpvol);
6765c51f124SMoriah Waterland 			ds_curpartcnt += index;
6775c51f124SMoriah Waterland 		}
6784656d474SGarrett D'Amore 		(void) snprintf(cmd, sizeof (cmd), "%s -icdumD -C %d",
6795c51f124SMoriah Waterland 		    CPIOPROC, (int)BLK_SIZE);
6805c51f124SMoriah Waterland 		if (n = esystem(cmd, ds_fd, -1)) {
6815c51f124SMoriah Waterland 			rpterr();
6825c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
6835c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_CMDFAIL), cmd, n);
6845c51f124SMoriah Waterland 		}
6855c51f124SMoriah Waterland 		if (ds_read == 0)
6865c51f124SMoriah Waterland 			nparts = 0;
6875c51f124SMoriah Waterland 		else
6885c51f124SMoriah Waterland 			nparts = ds_toc->nparts;
6895c51f124SMoriah Waterland 		if (n || (n = ckvolseq(instdir, ds_read + 1, nparts))) {
6905c51f124SMoriah Waterland 			if (ds_volno == 1 || ds_volpart > ds_skippart)
6915c51f124SMoriah Waterland 				return (-1);
6925c51f124SMoriah Waterland 
6935c51f124SMoriah Waterland 			if (n = ds_getnextvol(device))
6945c51f124SMoriah Waterland 				return (n);
6955c51f124SMoriah Waterland 			continue;
6965c51f124SMoriah Waterland 		}
6975c51f124SMoriah Waterland 		ds_read++;
6985c51f124SMoriah Waterland 		ds_totread++;
6995c51f124SMoriah Waterland 		ds_volpart++;
7005c51f124SMoriah Waterland 
7015c51f124SMoriah Waterland 		return (0);
7025c51f124SMoriah Waterland 	}
7035c51f124SMoriah Waterland 	/*NOTREACHED*/
7045c51f124SMoriah Waterland }
7055c51f124SMoriah Waterland 
7065c51f124SMoriah Waterland /*
7075c51f124SMoriah Waterland  * ds_ginit: Determine the device being accessed, set the buffer size,
7084656d474SGarrett D'Amore  * and perform any device specific initialization.
7095c51f124SMoriah Waterland  */
7105c51f124SMoriah Waterland 
7115c51f124SMoriah Waterland int
ds_ginit(char * device)7125c51f124SMoriah Waterland ds_ginit(char *device)
7135c51f124SMoriah Waterland {
7145c51f124SMoriah Waterland 	int oflag;
7155c51f124SMoriah Waterland 	char *pbufsize, cmd[CMDSIZ];
7165c51f124SMoriah Waterland 	int fd2, fd;
7175c51f124SMoriah Waterland 
7185c51f124SMoriah Waterland 	if ((pbufsize = devattr(device, "bufsize")) != NULL) {
7195c51f124SMoriah Waterland 		ds_bufsize = atoi(pbufsize);
7205c51f124SMoriah Waterland 		(void) free(pbufsize);
7215c51f124SMoriah Waterland 	} else
7225c51f124SMoriah Waterland 		ds_bufsize = BLK_SIZE;
7235c51f124SMoriah Waterland 	oflag = fcntl(ds_fd, F_GETFL, 0);
7245c51f124SMoriah Waterland 
7255c51f124SMoriah Waterland 	if (ds_bufsize > BLK_SIZE) {
7265c51f124SMoriah Waterland 		if (oflag & O_WRONLY)
7275c51f124SMoriah Waterland 			fd = 1;
7285c51f124SMoriah Waterland 		else
7295c51f124SMoriah Waterland 			fd = 0;
7305c51f124SMoriah Waterland 		fd2 = fcntl(fd, F_DUPFD, fd);
7315c51f124SMoriah Waterland 		(void) close(fd);
7324656d474SGarrett D'Amore 		(void) fcntl(ds_fd, F_DUPFD, fd);
7335c51f124SMoriah Waterland 		if (fd)
7344656d474SGarrett D'Amore 			(void) snprintf(cmd, sizeof (cmd),
7354656d474SGarrett D'Amore 			    "%s obs=%d 2>/dev/null", DDPROC, ds_bufsize);
7365c51f124SMoriah Waterland 		else
7374656d474SGarrett D'Amore 			(void) snprintf(cmd, sizeof (cmd),
7384656d474SGarrett D'Amore 			    "%s ibs=%d 2>/dev/null", DDPROC, ds_bufsize);
7395c51f124SMoriah Waterland 		if ((ds_pp = popen(cmd, fd ? "w" : "r")) == NULL) {
7405c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
7415c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_POPEN), cmd, errno);
7425c51f124SMoriah Waterland 			return (-1);
7435c51f124SMoriah Waterland 		}
7445c51f124SMoriah Waterland 		(void) close(fd);
7454656d474SGarrett D'Amore 		(void) fcntl(fd2, F_DUPFD, fd);
7465c51f124SMoriah Waterland 		(void) close(fd2);
7475c51f124SMoriah Waterland 		ds_realfd = ds_fd;
7485c51f124SMoriah Waterland 		ds_fd = fileno(ds_pp);
7495c51f124SMoriah Waterland 	}
7505c51f124SMoriah Waterland 	return (ds_bufsize);
7515c51f124SMoriah Waterland }
7525c51f124SMoriah Waterland 
7535c51f124SMoriah Waterland int
ds_close(int pkgendflg)7545c51f124SMoriah Waterland ds_close(int pkgendflg)
7555c51f124SMoriah Waterland {
7565c51f124SMoriah Waterland 	int n, ret = 0;
7575c51f124SMoriah Waterland 
7585c51f124SMoriah Waterland 	if (pkgendflg) {
7595c51f124SMoriah Waterland 		if (ds_header)
7605c51f124SMoriah Waterland 			(void) free(ds_header);
7615c51f124SMoriah Waterland 		ds_header = (char *)NULL;
7625c51f124SMoriah Waterland 		ds_totread = 0;
7635c51f124SMoriah Waterland 	}
7645c51f124SMoriah Waterland 
7655c51f124SMoriah Waterland 	if (ds_pp) {
7665c51f124SMoriah Waterland 		(void) pclose(ds_pp);
7675c51f124SMoriah Waterland 		ds_pp = 0;
7685c51f124SMoriah Waterland 		(void) close(ds_realfd);
7695c51f124SMoriah Waterland 		ds_realfd = -1;
7705c51f124SMoriah Waterland 		ds_fd = -1;
7715c51f124SMoriah Waterland 	} else if (ds_fd >= 0) {
7725c51f124SMoriah Waterland 		(void) close(ds_fd);
7735c51f124SMoriah Waterland 		ds_fd = -1;
7745c51f124SMoriah Waterland 	}
7755c51f124SMoriah Waterland 
7765c51f124SMoriah Waterland 	if (ds_device) {
7775c51f124SMoriah Waterland 		/* rewind device */
7785c51f124SMoriah Waterland 		if ((n = open(ds_device, 0)) >= 0)
7795c51f124SMoriah Waterland 			(void) close(n);
7805c51f124SMoriah Waterland 		ds_device = NULL;
7815c51f124SMoriah Waterland 	}
7825c51f124SMoriah Waterland 	return (ret);
7835c51f124SMoriah Waterland }
784