diff options
author | Bert Belder <bertbelder@gmail.com> | 2011-11-24 02:38:34 +0100 |
---|---|---|
committer | Bert Belder <bertbelder@gmail.com> | 2011-11-24 02:38:34 +0100 |
commit | 86fba381fdeadc00921d34024bdef357e6a56e6e (patch) | |
tree | ed35164340f0bb27fed3ca58de85160fa59941ad /src | |
parent | cbcf4fe768fc9e046d18e58510c77de17c83ed4d (diff) | |
download | node-new-86fba381fdeadc00921d34024bdef357e6a56e6e.tar.gz |
Windows: correctly resolve drive-relative paths
Diffstat (limited to 'src')
-rw-r--r-- | src/node.cc | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/src/node.cc b/src/node.cc index 1f5e2c9aba..d61fd82a95 100644 --- a/src/node.cc +++ b/src/node.cc @@ -1178,6 +1178,76 @@ static Handle<Value> Cwd(const Arguments& args) { return scope.Close(cwd); } +#ifdef _WIN32 +static Handle<Value> CwdForDrive(const Arguments& args) { + HandleScope scope; + + if (args.Length() < 1) { + Local<Value> exception = Exception::Error( + String::New("process._cwdForDrive takes exactly 1 argument.")); + return ThrowException(exception); + } + + Local<String> driveLetter = args[0]->ToString(); + if (driveLetter->Length() != 1) { + Local<Value> exception = Exception::Error( + String::New("Drive name should be 1 character.")); + return ThrowException(exception); + } + + char drive; + + driveLetter->WriteAscii(&drive, 0, 1, 0); + if (drive >= 'a' && drive <= 'z') { + // Convert to uppercase + drive += 'A' - 'a'; + } else if (drive < 'A' || drive > 'Z') { + // Not a letter + Local<Value> exception = Exception::Error( + String::New("Drive name should be a letter.")); + return ThrowException(exception); + } + + WCHAR env_key[] = L"=X:"; + env_key[1] = (WCHAR) drive; + + DWORD len = GetEnvironmentVariableW(env_key, NULL, 0); + if (len == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND) { + // There is no current directory for that drive. Default to drive + ":\". + Local<String> cwd = String::Concat(String::New(&drive, 1), + String::New(":\\")); + return scope.Close(cwd); + + } else if (len == 0) { + // Error + Local<Value> exception = Exception::Error( + String::New(winapi_strerror(GetLastError()))); + return ThrowException(exception); + } + + WCHAR* buffer = new WCHAR[len]; + if (buffer == NULL) { + Local<Value> exception = Exception::Error( + String::New("Out of memory.")); + return ThrowException(exception); + } + + DWORD len2 = GetEnvironmentVariableW(env_key, buffer, len); + if (len2 == 0 || len2 >= len) { + // Error + delete[] buffer; + Local<Value> exception = Exception::Error( + String::New(winapi_strerror(GetLastError()))); + return ThrowException(exception); + } + + Local<String> cwd = String::New(reinterpret_cast<uint16_t*>(buffer), len2); + delete[] buffer; + return scope.Close(cwd); +} +#endif + + static Handle<Value> Umask(const Arguments& args) { HandleScope scope; unsigned int old; @@ -1931,6 +2001,10 @@ Handle<Object> SetupProcessObject(int argc, char *argv[]) { NODE_SET_METHOD(process, "chdir", Chdir); NODE_SET_METHOD(process, "cwd", Cwd); +#ifdef _WIN32 + NODE_SET_METHOD(process, "_cwdForDrive", CwdForDrive); +#endif + NODE_SET_METHOD(process, "umask", Umask); #ifdef __POSIX__ |