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
ds_order(char * list[])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 *
ds_gets(char * buf,int size)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
ds_readbuf(char * device)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
ds_volsum(struct dstoc * toc)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
ds_pkginit(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
ds_putinfo(char * buf,size_t sz)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
ds_getinfo(char * string)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
ds_fd_open(void)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
ds_init(char * device,char ** pkg,char * norewind)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
ds_findpkg(char * device,char * pkg)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
ds_getpkg(char * device,int n,char * dstdir)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
ds_getnextvol(char * device)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
ds_skip(char * device,int nskip)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
ds_skiptoend(char * device)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
ds_next(char * device,char * instdir)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
BIO_ds_dump(PKG_ERR * err,char * device,BIO * bio)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
BIO_ds_dump_header(PKG_ERR * err,BIO * bio)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
ds_ginit(char * device)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
ds_close(int pkgendflg)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