fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
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}