00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 #include "compress_io.h"
00056 #include "pg_backup_utils.h"
00057 #include "parallel.h"
00058
00059
00060
00061
00062
00063
00064
00065 struct CompressorState
00066 {
00067 CompressionAlgorithm comprAlg;
00068 WriteFunc writeF;
00069
00070 #ifdef HAVE_LIBZ
00071 z_streamp zp;
00072 char *zlibOut;
00073 size_t zlibOutSize;
00074 #endif
00075 };
00076
00077
00078 static const char *modulename = gettext_noop("compress_io");
00079
00080 static void ParseCompressionOption(int compression, CompressionAlgorithm *alg,
00081 int *level);
00082
00083
00084 #ifdef HAVE_LIBZ
00085 static void InitCompressorZlib(CompressorState *cs, int level);
00086 static void DeflateCompressorZlib(ArchiveHandle *AH, CompressorState *cs,
00087 bool flush);
00088 static void ReadDataFromArchiveZlib(ArchiveHandle *AH, ReadFunc readF);
00089 static size_t WriteDataToArchiveZlib(ArchiveHandle *AH, CompressorState *cs,
00090 const char *data, size_t dLen);
00091 static void EndCompressorZlib(ArchiveHandle *AH, CompressorState *cs);
00092 #endif
00093
00094
00095 static void ReadDataFromArchiveNone(ArchiveHandle *AH, ReadFunc readF);
00096 static size_t WriteDataToArchiveNone(ArchiveHandle *AH, CompressorState *cs,
00097 const char *data, size_t dLen);
00098
00099
00100
00101
00102
00103
00104 static void
00105 ParseCompressionOption(int compression, CompressionAlgorithm *alg, int *level)
00106 {
00107 if (compression == Z_DEFAULT_COMPRESSION ||
00108 (compression > 0 && compression <= 9))
00109 *alg = COMPR_ALG_LIBZ;
00110 else if (compression == 0)
00111 *alg = COMPR_ALG_NONE;
00112 else
00113 {
00114 exit_horribly(modulename, "invalid compression code: %d\n",
00115 compression);
00116 *alg = COMPR_ALG_NONE;
00117 }
00118
00119
00120 if (level)
00121 *level = compression;
00122 }
00123
00124
00125
00126
00127 CompressorState *
00128 AllocateCompressor(int compression, WriteFunc writeF)
00129 {
00130 CompressorState *cs;
00131 CompressionAlgorithm alg;
00132 int level;
00133
00134 ParseCompressionOption(compression, &alg, &level);
00135
00136 #ifndef HAVE_LIBZ
00137 if (alg == COMPR_ALG_LIBZ)
00138 exit_horribly(modulename, "not built with zlib support\n");
00139 #endif
00140
00141 cs = (CompressorState *) pg_malloc0(sizeof(CompressorState));
00142 cs->writeF = writeF;
00143 cs->comprAlg = alg;
00144
00145
00146
00147
00148 #ifdef HAVE_LIBZ
00149 if (alg == COMPR_ALG_LIBZ)
00150 InitCompressorZlib(cs, level);
00151 #endif
00152
00153 return cs;
00154 }
00155
00156
00157
00158
00159
00160 void
00161 ReadDataFromArchive(ArchiveHandle *AH, int compression, ReadFunc readF)
00162 {
00163 CompressionAlgorithm alg;
00164
00165 ParseCompressionOption(compression, &alg, NULL);
00166
00167 if (alg == COMPR_ALG_NONE)
00168 ReadDataFromArchiveNone(AH, readF);
00169 if (alg == COMPR_ALG_LIBZ)
00170 {
00171 #ifdef HAVE_LIBZ
00172 ReadDataFromArchiveZlib(AH, readF);
00173 #else
00174 exit_horribly(modulename, "not built with zlib support\n");
00175 #endif
00176 }
00177 }
00178
00179
00180
00181
00182 size_t
00183 WriteDataToArchive(ArchiveHandle *AH, CompressorState *cs,
00184 const void *data, size_t dLen)
00185 {
00186
00187 checkAborting(AH);
00188
00189 switch (cs->comprAlg)
00190 {
00191 case COMPR_ALG_LIBZ:
00192 #ifdef HAVE_LIBZ
00193 return WriteDataToArchiveZlib(AH, cs, data, dLen);
00194 #else
00195 exit_horribly(modulename, "not built with zlib support\n");
00196 #endif
00197 case COMPR_ALG_NONE:
00198 return WriteDataToArchiveNone(AH, cs, data, dLen);
00199 }
00200 return 0;
00201 }
00202
00203
00204
00205
00206 void
00207 EndCompressor(ArchiveHandle *AH, CompressorState *cs)
00208 {
00209 #ifdef HAVE_LIBZ
00210 if (cs->comprAlg == COMPR_ALG_LIBZ)
00211 EndCompressorZlib(AH, cs);
00212 #endif
00213 free(cs);
00214 }
00215
00216
00217
00218 #ifdef HAVE_LIBZ
00219
00220
00221
00222
00223 static void
00224 InitCompressorZlib(CompressorState *cs, int level)
00225 {
00226 z_streamp zp;
00227
00228 zp = cs->zp = (z_streamp) pg_malloc(sizeof(z_stream));
00229 zp->zalloc = Z_NULL;
00230 zp->zfree = Z_NULL;
00231 zp->opaque = Z_NULL;
00232
00233
00234
00235
00236
00237
00238 cs->zlibOut = (char *) pg_malloc(ZLIB_OUT_SIZE + 1);
00239 cs->zlibOutSize = ZLIB_OUT_SIZE;
00240
00241 if (deflateInit(zp, level) != Z_OK)
00242 exit_horribly(modulename,
00243 "could not initialize compression library: %s\n",
00244 zp->msg);
00245
00246
00247 zp->next_out = (void *) cs->zlibOut;
00248 zp->avail_out = cs->zlibOutSize;
00249 }
00250
00251 static void
00252 EndCompressorZlib(ArchiveHandle *AH, CompressorState *cs)
00253 {
00254 z_streamp zp = cs->zp;
00255
00256 zp->next_in = NULL;
00257 zp->avail_in = 0;
00258
00259
00260 DeflateCompressorZlib(AH, cs, true);
00261
00262 if (deflateEnd(zp) != Z_OK)
00263 exit_horribly(modulename,
00264 "could not close compression stream: %s\n", zp->msg);
00265
00266 free(cs->zlibOut);
00267 free(cs->zp);
00268 }
00269
00270 static void
00271 DeflateCompressorZlib(ArchiveHandle *AH, CompressorState *cs, bool flush)
00272 {
00273 z_streamp zp = cs->zp;
00274 char *out = cs->zlibOut;
00275 int res = Z_OK;
00276
00277 while (cs->zp->avail_in != 0 || flush)
00278 {
00279 res = deflate(zp, flush ? Z_FINISH : Z_NO_FLUSH);
00280 if (res == Z_STREAM_ERROR)
00281 exit_horribly(modulename,
00282 "could not compress data: %s\n", zp->msg);
00283 if ((flush && (zp->avail_out < cs->zlibOutSize))
00284 || (zp->avail_out == 0)
00285 || (zp->avail_in != 0)
00286 )
00287 {
00288
00289
00290
00291
00292
00293 if (zp->avail_out < cs->zlibOutSize)
00294 {
00295
00296
00297
00298
00299 size_t len = cs->zlibOutSize - zp->avail_out;
00300
00301 if (cs->writeF(AH, out, len) != len)
00302 exit_horribly(modulename,
00303 "could not write to output file: %s\n",
00304 strerror(errno));
00305 }
00306 zp->next_out = (void *) out;
00307 zp->avail_out = cs->zlibOutSize;
00308 }
00309
00310 if (res == Z_STREAM_END)
00311 break;
00312 }
00313 }
00314
00315 static size_t
00316 WriteDataToArchiveZlib(ArchiveHandle *AH, CompressorState *cs,
00317 const char *data, size_t dLen)
00318 {
00319 cs->zp->next_in = (void *) data;
00320 cs->zp->avail_in = dLen;
00321 DeflateCompressorZlib(AH, cs, false);
00322
00323
00324
00325
00326
00327 return dLen;
00328 }
00329
00330 static void
00331 ReadDataFromArchiveZlib(ArchiveHandle *AH, ReadFunc readF)
00332 {
00333 z_streamp zp;
00334 char *out;
00335 int res = Z_OK;
00336 size_t cnt;
00337 char *buf;
00338 size_t buflen;
00339
00340 zp = (z_streamp) pg_malloc(sizeof(z_stream));
00341 zp->zalloc = Z_NULL;
00342 zp->zfree = Z_NULL;
00343 zp->opaque = Z_NULL;
00344
00345 buf = pg_malloc(ZLIB_IN_SIZE);
00346 buflen = ZLIB_IN_SIZE;
00347
00348 out = pg_malloc(ZLIB_OUT_SIZE + 1);
00349
00350 if (inflateInit(zp) != Z_OK)
00351 exit_horribly(modulename,
00352 "could not initialize compression library: %s\n",
00353 zp->msg);
00354
00355
00356 while ((cnt = readF(AH, &buf, &buflen)))
00357 {
00358
00359 checkAborting(AH);
00360
00361 zp->next_in = (void *) buf;
00362 zp->avail_in = cnt;
00363
00364 while (zp->avail_in > 0)
00365 {
00366 zp->next_out = (void *) out;
00367 zp->avail_out = ZLIB_OUT_SIZE;
00368
00369 res = inflate(zp, 0);
00370 if (res != Z_OK && res != Z_STREAM_END)
00371 exit_horribly(modulename,
00372 "could not uncompress data: %s\n", zp->msg);
00373
00374 out[ZLIB_OUT_SIZE - zp->avail_out] = '\0';
00375 ahwrite(out, 1, ZLIB_OUT_SIZE - zp->avail_out, AH);
00376 }
00377 }
00378
00379 zp->next_in = NULL;
00380 zp->avail_in = 0;
00381 while (res != Z_STREAM_END)
00382 {
00383 zp->next_out = (void *) out;
00384 zp->avail_out = ZLIB_OUT_SIZE;
00385 res = inflate(zp, 0);
00386 if (res != Z_OK && res != Z_STREAM_END)
00387 exit_horribly(modulename,
00388 "could not uncompress data: %s\n", zp->msg);
00389
00390 out[ZLIB_OUT_SIZE - zp->avail_out] = '\0';
00391 ahwrite(out, 1, ZLIB_OUT_SIZE - zp->avail_out, AH);
00392 }
00393
00394 if (inflateEnd(zp) != Z_OK)
00395 exit_horribly(modulename,
00396 "could not close compression library: %s\n", zp->msg);
00397
00398 free(buf);
00399 free(out);
00400 free(zp);
00401 }
00402 #endif
00403
00404
00405
00406
00407
00408
00409 static void
00410 ReadDataFromArchiveNone(ArchiveHandle *AH, ReadFunc readF)
00411 {
00412 size_t cnt;
00413 char *buf;
00414 size_t buflen;
00415
00416 buf = pg_malloc(ZLIB_OUT_SIZE);
00417 buflen = ZLIB_OUT_SIZE;
00418
00419 while ((cnt = readF(AH, &buf, &buflen)))
00420 {
00421
00422 checkAborting(AH);
00423
00424 ahwrite(buf, 1, cnt, AH);
00425 }
00426
00427 free(buf);
00428 }
00429
00430 static size_t
00431 WriteDataToArchiveNone(ArchiveHandle *AH, CompressorState *cs,
00432 const char *data, size_t dLen)
00433 {
00434
00435
00436
00437
00438 if (cs->writeF(AH, data, dLen) != dLen)
00439 exit_horribly(modulename,
00440 "could not write to output file: %s\n",
00441 strerror(errno));
00442 return dLen;
00443 }
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455 struct cfp
00456 {
00457 FILE *uncompressedfp;
00458 #ifdef HAVE_LIBZ
00459 gzFile compressedfp;
00460 #endif
00461 };
00462
00463 #ifdef HAVE_LIBZ
00464 static int hasSuffix(const char *filename, const char *suffix);
00465 #endif
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475 cfp *
00476 cfopen_read(const char *path, const char *mode)
00477 {
00478 cfp *fp;
00479
00480 #ifdef HAVE_LIBZ
00481 if (hasSuffix(path, ".gz"))
00482 fp = cfopen(path, mode, 1);
00483 else
00484 #endif
00485 {
00486 fp = cfopen(path, mode, 0);
00487 #ifdef HAVE_LIBZ
00488 if (fp == NULL)
00489 {
00490 int fnamelen = strlen(path) + 4;
00491 char *fname = pg_malloc(fnamelen);
00492
00493 snprintf(fname, fnamelen, "%s%s", path, ".gz");
00494 fp = cfopen(fname, mode, 1);
00495 free(fname);
00496 }
00497 #endif
00498 }
00499 return fp;
00500 }
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511 cfp *
00512 cfopen_write(const char *path, const char *mode, int compression)
00513 {
00514 cfp *fp;
00515
00516 if (compression == 0)
00517 fp = cfopen(path, mode, 0);
00518 else
00519 {
00520 #ifdef HAVE_LIBZ
00521 int fnamelen = strlen(path) + 4;
00522 char *fname = pg_malloc(fnamelen);
00523
00524 snprintf(fname, fnamelen, "%s%s", path, ".gz");
00525 fp = cfopen(fname, mode, 1);
00526 free(fname);
00527 #else
00528 exit_horribly(modulename, "not built with zlib support\n");
00529 fp = NULL;
00530 #endif
00531 }
00532 return fp;
00533 }
00534
00535
00536
00537
00538
00539 cfp *
00540 cfopen(const char *path, const char *mode, int compression)
00541 {
00542 cfp *fp = pg_malloc(sizeof(cfp));
00543
00544 if (compression != 0)
00545 {
00546 #ifdef HAVE_LIBZ
00547 fp->compressedfp = gzopen(path, mode);
00548 fp->uncompressedfp = NULL;
00549 if (fp->compressedfp == NULL)
00550 {
00551 free(fp);
00552 fp = NULL;
00553 }
00554 #else
00555 exit_horribly(modulename, "not built with zlib support\n");
00556 #endif
00557 }
00558 else
00559 {
00560 #ifdef HAVE_LIBZ
00561 fp->compressedfp = NULL;
00562 #endif
00563 fp->uncompressedfp = fopen(path, mode);
00564 if (fp->uncompressedfp == NULL)
00565 {
00566 free(fp);
00567 fp = NULL;
00568 }
00569 }
00570
00571 return fp;
00572 }
00573
00574
00575 int
00576 cfread(void *ptr, int size, cfp *fp)
00577 {
00578 #ifdef HAVE_LIBZ
00579 if (fp->compressedfp)
00580 return gzread(fp->compressedfp, ptr, size);
00581 else
00582 #endif
00583 return fread(ptr, 1, size, fp->uncompressedfp);
00584 }
00585
00586 int
00587 cfwrite(const void *ptr, int size, cfp *fp)
00588 {
00589 #ifdef HAVE_LIBZ
00590 if (fp->compressedfp)
00591 return gzwrite(fp->compressedfp, ptr, size);
00592 else
00593 #endif
00594 return fwrite(ptr, 1, size, fp->uncompressedfp);
00595 }
00596
00597 int
00598 cfgetc(cfp *fp)
00599 {
00600 #ifdef HAVE_LIBZ
00601 if (fp->compressedfp)
00602 return gzgetc(fp->compressedfp);
00603 else
00604 #endif
00605 return fgetc(fp->uncompressedfp);
00606 }
00607
00608 char *
00609 cfgets(cfp *fp, char *buf, int len)
00610 {
00611 #ifdef HAVE_LIBZ
00612 if (fp->compressedfp)
00613 return gzgets(fp->compressedfp, buf, len);
00614 else
00615 #endif
00616 return fgets(buf, len, fp->uncompressedfp);
00617 }
00618
00619 int
00620 cfclose(cfp *fp)
00621 {
00622 int result;
00623
00624 if (fp == NULL)
00625 {
00626 errno = EBADF;
00627 return EOF;
00628 }
00629 #ifdef HAVE_LIBZ
00630 if (fp->compressedfp)
00631 {
00632 result = gzclose(fp->compressedfp);
00633 fp->compressedfp = NULL;
00634 }
00635 else
00636 #endif
00637 {
00638 result = fclose(fp->uncompressedfp);
00639 fp->uncompressedfp = NULL;
00640 }
00641 free(fp);
00642
00643 return result;
00644 }
00645
00646 int
00647 cfeof(cfp *fp)
00648 {
00649 #ifdef HAVE_LIBZ
00650 if (fp->compressedfp)
00651 return gzeof(fp->compressedfp);
00652 else
00653 #endif
00654 return feof(fp->uncompressedfp);
00655 }
00656
00657 #ifdef HAVE_LIBZ
00658 static int
00659 hasSuffix(const char *filename, const char *suffix)
00660 {
00661 int filenamelen = strlen(filename);
00662 int suffixlen = strlen(suffix);
00663
00664 if (filenamelen < suffixlen)
00665 return 0;
00666
00667 return memcmp(&filename[filenamelen - suffixlen],
00668 suffix,
00669 suffixlen) == 0;
00670 }
00671
00672 #endif