Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / devs / diskimage / plugins / xad.c
blob40c9dd10e858260ad2412a62c30438b246dfc678
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 <gadgets/fuelgauge.h>
30 #include <libraries/xadmaster.h>
31 #include <proto/exec.h>
32 #include <proto/dos.h>
33 #include <proto/xadmaster.h>
34 #include <string.h>
35 #include "device_locale.h"
36 #include <SDI_compiler.h>
37 #include "rev/diskimage.device_rev.h"
39 PLUGIN_VERSTAG("XAD")
41 extern struct DiskImagePlugin xad_plugin;
43 PLUGIN_TABLE(&xad_plugin)
45 BOOL XAD_Init (struct DiskImagePlugin *Self, const struct PluginData *data);
46 void XAD_Exit (struct DiskImagePlugin *Self);
47 BOOL XAD_CheckImage (struct DiskImagePlugin *Self, BPTR file, CONST_STRPTR name, QUAD file_size,
48 const UBYTE *test, LONG testsize);
49 APTR XAD_OpenImage (struct DiskImagePlugin *Self, APTR unit, BPTR file, CONST_STRPTR name);
50 static ULONG ProgressHookFunc (REG(a0, struct Hook *hook), REG(a2, void *unused),
51 REG(a1, struct xadProgressInfo *pi));
52 static LONG XADError (LONG error, LONG *error_string);
54 struct DiskImagePlugin xad_plugin = {
55 PLUGIN_NODE(-1, "XAD"),
56 PLUGIN_FLAG_M68K,
58 ZERO,
59 NULL,
60 XAD_Init,
61 XAD_Exit,
62 XAD_CheckImage,
63 XAD_OpenImage,
64 NULL,
65 NULL,
66 NULL,
67 NULL,
68 NULL,
69 NULL,
70 NULL,
71 NULL
74 struct Library *SysBase;
75 struct Library *DOSBase;
76 static struct DIPluginIFace *IPlugin;
77 static struct xadMasterBase *xadMasterBase;
79 BOOL XAD_Init (struct DiskImagePlugin *Self, const struct PluginData *data) {
80 SysBase = data->SysBase;
81 DOSBase = data->DOSBase;
82 IPlugin = data->IPlugin;
83 return TRUE;
86 void XAD_Exit (struct DiskImagePlugin *Self) {
87 if (xadMasterBase) CloseLibrary((struct Library *)xadMasterBase);
90 BOOL XAD_CheckImage (struct DiskImagePlugin *Self, BPTR file, CONST_STRPTR name, QUAD file_size,
91 const UBYTE *test, LONG testsize)
93 struct xadArchiveInfo *xai;
94 BOOL is_xad = FALSE;
96 if (!xadMasterBase) {
97 xadMasterBase = (struct xadMasterBase *)OpenLibrary("xadmaster.library", 0);
98 if (!xadMasterBase) return FALSE;
101 xai = xadAllocObjectA(XADOBJ_ARCHIVEINFO, NULL);
102 if (xai) {
103 if (xadGetInfo(xai, XAD_INFILEHANDLE, file, TAG_END) == XADERR_OK) {
104 if (xai->xai_FileInfo) is_xad = TRUE;
105 xadFreeInfo(xai);
107 xadFreeObjectA(xai, NULL);
108 ChangeFilePosition(file, 0, OFFSET_BEGINNING);
110 return is_xad;
113 static CONST TEXT match_str1[] = "#?.(adf|b5i|bin|cdi|cso|d64|daa|dax|"
114 "dmg|img|iso|mdf|nrg|pdi|raw|sad|toast|uif)";
115 static CONST TEXT match_str2[] = "~(#?(displayme|readme|liesmich)#?|"
116 "#?.(diz|info|doc|dok|txt|text|exe|lst|cue|mds|nfo|pdf))";
118 static CONST CONST_STRPTR match_strs[] = {
119 match_str1, match_str2, NULL
122 APTR XAD_OpenImage (struct DiskImagePlugin *Self, APTR unit, BPTR file,
123 CONST_STRPTR name)
125 LONG done = FALSE;
126 LONG error = NO_ERROR;
127 LONG error_string = NO_ERROR_STRING;
128 IPTR error_args[4] = {0};
129 APTR image = NULL;
130 struct xadArchiveInfo *xai;
131 UBYTE *patbuf;
132 ULONG patbuf_size;
133 struct xadFileInfo *xfi, *chosen = NULL;
134 CONST CONST_STRPTR *match_str;
135 BPTR outfile = ZERO;
136 CONST_STRPTR ext;
137 BPTR tmpdir;
138 CONST_STRPTR tmpname;
140 if (!xadMasterBase) {
141 xadMasterBase = (struct xadMasterBase *)OpenLibrary("xadmaster.library", 0);
142 if (!xadMasterBase) {
143 error = ERROR_OBJECT_NOT_FOUND;
144 error_string = MSG_REQ;
145 error_args[0] = (IPTR)"xadmaster.library";
146 goto error;
150 xai = xadAllocObjectA(XADOBJ_ARCHIVEINFO, NULL);
151 patbuf_size = 2*max(sizeof(match_str1), sizeof(match_str2))+2;
152 patbuf = AllocVec(patbuf_size, MEMF_ANY);
153 if (!xai || !patbuf) {
154 error = ERROR_NO_FREE_STORE;
155 goto error;
158 if (xadGetInfo(xai, XAD_INFILEHANDLE, file, TAG_END) != XADERR_OK) {
159 error = ERROR_OBJECT_WRONG_TYPE;
160 goto error;
163 match_str = match_strs;
164 while (!chosen && *match_str) {
165 ParsePatternNoCase(*match_str++, patbuf, patbuf_size);
166 for (xfi = xai->xai_FileInfo; xfi; xfi = xfi->xfi_Next) {
167 if (MatchPatternNoCase(patbuf, FilePart(xfi->xfi_FileName))) {
168 chosen = xfi;
169 break;
173 FreeVec(patbuf);
174 patbuf = NULL;
175 if (!chosen) {
176 chosen = xai->xai_FileInfo;
177 if (!chosen) {
178 error = ERROR_OBJECT_NOT_FOUND;
179 goto error;
183 ext = strrchr(FilePart(chosen->xfi_FileName), '.');
184 if (ext) ext++;
186 error = IPlugin_CreateTempFile(unit, ext, &tmpdir, &tmpname);
187 if (error != NO_ERROR) goto error;
189 outfile = IPlugin_OpenTempFile(unit, MODE_NEWFILE);
190 if (!outfile) {
191 error = IoErr();
192 goto error;
193 } else {
194 struct Hook progresshook = {0};
195 LONG xad_err;
197 progresshook.h_Entry = ProgressHookFunc;
198 progresshook.h_Data = IPlugin_CreateProgressBar(unit, TRUE);
200 xad_err = xadFileUnArc(xai,
201 XAD_OUTFILEHANDLE, outfile,
202 XAD_OVERWRITE, TRUE,
203 XAD_ENTRYNUMBER, chosen->xfi_EntryNumber,
204 XAD_PROGRESSHOOK, &progresshook,
205 TAG_END);
206 if (xad_err == XADERR_PASSWORD) {
207 CONST_STRPTR passwd;
208 passwd = IPlugin_RequestPassword(unit);
209 if (passwd) {
210 xad_err = xadFileUnArc(xai,
211 XAD_PASSWORD, passwd,
212 XAD_OUTFILEHANDLE, outfile,
213 XAD_OVERWRITE, TRUE,
214 XAD_ENTRYNUMBER, chosen->xfi_EntryNumber,
215 XAD_PROGRESSHOOK, &progresshook,
216 TAG_DONE);
217 FreeVec(passwd);
218 } else {
219 error = ERROR_NO_FREE_STORE;
222 IPlugin_DeleteProgressBar(progresshook.h_Data);
223 Close(outfile);
224 xadFreeObjectA(xai, NULL);
225 xai = NULL;
226 Close(file);
227 file = ZERO;
228 if (error != NO_ERROR) goto error;
230 error = XADError(xad_err, &error_string);
231 if (error != NO_ERROR) goto error;
233 outfile = IPlugin_OpenTempFile(unit, MODE_OLDFILE);
234 if (!outfile) {
235 error = IoErr();
236 goto error;
239 done = TRUE;
240 tmpdir = CurrentDir(tmpdir);
241 image = IPlugin_OpenImage(unit, outfile, tmpname);
242 CurrentDir(tmpdir);
245 error:
246 if (xai) xadFreeObjectA(xai, NULL);
247 FreeVec(patbuf);
248 Close(file);
249 if (!done) {
250 IPlugin_SetDiskImageErrorA(unit, error, error_string, error_args);
252 return image;
255 static ULONG ProgressHookFunc (REG(a0, struct Hook *hook), REG(a2, void *unused),
256 REG(a1, struct xadProgressInfo *pi))
258 APTR pb = hook->h_Data;
259 if (pb) {
260 switch (pi->xpi_Mode) {
261 case XADPMODE_PROGRESS:
262 if (pi->xpi_FileInfo->xfi_Flags & XADFIF_NOUNCRUNCHSIZE) {
263 hook->h_SubEntry = (void *)(pi->xpi_CurrentSize >> 10);
264 IPlugin_SetProgressBarAttrs(pb,
265 FUELGAUGE_Percent, FALSE,
266 FUELGAUGE_Level, 0,
267 GA_Text, "%ld KB",
268 FUELGAUGE_VarArgs, &hook->h_SubEntry,
269 TAG_END);
270 } else {
271 IPlugin_SetProgressBarAttrs(pb,
272 FUELGAUGE_Percent, TRUE,
273 FUELGAUGE_Max, pi->xpi_FileInfo->xfi_Size,
274 FUELGAUGE_Level, pi->xpi_CurrentSize,
275 TAG_END);
277 break;
280 return IPlugin_ProgressBarInput(pb) ? 0 : XADPIF_OK;
283 static LONG XADError (LONG error, LONG *error_string) {
284 switch (error) {
285 case XADERR_OK:
286 return NO_ERROR;
287 case XADERR_INPUT:
288 case XADERR_OUTPUT:
289 return ERROR_BUFFER_OVERFLOW;
290 case XADERR_NOMEMORY:
291 return ERROR_NO_FREE_STORE;
292 case XADERR_BREAK:
293 *error_string = MSG_CANCELED;
294 return ERROR_BREAK;
295 case XADERR_PASSWORD:
296 *error_string = MSG_WRONGPASSWD;
297 return ERROR_REQUIRED_ARG_MISSING;
298 default:
299 *error_string = MSG_XADERR;
300 return ERROR_OBJECT_WRONG_TYPE;