Narrow FileAccess scope to prevent deadlocks.
This commit is contained in:
parent
5974e1432e
commit
4bf99f4af2
29 changed files with 511 additions and 459 deletions
|
@ -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 {
|
||||
|
|
|
@ -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> 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);
|
||||
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;
|
||||
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());
|
||||
}
|
||||
if (fdst->get_error() != OK) {
|
||||
err = fdst->get_error();
|
||||
break;
|
||||
}
|
||||
|
||||
fdst->store_8(fsrc->get_8());
|
||||
}
|
||||
|
||||
if (err == OK && p_chmod_flags != -1) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 "";
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
{
|
||||
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));
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
{
|
||||
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;
|
||||
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;
|
||||
}
|
||||
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];
|
||||
|
||||
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);
|
||||
}
|
||||
if (l.is_empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
file_cache[name] = fc;
|
||||
if (l.begins_with("::")) {
|
||||
Vector<String> split = l.split("::");
|
||||
ERR_CONTINUE(split.size() != 3);
|
||||
String name = split[1];
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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'.");
|
||||
|
||||
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");
|
||||
|
||||
f->store_line("");
|
||||
|
||||
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]);
|
||||
//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));
|
||||
}
|
||||
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];
|
||||
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");
|
||||
|
||||
f->store_line("");
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
f->store_line("uid=\"" + ResourceUID::get_singleton()->id_to_text(uid) + "\""); //store in readable format
|
||||
|
||||
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'.");
|
||||
|
||||
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();
|
||||
//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() + "\"");
|
||||
}
|
||||
|
||||
f->store_line("path." + E + "=\"" + path + "\"");
|
||||
if (uid == ResourceUID::INVALID_ID) {
|
||||
uid = ResourceUID::get_singleton()->create_id();
|
||||
}
|
||||
|
||||
f->store_line("uid=\"" + ResourceUID::get_singleton()->id_to_text(uid) + "\""); //store in readable format
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
f->store_line("");
|
||||
|
||||
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 (metadata != Variant()) {
|
||||
f->store_line("metadata=" + metadata.get_construct_string());
|
||||
}
|
||||
|
||||
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("[deps]\n");
|
||||
|
||||
if (dest_paths.size()) {
|
||||
Array dp;
|
||||
for (int i = 0; i < dest_paths.size(); i++) {
|
||||
dp.push_back(dest_paths[i]);
|
||||
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("");
|
||||
}
|
||||
f->store_line("dest_files=" + Variant(dp).get_construct_string() + "\n");
|
||||
}
|
||||
|
||||
f->store_line("[params]");
|
||||
f->store_line("");
|
||||
f->store_line("source_file=" + Variant(p_file).get_construct_string());
|
||||
|
||||
//store options in provided order, to avoid file changing. Order is also important because first match is accepted first.
|
||||
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");
|
||||
}
|
||||
|
||||
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);
|
||||
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.
|
||||
|
||||
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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -152,7 +152,7 @@ void VideoStreamPlaybackTheora::clear() {
|
|||
theora_eos = false;
|
||||
vorbis_eos = false;
|
||||
|
||||
file = Ref<FileAccess>();
|
||||
file.unref();
|
||||
playing = false;
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -197,7 +197,7 @@ void HTTPRequest::cancel_request() {
|
|||
thread.wait_to_finish();
|
||||
}
|
||||
|
||||
file = Ref<FileAccess>();
|
||||
file.unref();
|
||||
client->close();
|
||||
body.clear();
|
||||
got_response = false;
|
||||
|
|
|
@ -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;
|
||||
|
||||
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.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;
|
||||
{
|
||||
Ref<FileAccess> wf2 = FileAccess::open(temp_file, FileAccess::WRITE);
|
||||
if (wf2.is_null()) {
|
||||
return ERR_CANT_OPEN;
|
||||
}
|
||||
|
||||
local_offsets.push_back(wf2->get_position());
|
||||
while (next_tag.name == "sub_resource" || next_tag.name == "resource") {
|
||||
String type;
|
||||
int id = -1;
|
||||
bool main_res;
|
||||
|
||||
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);
|
||||
|
||||
int prop_count = 0;
|
||||
|
||||
while (true) {
|
||||
String assign;
|
||||
Variant value;
|
||||
|
||||
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 (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;
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
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);
|
||||
|
||||
int prop_count = 0;
|
||||
|
||||
while (true) {
|
||||
String assign;
|
||||
Variant value;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
_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;
|
||||
}
|
||||
}
|
||||
|
||||
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!
|
||||
|
||||
if (!is_scene) {
|
||||
error_text += "found the 'node' tag on a resource file!";
|
||||
_printerr();
|
||||
error = ERR_FILE_CORRUPT;
|
||||
return error;
|
||||
}
|
||||
|
||||
if (!assign.is_empty()) {
|
||||
Ref<PackedScene> packed_scene = _parse_node_tag(rp);
|
||||
|
||||
if (!packed_scene.is_valid()) {
|
||||
return error;
|
||||
}
|
||||
|
||||
error = OK;
|
||||
//get it here
|
||||
List<PropertyInfo> props;
|
||||
packed_scene->get_property_list(&props);
|
||||
|
||||
bs_save_unicode_string(wf, "local://0");
|
||||
local_pointers_pos.push_back(wf->get_position());
|
||||
wf->store_64(0); //temp local offset
|
||||
|
||||
local_offsets.push_back(wf2->get_position());
|
||||
bs_save_unicode_string(wf2, "PackedScene");
|
||||
uint64_t propcount_ofs = wf2->get_position();
|
||||
wf2->store_32(0);
|
||||
|
||||
int prop_count = 0;
|
||||
|
||||
for (const PropertyInfo &E : props) {
|
||||
if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String name = E.name;
|
||||
Variant value = packed_scene->get(name);
|
||||
|
||||
Map<StringName, int> empty_string_map; //unused
|
||||
bs_save_unicode_string(wf2, assign, true);
|
||||
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++;
|
||||
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
|
||||
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!
|
||||
|
||||
if (!is_scene) {
|
||||
error_text += "found the 'node' tag on a resource file!";
|
||||
_printerr();
|
||||
error = ERR_FILE_CORRUPT;
|
||||
return error;
|
||||
}
|
||||
|
||||
Ref<PackedScene> packed_scene = _parse_node_tag(rp);
|
||||
|
||||
if (!packed_scene.is_valid()) {
|
||||
return error;
|
||||
}
|
||||
|
||||
error = OK;
|
||||
//get it here
|
||||
List<PropertyInfo> props;
|
||||
packed_scene->get_property_list(&props);
|
||||
|
||||
bs_save_unicode_string(wf, "local://0");
|
||||
local_pointers_pos.push_back(wf->get_position());
|
||||
wf->store_64(0); //temp local offset
|
||||
|
||||
local_offsets.push_back(wf2->get_position());
|
||||
bs_save_unicode_string(wf2, "PackedScene");
|
||||
uint64_t propcount_ofs = wf2->get_position();
|
||||
wf2->store_32(0);
|
||||
|
||||
int prop_count = 0;
|
||||
|
||||
for (const PropertyInfo &E : props) {
|
||||
if (!(E.usage & PROPERTY_USAGE_STORAGE)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
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();
|
||||
|
|
Loading…
Reference in a new issue