1 #define _LARGEFILE_SOURCE
2 #define _LARGEFILE64_SOURCE
3 #define _GNU_SOURCE
4 #include <errno.h>
5
6 #include "ibm.h"
7 #include "hdd_file.h"
8
hdd_load_ext(hdd_file_t * hdd,const char * fn,int spt,int hpc,int tracks,int read_only)9 void hdd_load_ext(hdd_file_t *hdd, const char *fn, int spt, int hpc, int tracks, int read_only)
10 {
11 if (hdd->f == NULL)
12 {
13 /* Try to open existing hard disk image */
14 if (read_only)
15 hdd->f = fopen64(fn, "rb");
16 else
17 hdd->f = fopen64(fn, "rb+");
18 if (hdd->f == NULL)
19 {
20 /* Failed to open existing hard disk image */
21 if (errno == ENOENT && !read_only)
22 {
23 /* Failed because it does not exist,
24 so try to create new file */
25 hdd->f = fopen64(fn, "wb+");
26 if (hdd->f == NULL)
27 {
28 pclog("Cannot create file '%s': %s",
29 fn, strerror(errno));
30 return;
31 }
32 }
33 else
34 {
35 /* Failed for another reason */
36 pclog("Cannot open file '%s': %s",
37 fn, strerror(errno));
38 return;
39 }
40 }
41 }
42
43 hdd->spt = spt;
44 hdd->hpc = hpc;
45 hdd->tracks = tracks;
46 hdd->sectors = spt * hpc * tracks;
47 hdd->read_only = read_only;
48 }
49
hdd_load(hdd_file_t * hdd,int d,const char * fn)50 void hdd_load(hdd_file_t *hdd, int d, const char *fn)
51 {
52 hdd_load_ext(hdd, fn, hdc[d].spt, hdc[d].hpc, hdc[d].tracks, 0);
53 }
54
hdd_close(hdd_file_t * hdd)55 void hdd_close(hdd_file_t *hdd)
56 {
57 if (hdd->f)
58 {
59 fclose(hdd->f);
60 hdd->f = NULL;
61 }
62 }
63
hdd_read_sectors(hdd_file_t * hdd,int offset,int nr_sectors,void * buffer)64 int hdd_read_sectors(hdd_file_t *hdd, int offset, int nr_sectors, void *buffer)
65 {
66 off64_t addr;
67 int transfer_sectors = nr_sectors;
68
69 if ((hdd->sectors - offset) < transfer_sectors)
70 transfer_sectors = hdd->sectors - offset;
71 addr = (uint64_t)offset * 512;
72
73 fseeko64(hdd->f, addr, SEEK_SET);
74 fread(buffer, transfer_sectors*512, 1, hdd->f);
75
76 if (nr_sectors != transfer_sectors)
77 return 1;
78 return 0;
79 }
80
hdd_write_sectors(hdd_file_t * hdd,int offset,int nr_sectors,void * buffer)81 int hdd_write_sectors(hdd_file_t *hdd, int offset, int nr_sectors, void *buffer)
82 {
83 off64_t addr;
84 int transfer_sectors = nr_sectors;
85
86 if (hdd->read_only)
87 return 1;
88
89 if ((hdd->sectors - offset) < transfer_sectors)
90 transfer_sectors = hdd->sectors - offset;
91 addr = (uint64_t)offset * 512;
92
93 fseeko64(hdd->f, addr, SEEK_SET);
94 fwrite(buffer, transfer_sectors*512, 1, hdd->f);
95
96 if (nr_sectors != transfer_sectors)
97 return 1;
98 return 0;
99 }
100
hdd_format_sectors(hdd_file_t * hdd,int offset,int nr_sectors)101 int hdd_format_sectors(hdd_file_t *hdd, int offset, int nr_sectors)
102 {
103 off64_t addr;
104 int c;
105 uint8_t zero_buffer[512];
106 int transfer_sectors = nr_sectors;
107
108 if (hdd->read_only)
109 return 1;
110
111 memset(zero_buffer, 0, 512);
112
113 if ((hdd->sectors - offset) < transfer_sectors)
114 transfer_sectors = hdd->sectors - offset;
115 addr = (uint64_t)offset * 512;
116 fseeko64(hdd->f, addr, SEEK_SET);
117 for (c = 0; c < transfer_sectors; c++)
118 fwrite(zero_buffer, 512, 1, hdd->f);
119
120 if (nr_sectors != transfer_sectors)
121 return 1;
122 return 0;
123 }
124