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