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