Fixed make_dir and make_dir_recursive erros, closes #1680 closes #1872

This commit is contained in:
Juan Linietsky 2016-06-18 11:12:08 -03:00
parent a7fc04626a
commit 61655d6dc2
9 changed files with 72 additions and 564 deletions

View File

@ -46,7 +46,7 @@ void FileAccessMemory::register_file(String p_name, Vector<uint8_t> p_data) {
name = Globals::get_singleton()->globalize_path(p_name); name = Globals::get_singleton()->globalize_path(p_name);
else else
name = p_name; name = p_name;
name = DirAccess::normalize_path(name); //name = DirAccess::normalize_path(name);
(*files)[name] = p_data; (*files)[name] = p_data;
} }
@ -68,7 +68,7 @@ FileAccess* FileAccessMemory::create() {
bool FileAccessMemory::file_exists(const String& p_name) { bool FileAccessMemory::file_exists(const String& p_name) {
String name = fix_path(p_name); String name = fix_path(p_name);
name = DirAccess::normalize_path(name); // name = DirAccess::normalize_path(name);
return files && (files->find(name) != NULL); return files && (files->find(name) != NULL);
} }
@ -87,7 +87,7 @@ Error FileAccessMemory::_open(const String& p_path, int p_mode_flags) {
ERR_FAIL_COND_V(!files, ERR_FILE_NOT_FOUND); ERR_FAIL_COND_V(!files, ERR_FILE_NOT_FOUND);
String name = fix_path(p_path); String name = fix_path(p_path);
name = DirAccess::normalize_path(name); // name = DirAccess::normalize_path(name);
Map<String, Vector<uint8_t> >::Element* E = files->find(name); Map<String, Vector<uint8_t> >::Element* E = files->find(name);
ERR_FAIL_COND_V(!E, ERR_FILE_NOT_FOUND); ERR_FAIL_COND_V(!E, ERR_FILE_NOT_FOUND);

View File

@ -143,118 +143,52 @@ Error DirAccess::make_dir_recursive(String p_dir) {
}; };
String full_dir; String full_dir;
Globals* g = Globals::get_singleton();
if (!p_dir.is_abs_path()) { if (p_dir.is_rel_path()) {
//append current //append current
full_dir=get_current_dir().plus_file(p_dir);
String cur = normalize_path(g->globalize_path(get_current_dir()));
if (cur[cur.length()-1] != '/') {
cur = cur + "/";
};
full_dir=(cur+"/"+p_dir).simplify_path();
} else { } else {
//validate and use given full_dir=p_dir;
String dir = normalize_path(g->globalize_path(p_dir));
if (dir.length() < 1) {
return OK;
};
if (dir[dir.length()-1] != '/') {
dir = dir + "/";
};
full_dir=dir;
} }
full_dir=full_dir.replace("\\","/");
//int slices = full_dir.get_slice_count("/"); //int slices = full_dir.get_slice_count("/");
int pos = 0; String base;
while (pos < full_dir.length()) {
int n = full_dir.find("/", pos); if (full_dir.begins_with("res://"))
if (n < 0) { base="res://";
n = full_dir.length(); else if (full_dir.begins_with("user://"))
}; base="user://";
pos = n + 1; else if (full_dir.begins_with("/"))
base="/";
else if (full_dir.find(":/")!=-1) {
base=full_dir.substr(0,full_dir.find(":/")+2);
} else {
ERR_FAIL_V(ERR_INVALID_PARAMETER);
}
if (pos > 1) { full_dir=full_dir.replace_first(base,"").simplify_path();
String to_create = full_dir.substr(0, pos -1);
//print_line("MKDIR: "+to_create);
Error err = make_dir(to_create);
if (err != OK && err != ERR_ALREADY_EXISTS) {
ERR_FAIL_V(err); Vector<String> subdirs=full_dir.split("/");
};
}; String curpath=base;
}; for(int i=0;i<subdirs.size();i++) {
curpath=curpath.plus_file(subdirs[i]);
Error err = make_dir(curpath);
if (err != OK && err != ERR_ALREADY_EXISTS) {
ERR_FAIL_V(err);
}
}
return OK; return OK;
}; }
String DirAccess::normalize_path(const String &p_path) {
static const int max_depth = 64;
int pos_stack[max_depth];
int curr = 0;
int pos = 0;
String cur_dir;
do {
if (curr >= max_depth) {
ERR_PRINT("Directory depth too deep.");
return "";
};
int start = pos;
int next = p_path.find("/", pos);
if (next < 0) {
next = p_path.length() - 1;
};
pos = next + 1;
cur_dir = p_path.substr(start, next - start);
if (cur_dir == "" || cur_dir == ".") {
continue;
};
if (cur_dir == "..") {
if (curr > 0) { // pop a dir
curr -= 2;
};
continue;
};
pos_stack[curr++] = start;
pos_stack[curr++] = next;
} while (pos < p_path.length());
String path;
if (p_path[0] == '/') {
path = "/";
};
int i=0;
while (i < curr) {
int start = pos_stack[i++];
while ( ((i+1)<curr) && (pos_stack[i] == pos_stack[i+1]) ) {
++i;
};
path = path + p_path.substr(start, (pos_stack[i++] - start) + 1);
};
return path;
};
String DirAccess::get_next(bool* p_is_dir) { String DirAccess::get_next(bool* p_is_dir) {
@ -276,9 +210,9 @@ String DirAccess::fix_path(String p_path) const {
String resource_path = Globals::get_singleton()->get_resource_path(); String resource_path = Globals::get_singleton()->get_resource_path();
if (resource_path != "") { if (resource_path != "") {
return p_path.replace("res:/",resource_path); return p_path.replace_first("res:/",resource_path);
}; };
return p_path.replace("res://", ""); return p_path.replace_first("res://", "");
} }
} }
@ -292,9 +226,9 @@ String DirAccess::fix_path(String p_path) const {
String data_dir=OS::get_singleton()->get_data_dir(); String data_dir=OS::get_singleton()->get_data_dir();
if (data_dir != "") { if (data_dir != "") {
return p_path.replace("user:/",data_dir); return p_path.replace_first("user:/",data_dir);
}; };
return p_path.replace("user://", ""); return p_path.replace_first("user://", "");
} }
} break; } break;

View File

@ -72,8 +72,6 @@ protected:
public: public:
static String normalize_path(const String& p_path);
virtual bool list_dir_begin()=0; ///< This starts dir listing virtual bool list_dir_begin()=0; ///< This starts dir listing
virtual String get_next(bool* p_is_dir); // compatibility virtual String get_next(bool* p_is_dir); // compatibility
virtual String get_next()=0; virtual String get_next()=0;

View File

@ -66,7 +66,7 @@ bool DirAccessUnix::file_exists(String p_file) {
if (p_file.is_rel_path()) if (p_file.is_rel_path())
p_file=current_dir+"/"+p_file; p_file=current_dir.plus_file(p_file);
else else
p_file=fix_path(p_file); p_file=fix_path(p_file);
@ -104,7 +104,7 @@ bool DirAccessUnix::dir_exists(String p_dir) {
uint64_t DirAccessUnix::get_modified_time(String p_file) { uint64_t DirAccessUnix::get_modified_time(String p_file) {
if (p_file.is_rel_path()) if (p_file.is_rel_path())
p_file=current_dir+"/"+p_file; p_file=current_dir.plus_file(p_file);
else else
p_file=fix_path(p_file); p_file=fix_path(p_file);
@ -138,11 +138,9 @@ String DirAccessUnix::get_next() {
//typedef struct stat Stat; //typedef struct stat Stat;
struct stat flags; struct stat flags;
String fname; String fname = fix_unicode_name(entry->d_name);
if (fname.parse_utf8(entry->d_name))
fname=entry->d_name; //no utf8, maybe latin?
String f=current_dir+"/"+fname; String f=current_dir.plus_file(fname);
if (stat(f.utf8().get_data(),&flags)==0) { if (stat(f.utf8().get_data(),&flags)==0) {
@ -201,8 +199,17 @@ Error DirAccessUnix::make_dir(String p_dir) {
GLOBAL_LOCK_FUNCTION GLOBAL_LOCK_FUNCTION
p_dir=fix_path(p_dir); if (p_dir.is_rel_path())
p_dir=get_current_dir().plus_file(p_dir);
else
p_dir=fix_path(p_dir);
#if 1
bool success=(mkdir(p_dir.utf8().get_data(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)==0);
int err = errno;
#else
char real_current_dir_name[2048]; char real_current_dir_name[2048];
getcwd(real_current_dir_name,2048); getcwd(real_current_dir_name,2048);
chdir(current_dir.utf8().get_data()); //ascii since this may be unicode or wathever the host os wants chdir(current_dir.utf8().get_data()); //ascii since this may be unicode or wathever the host os wants
@ -211,7 +218,7 @@ Error DirAccessUnix::make_dir(String p_dir) {
int err = errno; int err = errno;
chdir(real_current_dir_name); chdir(real_current_dir_name);
#endif
if (success) { if (success) {
return OK; return OK;
}; };

View File

@ -51,7 +51,10 @@ class DirAccessUnix : public DirAccess {
String current_dir; String current_dir;
bool _cisdir; bool _cisdir;
bool _cishidden; bool _cishidden;
protected:
virtual String fix_unicode_name(const char* p_name) const { return String::utf8(p_name); }
public: public:
virtual bool list_dir_begin(); ///< This starts dir listing virtual bool list_dir_begin(); ///< This starts dir listing

View File

@ -191,23 +191,21 @@ Error DirAccessWindows::make_dir(String p_dir) {
#else #else
p_dir=fix_path(p_dir); if (p_dir.is_rel_path())
p_dir=get_current_dir().plus_file(p_dir);
else
p_dir=fix_path(p_dir);
//p_dir.replace("/","\\"); //p_dir.replace("/","\\");
bool success; bool success;
int err; int err;
wchar_t real_current_dir_name[2048]; p_dir="\\\\?\\"+p_dir; //done according to
GetCurrentDirectoryW(2048,real_current_dir_name); // https://msdn.microsoft.com/en-us/library/windows/desktop/aa363855(v=vs.85).aspx
SetCurrentDirectoryW(current_dir.c_str());
success=CreateDirectoryW(p_dir.c_str(), NULL); success=CreateDirectoryW(p_dir.c_str(), NULL);
err = GetLastError(); err = GetLastError();
SetCurrentDirectoryW(real_current_dir_name);
if (success) { if (success) {
return OK; return OK;
}; };
@ -315,6 +313,7 @@ Error DirAccessWindows::remove(String p_path) {
else else
p_path=fix_path(p_path); p_path=fix_path(p_path);
printf("erasing %s\n",p_path.utf8().get_data()); printf("erasing %s\n",p_path.utf8().get_data());
//WIN32_FILE_ATTRIBUTE_DATA fileInfo; //WIN32_FILE_ATTRIBUTE_DATA fileInfo;
//DWORD fileAttr = GetFileAttributesExW(p_path.c_str(), GetFileExInfoStandard, &fileInfo); //DWORD fileAttr = GetFileAttributesExW(p_path.c_str(), GetFileExInfoStandard, &fileInfo);

View File

@ -37,52 +37,16 @@
#include <dirent.h> #include <dirent.h>
#include "os/dir_access.h" #include "os/dir_access.h"
#include "drivers/unix/dir_access_unix.h"
/** /**
@author Juan Linietsky <reduzio@gmail.com> @author Juan Linietsky <reduzio@gmail.com>
*/ */
class DirAccessOSX : public DirAccess { class DirAccessOSX : public DirAccessUnix {
protected:
DIR *dir_stream; virtual String fix_unicode_name(const char* p_name) const;
static DirAccess *create_fs();
String current_dir;
bool _cisdir;
bool _cishidden;
public:
virtual bool list_dir_begin(); ///< This starts dir listing
virtual String get_next();
virtual bool current_is_dir() const;
virtual bool current_is_hidden() const;
virtual void list_dir_end(); ///<
virtual int get_drive_count();
virtual String get_drive(int p_drive);
virtual Error change_dir(String p_dir); ///< can be relative or absolute, return false on success
virtual String get_current_dir(); ///< return current dir location
virtual Error make_dir(String p_dir);
virtual bool file_exists(String p_file);
virtual bool dir_exists(String p_dir);
virtual uint64_t get_modified_time(String p_file);
virtual Error rename(String p_from, String p_to);
virtual Error remove(String p_name);
virtual size_t get_space_left();
DirAccessOSX();
~DirAccessOSX();
}; };

View File

@ -30,324 +30,21 @@
#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED) #if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED)
#ifndef ANDROID_ENABLED
#include <sys/statvfs.h>
#endif
#include <stdio.h>
#include "os/memory.h"
#include "print_string.h"
#include <errno.h> #include <errno.h>
#include <Foundation/NSString.h> #include <Foundation/NSString.h>
DirAccess *DirAccessOSX::create_fs() {
return memnew( DirAccessOSX ); String DirAccessOSX::fix_unicode_name(const char* p_name) const {
}
bool DirAccessOSX::list_dir_begin() {
list_dir_end(); //close any previous dir opening!
// char real_current_dir_name[2048]; //is this enough?!
//getcwd(real_current_dir_name,2048);
//chdir(curent_path.utf8().get_data());
dir_stream = opendir(current_dir.utf8().get_data());
//chdir(real_current_dir_name);
if (!dir_stream)
return true; //error!
return false;
}
bool DirAccessOSX::file_exists(String p_file) {
GLOBAL_LOCK_FUNCTION
if (p_file.is_rel_path())
p_file=current_dir+"/"+p_file;
else
p_file=fix_path(p_file);
struct stat flags;
bool success = (stat(p_file.utf8().get_data(),&flags)==0);
if (success && S_ISDIR(flags.st_mode)) {
success=false;
}
return success;
}
bool DirAccessOSX::dir_exists(String p_dir) {
GLOBAL_LOCK_FUNCTION
if (p_dir.is_rel_path())
p_dir=get_current_dir().plus_file(p_dir);
else
p_dir=fix_path(p_dir);
struct stat flags;
bool success = (stat(p_dir.utf8().get_data(),&flags)==0);
if (success && S_ISDIR(flags.st_mode))
return true;
return false;
}
uint64_t DirAccessOSX::get_modified_time(String p_file) {
if (p_file.is_rel_path())
p_file=current_dir+"/"+p_file;
else
p_file=fix_path(p_file);
struct stat flags;
bool success = (stat(p_file.utf8().get_data(),&flags)==0);
if (success) {
return flags.st_mtime;
} else {
ERR_FAIL_V(0);
};
return 0;
};
String DirAccessOSX::get_next() {
if (!dir_stream)
return "";
dirent *entry;
entry=readdir(dir_stream);
if (entry==NULL) {
list_dir_end();
return "";
}
//typedef struct stat Stat;
struct stat flags;
String fname; String fname;
NSString* nsstr = [[NSString stringWithUTF8String: entry->d_name] precomposedStringWithCanonicalMapping]; NSString* nsstr = [[NSString stringWithUTF8String: p_name] precomposedStringWithCanonicalMapping];
fname.parse_utf8([nsstr UTF8String]); fname.parse_utf8([nsstr UTF8String]);
//[nsstr autorelease];
String f=current_dir+"/"+fname;
if (stat(f.utf8().get_data(),&flags)==0) {
if (S_ISDIR(flags.st_mode)) {
_cisdir=true;
} else {
_cisdir=false;
}
} else {
_cisdir=false;
}
_cishidden=(fname!="." && fname!=".." && fname.begins_with("."));
return fname; return fname;
} }
bool DirAccessOSX::current_is_dir() const {
return _cisdir;
}
bool DirAccessOSX::current_is_hidden() const {
return _cishidden;
}
void DirAccessOSX::list_dir_end() {
if (dir_stream)
closedir(dir_stream);
dir_stream=0;
_cisdir=false;
}
int DirAccessOSX::get_drive_count() {
return 0;
}
String DirAccessOSX::get_drive(int p_drive) {
return "";
}
Error DirAccessOSX::make_dir(String p_dir) {
GLOBAL_LOCK_FUNCTION
p_dir=fix_path(p_dir);
char real_current_dir_name[2048];
getcwd(real_current_dir_name,2048);
chdir(current_dir.utf8().get_data()); //ascii since this may be unicode or wathever the host os wants
bool success=(mkdir(p_dir.utf8().get_data(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)==0);
int err = errno;
chdir(real_current_dir_name);
if (success) {
return OK;
};
if (err == EEXIST) {
return ERR_ALREADY_EXISTS;
};
return ERR_CANT_CREATE;
}
Error DirAccessOSX::change_dir(String p_dir) {
GLOBAL_LOCK_FUNCTION
p_dir=fix_path(p_dir);
char real_current_dir_name[2048];
getcwd(real_current_dir_name,2048);
String prev_dir;
if (prev_dir.parse_utf8(real_current_dir_name))
prev_dir=real_current_dir_name; //no utf8, maybe latin?
chdir(current_dir.utf8().get_data()); //ascii since this may be unicode or wathever the host os wants
bool worked=(chdir(p_dir.utf8().get_data())==0); // we can only give this utf8
#ifndef IPHONE_ENABLED
String base = _get_root_path();
if (base!="") {
getcwd(real_current_dir_name,2048);
String new_dir;
new_dir.parse_utf8(real_current_dir_name);
if (!new_dir.begins_with(base))
worked=false;
}
#endif
if (worked) {
getcwd(real_current_dir_name,2048);
if (current_dir.parse_utf8(real_current_dir_name))
current_dir=real_current_dir_name; //no utf8, maybe latin?
}
chdir(prev_dir.utf8().get_data());
return worked?OK:ERR_INVALID_PARAMETER;
}
String DirAccessOSX::get_current_dir() {
String base = _get_root_path();
if (base!="") {
String bd = current_dir.replace_first(base,"");
if (bd.begins_with("/"))
return _get_root_string()+bd.substr(1,bd.length());
else
return _get_root_string()+bd;
}
return current_dir;
}
Error DirAccessOSX::rename(String p_path,String p_new_path) {
if (p_path.is_rel_path())
p_path=get_current_dir().plus_file(p_path);
else
p_path=fix_path(p_path);
if (p_new_path.is_rel_path())
p_new_path=get_current_dir().plus_file(p_new_path);
else
p_new_path=fix_path(p_new_path);
return ::rename(p_path.utf8().get_data(),p_new_path.utf8().get_data())==0?OK:FAILED;
}
Error DirAccessOSX::remove(String p_path) {
if (p_path.is_rel_path())
p_path=get_current_dir().plus_file(p_path);
else
p_path=fix_path(p_path);
struct stat flags;
if ((stat(p_path.utf8().get_data(),&flags)!=0))
return FAILED;
if (S_ISDIR(flags.st_mode))
return ::rmdir(p_path.utf8().get_data())==0?OK:FAILED;
else
return ::unlink(p_path.utf8().get_data())==0?OK:FAILED;
}
size_t DirAccessOSX::get_space_left() {
#ifndef NO_STATVFS
struct statvfs vfs;
if (statvfs(current_dir.utf8().get_data(), &vfs) != 0) {
return 0;
};
return (size_t) (vfs.f_bavail * vfs.f_bsize);
#else
#warning THIS IS BROKEN
return 0;
#endif
};
DirAccessOSX::DirAccessOSX() {
dir_stream=0;
current_dir=".";
_cisdir=false;
/* determine drive count */
change_dir(current_dir);
}
DirAccessOSX::~DirAccessOSX() {
list_dir_end();
}
#endif //posix_enabled #endif //posix_enabled

View File

@ -743,100 +743,6 @@ void EditorNode::_set_scene_metadata(const String& p_file) {
} }
static Error _fix_object_paths(Object* obj, Node* root, String save_path) {
Globals* g = Globals::get_singleton();
String import_dir = root->get_meta("__editor_import_file__");
import_dir = import_dir.get_base_dir();
import_dir = DirAccess::normalize_path(import_dir);
if (import_dir[import_dir.length()-1] != '/') {
import_dir = import_dir + "/";
};
String resource_dir = DirAccess::normalize_path(g->get_resource_path());
if (resource_dir[resource_dir.length()-1] != '/') {
resource_dir = resource_dir + "/";
};
List<PropertyInfo> list;
obj->get_property_list(&list, false);
List<PropertyInfo>::Element *E = list.front();
while (E) {
Variant v = obj->get(E->get().name);
if (v.get_type() == Variant::OBJECT) {
Ref<Resource> res = (RefPtr)v;
if (res.is_null()) {
E = E->next();
continue;
}
if (res->get_path() != "") {
String res_path = res->get_path();
res_path = Globals::get_singleton()->globalize_path(res_path);
res_path = DirAccess::normalize_path(res_path);
if (res_path.find(resource_dir) != 0) {
// path of resource is not inside engine's resource path
String new_path;
if (res_path.find(import_dir) == 0) {
// path of resource is relative to path of import file
new_path = save_path + "/" + res_path.substr(import_dir.length(), res_path.length() - import_dir.length());
} else {
// path of resource is not relative to import file
new_path = save_path + "/" + res_path.get_file();
};
res->set_path(g->localize_path(new_path));
DirAccess* d = DirAccess::create(DirAccess::ACCESS_RESOURCES);
d->make_dir_recursive(new_path.get_base_dir());
printf("copying from %ls to %ls\n", res_path.c_str(), new_path.c_str());
Error err = d->copy(res_path, new_path);
memdelete(d);
ERR_FAIL_COND_V(err != OK, err);
}
} else {
_fix_object_paths(res.operator->(), root, save_path);
};
};
E = E->next();
};
return OK;
};
static Error _fix_imported_scene_paths(Node* node, Node* root, String save_path) {
if (node == root || node->get_owner() == root) {
Error e = _fix_object_paths(node, root, save_path);
ERR_FAIL_COND_V(e != OK, e);
};
for (int i=0; i<node->get_child_count(); i++) {
Error e = _fix_imported_scene_paths(node->get_child(i), root, save_path);
ERR_FAIL_COND_V(e != OK, e);
};
return OK;
};
bool EditorNode::_find_and_save_resource(RES res,Map<RES,bool>& processed,int32_t flags) { bool EditorNode::_find_and_save_resource(RES res,Map<RES,bool>& processed,int32_t flags) {