Commit 4fa7b1eb606ecd749409a907ea7a47b39d48cb7b
1 parent
cd2bd667
Add remove_file and rename_file to QUtil
Showing
5 changed files
with
119 additions
and
5 deletions
ChangeLog
include/qpdf/QUtil.hh
| ... | ... | @@ -111,6 +111,13 @@ namespace QUtil |
| 111 | 111 | bool same_file(char const* name1, char const* name2); |
| 112 | 112 | |
| 113 | 113 | QPDF_DLL |
| 114 | + void remove_file(char const* path); | |
| 115 | + | |
| 116 | + // rename_file will overwrite newname if it exists | |
| 117 | + QPDF_DLL | |
| 118 | + void rename_file(char const* oldname, char const* newname); | |
| 119 | + | |
| 120 | + QPDF_DLL | |
| 114 | 121 | char* copy_string(std::string const&); |
| 115 | 122 | |
| 116 | 123 | // Returns lower-case hex-encoded version of the string, treating | ... | ... |
libqpdf/QUtil.cc
| ... | ... | @@ -394,15 +394,14 @@ QUtil::os_wrapper(std::string const& description, int status) |
| 394 | 394 | return status; |
| 395 | 395 | } |
| 396 | 396 | |
| 397 | -FILE* | |
| 398 | -QUtil::safe_fopen(char const* filename, char const* mode) | |
| 399 | -{ | |
| 400 | - FILE* f = 0; | |
| 401 | 397 | #ifdef _WIN32 |
| 398 | +static PointerHolder<wchar_t> | |
| 399 | +win_convert_filename(char const* filename) | |
| 400 | +{ | |
| 402 | 401 | // Convert the utf-8 encoded filename argument to wchar_t*. First, |
| 403 | 402 | // convert to utf16, then to wchar_t*. Note that u16 will start |
| 404 | 403 | // with the UTF16 marker, which we skip. |
| 405 | - std::string u16 = utf8_to_utf16(filename); | |
| 404 | + std::string u16 = QUtil::utf8_to_utf16(filename); | |
| 406 | 405 | size_t len = u16.length(); |
| 407 | 406 | size_t wlen = (len / 2) - 1; |
| 408 | 407 | PointerHolder<wchar_t> wfilenamep(true, new wchar_t[wlen + 1]); |
| ... | ... | @@ -415,6 +414,17 @@ QUtil::safe_fopen(char const* filename, char const* mode) |
| 415 | 414 | (static_cast<unsigned char>(u16.at(i)) << 8) + |
| 416 | 415 | static_cast<unsigned char>(u16.at(i+1))); |
| 417 | 416 | } |
| 417 | + return wfilenamep; | |
| 418 | +} | |
| 419 | +#endif | |
| 420 | + | |
| 421 | +FILE* | |
| 422 | +QUtil::safe_fopen(char const* filename, char const* mode) | |
| 423 | +{ | |
| 424 | + FILE* f = 0; | |
| 425 | +#ifdef _WIN32 | |
| 426 | + PointerHolder<wchar_t> wfilenamep = win_convert_filename(filename); | |
| 427 | + wchar_t* wfilename = wfilenamep.getPointer(); | |
| 418 | 428 | PointerHolder<wchar_t> wmodep(true, new wchar_t[strlen(mode) + 1]); |
| 419 | 429 | wchar_t* wmode = wmodep.getPointer(); |
| 420 | 430 | wmode[strlen(mode)] = 0; |
| ... | ... | @@ -537,6 +547,40 @@ QUtil::same_file(char const* name1, char const* name2) |
| 537 | 547 | return false; |
| 538 | 548 | } |
| 539 | 549 | |
| 550 | + | |
| 551 | +void | |
| 552 | +QUtil::remove_file(char const* path) | |
| 553 | +{ | |
| 554 | +#ifdef _WIN32 | |
| 555 | + PointerHolder<wchar_t> wpath = win_convert_filename(path); | |
| 556 | + os_wrapper(std::string("remove ") + path, _wunlink(wpath.getPointer())); | |
| 557 | +#else | |
| 558 | + os_wrapper(std::string("remove ") + path, unlink(path)); | |
| 559 | +#endif | |
| 560 | +} | |
| 561 | + | |
| 562 | +void | |
| 563 | +QUtil::rename_file(char const* oldname, char const* newname) | |
| 564 | +{ | |
| 565 | +#ifdef _WIN32 | |
| 566 | + try | |
| 567 | + { | |
| 568 | + remove_file(newname); | |
| 569 | + } | |
| 570 | + catch (QPDFSystemError&) | |
| 571 | + { | |
| 572 | + // ignore | |
| 573 | + } | |
| 574 | + PointerHolder<wchar_t> wold = win_convert_filename(oldname); | |
| 575 | + PointerHolder<wchar_t> wnew = win_convert_filename(newname); | |
| 576 | + os_wrapper(std::string("rename ") + oldname + " " + newname, | |
| 577 | + _wrename(wold.getPointer(), wnew.getPointer())); | |
| 578 | +#else | |
| 579 | + os_wrapper(std::string("rename ") + oldname + " " + newname, | |
| 580 | + rename(oldname, newname)); | |
| 581 | +#endif | |
| 582 | +} | |
| 583 | + | |
| 540 | 584 | char* |
| 541 | 585 | QUtil::copy_string(std::string const& str) |
| 542 | 586 | { | ... | ... |
libtests/qtest/qutil/qutil.out
libtests/qutil.cc
| ... | ... | @@ -457,6 +457,57 @@ void hex_encode_decode_test() |
| 457 | 457 | std::cout << "end hex encode/decode\n"; |
| 458 | 458 | } |
| 459 | 459 | |
| 460 | +static void assert_no_file(char const* filename) | |
| 461 | +{ | |
| 462 | + try | |
| 463 | + { | |
| 464 | + fclose(QUtil::safe_fopen(filename, "r")); | |
| 465 | + assert(false); | |
| 466 | + } | |
| 467 | + catch (QPDFSystemError&) | |
| 468 | + { | |
| 469 | + } | |
| 470 | +} | |
| 471 | + | |
| 472 | +void rename_delete_test() | |
| 473 | +{ | |
| 474 | + PointerHolder<char> buf; | |
| 475 | + size_t size = 0; | |
| 476 | + | |
| 477 | + try | |
| 478 | + { | |
| 479 | + QUtil::remove_file("old\xcf\x80"); | |
| 480 | + } | |
| 481 | + catch (QPDFSystemError&) | |
| 482 | + { | |
| 483 | + } | |
| 484 | + assert_no_file("old\xcf\x80"); | |
| 485 | + std::cout << "create file" << std::endl;; | |
| 486 | + FILE* f1 = QUtil::safe_fopen("old\xcf\x80", "w"); | |
| 487 | + fprintf(f1, "one"); | |
| 488 | + fclose(f1); | |
| 489 | + QUtil::read_file_into_memory("old\xcf\x80", buf, size); | |
| 490 | + assert(memcmp(buf.getPointer(), "one", 3) == 0); | |
| 491 | + std::cout << "rename file" << std::endl;; | |
| 492 | + QUtil::rename_file("old\xcf\x80", "old\xcf\x80.~tmp"); | |
| 493 | + QUtil::read_file_into_memory("old\xcf\x80.~tmp", buf, size); | |
| 494 | + assert(memcmp(buf.getPointer(), "one", 3) == 0); | |
| 495 | + assert_no_file("old\xcf\x80"); | |
| 496 | + std::cout << "create file" << std::endl;; | |
| 497 | + f1 = QUtil::safe_fopen("old\xcf\x80", "w"); | |
| 498 | + fprintf(f1, "two"); | |
| 499 | + fclose(f1); | |
| 500 | + std::cout << "rename over existing" << std::endl;; | |
| 501 | + QUtil::rename_file("old\xcf\x80", "old\xcf\x80.~tmp"); | |
| 502 | + QUtil::read_file_into_memory("old\xcf\x80.~tmp", buf, size); | |
| 503 | + assert(memcmp(buf.getPointer(), "two", 3) == 0); | |
| 504 | + assert_no_file("old\xcf\x80"); | |
| 505 | + std::cout << "delete file" << std::endl;; | |
| 506 | + QUtil::remove_file("old\xcf\x80.~tmp"); | |
| 507 | + assert_no_file("old\xcf\x80"); | |
| 508 | + assert_no_file("old\xcf\x80.~tmp"); | |
| 509 | +} | |
| 510 | + | |
| 460 | 511 | int main(int argc, char* argv[]) |
| 461 | 512 | { |
| 462 | 513 | try |
| ... | ... | @@ -485,6 +536,8 @@ int main(int argc, char* argv[]) |
| 485 | 536 | read_from_file_test(); |
| 486 | 537 | std::cout << "---- hex encode/decode" << std::endl; |
| 487 | 538 | hex_encode_decode_test(); |
| 539 | + std::cout << "---- rename/delete" << std::endl; | |
| 540 | + rename_delete_test(); | |
| 488 | 541 | } |
| 489 | 542 | catch (std::exception& e) |
| 490 | 543 | { | ... | ... |