1  /*
2   * UAE - The Un*x Amiga Emulator
3   *
4   * routines to handle compressed file automatically
5   *
6   * (c) 1996 Samuel Devulder, Tim Gunn
7   */
8 
9 #include "sysconfig.h"
10 #include "sysdeps.h"
11 
12 #include "options.h"
13 #include "zfile.h"
14 
15 #ifdef AMIGA
16 extern char *amiga_dev_path;   /* dev: */
17 extern char *ixemul_dev_path;  /* /dev/ */
18 extern int readdevice (const char *, char *);
19 #endif
20 
21 struct zfile
22 {
23     struct zfile *next;
24     struct zfile **pprev;
25     FILE *f;
26     char name[L_tmpnam];
27 };
28 
29 static struct zfile *zlist = 0;
30 
31 /*
32  * called on exit ()
33  */
zfile_exit(void)34 void zfile_exit (void)
35 {
36     struct zfile *l;
37 
38     while ((l = zlist)) {
39 	zlist = l->next;
40 	fclose (l->f);
41 	unlink (l->name); /* sam: in case unlink () after fopen () fails */
42 	free (l);
43     }
44 }
45 
46 /*
47  * fclose () but for a compressed file
48  */
zfile_fclose(struct zfile * f)49 int zfile_fclose (struct zfile *f)
50 {
51     int ret;
52 
53     if (f->next)
54 	f->next->pprev = f->pprev;
55     (*f->pprev) = f->next;
56 
57     ret = fclose (f->f);
58     unlink (f->name);
59 
60     free (f);
61 
62     return ret;
63 }
64 
zfile_fseek(struct zfile * z,long offset,int mode)65 int zfile_fseek (struct zfile *z, long offset, int mode)
66 {
67     return fseek (z->f, offset, mode);
68 }
69 
zfile_ftell(struct zfile * z)70 long zfile_ftell (struct zfile *z)
71 {
72     return ftell (z->f);
73 }
74 
zfile_fread(void * b,size_t l1,size_t l2,struct zfile * z)75 size_t zfile_fread (void *b, size_t l1, size_t l2, struct zfile *z)
76 {
77     return fread (b, l1, l2, z->f);
78 }
79 
zfile_fwrite(void * b,size_t l1,size_t l2,struct zfile * z)80 size_t zfile_fwrite (void *b, size_t l1, size_t l2, struct zfile *z)
81 {
82     return fwrite (b, l1, l2, z->f);
83 }
84 
85 /*
86  * gzip decompression
87  */
gunzip(const char * decompress,const char * src,const char * dst)88 static int gunzip (const char *decompress, const char *src, const char *dst)
89 {
90     char cmd[1024];
91     char *ext = strrchr (src, '.');
92     if (!dst)
93 	return 1;
94 #if defined (AMIGA)
95     sprintf (cmd, "%s -c -d -S %s \"%s\" > \"%s\"", decompress, ext, src, dst);
96 #else
97     sprintf (cmd, "%s -c -d \"%s\" > \"%s\"", decompress, src, dst);
98 #endif
99     return !system (cmd);
100 }
101 
102 /*
103  * bzip/bzip2 decompression
104  */
bunzip(const char * decompress,const char * src,const char * dst)105 static int bunzip (const char *decompress, const char *src, const char *dst)
106 {
107     char cmd[1024];
108     if (!dst)
109 	return 1;
110     sprintf (cmd, "%s -c -d \"%s\" > \"%s\"", decompress, src, dst);
111     return !system (cmd);
112 }
113 
114 /*
115  * lha decompression
116  */
lha(const char * src,const char * dst)117 static int lha (const char *src, const char *dst)
118 {
119     char cmd[1024];
120     if (!dst)
121 	return 1;
122 #if defined (AMIGA)
123     sprintf (cmd, "lha -q -N p %s >%s", src, dst);
124 #else
125     sprintf (cmd, "lha pq %s >%s", src, dst);
126 #endif
127     return !system (cmd);
128 }
129 
130 /*
131  * (pk)unzip decompression
132  */
unzip(const char * src,const char * dst)133 static int unzip (const char *src, const char *dst)
134 {
135     char cmd[1024];
136     if (!dst)
137 	return 1;
138 #if defined AMIGA || defined __unix
139     sprintf (cmd, "unzip -p %s '*.adf' >%s", src, dst);
140     return !system (cmd);
141 #endif
142 }
143 
144 /*
145  * decompresses the file (or check if dest is null)
146  */
uncompress(const char * name,char * dest)147 static int uncompress (const char *name, char *dest)
148 {
149     char *ext = strrchr (name, '.');
150     char nam[1024];
151 
152     if (ext != NULL && access (name, 0) >= 0) {
153 	ext++;
154 	if (strcasecmp (ext, "z") == 0
155 	    || strcasecmp (ext, "gz") == 0
156 	    || strcasecmp (ext, "adz") == 0
157 	    || strcasecmp (ext, "roz") == 0)
158 	    return gunzip ("gzip", name, dest);
159 	if (strcasecmp (ext, "bz") == 0)
160 	    return bunzip ("bzip", name, dest);
161 	if (strcasecmp (ext, "bz2") == 0)
162 	    return bunzip ("bzip2", name, dest);
163 
164 #ifndef __DOS__
165 	if (strcasecmp (ext, "lha") == 0
166 	    || strcasecmp (ext, "lzh") == 0)
167 	    return lha (name, dest);
168 	if (strcasecmp (ext, "zip") == 0)
169 	     return unzip (name, dest);
170 #endif
171     }
172 
173     if (access (strcat (strcpy (nam, name), ".z"), 0) >= 0
174 	|| access (strcat (strcpy (nam, name), ".Z"), 0) >= 0
175 	|| access (strcat (strcpy (nam, name), ".gz"), 0) >= 0
176 	|| access (strcat (strcpy (nam, name), ".GZ"), 0) >= 0
177 	|| access (strcat (strcpy (nam, name), ".adz"), 0) >= 0
178 	|| access (strcat (strcpy (nam, name), ".roz"), 0) >= 0)
179 	return gunzip ("gzip", nam, dest);
180 
181     if (access (strcat (strcpy (nam, name), ".bz"), 0) >= 0
182 	|| access (strcat (strcpy (nam, name), ".BZ"), 0) >= 0)
183 	return bunzip ("bzip", nam, dest);
184 
185     if (access (strcat (strcpy (nam, name), ".bz2"), 0) >= 0
186 	|| access (strcat (strcpy (nam, name), ".BZ2"), 0) >= 0)
187 	return bunzip ("bzip2", nam, dest);
188 
189 #ifndef __DOS__
190     if (access (strcat (strcpy (nam, name), ".lha"), 0) >= 0
191 	|| access (strcat (strcpy (nam, name), ".LHA"), 0) >= 0
192 	|| access (strcat (strcpy (nam, name), ".lzh"), 0) >= 0
193 	|| access (strcat (strcpy (nam, name), ".LZH"), 0) >= 0)
194 	return lha (nam, dest);
195 
196     if (access (strcat (strcpy (nam, name),".zip"),0) >= 0
197 	|| access (strcat (strcpy (nam, name),".ZIP"),0) >= 0)
198        return unzip (nam, dest);
199 #endif
200 
201 #if defined (AMIGA)
202     /* sam: must be before real access to work */
203     if (!strnicmp (name, ixemul_dev_path, strlen (ixemul_dev_path)))
204 	return readdevice (name + strlen (ixemul_dev_path), dest);
205     if (!strnicmp (name, amiga_dev_path, strlen (amiga_dev_path)))
206 	return readdevice (name + strlen (amiga_dev_path), dest);
207 #endif
208 
209     return 0;
210 }
211 
212 /*
213  * fopen () for a compressed file
214  */
zfile_open(const char * name,const char * mode)215 struct zfile *zfile_open (const char *name, const char *mode)
216 {
217     struct zfile *l = malloc (sizeof *l);
218     int fd = 0;
219 
220     if (! l)
221 	return NULL;
222 
223     strcpy (l->name, "");
224 
225     if (! uncompress (name, NULL))
226 	l->f = fopen (name, mode);
227     else {
228 	tmpnam (l->name);
229 	fd = creat (l->name, S_IRUSR | S_IWUSR);
230 	if (fd < 0)
231 	    return NULL;
232 
233 	if (! uncompress (name, l->name)) {
234 	    close (fd);
235 	    unlink (l->name);
236 	    free (l);
237 	    return NULL;
238 	}
239 	l->f = fopen (l->name, mode);
240 	close (fd);
241 
242     }
243     if (l->f == NULL) {
244 	if (strlen (l->name) > 0)
245 	    unlink (l->name);
246 	free (l);
247 	return NULL;
248     }
249 
250     l->pprev = &zlist;
251     l->next = zlist;
252     if (l->next)
253 	l->next->pprev = &l->next;
254     zlist = l;
255 
256     return l;
257 }
258