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