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