Were did that svn:executable come from?
[AROS.git] / workbench / devs / diskimage / plugins / gi.c
blob662f83176e4aab8a1e82964d5f909dcb910d78b1
1 /* Copyright 2007-2012 Fredrik Wikstrom. All rights reserved.
2 **
3 ** Redistribution and use in source and binary forms, with or without
4 ** modification, are permitted provided that the following conditions
5 ** are met:
6 **
7 ** 1. Redistributions of source code must retain the above copyright
8 ** notice, this list of conditions and the following disclaimer.
9 **
10 ** 2. Redistributions in binary form must reproduce the above copyright
11 ** notice, this list of conditions and the following disclaimer in the
12 ** documentation and/or other materials provided with the distribution.
14 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
15 ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 ** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 ** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 ** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 ** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 ** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 ** POSSIBILITY OF SUCH DAMAGE.
27 #define USED_PLUGIN_API_VERSION 8
28 #include <devices/diskimage.h>
29 #include <proto/exec.h>
30 #include <proto/dos.h>
31 #include <proto/utility.h>
32 #include "device_locale.h"
33 #include <string.h>
34 #include "support.h"
35 #include <SDI_compiler.h>
36 #include "rev/diskimage.device_rev.h"
38 PLUGIN_VERSTAG("GI")
40 extern struct DiskImagePlugin gi_plugin;
42 PLUGIN_TABLE(&gi_plugin)
44 BOOL GI_Init (struct DiskImagePlugin *Self, const struct PluginData *data);
45 BOOL GI_CheckImage (struct DiskImagePlugin *Self, BPTR file, CONST_STRPTR name, QUAD file_size,
46 const UBYTE *test, LONG testsize);
47 APTR GI_OpenImage (struct DiskImagePlugin *Self, APTR unit, BPTR file, CONST_STRPTR name);
48 void GI_CloseImage (struct DiskImagePlugin *Self, APTR image_ptr);
49 LONG GI_Geometry (struct DiskImagePlugin *Self, APTR image_ptr, struct DriveGeometry *dg);
50 LONG GI_Read (struct DiskImagePlugin *Self, APTR image_ptr, struct IOStdReq *io);
52 struct DiskImagePlugin gi_plugin = {
53 PLUGIN_NODE(0, "GI"),
54 PLUGIN_FLAG_M68K,
56 ZERO,
57 NULL,
58 GI_Init,
59 NULL,
60 GI_CheckImage,
61 GI_OpenImage,
62 GI_CloseImage,
63 GI_Geometry,
64 GI_Read,
65 NULL,
66 NULL,
67 NULL,
68 NULL,
69 NULL
72 struct Library *SysBase;
73 struct Library *DOSBase;
74 static struct Library *UtilityBase;
75 static struct DIPluginIFace *IPlugin;
77 BOOL GI_Init (struct DiskImagePlugin *Self, const struct PluginData *data) {
78 SysBase = data->SysBase;
79 DOSBase = data->DOSBase;
80 UtilityBase = data->UtilityBase;
81 IPlugin = data->IPlugin;
82 return TRUE;
85 BOOL GI_CheckImage (struct DiskImagePlugin *Self, BPTR file, CONST_STRPTR name, QUAD file_size,
86 const UBYTE *test, LONG testsize)
88 int len;
89 len = strlen(name)-3;
90 if (len > 0) {
91 name += len;
92 return !Stricmp(name, ".gi");
94 return FALSE;
97 struct FileNode {
98 struct FileNode *next;
99 BPTR file;
100 UQUAD offset;
101 UQUAD size;
104 struct GIImage {
105 struct FileNode *files;
106 ULONG block_size;
107 UQUAD total_bytes;
108 ULONG total_blocks;
111 APTR GI_OpenImage (struct DiskImagePlugin *Self, APTR unit, BPTR file,
112 CONST_STRPTR name)
114 LONG done = FALSE;
115 LONG error = NO_ERROR;
116 LONG error_string = NO_ERROR_STRING;
117 IPTR error_args[4] = {0};
118 struct GIImage *image = NULL;
119 CONST_STRPTR ext;
120 LONG len, i;
121 STRPTR namebuf = NULL, extbuf;
122 CONST_STRPTR fmt = "%ld.gi";
123 struct FileNode *fn;
125 image = AllocVec(sizeof(*image), MEMF_CLEAR);
126 if (!image) {
127 error = ERROR_NO_FREE_STORE;
128 goto error;
131 ext = strrchr(name, '.');
132 len = ext - name;
134 namebuf = AllocVec(len + 8, MEMF_ANY);
135 image->files = fn = AllocVec(sizeof(*fn), MEMF_CLEAR);
136 if (!namebuf || !fn) {
137 error = ERROR_NO_FREE_STORE;
138 Close(file);
139 goto error;
142 CopyMem(name, namebuf, len);
143 extbuf = namebuf + len;
145 i = 1;
146 for (;;) {
147 fn->file = file;
148 fn->offset = image->total_bytes;
149 fn->size = GetFileSize(file);
150 if (fn->size == -1) {
151 error = IoErr();
152 goto error;
154 image->total_bytes += fn->size;
156 SNPrintf(extbuf, 8, fmt, i++);
157 file = Open(namebuf, MODE_OLDFILE);
158 if (!file) {
159 error = IoErr();
160 if (error != ERROR_OBJECT_NOT_FOUND) {
161 goto error;
163 error = NO_ERROR;
164 break;
166 fn->next = AllocVec(sizeof(*fn), MEMF_CLEAR);
167 if (!(fn = fn->next)) {
168 error = ERROR_NO_FREE_STORE;
169 Close(file);
170 goto error;
174 image->block_size = 2048;
175 image->total_blocks = image->total_bytes >> 11;
177 done = TRUE;
179 error:
180 FreeVec(namebuf);
181 if (!done) {
182 if (image) {
183 Plugin_CloseImage(Self, image);
184 image = NULL;
185 } else {
186 Close(file);
188 if (error == NO_ERROR) {
189 error = ERROR_OBJECT_WRONG_TYPE;
190 error_string = MSG_EOF;
192 IPlugin_SetDiskImageErrorA(unit, error, error_string, error_args);
194 return image;
197 void GI_CloseImage (struct DiskImagePlugin *Self, APTR image_ptr) {
198 struct GIImage *image = image_ptr;
199 if (image) {
200 struct FileNode *fn, *next;
201 fn = image->files;
202 while (fn) {
203 next = fn->next;
204 Close(fn->file);
205 FreeVec(fn);
206 fn = next;
208 FreeVec(image);
212 LONG GI_Geometry (struct DiskImagePlugin *Self, APTR image_ptr, struct DriveGeometry *dg) {
213 struct GIImage *image = image_ptr;
214 dg->dg_SectorSize = image->block_size;
215 dg->dg_Heads =
216 dg->dg_TrackSectors =
217 dg->dg_CylSectors = 1;
218 dg->dg_Cylinders =
219 dg->dg_TotalSectors = image->total_blocks;
220 return IOERR_SUCCESS;
223 LONG GI_Read (struct DiskImagePlugin *Self, APTR image_ptr, struct IOStdReq *io) {
224 struct GIImage *image = image_ptr;
225 UBYTE *buffer;
226 UQUAD offset, in_offs;
227 ULONG size, to_read;
228 LONG status;
229 struct FileNode *fn;
231 buffer = io->io_Data;
232 offset = ((UQUAD)io->io_Offset)|((UQUAD)io->io_Actual << 32);
233 size = io->io_Length;
234 io->io_Actual = 0;
236 if (offset >= image->total_bytes) return TDERR_SeekError;
238 fn = image->files;
239 while (fn && fn->offset + fn->size <= offset) fn = fn->next;
240 if (!fn) return TDERR_SeekError;
242 in_offs = offset - fn->offset;
243 if (in_offs && !ChangeFilePosition(fn->file, in_offs, OFFSET_BEGINNING)) {
244 return TDERR_SeekError;
247 while (size) {
248 if (!fn) return IOERR_BADLENGTH;
250 to_read = min(size, fn->size - in_offs);
251 status = Read(fn->file, buffer, to_read);
252 if (status == -1) {
253 return IPlugin_DOS2IOErr(IoErr());
254 } else
255 if (status != to_read) {
256 return IOERR_BADLENGTH;
258 in_offs = 0;
260 buffer += to_read;
261 size -= to_read;
262 io->io_Actual += to_read;
263 fn = fn->next;
265 return IOERR_SUCCESS;