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