diff options
author | bruvzg <7645683+bruvzg@users.noreply.github.com> | 2022-04-12 10:12:40 +0300 |
---|---|---|
committer | bruvzg <7645683+bruvzg@users.noreply.github.com> | 2022-04-12 10:54:39 +0300 |
commit | 4bf99f4af2c4918883c4382ead7de275fae21eea (patch) | |
tree | e741cea7e9395dcffeaa986f34e19819564356fb | |
parent | 5974e1432ef7941a5e29f8723dec85aa45505963 (diff) |
Narrow FileAccess scope to prevent deadlocks.
29 files changed, 488 insertions, 436 deletions
diff --git a/core/core_bind.cpp b/core/core_bind.cpp index 7d8ec6064d..53c58084ac 100644 --- a/core/core_bind.cpp +++ b/core/core_bind.cpp @@ -1088,7 +1088,7 @@ void File::flush() { void File::close() { ERR_FAIL_COND_MSG(f.is_null(), "File must be opened."); - f = Ref<FileAccess>(); + f.unref(); } bool File::is_open() const { diff --git a/core/io/dir_access.cpp b/core/io/dir_access.cpp index dd994fe2fb..433a7efb21 100644 --- a/core/io/dir_access.cpp +++ b/core/io/dir_access.cpp @@ -275,27 +275,29 @@ String DirAccess::get_full_path(const String &p_path, AccessType p_access) { Error DirAccess::copy(String p_from, String p_to, int p_chmod_flags) { //printf("copy %s -> %s\n",p_from.ascii().get_data(),p_to.ascii().get_data()); Error err; - Ref<FileAccess> fsrc = FileAccess::open(p_from, FileAccess::READ, &err); - ERR_FAIL_COND_V_MSG(err != OK, err, "Failed to open " + p_from); - - Ref<FileAccess> fdst = FileAccess::open(p_to, FileAccess::WRITE, &err); - ERR_FAIL_COND_V_MSG(err != OK, err, "Failed to open " + p_to); - - fsrc->seek_end(0); - int size = fsrc->get_position(); - fsrc->seek(0); - err = OK; - while (size--) { - if (fsrc->get_error() != OK) { - err = fsrc->get_error(); - break; - } - if (fdst->get_error() != OK) { - err = fdst->get_error(); - break; - } + { + Ref<FileAccess> fsrc = FileAccess::open(p_from, FileAccess::READ, &err); + ERR_FAIL_COND_V_MSG(err != OK, err, "Failed to open " + p_from); + + Ref<FileAccess> fdst = FileAccess::open(p_to, FileAccess::WRITE, &err); + ERR_FAIL_COND_V_MSG(err != OK, err, "Failed to open " + p_to); + + fsrc->seek_end(0); + int size = fsrc->get_position(); + fsrc->seek(0); + err = OK; + while (size--) { + if (fsrc->get_error() != OK) { + err = fsrc->get_error(); + break; + } + if (fdst->get_error() != OK) { + err = fdst->get_error(); + break; + } - fdst->store_8(fsrc->get_8()); + fdst->store_8(fsrc->get_8()); + } } if (err == OK && p_chmod_flags != -1) { diff --git a/core/io/file_access.cpp b/core/io/file_access.cpp index 87c10074af..7d8da1b11c 100644 --- a/core/io/file_access.cpp +++ b/core/io/file_access.cpp @@ -105,7 +105,7 @@ Ref<FileAccess> FileAccess::open(const String &p_path, int p_mode_flags, Error * *r_error = err; } if (err != OK) { - ret = Ref<FileAccess>(); + ret.unref(); } return ret; diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp index 0c961ba8fb..ebd729cc64 100644 --- a/core/io/file_access_compressed.cpp +++ b/core/io/file_access_compressed.cpp @@ -63,7 +63,7 @@ Error FileAccessCompressed::open_after_magic(Ref<FileAccess> p_base) { cmode = (Compression::Mode)f->get_32(); block_size = f->get_32(); if (block_size == 0) { - f = Ref<FileAccess>(); + f.unref(); ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Can't open compressed file '" + p_base->get_path() + "' with block size 0, it is corrupted."); } read_total = f->get_32(); @@ -106,7 +106,7 @@ Error FileAccessCompressed::_open(const String &p_path, int p_mode_flags) { f = FileAccess::open(p_path, p_mode_flags, &err); if (err != OK) { //not openable - f = Ref<FileAccess>(); + f.unref(); return err; } @@ -126,7 +126,7 @@ Error FileAccessCompressed::_open(const String &p_path, int p_mode_flags) { rmagic[4] = 0; err = ERR_FILE_UNRECOGNIZED; if (magic != rmagic || (err = open_after_magic(f)) != OK) { - f = Ref<FileAccess>(); + f.unref(); return err; } } @@ -180,7 +180,7 @@ void FileAccessCompressed::close() { buffer.clear(); read_blocks.clear(); } - f = Ref<FileAccess>(); + f.unref(); } bool FileAccessCompressed::is_open() const { diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp index 2443e2bea0..5d44ff3f10 100644 --- a/core/io/file_access_encrypted.cpp +++ b/core/io/file_access_encrypted.cpp @@ -122,9 +122,7 @@ void FileAccessEncrypted::close() { _release(); - file->close(); - - file = Ref<FileAccess>(); + file.unref(); } void FileAccessEncrypted::release() { @@ -134,7 +132,7 @@ void FileAccessEncrypted::release() { _release(); - file = Ref<FileAccess>(); + file.unref(); } void FileAccessEncrypted::_release() { diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp index 0b8deb8ec2..1254ecbca9 100644 --- a/core/io/file_access_pack.cpp +++ b/core/io/file_access_pack.cpp @@ -227,14 +227,20 @@ Error FileAccessPack::_open(const String &p_path, int p_mode_flags) { } void FileAccessPack::close() { - f->close(); + f.unref(); } bool FileAccessPack::is_open() const { - return f->is_open(); + if (f.is_valid()) { + return f->is_open(); + } else { + return false; + } } void FileAccessPack::seek(uint64_t p_position) { + ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use."); + if (p_position > pf.size) { eof = true; } else { @@ -262,6 +268,7 @@ bool FileAccessPack::eof_reached() const { } uint8_t FileAccessPack::get_8() const { + ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use."); if (pos >= pf.size) { eof = true; return 0; @@ -272,6 +279,7 @@ uint8_t FileAccessPack::get_8() const { } uint64_t FileAccessPack::get_buffer(uint8_t *p_dst, uint64_t p_length) const { + ERR_FAIL_COND_V_MSG(f.is_null(), -1, "File must be opened before use."); ERR_FAIL_COND_V(!p_dst && p_length > 0, -1); if (eof) { @@ -295,6 +303,8 @@ uint64_t FileAccessPack::get_buffer(uint8_t *p_dst, uint64_t p_length) const { } void FileAccessPack::set_big_endian(bool p_big_endian) { + ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use."); + FileAccess::set_big_endian(p_big_endian); f->set_big_endian(p_big_endian); } diff --git a/core/io/logger.cpp b/core/io/logger.cpp index 0caa2af5c4..c19fc2820b 100644 --- a/core/io/logger.cpp +++ b/core/io/logger.cpp @@ -148,7 +148,7 @@ void RotatedFileLogger::clear_old_backups() { } void RotatedFileLogger::rotate_file() { - file = Ref<FileAccess>(); + file.unref(); if (FileAccess::exists(base_path)) { if (max_files > 1) { diff --git a/core/io/pck_packer.cpp b/core/io/pck_packer.cpp index d1a305e836..6240370504 100644 --- a/core/io/pck_packer.cpp +++ b/core/io/pck_packer.cpp @@ -216,7 +216,7 @@ Error PCKPacker::flush(bool p_verbose) { Ref<FileAccess> src = FileAccess::open(files[i].src_path, FileAccess::READ); uint64_t to_write = files[i].size; - fae = Ref<FileAccess>(); + fae.unref(); Ref<FileAccess> ftmp = file; if (files[i].encrypted) { fae.instantiate(); @@ -253,7 +253,7 @@ Error PCKPacker::flush(bool p_verbose) { printf("\n"); } - file = Ref<FileAccess>(); + file.unref(); memdelete_arr(buf); return OK; diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index 87e4a01819..8d4dbc3f73 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -789,7 +789,7 @@ Error ResourceLoaderBinary::load() { resource_cache.push_back(res); if (main) { - f = Ref<FileAccess>(); + f.unref(); resource = res; resource->set_as_translation_remapped(translation_remapped); error = OK; @@ -868,7 +868,7 @@ void ResourceLoaderBinary::open(Ref<FileAccess> p_f, bool p_no_resources, bool p fac.instantiate(); error = fac->open_after_magic(f); if (error != OK) { - f = Ref<FileAccess>(); + f.unref(); ERR_FAIL_MSG("Failed to open binary resource file: " + local_path + "."); } f = fac; @@ -876,7 +876,7 @@ void ResourceLoaderBinary::open(Ref<FileAccess> p_f, bool p_no_resources, bool p } else if (header[0] != 'R' || header[1] != 'S' || header[2] != 'R' || header[3] != 'C') { // Not normal. error = ERR_FILE_UNRECOGNIZED; - f = Ref<FileAccess>(); + f.unref(); ERR_FAIL_MSG("Unrecognized binary resource file: " + local_path + "."); } @@ -901,7 +901,7 @@ void ResourceLoaderBinary::open(Ref<FileAccess> p_f, bool p_no_resources, bool p print_bl("format: " + itos(ver_format)); if (ver_format > FORMAT_VERSION || ver_major > VERSION_MAJOR) { - f = Ref<FileAccess>(); + f.unref(); ERR_FAIL_MSG(vformat("File '%s' can't be loaded, as it uses a format version (%d) or engine version (%d.%d) which are not supported by your engine version (%s).", local_path, ver_format, ver_major, ver_minor, VERSION_BRANCH)); } @@ -978,6 +978,7 @@ void ResourceLoaderBinary::open(Ref<FileAccess> p_f, bool p_no_resources, bool p if (f->eof_reached()) { error = ERR_FILE_CORRUPT; + f.unref(); ERR_FAIL_MSG("Premature end of file (EOF): " + local_path + "."); } } @@ -994,7 +995,7 @@ String ResourceLoaderBinary::recognize(Ref<FileAccess> p_f) { fac.instantiate(); error = fac->open_after_magic(f); if (error != OK) { - f = Ref<FileAccess>(); + f.unref(); return ""; } f = fac; @@ -1002,7 +1003,7 @@ String ResourceLoaderBinary::recognize(Ref<FileAccess> p_f) { } else if (header[0] != 'R' || header[1] != 'S' || header[2] != 'R' || header[3] != 'C') { // Not normal. error = ERR_FILE_UNRECOGNIZED; - f = Ref<FileAccess>(); + f.unref(); return ""; } @@ -1016,7 +1017,7 @@ String ResourceLoaderBinary::recognize(Ref<FileAccess> p_f) { uint32_t ver_format = f->get_32(); if (ver_format > FORMAT_VERSION || ver_major > VERSION_MAJOR) { - f = Ref<FileAccess>(); + f.unref(); return ""; } diff --git a/core/io/resource_uid.cpp b/core/io/resource_uid.cpp index 8f1f354e90..515b7c710e 100644 --- a/core/io/resource_uid.cpp +++ b/core/io/resource_uid.cpp @@ -220,7 +220,7 @@ Error ResourceUID::update_cache() { } } - if (f != nullptr) { + if (f.is_valid()) { f->seek(0); f->store_32(cache_entries); //update amount of entries } diff --git a/core/os/os.cpp b/core/os/os.cpp index bf6cd4c9ab..846aeb16c5 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -201,14 +201,14 @@ void OS::print_all_resources(String p_to_file) { Error err; _OSPRF = FileAccess::open(p_to_file, FileAccess::WRITE, &err); if (err != OK) { - _OSPRF = Ref<FileAccess>(); + _OSPRF.unref(); ERR_FAIL_MSG("Can't print all resources to file: " + String(p_to_file) + "."); } } ObjectDB::debug_objects(_OS_printres); - _OSPRF = Ref<FileAccess>(); + _OSPRF.unref(); } void OS::print_resources_in_use(bool p_short) { diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index 50e1d03663..fbb61a1614 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -377,13 +377,15 @@ void CreateDialog::_confirmed() { return; } - Ref<FileAccess> f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("create_recent." + base_type), FileAccess::WRITE); - if (f.is_valid()) { - f->store_line(selected_item); - - for (int i = 0; i < MIN(32, recent->get_item_count()); i++) { - if (recent->get_item_text(i) != selected_item) { - f->store_line(recent->get_item_text(i)); + { + Ref<FileAccess> f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("create_recent." + base_type), FileAccess::WRITE); + if (f.is_valid()) { + f->store_line(selected_item); + + for (int i = 0; i < MIN(32, recent->get_item_count()); i++) { + if (recent->get_item_text(i) != selected_item) { + f->store_line(recent->get_item_text(i)); + } } } } @@ -645,23 +647,25 @@ void CreateDialog::_save_and_update_favorite_list() { favorites->clear(); TreeItem *root = favorites->create_item(); - Ref<FileAccess> f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("favorites." + base_type), FileAccess::WRITE); - if (f.is_valid()) { - for (int i = 0; i < favorite_list.size(); i++) { - String l = favorite_list[i]; - String name = l.get_slicec(' ', 0); - if (!(ClassDB::class_exists(name) || ScriptServer::is_global_class(name))) { - continue; - } - f->store_line(l); + { + Ref<FileAccess> f = FileAccess::open(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("favorites." + base_type), FileAccess::WRITE); + if (f.is_valid()) { + for (int i = 0; i < favorite_list.size(); i++) { + String l = favorite_list[i]; + String name = l.get_slicec(' ', 0); + if (!(ClassDB::class_exists(name) || ScriptServer::is_global_class(name))) { + continue; + } + f->store_line(l); - if (_is_class_disabled_by_feature_profile(name)) { - continue; - } + if (_is_class_disabled_by_feature_profile(name)) { + continue; + } - TreeItem *ti = favorites->create_item(root); - ti->set_text(0, l); - ti->set_icon(0, EditorNode::get_singleton()->get_class_icon(name, icon_fallback)); + TreeItem *ti = favorites->create_item(root); + ti->set_text(0, l); + ti->set_icon(0, EditorNode::get_singleton()->get_class_icon(name, icon_fallback)); + } } } diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp index 40b850cace..a822c5fb5f 100644 --- a/editor/editor_export.cpp +++ b/editor/editor_export.cpp @@ -1142,6 +1142,10 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b Error err = export_project_files(p_preset, p_debug, _save_pack_file, &pd, _add_shared_object); + // Close temp file. + pd.f.unref(); + ftmp.unref(); + if (err != OK) { DirAccess::remove_file_or_error(tmppath); ERR_PRINT("Failed to export project files"); @@ -1301,6 +1305,8 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, b f->store_buffer(buf, got); } + ftmp.unref(); // Close temp file. + if (p_embed) { // Ensure embedded data ends at a 64-bit multiple uint64_t embed_end = f->get_position() - embed_pos + 12; diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index 98bf5d3234..099dfe69d5 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -218,69 +218,71 @@ void EditorFileSystem::_scan_filesystem() { String project = ProjectSettings::get_singleton()->get_resource_path(); String fscache = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(CACHE_FILE_NAME); - Ref<FileAccess> f = FileAccess::open(fscache, FileAccess::READ); - - bool first = true; - if (f.is_valid()) { - //read the disk cache - while (!f->eof_reached()) { - String l = f->get_line().strip_edges(); - if (first) { - if (first_scan) { - // only use this on first scan, afterwards it gets ignored - // this is so on first reimport we synchronize versions, then - // we don't care until editor restart. This is for usability mainly so - // your workflow is not killed after changing a setting by forceful reimporting - // everything there is. - filesystem_settings_version_for_import = l.strip_edges(); - if (filesystem_settings_version_for_import != ResourceFormatImporter::get_singleton()->get_import_settings_hash()) { - revalidate_import_files = true; + { + Ref<FileAccess> f = FileAccess::open(fscache, FileAccess::READ); + + bool first = true; + if (f.is_valid()) { + //read the disk cache + while (!f->eof_reached()) { + String l = f->get_line().strip_edges(); + if (first) { + if (first_scan) { + // only use this on first scan, afterwards it gets ignored + // this is so on first reimport we synchronize versions, then + // we don't care until editor restart. This is for usability mainly so + // your workflow is not killed after changing a setting by forceful reimporting + // everything there is. + filesystem_settings_version_for_import = l.strip_edges(); + if (filesystem_settings_version_for_import != ResourceFormatImporter::get_singleton()->get_import_settings_hash()) { + revalidate_import_files = true; + } } + first = false; + continue; + } + if (l.is_empty()) { + continue; } - first = false; - continue; - } - if (l.is_empty()) { - continue; - } - if (l.begins_with("::")) { - Vector<String> split = l.split("::"); - ERR_CONTINUE(split.size() != 3); - String name = split[1]; + if (l.begins_with("::")) { + Vector<String> split = l.split("::"); + ERR_CONTINUE(split.size() != 3); + String name = split[1]; - cpath = name; + cpath = name; - } else { - Vector<String> split = l.split("::"); - ERR_CONTINUE(split.size() != 9); - String name = split[0]; - String file; - - file = name; - name = cpath.plus_file(name); - - FileCache fc; - fc.type = split[1]; - fc.uid = split[2].to_int(); - fc.modification_time = split[3].to_int(); - fc.import_modification_time = split[4].to_int(); - fc.import_valid = split[5].to_int() != 0; - fc.import_group_file = split[6].strip_edges(); - fc.script_class_name = split[7].get_slice("<>", 0); - fc.script_class_extends = split[7].get_slice("<>", 1); - fc.script_class_icon_path = split[7].get_slice("<>", 2); - - String deps = split[8].strip_edges(); - if (deps.length()) { - Vector<String> dp = deps.split("<>"); - for (int i = 0; i < dp.size(); i++) { - String path = dp[i]; - fc.deps.push_back(path); + } else { + Vector<String> split = l.split("::"); + ERR_CONTINUE(split.size() != 9); + String name = split[0]; + String file; + + file = name; + name = cpath.plus_file(name); + + FileCache fc; + fc.type = split[1]; + fc.uid = split[2].to_int(); + fc.modification_time = split[3].to_int(); + fc.import_modification_time = split[4].to_int(); + fc.import_valid = split[5].to_int() != 0; + fc.import_group_file = split[6].strip_edges(); + fc.script_class_name = split[7].get_slice("<>", 0); + fc.script_class_extends = split[7].get_slice("<>", 1); + fc.script_class_icon_path = split[7].get_slice("<>", 2); + + String deps = split[8].strip_edges(); + if (deps.length()) { + Vector<String> dp = deps.split("<>"); + for (int i = 0; i < dp.size(); i++) { + String path = dp[i]; + fc.deps.push_back(path); + } } - } - file_cache[name] = fc; + file_cache[name] = fc; + } } } } @@ -1700,74 +1702,77 @@ Error EditorFileSystem::_reimport_group(const String &p_group_file, const Vector for (const KeyValue<String, Map<StringName, Variant>> &E : source_file_options) { const String &file = E.key; String base_path = ResourceFormatImporter::get_singleton()->get_import_base_path(file); - Ref<FileAccess> f = FileAccess::open(file + ".import", FileAccess::WRITE); - ERR_FAIL_COND_V_MSG(f.is_null(), ERR_FILE_CANT_OPEN, "Cannot open import file '" + file + ".import'."); - - //write manually, as order matters ([remap] has to go first for performance). - f->store_line("[remap]"); - f->store_line(""); - f->store_line("importer=\"" + importer->get_importer_name() + "\""); - int version = importer->get_format_version(); - if (version > 0) { - f->store_line("importer_version=" + itos(version)); - } - if (!importer->get_resource_type().is_empty()) { - f->store_line("type=\"" + importer->get_resource_type() + "\""); - } - Vector<String> dest_paths; + { + Ref<FileAccess> f = FileAccess::open(file + ".import", FileAccess::WRITE); + ERR_FAIL_COND_V_MSG(f.is_null(), ERR_FILE_CANT_OPEN, "Cannot open import file '" + file + ".import'."); + + //write manually, as order matters ([remap] has to go first for performance). + f->store_line("[remap]"); + f->store_line(""); + f->store_line("importer=\"" + importer->get_importer_name() + "\""); + int version = importer->get_format_version(); + if (version > 0) { + f->store_line("importer_version=" + itos(version)); + } + if (!importer->get_resource_type().is_empty()) { + f->store_line("type=\"" + importer->get_resource_type() + "\""); + } - if (err == OK) { - String path = base_path + "." + importer->get_save_extension(); - f->store_line("path=\"" + path + "\""); - dest_paths.push_back(path); - } - - f->store_line("group_file=" + Variant(p_group_file).get_construct_string()); - - if (err == OK) { - f->store_line("valid=true"); - } else { - f->store_line("valid=false"); - } - f->store_line("[deps]\n"); + if (err == OK) { + String path = base_path + "." + importer->get_save_extension(); + f->store_line("path=\"" + path + "\""); + dest_paths.push_back(path); + } - f->store_line(""); + f->store_line("group_file=" + Variant(p_group_file).get_construct_string()); - f->store_line("source_file=" + Variant(file).get_construct_string()); - if (dest_paths.size()) { - Array dp; - for (int i = 0; i < dest_paths.size(); i++) { - dp.push_back(dest_paths[i]); + if (err == OK) { + f->store_line("valid=true"); + } else { + f->store_line("valid=false"); } - f->store_line("dest_files=" + Variant(dp).get_construct_string() + "\n"); - } - f->store_line("[params]"); - f->store_line(""); + f->store_line("[deps]\n"); - //store options in provided order, to avoid file changing. Order is also important because first match is accepted first. + f->store_line(""); - List<ResourceImporter::ImportOption> options; - importer->get_import_options(file, &options); - //set default values - for (const ResourceImporter::ImportOption &F : options) { - String base = F.option.name; - Variant v = F.default_value; - if (source_file_options[file].has(base)) { - v = source_file_options[file][base]; + f->store_line("source_file=" + Variant(file).get_construct_string()); + if (dest_paths.size()) { + Array dp; + for (int i = 0; i < dest_paths.size(); i++) { + dp.push_back(dest_paths[i]); + } + f->store_line("dest_files=" + Variant(dp).get_construct_string() + "\n"); + } + f->store_line("[params]"); + f->store_line(""); + + //store options in provided order, to avoid file changing. Order is also important because first match is accepted first. + + List<ResourceImporter::ImportOption> options; + importer->get_import_options(file, &options); + //set default values + for (const ResourceImporter::ImportOption &F : options) { + String base = F.option.name; + Variant v = F.default_value; + if (source_file_options[file].has(base)) { + v = source_file_options[file][base]; + } + String value; + VariantWriter::write_to_string(v, value); + f->store_line(base + "=" + value); } - String value; - VariantWriter::write_to_string(v, value); - f->store_line(base + "=" + value); } // Store the md5's of the various files. These are stored separately so that the .import files can be version controlled. - Ref<FileAccess> md5s = FileAccess::open(base_path + ".md5", FileAccess::WRITE); - ERR_FAIL_COND_V_MSG(md5s.is_null(), ERR_FILE_CANT_OPEN, "Cannot open MD5 file '" + base_path + ".md5'."); + { + Ref<FileAccess> md5s = FileAccess::open(base_path + ".md5", FileAccess::WRITE); + ERR_FAIL_COND_V_MSG(md5s.is_null(), ERR_FILE_CANT_OPEN, "Cannot open MD5 file '" + base_path + ".md5'."); - md5s->store_line("source_md5=\"" + FileAccess::get_md5(file) + "\""); - if (dest_paths.size()) { - md5s->store_line("dest_md5=\"" + FileAccess::get_multiple_md5(dest_paths) + "\"\n"); + md5s->store_line("source_md5=\"" + FileAccess::get_md5(file) + "\""); + if (dest_paths.size()) { + md5s->store_line("dest_md5=\"" + FileAccess::get_multiple_md5(dest_paths) + "\"\n"); + } } EditorFileSystemDirectory *fs = nullptr; @@ -1914,100 +1919,103 @@ void EditorFileSystem::_reimport_file(const String &p_file, const Map<StringName //as import is complete, save the .import file - Ref<FileAccess> f = FileAccess::open(p_file + ".import", FileAccess::WRITE); - ERR_FAIL_COND_MSG(f.is_null(), "Cannot open file from path '" + p_file + ".import'."); - - //write manually, as order matters ([remap] has to go first for performance). - f->store_line("[remap]"); - f->store_line(""); - f->store_line("importer=\"" + importer->get_importer_name() + "\""); - int version = importer->get_format_version(); - if (version > 0) { - f->store_line("importer_version=" + itos(version)); - } - if (!importer->get_resource_type().is_empty()) { - f->store_line("type=\"" + importer->get_resource_type() + "\""); - } - - if (uid == ResourceUID::INVALID_ID) { - uid = ResourceUID::get_singleton()->create_id(); - } + Vector<String> dest_paths; + { + Ref<FileAccess> f = FileAccess::open(p_file + ".import", FileAccess::WRITE); + ERR_FAIL_COND_MSG(f.is_null(), "Cannot open file from path '" + p_file + ".import'."); - f->store_line("uid=\"" + ResourceUID::get_singleton()->id_to_text(uid) + "\""); //store in readable format + //write manually, as order matters ([remap] has to go first for performance). + f->store_line("[remap]"); + f->store_line(""); + f->store_line("importer=\"" + importer->get_importer_name() + "\""); + int version = importer->get_format_version(); + if (version > 0) { + f->store_line("importer_version=" + itos(version)); + } + if (!importer->get_resource_type().is_empty()) { + f->store_line("type=\"" + importer->get_resource_type() + "\""); + } - Vector<String> dest_paths; + if (uid == ResourceUID::INVALID_ID) { + uid = ResourceUID::get_singleton()->create_id(); + } - if (err == OK) { - if (importer->get_save_extension().is_empty()) { - //no path - } else if (import_variants.size()) { - //import with variants - for (const String &E : import_variants) { - String path = base_path.c_escape() + "." + E + "." + importer->get_save_extension(); + f->store_line("uid=\"" + ResourceUID::get_singleton()->id_to_text(uid) + "\""); //store in readable format - f->store_line("path." + E + "=\"" + path + "\""); + if (err == OK) { + if (importer->get_save_extension().is_empty()) { + //no path + } else if (import_variants.size()) { + //import with variants + for (const String &E : import_variants) { + String path = base_path.c_escape() + "." + E + "." + importer->get_save_extension(); + + f->store_line("path." + E + "=\"" + path + "\""); + dest_paths.push_back(path); + } + } else { + String path = base_path + "." + importer->get_save_extension(); + f->store_line("path=\"" + path + "\""); dest_paths.push_back(path); } + } else { - String path = base_path + "." + importer->get_save_extension(); - f->store_line("path=\"" + path + "\""); - dest_paths.push_back(path); + f->store_line("valid=false"); } - } else { - f->store_line("valid=false"); - } + if (metadata != Variant()) { + f->store_line("metadata=" + metadata.get_construct_string()); + } - if (metadata != Variant()) { - f->store_line("metadata=" + metadata.get_construct_string()); - } + f->store_line(""); - f->store_line(""); + f->store_line("[deps]\n"); - f->store_line("[deps]\n"); + if (gen_files.size()) { + Array genf; + for (const String &E : gen_files) { + genf.push_back(E); + dest_paths.push_back(E); + } - if (gen_files.size()) { - Array genf; - for (const String &E : gen_files) { - genf.push_back(E); - dest_paths.push_back(E); + String value; + VariantWriter::write_to_string(genf, value); + f->store_line("files=" + value); + f->store_line(""); } - String value; - VariantWriter::write_to_string(genf, value); - f->store_line("files=" + value); - f->store_line(""); - } + f->store_line("source_file=" + Variant(p_file).get_construct_string()); - f->store_line("source_file=" + Variant(p_file).get_construct_string()); - - if (dest_paths.size()) { - Array dp; - for (int i = 0; i < dest_paths.size(); i++) { - dp.push_back(dest_paths[i]); + if (dest_paths.size()) { + Array dp; + for (int i = 0; i < dest_paths.size(); i++) { + dp.push_back(dest_paths[i]); + } + f->store_line("dest_files=" + Variant(dp).get_construct_string() + "\n"); } - f->store_line("dest_files=" + Variant(dp).get_construct_string() + "\n"); - } - f->store_line("[params]"); - f->store_line(""); + f->store_line("[params]"); + f->store_line(""); - //store options in provided order, to avoid file changing. Order is also important because first match is accepted first. + //store options in provided order, to avoid file changing. Order is also important because first match is accepted first. - for (const ResourceImporter::ImportOption &E : opts) { - String base = E.option.name; - String value; - VariantWriter::write_to_string(params[base], value); - f->store_line(base + "=" + value); + for (const ResourceImporter::ImportOption &E : opts) { + String base = E.option.name; + String value; + VariantWriter::write_to_string(params[base], value); + f->store_line(base + "=" + value); + } } // Store the md5's of the various files. These are stored separately so that the .import files can be version controlled. - Ref<FileAccess> md5s = FileAccess::open(base_path + ".md5", FileAccess::WRITE); - ERR_FAIL_COND_MSG(md5s.is_null(), "Cannot open MD5 file '" + base_path + ".md5'."); + { + Ref<FileAccess> md5s = FileAccess::open(base_path + ".md5", FileAccess::WRITE); + ERR_FAIL_COND_MSG(md5s.is_null(), "Cannot open MD5 file '" + base_path + ".md5'."); - md5s->store_line("source_md5=\"" + FileAccess::get_md5(p_file) + "\""); - if (dest_paths.size()) { - md5s->store_line("dest_md5=\"" + FileAccess::get_multiple_md5(dest_paths) + "\"\n"); + md5s->store_line("source_md5=\"" + FileAccess::get_md5(p_file) + "\""); + if (dest_paths.size()) { + md5s->store_line("dest_md5=\"" + FileAccess::get_multiple_md5(dest_paths) + "\"\n"); + } } //update modified times, to avoid reimport diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp index aa10d7e68e..8541918e88 100644 --- a/editor/editor_resource_preview.cpp +++ b/editor/editor_resource_preview.cpp @@ -263,28 +263,31 @@ void EditorResourcePreview::_iterate() { if (tsize != thumbnail_size) { cache_valid = false; + f.unref(); } else if (last_modtime != modtime) { String last_md5 = f->get_line(); String md5 = FileAccess::get_md5(item.path); + f.unref(); if (last_md5 != md5) { cache_valid = false; - } else { //update modified time - f = FileAccess::open(file, FileAccess::WRITE); - if (f.is_null()) { + Ref<FileAccess> f2 = FileAccess::open(file, FileAccess::WRITE); + if (f2.is_null()) { // Not returning as this would leave the thread hanging and would require // some proper cleanup/disabling of resource preview generation. ERR_PRINT("Cannot create file '" + file + "'. Check user write permissions."); } else { - f->store_line(itos(thumbnail_size)); - f->store_line(itos(has_small_texture)); - f->store_line(itos(modtime)); - f->store_line(md5); + f2->store_line(itos(thumbnail_size)); + f2->store_line(itos(has_small_texture)); + f2->store_line(itos(modtime)); + f2->store_line(md5); } } + } else { + f.unref(); } if (cache_valid) { diff --git a/editor/export_template_manager.cpp b/editor/export_template_manager.cpp index a1fd2d9049..06c179e77c 100644 --- a/editor/export_template_manager.cpp +++ b/editor/export_template_manager.cpp @@ -514,7 +514,7 @@ bool ExportTemplateManager::_install_file_selected(const String &p_file, bool p_ } f->store_buffer(data.ptr(), data.size()); - + f.unref(); // close file. #ifndef WINDOWS_ENABLED FileAccess::set_unix_permissions(to_write, (info.external_fa >> 16) & 0x01FF); #endif @@ -728,6 +728,7 @@ Error ExportTemplateManager::install_android_template_from_file(const String &p_ Ref<FileAccess> f = FileAccess::open(to_write, FileAccess::WRITE); if (f.is_valid()) { f->store_buffer(data.ptr(), data.size()); + f.unref(); // close file. #ifndef WINDOWS_ENABLED FileAccess::set_unix_permissions(to_write, (info.external_fa >> 16) & 0x01FF); #endif diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 09bff7c00b..906edb006c 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -1091,10 +1091,12 @@ void ScriptEditor::_file_dialog_action(String p_file) { switch (file_dialog_option) { case FILE_NEW_TEXTFILE: { Error err; - Ref<FileAccess> file = FileAccess::open(p_file, FileAccess::WRITE, &err); - if (err) { - EditorNode::get_singleton()->show_warning(TTR("Error writing TextFile:") + "\n" + p_file, TTR("Error!")); - break; + { + Ref<FileAccess> file = FileAccess::open(p_file, FileAccess::WRITE, &err); + if (err) { + EditorNode::get_singleton()->show_warning(TTR("Error writing TextFile:") + "\n" + p_file, TTR("Error!")); + break; + } } if (EditorFileSystem::get_singleton()) { @@ -2209,13 +2211,15 @@ Error ScriptEditor::_save_text_file(Ref<TextFile> p_text_file, const String &p_p String source = sqscr->get_text(); Error err; - Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err); + { + Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err); - ERR_FAIL_COND_V_MSG(err, err, "Cannot save text file '" + p_path + "'."); + ERR_FAIL_COND_V_MSG(err, err, "Cannot save text file '" + p_path + "'."); - file->store_string(source); - if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) { - return ERR_CANT_CREATE; + file->store_string(source); + if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) { + return ERR_CANT_CREATE; + } } if (ResourceSaver::get_timestamp_on_save()) { diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 269e6f0580..59254fc3ad 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -2353,14 +2353,16 @@ Error ResourceFormatSaverGDScript::save(const String &p_path, const RES &p_resou String source = sqscr->get_source_code(); - Error err; - Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err); + { + Error err; + Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err); - ERR_FAIL_COND_V_MSG(err, err, "Cannot save GDScript file '" + p_path + "'."); + ERR_FAIL_COND_V_MSG(err, err, "Cannot save GDScript file '" + p_path + "'."); - file->store_string(source); - if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) { - return ERR_CANT_CREATE; + file->store_string(source); + if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) { + return ERR_CANT_CREATE; + } } if (ScriptServer::is_reload_scripts_on_save_enabled()) { diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 2a8f7c17c7..02aebb3805 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -3641,14 +3641,16 @@ Error ResourceFormatSaverCSharpScript::save(const String &p_path, const RES &p_r } #endif - Error err; - Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err); - ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save C# script file '" + p_path + "'."); + { + Error err; + Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err); + ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot save C# script file '" + p_path + "'."); - file->store_string(source); + file->store_string(source); - if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) { - return ERR_CANT_CREATE; + if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) { + return ERR_CANT_CREATE; + } } #ifdef TOOLS_ENABLED diff --git a/modules/mono/mono_gd/gd_mono_log.cpp b/modules/mono/mono_gd/gd_mono_log.cpp index 1fbacca5bf..6ea3c5539e 100644 --- a/modules/mono/mono_gd/gd_mono_log.cpp +++ b/modules/mono/mono_gd/gd_mono_log.cpp @@ -77,22 +77,20 @@ static String make_text(const char *log_domain, const char *log_level, const cha } void GDMonoLog::mono_log_callback(const char *log_domain, const char *log_level, const char *message, mono_bool fatal, void *) { - Ref<FileAccess> f = GDMonoLog::get_singleton()->log_file; - if (GDMonoLog::get_singleton()->log_level_id >= get_log_level_id(log_level)) { String text = make_text(log_domain, log_level, message); text += "\n"; - f->seek_end(); - f->store_string(text); + GDMonoLog::get_singleton()->log_file->seek_end(); + GDMonoLog::get_singleton()->log_file->store_string(text); } if (fatal) { String text = make_text(log_domain, log_level, message); ERR_PRINT("Mono: FATAL ERROR '" + text + "', ABORTING! Logfile: '" + GDMonoLog::get_singleton()->log_file_path + "'."); // Make sure to flush before aborting - f->flush(); - f->close(); + GDMonoLog::get_singleton()->log_file->flush(); + GDMonoLog::get_singleton()->log_file.unref(); abort(); } diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp index 441fc8edbd..3f5140cc8c 100644 --- a/modules/theora/video_stream_theora.cpp +++ b/modules/theora/video_stream_theora.cpp @@ -152,7 +152,7 @@ void VideoStreamPlaybackTheora::clear() { theora_eos = false; vorbis_eos = false; - file = Ref<FileAccess>(); + file.unref(); playing = false; }; diff --git a/platform/iphone/export/export_plugin.cpp b/platform/iphone/export/export_plugin.cpp index a540a7658c..57bee59523 100644 --- a/platform/iphone/export/export_plugin.cpp +++ b/platform/iphone/export/export_plugin.cpp @@ -1570,13 +1570,15 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p } /* write the file */ - Ref<FileAccess> f = FileAccess::open(file, FileAccess::WRITE); - if (f.is_null()) { - ERR_PRINT("Can't write '" + file + "'."); - unzClose(src_pkg_zip); - return ERR_CANT_CREATE; - }; - f->store_buffer(data.ptr(), data.size()); + { + Ref<FileAccess> f = FileAccess::open(file, FileAccess::WRITE); + if (f.is_null()) { + ERR_PRINT("Can't write '" + file + "'."); + unzClose(src_pkg_zip); + return ERR_CANT_CREATE; + }; + f->store_buffer(data.ptr(), data.size()); + } #if defined(OSX_ENABLED) || defined(X11_ENABLED) if (is_execute) { @@ -1714,12 +1716,14 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p _export_additional_assets(dest_dir + binary_name, libraries, assets); _add_assets_to_project(p_preset, project_file_data, assets); String project_file_name = dest_dir + binary_name + ".xcodeproj/project.pbxproj"; - Ref<FileAccess> f = FileAccess::open(project_file_name, FileAccess::WRITE); - if (f.is_null()) { - ERR_PRINT("Can't write '" + project_file_name + "'."); - return ERR_CANT_CREATE; - }; - f->store_buffer(project_file_data.ptr(), project_file_data.size()); + { + Ref<FileAccess> f = FileAccess::open(project_file_name, FileAccess::WRITE); + if (f.is_null()) { + ERR_PRINT("Can't write '" + project_file_name + "'."); + return ERR_CANT_CREATE; + }; + f->store_buffer(project_file_data.ptr(), project_file_data.size()); + } #ifdef OSX_ENABLED { diff --git a/platform/javascript/api/javascript_tools_editor_plugin.cpp b/platform/javascript/api/javascript_tools_editor_plugin.cpp index 46eec8eda2..31ce71127d 100644 --- a/platform/javascript/api/javascript_tools_editor_plugin.cpp +++ b/platform/javascript/api/javascript_tools_editor_plugin.cpp @@ -81,12 +81,14 @@ void JavaScriptToolsEditorPlugin::_download_zip(Variant p_v) { const String base_path = resource_path.substr(0, resource_path.rfind("/")) + "/"; _zip_recursive(resource_path, base_path, zip); zipClose(zip, nullptr); - Ref<FileAccess> f = FileAccess::open(output_path, FileAccess::READ); - ERR_FAIL_COND_MSG(f.is_null(), "Unable to create ZIP file."); - Vector<uint8_t> buf; - buf.resize(f->get_length()); - f->get_buffer(buf.ptrw(), buf.size()); - godot_js_os_download_buffer(buf.ptr(), buf.size(), output_name.utf8().get_data(), "application/zip"); + { + Ref<FileAccess> f = FileAccess::open(output_path, FileAccess::READ); + ERR_FAIL_COND_MSG(f.is_null(), "Unable to create ZIP file."); + Vector<uint8_t> buf; + buf.resize(f->get_length()); + f->get_buffer(buf.ptrw(), buf.size()); + godot_js_os_download_buffer(buf.ptr(), buf.size(), output_name.utf8().get_data(), "application/zip"); + } // Remove the temporary file since it was sent to the user's native filesystem as a download. DirAccess::remove_file_or_error(output_path); diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp index 62e9aaed45..bf142f8804 100644 --- a/platform/linuxbsd/os_linuxbsd.cpp +++ b/platform/linuxbsd/os_linuxbsd.cpp @@ -511,9 +511,11 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) { String trash_info = "[Trash Info]\nPath=" + path.uri_encode() + "\nDeletionDate=" + timestamp + "\n"; { Error err; - Ref<FileAccess> file = FileAccess::open(trash_path + "/info/" + file_name + ".trashinfo", FileAccess::WRITE, &err); - ERR_FAIL_COND_V_MSG(err != OK, err, "Can't create trashinfo file: \"" + trash_path + "/info/" + file_name + ".trashinfo\""); - file->store_string(trash_info); + { + Ref<FileAccess> file = FileAccess::open(trash_path + "/info/" + file_name + ".trashinfo", FileAccess::WRITE, &err); + ERR_FAIL_COND_V_MSG(err != OK, err, "Can't create trashinfo file: \"" + trash_path + "/info/" + file_name + ".trashinfo\""); + file->store_string(trash_info); + } // Rename our resource before moving it to the trash can. Ref<DirAccess> dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); diff --git a/platform/osx/export/export_plugin.cpp b/platform/osx/export/export_plugin.cpp index 580cd81583..94ef875072 100644 --- a/platform/osx/export/export_plugin.cpp +++ b/platform/osx/export/export_plugin.cpp @@ -256,21 +256,23 @@ void EditorExportPlatformOSX::_make_icon(const Ref<Image> &p_icon, Vector<uint8_ String path = EditorPaths::get_singleton()->get_cache_dir().plus_file("icon.png"); ResourceSaver::save(path, it); - Ref<FileAccess> f = FileAccess::open(path, FileAccess::READ); - if (f.is_null()) { - // Clean up generated file. - DirAccess::remove_file_or_error(path); - ERR_FAIL(); - } + { + Ref<FileAccess> f = FileAccess::open(path, FileAccess::READ); + if (f.is_null()) { + // Clean up generated file. + DirAccess::remove_file_or_error(path); + ERR_FAIL(); + } - int ofs = data.size(); - uint64_t len = f->get_length(); - data.resize(data.size() + len + 8); - f->get_buffer(&data.write[ofs + 8], len); - len += 8; - len = BSWAP32(len); - memcpy(&data.write[ofs], icon_infos[i].name, 4); - encode_uint32(len, &data.write[ofs + 4]); + int ofs = data.size(); + uint64_t len = f->get_length(); + data.resize(data.size() + len + 8); + f->get_buffer(&data.write[ofs + 8], len); + len += 8; + len = BSWAP32(len); + memcpy(&data.write[ofs], icon_infos[i].name, 4); + encode_uint32(len, &data.write[ofs + 4]); + } // Clean up generated file. DirAccess::remove_file_or_error(path); diff --git a/platform/uwp/export/app_packager.cpp b/platform/uwp/export/app_packager.cpp index 8d09a16653..2f70c3e74c 100644 --- a/platform/uwp/export/app_packager.cpp +++ b/platform/uwp/export/app_packager.cpp @@ -457,7 +457,7 @@ void AppxPackager::finish() { Vector<uint8_t> end_record = make_end_of_central_record(); package->store_buffer(end_record.ptr(), end_record.size()); - package = Ref<FileAccess>(); + package.unref(); } AppxPackager::AppxPackager() {} diff --git a/platform/uwp/export/export_plugin.h b/platform/uwp/export/export_plugin.h index 7f10b00dc1..ceb6d613b3 100644 --- a/platform/uwp/export/export_plugin.h +++ b/platform/uwp/export/export_plugin.h @@ -346,19 +346,21 @@ class EditorExportPlatformUWP : public EditorExportPlatform { ERR_FAIL_V_MSG(data, err_string); } - Ref<FileAccess> f = FileAccess::open(tmp_path, FileAccess::READ, &err); + { + Ref<FileAccess> f = FileAccess::open(tmp_path, FileAccess::READ, &err); + + if (err != OK) { + String err_string = "Couldn't open temp logo file."; + // Cleanup generated file. + DirAccess::remove_file_or_error(tmp_path); + EditorNode::add_io_error(err_string); + ERR_FAIL_V_MSG(data, err_string); + } - if (err != OK) { - String err_string = "Couldn't open temp logo file."; - // Cleanup generated file. - DirAccess::remove_file_or_error(tmp_path); - EditorNode::add_io_error(err_string); - ERR_FAIL_V_MSG(data, err_string); + data.resize(f->get_length()); + f->get_buffer(data.ptrw(), data.size()); } - data.resize(f->get_length()); - f->get_buffer(data.ptrw(), data.size()); - DirAccess::remove_file_or_error(tmp_path); return data; diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp index 43cdbc7f1d..34b0e19d31 100644 --- a/scene/main/http_request.cpp +++ b/scene/main/http_request.cpp @@ -197,7 +197,7 @@ void HTTPRequest::cancel_request() { thread.wait_to_finish(); } - file = Ref<FileAccess>(); + file.unref(); client->close(); body.clear(); got_response = false; diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp index ce7007f257..4b0456681b 100644 --- a/scene/resources/resource_format_text.cpp +++ b/scene/resources/resource_format_text.cpp @@ -890,7 +890,7 @@ Error ResourceLoaderText::rename_dependencies(Ref<FileAccess> p_f, const String fw->store_8(c); c = f->get_8(); } - f = Ref<FileAccess>(); + f.unref(); bool all_ok = fw->get_error() == OK; @@ -1098,142 +1098,143 @@ Error ResourceLoaderText::save_as_binary(Ref<FileAccess> p_f, const String &p_pa wf->store_32(0); //zero sub resources, still parsing them String temp_file = p_path + ".temp"; - Ref<FileAccess> wf2 = FileAccess::open(temp_file, FileAccess::WRITE); - if (wf2.is_null()) { - return ERR_CANT_OPEN; - } - Vector<uint64_t> local_offsets; Vector<uint64_t> local_pointers_pos; + { + Ref<FileAccess> wf2 = FileAccess::open(temp_file, FileAccess::WRITE); + if (wf2.is_null()) { + return ERR_CANT_OPEN; + } - while (next_tag.name == "sub_resource" || next_tag.name == "resource") { - String type; - int id = -1; - bool main_res; + while (next_tag.name == "sub_resource" || next_tag.name == "resource") { + String type; + int id = -1; + bool main_res; - if (next_tag.name == "sub_resource") { - if (!next_tag.fields.has("type")) { - error = ERR_FILE_CORRUPT; - error_text = "Missing 'type' in external resource tag"; - _printerr(); - return error; - } + if (next_tag.name == "sub_resource") { + if (!next_tag.fields.has("type")) { + error = ERR_FILE_CORRUPT; + error_text = "Missing 'type' in external resource tag"; + _printerr(); + return error; + } - if (!next_tag.fields.has("id")) { - error = ERR_FILE_CORRUPT; - error_text = "Missing 'id' in external resource tag"; - _printerr(); - return error; + if (!next_tag.fields.has("id")) { + error = ERR_FILE_CORRUPT; + error_text = "Missing 'id' in external resource tag"; + _printerr(); + return error; + } + + type = next_tag.fields["type"]; + id = next_tag.fields["id"]; + main_res = false; + } else { + type = res_type; + id = 0; //used for last anyway + main_res = true; } - type = next_tag.fields["type"]; - id = next_tag.fields["id"]; - main_res = false; - } else { - type = res_type; - id = 0; //used for last anyway - main_res = true; - } + local_offsets.push_back(wf2->get_position()); - local_offsets.push_back(wf2->get_position()); + bs_save_unicode_string(wf, "local://" + itos(id)); + local_pointers_pos.push_back(wf->get_position()); + wf->store_64(0); //temp local offset - bs_save_unicode_string(wf, "local://" + itos(id)); - local_pointers_pos.push_back(wf->get_position()); - wf->store_64(0); //temp local offset + bs_save_unicode_string(wf2, type); + uint64_t propcount_ofs = wf2->get_position(); + wf2->store_32(0); - bs_save_unicode_string(wf2, type); - uint64_t propcount_ofs = wf2->get_position(); - wf2->store_32(0); + int prop_count = 0; - int prop_count = 0; + while (true) { + String assign; + Variant value; - while (true) { - String assign; - Variant value; + error = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, &rp); - error = VariantParser::parse_tag_assign_eof(&stream, lines, error_text, next_tag, assign, value, &rp); + if (error) { + if (main_res && error == ERR_FILE_EOF) { + next_tag.name = ""; //exit + break; + } - if (error) { - if (main_res && error == ERR_FILE_EOF) { - next_tag.name = ""; //exit - break; + _printerr(); + return error; } - _printerr(); - return error; + if (!assign.is_empty()) { + Map<StringName, int> empty_string_map; //unused + bs_save_unicode_string(wf2, assign, true); + ResourceFormatSaverBinaryInstance::write_variant(wf2, value, dummy_read.resource_index_map, dummy_read.external_resources, empty_string_map); + prop_count++; + + } else if (!next_tag.name.is_empty()) { + error = OK; + break; + } else { + error = ERR_FILE_CORRUPT; + error_text = "Premature end of file while parsing [sub_resource]"; + _printerr(); + return error; + } } - if (!assign.is_empty()) { - Map<StringName, int> empty_string_map; //unused - bs_save_unicode_string(wf2, assign, true); - ResourceFormatSaverBinaryInstance::write_variant(wf2, value, dummy_read.resource_index_map, dummy_read.external_resources, empty_string_map); - prop_count++; + wf2->seek(propcount_ofs); + wf2->store_32(prop_count); + wf2->seek_end(); + } - } else if (!next_tag.name.is_empty()) { - error = OK; - break; - } else { - error = ERR_FILE_CORRUPT; - error_text = "Premature end of file while parsing [sub_resource]"; + if (next_tag.name == "node") { + //this is a node, must save one more! + + if (!is_scene) { + error_text += "found the 'node' tag on a resource file!"; _printerr(); + error = ERR_FILE_CORRUPT; return error; } - } - wf2->seek(propcount_ofs); - wf2->store_32(prop_count); - wf2->seek_end(); - } - - if (next_tag.name == "node") { - //this is a node, must save one more! + Ref<PackedScene> packed_scene = _parse_node_tag(rp); - if (!is_scene) { - error_text += "found the 'node' tag on a resource file!"; - _printerr(); - error = ERR_FILE_CORRUPT; - return error; - } + if (!packed_scene.is_valid()) { + return error; + } - Ref<PackedScene> packed_scene = _parse_node_tag(rp); + error = OK; + //get it here + List<PropertyInfo> props; + packed_scene->get_property_list(&props); - if (!packed_scene.is_valid()) { - return error; - } + bs_save_unicode_string(wf, "local://0"); + local_pointers_pos.push_back(wf->get_position()); + wf->store_64(0); //temp local offset - error = OK; - //get it here - List<PropertyInfo> props; - packed_scene->get_property_list(&props); + local_offsets.push_back(wf2->get_position()); + bs_save_unicode_string(wf2, "PackedScene"); + uint64_t propcount_ofs = wf2->get_position(); + wf2->store_32(0); - bs_save_unicode_string(wf, "local://0"); - local_pointers_pos.push_back(wf->get_position()); - wf->store_64(0); //temp local offset + int prop_count = 0; - local_offsets.push_back(wf2->get_position()); - bs_save_unicode_string(wf2, "PackedScene"); - uint64_t propcount_ofs = wf2->get_position(); - wf2->store_32(0); + for (const PropertyInfo &E : props) { + if (!(E.usage & PROPERTY_USAGE_STORAGE)) { + continue; + } - int prop_count = 0; + String name = E.name; + Variant value = packed_scene->get(name); - for (const PropertyInfo &E : props) { - if (!(E.usage & PROPERTY_USAGE_STORAGE)) { - continue; + Map<StringName, int> empty_string_map; //unused + bs_save_unicode_string(wf2, name, true); + ResourceFormatSaverBinaryInstance::write_variant(wf2, value, dummy_read.resource_index_map, dummy_read.external_resources, empty_string_map); + prop_count++; } - String name = E.name; - Variant value = packed_scene->get(name); - - Map<StringName, int> empty_string_map; //unused - bs_save_unicode_string(wf2, name, true); - ResourceFormatSaverBinaryInstance::write_variant(wf2, value, dummy_read.resource_index_map, dummy_read.external_resources, empty_string_map); - prop_count++; + wf2->seek(propcount_ofs); + wf2->store_32(prop_count); + wf2->seek_end(); } - - wf2->seek(propcount_ofs); - wf2->store_32(prop_count); - wf2->seek_end(); } uint64_t offset_from = wf->get_position(); |