Initial commit.
[amiga/xmodule.git] / Compress.c
1 /*
2 **      Compress.c
3 **
4 **      Copyright (C) 1994,96,97 Bernardo Innocenti
5 **
6 **      Compression/Decompression handling functions.
7 */
8
9 #include <exec/memory.h>
10 #include <utility/hooks.h>
11 #include <xpk/xpk.h>
12
13 #include <proto/exec.h>
14 #include <proto/dos.h>
15 #include <proto/powerpacker.h>
16 #include <proto/xpkmaster.h>
17 #include <proto/xmodule.h>
18
19 #include "XModulePriv.h"
20 #include "Gui.h"
21
22
23 #define CTYPE_LHA               1
24 #define CTYPE_XPK               2
25 #define CTYPE_POWERPACKER       3
26
27
28 /* static struct Library *PPBase = NULL; */
29 static struct Library *XpkBase = NULL;
30
31
32 XDEF UBYTE LhACommand[64] = "LhA >NIL: e -x0 -q \"%s\"";
33 XDEF UBYTE TmpDir[PATHNAME_MAX] = "T:XModuleTmp";
34 XDEF UBYTE LhAFilter[64] = "~(#?readme#?|#?txt#?|#?display#?|#?fileid#?)";
35
36
37
38 static LONG HOOKCALL XPKProgressFunc (REG(a0,struct Hook *hook), REG(a1,struct XpkProgress *pr))
39 {
40         return (DisplayProgress (pr->xp_UCur, pr->xp_ULen));
41 }
42
43
44
45 static struct Hook XPKProgressHook =
46 {
47         { NULL, NULL },
48         XPKProgressFunc,
49         NULL,
50         0
51 };
52
53
54
55 GLOBALCALL BPTR DecompressFile (CONST_STRPTR name, UWORD type)
56
57 /* This function will try to decompress the given file and store
58  * it in TmpDir.  If TmpDir does not exist, it will be created.
59  * The decompressed file is then locked and returned.
60  * A return value of NULL means failure.  Call DecompressFileDone()
61  * when you are done with the decompressed file.
62  */
63 {
64         struct AnchorPath *ap;
65         BPTR ret = 0;
66         BPTR dir, olddir;
67         LONG err = 0;
68         UBYTE FullName[PATHNAME_MAX];
69
70
71         OpenProgressWindow();
72
73         DisplayAction (MSG_DECRUNCHING);
74
75         /* Find the full path name of the given file */
76         {
77                 BPTR lock;
78
79                 if (lock = Lock (name, ACCESS_READ))
80                 {
81                         if (!NameFromLock (lock, FullName, PATHNAME_MAX))
82                                 err = IoErr();
83                         UnLock (lock);
84                 }
85                 else err = IoErr();
86         }
87
88         if (!err)
89         {
90                 /* Try to lock or create TmpDir */
91
92                 if (!(dir = Lock (TmpDir, ACCESS_READ)))
93                 {
94                         if (dir = CreateDir (TmpDir))
95                                 if (!(ChangeMode (CHANGE_LOCK, dir, ACCESS_READ)))
96                                 {
97                                         UnLock (dir);
98                                         dir = NULL;
99                                 }
100                 }
101
102                 if (dir)
103                 {
104                         olddir = CurrentDir (dir);
105
106                         switch (type)
107                         {
108                                 case CTYPE_LHA:
109                                 {
110                                         UBYTE buf[64+PATHNAME_MAX];
111
112                                         SPrintf (buf, LhACommand, FullName);
113                                         if (!SystemTagList (buf, NULL))
114                                         {
115                                                 if (ap = AllocMem (sizeof (struct AnchorPath) + PATHNAME_MAX, MEMF_CLEAR))
116                                                 {
117                                                         ap->ap_Strlen = PATHNAME_MAX;
118
119                                                         if (!(err = MatchFirst (LhAFilter, ap)))
120                                                         {
121                                                                 if (!(ret = Lock (ap->ap_Buf, ACCESS_READ)))
122                                                                         err = IoErr();
123                                                         }
124
125                                                         MatchEnd (ap);
126                                                         FreeMem (ap, sizeof (struct AnchorPath) + PATHNAME_MAX);
127                                                 }
128                                                 else err = ERROR_NO_FREE_STORE; /* Fail AllocMem() */
129
130                                         }
131                                         else err = IoErr(); /* Fail SystemTagList() */
132
133                                         break;
134                                 }
135
136                                 case CTYPE_XPK:
137                                 {
138                                         UBYTE dest[PATHNAME_MAX];
139                                         UBYTE errstring[XPKERRMSGSIZE];
140
141                                         if (!(XpkBase = OpenLibrary ("xpkmaster.library", 2L)))
142                                         {
143                                                 CantOpenLib ("xpkmaster.library", 2L);
144                                                 CloseProgressWindow();
145                                                 return 0;
146                                         }
147
148                                         strcpy (dest, TmpDir);
149                                         if (AddPart (dest, "XPKTmp", PATHNAME_MAX))
150                                         {
151                                                 if (XpkUnpackTags (
152                                                         XPK_InName,             FullName,
153                                                         XPK_OutName,    dest,
154                                                         XPK_GetError,   errstring,
155                                                         XPK_ChunkHook,  &XPKProgressHook,
156                                                         // XPK_TaskPri, ThisTask->pr_Task.tc_Node.ln_Pri-1,
157                                                         TAG_DONE))
158                                                 {
159                                                         xmDisplayMessage (XMDMF_ERROR | XMDMF_USECATALOG,
160                                                                 (APTR)MSG_ERROR_DECOMPRESSING, FilePart (FullName),
161                                                                 errstring);
162                                                 }
163                                                 else ret = Lock (dest, ACCESS_READ);
164                                         }
165
166                                         CloseLibrary (XpkBase); XpkBase = NULL;
167                                         break;
168                                 }
169
170 /*                              case CTYPE_POWERPACKER:
171
172                                         if (!(PPBase = OpenLibrary ("powerpacker.library", 0L)))
173                                         {
174                                                 CantOpenLib ("powerpacker.library", 0L);
175                                                 CloseProgressWindow();
176                                                 return 0;
177                                         }
178
179                                         xmDisplayMessageA (XMDMF_INFORMATION,
180                                                 "PowerPacker compressed files are not supported yet.", NULL);
181
182                                         CloseLibrary (PPBase); PPBase = NULL;
183 */
184                                 default:
185                                         break;
186                         }
187
188                         CurrentDir (olddir);
189                         UnLock (dir);
190                 }
191                 else err = IoErr(); /* Fail CreateDir() */
192         }
193
194         /* Report error */
195
196         if (err)
197         {
198                 if (err == ERROR_NO_MORE_ENTRIES)
199                         xmDisplayMessage (XMDMF_ERROR | XMDMF_USECATALOG,
200                                 (APTR)MSG_NOTHING_IN_ARC, name);
201                 else
202                         xmDisplayMessageA (XMDMF_DOSFAULT | XMDMF_USECATALOG,
203                                 (APTR)MSG_CANT_LOAD_COMPRESSED, NULL);
204         }
205
206         if (!ret) DecompressFileDone();
207
208         CloseProgressWindow();
209
210         return ret;
211 }
212
213
214
215 GLOBALCALL void DecompressFileDone (void)
216
217 /* This call releases all resources got by DecompressFile(). */
218 {
219         BPTR dir, olddir;
220         struct FileInfoBlock *fib;
221
222         if (dir = Lock (TmpDir, ACCESS_READ))
223         {
224                 olddir = CurrentDir (dir);
225
226                 if (fib = AllocDosObject (DOS_FIB, NULL))
227                 {
228                         if (Examine (dir, fib))
229                         {
230                                 /* Delete all files in the temp directory */
231                                 while (ExNext (dir, fib))
232                                         DeleteFile (fib->fib_FileName);
233                         }
234
235                         FreeDosObject (DOS_FIB, fib);
236                 }
237
238                 CurrentDir (olddir);
239                 UnLock (dir);
240         }
241
242         DeleteFile (TmpDir);
243 }
244
245
246
247 GLOBALCALL LONG CruncherType (BPTR file)
248 {
249         union
250         {
251                 LONG fileid;
252                 struct
253                 {
254                         UWORD dummy;
255                         ULONG prefix;
256                 } lha;
257         } id;
258
259         if (Read (file, &id, sizeof (id)) != sizeof (id))
260                 return 0;
261
262         if ((id.lha.prefix >> 8) == '-lh')
263                 return CTYPE_LHA;
264
265         if (id.fileid == 'XPKF' || id.fileid == 'PP20' || id.fileid == 'PX20')
266                 return CTYPE_XPK;
267
268         return 0;
269 }