fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/drivers/block/blkraw.c *
7 * Created: 2004-09-17 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 2004-2012 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 "blkraw.h"
24
25#include <stdlib.h>
26
27
28static
29int dsk_img_read (disk_t *dsk, void *buf, uint32_t i, uint32_t n)
30{
31 disk_img_t *img;
32 uint64_t ofs, cnt;
33
34 if ((i + n) > dsk->blocks) {
35 return (1);
36 }
37
38 img = dsk->ext;
39
40 ofs = img->start + 512 * (uint64_t) i;
41 cnt = 512 * (uint64_t) n;
42
43 if (dsk_read (img->fp, buf, ofs, cnt)) {
44 return (1);
45 }
46
47 return (0);
48}
49
50static
51int dsk_img_write (disk_t *dsk, const void *buf, uint32_t i, uint32_t n)
52{
53 disk_img_t *img;
54 uint64_t ofs, cnt;
55
56 if (dsk->readonly) {
57 return (1);
58 }
59
60 if ((i + n) > dsk->blocks) {
61 return (1);
62 }
63
64 img = dsk->ext;
65
66 ofs = img->start + 512 * (uint64_t) i;
67 cnt = 512 * (uint64_t) n;
68
69 if (dsk_write (img->fp, buf, ofs, cnt)) {
70 return (1);
71 }
72
73 fflush (img->fp);
74
75 return (0);
76}
77
78static
79void dsk_img_del (disk_t *dsk)
80{
81 disk_img_t *img;
82
83 img = dsk->ext;
84
85 fclose (img->fp);
86 free (img);
87}
88
89static
90disk_t *dsk_img_open_size (FILE *fp, uint32_t n, uint64_t ofs, int ro)
91{
92 disk_img_t *img;
93
94 img = malloc (sizeof (disk_img_t));
95
96 if (img == NULL) {
97 return (NULL);
98 }
99
100 dsk_init (&img->dsk, img, n, 0, 0, 0);
101
102 dsk_set_type (&img->dsk, PCE_DISK_RAW);
103
104 dsk_set_readonly (&img->dsk, ro);
105
106 img->dsk.del = dsk_img_del;
107 img->dsk.read = dsk_img_read;
108 img->dsk.write = dsk_img_write;
109
110 img->start = ofs;
111
112 img->fp = fp;
113
114 return (&img->dsk);
115}
116
117disk_t *dsk_img_open_fp (FILE *fp, uint64_t ofs, int ro)
118{
119 uint64_t cnt;
120 disk_t *dsk;
121
122 if (dsk_get_filesize (fp, &cnt)) {
123 return (NULL);
124 }
125
126 if (cnt <= ofs) {
127 return (NULL);
128 }
129
130 cnt = (cnt - ofs) / 512;
131
132 if (cnt == 0) {
133 return (NULL);
134 }
135
136 dsk = dsk_img_open_size (fp, cnt, ofs, ro);
137
138 if (dsk == NULL) {
139 return (NULL);
140 }
141
142 dsk_guess_geometry (dsk);
143
144 return (dsk);
145}
146
147disk_t *dsk_img_open (const char *fname, uint64_t ofs, int ro)
148{
149 disk_t *dsk;
150 FILE *fp;
151
152 if (ro) {
153 fp = fopen (fname, "rb");
154 }
155 else {
156 fp = fopen (fname, "r+b");
157
158 if (fp == NULL) {
159 fp = fopen (fname, "rb");
160 ro = 1;
161 }
162 }
163
164 if (fp == NULL) {
165 return (NULL);
166 }
167
168 dsk = dsk_img_open_fp (fp, ofs, ro);
169
170 if (dsk == NULL) {
171 fclose (fp);
172 return (NULL);
173 }
174
175 dsk_set_fname (dsk, fname);
176
177 return (dsk);
178}
179
180void dsk_img_set_offset (disk_t *dsk, uint64_t ofs)
181{
182 disk_img_t *img;
183
184 img = dsk->ext;
185
186 img->start = ofs;
187}
188
189int dsk_img_create_fp (FILE *fp, uint32_t n, uint64_t ofs)
190{
191 uint64_t cnt;
192 unsigned char buf;
193
194 cnt = 512 * (uint64_t) n;
195
196 if (cnt == 0) {
197 return (1);
198 }
199
200 buf = 0;
201
202 if (dsk_set_filesize (fp, ofs + cnt)) {
203 if (dsk_write (fp, &buf, ofs + cnt - 1, 1)) {
204 return (1);
205 }
206 }
207
208 return (0);
209}
210
211int dsk_img_create (const char *fname, uint32_t n, uint64_t ofs)
212{
213 int r;
214 FILE *fp;
215
216 fp = fopen (fname, "wb");
217
218 if (fp == NULL) {
219 return (1);
220 }
221
222 r = dsk_img_create_fp (fp, n, ofs);
223
224 fclose (fp);
225
226 return (r);
227}