00001
00002
00003
00004
00005
00006 #include "gzguts.h"
00007
00008
00009 local int gz_init OF((gz_statep));
00010 local int gz_comp OF((gz_statep, int));
00011 local int gz_zero OF((gz_statep, z_off64_t));
00012
00013
00014
00015 local int gz_init(state)
00016 gz_statep state;
00017 {
00018 int ret;
00019 z_streamp strm = &(state->strm);
00020
00021
00022 state->in = malloc(state->want);
00023 state->out = malloc(state->want);
00024 if (state->in == NULL || state->out == NULL) {
00025 if (state->out != NULL)
00026 free(state->out);
00027 if (state->in != NULL)
00028 free(state->in);
00029 gz_error(state, Z_MEM_ERROR, "out of memory");
00030 return -1;
00031 }
00032
00033
00034 strm->zalloc = Z_NULL;
00035 strm->zfree = Z_NULL;
00036 strm->opaque = Z_NULL;
00037 ret = deflateInit2(strm, state->level, Z_DEFLATED,
00038 15 + 16, 8, state->strategy);
00039 if (ret != Z_OK) {
00040 free(state->in);
00041 gz_error(state, Z_MEM_ERROR, "out of memory");
00042 return -1;
00043 }
00044
00045
00046 state->size = state->want;
00047
00048
00049 strm->avail_out = state->size;
00050 strm->next_out = state->out;
00051 state->next = strm->next_out;
00052 return 0;
00053 }
00054
00055
00056
00057
00058
00059 local int gz_comp(state, flush)
00060 gz_statep state;
00061 int flush;
00062 {
00063 int ret, got;
00064 unsigned have;
00065 z_streamp strm = &(state->strm);
00066
00067
00068 if (state->size == 0 && gz_init(state) == -1)
00069 return -1;
00070
00071
00072 ret = Z_OK;
00073 do {
00074
00075
00076 if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
00077 (flush != Z_FINISH || ret == Z_STREAM_END))) {
00078 have = (unsigned)(strm->next_out - state->next);
00079 if (have && ((got = write(state->fd, state->next, have)) < 0 ||
00080 (unsigned)got != have)) {
00081 gz_error(state, Z_ERRNO, zstrerror());
00082 return -1;
00083 }
00084 if (strm->avail_out == 0) {
00085 strm->avail_out = state->size;
00086 strm->next_out = state->out;
00087 }
00088 state->next = strm->next_out;
00089 }
00090
00091
00092 have = strm->avail_out;
00093 ret = deflate(strm, flush);
00094 if (ret == Z_STREAM_ERROR) {
00095 gz_error(state, Z_STREAM_ERROR,
00096 "internal error: deflate stream corrupt");
00097 return -1;
00098 }
00099 have -= strm->avail_out;
00100 } while (have);
00101
00102
00103 if (flush == Z_FINISH)
00104 deflateReset(strm);
00105
00106
00107 return 0;
00108 }
00109
00110
00111 local int gz_zero(state, len)
00112 gz_statep state;
00113 z_off64_t len;
00114 {
00115 int first;
00116 unsigned n;
00117 z_streamp strm = &(state->strm);
00118
00119
00120 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
00121 return -1;
00122
00123
00124 first = 1;
00125 while (len) {
00126 n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
00127 (unsigned)len : state->size;
00128 if (first) {
00129 memset(state->in, 0, n);
00130 first = 0;
00131 }
00132 strm->avail_in = n;
00133 strm->next_in = state->in;
00134 state->pos += n;
00135 if (gz_comp(state, Z_NO_FLUSH) == -1)
00136 return -1;
00137 len -= n;
00138 }
00139 return 0;
00140 }
00141
00142
00143 int ZEXPORT gzwrite(file, buf, len)
00144 gzFile file;
00145 voidpc buf;
00146 unsigned len;
00147 {
00148 unsigned put = len;
00149 unsigned n;
00150 gz_statep state;
00151 z_streamp strm;
00152
00153
00154 if (file == NULL)
00155 return 0;
00156 state = (gz_statep)file;
00157 strm = &(state->strm);
00158
00159
00160 if (state->mode != GZ_WRITE || state->err != Z_OK)
00161 return 0;
00162
00163
00164
00165 if ((int)len < 0) {
00166 gz_error(state, Z_BUF_ERROR, "requested length does not fit in int");
00167 return 0;
00168 }
00169
00170
00171 if (len == 0)
00172 return 0;
00173
00174
00175 if (state->size == 0 && gz_init(state) == -1)
00176 return 0;
00177
00178
00179 if (state->seek) {
00180 state->seek = 0;
00181 if (gz_zero(state, state->skip) == -1)
00182 return 0;
00183 }
00184
00185
00186 if (len < state->size) {
00187
00188 do {
00189 if (strm->avail_in == 0)
00190 strm->next_in = state->in;
00191 n = state->size - strm->avail_in;
00192 if (n > len)
00193 n = len;
00194 memcpy(strm->next_in + strm->avail_in, buf, n);
00195 strm->avail_in += n;
00196 state->pos += n;
00197 buf = (char *)buf + n;
00198 len -= n;
00199 if (len && gz_comp(state, Z_NO_FLUSH) == -1)
00200 return 0;
00201 } while (len);
00202 }
00203 else {
00204
00205 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
00206 return 0;
00207
00208
00209 strm->avail_in = len;
00210 strm->next_in = (voidp)buf;
00211 state->pos += len;
00212 if (gz_comp(state, Z_NO_FLUSH) == -1)
00213 return 0;
00214 }
00215
00216
00217 return (int)put;
00218 }
00219
00220
00221 int ZEXPORT gzputc(file, c)
00222 gzFile file;
00223 int c;
00224 {
00225 unsigned char buf[1];
00226 gz_statep state;
00227 z_streamp strm;
00228
00229
00230 if (file == NULL)
00231 return -1;
00232 state = (gz_statep)file;
00233 strm = &(state->strm);
00234
00235
00236 if (state->mode != GZ_WRITE || state->err != Z_OK)
00237 return -1;
00238
00239
00240 if (state->seek) {
00241 state->seek = 0;
00242 if (gz_zero(state, state->skip) == -1)
00243 return -1;
00244 }
00245
00246
00247
00248 if (strm->avail_in < state->size) {
00249 if (strm->avail_in == 0)
00250 strm->next_in = state->in;
00251 strm->next_in[strm->avail_in++] = c;
00252 state->pos++;
00253 return c;
00254 }
00255
00256
00257 buf[0] = c;
00258 if (gzwrite(file, buf, 1) != 1)
00259 return -1;
00260 return c;
00261 }
00262
00263
00264 int ZEXPORT gzputs(file, str)
00265 gzFile file;
00266 const char *str;
00267 {
00268 int ret;
00269 unsigned len;
00270
00271
00272 len = (unsigned)strlen(str);
00273 ret = gzwrite(file, str, len);
00274 return ret == 0 && len != 0 ? -1 : ret;
00275 }
00276
00277 #ifdef STDC
00278 #include <stdarg.h>
00279
00280
00281 int ZEXPORTVA gzprintf (gzFile file, const char *format, ...)
00282 {
00283 int size, len;
00284 gz_statep state;
00285 z_streamp strm;
00286 va_list va;
00287
00288
00289 if (file == NULL)
00290 return -1;
00291 state = (gz_statep)file;
00292 strm = &(state->strm);
00293
00294
00295 if (state->mode != GZ_WRITE || state->err != Z_OK)
00296 return 0;
00297
00298
00299 if (state->size == 0 && gz_init(state) == -1)
00300 return 0;
00301
00302
00303 if (state->seek) {
00304 state->seek = 0;
00305 if (gz_zero(state, state->skip) == -1)
00306 return 0;
00307 }
00308
00309
00310 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
00311 return 0;
00312
00313
00314 size = (int)(state->size);
00315 state->in[size - 1] = 0;
00316 va_start(va, format);
00317 #ifdef NO_vsnprintf
00318 # ifdef HAS_vsprintf_void
00319 (void)vsprintf(state->in, format, va);
00320 va_end(va);
00321 for (len = 0; len < size; len++)
00322 if (state->in[len] == 0) break;
00323 # else
00324 len = vsprintf(state->in, format, va);
00325 va_end(va);
00326 # endif
00327 #else
00328 # ifdef HAS_vsnprintf_void
00329 (void)vsnprintf(state->in, size, format, va);
00330 va_end(va);
00331 len = strlen(state->in);
00332 # else
00333 len = vsnprintf((char *)(state->in), size, format, va);
00334 va_end(va);
00335 # endif
00336 #endif
00337
00338
00339 if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
00340 return 0;
00341
00342
00343 strm->avail_in = (unsigned)len;
00344 strm->next_in = state->in;
00345 state->pos += len;
00346 return len;
00347 }
00348
00349 #else
00350
00351
00352 int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
00353 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
00354 gzFile file;
00355 const char *format;
00356 int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
00357 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
00358 {
00359 int size, len;
00360 gz_statep state;
00361 z_streamp strm;
00362
00363
00364 if (file == NULL)
00365 return -1;
00366 state = (gz_statep)file;
00367 strm = &(state->strm);
00368
00369
00370 if (state->mode != GZ_WRITE || state->err != Z_OK)
00371 return 0;
00372
00373
00374 if (state->size == 0 && gz_init(state) == -1)
00375 return 0;
00376
00377
00378 if (state->seek) {
00379 state->seek = 0;
00380 if (gz_zero(state, state->skip) == -1)
00381 return 0;
00382 }
00383
00384
00385 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
00386 return 0;
00387
00388
00389 size = (int)(state->size);
00390 state->in[size - 1] = 0;
00391 #ifdef NO_snprintf
00392 # ifdef HAS_sprintf_void
00393 sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8,
00394 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
00395 for (len = 0; len < size; len++)
00396 if (state->in[len] == 0) break;
00397 # else
00398 len = sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8,
00399 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
00400 # endif
00401 #else
00402 # ifdef HAS_snprintf_void
00403 snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8,
00404 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
00405 len = strlen(state->in);
00406 # else
00407 len = snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8,
00408 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
00409 # endif
00410 #endif
00411
00412
00413 if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
00414 return 0;
00415
00416
00417 strm->avail_in = (unsigned)len;
00418 strm->next_in = state->in;
00419 state->pos += len;
00420 return len;
00421 }
00422
00423 #endif
00424
00425
00426 int ZEXPORT gzflush(file, flush)
00427 gzFile file;
00428 int flush;
00429 {
00430 gz_statep state;
00431
00432
00433 if (file == NULL)
00434 return -1;
00435 state = (gz_statep)file;
00436
00437
00438 if (state->mode != GZ_WRITE || state->err != Z_OK)
00439 return Z_STREAM_ERROR;
00440
00441
00442 if (flush < 0 || flush > Z_FINISH)
00443 return Z_STREAM_ERROR;
00444
00445
00446 if (state->seek) {
00447 state->seek = 0;
00448 if (gz_zero(state, state->skip) == -1)
00449 return -1;
00450 }
00451
00452
00453 gz_comp(state, flush);
00454 return state->err;
00455 }
00456
00457
00458 int ZEXPORT gzsetparams(file, level, strategy)
00459 gzFile file;
00460 int level;
00461 int strategy;
00462 {
00463 gz_statep state;
00464 z_streamp strm;
00465
00466
00467 if (file == NULL)
00468 return Z_STREAM_ERROR;
00469 state = (gz_statep)file;
00470 strm = &(state->strm);
00471
00472
00473 if (state->mode != GZ_WRITE || state->err != Z_OK)
00474 return Z_STREAM_ERROR;
00475
00476
00477 if (level == state->level && strategy == state->strategy)
00478 return Z_OK;
00479
00480
00481 if (state->seek) {
00482 state->seek = 0;
00483 if (gz_zero(state, state->skip) == -1)
00484 return -1;
00485 }
00486
00487
00488 if (state->size) {
00489
00490 if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1)
00491 return state->err;
00492 deflateParams(strm, level, strategy);
00493 }
00494 state->level = level;
00495 state->strategy = strategy;
00496 return Z_OK;
00497 }
00498
00499
00500 int ZEXPORT gzclose_w(file)
00501 gzFile file;
00502 {
00503 int ret = 0;
00504 gz_statep state;
00505
00506
00507 if (file == NULL)
00508 return Z_STREAM_ERROR;
00509 state = (gz_statep)file;
00510
00511
00512 if (state->mode != GZ_WRITE)
00513 return Z_STREAM_ERROR;
00514
00515
00516 if (state->seek) {
00517 state->seek = 0;
00518 ret += gz_zero(state, state->skip);
00519 }
00520
00521
00522 ret += gz_comp(state, Z_FINISH);
00523 (void)deflateEnd(&(state->strm));
00524 free(state->out);
00525 free(state->in);
00526 gz_error(state, Z_OK, NULL);
00527 free(state->path);
00528 ret += close(state->fd);
00529 free(state);
00530 return ret ? Z_ERRNO : Z_OK;
00531 }