From: Arkadiusz Pietraszek Date: Thu, 19 Apr 2018 09:23:58 +0000 (+0200) Subject: [Filesystem] Filesystem handling methods implementation. X-Git-Tag: submit/tizen/20180518.121229~6^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F54%2F176454%2F12;p=platform%2Fcore%2Fapi%2Fwebapi-plugins.git [Filesystem] Filesystem handling methods implementation. ACR: http://suprem.sec.samsung.net/jira/browse/TWDAPI-121 Change-Id: I84f383a2f5a8c56a9b21ad2bbc3cc872ee86e427 Signed-off-by: Szymon Jastrzebski Signed-off-by: Arkadiusz Pietraszek Signed-off-by: Jakub Skowron Signed-off-by: Pawel Wasowski --- diff --git a/src/filesystem/filesystem_instance.cc b/src/filesystem/filesystem_instance.cc index 81c635c8..c8faf71c 100644 --- a/src/filesystem/filesystem_instance.cc +++ b/src/filesystem/filesystem_instance.cc @@ -126,14 +126,16 @@ FilesystemInstance::Worker::~Worker() { LoggerE("Finally should never throw"); } } -}; +} FilesystemInstance::FilesystemInstance() { ScopeLogger(); + using std::placeholders::_1; using std::placeholders::_2; #define REGISTER_SYNC(c, x) RegisterSyncHandler(c, std::bind(&FilesystemInstance::x, this, _1, _2)); + REGISTER_SYNC("File_stat", FileStat); REGISTER_SYNC("File_statSync", FileStatSync); REGISTER_SYNC("File_createSync", FileCreateSync); @@ -154,6 +156,21 @@ FilesystemInstance::FilesystemInstance() { REGISTER_SYNC("File_removeDirectory", RemoveDirectory); REGISTER_SYNC("File_copyTo", CopyTo); REGISTER_SYNC("FileSystemManager_getCanonicalPath", FileSystemManagerGetCanonicalPath); + + REGISTER_SYNC("FileSystemManager_createDirectory", FileSystemManagerCreateDirectory); + REGISTER_SYNC("FileSystemManager_deleteFile", FileSystemManagerDeleteFile); + REGISTER_SYNC("FileSystemManager_deleteDirectory", FileSystemManagerDeleteDirectory); + REGISTER_SYNC("FileSystemManager_copyFile", FileSystemManagerCopyFile); + REGISTER_SYNC("FileSystemManager_copyDirectory", FileSystemManagerCopyDirectory); + REGISTER_SYNC("FileSystemManager_moveFile", FileSystemManagerMoveFile); + REGISTER_SYNC("FileSystemManager_moveDirectory", FileSystemManagerMoveDirectory); + REGISTER_SYNC("FileSystemManager_rename", FileSystemManagerRename); + REGISTER_SYNC("FileSystemManager_listDirectory", FileSystemManagerListDirectory); + REGISTER_SYNC("FileSystemManager_isFile", FileSystemManagerIsFile); + REGISTER_SYNC("FileSystemManager_isDirectory", FileSystemManagerIsDirectory); + REGISTER_SYNC("FileSystemManager_pathExists", FileSystemManagerPathExists); + REGISTER_SYNC("FileSystemManager_getLimits", FileSystemManagerGetLimits); + #undef REGISTER_SYNC FilesystemManager::GetInstance().AddListener(this); } @@ -300,7 +317,7 @@ static std::vector read_file(std::string path, long offset = 0, FILE* file = std::fopen(path.c_str(), "r"); if (!file) { - std::string err_msg = std::string("cannot open file to read") + strerror(errno); + std::string err_msg = std::string("Cannot open file to read. ") + strerror(errno); throw std::system_error{errno, std::generic_category(), err_msg}; } @@ -312,7 +329,7 @@ static std::vector read_file(std::string path, long offset = 0, }; if (0 != offset && 0 != std::fseek(file, offset, SEEK_SET)) { - std::string err_msg = std::string("cannot perform seek") + strerror(errno); + std::string err_msg = std::string("Cannot perform seek. ") + strerror(errno); throw std::system_error{errno, std::generic_category(), err_msg}; } @@ -342,7 +359,7 @@ static std::vector read_file(FILE* file, std::size_t length /*= NP data_p += std::fread(data_p, 1, end_p - data_p, file); if (std::ferror(file)) { - std::string err_msg = std::string("error during file read") + strerror(errno); + std::string err_msg = std::string("Error during file read. ") + strerror(errno); throw std::runtime_error(err_msg); } @@ -366,13 +383,13 @@ void write_file(const std::uint8_t* data, std::size_t len, FILE* file) { data_p += fwrite(data_p, 1, end_p - data_p, file); if (std::ferror(file)) { - std::string err_msg = std::string("error during file write") + strerror(errno); + std::string err_msg = std::string("Error during file write. ") + strerror(errno); throw std::runtime_error(err_msg); } } if (std::fflush(file)) { - std::string err_msg = std::string("error during file write") + strerror(errno); + std::string err_msg = std::string("Error during file write. ") + strerror(errno); throw std::runtime_error(err_msg); } } @@ -387,7 +404,7 @@ void write_file(const std::uint8_t* data, std::size_t len, std::string path, lon FILE* file = std::fopen(path.c_str(), mode); if (!file) { - std::string err_msg = std::string("cannot open file to write") + strerror(errno); + std::string err_msg = std::string("Cannot open file to write. ") + strerror(errno); throw std::runtime_error(err_msg); } @@ -399,7 +416,7 @@ void write_file(const std::uint8_t* data, std::size_t len, std::string path, lon }; if (offset != 0 && std::fseek(file, offset, SEEK_SET) != 0) { - std::string err_msg = std::string("cannot perform seek") + strerror(errno); + std::string err_msg = std::string("Cannot perform seek. ") + strerror(errno); throw std::system_error{errno, std::generic_category(), err_msg}; } @@ -1001,6 +1018,490 @@ void FilesystemInstance::FileSystemManagerGetCanonicalPath(const picojson::value FilesystemManager::GetInstance().GetCanonicalPath(path, onSuccess, onError); } +void FilesystemInstance::FileSystemManagerCreateDirectory(const picojson::value& args, + picojson::object& out) { + ScopeLogger(); + CHECK_PRIVILEGE_ACCESS(kPrivilegeFilesystemWrite, &out); + + double callback_id = args.get("callbackId").get(); + const std::string& path = args.get("path").get(); + bool make_parents = args.get("makeParents").get(); + + this->worker.add_job([this, callback_id, path, make_parents] { + picojson::value response = picojson::value(picojson::object()); + picojson::object& obj = response.get(); + obj["callbackId"] = picojson::value(callback_id); + + try { + FilesystemUtils::Mkdir(path, make_parents); + ReportSuccess(obj); + } catch (const std::system_error& e) { + FilesystemUtils::TranslateException(e, obj); + } + this->PostMessage(response.serialize().c_str()); + }); + + ReportSuccess(out); +} + +void FilesystemInstance::FileSystemManagerDeleteFile(const picojson::value& args, + picojson::object& out) { + ScopeLogger(); + CHECK_PRIVILEGE_ACCESS(kPrivilegeFilesystemWrite, &out); + + double callback_id = args.get("callbackId").get(); + const std::string& path = args.get("path").get(); + + this->worker.add_job([this, callback_id, path] { + picojson::value response = picojson::value(picojson::object()); + picojson::object& obj = response.get(); + obj["callbackId"] = picojson::value(callback_id); + + try { + FilesystemUtils::Unlink(path); + ReportSuccess(obj); + } catch (const std::system_error& e) { + FilesystemUtils::TranslateException(e, obj); + } + this->PostMessage(response.serialize().c_str()); + }); + + ReportSuccess(out); +} + +void FilesystemInstance::FileSystemManagerDeleteDirectory(const picojson::value& args, + picojson::object& out) { + ScopeLogger(); + CHECK_PRIVILEGE_ACCESS(kPrivilegeFilesystemWrite, &out); + + double callback_id = args.get("callbackId").get(); + const std::string& path = args.get("path").get(); + bool recursive = args.get("recursive").get(); + + this->worker.add_job([this, callback_id, path, recursive] { + ScopeLogger(); + picojson::value response = picojson::value(picojson::object()); + picojson::object& obj = response.get(); + obj["callbackId"] = picojson::value(callback_id); + + try { + struct stat buf {}; + if (!FilesystemUtils::CheckIfExists(path, &buf) || !FilesystemUtils::CheckIfDir(buf)) { + LogAndReportError(NotFoundException("Given path does not point to directory."), obj); + return; + } + if (recursive) { + FilesystemUtils::RemoveDirectoryRecursively(path); + } else { + FilesystemUtils::RemoveDirectory(path); + } + ReportSuccess(obj); + } catch (const std::system_error& e) { + FilesystemUtils::TranslateException(e, obj); + } + this->PostMessage(response.serialize().c_str()); + }); + + ReportSuccess(out); +} + +void FilesystemInstance::FileSystemManagerCopyFile(const picojson::value& args, + picojson::object& out) { + // TODO: currently does not create file with the same name as src if dest is a directory + ScopeLogger(); + CHECK_PRIVILEGE_ACCESS(kPrivilegeFilesystemWrite, &out); + CHECK_PRIVILEGE_ACCESS(kPrivilegeFilesystemRead, &out); + + double callback_id = args.get("callbackId").get(); + const std::string& path = args.get("path").get(); + const std::string& destination_path = args.get("destinationPath").get(); + bool overwrite = args.get("overwrite").get(); + + this->worker.add_job([this, callback_id, path, destination_path, overwrite] { + picojson::value response = picojson::value(picojson::object()); + picojson::object& obj = response.get(); + obj["callbackId"] = picojson::value(callback_id); + + try { + struct stat buf {}; + if (!FilesystemUtils::CheckIfExists(path, &buf) || !FilesystemUtils::CheckIfFile(buf)) { + LogAndReportError(NotFoundException("Given path does not point to file."), obj); + return; + } + buf = {}; + if (!FilesystemUtils::CheckIfExists(destination_path, &buf) || + !FilesystemUtils::CheckIfDir(buf)) { + LogAndReportError(NotFoundException("Given path does not point to directory."), obj); + return; + } + + buf = {}; + std::string new_path = destination_path + '/' + FilesystemUtils::PosixBasename(path); + if (!overwrite && FilesystemUtils::CheckIfExists(new_path, &buf)) { + LogAndReportError(IOException("File or directory with conflicting name already exists."), + obj); + return; + } + FilesystemUtils::CopyFile(path, destination_path, overwrite); + ReportSuccess(obj); + } catch (const std::system_error& e) { + FilesystemUtils::TranslateException(e, obj); + } + this->PostMessage(response.serialize().c_str()); + }); + + ReportSuccess(out); +} + +void FilesystemInstance::FileSystemManagerCopyDirectory(const picojson::value& args, + picojson::object& out) { + ScopeLogger(); + CHECK_PRIVILEGE_ACCESS(kPrivilegeFilesystemRead, &out); + CHECK_PRIVILEGE_ACCESS(kPrivilegeFilesystemWrite, &out); + const std::string& path = args.get("path").get(); + const std::string& destination_path = args.get("destinationPath").get(); + double callback_id = args.get("callbackId").get(); + bool overwrite = args.get("overwrite").get(); + + this->worker.add_job([this, callback_id, path, destination_path, overwrite] { + ScopeLogger(); + picojson::value response = picojson::value(picojson::object()); + picojson::object& obj = response.get(); + obj["callbackId"] = picojson::value(callback_id); + + try { + struct stat buf {}; + if (!FilesystemUtils::CheckIfExists(path, &buf) || !FilesystemUtils::CheckIfDir(buf)) { + LogAndReportError(NotFoundException("Given path does not point to directory."), obj); + return; + } + buf = {}; + if (!FilesystemUtils::CheckIfExists(destination_path, &buf) || + !FilesystemUtils::CheckIfDir(buf)) { + LogAndReportError(NotFoundException("Given path does not point to directory."), obj); + return; + } + std::string new_path = destination_path + '/' + FilesystemUtils::PosixBasename(path); + buf = {}; + if (FilesystemUtils::CheckIfExists(new_path, &buf) && !FilesystemUtils::CheckIfDir(buf)) { + LogAndReportError(IOException("File with conflicting name already exists."), obj); + return; + } + FilesystemUtils::CopyDirectory(path, destination_path, overwrite); + ReportSuccess(obj); + } catch (const std::system_error& e) { + FilesystemUtils::TranslateException(e, obj); + } + this->PostMessage(response.serialize().c_str()); + }); + + ReportSuccess(out); +} + +void FilesystemInstance::FileSystemManagerMoveFile(const picojson::value& args, + picojson::object& out) { + ScopeLogger(); + CHECK_PRIVILEGE_ACCESS(kPrivilegeFilesystemRead, &out); + CHECK_PRIVILEGE_ACCESS(kPrivilegeFilesystemWrite, &out); + + const std::string& path = args.get("path").get(); + const std::string& destination_path = args.get("destinationPath").get(); + double callback_id = args.get("callbackId").get(); + bool overwrite = args.get("overwrite").get(); + + this->worker.add_job([this, callback_id, path, destination_path, overwrite] { + ScopeLogger(); + picojson::value response = picojson::value(picojson::object()); + picojson::object& obj = response.get(); + obj["callbackId"] = picojson::value(callback_id); + + try { + struct stat buf {}; + if (!FilesystemUtils::CheckIfExists(path, &buf) || !FilesystemUtils::CheckIfFile(buf)) { + LogAndReportError(NotFoundException("Given path does not point to file."), obj); + return; + } + buf = {}; + if (!FilesystemUtils::CheckIfExists(destination_path, &buf) || + !FilesystemUtils::CheckIfDir(buf)) { + LogAndReportError(NotFoundException("Given path does not point to directory."), obj); + return; + } + + buf = {}; + std::string new_path = destination_path + '/' + FilesystemUtils::PosixBasename(path); + if (!overwrite && FilesystemUtils::CheckIfExists(new_path, &buf)) { + LogAndReportError(IOException("File or directory with conflicting name already exists."), + obj); + return; + } + FilesystemUtils::MoveFile(path, new_path, overwrite); + ReportSuccess(obj); + } catch (const std::system_error& e) { + FilesystemUtils::TranslateException(e, obj); + } + this->PostMessage(response.serialize().c_str()); + }); + + ReportSuccess(out); +} + +void FilesystemInstance::FileSystemManagerMoveDirectory(const picojson::value& args, + picojson::object& out) { + ScopeLogger(); + + CHECK_PRIVILEGE_ACCESS(kPrivilegeFilesystemRead, &out); + CHECK_PRIVILEGE_ACCESS(kPrivilegeFilesystemWrite, &out); + double callback_id = args.get("callbackId").get(); + const std::string& path = args.get("path").get(); + const std::string& destination_path = args.get("destinationPath").get(); + bool overwrite = args.get("overwrite").get(); + + this->worker.add_job([this, callback_id, path, destination_path, overwrite] { + picojson::value response = picojson::value(picojson::object()); + picojson::object& obj = response.get(); + obj["callbackId"] = picojson::value(callback_id); + + try { + struct stat buf {}; + if (!FilesystemUtils::CheckIfExists(path, &buf) || !FilesystemUtils::CheckIfDir(buf)) { + LogAndReportError(NotFoundException("Given path does not point to directory."), obj); + return; + } + buf = {}; + if (!FilesystemUtils::CheckIfExists(destination_path, &buf) || + !FilesystemUtils::CheckIfDir(buf)) { + LogAndReportError(NotFoundException("Given path does not point to directory."), obj); + return; + } + buf = {}; + std::string new_path = destination_path + '/' + FilesystemUtils::PosixBasename(path); + if (FilesystemUtils::CheckIfExists(new_path, &buf) && !FilesystemUtils::CheckIfDir(buf)) { + LogAndReportError(IOException("File or directory with conflicting name already exists."), obj); + return; + } + FilesystemUtils::MoveDirectory(path, destination_path, overwrite); + ReportSuccess(obj); + } catch (const std::system_error& e) { + FilesystemUtils::TranslateException(e, obj); + } + this->PostMessage(response.serialize().c_str()); + }); + + ReportSuccess(out); +} + +void FilesystemInstance::FileSystemManagerRename(const picojson::value& args, + picojson::object& out) { + ScopeLogger(); + CHECK_PRIVILEGE_ACCESS(kPrivilegeFilesystemWrite, &out); + const std::string& path = args.get("path").get(); + double callback_id = args.get("callbackId").get(); + const std::string& new_name = args.get("newName").get(); + + this->worker.add_job([this, callback_id, new_name, path] { + ScopeLogger(); + picojson::value response = picojson::value(picojson::object()); + picojson::object& obj = response.get(); + obj["callbackId"] = picojson::value(callback_id); + + try { + struct stat buf {}; + bool exists = FilesystemUtils::CheckIfExists(path, &buf); + if (!exists) { + LogAndReportError(NotFoundException("Given path does not point to file or directory."), + obj); + return; + } + std::string new_path{FilesystemUtils::Dirname(path) + "/" + new_name}; + buf = {}; + exists = FilesystemUtils::CheckIfExists(new_path, &buf); + if (exists) { + LogAndReportError(IOException("File or directory with conflicting name already exists"), + obj); + return; + } + FilesystemUtils::Rename(path, new_path); + ReportSuccess(obj); + } catch (const std::system_error& e) { + FilesystemUtils::TranslateException(e, obj); + } + this->PostMessage(response.serialize().c_str()); + }); + + ReportSuccess(out); +} + +void FilterResult(std::vector& names, std::vector& types, bool is_type, + unsigned char type) { + int i = (int)names.size() - 1; + + while (i >= 0) { + if (is_type ? type != types[i] : type == types[i]) { + names.erase(names.begin() + i); + } + i--; + } +} + +void FilesystemInstance::FileSystemManagerListDirectory(const picojson::value& args, + picojson::object& out) { + ScopeLogger(); + CHECK_PRIVILEGE_ACCESS(kPrivilegeFilesystemRead, &out); + + double callback_id = args.get("callbackId").get(); + const std::string& path = args.get("path").get(); + const picojson::object& filter = args.get("filter").get(); + + this->worker.add_job([this, callback_id, path, filter] { + ScopeLogger(); + picojson::value response = picojson::value(picojson::object()); + picojson::object& obj = response.get(); + obj["callbackId"] = picojson::value(callback_id); + + try { + std::vector names; + { + std::vector types; + FilesystemUtils::ListDirectory(path, [&](const char* name, unsigned char type) { + names.push_back(name); + types.push_back(type); + }); + + auto it = filter.find("isFile"); + if (filter.end() != it) { + FilterResult(names, types, it->second.get(), DT_REG); + } + + it = filter.find("isDirectory"); + if (filter.end() != it) { + FilterResult(names, types, it->second.get(), DT_DIR); + } + } + + auto start_modified_it = filter.find("startModified"), + end_modified_it = filter.find("endModified"), + start_created_it = filter.find("startCreated"), + end_created_it = filter.find("endCreated"); + if (filter.end() != start_modified_it || filter.end() != end_modified_it || + filter.end() != start_created_it || filter.end() != end_created_it) { + auto name_iterator = names.begin(); + while (name_iterator != names.end()) { + struct ::stat buf; + std::string path_with_name = path + std::string("/") + std::string(*name_iterator); + int status = ::stat(path_with_name.c_str(), &buf); + if (status != 0) { + throw std::system_error{errno, std::generic_category(), + "Failed to get last modification date of a file"}; + } + if (filter.end() != start_modified_it && + (buf.st_mtime < start_modified_it->second.get())) { + name_iterator = names.erase(name_iterator); + continue; + } + if (filter.end() != end_modified_it && + (buf.st_mtime > end_modified_it->second.get())) { + name_iterator = names.erase(name_iterator); + continue; + } + if (filter.end() != start_created_it && + (buf.st_ctime < start_created_it->second.get())) { + name_iterator = names.erase(name_iterator); + continue; + } + if (filter.end() != end_created_it && + (buf.st_ctime > end_created_it->second.get())) { + name_iterator = names.erase(name_iterator); + continue; + } + name_iterator++; + } + } + + picojson::value value{picojson::array_type, true}; + picojson::array& names_array = value.get(); + + for (unsigned int i = 0; i < names.size(); ++i) { + names_array.push_back(picojson::value(names[i])); + } + + ReportSuccess(value, obj); + } catch (const std::system_error& e) { + FilesystemUtils::TranslateException(e, obj); + } + this->PostMessage(response.serialize().c_str()); + }); + + ReportSuccess(out); +} + +void FilesystemInstance::FileSystemManagerIsFile(const picojson::value& args, + picojson::object& out) { + ScopeLogger(); + CHECK_PRIVILEGE_ACCESS(kPrivilegeFilesystemRead, &out); + const std::string& path = args.get("path").get(); + picojson::value is_file{}; + try { + struct stat buf {}; + bool exists = FilesystemUtils::CheckIfExists(path, &buf); + if (!exists) { + LogAndReportError(NotFoundException("Given path does not point to file."), out); + return; + } + is_file = picojson::value{FilesystemUtils::CheckIfFile(buf)}; + } catch (const std::system_error& e) { + FilesystemUtils::TranslateException(e, out); + } + ReportSuccess(is_file, out); +} + +void FilesystemInstance::FileSystemManagerIsDirectory(const picojson::value& args, + picojson::object& out) { + ScopeLogger(); + CHECK_PRIVILEGE_ACCESS(kPrivilegeFilesystemRead, &out); + const std::string& path = args.get("path").get(); + picojson::value is_directory{}; + try { + struct stat buf {}; + bool exists = FilesystemUtils::CheckIfExists(path, &buf); + if (!exists) { + LogAndReportError(NotFoundException("Given path does not point to directory."), out); + return; + } + is_directory = picojson::value{FilesystemUtils::CheckIfDir(buf)}; + } catch (const std::system_error& e) { + FilesystemUtils::TranslateException(e, out); + } + ReportSuccess(is_directory, out); +} + +void FilesystemInstance::FileSystemManagerPathExists(const picojson::value& args, + picojson::object& out) { + ScopeLogger(); + CHECK_PRIVILEGE_ACCESS(kPrivilegeFilesystemRead, &out); + const std::string& path = args.get("path").get(); + picojson::value does_file_exist = picojson::value{true}; + try { + struct stat buf {}; + bool exists = FilesystemUtils::CheckIfExists(path, &buf); + if (!exists) { + does_file_exist = picojson::value{false}; + } + } catch (const std::system_error& e) { + FilesystemUtils::TranslateException(e, out); + } + ReportSuccess(does_file_exist, out); +} + +void FilesystemInstance::FileSystemManagerGetLimits(const picojson::value& args, + picojson::object& out) { + ScopeLogger(); + picojson::value response = + picojson::value{picojson::array{picojson::value{static_cast(NAME_MAX)}, + picojson::value{static_cast(PATH_MAX)}}}; + ReportSuccess(response, out); +} + #undef CHECK_EXIST } // namespace filesystem diff --git a/src/filesystem/filesystem_instance.h b/src/filesystem/filesystem_instance.h index d5dc284e..dbe9ee76 100644 --- a/src/filesystem/filesystem_instance.h +++ b/src/filesystem/filesystem_instance.h @@ -129,6 +129,21 @@ class FilesystemInstance : public common::ParsedInstance, FilesystemStateChangeL void onFilesystemStateChangeSuccessCallback(const common::Storage& storage); void PrepareError(const FilesystemError& error, picojson::object& out); void FileSystemManagerGetCanonicalPath(const picojson::value& args, picojson::object& out); + + void FileSystemManagerCreateDirectory(const picojson::value& args, picojson::object& out); + void FileSystemManagerDeleteFile(const picojson::value& args, picojson::object& out); + void FileSystemManagerDeleteDirectory(const picojson::value& args, picojson::object& out); + void FileSystemManagerCopyFile(const picojson::value& args, picojson::object& out); + void FileSystemManagerCopyDirectory(const picojson::value& args, picojson::object& out); + void FileSystemManagerMoveFile(const picojson::value& args, picojson::object& out); + void FileSystemManagerMoveDirectory(const picojson::value& args, picojson::object& out); + void FileSystemManagerRename(const picojson::value& args, picojson::object& out); + void FileSystemManagerListDirectory(const picojson::value& args, picojson::object& out); + void FileSystemManagerIsFile(const picojson::value& args, picojson::object& out); + void FileSystemManagerIsDirectory(const picojson::value& args, picojson::object& out); + void FileSystemManagerPathExists(const picojson::value& args, picojson::object& out); + void FileSystemManagerToURI(const picojson::value& args, picojson::object& out); + void FileSystemManagerGetLimits(const picojson::value& args, picojson::object& out); }; } // namespace filesystem