]> cygwin.com Git - cygwin-apps/setup.git/blob - compress_bz.cc
Suggest URLs for updated setup based on build architecture
[cygwin-apps/setup.git] / compress_bz.cc
1 /*
2 * Copyright (c) 2001, Robert Collins.
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 * A copy of the GNU General Public License can be found at
10 * http://www.gnu.org/
11 *
12 * Written by Robert Collins <rbtcollins@hotmail.com>
13 *
14 */
15
16 /* Archive IO operations for bz2 files. Derived from the fd convenience
17 functions in the libbz2 package. */
18
19 #include "compress_bz.h"
20
21 #include <stdexcept>
22
23 #include <errno.h>
24 #include <string.h>
25
26 compress_bz::compress_bz (io_stream * parent) : peeklen (0), position (0)
27 {
28 /* read only via this constructor */
29 original = 0;
30 lasterr = 0;
31 if (!parent || parent->error ())
32 {
33 lasterr = EBADF;
34 return;
35 }
36 original = parent;
37 owns_original = true;
38 init_state();
39 }
40
41 void
42 compress_bz::init_state(void)
43 {
44 initialisedOk = 0;
45 endReached = 0;
46 writing = 0;
47 strm.bzalloc = 0;
48 strm.bzfree = 0;
49 strm.opaque = 0;
50 int ret = BZ2_bzDecompressInit (&(strm), 0, 0);
51 if (ret)
52 {
53 lasterr = ret;
54 return;
55 }
56 strm.avail_in = 0;
57 strm.next_in = 0;
58 initialisedOk = 1;
59 }
60
61 ssize_t
62 compress_bz::read (void *buffer, size_t len)
63 {
64 if (!initialisedOk || writing)
65 {
66 lasterr = EBADF;
67 return -1;
68 }
69 if (endReached)
70 return 0;
71 if (len == 0)
72 return 0;
73
74 if (peeklen)
75 {
76 ssize_t tmplen = std::min (peeklen, len);
77 peeklen -= tmplen;
78 memcpy (buffer, peekbuf, tmplen);
79 memmove (peekbuf, peekbuf + tmplen, tmplen);
80 ssize_t tmpread = read (&((char *) buffer)[tmplen], len - tmplen);
81 if (tmpread >= 0)
82 return tmpread + tmplen;
83 else
84 return tmpread;
85 }
86
87 strm.avail_out = len;
88 strm.next_out = (char *) buffer;
89 int rlen = 1;
90 while (1)
91 {
92 int ret = BZ2_bzDecompress (&strm);
93
94 if (strm.avail_in == 0 && rlen > 0)
95 {
96 rlen = original->read (buf, 4096);
97 if (rlen < 0)
98 {
99 lasterr = original->error ();
100 return -1;
101 }
102 strm.avail_in = rlen;
103 strm.next_in = buf;
104 }
105
106 if (ret != BZ_OK && ret != BZ_STREAM_END)
107 {
108 lasterr = ret;
109 return -1;
110 }
111 if (ret == BZ_OK && rlen == 0 && strm.avail_out)
112 {
113 /* unexpected end of file */
114 lasterr = EIO;
115 return -1;
116 }
117 if (ret == BZ_STREAM_END)
118 {
119 /* Are we also at EOF? */
120 if (rlen == 0)
121 {
122 endReached = 1;
123 }
124 else
125 {
126 /* BZ_SSTREAM_END but not at EOF means the file contains
127 another stream */
128 BZ2_bzDecompressEnd (&strm);
129 BZ2_bzDecompressInit (&(strm), 0, 0);
130 /* This doesn't reinitialize strm, so strm.next_in still
131 points at strm.avail_in bytes left to decompress in buf */
132 }
133
134 position += len - strm.avail_out;
135 return len - strm.avail_out;
136 }
137 if (strm.avail_out == 0)
138 {
139 position += len;
140 return len;
141 }
142 }
143
144 /* not reached */
145 return 0;
146 }
147
148 ssize_t compress_bz::write (const void *buffer, size_t len)
149 {
150 throw new std::logic_error ("compress_bz::write is not implemented");
151 }
152
153 ssize_t compress_bz::peek (void *buffer, size_t len)
154 {
155 if (writing)
156 {
157 lasterr = EBADF;
158 return -1;
159 }
160
161 /* can only peek 512 bytes */
162 if (len > 512)
163 {
164 lasterr = ENOMEM;
165 return -1;
166 }
167
168 if (len > peeklen)
169 {
170 size_t want = len - peeklen;
171 ssize_t got = read (&peekbuf[peeklen], want);
172 if (got >= 0)
173 peeklen += got;
174 else
175 /* error */
176 return got;
177
178 /* we may have read less than requested. */
179 memcpy (buffer, peekbuf, peeklen);
180 return peeklen;
181 }
182 else
183 {
184 memcpy (buffer, peekbuf, len);
185 return len;
186 }
187 return 0;
188 }
189
190 off_t
191 compress_bz::tell ()
192 {
193 if (writing)
194 throw new std::logic_error ("compress_bz::tell is not implemented "
195 "in writing mode");
196 return position;
197 }
198
199 off_t
200 compress_bz::seek (off_t where, io_stream_seek_t whence)
201 {
202 if ((whence == IO_SEEK_SET) && (where == 0))
203 {
204 off_t result = original->seek(where, whence);
205 init_state();
206 return result;
207 }
208
209 throw new std::logic_error ("compress_bz::seek is not implemented");
210 }
211
212 int
213 compress_bz::error ()
214 {
215 return lasterr;
216 }
217
218 int
219 compress_bz::set_mtime (time_t time)
220 {
221 if (original)
222 return original->set_mtime (time);
223 return 1;
224 }
225
226 time_t
227 compress_bz::get_mtime ()
228 {
229 if (original)
230 return original->get_mtime ();
231 return 0;
232 }
233
234 mode_t
235 compress_bz::get_mode ()
236 {
237 if (original)
238 return original->get_mode ();
239 return 0;
240 }
241
242 void
243 compress_bz::release_original ()
244 {
245 owns_original = false;
246 }
247
248 compress_bz::~compress_bz ()
249 {
250 if (initialisedOk)
251 BZ2_bzDecompressEnd (&strm);
252 if (original && owns_original)
253 delete original;
254 }
This page took 0.049224 seconds and 6 git commands to generate.