support windows unicode filenames

This commit is contained in:
David Rose 2011-08-29 18:56:32 +00:00
parent a37e44c7c5
commit 7667709357
3 changed files with 269 additions and 116 deletions

View File

@ -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;
}

View File

@ -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.

View File

@ -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;