5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * CDDL HEADER START
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * The contents of this file are subject to the terms of the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Common Development and Distribution License (the "License").
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * You may not use this file except in compliance with the License.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * or http://www.opensolaris.org/os/licensing.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * See the License for the specific language governing permissions
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * and limitations under the License.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * When distributing Covered Code, include this CDDL HEADER in each
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * If applicable, add the following below this CDDL HEADER, with the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * fields enclosed by brackets "[]" replaced with your own identifying
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * information: Portions Copyright [yyyy] [name of copyright owner]
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * CDDL HEADER END
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Use is subject to license terms.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/* All Rights Reserved */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/* libadm.a */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandextern char *devattr(char *device, char *attribute);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandextern int pkgnmchk(register char *pkg, register char *spec,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandextern int getvol(char *device, char *label, int options, char *prompt);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/* device types */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define G_TM_TAPE 1 /* Tapemaster controller */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define G_NO_DEV 29 /* device does not require special treatment */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define G_DEV_MAX 30 /* last valid device type */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandint ds_totread; /* total number of parts read */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic int ds_realfd = -1; /* file descriptor for real device */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic int ds_read; /* number of parts read for current package */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic int ds_volno; /* volume number of current volume */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic int ds_volcnt; /* total number of volumes */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic char ds_volnos[128]; /* parts/volume info */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic int ds_volpart; /* number of parts read in current volume, */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* including skipped parts */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic int ds_skippart; /* number of parts skipped in current volume */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic int ds_skip(char *device, int nskip);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland register int j, n;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland for (j = n; list[j]; j++) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* just swap places in the array */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((ds_header = (char *)realloc(ds_header,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (read(ds_fd, ds_header + ds_headsize, BLK_SIZE) < BLK_SIZE)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (length + (int)strlen(pds_header) > size)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) strncpy(buf + length, pds_header, strlen(pds_header));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) strncpy(buf, pds_header, strlen(pds_header));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * function to determine if media is datastream or mounted
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((ds_fd = open(device, O_RDONLY)) >= 0 &&
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((ds_header = (char *)calloc(BLK_SIZE, 1)) == NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else if (ds_fd >= 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Determine how many additional volumes are needed for current package.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Note: a 0 will occur as first volume number when the package begins
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * on the next volume.
4656d4747c8743290bfbe910c64cd75eb4e4af8dGarrett D'Amore (void) sscanf(toc->volnos, "%d %[ 0-9]", &curpartcnt, volnos);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland while (sum < toc->nparts && sscanf(volnos, "%d %[ 0-9]",
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* side effect - set number of parts read on current volume */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/* initialize ds_curpartcnt and ds_volnos */
4656d4747c8743290bfbe910c64cd75eb4e4af8dGarrett D'Amore (void) sscanf(ds_toc->volnos, "%d %[ 0-9]", &ds_curpartcnt,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * functions to pass current package info to exec'ed program
4656d4747c8743290bfbe910c64cd75eb4e4af8dGarrett D'Amore (void) snprintf(buf, sz, "%d %d %d %d %d %d %d %d %d %d %s",
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland ds_fd, ds_realfd, ds_volcnt, ds_volno, ds_totread, ds_volpart,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland ds_skippart, ds_bufsize, ds_toc->nparts, ds_toc->maxsiz,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland ds_toc = (struct dstoc *)calloc(1, sizeof (struct dstoc));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sscanf(string, "%d %d %d %d %d %d %d %d %d %d %[ 0-9]",
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland &ds_fd, &ds_realfd, &ds_volcnt, &ds_volno, &ds_totread,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland &ds_volpart, &ds_skippart, &ds_bufsize, &ds_toc->nparts,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Return true if the file descriptor (ds_fd) is open on the package stream.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Read the source device. Acquire the header data and check it for validity.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandds_init(char *device, char **pkg, char *norewind)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int i, n, count = 0, header_size = BLK_SIZE;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (!ds_header) { /* If the header hasn't been read yet */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* always start with rewind device */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((ds_fd = open(device, O_RDONLY)) < 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* allocate room for the header equivalent to a block */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((ds_header = (char *)calloc(BLK_SIZE, 1)) == NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* initialize the device */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* read a logical block from the source device */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (read(ds_fd, ds_header, BLK_SIZE) != BLK_SIZE) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * This loop scans the medium for the start of the header.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * If the above read worked, we skip this. If it did't, this
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * loop will retry the read ten times looking for the header
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * marker string.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland while (strncmp(ds_header, HDR_PREFIX, 20) != 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* only ten tries iff the device rewinds */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* read through to the last block */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland while (read(ds_fd, ds_header, BLK_SIZE) > 0)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* then close the device */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* and reopen it */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((ds_fd = open(norewind, O_RDONLY)) < 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* initialize the device */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* read the block again */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (read(ds_fd, ds_header, BLK_SIZE) != BLK_SIZE) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* Now keep scanning until the whole header is in place. */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland while (strstr(ds_header, HDR_SUFFIX) == NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* We need a bigger buffer */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((ds_header = (char *)realloc(ds_header,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* clear the new memory */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) memset(ds_header + header_size, '\0',
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* read a logical block from the source device */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (read(ds_fd, ds_header + header_size, BLK_SIZE) !=
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * remember rewind device for ds_close to rewind at
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* save raw copy of header for later use in BIO_dump_header */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((ds_header_raw = (char *)malloc(header_size)) == NULL) {
4656d4747c8743290bfbe910c64cd75eb4e4af8dGarrett D'Amore (void) memcpy(ds_header_raw, ds_header, header_size);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* read datastream table of contents */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland toc_pt = (struct dstoc *)calloc(1, sizeof (struct dstoc));
4656d4747c8743290bfbe910c64cd75eb4e4af8dGarrett D'Amore /* LINTED E_SEC_SCANF_UNBOUNDED_COPY */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (sscanf(line, "%s %d %d %[ 0-9]", toc_pt->pkg,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland &toc_pt->nparts, &toc_pt->maxsiz, toc_pt->volnos) < 3) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* this could break, thanks to cpio command limit */
4656d4747c8743290bfbe910c64cd75eb4e4af8dGarrett D'Amore (void) snprintf(cmd, sizeof (cmd), "%s -icdumD -C %d",
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland for (i = 0; pkg[i]; i++) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (n == 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* extract signature too, if present. */
4656d4747c8743290bfbe910c64cd75eb4e4af8dGarrett D'Amore (void) strlcat(cmd, SIGNATURE_FILENAME, CMDSIZ);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * if we are extracting all packages (pkgs == NULL),
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * signature will automatically be extracted
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * skip past archives belonging to last package on current
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (ds_volpart > 0 && ds_getnextvol(device))
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else if (ds_curpartcnt < 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Get datastream part
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Call for first part should be preceded by
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * call to ds_findpkg
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandds_getpkg(char *device, int n, char *dstdir)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland free_blocks = (((long)svfsb.f_frsize > 0) ?
4656d4747c8743290bfbe910c64cd75eb4e4af8dGarrett D'Amore howmany(svfsb.f_bsize, DEV_BSIZE)) * svfsb.f_bfree;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland logerr(pkg_gt(MSG_NOSPACE), ds_maxsiz+50, free_blocks);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (n = getvol(device, NULL, NULL, prompt))
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * called by ds_findpkg to skip past archives for unwanted packages
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * in current volume
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* skip this one */
4656d4747c8743290bfbe910c64cd75eb4e4af8dGarrett D'Amore "%s -ictD -C %d > /dev/null", CPIOPROC, (int)BLK_SIZE);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/* skip to end of package if necessary */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (ds_read < ds_nparts && ds_curpartcnt < 0)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) ds_skip(device, ds_nparts - ds_read);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*CONSTCOND*/
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (ds_read + 1 > ds_curpartcnt && ds_curpartcnt >= 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) sscanf(ds_volnos, "%d %[ 0-9]", &index, tmpvol);
4656d4747c8743290bfbe910c64cd75eb4e4af8dGarrett D'Amore (void) snprintf(cmd, sizeof (cmd), "%s -icdumD -C %d",
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (n || (n = ckvolseq(instdir, ds_read + 1, nparts))) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (ds_volno == 1 || ds_volpart > ds_skippart)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*NOTREACHED*/
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Name: BIO_ds_dump
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Description: Dumps all data from the static 'ds_fd' file handle into
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * the supplied BIO.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Arguments: err - where to record any errors.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * device - Description of device being dumped into,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * for error reporting
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * bio - BIO object to dump data into
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Returns : zero - successfully dumped all data to EOF
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * non-zero - some failure occurred.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah WaterlandBIO_ds_dump(PKG_ERR *err, char *device, BIO *bio)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * note this will read to the end of the device, so it won't
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * work for character devices since we don't know when the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * end of the CPIO archive is
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland while ((amtread = read(ds_fd, readbuf, BLK_SIZE)) != 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (BIO_write(bio, readbuf, amtread) != amtread) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland pkgerr_add(err, PKGERR_WRITE, ERR_WRITE, device,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*NOTREACHED*/
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Name: BIO_ds_dump_header
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Description: Dumps all ds_headsize bytes from the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * static 'ds_header_raw' character array
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * to the supplied BIO.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Arguments: err - where to record any errors.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * bio - BIO object to dump data into
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Returns : zero - successfully dumped all raw
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * header characters
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * non-zero - some failure occurred.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (BIO_write(bio, ds_header_raw, ds_headsize) != ds_headsize) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland pkgerr_add(err, PKGERR_WRITE, ERR_WRITE, "bio",
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * ds_ginit: Determine the device being accessed, set the buffer size,
4656d4747c8743290bfbe910c64cd75eb4e4af8dGarrett D'Amore * and perform any device specific initialization.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((pbufsize = devattr(device, "bufsize")) != NULL) {
4656d4747c8743290bfbe910c64cd75eb4e4af8dGarrett D'Amore "%s obs=%d 2>/dev/null", DDPROC, ds_bufsize);
4656d4747c8743290bfbe910c64cd75eb4e4af8dGarrett D'Amore "%s ibs=%d 2>/dev/null", DDPROC, ds_bufsize);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((ds_pp = popen(cmd, fd ? "w" : "r")) == NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else if (ds_fd >= 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* rewind device */