Translated using Weblate (Chinese (Simplified))
[cygwin-setup.git] / compress_bz.cc
blobd801de1e6bfc16542da262e6daad69f2db1a46bf
1 /*
2 * Copyright (c) 2001, Robert Collins.
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.
9 * A copy of the GNU General Public License can be found at
10 * http://www.gnu.org/
12 * Written by Robert Collins <rbtcollins@hotmail.com>
16 /* Archive IO operations for bz2 files. Derived from the fd convenience
17 functions in the libbz2 package. */
19 #include "compress_bz.h"
21 #include <stdexcept>
23 #include <errno.h>
24 #include <string.h>
26 compress_bz::compress_bz (io_stream * parent) : peeklen (0), position (0)
28 /* read only via this constructor */
29 original = 0;
30 lasterr = 0;
31 if (!parent || parent->error ())
33 lasterr = EBADF;
34 return;
36 original = parent;
37 owns_original = true;
38 init_state();
41 void
42 compress_bz::init_state(void)
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)
53 lasterr = ret;
54 return;
56 strm.avail_in = 0;
57 strm.next_in = 0;
58 initialisedOk = 1;
61 ssize_t
62 compress_bz::read (void *buffer, size_t len)
64 if (!initialisedOk || writing)
66 lasterr = EBADF;
67 return -1;
69 if (endReached)
70 return 0;
71 if (len == 0)
72 return 0;
74 if (peeklen)
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;
87 strm.avail_out = len;
88 strm.next_out = (char *) buffer;
89 int rlen = 1;
90 while (1)
92 int ret = BZ2_bzDecompress (&strm);
94 if (strm.avail_in == 0 && rlen > 0)
96 rlen = original->read (buf, 4096);
97 if (rlen < 0)
99 lasterr = original->error ();
100 return -1;
102 strm.avail_in = rlen;
103 strm.next_in = buf;
106 if (ret != BZ_OK && ret != BZ_STREAM_END)
108 lasterr = ret;
109 return -1;
111 if (ret == BZ_OK && rlen == 0 && strm.avail_out)
113 /* unexpected end of file */
114 lasterr = EIO;
115 return -1;
117 if (ret == BZ_STREAM_END)
119 /* Are we also at EOF? */
120 if (rlen == 0)
122 endReached = 1;
124 else
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 */
134 position += len - strm.avail_out;
135 return len - strm.avail_out;
137 if (strm.avail_out == 0)
139 position += len;
140 return len;
144 /* not reached */
145 return 0;
148 ssize_t compress_bz::write (const void *buffer, size_t len)
150 throw new std::logic_error ("compress_bz::write is not implemented");
153 ssize_t compress_bz::peek (void *buffer, size_t len)
155 if (writing)
157 lasterr = EBADF;
158 return -1;
161 /* can only peek 512 bytes */
162 if (len > 512)
164 lasterr = ENOMEM;
165 return -1;
168 if (len > peeklen)
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;
178 /* we may have read less than requested. */
179 memcpy (buffer, peekbuf, peeklen);
180 return peeklen;
182 else
184 memcpy (buffer, peekbuf, len);
185 return len;
187 return 0;
190 off_t
191 compress_bz::tell ()
193 if (writing)
194 throw new std::logic_error ("compress_bz::tell is not implemented "
195 "in writing mode");
196 return position;
199 off_t
200 compress_bz::seek (off_t where, io_stream_seek_t whence)
202 if ((whence == IO_SEEK_SET) && (where == 0))
204 off_t result = original->seek(where, whence);
205 init_state();
206 return result;
209 throw new std::logic_error ("compress_bz::seek is not implemented");
213 compress_bz::error ()
215 return lasterr;
219 compress_bz::set_mtime (time_t time)
221 if (original)
222 return original->set_mtime (time);
223 return 1;
226 time_t
227 compress_bz::get_mtime ()
229 if (original)
230 return original->get_mtime ();
231 return 0;
234 mode_t
235 compress_bz::get_mode ()
237 if (original)
238 return original->get_mode ();
239 return 0;
242 void
243 compress_bz::release_original ()
245 owns_original = false;
248 compress_bz::~compress_bz ()
250 if (initialisedOk)
251 BZ2_bzDecompressEnd (&strm);
252 if (original && owns_original)
253 delete original;