| 80 #include <glib/gstdio.h> |
80 #include <glib/gstdio.h> |
| 81 |
81 |
| 82 #include <purple.h> |
82 #include <purple.h> |
| 83 |
83 |
| 84 #include "untar.h" |
84 #include "untar.h" |
| 85 |
|
| 86 #define untar_error( error, args... ) purple_debug(PURPLE_DEBUG_ERROR, "untar", error, ## args ) |
|
| 87 #define untar_warning( warning, args... ) purple_debug(PURPLE_DEBUG_WARNING, "untar", warning, ## args ) |
|
| 88 #define untar_verbose( args... ) purple_debug(PURPLE_DEBUG_INFO, "untar", ## args ) |
|
| 89 |
85 |
| 90 #define WSIZE 32768 /* size of decompression buffer */ |
86 #define WSIZE 32768 /* size of decompression buffer */ |
| 91 #define TSIZE 512 /* size of a "tape" block */ |
87 #define TSIZE 512 /* size of a "tape" block */ |
| 92 #define CR 13 /* carriage-return character */ |
88 #define CR 13 /* carriage-return character */ |
| 93 #define LF 10 /* line-feed character */ |
89 #define LF 10 /* line-feed character */ |
| 147 int i; |
143 int i; |
| 148 |
144 |
| 149 /* if we aren't allowed to overwrite and this file exists, return NULL */ |
145 /* if we aren't allowed to overwrite and this file exists, return NULL */ |
| 150 if (!FORCE && access(name, 0) == 0) |
146 if (!FORCE && access(name, 0) == 0) |
| 151 { |
147 { |
| 152 untar_warning("%s: exists, will not overwrite without \"FORCE option\"\n", name); |
148 purple_debug_warning("untar", "%s: exists, will not overwrite without \"FORCE option\"", name); |
| 153 return NULL; |
149 return NULL; |
| 154 } |
150 } |
| 155 |
151 |
| 156 /* first try creating it the easy way */ |
152 /* first try creating it the easy way */ |
| 157 fp = g_fopen(name, CONVERT ? "w" : "wb"); |
153 fp = g_fopen(name, CONVERT ? "w" : "wb"); |
| 194 |
190 |
| 195 /* Open the source file. We do this first to make sure it exists */ |
191 /* Open the source file. We do this first to make sure it exists */ |
| 196 fpsrc = g_fopen(src, "rb"); |
192 fpsrc = g_fopen(src, "rb"); |
| 197 if (!fpsrc) |
193 if (!fpsrc) |
| 198 { |
194 { |
| 199 untar_error("Error opening: %s\n", src); |
195 purple_debug_error("untar", "Error opening: %s", src); |
| 200 return; |
196 return; |
| 201 } |
197 } |
| 202 |
198 |
| 203 /* Create the destination file. On POSIX systems, this is just to |
199 /* Create the destination file. On POSIX systems, this is just to |
| 204 * make sure the directory path exists. |
200 * make sure the directory path exists. |
| 245 /* Close the files */ |
241 /* Close the files */ |
| 246 fclose(fpsrc); |
242 fclose(fpsrc); |
| 247 fclose(fpdst); |
243 fclose(fpdst); |
| 248 |
244 |
| 249 /* Give a warning */ |
245 /* Give a warning */ |
| 250 untar_warning("%s: copy instead of link\n", dst); |
246 purple_debug_warning("untar", "%s: copy instead of link", dst); |
| 251 } |
247 } |
| 252 |
248 |
| 253 /* This calls fwrite(), possibly after converting CR-LF to LF */ |
249 /* This calls fwrite(), possibly after converting CR-LF to LF */ |
| 254 static void cvtwrite(blk, size, fp) |
250 static void cvtwrite(blk, size, fp) |
| 255 Uchar_t *blk; /* the block to be written */ |
251 Uchar_t *blk; /* the block to be written */ |
| 377 && (tblk)->size[0] != ' ') |
373 && (tblk)->size[0] != ' ') |
| 378 || (tblk)->size[0] > '9') |
374 || (tblk)->size[0] > '9') |
| 379 { |
375 { |
| 380 if (first) |
376 if (first) |
| 381 { |
377 { |
| 382 untar_error("%s: not a valid tar file\n", inname); |
378 purple_debug_error("untar", "%s: not a valid tar file", inname); |
| 383 return 0; |
379 return 0; |
| 384 } |
380 } |
| 385 else |
381 else |
| 386 { |
382 { |
| 387 untar_error("Garbage detected; preceding file may be damaged\n"); |
383 purple_debug_error("untar", "Garbage detected; preceding file may be damaged"); |
| 388 return 0; |
384 return 0; |
| 389 } |
385 } |
| 390 } |
386 } |
| 391 |
387 |
| 392 /* combine prefix and filename */ |
388 /* combine prefix and filename */ |
| 442 && (tblk)->checksum[i] <= '7') |
438 && (tblk)->checksum[i] <= '7') |
| 443 sum = sum * 8 + (tblk)->checksum[i] - '0'; |
439 sum = sum * 8 + (tblk)->checksum[i] - '0'; |
| 444 } |
440 } |
| 445 if (sum != checksum(tblk, 0) && sum != checksum(tblk, 1)) |
441 if (sum != checksum(tblk, 0) && sum != checksum(tblk, 1)) |
| 446 { |
442 { |
| 447 if (!first) |
443 if (!first) { |
| 448 untar_error("Garbage detected; preceding file may be damaged\n"); |
444 purple_debug_error("untar", "Garbage detected; preceding file may be damaged"); |
| 449 untar_error("%s: header has bad checksum for %s\n", inname, nbuf); |
445 } |
| |
446 purple_debug_error("untar", "%s: header has bad checksum for %s", inname, nbuf); |
| 450 return 0; |
447 return 0; |
| 451 } |
448 } |
| 452 |
449 |
| 453 /* From this point on, we don't care whether this is the first |
450 /* From this point on, we don't care whether this is the first |
| 454 * block or not. Might as well reset the "first" flag now. |
451 * block or not. Might as well reset the "first" flag now. |
| 484 } |
481 } |
| 485 #endif |
482 #endif |
| 486 |
483 |
| 487 /* list the file */ |
484 /* list the file */ |
| 488 if (VERBOSE) |
485 if (VERBOSE) |
| 489 untar_verbose("%c %s", |
486 purple_debug_info("untar", "%c %s", |
| 490 ISREGULAR(*tblk) ? '-' : ("hlcbdp"[(tblk)->type - '1']), |
487 ISREGULAR(*tblk) ? '-' : ("hlcbdp"[(tblk)->type - '1']), |
| 491 nbuf); |
488 nbuf); |
| 492 else if (!QUIET) |
489 else if (!QUIET) |
| 493 untar_verbose("%s\n", nbuf); |
490 purple_debug_info("untar", "%s", nbuf); |
| 494 |
491 |
| 495 /* if link, then do the link-or-copy thing */ |
492 /* if link, then do the link-or-copy thing */ |
| 496 if (tblk->type == '1' || tblk->type == '2') |
493 if (tblk->type == '1' || tblk->type == '2') |
| 497 { |
494 { |
| 498 if (VERBOSE) |
495 if (VERBOSE) |
| 499 untar_verbose(" -> %s\n", tblk->linkto); |
496 purple_debug_info("untar", " -> %s", tblk->linkto); |
| 500 if (!LISTING) |
497 if (!LISTING) |
| 501 linkorcopy(tblk->linkto, nbuf, tblk->type == '2'); |
498 linkorcopy(tblk->linkto, nbuf, tblk->type == '2'); |
| 502 outsize = 0L; |
499 outsize = 0L; |
| 503 return 1; |
500 return 1; |
| 504 } |
501 } |
| 520 #endif |
517 #endif |
| 521 tmp = " created"; |
518 tmp = " created"; |
| 522 else |
519 else |
| 523 tmp = " ignored"; |
520 tmp = " ignored"; |
| 524 if (VERBOSE) |
521 if (VERBOSE) |
| 525 untar_verbose("%s\n", tmp); |
522 purple_debug_info("untar", "%s", tmp); |
| 526 return 1; |
523 return 1; |
| 527 } |
524 } |
| 528 |
525 |
| 529 /* if not a regular file, then skip it */ |
526 /* if not a regular file, then skip it */ |
| 530 if (!ISREGULAR(*tblk)) |
527 if (!ISREGULAR(*tblk)) |
| 531 { |
528 { |
| 532 if (VERBOSE) |
529 if (VERBOSE) |
| 533 untar_verbose(" ignored\n"); |
530 purple_debug_info("untar", " ignored"); |
| 534 outsize = 0L; |
531 outsize = 0L; |
| 535 return 1; |
532 return 1; |
| 536 } |
533 } |
| 537 |
534 |
| 538 /* print file statistics */ |
535 /* print file statistics */ |
| 539 if (VERBOSE) |
536 if (VERBOSE) |
| 540 { |
537 { |
| 541 untar_verbose(" (%ld byte%s, %ld tape block%s)\n", |
538 purple_debug_info("untar", " (%ld byte%s, %ld tape block%s)", |
| 542 outsize, |
539 outsize, |
| 543 outsize == 1 ? "" : "s", |
540 outsize == 1 ? "" : "s", |
| 544 (outsize + TSIZE - 1) / TSIZE, |
541 (outsize + TSIZE - 1) / TSIZE, |
| 545 (outsize > 0 && outsize <= TSIZE) ? "" : "s"); |
542 (outsize > 0 && outsize <= TSIZE) ? "" : "s"); |
| 546 } |
543 } |
| 575 /* open the archive */ |
572 /* open the archive */ |
| 576 inname = filename; |
573 inname = filename; |
| 577 infp = g_fopen(filename, "rb"); |
574 infp = g_fopen(filename, "rb"); |
| 578 if (!infp) |
575 if (!infp) |
| 579 { |
576 { |
| 580 untar_error("Error opening: %s\n", filename); |
577 purple_debug_error("untar", "Error opening: %s", filename); |
| 581 return 0; |
578 return 0; |
| 582 } |
579 } |
| 583 |
580 |
| 584 w_destdir = g_utf8_to_utf16(destdir, -1, NULL, NULL, NULL); |
581 w_destdir = g_utf8_to_utf16(destdir, -1, NULL, NULL, NULL); |
| 585 |
582 |
| 586 /* Set current directory */ |
583 /* Set current directory */ |
| 587 if(!GetCurrentDirectoryW(_MAX_PATH, curdir)) { |
584 if(!GetCurrentDirectoryW(_MAX_PATH, curdir)) { |
| 588 untar_error("Could not get current directory (error %lu).\n", GetLastError()); |
585 purple_debug_error("untar", "Could not get current directory (error %lu).", GetLastError()); |
| 589 fclose(infp); |
586 fclose(infp); |
| 590 return 0; |
587 return 0; |
| 591 } |
588 } |
| 592 if(!SetCurrentDirectoryW(w_destdir)) { |
589 if(!SetCurrentDirectoryW(w_destdir)) { |
| 593 untar_error("Could not set current directory to (error %lu): %s\n", GetLastError(), destdir); |
590 purple_debug_error("untar", "Could not set current directory to (error %lu): %s", GetLastError(), destdir); |
| 594 fclose(infp); |
591 fclose(infp); |
| 595 return 0; |
592 return 0; |
| 596 } else { |
593 } else { |
| 597 /* UNCOMPRESSED */ |
594 /* UNCOMPRESSED */ |
| 598 /* send each block to the untar_block() function */ |
595 /* send each block to the untar_block() function */ |
| 599 while (fread(slide, 1, TSIZE, infp) == TSIZE) { |
596 while (fread(slide, 1, TSIZE, infp) == TSIZE) { |
| 600 if(!untar_block(slide)) { |
597 if(!untar_block(slide)) { |
| 601 untar_error("untar failure: %s\n", filename); |
598 purple_debug_error("untar", "untar failure: %s", filename); |
| 602 fclose(infp); |
599 fclose(infp); |
| 603 ret=0; |
600 ret=0; |
| 604 } |
601 } |
| 605 } |
602 } |
| 606 if (outsize > 0 && ret) { |
603 if (outsize > 0 && ret) { |
| 607 untar_warning("Last file might be truncated!\n"); |
604 purple_debug_warning("untar", "Last file might be truncated!"); |
| 608 fclose(outfp); |
605 fclose(outfp); |
| 609 outfp = NULL; |
606 outfp = NULL; |
| 610 } |
607 } |
| 611 if(!SetCurrentDirectoryW(curdir)) { |
608 if(!SetCurrentDirectoryW(curdir)) { |
| 612 untar_error("Could not set current dir back to original (error %lu).\n", GetLastError()); |
609 purple_debug_error("untar", "Could not set current dir back to original (error %lu).", GetLastError()); |
| 613 ret=0; |
610 ret=0; |
| 614 } |
611 } |
| 615 } |
612 } |
| 616 |
613 |
| 617 g_free(w_destdir); |
614 g_free(w_destdir); |