Commit 4fa7b1eb606ecd749409a907ea7a47b39d48cb7b

Authored by Jay Berkenbilt
1 parent cd2bd667

Add remove_file and rename_file to QUtil

ChangeLog
  1 +2019-08-31 Jay Berkenbilt <ejb@ql.org>
  2 +
  3 + * Add methods rename_file and remove_file to QUtil.
  4 +
1 2019-08-24 Jay Berkenbilt <ejb@ql.org> 5 2019-08-24 Jay Berkenbilt <ejb@ql.org>
2 6
3 * Add QPDF::userPasswordMatched() and QPDF::ownerPasswordMatched() 7 * Add QPDF::userPasswordMatched() and QPDF::ownerPasswordMatched()
include/qpdf/QUtil.hh
@@ -111,6 +111,13 @@ namespace QUtil @@ -111,6 +111,13 @@ namespace QUtil
111 bool same_file(char const* name1, char const* name2); 111 bool same_file(char const* name1, char const* name2);
112 112
113 QPDF_DLL 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 char* copy_string(std::string const&); 121 char* copy_string(std::string const&);
115 122
116 // Returns lower-case hex-encoded version of the string, treating 123 // Returns lower-case hex-encoded version of the string, treating
libqpdf/QUtil.cc
@@ -394,15 +394,14 @@ QUtil::os_wrapper(std::string const&amp; description, int status) @@ -394,15 +394,14 @@ QUtil::os_wrapper(std::string const&amp; description, int status)
394 return status; 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 #ifdef _WIN32 397 #ifdef _WIN32
  398 +static PointerHolder<wchar_t>
  399 +win_convert_filename(char const* filename)
  400 +{
402 // Convert the utf-8 encoded filename argument to wchar_t*. First, 401 // Convert the utf-8 encoded filename argument to wchar_t*. First,
403 // convert to utf16, then to wchar_t*. Note that u16 will start 402 // convert to utf16, then to wchar_t*. Note that u16 will start
404 // with the UTF16 marker, which we skip. 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 size_t len = u16.length(); 405 size_t len = u16.length();
407 size_t wlen = (len / 2) - 1; 406 size_t wlen = (len / 2) - 1;
408 PointerHolder<wchar_t> wfilenamep(true, new wchar_t[wlen + 1]); 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,6 +414,17 @@ QUtil::safe_fopen(char const* filename, char const* mode)
415 (static_cast<unsigned char>(u16.at(i)) << 8) + 414 (static_cast<unsigned char>(u16.at(i)) << 8) +
416 static_cast<unsigned char>(u16.at(i+1))); 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 PointerHolder<wchar_t> wmodep(true, new wchar_t[strlen(mode) + 1]); 428 PointerHolder<wchar_t> wmodep(true, new wchar_t[strlen(mode) + 1]);
419 wchar_t* wmode = wmodep.getPointer(); 429 wchar_t* wmode = wmodep.getPointer();
420 wmode[strlen(mode)] = 0; 430 wmode[strlen(mode)] = 0;
@@ -537,6 +547,40 @@ QUtil::same_file(char const* name1, char const* name2) @@ -537,6 +547,40 @@ QUtil::same_file(char const* name1, char const* name2)
537 return false; 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 char* 584 char*
541 QUtil::copy_string(std::string const& str) 585 QUtil::copy_string(std::string const& str)
542 { 586 {
libtests/qtest/qutil/qutil.out
@@ -99,3 +99,9 @@ read 24652 bytes @@ -99,3 +99,9 @@ read 24652 bytes
99 ---- hex encode/decode 99 ---- hex encode/decode
100 begin hex encode/decode 100 begin hex encode/decode
101 end hex encode/decode 101 end hex encode/decode
  102 +---- rename/delete
  103 +create file
  104 +rename file
  105 +create file
  106 +rename over existing
  107 +delete file
libtests/qutil.cc
@@ -457,6 +457,57 @@ void hex_encode_decode_test() @@ -457,6 +457,57 @@ void hex_encode_decode_test()
457 std::cout << "end hex encode/decode\n"; 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 int main(int argc, char* argv[]) 511 int main(int argc, char* argv[])
461 { 512 {
462 try 513 try
@@ -485,6 +536,8 @@ int main(int argc, char* argv[]) @@ -485,6 +536,8 @@ int main(int argc, char* argv[])
485 read_from_file_test(); 536 read_from_file_test();
486 std::cout << "---- hex encode/decode" << std::endl; 537 std::cout << "---- hex encode/decode" << std::endl;
487 hex_encode_decode_test(); 538 hex_encode_decode_test();
  539 + std::cout << "---- rename/delete" << std::endl;
  540 + rename_delete_test();
488 } 541 }
489 catch (std::exception& e) 542 catch (std::exception& e)
490 { 543 {