fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 1063 lines 18 kB view raw
1/***************************************************************************** 2 * pce * 3 *****************************************************************************/ 4 5/***************************************************************************** 6 * File name: src/drivers/block/block.c * 7 * Created: 2003-04-14 by Hampa Hug <hampa@hampa.ch> * 8 * Copyright: (C) 2003-2019 Hampa Hug <hampa@hampa.ch> * 9 *****************************************************************************/ 10 11/***************************************************************************** 12 * This program is free software. You can redistribute it and / or modify it * 13 * under the terms of the GNU General Public License version 2 as published * 14 * by the Free Software Foundation. * 15 * * 16 * This program is distributed in the hope that it will be useful, but * 17 * WITHOUT ANY WARRANTY, without even the implied warranty of * 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * 19 * Public License for more details. * 20 *****************************************************************************/ 21 22 23#include <drivers/block/block.h> 24 25#include <drivers/block/blkchd.h> 26#include <drivers/block/blkdosem.h> 27#include <drivers/block/blkpbi.h> 28#include <drivers/block/blkpce.h> 29#include <drivers/block/blkpri.h> 30#include <drivers/block/blkpsi.h> 31#include <drivers/block/blkqed.h> 32#include <drivers/block/blkraw.h> 33 34#include <stdlib.h> 35#include <string.h> 36#include <limits.h> 37 38#include <drivers/psi/psi-img.h> 39 40 41uint16_t dsk_get_uint16_be (const void *buf, unsigned i) 42{ 43 const unsigned char *tmp; 44 uint16_t v; 45 46 tmp = (const unsigned char *) buf + i; 47 48 v = tmp[0]; 49 v = (v << 8) | tmp[1]; 50 51 return (v); 52} 53 54uint32_t dsk_get_uint32_be (const void *buf, unsigned i) 55{ 56 const unsigned char *tmp; 57 uint32_t v; 58 59 tmp = (const unsigned char *) buf + i; 60 61 v = tmp[0]; 62 v = (v << 8) | tmp[1]; 63 v = (v << 8) | tmp[2]; 64 v = (v << 8) | tmp[3]; 65 66 return (v); 67} 68 69uint64_t dsk_get_uint64_be (const void *buf, unsigned i) 70{ 71 const unsigned char *tmp; 72 uint64_t v; 73 74 tmp = (const unsigned char *) buf + i; 75 76 v = tmp[0]; 77 v = (v << 8) | tmp[1]; 78 v = (v << 8) | tmp[2]; 79 v = (v << 8) | tmp[3]; 80 v = (v << 8) | tmp[4]; 81 v = (v << 8) | tmp[5]; 82 v = (v << 8) | tmp[6]; 83 v = (v << 8) | tmp[7]; 84 85 return (v); 86} 87 88void dsk_set_uint16_be (void *buf, unsigned i, uint16_t v) 89{ 90 unsigned char *tmp; 91 92 tmp = (unsigned char *) buf + i; 93 94 tmp[0] = (v >> 8) & 0xff; 95 tmp[1] = v & 0xff; 96} 97 98void dsk_set_uint32_be (void *buf, unsigned i, uint32_t v) 99{ 100 unsigned char *tmp; 101 102 tmp = (unsigned char *) buf + i; 103 104 tmp[0] = (v >> 24) & 0xff; 105 tmp[1] = (v >> 16) & 0xff; 106 tmp[2] = (v >> 8) & 0xff; 107 tmp[3] = v & 0xff; 108} 109 110void dsk_set_uint64_be (void *buf, unsigned i, uint64_t v) 111{ 112 unsigned char *tmp; 113 114 tmp = (unsigned char *) buf + i; 115 116 tmp[0] = (v >> 56) & 0xff; 117 tmp[1] = (v >> 48) & 0xff; 118 tmp[2] = (v >> 40) & 0xff; 119 tmp[3] = (v >> 32) & 0xff; 120 tmp[4] = (v >> 24) & 0xff; 121 tmp[5] = (v >> 16) & 0xff; 122 tmp[6] = (v >> 8) & 0xff; 123 tmp[7] = v & 0xff; 124} 125 126uint16_t dsk_get_uint16_le (const void *buf, unsigned i) 127{ 128 const unsigned char *tmp; 129 uint16_t v; 130 131 tmp = (const unsigned char *) buf + i; 132 133 v = tmp[1]; 134 v = (v << 8) | tmp[0]; 135 136 return (v); 137} 138 139uint32_t dsk_get_uint32_le (const void *buf, unsigned i) 140{ 141 const unsigned char *tmp; 142 uint32_t v; 143 144 tmp = (const unsigned char *) buf + i; 145 146 v = tmp[3]; 147 v = (v << 8) | tmp[2]; 148 v = (v << 8) | tmp[1]; 149 v = (v << 8) | tmp[0]; 150 151 return (v); 152} 153 154uint64_t dsk_get_uint64_le (const void *buf, unsigned i) 155{ 156 const unsigned char *tmp; 157 uint64_t v; 158 159 tmp = (const unsigned char *) buf + i; 160 161 v = tmp[7]; 162 v = (v << 8) | tmp[6]; 163 v = (v << 8) | tmp[5]; 164 v = (v << 8) | tmp[4]; 165 v = (v << 8) | tmp[3]; 166 v = (v << 8) | tmp[2]; 167 v = (v << 8) | tmp[1]; 168 v = (v << 8) | tmp[0]; 169 170 return (v); 171} 172 173void dsk_set_uint16_le (void *buf, unsigned i, uint16_t v) 174{ 175 unsigned char *tmp; 176 177 tmp = (unsigned char *) buf + i; 178 179 tmp[0] = v & 0xff; 180 tmp[1] = (v >> 8) & 0xff; 181} 182 183void dsk_set_uint32_le (void *buf, unsigned i, uint32_t v) 184{ 185 unsigned char *tmp; 186 187 tmp = (unsigned char *) buf + i; 188 189 tmp[0] = v & 0xff; 190 tmp[1] = (v >> 8) & 0xff; 191 tmp[2] = (v >> 16) & 0xff; 192 tmp[3] = (v >> 24) & 0xff; 193} 194 195void dsk_set_uint64_le (void *buf, unsigned i, uint64_t v) 196{ 197 unsigned char *tmp; 198 199 tmp = (unsigned char *) buf + i; 200 201 tmp[0] = v & 0xff; 202 tmp[1] = (v >> 8) & 0xff; 203 tmp[2] = (v >> 16) & 0xff; 204 tmp[3] = (v >> 24) & 0xff; 205 tmp[4] = (v >> 32) & 0xff; 206 tmp[5] = (v >> 40) & 0xff; 207 tmp[6] = (v >> 48) & 0xff; 208 tmp[7] = (v >> 56) & 0xff; 209} 210 211 212int dsk_set_pos (FILE *fp, uint64_t ofs) 213{ 214#ifdef HAVE_FSEEKO 215 if (fseeko (fp, ofs, SEEK_SET)) { 216 return (1); 217 } 218#else 219 if (ofs > (uint64_t) LONG_MAX) { 220 return (1); 221 } 222 223 if (fseek (fp, (long) ofs, SEEK_SET)) { 224 return (1); 225 } 226#endif 227 228 return (0); 229} 230 231int dsk_read (FILE *fp, void *buf, uint64_t ofs, uint64_t cnt) 232{ 233 size_t r; 234 235 if (dsk_set_pos (fp, ofs)) { 236 return (1); 237 } 238 239 r = fread (buf, 1, cnt, fp); 240 241 if (r < cnt) { 242 memset ((unsigned char *) buf + r, 0x00, cnt - r); 243 } 244 245 return (0); 246} 247 248int dsk_write (FILE *fp, const void *buf, uint64_t ofs, uint64_t cnt) 249{ 250 size_t r; 251 252 if (dsk_set_pos (fp, ofs)) { 253 return (1); 254 } 255 256 r = fwrite (buf, 1, cnt, fp); 257 258 if (r != cnt) { 259 return (1); 260 } 261 262 return (0); 263} 264 265int dsk_get_filesize (FILE *fp, uint64_t *cnt) 266{ 267#ifdef HAVE_FSEEKO 268 off_t val; 269 270 if (fseeko (fp, 0, SEEK_END)) { 271 return (1); 272 } 273 274 val = ftello (fp); 275 if (val == (off_t) -1) { 276 return (1); 277 } 278#else 279 long val; 280 281 if (fseek (fp, 0, SEEK_END)) { 282 return (1); 283 } 284 285 val = ftell (fp); 286 if (val == -1) { 287 return (1); 288 } 289#endif 290 291 *cnt = val; 292 293 return (0); 294} 295 296int dsk_set_filesize (FILE *fp, uint64_t cnt) 297{ 298 fflush (fp); 299 300#ifdef HAVE_FTRUNCATE 301 if (ftruncate (fileno (fp), cnt) == 0) { 302 return (0); 303 } 304#endif 305 306 return (1); 307} 308 309 310int dsk_adjust_chs (uint32_t *n, uint32_t *c, uint32_t *h, uint32_t *s) 311{ 312 if (*n == 0) { 313 *n = *c * *h * *s; 314 } 315 316 if (*n == 0) { 317 return (1); 318 } 319 320 if (*c == 0) { 321 if (*s == 0) { 322 *s = 63; 323 } 324 325 if (*h == 0) { 326 *h = 16; 327 } 328 329 *c = *n / (*h * *s); 330 } 331 332 if (*h == 0) { 333 if (*s == 0) { 334 *s = 63; 335 } 336 337 *h = *n / (*c * *s); 338 } 339 340 if (*s == 0) { 341 *s = *n / (*c * *h); 342 } 343 344 return (0); 345} 346 347void dsk_init (disk_t *dsk, void *ext, uint32_t n, uint32_t c, uint32_t h, uint32_t s) 348{ 349 dsk->type = PCE_DISK_NONE; 350 351 dsk->del = NULL; 352 dsk->read = NULL; 353 dsk->write = NULL; 354 dsk->get_msg = NULL; 355 dsk->set_msg = NULL; 356 357 dsk->drive = 0; 358 359 dsk_adjust_chs (&n, &c, &h, &s); 360 361 dsk->blocks = n; 362 363 dsk->c = c; 364 dsk->h = h; 365 dsk->s = s; 366 367 dsk->visible_c = c; 368 dsk->visible_h = h; 369 dsk->visible_s = s; 370 371 dsk->readonly = 0; 372 373 dsk->fname = NULL; 374 375 dsk->ext = ext; 376} 377 378void dsk_del (disk_t *dsk) 379{ 380 char *tmp; 381 382 if (dsk != NULL) { 383 tmp = dsk->fname; 384 385 if (dsk->del != NULL) { 386 dsk->del (dsk); 387 } 388 389 free (tmp); 390 } 391} 392 393 394void dsk_set_drive (disk_t *dsk, unsigned d) 395{ 396 dsk->drive = d; 397} 398 399unsigned dsk_get_type (const disk_t *dsk) 400{ 401 return (dsk->type); 402} 403 404void dsk_set_type (disk_t *dsk, unsigned type) 405{ 406 dsk->type = type; 407} 408 409int dsk_get_readonly (disk_t *dsk) 410{ 411 return (dsk->readonly != 0); 412} 413 414void dsk_set_readonly (disk_t *dsk, int v) 415{ 416 dsk->readonly = (v != 0); 417} 418 419void dsk_set_fname (disk_t *dsk, const char *fname) 420{ 421 if (dsk->fname != NULL) { 422 free (dsk->fname); 423 } 424 425 if (fname == NULL) { 426 dsk->fname = NULL; 427 return; 428 } 429 430 dsk->fname = malloc (strlen (fname) + 1); 431 432 if (dsk->fname == NULL) { 433 return; 434 } 435 436 strcpy (dsk->fname, fname); 437} 438 439const char *dsk_get_fname (const disk_t *dsk) 440{ 441 return (dsk->fname); 442} 443 444int dsk_set_geometry (disk_t *dsk, uint32_t n, uint32_t c, uint32_t h, uint32_t s) 445{ 446 if (dsk_adjust_chs (&n, &c, &h, &s)) { 447 return (1); 448 } 449 450 dsk->blocks = n; 451 452 dsk->c = c; 453 dsk->h = h; 454 dsk->s = s; 455 456 return (0); 457} 458 459void dsk_set_visible_chs (disk_t *dsk, uint32_t c, uint32_t h, uint32_t s) 460{ 461 dsk->visible_c = c; 462 dsk->visible_h = h; 463 dsk->visible_s = s; 464} 465 466unsigned dsk_get_drive (const disk_t *dsk) 467{ 468 return (dsk->drive); 469} 470 471uint32_t dsk_get_block_cnt (const disk_t *dsk) 472{ 473 return (dsk->blocks); 474} 475 476 477/* 478 * Calculate heads and sectors per track from a partition table entry. 479 */ 480static 481int dsk_guess_geometry_pte (const unsigned char *p, unsigned *h, unsigned *s) 482{ 483 unsigned c1, h1, s1; 484 unsigned c2, h2, s2; 485 unsigned long l1, l2; 486 long long v1, v2; 487 488 if (p[0] & 0x7f) { 489 return (1); 490 } 491 492 /* partition start */ 493 c1 = p[3] | ((p[2] & 0xc0) << 2); 494 h1 = p[1]; 495 s1 = p[2] & 0x3f; 496 l1 = dsk_get_uint32_le (p, 8); 497 498 /* partition end */ 499 c2 = p[7] | ((p[6] & 0xc0) << 2); 500 h2 = p[5]; 501 s2 = p[6] & 0x3f; 502 l2 = dsk_get_uint32_le (p, 12); 503 504 if ((s1 == 0) || (s2 == 0) || (l1 == 0) || (l2 == 0)) { 505 return (1); 506 } 507 508 s1 -= 1; 509 s2 -= 1; 510 l2 = l1 + l2 - 1; 511 512 if ((l1 <= s1) || (l2 <= s2)) { 513 return (1); 514 } 515 516 v1 = (long long) c1 * (l2 - s2) - (long long) c2 * (l1 - s1); 517 v2 = (long long) c1 * h2 - (long long) c2 * h1; 518 519 if (v2 == 0) { 520 return (1); 521 } 522 523 *s = v1 / v2; 524 525 if ((*s == 0) || (*s > 255)) { 526 return (1); 527 } 528 529 v1 = (long long) (l2 - s2) - (long long) h2 * *s; 530 v2 = (long long) c2 * *s; 531 532 if (v2 == 0) { 533 return (0); 534 } 535 536 *h = v1 / v2; 537 538 if ((*h == 0) || (*h > 256)) { 539 return (1); 540 } 541 542 return (0); 543} 544 545static 546int dsk_guess_geometry_mbr (disk_t *dsk) 547{ 548 unsigned i; 549 unsigned char buf[512]; 550 unsigned c, h, s, th, ts; 551 552 if (dsk_read_lba (dsk, buf, 0, 1)) { 553 return (1); 554 } 555 556 if ((buf[510] != 0x55) || (buf[511] != 0xaa)) { 557 return (1); 558 } 559 560 h = 0; 561 s = 0; 562 563 th = 0; 564 ts = 0; 565 566 for (i = 0; i < 4; i++) { 567 if (dsk_guess_geometry_pte (buf + 0x1be + 16 * i, &th, &ts)) { 568 continue; 569 } 570 571 if ((h != 0) && (h != th)) { 572 return (1); 573 } 574 575 if ((s != 0) && (s != ts)) { 576 return (1); 577 } 578 579 h = th; 580 s = ts; 581 } 582 583 if ((h == 0) || (s == 0)) { 584 return (1); 585 } 586 587 c = dsk->blocks / (h * s); 588 589 dsk_set_geometry (dsk, dsk->blocks, c, h, s); 590 591 return (0); 592} 593 594static 595int dsk_guess_geometry_sun (disk_t *dsk) 596{ 597 unsigned i; 598 unsigned c, h, s, chk; 599 unsigned char buf[512]; 600 601 if (dsk_read_lba (dsk, buf, 0, 1)) { 602 return (1); 603 } 604 605 if (dsk_get_uint16_be (buf, 508) != 0xdabe) { 606 return (1); 607 } 608 609 chk = 0; 610 611 for (i = 0; i < 512; i += 2) { 612 chk ^= buf[i] << 8; 613 chk ^= buf[i + 1]; 614 } 615 616 if (chk != 0) { 617 return (1); 618 } 619 620 if (dsk_get_uint32_be (buf, 128) != 1) { 621 return (1); 622 } 623 624 if (dsk_get_uint16_be (buf, 140) > 8) { 625 return (1); 626 } 627 628 c = dsk_get_uint16_be (buf, 422); 629 h = dsk_get_uint16_be (buf, 436); 630 s = dsk_get_uint16_be (buf, 438); 631 632 dsk_set_geometry (dsk, dsk->blocks, c, h, s); 633 634 return (0); 635} 636 637static 638int dsk_guess_geometry_dos (disk_t *dsk) 639{ 640 unsigned char buf[512]; 641 uint32_t c, h, s; 642 643 if (dsk_read_lba (dsk, buf, 0, 1)) { 644 return (1); 645 } 646 647 /* boot sector id */ 648 if ((buf[510] != 0x55) || (buf[511] != 0xaa)) { 649 return (1); 650 } 651 652 /* sector size */ 653 if (dsk_get_uint16_le (buf, 11) != 512) { 654 return (1); 655 } 656 657 h = dsk_get_uint16_le (buf, 26); 658 s = dsk_get_uint16_le (buf, 24); 659 660 if ((h == 0) || (h > 255)) { 661 return (1); 662 } 663 664 if ((s == 0) || (s > 255)) { 665 return (1); 666 } 667 668 c = dsk->blocks / (h * s); 669 670 dsk_set_geometry (dsk, dsk->blocks, c, h, s); 671 672 return (0); 673} 674 675static 676int dsk_guess_geometry_size (disk_t *dsk) 677{ 678 switch (dsk->blocks) { 679 case 160 * 2: 680 dsk_set_geometry (dsk, dsk->blocks, 40, 1, 8); 681 break; 682 683 case 180 * 2: 684 dsk_set_geometry (dsk, dsk->blocks, 40, 1, 9); 685 break; 686 687 case 320 * 2: 688 dsk_set_geometry (dsk, dsk->blocks, 40, 2, 8); 689 break; 690 691 case 360 * 2: 692 dsk_set_geometry (dsk, dsk->blocks, 40, 2, 9); 693 break; 694 695 case 400 * 2: 696 dsk_set_geometry (dsk, dsk->blocks, 40, 2, 10); 697 break; 698 699 case 720 * 2: 700 dsk_set_geometry (dsk, dsk->blocks, 80, 2, 9); 701 break; 702 703 case 800 * 2: 704 dsk_set_geometry (dsk, dsk->blocks, 80, 2, 10); 705 break; 706 707 case 1200 * 2: 708 dsk_set_geometry (dsk, dsk->blocks, 80, 2, 15); 709 break; 710 711 case 1440 * 2: 712 dsk_set_geometry (dsk, dsk->blocks, 80, 2, 18); 713 break; 714 715 case 2880 * 2: 716 dsk_set_geometry (dsk, dsk->blocks, 80, 2, 36); 717 break; 718 719 default: 720 return (1); 721 } 722 723 return (0); 724} 725 726int dsk_guess_geometry (disk_t *dsk) 727{ 728 if (dsk_guess_geometry_mbr (dsk) == 0) { 729 return (0); 730 } 731 732 if (dsk_guess_geometry_dos (dsk) == 0) { 733 return (0); 734 } 735 736 if (dsk_guess_geometry_sun (dsk) == 0) { 737 return (0); 738 } 739 740 if (dsk_guess_geometry_size (dsk) == 0) { 741 return (0); 742 } 743 744 dsk_set_geometry (dsk, dsk->blocks, dsk->c, dsk->h, dsk->s); 745 746 return (0); 747} 748 749 750disk_t *dsk_auto_open (const char *fname, uint64_t ofs, int ro) 751{ 752 unsigned type; 753 754 if (dsk_pbi_probe (fname)) { 755 return (dsk_pbi_open (fname, ro)); 756 } 757 758 if (dsk_pce_probe (fname)) { 759 return (dsk_pce_open (fname, ro)); 760 } 761 762 if (dsk_qed_probe (fname)) { 763 return (dsk_qed_open (fname, ro)); 764 } 765 766 if (dsk_chd_probe (fname)) { 767 return (dsk_chd_open (fname, ro)); 768 } 769 770 if (dsk_dosemu_probe (fname)) { 771 return (dsk_dosemu_open (fname, ro)); 772 } 773 774 type = dsk_psi_probe (fname); 775 776 if (type != PSI_FORMAT_NONE) { 777 return (dsk_psi_open (fname, type, ro)); 778 } 779 780 type = dsk_pri_probe (fname); 781 782 if (type != PRI_FORMAT_NONE) { 783 return (dsk_pri_open (fname, type, ro)); 784 } 785 786 type = psi_guess_type (fname); 787 788 if (type != PSI_FORMAT_NONE) { 789 if (type != PSI_FORMAT_RAW) { 790 return (dsk_psi_open (fname, type, ro)); 791 } 792 } 793 794 return (dsk_img_open (fname, ofs, ro)); 795} 796 797 798int dsk_get_lba (disk_t *dsk, uint32_t c, uint32_t h, uint32_t s, uint32_t *v) 799{ 800 if ((s < 1) || (s > dsk->s)) { 801 return (1); 802 } 803 804 if ((h >= dsk->h) || (c >= dsk->c)) { 805 return (1); 806 } 807 808 *v = ((c * dsk->h + h) * dsk->s + s - 1); 809 810 return (0); 811} 812 813int dsk_read_lba (disk_t *dsk, void *buf, uint32_t i, uint32_t n) 814{ 815 if (dsk->read != NULL) { 816 return (dsk->read (dsk, buf, i, n)); 817 } 818 819 return (1); 820} 821 822int dsk_read_lbaz (disk_t *dsk, void *buf, uint32_t i, uint32_t n) 823{ 824 if ((i + n) <= dsk->blocks) { 825 return (dsk_read_lba (dsk, buf, i, n)); 826 } 827 828 memset (buf, 0, 512 * n); 829 830 if (i < dsk->blocks) { 831 return (dsk_read_lba (dsk, buf, i, dsk->blocks - i)); 832 } 833 834 return (0); 835} 836 837int dsk_read_chs (disk_t *dsk, void *buf, 838 uint32_t c, uint32_t h, uint32_t s, uint32_t n) 839{ 840 uint32_t i; 841 842 if (dsk_get_lba (dsk, c, h, s, &i)) { 843 return (1); 844 } 845 846 return (dsk_read_lba (dsk, buf, i, n)); 847} 848 849int dsk_write_lba (disk_t *dsk, const void *buf, uint32_t i, uint32_t n) 850{ 851 if (dsk->write != NULL) { 852 return (dsk->write (dsk, buf, i, n)); 853 } 854 855 return (1); 856} 857 858int dsk_write_chs (disk_t *dsk, const void *buf, 859 uint32_t c, uint32_t h, uint32_t s, uint32_t n) 860{ 861 uint32_t i; 862 863 if (dsk_get_lba (dsk, c, h, s, &i)) { 864 return (1); 865 } 866 867 return (dsk_write_lba (dsk, buf, i, n)); 868} 869 870int dsk_commit (disk_t *dsk) 871{ 872 return (dsk_set_msg (dsk, "commit", NULL)); 873} 874 875disk_t *dsk_create_cow (disk_t *dsk, const char *name, unsigned long minblk) 876{ 877 disk_t *cow; 878 disk_pbi_t *pbi; 879 880 if ((minblk == 0) && (dsk->type == PCE_DISK_PBI)) { 881 pbi = dsk->ext; 882 minblk = pbi->block_size; 883 } 884 885 cow = dsk_pbi_cow_create (dsk, name, dsk->blocks, dsk->c, dsk->h, dsk->s, minblk); 886 887 return (cow); 888} 889 890disk_t *dsk_open_cow (disk_t *dsk, const char *name) 891{ 892 disk_t *cow; 893 894 if ((cow = dsk_pbi_cow_open (dsk, name)) != NULL) { 895 return (cow); 896 } 897 898 if ((cow = dsk_qed_cow_open (dsk, name)) != NULL) { 899 return (cow); 900 } 901 902 return (NULL); 903} 904 905int dsk_get_msg (disk_t *dsk, const char *msg, char *val, unsigned max) 906{ 907 if (dsk->get_msg != NULL) { 908 return (dsk->get_msg (dsk, msg, val, max)); 909 } 910 911 return (1); 912} 913 914int dsk_set_msg (disk_t *dsk, const char *msg, const char *val) 915{ 916 if (dsk->set_msg != NULL) { 917 if (val == NULL) { 918 val = ""; 919 } 920 921 return (dsk->set_msg (dsk, msg, val)); 922 } 923 924 return (1); 925} 926 927 928disks_t *dsks_new (void) 929{ 930 disks_t *dsks; 931 932 dsks = (disks_t *) malloc (sizeof (disks_t)); 933 if (dsks == NULL) { 934 return (NULL); 935 } 936 937 dsks->cnt = 0; 938 dsks->dsk = NULL; 939 940 return (dsks); 941} 942 943void dsks_del (disks_t *dsks) 944{ 945 unsigned i; 946 947 if (dsks == NULL) { 948 return; 949 } 950 951 for (i = 0; i < dsks->cnt; i++) { 952 dsk_del (dsks->dsk[i]); 953 } 954 955 free (dsks->dsk); 956 free (dsks); 957} 958 959int dsks_add_disk (disks_t *dsks, disk_t *dsk) 960{ 961 unsigned i, n; 962 disk_t **tmp; 963 964 for (i = 0; i < dsks->cnt; i++) { 965 if (dsks->dsk[i]->drive == dsk->drive) { 966 return (1); 967 } 968 } 969 970 n = dsks->cnt + 1; 971 tmp = (disk_t **) realloc (dsks->dsk, n * sizeof (disk_t *)); 972 if (tmp == NULL) { 973 return (1); 974 } 975 976 tmp[dsks->cnt] = dsk; 977 978 dsks->cnt = n; 979 dsks->dsk = tmp; 980 981 return (0); 982} 983 984int dsks_rmv_disk (disks_t *dsks, disk_t *dsk) 985{ 986 int r; 987 unsigned i, j; 988 989 r = 0; 990 j = 0; 991 for (i = 0; i < dsks->cnt; i++) { 992 if (dsks->dsk[i] != dsk) { 993 dsks->dsk[j] = dsks->dsk[i]; 994 j += 1; 995 } 996 else { 997 r = 1; 998 } 999 } 1000 1001 dsks->cnt = j; 1002 1003 return (r); 1004} 1005 1006disk_t *dsks_get_disk (disks_t *dsks, unsigned drive) 1007{ 1008 unsigned i; 1009 1010 for (i = 0; i < dsks->cnt; i++) { 1011 if (dsks->dsk[i]->drive == drive) { 1012 return (dsks->dsk[i]); 1013 } 1014 } 1015 1016 return (NULL); 1017} 1018 1019int dsks_commit (disks_t *dsks) 1020{ 1021 unsigned i; 1022 int r; 1023 1024 r = 0; 1025 1026 for (i = 0; i < dsks->cnt; i++) { 1027 if (dsks->dsk[i]->set_msg != NULL) { 1028 if (dsk_set_msg (dsks->dsk[i], "commit", NULL)) { 1029 r = 1; 1030 } 1031 } 1032 } 1033 1034 return (r); 1035} 1036 1037int dsks_get_msg (disks_t *dsks, unsigned drv, const char *msg, char *val, unsigned max) 1038{ 1039 disk_t *dsk; 1040 1041 dsk = dsks_get_disk (dsks, drv); 1042 if (dsk == NULL) { 1043 return (1); 1044 } 1045 1046 return (dsk_get_msg (dsk, msg, val, max)); 1047} 1048 1049int dsks_set_msg (disks_t *dsks, unsigned drv, const char *msg, const char *val) 1050{ 1051 disk_t *dsk; 1052 1053 dsk = dsks_get_disk (dsks, drv); 1054 if (dsk == NULL) { 1055 return (1); 1056 } 1057 1058 if (val == NULL) { 1059 val = ""; 1060 } 1061 1062 return (dsk_set_msg (dsk, msg, val)); 1063}