1 /*
2     TiMidity++ -- MIDI to WAVE converter and player
3     Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp>
4     Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>
5 
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20 
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif /* HAVE_CONFIG_H */
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include "timidity.h"
27 #include "url.h"
28 #include "mblock.h"
29 #include "zip.h"
30 
31 typedef struct _URL_inflate
32 {
33     char common[sizeof(struct _URL)];
34     InflateHandler decoder;
35     URL instream;
36     long compsize;
37     long pos;
38     int autoclose;
39 } URL_inflate;
40 
41 static long url_inflate_read_func(char *buf, long size, void *v);
42 static long url_inflate_read(URL url, void *buff, long n);
43 static long url_inflate_tell(URL url);
44 static void url_inflate_close(URL url);
45 
url_inflate_open(URL instream,long compsize,int autoclose)46 URL url_inflate_open(URL instream, long compsize, int autoclose)
47 {
48     URL_inflate *url;
49 
50     url = (URL_inflate *)alloc_url(sizeof(URL_inflate));
51     if(url == NULL)
52     {
53 	if(autoclose)
54 	    url_close(instream);
55 	url_errno = errno;
56 	return NULL;
57     }
58 
59     /* common members */
60     URLm(url, type)      = URL_inflate_t;
61     URLm(url, url_read)  = url_inflate_read;
62     URLm(url, url_gets)  = NULL;
63     URLm(url, url_fgetc) = NULL;
64     URLm(url, url_seek)  = NULL;
65     URLm(url, url_tell)  = url_inflate_tell;
66     URLm(url, url_close) = url_inflate_close;
67 
68     /* private members */
69     url->decoder = NULL;
70     url->instream = instream;
71     url->pos = 0;
72     url->compsize = compsize;
73     url->autoclose = autoclose;
74 
75     errno = 0;
76     url->decoder = open_inflate_handler(url_inflate_read_func, url);
77     if(url->decoder == NULL)
78     {
79 	if(autoclose)
80 	    url_close(instream);
81 	url_inflate_close((URL)url);
82 	url_errno = errno;
83 	return NULL;
84     }
85 
86     return (URL)url;
87 }
88 
url_inflate_read_func(char * buf,long size,void * v)89 static long url_inflate_read_func(char *buf, long size, void *v)
90 {
91     URL_inflate *urlp = (URL_inflate *)v;
92     long n;
93 
94     if(urlp->compsize == -1) /* size if unknown */
95 	return url_read(urlp->instream, buf, size);
96 
97     if(urlp->compsize == 0)
98 	return 0;
99     n = size;
100     if(n > urlp->compsize)
101 	n = urlp->compsize;
102     n = url_read(urlp->instream, buf, n);
103     if(n == -1)
104 	return -1;
105     urlp->compsize -= n;
106     return n;
107 }
108 
url_inflate_read(URL url,void * buff,long n)109 static long url_inflate_read(URL url, void *buff, long n)
110 {
111     URL_inflate *urlp = (URL_inflate *)url;
112 
113     n = zip_inflate(urlp->decoder, (char *)buff, n);
114     if(n <= 0)
115 	return n;
116     urlp->pos += n;
117     return n;
118 }
119 
url_inflate_tell(URL url)120 static long url_inflate_tell(URL url)
121 {
122     return ((URL_inflate *)url)->pos;
123 }
124 
url_inflate_close(URL url)125 static void url_inflate_close(URL url)
126 {
127     int save_errno = errno;
128     URL_inflate *urlp = (URL_inflate *)url;
129     if(urlp->decoder)
130 	close_inflate_handler(urlp->decoder);
131     if(urlp->autoclose)
132 	url_close(urlp->instream);
133     free(url);
134     errno = save_errno;
135 }
136