CDirectory.cpp 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. #include "CAssetLoadException.h"
  2. #include "CDirectory.h"
  3. using namespace WallpaperEngine::Assets;
  4. CDirectory::CDirectory (const std::filesystem::path& basepath) {
  5. try {
  6. // resolve the path to it's real location
  7. std::filesystem::path finalpath = std::filesystem::canonical(basepath);
  8. std::filesystem::file_status status = std::filesystem::status (finalpath);
  9. if (!std::filesystem::exists (finalpath)) {
  10. throw CAssetLoadException (basepath, "Cannot find directory");
  11. }
  12. if (!std::filesystem::is_directory(status)) {
  13. throw CAssetLoadException (basepath, "Expected directory but found a file");
  14. }
  15. this->m_basepath = finalpath;
  16. } catch (std::bad_alloc&) {
  17. throw CAssetLoadException (basepath, "Cannot allocate memory");
  18. } catch (std::filesystem::filesystem_error& e) {
  19. throw CAssetLoadException (basepath, e.what ());
  20. }
  21. }
  22. std::filesystem::path CDirectory::resolveRealFile (const std::filesystem::path& filename) const {
  23. try {
  24. std::filesystem::path final = std::filesystem::canonical (this->m_basepath / filename);
  25. // first validate the path, so the message doesn't reflect if the file exists or not unless it's under the actual directory
  26. if (final.string ().find (this->m_basepath.string ()) != 0) {
  27. throw CAssetLoadException (filename, "File is not a child of the given directory");
  28. }
  29. std::filesystem::file_status status = std::filesystem::status (final);
  30. if (!std::filesystem::exists (final)) {
  31. throw CAssetLoadException (filename, "Cannot find file");
  32. }
  33. if (!std::filesystem::is_regular_file (status)) {
  34. throw CAssetLoadException (filename, "Expected file but found a directory");
  35. }
  36. return final;
  37. } catch (std::filesystem::filesystem_error& e) {
  38. throw CAssetLoadException (filename, e.what ());
  39. }
  40. }
  41. std::shared_ptr<const uint8_t[]> CDirectory::readFile (const std::filesystem::path& filename, uint32_t* length) const {
  42. std::filesystem::path final = this->resolveRealFile (filename);
  43. FILE* fp = fopen (final.c_str (), "rb");
  44. if (fp == nullptr) {
  45. throw CAssetLoadException (filename, "Cannot open file for reading");
  46. }
  47. try {
  48. // go to the end, get the position and return to the beginning
  49. fseek (fp, 0, SEEK_END);
  50. const long size = ftell (fp);
  51. fseek (fp, 0, SEEK_SET);
  52. // now read the whole file
  53. std::shared_ptr<uint8_t[]> contents = std::shared_ptr<uint8_t[]>(new uint8_t [size]);
  54. if (fread (contents.get(), size, 1, fp) != 1) {
  55. throw CAssetLoadException (filename, "Unexpected error when reading the file");
  56. }
  57. if (length != nullptr) {
  58. *length = size;
  59. }
  60. fclose (fp);
  61. return contents;
  62. } catch (std::filesystem::filesystem_error& e) {
  63. fclose (fp);
  64. throw CAssetLoadException (filename, e.what ());
  65. }
  66. }