xref: /titanic_50/usr/src/lib/libpkg/common/dstream.c (revision 5c51f1241dbbdf2656d0e10011981411ed0c9673)
1*5c51f124SMoriah Waterland /*
2*5c51f124SMoriah Waterland  * CDDL HEADER START
3*5c51f124SMoriah Waterland  *
4*5c51f124SMoriah Waterland  * The contents of this file are subject to the terms of the
5*5c51f124SMoriah Waterland  * Common Development and Distribution License (the "License").
6*5c51f124SMoriah Waterland  * You may not use this file except in compliance with the License.
7*5c51f124SMoriah Waterland  *
8*5c51f124SMoriah Waterland  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*5c51f124SMoriah Waterland  * or http://www.opensolaris.org/os/licensing.
10*5c51f124SMoriah Waterland  * See the License for the specific language governing permissions
11*5c51f124SMoriah Waterland  * and limitations under the License.
12*5c51f124SMoriah Waterland  *
13*5c51f124SMoriah Waterland  * When distributing Covered Code, include this CDDL HEADER in each
14*5c51f124SMoriah Waterland  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*5c51f124SMoriah Waterland  * If applicable, add the following below this CDDL HEADER, with the
16*5c51f124SMoriah Waterland  * fields enclosed by brackets "[]" replaced with your own identifying
17*5c51f124SMoriah Waterland  * information: Portions Copyright [yyyy] [name of copyright owner]
18*5c51f124SMoriah Waterland  *
19*5c51f124SMoriah Waterland  * CDDL HEADER END
20*5c51f124SMoriah Waterland  */
21*5c51f124SMoriah Waterland 
22*5c51f124SMoriah Waterland /*
23*5c51f124SMoriah Waterland  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24*5c51f124SMoriah Waterland  * Use is subject to license terms.
25*5c51f124SMoriah Waterland  */
26*5c51f124SMoriah Waterland 
27*5c51f124SMoriah Waterland /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28*5c51f124SMoriah Waterland /* All Rights Reserved */
29*5c51f124SMoriah Waterland 
30*5c51f124SMoriah Waterland 
31*5c51f124SMoriah Waterland 
32*5c51f124SMoriah Waterland #include <stdio.h>
33*5c51f124SMoriah Waterland #include <string.h>
34*5c51f124SMoriah Waterland #include <signal.h>
35*5c51f124SMoriah Waterland #include <stdlib.h>
36*5c51f124SMoriah Waterland #include <unistd.h>
37*5c51f124SMoriah Waterland #include <sys/types.h>
38*5c51f124SMoriah Waterland #include <sys/param.h>
39*5c51f124SMoriah Waterland #include <sys/sysmacros.h>
40*5c51f124SMoriah Waterland #include <errno.h>
41*5c51f124SMoriah Waterland #include <sys/types.h>
42*5c51f124SMoriah Waterland #include <sys/stat.h>
43*5c51f124SMoriah Waterland #include <sys/statvfs.h>
44*5c51f124SMoriah Waterland #include <fcntl.h>
45*5c51f124SMoriah Waterland #ifdef u3b2
46*5c51f124SMoriah Waterland #include <sys/sys3b.h>
47*5c51f124SMoriah Waterland #endif	/* u3b2 */
48*5c51f124SMoriah Waterland #include <openssl/err.h>
49*5c51f124SMoriah Waterland #include "pkglib.h"
50*5c51f124SMoriah Waterland #include "pkglibmsgs.h"
51*5c51f124SMoriah Waterland #include "pkglocale.h"
52*5c51f124SMoriah Waterland #ifdef u3b2
53*5c51f124SMoriah Waterland static
54*5c51f124SMoriah Waterland struct stat	orig_st_buf; /* Stat structure of original file (3B2/CTC) */
55*5c51f124SMoriah Waterland static char	ds_ctcflg;
56*5c51f124SMoriah Waterland #endif	/* u3b2 */
57*5c51f124SMoriah Waterland 
58*5c51f124SMoriah Waterland /* libadm.a */
59*5c51f124SMoriah Waterland extern char	*devattr(char *device, char *attribute);
60*5c51f124SMoriah Waterland extern int	pkgnmchk(register char *pkg, register char *spec,
61*5c51f124SMoriah Waterland 				int presvr4flg);
62*5c51f124SMoriah Waterland extern int	getvol(char *device, char *label, int options, char *prompt);
63*5c51f124SMoriah Waterland 
64*5c51f124SMoriah Waterland #define	CMDSIZ	512
65*5c51f124SMoriah Waterland #define	LSIZE	128
66*5c51f124SMoriah Waterland #define	DDPROC		"/usr/bin/dd"
67*5c51f124SMoriah Waterland #define	CPIOPROC	"/usr/bin/cpio"
68*5c51f124SMoriah Waterland 
69*5c51f124SMoriah Waterland /* device types */
70*5c51f124SMoriah Waterland 
71*5c51f124SMoriah Waterland #define	G_TM_TAPE	1   /* Tapemaster controller */
72*5c51f124SMoriah Waterland #define	G_XY_DISK	3   /* xy disks */
73*5c51f124SMoriah Waterland #define	G_SD_DISK	7   /* scsi sd disk */
74*5c51f124SMoriah Waterland #define	G_XT_TAPE	8   /* xt tapes */
75*5c51f124SMoriah Waterland #define	G_SF_FLOPPY	9   /* sf floppy */
76*5c51f124SMoriah Waterland #define	G_XD_DISK	10  /* xd disks */
77*5c51f124SMoriah Waterland #define	G_ST_TAPE	11  /* scsi tape */
78*5c51f124SMoriah Waterland #define	G_NS		12  /* noswap pseudo-dev */
79*5c51f124SMoriah Waterland #define	G_RAM		13  /* ram pseudo-dev */
80*5c51f124SMoriah Waterland #define	G_FT		14  /* tftp */
81*5c51f124SMoriah Waterland #define	G_HD		15  /* 386 network disk */
82*5c51f124SMoriah Waterland #define	G_FD		16  /* 386 AT disk */
83*5c51f124SMoriah Waterland #define	G_FILE		28  /* file, not a device */
84*5c51f124SMoriah Waterland #define	G_NO_DEV	29  /* device does not require special treatment */
85*5c51f124SMoriah Waterland #define	G_DEV_MAX	30  /* last valid device type */
86*5c51f124SMoriah Waterland 
87*5c51f124SMoriah Waterland struct dstoc {
88*5c51f124SMoriah Waterland 	int	cnt;
89*5c51f124SMoriah Waterland 	char	pkg[NON_ABI_NAMELNGTH];
90*5c51f124SMoriah Waterland 	int	nparts;
91*5c51f124SMoriah Waterland 	long	maxsiz;
92*5c51f124SMoriah Waterland 	char    volnos[128];
93*5c51f124SMoriah Waterland 	struct dstoc *next;
94*5c51f124SMoriah Waterland } *ds_head, *ds_toc;
95*5c51f124SMoriah Waterland 
96*5c51f124SMoriah Waterland #define	ds_nparts	ds_toc->nparts
97*5c51f124SMoriah Waterland #define	ds_maxsiz	ds_toc->maxsiz
98*5c51f124SMoriah Waterland 
99*5c51f124SMoriah Waterland int	ds_totread; 	/* total number of parts read */
100*5c51f124SMoriah Waterland int	ds_fd = -1;
101*5c51f124SMoriah Waterland int	ds_curpartcnt = -1;
102*5c51f124SMoriah Waterland 
103*5c51f124SMoriah Waterland int	ds_next(char *device, char *instdir);
104*5c51f124SMoriah Waterland int	ds_ginit(char *device);
105*5c51f124SMoriah Waterland int	ds_close(int pkgendflg);
106*5c51f124SMoriah Waterland 
107*5c51f124SMoriah Waterland static FILE	*ds_pp;
108*5c51f124SMoriah Waterland static int	ds_realfd = -1; 	/* file descriptor for real device */
109*5c51f124SMoriah Waterland static int	ds_read; 	/* number of parts read for current package */
110*5c51f124SMoriah Waterland static int	ds_volno; 	/* volume number of current volume */
111*5c51f124SMoriah Waterland static int	ds_volcnt; 	/* total number of volumes */
112*5c51f124SMoriah Waterland static char	ds_volnos[128]; 	/* parts/volume info */
113*5c51f124SMoriah Waterland static char	*ds_device;
114*5c51f124SMoriah Waterland static int	ds_volpart;	/* number of parts read in current volume, */
115*5c51f124SMoriah Waterland 						/* including skipped parts */
116*5c51f124SMoriah Waterland static int	ds_bufsize;
117*5c51f124SMoriah Waterland static int	ds_skippart; 	/* number of parts skipped in current volume */
118*5c51f124SMoriah Waterland 
119*5c51f124SMoriah Waterland static int	ds_getnextvol(char *device);
120*5c51f124SMoriah Waterland static int	ds_skip(char *device, int nskip);
121*5c51f124SMoriah Waterland 
122*5c51f124SMoriah Waterland void
123*5c51f124SMoriah Waterland ds_order(char *list[])
124*5c51f124SMoriah Waterland {
125*5c51f124SMoriah Waterland 	struct dstoc *toc_pt;
126*5c51f124SMoriah Waterland 	register int j, n;
127*5c51f124SMoriah Waterland 	char	*pt;
128*5c51f124SMoriah Waterland 
129*5c51f124SMoriah Waterland 	toc_pt = ds_head;
130*5c51f124SMoriah Waterland 	n = 0;
131*5c51f124SMoriah Waterland 	while (toc_pt) {
132*5c51f124SMoriah Waterland 		for (j = n; list[j]; j++) {
133*5c51f124SMoriah Waterland 			if (strcmp(list[j], toc_pt->pkg) == 0) {
134*5c51f124SMoriah Waterland 				/* just swap places in the array */
135*5c51f124SMoriah Waterland 				pt = list[n];
136*5c51f124SMoriah Waterland 				list[n++] = list[j];
137*5c51f124SMoriah Waterland 				list[j] = pt;
138*5c51f124SMoriah Waterland 			}
139*5c51f124SMoriah Waterland 		}
140*5c51f124SMoriah Waterland 		toc_pt = toc_pt->next;
141*5c51f124SMoriah Waterland 	}
142*5c51f124SMoriah Waterland }
143*5c51f124SMoriah Waterland 
144*5c51f124SMoriah Waterland static char *pds_header;
145*5c51f124SMoriah Waterland static char *ds_header;
146*5c51f124SMoriah Waterland static char *ds_header_raw;
147*5c51f124SMoriah Waterland static int ds_headsize;
148*5c51f124SMoriah Waterland 
149*5c51f124SMoriah Waterland static char *
150*5c51f124SMoriah Waterland ds_gets(char *buf, int size)
151*5c51f124SMoriah Waterland {
152*5c51f124SMoriah Waterland 	int length;
153*5c51f124SMoriah Waterland 	char *nextp;
154*5c51f124SMoriah Waterland 
155*5c51f124SMoriah Waterland 	nextp = strchr(pds_header, '\n');
156*5c51f124SMoriah Waterland 	if (nextp == NULL) {
157*5c51f124SMoriah Waterland 		length = strlen(pds_header);
158*5c51f124SMoriah Waterland 		if (length > size)
159*5c51f124SMoriah Waterland 			return (0);
160*5c51f124SMoriah Waterland 		if ((ds_header = (char *)realloc(ds_header,
161*5c51f124SMoriah Waterland 		    ds_headsize + BLK_SIZE)) == NULL)
162*5c51f124SMoriah Waterland 			return (0);
163*5c51f124SMoriah Waterland 		if (read(ds_fd, ds_header + ds_headsize, BLK_SIZE) < BLK_SIZE)
164*5c51f124SMoriah Waterland 			return (0);
165*5c51f124SMoriah Waterland 		ds_headsize += BLK_SIZE;
166*5c51f124SMoriah Waterland 		nextp = strchr(pds_header, '\n');
167*5c51f124SMoriah Waterland 		if (nextp == NULL)
168*5c51f124SMoriah Waterland 			return (0);
169*5c51f124SMoriah Waterland 		*nextp = '\0';
170*5c51f124SMoriah Waterland 		if (length + (int)strlen(pds_header) > size)
171*5c51f124SMoriah Waterland 			return (0);
172*5c51f124SMoriah Waterland 		(void) strncpy(buf + length, pds_header, strlen(pds_header));
173*5c51f124SMoriah Waterland 		buf[length + strlen(pds_header)] = '\0';
174*5c51f124SMoriah Waterland 		pds_header = nextp + 1;
175*5c51f124SMoriah Waterland 		return (buf);
176*5c51f124SMoriah Waterland 	}
177*5c51f124SMoriah Waterland 	*nextp = '\0';
178*5c51f124SMoriah Waterland 	if ((int)strlen(pds_header) > size)
179*5c51f124SMoriah Waterland 		return (0);
180*5c51f124SMoriah Waterland 	(void) strncpy(buf, pds_header, strlen(pds_header));
181*5c51f124SMoriah Waterland 	buf[strlen(pds_header)] = '\0';
182*5c51f124SMoriah Waterland 	pds_header = nextp + 1;
183*5c51f124SMoriah Waterland 	return (buf);
184*5c51f124SMoriah Waterland }
185*5c51f124SMoriah Waterland 
186*5c51f124SMoriah Waterland /*
187*5c51f124SMoriah Waterland  * function to determine if media is datastream or mounted
188*5c51f124SMoriah Waterland  * floppy
189*5c51f124SMoriah Waterland  */
190*5c51f124SMoriah Waterland int
191*5c51f124SMoriah Waterland ds_readbuf(char *device)
192*5c51f124SMoriah Waterland {
193*5c51f124SMoriah Waterland 	char buf[BLK_SIZE];
194*5c51f124SMoriah Waterland 
195*5c51f124SMoriah Waterland 	if (ds_fd >= 0)
196*5c51f124SMoriah Waterland 		(void) close(ds_fd);
197*5c51f124SMoriah Waterland 	if ((ds_fd = open(device, O_RDONLY)) >= 0 &&
198*5c51f124SMoriah Waterland 	    read(ds_fd, buf, BLK_SIZE) == BLK_SIZE &&
199*5c51f124SMoriah Waterland 	    strncmp(buf, HDR_PREFIX, 20) == 0) {
200*5c51f124SMoriah Waterland 		if ((ds_header = (char *)calloc(BLK_SIZE, 1)) == NULL) {
201*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
202*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_MEM));
203*5c51f124SMoriah Waterland 			(void) ds_close(0);
204*5c51f124SMoriah Waterland 			return (0);
205*5c51f124SMoriah Waterland 		}
206*5c51f124SMoriah Waterland 		memcpy(ds_header, buf, BLK_SIZE);
207*5c51f124SMoriah Waterland 		ds_headsize = BLK_SIZE;
208*5c51f124SMoriah Waterland 
209*5c51f124SMoriah Waterland 		if (ds_ginit(device) < 0) {
210*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
211*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_OPEN), device, errno);
212*5c51f124SMoriah Waterland 			(void) ds_close(0);
213*5c51f124SMoriah Waterland 			return (0);
214*5c51f124SMoriah Waterland 		}
215*5c51f124SMoriah Waterland 		return (1);
216*5c51f124SMoriah Waterland 	} else if (ds_fd >= 0) {
217*5c51f124SMoriah Waterland 		(void) close(ds_fd);
218*5c51f124SMoriah Waterland 		ds_fd = -1;
219*5c51f124SMoriah Waterland 	}
220*5c51f124SMoriah Waterland 	return (0);
221*5c51f124SMoriah Waterland }
222*5c51f124SMoriah Waterland 
223*5c51f124SMoriah Waterland /*
224*5c51f124SMoriah Waterland  * Determine how many additional volumes are needed for current package.
225*5c51f124SMoriah Waterland  * Note: a 0 will occur as first volume number when the package begins
226*5c51f124SMoriah Waterland  * on the next volume.
227*5c51f124SMoriah Waterland  */
228*5c51f124SMoriah Waterland static int
229*5c51f124SMoriah Waterland ds_volsum(struct dstoc *toc)
230*5c51f124SMoriah Waterland {
231*5c51f124SMoriah Waterland 	int curpartcnt, volcnt;
232*5c51f124SMoriah Waterland 	char volnos[128], tmpvol[128];
233*5c51f124SMoriah Waterland 	if (toc->volnos[0]) {
234*5c51f124SMoriah Waterland 		int index, sum;
235*5c51f124SMoriah Waterland 		sscanf(toc->volnos, "%d %[ 0-9]", &curpartcnt, volnos);
236*5c51f124SMoriah Waterland 		volcnt = 0;
237*5c51f124SMoriah Waterland 		sum = curpartcnt;
238*5c51f124SMoriah Waterland 		while (sum < toc->nparts && sscanf(volnos, "%d %[ 0-9]",
239*5c51f124SMoriah Waterland 		    &index, tmpvol) >= 1) {
240*5c51f124SMoriah Waterland 			(void) strcpy(volnos, tmpvol);
241*5c51f124SMoriah Waterland 			volcnt++;
242*5c51f124SMoriah Waterland 			sum += index;
243*5c51f124SMoriah Waterland 		}
244*5c51f124SMoriah Waterland 		/* side effect - set number of parts read on current volume */
245*5c51f124SMoriah Waterland 		ds_volpart = index;
246*5c51f124SMoriah Waterland 		return (volcnt);
247*5c51f124SMoriah Waterland 	}
248*5c51f124SMoriah Waterland 	ds_volpart += toc->nparts;
249*5c51f124SMoriah Waterland 	return (0);
250*5c51f124SMoriah Waterland }
251*5c51f124SMoriah Waterland 
252*5c51f124SMoriah Waterland /* initialize ds_curpartcnt and ds_volnos */
253*5c51f124SMoriah Waterland static void
254*5c51f124SMoriah Waterland ds_pkginit(void)
255*5c51f124SMoriah Waterland {
256*5c51f124SMoriah Waterland 	if (ds_toc->volnos[0])
257*5c51f124SMoriah Waterland 		sscanf(ds_toc->volnos, "%d %[ 0-9]", &ds_curpartcnt, ds_volnos);
258*5c51f124SMoriah Waterland 	else
259*5c51f124SMoriah Waterland 		ds_curpartcnt = -1;
260*5c51f124SMoriah Waterland }
261*5c51f124SMoriah Waterland 
262*5c51f124SMoriah Waterland /*
263*5c51f124SMoriah Waterland  * functions to pass current package info to exec'ed program
264*5c51f124SMoriah Waterland  */
265*5c51f124SMoriah Waterland void
266*5c51f124SMoriah Waterland ds_putinfo(char *buf)
267*5c51f124SMoriah Waterland {
268*5c51f124SMoriah Waterland 	(void) sprintf(buf, "%d %d %d %d %d %d %d %d %d %d %s",
269*5c51f124SMoriah Waterland 	    ds_fd, ds_realfd, ds_volcnt, ds_volno, ds_totread, ds_volpart,
270*5c51f124SMoriah Waterland 	    ds_skippart, ds_bufsize, ds_toc->nparts, ds_toc->maxsiz,
271*5c51f124SMoriah Waterland 	    ds_toc->volnos);
272*5c51f124SMoriah Waterland }
273*5c51f124SMoriah Waterland 
274*5c51f124SMoriah Waterland int
275*5c51f124SMoriah Waterland ds_getinfo(char *string)
276*5c51f124SMoriah Waterland {
277*5c51f124SMoriah Waterland 	ds_toc = (struct dstoc *)calloc(1, sizeof (struct dstoc));
278*5c51f124SMoriah Waterland 	(void) sscanf(string, "%d %d %d %d %d %d %d %d %d %d %[ 0-9]",
279*5c51f124SMoriah Waterland 	    &ds_fd, &ds_realfd, &ds_volcnt, &ds_volno, &ds_totread,
280*5c51f124SMoriah Waterland 	    &ds_volpart, &ds_skippart, &ds_bufsize, &ds_toc->nparts,
281*5c51f124SMoriah Waterland 	    &ds_toc->maxsiz, ds_toc->volnos);
282*5c51f124SMoriah Waterland 	ds_pkginit();
283*5c51f124SMoriah Waterland 	return (ds_toc->nparts);
284*5c51f124SMoriah Waterland }
285*5c51f124SMoriah Waterland 
286*5c51f124SMoriah Waterland /*
287*5c51f124SMoriah Waterland  * Return true if the file descriptor (ds_fd) is open on the package stream.
288*5c51f124SMoriah Waterland  */
289*5c51f124SMoriah Waterland boolean_t
290*5c51f124SMoriah Waterland ds_fd_open(void)
291*5c51f124SMoriah Waterland {
292*5c51f124SMoriah Waterland 	return (ds_fd >= 0 ? B_TRUE : B_FALSE);
293*5c51f124SMoriah Waterland }
294*5c51f124SMoriah Waterland 
295*5c51f124SMoriah Waterland /*
296*5c51f124SMoriah Waterland  * Read the source device. Acquire the header data and check it for validity.
297*5c51f124SMoriah Waterland  */
298*5c51f124SMoriah Waterland int
299*5c51f124SMoriah Waterland ds_init(char *device, char **pkg, char *norewind)
300*5c51f124SMoriah Waterland {
301*5c51f124SMoriah Waterland 	struct dstoc *tail, *toc_pt;
302*5c51f124SMoriah Waterland 	char	*ret;
303*5c51f124SMoriah Waterland 	char	cmd[CMDSIZ];
304*5c51f124SMoriah Waterland 	char	line[LSIZE+1];
305*5c51f124SMoriah Waterland 	int	i, n, count = 0, header_size = BLK_SIZE;
306*5c51f124SMoriah Waterland 
307*5c51f124SMoriah Waterland 	if (!ds_header) { 	/* If the header hasn't been read yet */
308*5c51f124SMoriah Waterland 		if (ds_fd >= 0)
309*5c51f124SMoriah Waterland 			(void) ds_close(0);
310*5c51f124SMoriah Waterland 
311*5c51f124SMoriah Waterland 		/* always start with rewind device */
312*5c51f124SMoriah Waterland 		if ((ds_fd = open(device, O_RDONLY)) < 0) {
313*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
314*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_OPEN), device, errno);
315*5c51f124SMoriah Waterland 			return (-1);
316*5c51f124SMoriah Waterland 		}
317*5c51f124SMoriah Waterland 
318*5c51f124SMoriah Waterland 		/* allocate room for the header equivalent to a block */
319*5c51f124SMoriah Waterland 		if ((ds_header = (char *)calloc(BLK_SIZE, 1)) == NULL) {
320*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
321*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_MEM));
322*5c51f124SMoriah Waterland 			return (-1);
323*5c51f124SMoriah Waterland 		}
324*5c51f124SMoriah Waterland 
325*5c51f124SMoriah Waterland 		/* initialize the device */
326*5c51f124SMoriah Waterland 		if (ds_ginit(device) < 0) {
327*5c51f124SMoriah Waterland 			(void) ds_close(0);
328*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
329*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_OPEN), device, errno);
330*5c51f124SMoriah Waterland 			return (-1);
331*5c51f124SMoriah Waterland 		}
332*5c51f124SMoriah Waterland 
333*5c51f124SMoriah Waterland 		/* read a logical block from the source device */
334*5c51f124SMoriah Waterland 		if (read(ds_fd, ds_header, BLK_SIZE) != BLK_SIZE) {
335*5c51f124SMoriah Waterland 			rpterr();
336*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
337*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_TOC));
338*5c51f124SMoriah Waterland 			(void) ds_close(0);
339*5c51f124SMoriah Waterland 			return (-1);
340*5c51f124SMoriah Waterland 		}
341*5c51f124SMoriah Waterland 
342*5c51f124SMoriah Waterland 		/*
343*5c51f124SMoriah Waterland 		 * This loop scans the medium for the start of the header.
344*5c51f124SMoriah Waterland 		 * If the above read worked, we skip this. If it did't, this
345*5c51f124SMoriah Waterland 		 * loop will retry the read ten times looking for the header
346*5c51f124SMoriah Waterland 		 * marker string.
347*5c51f124SMoriah Waterland 		 */
348*5c51f124SMoriah Waterland 		while (strncmp(ds_header, HDR_PREFIX, 20) != 0) {
349*5c51f124SMoriah Waterland 			/* only ten tries iff the device rewinds */
350*5c51f124SMoriah Waterland 			if (!norewind || count++ > 10) {
351*5c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_UNPACK));
352*5c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_TOC));
353*5c51f124SMoriah Waterland 				(void) ds_close(0);
354*5c51f124SMoriah Waterland 				return (-1);
355*5c51f124SMoriah Waterland 			}
356*5c51f124SMoriah Waterland 
357*5c51f124SMoriah Waterland 			/* read through to the last block */
358*5c51f124SMoriah Waterland 			if (count > 1)
359*5c51f124SMoriah Waterland 				while (read(ds_fd, ds_header, BLK_SIZE) > 0)
360*5c51f124SMoriah Waterland 					;
361*5c51f124SMoriah Waterland 
362*5c51f124SMoriah Waterland 			/* then close the device */
363*5c51f124SMoriah Waterland 			(void) ds_close(0);
364*5c51f124SMoriah Waterland 
365*5c51f124SMoriah Waterland 			/* and reopen it */
366*5c51f124SMoriah Waterland 			if ((ds_fd = open(norewind, O_RDONLY)) < 0) {
367*5c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_UNPACK));
368*5c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_OPEN), device, errno);
369*5c51f124SMoriah Waterland 				(void) free(ds_header);
370*5c51f124SMoriah Waterland 				return (-1);
371*5c51f124SMoriah Waterland 			}
372*5c51f124SMoriah Waterland 
373*5c51f124SMoriah Waterland 			/* initialize the device */
374*5c51f124SMoriah Waterland 			if (ds_ginit(device) < 0) {
375*5c51f124SMoriah Waterland 				(void) ds_close(0);
376*5c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_UNPACK));
377*5c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_OPEN), device, errno);
378*5c51f124SMoriah Waterland 				return (-1);
379*5c51f124SMoriah Waterland 			}
380*5c51f124SMoriah Waterland 
381*5c51f124SMoriah Waterland 			/* read the block again */
382*5c51f124SMoriah Waterland 			if (read(ds_fd, ds_header, BLK_SIZE) != BLK_SIZE) {
383*5c51f124SMoriah Waterland 				rpterr();
384*5c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_UNPACK));
385*5c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_TOC));
386*5c51f124SMoriah Waterland 				(void) ds_close(0);
387*5c51f124SMoriah Waterland 				return (-1);
388*5c51f124SMoriah Waterland 			}
389*5c51f124SMoriah Waterland 		}
390*5c51f124SMoriah Waterland 
391*5c51f124SMoriah Waterland 		/* Now keep scanning until the whole header is in place. */
392*5c51f124SMoriah Waterland 		while (strstr(ds_header, HDR_SUFFIX) == NULL) {
393*5c51f124SMoriah Waterland 			/* We need a bigger buffer */
394*5c51f124SMoriah Waterland 			if ((ds_header = (char *)realloc(ds_header,
395*5c51f124SMoriah Waterland 			    header_size + BLK_SIZE)) == NULL) {
396*5c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_UNPACK));
397*5c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_MEM));
398*5c51f124SMoriah Waterland 				(void) ds_close(0);
399*5c51f124SMoriah Waterland 				return (1);
400*5c51f124SMoriah Waterland 			}
401*5c51f124SMoriah Waterland 
402*5c51f124SMoriah Waterland 			/* clear the new memory */
403*5c51f124SMoriah Waterland 			(void) memset(ds_header + header_size, '\0',
404*5c51f124SMoriah Waterland 			    BLK_SIZE);
405*5c51f124SMoriah Waterland 
406*5c51f124SMoriah Waterland 
407*5c51f124SMoriah Waterland 			/* read a logical block from the source device */
408*5c51f124SMoriah Waterland 			if (read(ds_fd, ds_header + header_size, BLK_SIZE) !=
409*5c51f124SMoriah Waterland 			    BLK_SIZE) {
410*5c51f124SMoriah Waterland 				rpterr();
411*5c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_UNPACK));
412*5c51f124SMoriah Waterland 				logerr(pkg_gt(MSG_TOC));
413*5c51f124SMoriah Waterland 				(void) ds_close(0);
414*5c51f124SMoriah Waterland 				return (-1);
415*5c51f124SMoriah Waterland 			} else
416*5c51f124SMoriah Waterland 				header_size += BLK_SIZE;	/* new size */
417*5c51f124SMoriah Waterland 		}
418*5c51f124SMoriah Waterland 
419*5c51f124SMoriah Waterland 		/*
420*5c51f124SMoriah Waterland 		 * remember rewind device for ds_close to rewind at
421*5c51f124SMoriah Waterland 		 * close
422*5c51f124SMoriah Waterland 		 */
423*5c51f124SMoriah Waterland 		if (count >= 1)
424*5c51f124SMoriah Waterland 			ds_device = device;
425*5c51f124SMoriah Waterland 		ds_headsize = header_size;
426*5c51f124SMoriah Waterland 
427*5c51f124SMoriah Waterland 	}
428*5c51f124SMoriah Waterland 
429*5c51f124SMoriah Waterland 	pds_header = ds_header;
430*5c51f124SMoriah Waterland 
431*5c51f124SMoriah Waterland 	/* save raw copy of header for later use in BIO_dump_header */
432*5c51f124SMoriah Waterland 	if ((ds_header_raw = (char *)malloc(header_size)) == NULL) {
433*5c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_UNPACK));
434*5c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_MEM));
435*5c51f124SMoriah Waterland 		(void) ds_close(0);
436*5c51f124SMoriah Waterland 		return (1);
437*5c51f124SMoriah Waterland 	}
438*5c51f124SMoriah Waterland 	memcpy(ds_header_raw, ds_header, header_size);
439*5c51f124SMoriah Waterland 
440*5c51f124SMoriah Waterland 	/* read datastream table of contents */
441*5c51f124SMoriah Waterland 	ds_head = tail = (struct dstoc *)0;
442*5c51f124SMoriah Waterland 	ds_volcnt = 1;
443*5c51f124SMoriah Waterland 
444*5c51f124SMoriah Waterland 	while (ret = ds_gets(line, LSIZE)) {
445*5c51f124SMoriah Waterland 		if (strcmp(line, HDR_SUFFIX) == 0)
446*5c51f124SMoriah Waterland 			break;
447*5c51f124SMoriah Waterland 		if (!line[0] || line[0] == '#')
448*5c51f124SMoriah Waterland 			continue;
449*5c51f124SMoriah Waterland 		toc_pt = (struct dstoc *)calloc(1, sizeof (struct dstoc));
450*5c51f124SMoriah Waterland 		if (!toc_pt) {
451*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
452*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_MEM));
453*5c51f124SMoriah Waterland 			ecleanup();
454*5c51f124SMoriah Waterland 			(void) free(ds_header);
455*5c51f124SMoriah Waterland 			return (-1);
456*5c51f124SMoriah Waterland 		}
457*5c51f124SMoriah Waterland 		if (sscanf(line, "%s %d %d %[ 0-9]", toc_pt->pkg,
458*5c51f124SMoriah Waterland 		    &toc_pt->nparts, &toc_pt->maxsiz, toc_pt->volnos) < 3) {
459*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
460*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_TOC));
461*5c51f124SMoriah Waterland 			free(toc_pt);
462*5c51f124SMoriah Waterland 			(void) free(ds_header);
463*5c51f124SMoriah Waterland 			ecleanup();
464*5c51f124SMoriah Waterland 			return (-1);
465*5c51f124SMoriah Waterland 		}
466*5c51f124SMoriah Waterland 		if (tail) {
467*5c51f124SMoriah Waterland 			tail->next = toc_pt;
468*5c51f124SMoriah Waterland 			tail = toc_pt;
469*5c51f124SMoriah Waterland 		} else
470*5c51f124SMoriah Waterland 			ds_head = tail = toc_pt;
471*5c51f124SMoriah Waterland 		ds_volcnt += ds_volsum(toc_pt);
472*5c51f124SMoriah Waterland 	}
473*5c51f124SMoriah Waterland 	if (!ret) {
474*5c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_UNPACK));
475*5c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_TOC));
476*5c51f124SMoriah Waterland 		(void) free(ds_header);
477*5c51f124SMoriah Waterland 		return (-1);
478*5c51f124SMoriah Waterland 	}
479*5c51f124SMoriah Waterland 	sighold(SIGINT);
480*5c51f124SMoriah Waterland 	sigrelse(SIGINT);
481*5c51f124SMoriah Waterland 	if (!ds_head) {
482*5c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_UNPACK));
483*5c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_EMPTY));
484*5c51f124SMoriah Waterland 		(void) free(ds_header);
485*5c51f124SMoriah Waterland 		return (-1);
486*5c51f124SMoriah Waterland 	}
487*5c51f124SMoriah Waterland 	/* this could break, thanks to cpio command limit */
488*5c51f124SMoriah Waterland #ifndef SUNOS41
489*5c51f124SMoriah Waterland 	(void) sprintf(cmd, "%s -icdumD -C %d", CPIOPROC, (int)BLK_SIZE);
490*5c51f124SMoriah Waterland #else
491*5c51f124SMoriah Waterland 	(void) sprintf(cmd, "%s -icdum -C %d", CPIOPROC, (int)BLK_SIZE);
492*5c51f124SMoriah Waterland #endif
493*5c51f124SMoriah Waterland 	n = 0;
494*5c51f124SMoriah Waterland 	for (i = 0; pkg[i]; i++) {
495*5c51f124SMoriah Waterland 		if (strcmp(pkg[i], "all") == 0)
496*5c51f124SMoriah Waterland 			continue;
497*5c51f124SMoriah Waterland 		if (n == 0) {
498*5c51f124SMoriah Waterland 			strcat(cmd, " ");
499*5c51f124SMoriah Waterland 			n = 1;
500*5c51f124SMoriah Waterland 		}
501*5c51f124SMoriah Waterland 		strlcat(cmd, pkg[i], CMDSIZ);
502*5c51f124SMoriah Waterland 		strlcat(cmd, "'/*' ", CMDSIZ);
503*5c51f124SMoriah Waterland 
504*5c51f124SMoriah Waterland 		/* extract signature too, if present. */
505*5c51f124SMoriah Waterland 		strlcat(cmd, SIGNATURE_FILENAME, CMDSIZ);
506*5c51f124SMoriah Waterland 		strlcat(cmd, " ", CMDSIZ);
507*5c51f124SMoriah Waterland 	}
508*5c51f124SMoriah Waterland 
509*5c51f124SMoriah Waterland 	/*
510*5c51f124SMoriah Waterland 	 * if we are extracting all packages (pkgs == NULL),
511*5c51f124SMoriah Waterland 	 * signature will automatically be extracted
512*5c51f124SMoriah Waterland 	 */
513*5c51f124SMoriah Waterland 	if (n = esystem(cmd, ds_fd, -1)) {
514*5c51f124SMoriah Waterland 		rpterr();
515*5c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_UNPACK));
516*5c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_CMDFAIL), cmd, n);
517*5c51f124SMoriah Waterland 		(void) free(ds_header);
518*5c51f124SMoriah Waterland 		return (-1);
519*5c51f124SMoriah Waterland 	}
520*5c51f124SMoriah Waterland 
521*5c51f124SMoriah Waterland 	ds_toc = ds_head;
522*5c51f124SMoriah Waterland 	ds_totread = 0;
523*5c51f124SMoriah Waterland 	ds_volno = 1;
524*5c51f124SMoriah Waterland 	return (0);
525*5c51f124SMoriah Waterland }
526*5c51f124SMoriah Waterland 
527*5c51f124SMoriah Waterland int
528*5c51f124SMoriah Waterland ds_findpkg(char *device, char *pkg)
529*5c51f124SMoriah Waterland {
530*5c51f124SMoriah Waterland 	char	*pkglist[2];
531*5c51f124SMoriah Waterland 	int	nskip, ods_volpart;
532*5c51f124SMoriah Waterland 
533*5c51f124SMoriah Waterland 	if (ds_head == NULL) {
534*5c51f124SMoriah Waterland 		pkglist[0] = pkg;
535*5c51f124SMoriah Waterland 		pkglist[1] = NULL;
536*5c51f124SMoriah Waterland 		if (ds_init(device, pkglist, NULL))
537*5c51f124SMoriah Waterland 			return (-1);
538*5c51f124SMoriah Waterland 	}
539*5c51f124SMoriah Waterland 
540*5c51f124SMoriah Waterland 	if (!pkg || pkgnmchk(pkg, "all", 0)) {
541*5c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_UNPACK));
542*5c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_PKGNAME));
543*5c51f124SMoriah Waterland 		return (-1);
544*5c51f124SMoriah Waterland 	}
545*5c51f124SMoriah Waterland 
546*5c51f124SMoriah Waterland 	nskip = 0;
547*5c51f124SMoriah Waterland 	ds_volno = 1;
548*5c51f124SMoriah Waterland 	ds_volpart = 0;
549*5c51f124SMoriah Waterland 	ds_toc = ds_head;
550*5c51f124SMoriah Waterland 	while (ds_toc) {
551*5c51f124SMoriah Waterland 		if (strcmp(ds_toc->pkg, pkg) == 0)
552*5c51f124SMoriah Waterland 			break;
553*5c51f124SMoriah Waterland 		nskip += ds_toc->nparts;
554*5c51f124SMoriah Waterland 		ds_volno += ds_volsum(ds_toc);
555*5c51f124SMoriah Waterland 		ds_toc = ds_toc->next;
556*5c51f124SMoriah Waterland 	}
557*5c51f124SMoriah Waterland 	if (!ds_toc) {
558*5c51f124SMoriah Waterland 		progerr(pkg_gt(ERR_UNPACK));
559*5c51f124SMoriah Waterland 		logerr(pkg_gt(MSG_NOPKG), pkg);
560*5c51f124SMoriah Waterland 		return (-1);
561*5c51f124SMoriah Waterland 	}
562*5c51f124SMoriah Waterland 
563*5c51f124SMoriah Waterland 	ds_pkginit();
564*5c51f124SMoriah Waterland 	ds_skippart = 0;
565*5c51f124SMoriah Waterland 	if (ds_curpartcnt > 0) {
566*5c51f124SMoriah Waterland 		ods_volpart = ds_volpart;
567*5c51f124SMoriah Waterland 		/*
568*5c51f124SMoriah Waterland 		 * skip past archives belonging to last package on current
569*5c51f124SMoriah Waterland 		 * volume
570*5c51f124SMoriah Waterland 		 */
571*5c51f124SMoriah Waterland 		if (ds_volpart > 0 && ds_getnextvol(device))
572*5c51f124SMoriah Waterland 			return (-1);
573*5c51f124SMoriah Waterland 		ds_totread = nskip - ods_volpart;
574*5c51f124SMoriah Waterland 		if (ds_skip(device, ods_volpart))
575*5c51f124SMoriah Waterland 			return (-1);
576*5c51f124SMoriah Waterland 	} else if (ds_curpartcnt < 0) {
577*5c51f124SMoriah Waterland 		if (ds_skip(device, nskip - ds_totread))
578*5c51f124SMoriah Waterland 			return (-1);
579*5c51f124SMoriah Waterland 	} else
580*5c51f124SMoriah Waterland 		ds_totread = nskip;
581*5c51f124SMoriah Waterland 	ds_read = 0;
582*5c51f124SMoriah Waterland 	return (ds_nparts);
583*5c51f124SMoriah Waterland }
584*5c51f124SMoriah Waterland 
585*5c51f124SMoriah Waterland /*
586*5c51f124SMoriah Waterland  * Get datastream part
587*5c51f124SMoriah Waterland  * Call for first part should be preceded by
588*5c51f124SMoriah Waterland  * call to ds_findpkg
589*5c51f124SMoriah Waterland  */
590*5c51f124SMoriah Waterland 
591*5c51f124SMoriah Waterland int
592*5c51f124SMoriah Waterland ds_getpkg(char *device, int n, char *dstdir)
593*5c51f124SMoriah Waterland {
594*5c51f124SMoriah Waterland 	struct statvfs64 svfsb;
595*5c51f124SMoriah Waterland 	u_longlong_t free_blocks;
596*5c51f124SMoriah Waterland 
597*5c51f124SMoriah Waterland 	if (ds_read >= ds_nparts)
598*5c51f124SMoriah Waterland 		return (2);
599*5c51f124SMoriah Waterland 
600*5c51f124SMoriah Waterland 	if (ds_read == n)
601*5c51f124SMoriah Waterland 		return (0);
602*5c51f124SMoriah Waterland 	else if ((ds_read > n) || (n > ds_nparts))
603*5c51f124SMoriah Waterland 		return (2);
604*5c51f124SMoriah Waterland 
605*5c51f124SMoriah Waterland 	if (ds_maxsiz > 0) {
606*5c51f124SMoriah Waterland 		if (statvfs64(".", &svfsb)) {
607*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
608*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_STATFS), errno);
609*5c51f124SMoriah Waterland 			return (-1);
610*5c51f124SMoriah Waterland 		}
611*5c51f124SMoriah Waterland #ifdef SUNOS41
612*5c51f124SMoriah Waterland 		free_blocks = svfsb.f_bfree * howmany(svfsb.f_bsize, DEV_BSIZE);
613*5c51f124SMoriah Waterland #else	/* !SUNOS41 */
614*5c51f124SMoriah Waterland 		free_blocks = (((long)svfsb.f_frsize > 0) ?
615*5c51f124SMoriah Waterland 			    howmany(svfsb.f_frsize, DEV_BSIZE) :
616*5c51f124SMoriah Waterland 			    howmany(svfsb.f_bsize, DEV_BSIZE)) * svfsb.f_bfree;
617*5c51f124SMoriah Waterland #endif	/* SUNOS41 */
618*5c51f124SMoriah Waterland 		if ((ds_maxsiz + 50) > free_blocks) {
619*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
620*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_NOSPACE), ds_maxsiz+50, free_blocks);
621*5c51f124SMoriah Waterland 			return (-1);
622*5c51f124SMoriah Waterland 		}
623*5c51f124SMoriah Waterland 	}
624*5c51f124SMoriah Waterland 	return (ds_next(device, dstdir));
625*5c51f124SMoriah Waterland }
626*5c51f124SMoriah Waterland 
627*5c51f124SMoriah Waterland static int
628*5c51f124SMoriah Waterland ds_getnextvol(char *device)
629*5c51f124SMoriah Waterland {
630*5c51f124SMoriah Waterland 	char prompt[128];
631*5c51f124SMoriah Waterland 	int n;
632*5c51f124SMoriah Waterland 
633*5c51f124SMoriah Waterland 	if (ds_close(0))
634*5c51f124SMoriah Waterland 		return (-1);
635*5c51f124SMoriah Waterland 	(void) sprintf(prompt,
636*5c51f124SMoriah Waterland 	    pkg_gt("Insert %%v %d of %d into %%p"),
637*5c51f124SMoriah Waterland 	    ds_volno, ds_volcnt);
638*5c51f124SMoriah Waterland 	if (n = getvol(device, NULL, NULL, prompt))
639*5c51f124SMoriah Waterland 		return (n);
640*5c51f124SMoriah Waterland 	if ((ds_fd = open(device, O_RDONLY)) < 0)
641*5c51f124SMoriah Waterland 		return (-1);
642*5c51f124SMoriah Waterland 	if (ds_ginit(device) < 0) {
643*5c51f124SMoriah Waterland 		(void) ds_close(0);
644*5c51f124SMoriah Waterland 		return (-1);
645*5c51f124SMoriah Waterland 	}
646*5c51f124SMoriah Waterland 	ds_volpart = 0;
647*5c51f124SMoriah Waterland 	return (0);
648*5c51f124SMoriah Waterland }
649*5c51f124SMoriah Waterland 
650*5c51f124SMoriah Waterland /*
651*5c51f124SMoriah Waterland  * called by ds_findpkg to skip past archives for unwanted packages
652*5c51f124SMoriah Waterland  * in current volume
653*5c51f124SMoriah Waterland  */
654*5c51f124SMoriah Waterland static int
655*5c51f124SMoriah Waterland ds_skip(char *device, int nskip)
656*5c51f124SMoriah Waterland {
657*5c51f124SMoriah Waterland 	char	cmd[CMDSIZ];
658*5c51f124SMoriah Waterland 	int	n, onskip = nskip;
659*5c51f124SMoriah Waterland 
660*5c51f124SMoriah Waterland 	while (nskip--) {
661*5c51f124SMoriah Waterland 		/* skip this one */
662*5c51f124SMoriah Waterland #ifndef SUNOS41
663*5c51f124SMoriah Waterland 		(void) sprintf(cmd, "%s -ictD -C %d > /dev/null",
664*5c51f124SMoriah Waterland #else
665*5c51f124SMoriah Waterland 		(void) sprintf(cmd, "%s -ict -C %d > /dev/null",
666*5c51f124SMoriah Waterland #endif
667*5c51f124SMoriah Waterland 		    CPIOPROC, (int)BLK_SIZE);
668*5c51f124SMoriah Waterland 		if (n = esystem(cmd, ds_fd, -1)) {
669*5c51f124SMoriah Waterland 			rpterr();
670*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
671*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_CMDFAIL), cmd, n);
672*5c51f124SMoriah Waterland 			nskip = onskip;
673*5c51f124SMoriah Waterland 			if (ds_volno == 1 || ds_volpart > 0)
674*5c51f124SMoriah Waterland 				return (n);
675*5c51f124SMoriah Waterland 			if (n = ds_getnextvol(device))
676*5c51f124SMoriah Waterland 				return (n);
677*5c51f124SMoriah Waterland 		}
678*5c51f124SMoriah Waterland 	}
679*5c51f124SMoriah Waterland 	ds_totread += onskip;
680*5c51f124SMoriah Waterland 	ds_volpart = onskip;
681*5c51f124SMoriah Waterland 	ds_skippart = onskip;
682*5c51f124SMoriah Waterland 	return (0);
683*5c51f124SMoriah Waterland }
684*5c51f124SMoriah Waterland 
685*5c51f124SMoriah Waterland /* skip to end of package if necessary */
686*5c51f124SMoriah Waterland void
687*5c51f124SMoriah Waterland ds_skiptoend(char *device)
688*5c51f124SMoriah Waterland {
689*5c51f124SMoriah Waterland 	if (ds_read < ds_nparts && ds_curpartcnt < 0)
690*5c51f124SMoriah Waterland 		(void) ds_skip(device, ds_nparts - ds_read);
691*5c51f124SMoriah Waterland }
692*5c51f124SMoriah Waterland 
693*5c51f124SMoriah Waterland int
694*5c51f124SMoriah Waterland ds_next(char *device, char *instdir)
695*5c51f124SMoriah Waterland {
696*5c51f124SMoriah Waterland 	char	cmd[CMDSIZ], tmpvol[128];
697*5c51f124SMoriah Waterland 	int	nparts, n, index;
698*5c51f124SMoriah Waterland 
699*5c51f124SMoriah Waterland 	/*CONSTCOND*/
700*5c51f124SMoriah Waterland 	while (1) {
701*5c51f124SMoriah Waterland 		if (ds_read + 1 > ds_curpartcnt && ds_curpartcnt >= 0) {
702*5c51f124SMoriah Waterland 			ds_volno++;
703*5c51f124SMoriah Waterland 			if (n = ds_getnextvol(device))
704*5c51f124SMoriah Waterland 				return (n);
705*5c51f124SMoriah Waterland 			(void) sscanf(ds_volnos, "%d %[ 0-9]", &index, tmpvol);
706*5c51f124SMoriah Waterland 			(void) strcpy(ds_volnos, tmpvol);
707*5c51f124SMoriah Waterland 			ds_curpartcnt += index;
708*5c51f124SMoriah Waterland 		}
709*5c51f124SMoriah Waterland #ifndef SUNOS41
710*5c51f124SMoriah Waterland 		(void) sprintf(cmd, "%s -icdumD -C %d",
711*5c51f124SMoriah Waterland #else
712*5c51f124SMoriah Waterland 		(void) sprintf(cmd, "%s -icdum -C %d",
713*5c51f124SMoriah Waterland #endif
714*5c51f124SMoriah Waterland 		    CPIOPROC, (int)BLK_SIZE);
715*5c51f124SMoriah Waterland 		if (n = esystem(cmd, ds_fd, -1)) {
716*5c51f124SMoriah Waterland 			rpterr();
717*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_UNPACK));
718*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_CMDFAIL), cmd, n);
719*5c51f124SMoriah Waterland 		}
720*5c51f124SMoriah Waterland 		if (ds_read == 0)
721*5c51f124SMoriah Waterland 			nparts = 0;
722*5c51f124SMoriah Waterland 		else
723*5c51f124SMoriah Waterland 			nparts = ds_toc->nparts;
724*5c51f124SMoriah Waterland 		if (n || (n = ckvolseq(instdir, ds_read + 1, nparts))) {
725*5c51f124SMoriah Waterland 			if (ds_volno == 1 || ds_volpart > ds_skippart)
726*5c51f124SMoriah Waterland 				return (-1);
727*5c51f124SMoriah Waterland 
728*5c51f124SMoriah Waterland 			if (n = ds_getnextvol(device))
729*5c51f124SMoriah Waterland 				return (n);
730*5c51f124SMoriah Waterland 			continue;
731*5c51f124SMoriah Waterland 		}
732*5c51f124SMoriah Waterland 		ds_read++;
733*5c51f124SMoriah Waterland 		ds_totread++;
734*5c51f124SMoriah Waterland 		ds_volpart++;
735*5c51f124SMoriah Waterland 
736*5c51f124SMoriah Waterland 		return (0);
737*5c51f124SMoriah Waterland 	}
738*5c51f124SMoriah Waterland 	/*NOTREACHED*/
739*5c51f124SMoriah Waterland }
740*5c51f124SMoriah Waterland 
741*5c51f124SMoriah Waterland /*
742*5c51f124SMoriah Waterland  * Name:		BIO_ds_dump
743*5c51f124SMoriah Waterland  * Description:	Dumps all data from the static 'ds_fd' file handle into
744*5c51f124SMoriah Waterland  *		the supplied BIO.
745*5c51f124SMoriah Waterland  *
746*5c51f124SMoriah Waterland  * Arguments:	err - where to record any errors.
747*5c51f124SMoriah Waterland  *		device - Description of device being dumped into,
748*5c51f124SMoriah Waterland  *			for error reporting
749*5c51f124SMoriah Waterland  *		bio - BIO object to dump data into
750*5c51f124SMoriah Waterland  *
751*5c51f124SMoriah Waterland  * Returns :	zero - successfully dumped all data to EOF
752*5c51f124SMoriah Waterland  *		non-zero - some failure occurred.
753*5c51f124SMoriah Waterland  */
754*5c51f124SMoriah Waterland int
755*5c51f124SMoriah Waterland BIO_ds_dump(PKG_ERR *err, char *device, BIO *bio)
756*5c51f124SMoriah Waterland {
757*5c51f124SMoriah Waterland 	int	amtread;
758*5c51f124SMoriah Waterland 	char	readbuf[BLK_SIZE];
759*5c51f124SMoriah Waterland 
760*5c51f124SMoriah Waterland 	/*
761*5c51f124SMoriah Waterland 	 * note this will read to the end of the device, so it won't
762*5c51f124SMoriah Waterland 	 * work for character devices since we don't know when the
763*5c51f124SMoriah Waterland 	 * end of the CPIO archive is
764*5c51f124SMoriah Waterland 	 */
765*5c51f124SMoriah Waterland 	while ((amtread = read(ds_fd, readbuf, BLK_SIZE)) != 0) {
766*5c51f124SMoriah Waterland 		if (BIO_write(bio, readbuf, amtread) != amtread) {
767*5c51f124SMoriah Waterland 			pkgerr_add(err, PKGERR_WRITE, ERR_WRITE, device,
768*5c51f124SMoriah Waterland 			    ERR_error_string(ERR_get_error(), NULL));
769*5c51f124SMoriah Waterland 			return (1);
770*5c51f124SMoriah Waterland 		}
771*5c51f124SMoriah Waterland 	}
772*5c51f124SMoriah Waterland 
773*5c51f124SMoriah Waterland 	return (0);
774*5c51f124SMoriah Waterland 	/*NOTREACHED*/
775*5c51f124SMoriah Waterland }
776*5c51f124SMoriah Waterland 
777*5c51f124SMoriah Waterland 
778*5c51f124SMoriah Waterland /*
779*5c51f124SMoriah Waterland  * Name:		BIO_ds_dump_header
780*5c51f124SMoriah Waterland  * Description:	Dumps all ds_headsize bytes from the
781*5c51f124SMoriah Waterland  *		static 'ds_header_raw' character array
782*5c51f124SMoriah Waterland  *		to the supplied BIO.
783*5c51f124SMoriah Waterland  *
784*5c51f124SMoriah Waterland  * Arguments:	err - where to record any errors.
785*5c51f124SMoriah Waterland  *		bio - BIO object to dump data into
786*5c51f124SMoriah Waterland  *
787*5c51f124SMoriah Waterland  * Returns :	zero - successfully dumped all raw
788*5c51f124SMoriah Waterland  *		header characters
789*5c51f124SMoriah Waterland  *		non-zero - some failure occurred.
790*5c51f124SMoriah Waterland  */
791*5c51f124SMoriah Waterland int
792*5c51f124SMoriah Waterland BIO_ds_dump_header(PKG_ERR *err, BIO *bio)
793*5c51f124SMoriah Waterland {
794*5c51f124SMoriah Waterland 
795*5c51f124SMoriah Waterland 	char	zeros[BLK_SIZE];
796*5c51f124SMoriah Waterland 
797*5c51f124SMoriah Waterland 	memset(zeros, 0, BLK_SIZE);
798*5c51f124SMoriah Waterland 
799*5c51f124SMoriah Waterland 	if (BIO_write(bio, ds_header_raw, ds_headsize) != ds_headsize) {
800*5c51f124SMoriah Waterland 		pkgerr_add(err, PKGERR_WRITE, ERR_WRITE, "bio",
801*5c51f124SMoriah Waterland 		    ERR_error_string(ERR_get_error(), NULL));
802*5c51f124SMoriah Waterland 		return (1);
803*5c51f124SMoriah Waterland 	}
804*5c51f124SMoriah Waterland 
805*5c51f124SMoriah Waterland 	return (0);
806*5c51f124SMoriah Waterland }
807*5c51f124SMoriah Waterland 
808*5c51f124SMoriah Waterland /*
809*5c51f124SMoriah Waterland  * ds_ginit: Determine the device being accessed, set the buffer size,
810*5c51f124SMoriah Waterland  * and perform any device specific initialization.  For the 3B2,
811*5c51f124SMoriah Waterland  * a device with major number of 17 (0x11) is an internal hard disk,
812*5c51f124SMoriah Waterland  * unless the minor number is 128 (0x80) in which case it is an internal
813*5c51f124SMoriah Waterland  * floppy disk.  Otherwise, get the system configuration
814*5c51f124SMoriah Waterland  * table and check it by comparing slot numbers to major numbers.
815*5c51f124SMoriah Waterland  * For the special case of the 3B2 CTC several unusual things must be done.
816*5c51f124SMoriah Waterland  * To enable
817*5c51f124SMoriah Waterland  * streaming mode on the CTC, the file descriptor must be closed, re-opened
818*5c51f124SMoriah Waterland  * (with O_RDWR and O_CTSPECIAL flags set), the STREAMON ioctl(2) command
819*5c51f124SMoriah Waterland  * issued, and the file descriptor re-re-opened either read-only or write_only.
820*5c51f124SMoriah Waterland  */
821*5c51f124SMoriah Waterland 
822*5c51f124SMoriah Waterland int
823*5c51f124SMoriah Waterland ds_ginit(char *device)
824*5c51f124SMoriah Waterland {
825*5c51f124SMoriah Waterland #ifdef u3b2
826*5c51f124SMoriah Waterland 	major_t maj;
827*5c51f124SMoriah Waterland 	minor_t min;
828*5c51f124SMoriah Waterland 	int nflag, i, count, size;
829*5c51f124SMoriah Waterland 	struct s3bconf *buffer;
830*5c51f124SMoriah Waterland 	struct s3bc *table;
831*5c51f124SMoriah Waterland 	struct stat st_buf;
832*5c51f124SMoriah Waterland 	int devtype;
833*5c51f124SMoriah Waterland 	char buf[BLK_SIZE];
834*5c51f124SMoriah Waterland 	int fd2, fd;
835*5c51f124SMoriah Waterland #endif	/* u3b2 */
836*5c51f124SMoriah Waterland 	int oflag;
837*5c51f124SMoriah Waterland 	char *pbufsize, cmd[CMDSIZ];
838*5c51f124SMoriah Waterland 	int fd2, fd;
839*5c51f124SMoriah Waterland 
840*5c51f124SMoriah Waterland 	if ((pbufsize = devattr(device, "bufsize")) != NULL) {
841*5c51f124SMoriah Waterland 		ds_bufsize = atoi(pbufsize);
842*5c51f124SMoriah Waterland 		(void) free(pbufsize);
843*5c51f124SMoriah Waterland 	} else
844*5c51f124SMoriah Waterland 		ds_bufsize = BLK_SIZE;
845*5c51f124SMoriah Waterland 	oflag = fcntl(ds_fd, F_GETFL, 0);
846*5c51f124SMoriah Waterland #ifdef u3b2
847*5c51f124SMoriah Waterland 	devtype = G_NO_DEV;
848*5c51f124SMoriah Waterland 	if (fstat(ds_fd, &st_buf) == -1)
849*5c51f124SMoriah Waterland 		return (-1);
850*5c51f124SMoriah Waterland 	if (!S_ISCHR(st_buf.st_mode) && !S_ISBLK(st_buf.st_mode))
851*5c51f124SMoriah Waterland 		goto lab;
852*5c51f124SMoriah Waterland 
853*5c51f124SMoriah Waterland 	/*
854*5c51f124SMoriah Waterland 	 * We'll have to add a remote attribute to stat but this should
855*5c51f124SMoriah Waterland 	 * work for now.
856*5c51f124SMoriah Waterland 	 */
857*5c51f124SMoriah Waterland 	else if (st_buf.st_dev & 0x8000)	/* if remote  rdev */
858*5c51f124SMoriah Waterland 		goto lab;
859*5c51f124SMoriah Waterland 
860*5c51f124SMoriah Waterland 	maj = major(st_buf.st_rdev);
861*5c51f124SMoriah Waterland 	min = minor(st_buf.st_rdev);
862*5c51f124SMoriah Waterland 	if (maj == 0x11) { /* internal hard or floppy disk */
863*5c51f124SMoriah Waterland 		if (min & 0x80)
864*5c51f124SMoriah Waterland 			devtype = G_3B2_FD; /* internal floppy disk */
865*5c51f124SMoriah Waterland 		else
866*5c51f124SMoriah Waterland 			devtype = G_3B2_HD; /* internal hard disk */
867*5c51f124SMoriah Waterland 	} else {
868*5c51f124SMoriah Waterland 		if (sys3b(S3BCONF, (struct s3bconf *)&count, sizeof (count)) ==
869*5c51f124SMoriah Waterland 		    -1)
870*5c51f124SMoriah Waterland 			return (-1);
871*5c51f124SMoriah Waterland 		size = sizeof (int) + (count * sizeof (struct s3bconf));
872*5c51f124SMoriah Waterland 		buffer = (struct s3bconf *)malloc((unsigned)size);
873*5c51f124SMoriah Waterland 		if (sys3b(S3BCONF, buffer, size) == -1)
874*5c51f124SMoriah Waterland 			return (-1);
875*5c51f124SMoriah Waterland 		table = (struct s3bc *)((char *)buffer + sizeof (int));
876*5c51f124SMoriah Waterland 		for (i = 0; i < count; i++) {
877*5c51f124SMoriah Waterland 			if (maj == (int)table->board) {
878*5c51f124SMoriah Waterland 				if (strncmp(table->name, "CTC", 3) == 0) {
879*5c51f124SMoriah Waterland 					devtype = G_3B2_CTC;
880*5c51f124SMoriah Waterland 					break;
881*5c51f124SMoriah Waterland 				} else if (strncmp(table->name, "TAPE", 4)
882*5c51f124SMoriah Waterland 						== 0) {
883*5c51f124SMoriah Waterland 					devtype = G_TAPE;
884*5c51f124SMoriah Waterland 					break;
885*5c51f124SMoriah Waterland 				}
886*5c51f124SMoriah Waterland 				/* other possible devices can go here */
887*5c51f124SMoriah Waterland 			}
888*5c51f124SMoriah Waterland 			table++;
889*5c51f124SMoriah Waterland 		}
890*5c51f124SMoriah Waterland 	}
891*5c51f124SMoriah Waterland 	switch (devtype) {
892*5c51f124SMoriah Waterland 		case G_3B2_CTC:	/* do special CTC initialization */
893*5c51f124SMoriah Waterland 			ds_bufsize = pbufsize ? ds_bufsize : 15872;
894*5c51f124SMoriah Waterland 			if (fstat(ds_fd, &orig_st_buf) < 0) {
895*5c51f124SMoriah Waterland 				ds_bufsize = -1;
896*5c51f124SMoriah Waterland 				break;
897*5c51f124SMoriah Waterland 			}
898*5c51f124SMoriah Waterland 			nflag = (O_RDWR | O_CTSPECIAL);
899*5c51f124SMoriah Waterland 			(void) close(ds_fd);
900*5c51f124SMoriah Waterland 			if ((ds_fd = open(device, nflag, 0666)) != -1) {
901*5c51f124SMoriah Waterland 				if (ioctl(ds_fd, STREAMON) != -1) {
902*5c51f124SMoriah Waterland 					(void) close(ds_fd);
903*5c51f124SMoriah Waterland 					nflag = (oflag == O_WRONLY) ?
904*5c51f124SMoriah Waterland 					    O_WRONLY : O_RDONLY;
905*5c51f124SMoriah Waterland 					if ((ds_fd =
906*5c51f124SMoriah Waterland 					    open(device, nflag, 0666)) == -1) {
907*5c51f124SMoriah Waterland 						rpterr();
908*5c51f124SMoriah Waterland 						progerr(
909*5c51f124SMoriah Waterland 						    pkg_gt(ERR_TRANSFER));
910*5c51f124SMoriah Waterland 						logerr(pkg_gt(MSG_OPEN),
911*5c51f124SMoriah Waterland 						    device, errno);
912*5c51f124SMoriah Waterland 						return (-1);
913*5c51f124SMoriah Waterland 					}
914*5c51f124SMoriah Waterland 					ds_bufsize = 15872;
915*5c51f124SMoriah Waterland 				}
916*5c51f124SMoriah Waterland 			} else
917*5c51f124SMoriah Waterland 				ds_bufsize = -1;
918*5c51f124SMoriah Waterland 			if (oflag == O_RDONLY && ds_header && ds_totread == 0)
919*5c51f124SMoriah Waterland 				/* Have already read in first block of header */
920*5c51f124SMoriah Waterland 				read(ds_fd, buf, BLK_SIZE);
921*5c51f124SMoriah Waterland 			ds_ctcflg = 1;
922*5c51f124SMoriah Waterland 
923*5c51f124SMoriah Waterland 			break;
924*5c51f124SMoriah Waterland 		case G_NO_DEV:
925*5c51f124SMoriah Waterland 		case G_3B2_HD:
926*5c51f124SMoriah Waterland 		case G_3B2_FD:
927*5c51f124SMoriah Waterland 		case G_TAPE:
928*5c51f124SMoriah Waterland 		case G_SCSI_HD: /* not developed yet */
929*5c51f124SMoriah Waterland 		case G_SCSI_FD:
930*5c51f124SMoriah Waterland 		case G_SCSI_9T:
931*5c51f124SMoriah Waterland 		case G_SCSI_Q24:
932*5c51f124SMoriah Waterland 		case G_SCSI_Q120:
933*5c51f124SMoriah Waterland 		case G_386_HD:
934*5c51f124SMoriah Waterland 		case G_386_FD:
935*5c51f124SMoriah Waterland 		case G_386_Q24:
936*5c51f124SMoriah Waterland 			ds_bufsize = pbufsize ? ds_bufsize : BLK_SIZE;
937*5c51f124SMoriah Waterland 			break;
938*5c51f124SMoriah Waterland 		default:
939*5c51f124SMoriah Waterland 			ds_bufsize = -1;
940*5c51f124SMoriah Waterland 			errno = ENODEV;
941*5c51f124SMoriah Waterland 	} /* devtype */
942*5c51f124SMoriah Waterland lab:
943*5c51f124SMoriah Waterland #endif	/* u3b2 */
944*5c51f124SMoriah Waterland 	if (ds_bufsize > BLK_SIZE) {
945*5c51f124SMoriah Waterland 		if (oflag & O_WRONLY)
946*5c51f124SMoriah Waterland 			fd = 1;
947*5c51f124SMoriah Waterland 		else
948*5c51f124SMoriah Waterland 			fd = 0;
949*5c51f124SMoriah Waterland 		fd2 = fcntl(fd, F_DUPFD, fd);
950*5c51f124SMoriah Waterland 		(void) close(fd);
951*5c51f124SMoriah Waterland 		fcntl(ds_fd, F_DUPFD, fd);
952*5c51f124SMoriah Waterland 		if (fd)
953*5c51f124SMoriah Waterland 			sprintf(cmd, "%s obs=%d 2>/dev/null", DDPROC,
954*5c51f124SMoriah Waterland 			    ds_bufsize);
955*5c51f124SMoriah Waterland 		else
956*5c51f124SMoriah Waterland 			sprintf(cmd, "%s ibs=%d 2>/dev/null", DDPROC,
957*5c51f124SMoriah Waterland 			    ds_bufsize);
958*5c51f124SMoriah Waterland 		if ((ds_pp = popen(cmd, fd ? "w" : "r")) == NULL) {
959*5c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_TRANSFER));
960*5c51f124SMoriah Waterland 			logerr(pkg_gt(MSG_POPEN), cmd, errno);
961*5c51f124SMoriah Waterland 			return (-1);
962*5c51f124SMoriah Waterland 		}
963*5c51f124SMoriah Waterland 		(void) close(fd);
964*5c51f124SMoriah Waterland 		fcntl(fd2, F_DUPFD, fd);
965*5c51f124SMoriah Waterland 		(void) close(fd2);
966*5c51f124SMoriah Waterland 		ds_realfd = ds_fd;
967*5c51f124SMoriah Waterland 		ds_fd = fileno(ds_pp);
968*5c51f124SMoriah Waterland 	}
969*5c51f124SMoriah Waterland 	return (ds_bufsize);
970*5c51f124SMoriah Waterland }
971*5c51f124SMoriah Waterland 
972*5c51f124SMoriah Waterland int
973*5c51f124SMoriah Waterland ds_close(int pkgendflg)
974*5c51f124SMoriah Waterland {
975*5c51f124SMoriah Waterland #ifdef u3b2
976*5c51f124SMoriah Waterland 	int cnt, mode;
977*5c51f124SMoriah Waterland 	char *ptr;
978*5c51f124SMoriah Waterland 	struct stat statbuf;
979*5c51f124SMoriah Waterland #endif	/* u3b2 */
980*5c51f124SMoriah Waterland 	int n, ret = 0;
981*5c51f124SMoriah Waterland 
982*5c51f124SMoriah Waterland #ifdef u3b2
983*5c51f124SMoriah Waterland 	if (ds_pp && ds_ctcflg) {
984*5c51f124SMoriah Waterland 		ds_ctcflg = 0;
985*5c51f124SMoriah Waterland 		if ((mode = fcntl(ds_realfd, F_GETFL, 0)) < 0) {
986*5c51f124SMoriah Waterland 			ret = -1;
987*5c51f124SMoriah Waterland 		} else if (mode & O_WRONLY) {
988*5c51f124SMoriah Waterland 		/*
989*5c51f124SMoriah Waterland 		 * pipe to dd write process,
990*5c51f124SMoriah Waterland 		 * make sure one more buffer
991*5c51f124SMoriah Waterland 		 * gets written out
992*5c51f124SMoriah Waterland 		 */
993*5c51f124SMoriah Waterland 			if ((ptr = calloc(BLK_SIZE, 1)) == NULL) {
994*5c51f124SMoriah Waterland 				ret = -1;
995*5c51f124SMoriah Waterland 			/* pad to bufsize */
996*5c51f124SMoriah Waterland 			} else {
997*5c51f124SMoriah Waterland 				cnt = ds_bufsize;
998*5c51f124SMoriah Waterland 				while (cnt > 0) {
999*5c51f124SMoriah Waterland 					if ((n = write(ds_fd, ptr,
1000*5c51f124SMoriah Waterland 					    BLK_SIZE)) < 0) {
1001*5c51f124SMoriah Waterland 						ret = -1;
1002*5c51f124SMoriah Waterland 						break;
1003*5c51f124SMoriah Waterland 					}
1004*5c51f124SMoriah Waterland 					cnt -= n;
1005*5c51f124SMoriah Waterland 				}
1006*5c51f124SMoriah Waterland 				(void) free(ptr);
1007*5c51f124SMoriah Waterland 			}
1008*5c51f124SMoriah Waterland 		}
1009*5c51f124SMoriah Waterland 	}
1010*5c51f124SMoriah Waterland #endif
1011*5c51f124SMoriah Waterland 	if (pkgendflg) {
1012*5c51f124SMoriah Waterland 		if (ds_header)
1013*5c51f124SMoriah Waterland 			(void) free(ds_header);
1014*5c51f124SMoriah Waterland 		ds_header = (char *)NULL;
1015*5c51f124SMoriah Waterland 		ds_totread = 0;
1016*5c51f124SMoriah Waterland 	}
1017*5c51f124SMoriah Waterland 
1018*5c51f124SMoriah Waterland 	if (ds_pp) {
1019*5c51f124SMoriah Waterland 		(void) pclose(ds_pp);
1020*5c51f124SMoriah Waterland 		ds_pp = 0;
1021*5c51f124SMoriah Waterland 		(void) close(ds_realfd);
1022*5c51f124SMoriah Waterland 		ds_realfd = -1;
1023*5c51f124SMoriah Waterland 		ds_fd = -1;
1024*5c51f124SMoriah Waterland 	} else if (ds_fd >= 0) {
1025*5c51f124SMoriah Waterland 		(void) close(ds_fd);
1026*5c51f124SMoriah Waterland 		ds_fd = -1;
1027*5c51f124SMoriah Waterland 	}
1028*5c51f124SMoriah Waterland 
1029*5c51f124SMoriah Waterland 	if (ds_device) {
1030*5c51f124SMoriah Waterland 		/* rewind device */
1031*5c51f124SMoriah Waterland 		if ((n = open(ds_device, 0)) >= 0)
1032*5c51f124SMoriah Waterland 			(void) close(n);
1033*5c51f124SMoriah Waterland 		ds_device = NULL;
1034*5c51f124SMoriah Waterland 	}
1035*5c51f124SMoriah Waterland 	return (ret);
1036*5c51f124SMoriah Waterland }
1037