1 /*********************************************************************/ 2 // dar - disk archive - a backup/restoration program 3 // Copyright (C) 2002-2052 Denis Corbin 4 // 5 // This program is free software; you can redistribute it and/or 6 // modify it under the terms of the GNU General Public License 7 // as published by the Free Software Foundation; either version 2 8 // of the License, or (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with this program; if not, write to the Free Software 17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 // 19 // to contact the author : http://dar.linux.free.fr/email.html 20 /*********************************************************************/ 21 22 #include "../my_config.h" 23 24 #include "wrapperlib.hpp" 25 #include "erreurs.hpp" 26 27 #define CHECK_Z if(z_ptr == nullptr) throw SRC_BUG 28 #define CHECK_BZ if(bz_ptr == nullptr) throw SRC_BUG 29 #define CHECK_LZMA if(lzma_ptr == nullptr) throw SRC_BUG; 30 31 using namespace std; 32 33 namespace libdar 34 { 35 36 #if LIBZ_AVAILABLE 37 static S_I zlib2wrap_code(S_I code); 38 static S_I wrap2zlib_code(S_I code); 39 #endif 40 #if LIBBZ2_AVAILABLE 41 static S_I bzlib2wrap_code(S_I code); 42 static S_I wrap2bzlib_code(S_I code); 43 #endif 44 #if LIBLZMA_AVAILABLE 45 static S_I lzma2wrap_code(S_I code); 46 static lzma_action wrap2lzma_code(S_I code); 47 #endif 48 wrapperlib(wrapperlib_mode mode)49 wrapperlib::wrapperlib(wrapperlib_mode mode) 50 { 51 switch(mode) 52 { 53 case zlib_mode: 54 #if LIBZ_AVAILABLE 55 meta_new(z_ptr, 1); 56 if(z_ptr == nullptr) 57 throw Ememory("wrapperlib::wrapperlib"); 58 #if LIBBZ2_AVAILABLE 59 bz_ptr = nullptr; 60 #endif 61 #if LIBLZMA_AVAILABLE 62 lzma_ptr = nullptr; 63 #endif 64 z_ptr->zalloc = nullptr; 65 z_ptr->zfree = nullptr; 66 z_ptr->opaque = nullptr; 67 x_compressInit = & wrapperlib::z_compressInit; 68 x_decompressInit = & wrapperlib::z_decompressInit; 69 x_compressEnd = & wrapperlib::z_compressEnd; 70 x_decompressEnd = & wrapperlib::z_decompressEnd; 71 x_compress = & wrapperlib::z_compress; 72 x_decompress = & wrapperlib::z_decompress; 73 x_set_next_in = & wrapperlib::z_set_next_in; 74 x_set_avail_in = & wrapperlib::z_set_avail_in; 75 x_get_avail_in = & wrapperlib::z_get_avail_in; 76 x_get_total_in = & wrapperlib::z_get_total_in; 77 x_set_next_out = & wrapperlib::z_set_next_out; 78 x_get_next_out = & wrapperlib::z_get_next_out; 79 x_set_avail_out = & wrapperlib::z_set_avail_out; 80 x_get_avail_out = & wrapperlib::z_get_avail_out; 81 x_get_total_out = & wrapperlib::z_get_total_out; 82 break; 83 #else 84 throw Ecompilation("zlib compression support"); 85 #endif 86 case bzlib_mode: 87 #if LIBBZ2_AVAILABLE 88 meta_new(bz_ptr, 1); 89 if(bz_ptr == nullptr) 90 throw Ememory("wrapperlib::wrapperlib"); 91 #if LIBZ_AVAILABLE 92 z_ptr = nullptr; 93 #endif 94 #if LIBLZMA_AVAILABLE 95 lzma_ptr = nullptr; 96 #endif 97 bz_ptr->bzalloc = nullptr; 98 bz_ptr->bzfree = nullptr; 99 bz_ptr->opaque = nullptr; 100 x_compressInit = & wrapperlib::bz_compressInit; 101 x_decompressInit = & wrapperlib::bz_decompressInit; 102 x_compressEnd = & wrapperlib::bz_compressEnd; 103 x_decompressEnd = & wrapperlib::bz_decompressEnd; 104 x_compress = & wrapperlib::bz_compress; 105 x_decompress = & wrapperlib::bz_decompress; 106 x_set_next_in = & wrapperlib::bz_set_next_in; 107 x_set_avail_in = & wrapperlib::bz_set_avail_in; 108 x_get_avail_in = & wrapperlib::bz_get_avail_in; 109 x_get_total_in = & wrapperlib::bz_get_total_in; 110 x_set_next_out = & wrapperlib::bz_set_next_out; 111 x_get_next_out = & wrapperlib::bz_get_next_out; 112 x_set_avail_out = & wrapperlib::bz_set_avail_out; 113 x_get_avail_out = & wrapperlib::bz_get_avail_out; 114 x_get_total_out = & wrapperlib::bz_get_total_out; 115 break; 116 #else 117 throw Ecompilation("libbz2 compression support"); 118 #endif 119 case xz_mode: 120 #if LIBZ_AVAILABLE 121 z_ptr = nullptr; 122 #endif 123 #if LIBBZ2_AVAILABLE 124 bz_ptr = nullptr; 125 #endif 126 #if LIBLZMA_AVAILABLE 127 meta_new(lzma_ptr, 1); 128 if(lzma_ptr == nullptr) 129 throw Ememory("wrapperlib::wrapperlib"); 130 *lzma_ptr = LZMA_STREAM_INIT; 131 x_compressInit = & wrapperlib::lzma_compressInit; 132 x_decompressInit = & wrapperlib::lzma_decompressInit; 133 x_compressEnd = & wrapperlib::lzma_end; 134 x_decompressEnd = & wrapperlib::lzma_end; 135 x_compress = & wrapperlib::lzma_encode; 136 x_decompress = & wrapperlib::lzma_encode; 137 x_set_next_in = & wrapperlib::lzma_set_next_in; 138 x_set_avail_in = & wrapperlib::lzma_set_avail_in; 139 x_get_avail_in = & wrapperlib::lzma_get_avail_in; 140 x_get_total_in = & wrapperlib::lzma_get_total_in; 141 x_set_next_out = & wrapperlib::lzma_set_next_out; 142 x_get_next_out = & wrapperlib::lzma_get_next_out; 143 x_set_avail_out = & wrapperlib::lzma_set_avail_out; 144 x_get_avail_out = & wrapperlib::lzma_get_avail_out; 145 x_get_total_out = & wrapperlib::lzma_get_total_out; 146 #endif 147 break; 148 default: 149 throw SRC_BUG; 150 } 151 level = -1; 152 } 153 wrapperlib(const wrapperlib & ref)154 wrapperlib::wrapperlib(const wrapperlib & ref) 155 { 156 throw Efeature(gettext("Cannot copy a wrapperlib object (NOT IMPLEMENTED)")); 157 } 158 operator =(const wrapperlib & ref)159 const wrapperlib & wrapperlib::operator = (const wrapperlib & ref) 160 { 161 throw Efeature(gettext("Cannot copy a wrapperlib object (NOT IMPLEMENTED)")); 162 } 163 ~wrapperlib()164 wrapperlib::~wrapperlib() 165 { 166 #if LIBZ_AVAILABLE 167 if(z_ptr != nullptr) 168 meta_delete(z_ptr); 169 #endif 170 #if LIBBZ2_AVAILABLE 171 if(bz_ptr != nullptr) 172 meta_delete(bz_ptr); 173 #endif 174 #if LIBLZMA_AVAILABLE 175 if(lzma_ptr != nullptr) 176 { 177 ::lzma_end(lzma_ptr); 178 meta_delete(lzma_ptr); 179 } 180 #endif 181 } 182 183 ////////////// Zlib routines ///////////// 184 185 #if LIBZ_AVAILABLE z_compressInit(U_I compression_level)186 S_I wrapperlib::z_compressInit(U_I compression_level) 187 { 188 CHECK_Z; 189 return zlib2wrap_code(deflateInit(z_ptr, compression_level)); 190 } 191 z_decompressInit()192 S_I wrapperlib::z_decompressInit() 193 { 194 CHECK_Z; 195 return zlib2wrap_code(inflateInit(z_ptr)); 196 } 197 z_compressEnd()198 S_I wrapperlib::z_compressEnd() 199 { 200 CHECK_Z; 201 return zlib2wrap_code(deflateEnd(z_ptr)); 202 } 203 z_decompressEnd()204 S_I wrapperlib::z_decompressEnd() 205 { 206 CHECK_Z; 207 return zlib2wrap_code(inflateEnd(z_ptr)); 208 } 209 z_compress(S_I flag)210 S_I wrapperlib::z_compress(S_I flag) 211 { 212 CHECK_Z; 213 return zlib2wrap_code(deflate(z_ptr, wrap2zlib_code(flag))); 214 } 215 z_decompress(S_I flag)216 S_I wrapperlib::z_decompress(S_I flag) 217 { 218 CHECK_Z; 219 return zlib2wrap_code(inflate(z_ptr, wrap2zlib_code(flag))); 220 } 221 z_set_next_in(const char * x)222 void wrapperlib::z_set_next_in(const char *x) 223 { 224 CHECK_Z; 225 z_ptr->next_in = (Bytef *)x; 226 } 227 z_set_avail_in(U_I x)228 void wrapperlib::z_set_avail_in(U_I x) 229 { 230 CHECK_Z; 231 z_ptr->avail_in = x; 232 } 233 z_get_avail_in() const234 U_I wrapperlib::z_get_avail_in() const 235 { 236 CHECK_Z; 237 return z_ptr->avail_in; 238 } 239 z_get_total_in() const240 U_64 wrapperlib::z_get_total_in() const 241 { 242 CHECK_Z; 243 return z_ptr->total_in; 244 } 245 z_set_next_out(char * x)246 void wrapperlib::z_set_next_out(char *x) 247 { 248 CHECK_Z; 249 z_ptr->next_out = (Bytef *)x; 250 } 251 z_get_next_out() const252 char *wrapperlib::z_get_next_out() const 253 { 254 CHECK_Z; 255 return (char *)z_ptr->next_out; 256 } 257 z_set_avail_out(U_I x)258 void wrapperlib::z_set_avail_out(U_I x) 259 { 260 CHECK_Z; 261 z_ptr->avail_out = x; 262 } 263 z_get_avail_out() const264 U_I wrapperlib::z_get_avail_out() const 265 { 266 CHECK_Z; 267 return z_ptr->avail_out; 268 } 269 z_get_total_out() const270 U_64 wrapperlib::z_get_total_out() const 271 { 272 CHECK_Z; 273 return z_ptr->total_out; 274 } 275 #endif 276 277 ////////////// BZlib routines ///////////// 278 279 #if LIBBZ2_AVAILABLE bz_set_next_in(const char * x)280 void wrapperlib::bz_set_next_in(const char *x) 281 { 282 CHECK_BZ; 283 bz_ptr->next_in = (char*)x; // It must be a bug in bz that the input is not a const char* 284 } 285 bz_set_avail_in(U_I x)286 void wrapperlib::bz_set_avail_in(U_I x) 287 { 288 CHECK_BZ; 289 bz_ptr->avail_in = x; 290 } 291 bz_get_avail_in() const292 U_I wrapperlib::bz_get_avail_in() const 293 { 294 CHECK_BZ; 295 return bz_ptr->avail_in; 296 } 297 bz_get_total_in() const298 U_64 wrapperlib::bz_get_total_in() const 299 { 300 CHECK_BZ; 301 return ((U_64)(bz_ptr->total_in_hi32) << 32) | ((U_64)(bz_ptr->total_in_lo32)); 302 } 303 bz_set_next_out(char * x)304 void wrapperlib::bz_set_next_out(char *x) 305 { 306 CHECK_BZ; 307 bz_ptr->next_out = x; 308 } 309 bz_get_next_out() const310 char *wrapperlib::bz_get_next_out() const 311 { 312 CHECK_BZ; 313 return bz_ptr->next_out; 314 } 315 bz_set_avail_out(U_I x)316 void wrapperlib::bz_set_avail_out(U_I x) 317 { 318 CHECK_BZ; 319 bz_ptr->avail_out = x; 320 } 321 bz_get_avail_out() const322 U_I wrapperlib::bz_get_avail_out() const 323 { 324 CHECK_BZ; 325 return bz_ptr->avail_out; 326 } 327 bz_get_total_out() const328 U_64 wrapperlib::bz_get_total_out() const 329 { 330 CHECK_BZ; 331 return ((U_64)(bz_ptr->total_out_hi32) << 32) | ((U_64)(bz_ptr->total_out_lo32)); 332 } 333 334 bz_compressInit(U_I compression_level)335 S_I wrapperlib::bz_compressInit(U_I compression_level) 336 { 337 CHECK_BZ; 338 return bzlib2wrap_code(BZ2_bzCompressInit(bz_ptr, compression_level, 0, 30)); 339 } 340 bz_decompressInit()341 S_I wrapperlib::bz_decompressInit() 342 { 343 CHECK_BZ; 344 return bzlib2wrap_code(BZ2_bzDecompressInit(bz_ptr, 0,0)); 345 } 346 bz_compressEnd()347 S_I wrapperlib::bz_compressEnd() 348 { 349 CHECK_BZ; 350 return bzlib2wrap_code(BZ2_bzCompressEnd(bz_ptr)); 351 } 352 bz_decompressEnd()353 S_I wrapperlib::bz_decompressEnd() 354 { 355 CHECK_BZ; 356 return bzlib2wrap_code(BZ2_bzDecompressEnd(bz_ptr)); 357 } 358 bz_compress(S_I flag)359 S_I wrapperlib::bz_compress(S_I flag) 360 { 361 S_I ret; 362 CHECK_BZ; 363 ret = BZ2_bzCompress(bz_ptr, wrap2bzlib_code(flag)); 364 if(ret == BZ_SEQUENCE_ERROR) 365 ret = BZ_STREAM_END; 366 return bzlib2wrap_code(ret); 367 } 368 bz_decompress(S_I flag)369 S_I wrapperlib::bz_decompress(S_I flag) 370 { 371 // flag is not used here. 372 S_I ret; 373 CHECK_BZ; 374 ret = BZ2_bzDecompress(bz_ptr); 375 if(ret == BZ_SEQUENCE_ERROR) 376 ret = BZ_STREAM_END; 377 return bzlib2wrap_code(ret); 378 } 379 #endif 380 381 ////////////// LZMA routines ///////////// 382 383 #if LIBLZMA_AVAILABLE lzma_compressInit(U_I compression_level)384 S_I wrapperlib::lzma_compressInit(U_I compression_level) 385 { 386 CHECK_LZMA; 387 return lzma2wrap_code(lzma_easy_encoder(lzma_ptr, 388 compression_level, 389 LZMA_CHECK_CRC32)); 390 // CR32 is large enough, even no LZMA_CHECK_NONE would 391 // be possible as compressed data is protected by libdar 392 // CRC which width is proportionnal to the size of the 393 // compressed file. 394 } 395 lzma_decompressInit()396 S_I wrapperlib::lzma_decompressInit() 397 { 398 CHECK_LZMA; 399 return lzma2wrap_code(lzma_auto_decoder(lzma_ptr, 400 UINT64_MAX, 401 0)); 402 } 403 lzma_end()404 S_I wrapperlib::lzma_end() 405 { 406 CHECK_LZMA; 407 return WR_OK; // nothing done 408 } 409 lzma_encode(S_I flag)410 S_I wrapperlib::lzma_encode(S_I flag) 411 { 412 CHECK_LZMA; 413 return lzma2wrap_code(lzma_code(lzma_ptr, wrap2lzma_code(flag))); 414 } 415 lzma_set_next_in(const char * x)416 void wrapperlib::lzma_set_next_in(const char *x) 417 { 418 CHECK_LZMA; 419 lzma_ptr->next_in = (Bytef *)x; 420 } 421 lzma_set_avail_in(U_I x)422 void wrapperlib::lzma_set_avail_in(U_I x) 423 { 424 CHECK_LZMA; 425 lzma_ptr->avail_in = x; 426 } 427 lzma_get_avail_in() const428 U_I wrapperlib::lzma_get_avail_in() const 429 { 430 CHECK_LZMA; 431 return lzma_ptr->avail_in; 432 } 433 lzma_get_total_in() const434 U_64 wrapperlib::lzma_get_total_in() const 435 { 436 CHECK_LZMA; 437 return lzma_ptr->total_in; 438 } 439 lzma_set_next_out(char * x)440 void wrapperlib::lzma_set_next_out(char *x) 441 { 442 CHECK_LZMA; 443 lzma_ptr->next_out = (Bytef *)x; 444 } 445 lzma_get_next_out() const446 char *wrapperlib::lzma_get_next_out() const 447 { 448 CHECK_LZMA; 449 return (char *)lzma_ptr->next_out; 450 } 451 lzma_set_avail_out(U_I x)452 void wrapperlib::lzma_set_avail_out(U_I x) 453 { 454 CHECK_LZMA; 455 lzma_ptr->avail_out = x; 456 } 457 lzma_get_avail_out() const458 U_I wrapperlib::lzma_get_avail_out() const 459 { 460 CHECK_LZMA; 461 return lzma_ptr->avail_out; 462 } 463 lzma_get_total_out() const464 U_64 wrapperlib::lzma_get_total_out() const 465 { 466 CHECK_LZMA; 467 return lzma_ptr->total_out; 468 } 469 #endif 470 compressReset()471 S_I wrapperlib::compressReset() 472 { 473 S_I ret; 474 475 if(level < 0) 476 throw Erange("wrapperlib::compressReset", gettext("compressReset called but compressInit never called before")); 477 ret = compressEnd(); 478 if(ret == WR_OK) 479 return compressInit(level); 480 else 481 return ret; 482 } 483 decompressReset()484 S_I wrapperlib::decompressReset() 485 { 486 S_I ret = decompressEnd(); 487 488 if(ret == WR_OK) 489 return decompressInit(); 490 else 491 return ret; 492 } 493 494 #if LIBZ_AVAILABLE zlib2wrap_code(S_I code)495 static S_I zlib2wrap_code(S_I code) 496 { 497 switch(code) 498 { 499 case Z_OK: 500 return WR_OK; 501 case Z_MEM_ERROR: 502 return WR_MEM_ERROR; 503 case Z_VERSION_ERROR: 504 return WR_VERSION_ERROR; 505 case Z_STREAM_END: 506 return WR_STREAM_END; 507 case Z_DATA_ERROR: 508 return WR_DATA_ERROR; 509 case Z_BUF_ERROR: 510 return WR_BUF_ERROR; 511 case Z_STREAM_ERROR: 512 return WR_STREAM_ERROR; 513 case Z_NEED_DICT: 514 return WR_DATA_ERROR; 515 // we do not use explicit dictionnary for compression, 516 // this is zlib assumes it requires a dictionnary, this is 517 // to be considered a data error. 518 default: 519 throw SRC_BUG; // unexpected error code 520 } 521 } 522 wrap2zlib_code(S_I code)523 static S_I wrap2zlib_code(S_I code) 524 { 525 switch(code) 526 { 527 case WR_NO_FLUSH: 528 return Z_NO_FLUSH; 529 case WR_FINISH: 530 return Z_FINISH; 531 default: 532 throw SRC_BUG; 533 } 534 } 535 536 537 #endif 538 539 #if LIBBZ2_AVAILABLE bzlib2wrap_code(S_I code)540 static S_I bzlib2wrap_code(S_I code) 541 { 542 switch(code) 543 { 544 case BZ_OK: 545 case BZ_RUN_OK: 546 case BZ_FLUSH_OK: 547 case BZ_FINISH_OK: 548 return WR_OK; 549 case BZ_PARAM_ERROR: 550 return WR_STREAM_ERROR; 551 case BZ_CONFIG_ERROR: 552 return WR_VERSION_ERROR; 553 case BZ_MEM_ERROR: 554 return WR_MEM_ERROR; 555 case BZ_DATA_ERROR: 556 case BZ_DATA_ERROR_MAGIC: 557 return WR_DATA_ERROR; 558 case BZ_STREAM_END: 559 return WR_STREAM_END; 560 case BZ_SEQUENCE_ERROR: 561 default: 562 throw SRC_BUG; 563 } 564 } 565 wrap2bzlib_code(S_I code)566 static S_I wrap2bzlib_code(S_I code) 567 { 568 switch(code) 569 { 570 case WR_NO_FLUSH: 571 return BZ_RUN; 572 case WR_FINISH: 573 return BZ_FINISH; 574 default: 575 throw SRC_BUG; 576 } 577 } 578 #endif 579 580 #if LIBLZMA_AVAILABLE lzma2wrap_code(S_I code)581 static S_I lzma2wrap_code(S_I code) 582 { 583 switch(code) 584 { 585 case LZMA_OK: 586 return WR_OK; 587 case LZMA_MEM_ERROR: 588 return WR_MEM_ERROR; 589 case LZMA_OPTIONS_ERROR: 590 case LZMA_FORMAT_ERROR: // no memory usage limit used from libdar, only file format error can generate this code 591 return WR_VERSION_ERROR; 592 case LZMA_STREAM_END: 593 return WR_STREAM_END; 594 case LZMA_DATA_ERROR: 595 return WR_DATA_ERROR; 596 case LZMA_BUF_ERROR: 597 return WR_BUF_ERROR; 598 case LZMA_NO_CHECK: 599 case LZMA_UNSUPPORTED_CHECK: 600 return WR_STREAM_ERROR; 601 case LZMA_PROG_ERROR: 602 throw SRC_BUG; // error in libdar calling liblzma 603 case LZMA_GET_CHECK: 604 throw SRC_BUG; 605 // can be retured by lzma_code "only if the decoder was initialized with the LZMA_TELL_ANY_CHECK flag" 606 // flag we do not use from libdar 607 default: 608 throw SRC_BUG; // unexpected error code 609 } 610 } 611 wrap2lzma_code(S_I code)612 static lzma_action wrap2lzma_code(S_I code) 613 { 614 switch(code) 615 { 616 case WR_NO_FLUSH: 617 return LZMA_RUN; 618 case WR_FINISH: 619 return LZMA_FINISH; 620 default: 621 throw SRC_BUG; 622 } 623 } 624 625 #endif 626 627 } // end of namespace 628