mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 08:44:19 -04:00
support windows unicode filenames
This commit is contained in:
parent
a37e44c7c5
commit
7667709357
@ -161,6 +161,31 @@ expand_string(const string &str) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
Filename ExecutionEnvironment::
|
||||
get_cwd() {
|
||||
#ifdef WIN32_VC
|
||||
// getcwd() requires us to allocate a dynamic buffer and grow it on
|
||||
// demand.
|
||||
static size_t bufsize = 1024;
|
||||
static wchar_t *buffer = NULL;
|
||||
|
||||
if (buffer == (wchar_t *)NULL) {
|
||||
buffer = new wchar_t[bufsize];
|
||||
}
|
||||
|
||||
while (_wgetcwd(buffer, bufsize) == (wchar_t *)NULL) {
|
||||
if (errno != ERANGE) {
|
||||
perror("getcwd");
|
||||
return string();
|
||||
}
|
||||
delete[] buffer;
|
||||
bufsize = bufsize * 2;
|
||||
buffer = new wchar_t[bufsize];
|
||||
assert(buffer != (wchar_t *)NULL);
|
||||
}
|
||||
|
||||
Filename cwd = Filename::from_os_specific_w(buffer);
|
||||
cwd.make_true_case();
|
||||
return cwd;
|
||||
#else // WIN32_VC
|
||||
// getcwd() requires us to allocate a dynamic buffer and grow it on
|
||||
// demand.
|
||||
static size_t bufsize = 1024;
|
||||
@ -184,6 +209,7 @@ get_cwd() {
|
||||
Filename cwd = Filename::from_os_specific(buffer);
|
||||
cwd.make_true_case();
|
||||
return cwd;
|
||||
#endif // WIN32_VC
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -233,6 +259,7 @@ ns_get_environment_variable(const string &var) const {
|
||||
if (!ns_has_environment_variable("PANDA_INCOMPATIBLE_PYTHON") && Py_IsInitialized()) {
|
||||
PyObject* obj = PySys_GetObject((char*) "argv");
|
||||
if (obj) {
|
||||
// Hmm, could this ever be a Unicode object?
|
||||
Filename main_dir = Filename::from_os_specific(PyString_AsString(PyList_GetItem(obj, 0)));
|
||||
if (main_dir.empty()) {
|
||||
// We must be running in the Python interpreter directly, so return the CWD.
|
||||
@ -479,10 +506,10 @@ read_args() {
|
||||
#endif
|
||||
if (dllhandle != 0) {
|
||||
static const DWORD buffer_size = 1024;
|
||||
char buffer[buffer_size];
|
||||
DWORD size = GetModuleFileName(dllhandle, buffer, buffer_size);
|
||||
wchar_t buffer[buffer_size];
|
||||
DWORD size = GetModuleFileNameW(dllhandle, buffer, buffer_size);
|
||||
if (size != 0) {
|
||||
Filename tmp = Filename::from_os_specific(string(buffer, size));
|
||||
Filename tmp = Filename::from_os_specific_w(wstring(buffer, size));
|
||||
tmp.make_true_case();
|
||||
_dtool_name = tmp;
|
||||
}
|
||||
@ -557,10 +584,10 @@ read_args() {
|
||||
#ifdef WIN32_VC
|
||||
if (_binary_name.empty()) {
|
||||
static const DWORD buffer_size = 1024;
|
||||
char buffer[buffer_size];
|
||||
DWORD size = GetModuleFileName(NULL, buffer, buffer_size);
|
||||
wchar_t buffer[buffer_size];
|
||||
DWORD size = GetModuleFileNameW(NULL, buffer, buffer_size);
|
||||
if (size != 0) {
|
||||
Filename tmp = Filename::from_os_specific(string(buffer, size));
|
||||
Filename tmp = Filename::from_os_specific_w(wstring(buffer, size));
|
||||
tmp.make_true_case();
|
||||
_binary_name = tmp;
|
||||
}
|
||||
|
@ -522,11 +522,11 @@ get_home_directory() {
|
||||
|
||||
if (home_directory.empty()) {
|
||||
#ifdef WIN32
|
||||
char buffer[MAX_PATH];
|
||||
wchar_t buffer[MAX_PATH];
|
||||
|
||||
// On Windows, fall back to the "My Documents" folder.
|
||||
if (SHGetSpecialFolderPath(NULL, buffer, CSIDL_PERSONAL, true)) {
|
||||
Filename dirname = from_os_specific(buffer);
|
||||
if (SHGetSpecialFolderPathW(NULL, buffer, CSIDL_PERSONAL, true)) {
|
||||
Filename dirname = from_os_specific_w(buffer);
|
||||
if (dirname.is_directory()) {
|
||||
if (dirname.make_canonical()) {
|
||||
home_directory = dirname;
|
||||
@ -572,9 +572,9 @@ get_temp_directory() {
|
||||
|
||||
#ifdef WIN32
|
||||
static const size_t buffer_size = 4096;
|
||||
char buffer[buffer_size];
|
||||
if (GetTempPath(buffer_size, buffer) != 0) {
|
||||
Filename dirname = from_os_specific(buffer);
|
||||
wchar_t buffer[buffer_size];
|
||||
if (GetTempPathW(buffer_size, buffer) != 0) {
|
||||
Filename dirname = from_os_specific_w(buffer);
|
||||
if (dirname.is_directory()) {
|
||||
if (dirname.make_canonical()) {
|
||||
temp_directory = dirname;
|
||||
@ -620,10 +620,10 @@ get_user_appdata_directory() {
|
||||
Filename user_appdata_directory;
|
||||
|
||||
#ifdef WIN32
|
||||
char buffer[MAX_PATH];
|
||||
wchar_t buffer[MAX_PATH];
|
||||
|
||||
if (SHGetSpecialFolderPath(NULL, buffer, CSIDL_LOCAL_APPDATA, true)) {
|
||||
Filename dirname = from_os_specific(buffer);
|
||||
if (SHGetSpecialFolderPathW(NULL, buffer, CSIDL_LOCAL_APPDATA, true)) {
|
||||
Filename dirname = from_os_specific_w(buffer);
|
||||
if (dirname.is_directory()) {
|
||||
if (dirname.make_canonical()) {
|
||||
user_appdata_directory = dirname;
|
||||
@ -669,10 +669,10 @@ get_common_appdata_directory() {
|
||||
Filename common_appdata_directory;
|
||||
|
||||
#ifdef WIN32
|
||||
char buffer[MAX_PATH];
|
||||
wchar_t buffer[MAX_PATH];
|
||||
|
||||
if (SHGetSpecialFolderPath(NULL, buffer, CSIDL_COMMON_APPDATA, true)) {
|
||||
Filename dirname = from_os_specific(buffer);
|
||||
if (SHGetSpecialFolderPathW(NULL, buffer, CSIDL_COMMON_APPDATA, true)) {
|
||||
Filename dirname = from_os_specific_w(buffer);
|
||||
if (dirname.is_directory()) {
|
||||
if (dirname.make_canonical()) {
|
||||
common_appdata_directory = dirname;
|
||||
@ -1126,14 +1126,14 @@ make_true_case() {
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
string os_specific = to_os_specific();
|
||||
wstring os_specific = to_os_specific_w();
|
||||
|
||||
// First, we have to convert it to its short name, then back to its
|
||||
// long name--that seems to be the trick to force Windows to throw
|
||||
// away the case we give it and get the actual file case.
|
||||
|
||||
char short_name[MAX_PATH + 1];
|
||||
DWORD l = GetShortPathName(os_specific.c_str(), short_name, MAX_PATH + 1);
|
||||
wchar_t short_name[MAX_PATH + 1];
|
||||
DWORD l = GetShortPathNameW(os_specific.c_str(), short_name, MAX_PATH + 1);
|
||||
if (l == 0) {
|
||||
// Couldn't query the path name for some reason. Probably the
|
||||
// file didn't exist.
|
||||
@ -1144,8 +1144,8 @@ make_true_case() {
|
||||
// according to the Windows docs, MAX_PATH will always be enough.
|
||||
assert(l < MAX_PATH + 1);
|
||||
|
||||
char long_name[MAX_PATH + 1];
|
||||
l = GetLongPathName(short_name, long_name, MAX_PATH + 1);
|
||||
wchar_t long_name[MAX_PATH + 1];
|
||||
l = GetLongPathNameW(short_name, long_name, MAX_PATH + 1);
|
||||
if (l == 0) {
|
||||
// Couldn't query the path name for some reason. Probably the
|
||||
// file didn't exist.
|
||||
@ -1153,15 +1153,15 @@ make_true_case() {
|
||||
}
|
||||
assert(l < MAX_PATH + 1);
|
||||
|
||||
Filename true_case = Filename::from_os_specific(long_name);
|
||||
Filename true_case = Filename::from_os_specific_w(long_name);
|
||||
|
||||
// Now sanity-check the true-case filename. If it's not the same as
|
||||
// the source file, except for case, reject it.
|
||||
string orig_filename = get_fullpath();
|
||||
string new_filename = true_case.get_fullpath();
|
||||
wstring orig_filename = get_fullpath_w();
|
||||
wstring new_filename = true_case.get_fullpath_w();
|
||||
bool match = (orig_filename.length() == new_filename.length());
|
||||
for (size_t i = 0; i < orig_filename.length() && match; ++i) {
|
||||
match = (tolower(orig_filename[i]) == tolower(new_filename[i]));
|
||||
match = (TextEncoder::unicode_tolower(orig_filename[i]) == TextEncoder::unicode_tolower(new_filename[i]));
|
||||
}
|
||||
if (!match) {
|
||||
// Something went wrong. Keep the original filename, assume it
|
||||
@ -1287,21 +1287,24 @@ to_os_short_name() const {
|
||||
assert(!get_pattern());
|
||||
|
||||
#ifdef WIN32
|
||||
string os_specific = to_os_specific();
|
||||
wstring os_specific = to_os_specific_w();
|
||||
|
||||
char short_name[MAX_PATH + 1];
|
||||
DWORD l = GetShortPathName(os_specific.c_str(), short_name, MAX_PATH + 1);
|
||||
wchar_t short_name[MAX_PATH + 1];
|
||||
DWORD l = GetShortPathNameW(os_specific.c_str(), short_name, MAX_PATH + 1);
|
||||
if (l == 0) {
|
||||
// Couldn't query the path name for some reason. Probably the
|
||||
// file didn't exist.
|
||||
return os_specific;
|
||||
return to_os_specific();
|
||||
}
|
||||
// According to the Windows docs, l will return a value greater than
|
||||
// the specified length if the short_name length wasn't enough--but also
|
||||
// according to the Windows docs, MAX_PATH will always be enough.
|
||||
assert(l < MAX_PATH + 1);
|
||||
|
||||
return string(short_name);
|
||||
TextEncoder encoder;
|
||||
encoder.set_encoding(get_filesystem_encoding());
|
||||
encoder.set_wtext(short_name);
|
||||
return encoder.get_text();
|
||||
|
||||
#else // WIN32
|
||||
return to_os_specific();
|
||||
@ -1321,18 +1324,21 @@ to_os_long_name() const {
|
||||
assert(!get_pattern());
|
||||
|
||||
#ifdef WIN32
|
||||
string os_specific = to_os_specific();
|
||||
wstring os_specific = to_os_specific_w();
|
||||
|
||||
char long_name[MAX_PATH + 1];
|
||||
DWORD l = GetLongPathName(os_specific.c_str(), long_name, MAX_PATH + 1);
|
||||
wchar_t long_name[MAX_PATH + 1];
|
||||
DWORD l = GetLongPathNameW(os_specific.c_str(), long_name, MAX_PATH + 1);
|
||||
if (l == 0) {
|
||||
// Couldn't query the path name for some reason. Probably the
|
||||
// file didn't exist.
|
||||
return os_specific;
|
||||
return to_os_specific();
|
||||
}
|
||||
assert(l < MAX_PATH + 1);
|
||||
|
||||
return string(long_name);
|
||||
TextEncoder encoder;
|
||||
encoder.set_encoding(get_filesystem_encoding());
|
||||
encoder.set_wtext(long_name);
|
||||
return encoder.get_text();
|
||||
|
||||
#else // WIN32
|
||||
return to_os_specific();
|
||||
@ -1349,17 +1355,19 @@ to_os_long_name() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Filename::
|
||||
exists() const {
|
||||
string os_specific = get_filename_index(0).to_os_specific();
|
||||
|
||||
#ifdef WIN32_VC
|
||||
wstring os_specific = get_filename_index(0).to_os_specific_w();
|
||||
|
||||
bool exists = false;
|
||||
|
||||
DWORD results = GetFileAttributes(os_specific.c_str());
|
||||
DWORD results = GetFileAttributesW(os_specific.c_str());
|
||||
if (results != -1) {
|
||||
exists = true;
|
||||
}
|
||||
|
||||
#else // WIN32_VC
|
||||
string os_specific = get_filename_index(0).to_os_specific();
|
||||
|
||||
struct stat this_buf;
|
||||
bool exists = false;
|
||||
|
||||
@ -1380,17 +1388,19 @@ exists() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Filename::
|
||||
is_regular_file() const {
|
||||
string os_specific = get_filename_index(0).to_os_specific();
|
||||
|
||||
#ifdef WIN32_VC
|
||||
wstring os_specific = get_filename_index(0).to_os_specific_w();
|
||||
|
||||
bool isreg = false;
|
||||
|
||||
DWORD results = GetFileAttributes(os_specific.c_str());
|
||||
DWORD results = GetFileAttributesW(os_specific.c_str());
|
||||
if (results != -1) {
|
||||
isreg = ((results & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE)) == 0);
|
||||
}
|
||||
|
||||
#else // WIN32_VC
|
||||
string os_specific = get_filename_index(0).to_os_specific();
|
||||
|
||||
struct stat this_buf;
|
||||
bool isreg = false;
|
||||
|
||||
@ -1410,16 +1420,18 @@ is_regular_file() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Filename::
|
||||
is_directory() const {
|
||||
string os_specific = get_filename_index(0).to_os_specific();
|
||||
|
||||
#ifdef WIN32_VC
|
||||
wstring os_specific = get_filename_index(0).to_os_specific_w();
|
||||
|
||||
bool isdir = false;
|
||||
|
||||
DWORD results = GetFileAttributes(os_specific.c_str());
|
||||
DWORD results = GetFileAttributesW(os_specific.c_str());
|
||||
if (results != -1) {
|
||||
isdir = (results & FILE_ATTRIBUTE_DIRECTORY) != 0;
|
||||
}
|
||||
#else // WIN32_VC
|
||||
string os_specific = get_filename_index(0).to_os_specific();
|
||||
|
||||
struct stat this_buf;
|
||||
bool isdir = false;
|
||||
|
||||
@ -1475,24 +1487,27 @@ int Filename::
|
||||
compare_timestamps(const Filename &other,
|
||||
bool this_missing_is_old,
|
||||
bool other_missing_is_old) const {
|
||||
string os_specific = get_filename_index(0).to_os_specific();
|
||||
string other_os_specific = other.get_filename_index(0).to_os_specific();
|
||||
|
||||
#ifdef WIN32_VC
|
||||
wstring os_specific = get_filename_index(0).to_os_specific_w();
|
||||
wstring other_os_specific = other.get_filename_index(0).to_os_specific_w();
|
||||
|
||||
struct _stat this_buf;
|
||||
bool this_exists = false;
|
||||
|
||||
if (_stat(os_specific.c_str(), &this_buf) == 0) {
|
||||
if (_wstat(os_specific.c_str(), &this_buf) == 0) {
|
||||
this_exists = true;
|
||||
}
|
||||
|
||||
struct _stat other_buf;
|
||||
bool other_exists = false;
|
||||
|
||||
if (_stat(other_os_specific.c_str(), &other_buf) == 0) {
|
||||
if (_wstat(other_os_specific.c_str(), &other_buf) == 0) {
|
||||
other_exists = true;
|
||||
}
|
||||
#else // WIN32_VC
|
||||
string os_specific = get_filename_index(0).to_os_specific();
|
||||
string other_os_specific = other.get_filename_index(0).to_os_specific();
|
||||
|
||||
struct stat this_buf;
|
||||
bool this_exists = false;
|
||||
|
||||
@ -1554,15 +1569,17 @@ compare_timestamps(const Filename &other,
|
||||
////////////////////////////////////////////////////////////////////
|
||||
time_t Filename::
|
||||
get_timestamp() const {
|
||||
string os_specific = get_filename_index(0).to_os_specific();
|
||||
|
||||
#ifdef WIN32_VC
|
||||
wstring os_specific = get_filename_index(0).to_os_specific_w();
|
||||
|
||||
struct _stat this_buf;
|
||||
|
||||
if (_stat(os_specific.c_str(), &this_buf) == 0) {
|
||||
if (_wstat(os_specific.c_str(), &this_buf) == 0) {
|
||||
return this_buf.st_mtime;
|
||||
}
|
||||
#else // WIN32_VC
|
||||
string os_specific = get_filename_index(0).to_os_specific();
|
||||
|
||||
struct stat this_buf;
|
||||
|
||||
if (stat(os_specific.c_str(), &this_buf) == 0) {
|
||||
@ -1583,15 +1600,17 @@ get_timestamp() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
time_t Filename::
|
||||
get_access_timestamp() const {
|
||||
string os_specific = get_filename_index(0).to_os_specific();
|
||||
|
||||
#ifdef WIN32_VC
|
||||
wstring os_specific = get_filename_index(0).to_os_specific_w();
|
||||
|
||||
struct _stat this_buf;
|
||||
|
||||
if (_stat(os_specific.c_str(), &this_buf) == 0) {
|
||||
if (_wstat(os_specific.c_str(), &this_buf) == 0) {
|
||||
return this_buf.st_atime;
|
||||
}
|
||||
#else // WIN32_VC
|
||||
string os_specific = get_filename_index(0).to_os_specific();
|
||||
|
||||
struct stat this_buf;
|
||||
|
||||
if (stat(os_specific.c_str(), &this_buf) == 0) {
|
||||
@ -1610,15 +1629,17 @@ get_access_timestamp() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
off_t Filename::
|
||||
get_file_size() const {
|
||||
string os_specific = get_filename_index(0).to_os_specific();
|
||||
|
||||
#ifdef WIN32_VC
|
||||
wstring os_specific = get_filename_index(0).to_os_specific_w();
|
||||
|
||||
struct _stat this_buf;
|
||||
|
||||
if (_stat(os_specific.c_str(), &this_buf) == 0) {
|
||||
if (_wstat(os_specific.c_str(), &this_buf) == 0) {
|
||||
return this_buf.st_size;
|
||||
}
|
||||
#else // WIN32_VC
|
||||
string os_specific = get_filename_index(0).to_os_specific();
|
||||
|
||||
struct stat this_buf;
|
||||
|
||||
if (stat(os_specific.c_str(), &this_buf) == 0) {
|
||||
@ -1801,15 +1822,15 @@ scan_directory(vector_string &contents) const {
|
||||
// list of files in a directory.
|
||||
size_t orig_size = contents.size();
|
||||
|
||||
string match;
|
||||
wstring match;
|
||||
if (empty()) {
|
||||
match = "*.*";
|
||||
match = L"*.*";
|
||||
} else {
|
||||
match = to_os_specific() + "\\*.*";
|
||||
match = to_os_specific_w() + L"\\*.*";
|
||||
}
|
||||
WIN32_FIND_DATA find_data;
|
||||
WIN32_FIND_DATAW find_data;
|
||||
|
||||
HANDLE handle = FindFirstFile(match.c_str(), &find_data);
|
||||
HANDLE handle = FindFirstFileW(match.c_str(), &find_data);
|
||||
if (handle == INVALID_HANDLE_VALUE) {
|
||||
if (GetLastError() == ERROR_NO_MORE_FILES) {
|
||||
// No matching files is not an error.
|
||||
@ -1818,13 +1839,16 @@ scan_directory(vector_string &contents) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
TextEncoder encoder;
|
||||
encoder.set_encoding(get_filesystem_encoding());
|
||||
do {
|
||||
thread_consider_yield();
|
||||
string filename = find_data.cFileName;
|
||||
if (filename != "." && filename != "..") {
|
||||
contents.push_back(filename);
|
||||
wstring filename = find_data.cFileName;
|
||||
if (filename != L"." && filename != L"..") {
|
||||
encoder.set_wtext(filename);
|
||||
contents.push_back(encoder.get_text());
|
||||
}
|
||||
} while (FindNextFile(handle, &find_data));
|
||||
} while (FindNextFileW(handle, &find_data));
|
||||
|
||||
bool scan_ok = (GetLastError() == ERROR_NO_MORE_FILES);
|
||||
FindClose(handle);
|
||||
@ -1980,9 +2004,15 @@ open_read(ifstream &stream) const {
|
||||
}
|
||||
#endif
|
||||
|
||||
string os_specific = to_os_specific();
|
||||
stream.clear();
|
||||
#ifdef WIN32_VC
|
||||
wstring os_specific = to_os_specific_w();
|
||||
stream.open(os_specific.c_str(), open_mode);
|
||||
#else
|
||||
string os_specific = to_os_specific();
|
||||
stream.open(os_specific.c_str(), open_mode);
|
||||
#endif // WIN32_VC
|
||||
|
||||
return (!stream.fail());
|
||||
}
|
||||
|
||||
@ -2031,12 +2061,17 @@ open_write(ofstream &stream, bool truncate) const {
|
||||
#endif
|
||||
|
||||
stream.clear();
|
||||
#ifdef WIN32_VC
|
||||
wstring os_specific = to_os_specific_w();
|
||||
stream.open(os_specific.c_str(), open_mode);
|
||||
#else
|
||||
string os_specific = to_os_specific();
|
||||
#ifdef HAVE_OPEN_MASK
|
||||
stream.open(os_specific.c_str(), open_mode, 0666);
|
||||
#else
|
||||
stream.open(os_specific.c_str(), open_mode);
|
||||
#endif
|
||||
#endif // WIN32_VC
|
||||
|
||||
return (!stream.fail());
|
||||
}
|
||||
@ -2068,12 +2103,17 @@ open_append(ofstream &stream) const {
|
||||
#endif
|
||||
|
||||
stream.clear();
|
||||
#ifdef WIN32_VC
|
||||
wstring os_specific = to_os_specific_w();
|
||||
stream.open(os_specific.c_str(), open_mode);
|
||||
#else
|
||||
string os_specific = to_os_specific();
|
||||
#ifdef HAVE_OPEN_MASK
|
||||
stream.open(os_specific.c_str(), open_mode, 0666);
|
||||
#else
|
||||
stream.open(os_specific.c_str(), open_mode);
|
||||
#endif
|
||||
#endif // WIN32_VC
|
||||
|
||||
return (!stream.fail());
|
||||
}
|
||||
@ -2115,12 +2155,17 @@ open_read_write(fstream &stream, bool truncate) const {
|
||||
#endif
|
||||
|
||||
stream.clear();
|
||||
#ifdef WIN32_VC
|
||||
wstring os_specific = to_os_specific_w();
|
||||
stream.open(os_specific.c_str(), open_mode);
|
||||
#else
|
||||
string os_specific = to_os_specific();
|
||||
#ifdef HAVE_OPEN_MASK
|
||||
stream.open(os_specific.c_str(), open_mode, 0666);
|
||||
#else
|
||||
stream.open(os_specific.c_str(), open_mode);
|
||||
#endif
|
||||
#endif // WIN32_VC
|
||||
|
||||
return (!stream.fail());
|
||||
}
|
||||
@ -2153,12 +2198,17 @@ open_read_append(fstream &stream) const {
|
||||
#endif
|
||||
|
||||
stream.clear();
|
||||
#ifdef WIN32_VC
|
||||
wstring os_specific = to_os_specific_w();
|
||||
stream.open(os_specific.c_str(), open_mode);
|
||||
#else
|
||||
string os_specific = to_os_specific();
|
||||
#ifdef HAVE_OPEN_MASK
|
||||
stream.open(os_specific.c_str(), open_mode, 0666);
|
||||
#else
|
||||
stream.open(os_specific.c_str(), open_mode);
|
||||
#endif
|
||||
#endif // WIN32_VC
|
||||
|
||||
return (!stream.fail());
|
||||
}
|
||||
@ -2397,10 +2447,10 @@ touch() const {
|
||||
// In Windows, we have to use the Windows API to do this reliably.
|
||||
|
||||
// First, guarantee the file exists (and also get its handle).
|
||||
string os_specific = to_os_specific();
|
||||
wstring os_specific = to_os_specific_w();
|
||||
HANDLE fhandle;
|
||||
fhandle = CreateFile(os_specific.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE,
|
||||
NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
fhandle = CreateFileW(os_specific.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE,
|
||||
NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (fhandle == INVALID_HANDLE_VALUE) {
|
||||
return false;
|
||||
}
|
||||
@ -2473,8 +2523,13 @@ touch() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Filename::
|
||||
chdir() const {
|
||||
#ifdef WIN32_VC
|
||||
wstring os_specific = to_os_specific_w();
|
||||
return (_wchdir(os_specific.c_str()) >= 0);
|
||||
#else
|
||||
string os_specific = to_os_specific();
|
||||
return (::chdir(os_specific.c_str()) >= 0);
|
||||
#endif // WIN32_VC
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -2488,12 +2543,15 @@ chdir() const {
|
||||
bool Filename::
|
||||
unlink() const {
|
||||
assert(!get_pattern());
|
||||
string os_specific = to_os_specific();
|
||||
#ifdef _WIN32
|
||||
#ifdef WIN32_VC
|
||||
// Windows can't delete a file if it's read-only. Weird.
|
||||
chmod(os_specific.c_str(), 0644);
|
||||
#endif
|
||||
wstring os_specific = to_os_specific_w();
|
||||
_wchmod(os_specific.c_str(), 0644);
|
||||
return (_wunlink(os_specific.c_str()) == 0);
|
||||
#else
|
||||
string os_specific = to_os_specific();
|
||||
return (::unlink(os_specific.c_str()) == 0);
|
||||
#endif // WIN32_VC
|
||||
}
|
||||
|
||||
|
||||
@ -2514,6 +2572,46 @@ rename_to(const Filename &other) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef WIN32_VC
|
||||
wstring os_specific = to_os_specific_w();
|
||||
wstring other_os_specific = other.to_os_specific_w();
|
||||
|
||||
if (_wrename(os_specific.c_str(),
|
||||
other_os_specific.c_str()) == 0) {
|
||||
// Successfully renamed.
|
||||
return true;
|
||||
}
|
||||
|
||||
// The above might fail if we have tried to move a file to a
|
||||
// different filesystem. In this case, copy the file into the same
|
||||
// directory first, and then rename it.
|
||||
string dirname = other.get_dirname();
|
||||
if (dirname.empty()) {
|
||||
dirname = ".";
|
||||
}
|
||||
Filename temp = Filename::temporary(dirname, "");
|
||||
temp.set_binary();
|
||||
if (!Filename::binary_filename(*this).copy_to(temp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
wstring temp_os_specific = temp.to_os_specific_w();
|
||||
if (_wrename(temp_os_specific.c_str(),
|
||||
other_os_specific.c_str()) == 0) {
|
||||
// Successfully renamed.
|
||||
unlink();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try unlinking the target first.
|
||||
other.unlink();
|
||||
if (_wrename(temp_os_specific.c_str(),
|
||||
other_os_specific.c_str()) == 0) {
|
||||
// Successfully renamed.
|
||||
unlink();
|
||||
return true;
|
||||
}
|
||||
#else // WIN32_VC
|
||||
string os_specific = to_os_specific();
|
||||
string other_os_specific = other.to_os_specific();
|
||||
|
||||
@ -2552,6 +2650,7 @@ rename_to(const Filename &other) const {
|
||||
unlink();
|
||||
return true;
|
||||
}
|
||||
#endif // WIN32_VC
|
||||
|
||||
// Failed.
|
||||
temp.unlink();
|
||||
@ -2644,23 +2743,25 @@ make_dir() const {
|
||||
size_t slash = dirname.find('/');
|
||||
while (slash != string::npos) {
|
||||
Filename component(dirname.substr(0, slash));
|
||||
string os_specific = component.to_os_specific();
|
||||
#ifndef WIN32_VC
|
||||
::mkdir(os_specific.c_str(), 0777);
|
||||
#ifdef WIN32_VC
|
||||
wstring os_specific = component.to_os_specific_w();
|
||||
_wmkdir(os_specific.c_str());
|
||||
#else
|
||||
::mkdir(os_specific.c_str());
|
||||
#endif
|
||||
string os_specific = component.to_os_specific();
|
||||
::mkdir(os_specific.c_str(), 0777);
|
||||
#endif // WIN32_VC
|
||||
slash = dirname.find('/', slash + 1);
|
||||
}
|
||||
|
||||
// Now make the last one, and check the return value.
|
||||
Filename component(dirname);
|
||||
string os_specific = component.to_os_specific();
|
||||
#ifndef WIN32_VC
|
||||
int result = ::mkdir(os_specific.c_str(), 0777);
|
||||
#ifdef WIN32_VC
|
||||
wstring os_specific = component.to_os_specific_w();
|
||||
int result = _wmkdir(os_specific.c_str());
|
||||
#else
|
||||
int result = ::mkdir(os_specific.c_str());
|
||||
#endif
|
||||
string os_specific = component.to_os_specific();
|
||||
int resutl = ::mkdir(os_specific.c_str(), 0777);
|
||||
#endif // WIN32_VC
|
||||
|
||||
return (result == 0);
|
||||
}
|
||||
@ -2676,12 +2777,13 @@ make_dir() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Filename::
|
||||
mkdir() const {
|
||||
string os_specific = to_os_specific();
|
||||
#ifndef WIN32_VC
|
||||
int result = ::mkdir(os_specific.c_str(), 0777);
|
||||
#ifdef WIN32_VC
|
||||
wstring os_specific = to_os_specific_w();
|
||||
int result = _wmkdir(os_specific.c_str());
|
||||
#else
|
||||
int result = ::mkdir(os_specific.c_str());
|
||||
#endif
|
||||
string os_specific = to_os_specific();
|
||||
int result = ::mkdir(os_specific.c_str(), 0777);
|
||||
#endif // WIN32_VC
|
||||
|
||||
return (result == 0);
|
||||
}
|
||||
@ -2694,18 +2796,21 @@ mkdir() const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool Filename::
|
||||
rmdir() const {
|
||||
string os_specific = to_os_specific();
|
||||
#ifdef WIN32_VC
|
||||
wstring os_specific = to_os_specific_w();
|
||||
|
||||
int result = ::rmdir(os_specific.c_str());
|
||||
|
||||
#ifdef WIN32
|
||||
int result = _wrmdir(os_specific.c_str());
|
||||
if (result != 0) {
|
||||
// Windows may require the directory to be writable before we can
|
||||
// remove it.
|
||||
chmod(os_specific.c_str(), 0777);
|
||||
result = ::rmdir(os_specific.c_str());
|
||||
_wchmod(os_specific.c_str(), 0777);
|
||||
result = _wrmdir(os_specific.c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
#else // WIN32_VC
|
||||
string os_specific = to_os_specific();
|
||||
int result = ::rmdir(os_specific.c_str());
|
||||
#endif // WIN32_VC
|
||||
|
||||
return (result == 0);
|
||||
}
|
||||
@ -2792,18 +2897,18 @@ atomic_compare_and_exchange_contents(string &orig_contents,
|
||||
const string &old_contents,
|
||||
const string &new_contents) const {
|
||||
#ifdef WIN32_VC
|
||||
string os_specific = to_os_specific();
|
||||
HANDLE hfile = CreateFile(os_specific.c_str(), GENERIC_READ | GENERIC_WRITE,
|
||||
0, NULL, OPEN_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
wstring os_specific = to_os_specific_w();
|
||||
HANDLE hfile = CreateFileW(os_specific.c_str(), GENERIC_READ | GENERIC_WRITE,
|
||||
0, NULL, OPEN_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
while (hfile == INVALID_HANDLE_VALUE) {
|
||||
DWORD error = GetLastError();
|
||||
if (error == ERROR_SHARING_VIOLATION) {
|
||||
// If the file is locked by another process, yield and try again.
|
||||
Sleep(0);
|
||||
hfile = CreateFile(os_specific.c_str(), GENERIC_READ | GENERIC_WRITE,
|
||||
0, NULL, OPEN_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
hfile = CreateFileW(os_specific.c_str(), GENERIC_READ | GENERIC_WRITE,
|
||||
0, NULL, OPEN_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
} else {
|
||||
cerr << "Couldn't open file: " << os_specific
|
||||
<< ", error " << error << "\n";
|
||||
@ -2929,18 +3034,18 @@ atomic_compare_and_exchange_contents(string &orig_contents,
|
||||
bool Filename::
|
||||
atomic_read_contents(string &contents) const {
|
||||
#ifdef WIN32_VC
|
||||
string os_specific = to_os_specific();
|
||||
HANDLE hfile = CreateFile(os_specific.c_str(), GENERIC_READ,
|
||||
FILE_SHARE_READ, NULL, OPEN_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
wstring os_specific = to_os_specific_w();
|
||||
HANDLE hfile = CreateFileW(os_specific.c_str(), GENERIC_READ,
|
||||
FILE_SHARE_READ, NULL, OPEN_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
while (hfile == INVALID_HANDLE_VALUE) {
|
||||
DWORD error = GetLastError();
|
||||
if (error == ERROR_SHARING_VIOLATION) {
|
||||
// If the file is locked by another process, yield and try again.
|
||||
Sleep(0);
|
||||
hfile = CreateFile(os_specific.c_str(), GENERIC_READ,
|
||||
FILE_SHARE_READ, NULL, OPEN_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
hfile = CreateFileW(os_specific.c_str(), GENERIC_READ,
|
||||
FILE_SHARE_READ, NULL, OPEN_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
} else {
|
||||
cerr << "Couldn't open file: " << os_specific
|
||||
<< ", error " << error << "\n";
|
||||
@ -3210,9 +3315,23 @@ r_make_canonical(const Filename &cwd) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef WIN32_VC
|
||||
// First, try to cd to the filename directly.
|
||||
wstring os_specific = to_os_specific_w();
|
||||
if (_wchdir(os_specific.c_str()) >= 0) {
|
||||
// That worked, save the full path string.
|
||||
(*this) = ExecutionEnvironment::get_cwd();
|
||||
|
||||
// And restore the current working directory.
|
||||
wstring osdir = cwd.to_os_specific_w();
|
||||
if (_wchdir(osdir.c_str()) < 0) {
|
||||
cerr << "Error! Cannot change back to " << osdir << "\n";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#else // WIN32_VC
|
||||
// First, try to cd to the filename directly.
|
||||
string os_specific = to_os_specific();
|
||||
|
||||
if (::chdir(os_specific.c_str()) >= 0) {
|
||||
// That worked, save the full path string.
|
||||
(*this) = ExecutionEnvironment::get_cwd();
|
||||
@ -3224,6 +3343,7 @@ r_make_canonical(const Filename &cwd) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif // WIN32_VC
|
||||
|
||||
// That didn't work; maybe it's not a directory. Recursively go to
|
||||
// the directory above.
|
||||
|
@ -14,6 +14,8 @@
|
||||
|
||||
#include "pandaFileStreamBuf.h"
|
||||
#include "memoryHook.h"
|
||||
#include "filename.h"
|
||||
#include "textEncoder.h"
|
||||
|
||||
#ifdef USE_PANDAFILESTREAM
|
||||
|
||||
@ -133,8 +135,12 @@ open(const char *filename, ios::openmode mode) {
|
||||
flags |= FILE_FLAG_OVERLAPPED;
|
||||
#endif
|
||||
|
||||
_handle = CreateFile(_filename.c_str(), access, share_mode,
|
||||
NULL, creation_disposition, flags, NULL);
|
||||
TextEncoder encoder;
|
||||
encoder.set_encoding(Filename::get_filesystem_encoding());
|
||||
encoder.set_text(_filename);
|
||||
wstring wfilename = encoder.get_wtext();
|
||||
_handle = CreateFileW(wfilename.c_str(), access, share_mode,
|
||||
NULL, creation_disposition, flags, NULL);
|
||||
if (_handle != INVALID_HANDLE_VALUE) {
|
||||
// The file was successfully opened and locked.
|
||||
_is_open = true;
|
||||
|
Loading…
x
Reference in New Issue
Block a user