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);
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);
}
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};
}
};
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};
}
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);
}
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);
}
}
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);
}
};
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};
}
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<double>();
+ const std::string& path = args.get("path").get<std::string>();
+ bool make_parents = args.get("makeParents").get<bool>();
+
+ this->worker.add_job([this, callback_id, path, make_parents] {
+ picojson::value response = picojson::value(picojson::object());
+ picojson::object& obj = response.get<picojson::object>();
+ 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<double>();
+ const std::string& path = args.get("path").get<std::string>();
+
+ this->worker.add_job([this, callback_id, path] {
+ picojson::value response = picojson::value(picojson::object());
+ picojson::object& obj = response.get<picojson::object>();
+ 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<double>();
+ const std::string& path = args.get("path").get<std::string>();
+ bool recursive = args.get("recursive").get<bool>();
+
+ this->worker.add_job([this, callback_id, path, recursive] {
+ ScopeLogger();
+ picojson::value response = picojson::value(picojson::object());
+ picojson::object& obj = response.get<picojson::object>();
+ 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<double>();
+ const std::string& path = args.get("path").get<std::string>();
+ const std::string& destination_path = args.get("destinationPath").get<std::string>();
+ bool overwrite = args.get("overwrite").get<bool>();
+
+ this->worker.add_job([this, callback_id, path, destination_path, overwrite] {
+ picojson::value response = picojson::value(picojson::object());
+ picojson::object& obj = response.get<picojson::object>();
+ 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<std::string>();
+ const std::string& destination_path = args.get("destinationPath").get<std::string>();
+ double callback_id = args.get("callbackId").get<double>();
+ bool overwrite = args.get("overwrite").get<bool>();
+
+ this->worker.add_job([this, callback_id, path, destination_path, overwrite] {
+ ScopeLogger();
+ picojson::value response = picojson::value(picojson::object());
+ picojson::object& obj = response.get<picojson::object>();
+ 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<std::string>();
+ const std::string& destination_path = args.get("destinationPath").get<std::string>();
+ double callback_id = args.get("callbackId").get<double>();
+ bool overwrite = args.get("overwrite").get<bool>();
+
+ this->worker.add_job([this, callback_id, path, destination_path, overwrite] {
+ ScopeLogger();
+ picojson::value response = picojson::value(picojson::object());
+ picojson::object& obj = response.get<picojson::object>();
+ 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<double>();
+ const std::string& path = args.get("path").get<std::string>();
+ const std::string& destination_path = args.get("destinationPath").get<std::string>();
+ bool overwrite = args.get("overwrite").get<bool>();
+
+ this->worker.add_job([this, callback_id, path, destination_path, overwrite] {
+ picojson::value response = picojson::value(picojson::object());
+ picojson::object& obj = response.get<picojson::object>();
+ 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<std::string>();
+ double callback_id = args.get("callbackId").get<double>();
+ const std::string& new_name = args.get("newName").get<std::string>();
+
+ this->worker.add_job([this, callback_id, new_name, path] {
+ ScopeLogger();
+ picojson::value response = picojson::value(picojson::object());
+ picojson::object& obj = response.get<picojson::object>();
+ 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<const char*>& names, std::vector<unsigned char>& 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<double>();
+ const std::string& path = args.get("path").get<std::string>();
+ const picojson::object& filter = args.get("filter").get<picojson::object>();
+
+ this->worker.add_job([this, callback_id, path, filter] {
+ ScopeLogger();
+ picojson::value response = picojson::value(picojson::object());
+ picojson::object& obj = response.get<picojson::object>();
+ obj["callbackId"] = picojson::value(callback_id);
+
+ try {
+ std::vector<const char*> names;
+ {
+ std::vector<unsigned char> 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<bool>(), DT_REG);
+ }
+
+ it = filter.find("isDirectory");
+ if (filter.end() != it) {
+ FilterResult(names, types, it->second.get<bool>(), 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<double>())) {
+ name_iterator = names.erase(name_iterator);
+ continue;
+ }
+ if (filter.end() != end_modified_it &&
+ (buf.st_mtime > end_modified_it->second.get<double>())) {
+ name_iterator = names.erase(name_iterator);
+ continue;
+ }
+ if (filter.end() != start_created_it &&
+ (buf.st_ctime < start_created_it->second.get<double>())) {
+ name_iterator = names.erase(name_iterator);
+ continue;
+ }
+ if (filter.end() != end_created_it &&
+ (buf.st_ctime > end_created_it->second.get<double>())) {
+ name_iterator = names.erase(name_iterator);
+ continue;
+ }
+ name_iterator++;
+ }
+ }
+
+ picojson::value value{picojson::array_type, true};
+ picojson::array& names_array = value.get<picojson::array>();
+
+ 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<std::string>();
+ 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<std::string>();
+ 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<std::string>();
+ 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<double>(NAME_MAX)},
+ picojson::value{static_cast<double>(PATH_MAX)}}};
+ ReportSuccess(response, out);
+}
+
#undef CHECK_EXIST
} // namespace filesystem