aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/native
diff options
context:
space:
mode:
authorGravatar Laszlo Csomor <laszlocsomor@google.com>2016-12-06 17:24:53 +0000
committerGravatar Damien Martin-Guillerez <dmarting@google.com>2016-12-06 18:29:11 +0000
commit4e33ac6326ce93ab1645b5caccb4582ddb6fe9a4 (patch)
tree78690858ede8c3b5367cf53191cbb206d8eed982 /src/main/native
parent12d766df10fbc5eba16ec1e6c20c8cd85f9c616f (diff)
Windows JNI library: prepare for widechar WinAPI
This change: - renames windows_error_handling.* to windows_util.* - moves most stuff except for the JNI method implementations into the new windows_util namespace - implements a jstring to wchar string converter - uses GetFileAttributesW in windows_file_operations.cc See https://github.com/bazelbuild/bazel/issues/2181 -- PiperOrigin-RevId: 141187291 MOS_MIGRATED_REVID=141187291
Diffstat (limited to 'src/main/native')
-rw-r--r--src/main/native/windows_file_operations.cc33
-rw-r--r--src/main/native/windows_processes.cc37
-rw-r--r--src/main/native/windows_util.cc (renamed from src/main/native/windows_error_handling.cc)25
-rw-r--r--src/main/native/windows_util.h (renamed from src/main/native/windows_error_handling.h)20
4 files changed, 80 insertions, 35 deletions
diff --git a/src/main/native/windows_file_operations.cc b/src/main/native/windows_file_operations.cc
index cbec4715c0..9f74293c9f 100644
--- a/src/main/native/windows_file_operations.cc
+++ b/src/main/native/windows_file_operations.cc
@@ -15,9 +15,12 @@
#include <jni.h>
#include <windows.h>
+#include <memory>
#include <string>
-#include "src/main/native/windows_error_handling.h"
+#include "src/main/native/windows_util.h"
+
+namespace windows_util {
// Keep in sync with j.c.g.devtools.build.lib.windows.WindowsFileOperations
enum {
@@ -28,6 +31,9 @@ enum {
// Determines whether `path` is a junction point or directory symlink.
//
+// Uses the `GetFileAttributesW` WinAPI function.
+// `path` should be a valid Windows-style or UNC path.
+//
// To read about differences between junction points and directory symlinks,
// see http://superuser.com/a/343079.
//
@@ -39,8 +45,8 @@ enum {
// created using "mklink" instead of "mklink /d", as such symlinks don't
// behave the same way as directories (e.g. they can't be listed)
// - IS_JUNCTION_ERROR, if `path` doesn't exist or some error occurred
-int IsJunctionOrDirectorySymlink(const char* path) {
- DWORD attrs = GetFileAttributesA(path);
+static int IsJunctionOrDirectorySymlink(const wchar_t* path) {
+ DWORD attrs = GetFileAttributesW(path);
if (attrs == INVALID_FILE_ATTRIBUTES) {
return IS_JUNCTION_ERROR;
} else {
@@ -53,21 +59,26 @@ int IsJunctionOrDirectorySymlink(const char* path) {
}
}
+} // namespace windows_util
+
extern "C" JNIEXPORT jint JNICALL
Java_com_google_devtools_build_lib_windows_WindowsFileOperations_nativeIsJunction(
JNIEnv* env, jclass clazz, jstring path, jobjectArray error_msg_holder) {
- const char* path_cstr = env->GetStringUTFChars(path, NULL);
bool report_error =
error_msg_holder != NULL && env->GetArrayLength(error_msg_holder) > 0;
- int result = IsJunctionOrDirectorySymlink(path_cstr);
- if (result == IS_JUNCTION_ERROR && report_error) {
- std::string error_str =
- GetLastErrorString(std::string("GetFileAttributesA(") +
- std::string(path_cstr) + std::string(")"));
+ std::unique_ptr<wchar_t[]> long_path(
+ windows_util::JstringToWstring(env, path));
+ int result = windows_util::IsJunctionOrDirectorySymlink(long_path.get());
+ if (result == windows_util::IS_JUNCTION_ERROR && report_error) {
+ // Getting the string's characters again in UTF8 encoding is probably
+ // easier than converting `long_path` using `wcstombs(3)`.
+ const char* path_cstr = env->GetStringUTFChars(path, NULL);
+ std::string error_str = windows_util::GetLastErrorString(
+ std::string("GetFileAttributes(") + std::string(path_cstr) +
+ std::string(")"));
+ env->ReleaseStringUTFChars(path, path_cstr);
jstring error_msg = env->NewStringUTF(error_str.c_str());
env->SetObjectArrayElement(error_msg_holder, 0, error_msg);
}
-
- env->ReleaseStringUTFChars(path, path_cstr);
return result;
}
diff --git a/src/main/native/windows_processes.cc b/src/main/native/windows_processes.cc
index 9210d259aa..49355430e6 100644
--- a/src/main/native/windows_processes.cc
+++ b/src/main/native/windows_processes.cc
@@ -22,7 +22,7 @@
#include <atomic>
#include <string>
-#include "src/main/native/windows_error_handling.h"
+#include "src/main/native/windows_util.h"
extern "C" JNIEXPORT jint JNICALL
Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeGetpid(
@@ -138,7 +138,7 @@ Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeCreateProcess(
}
if (!CreatePipe(&stdin_process, &result->stdin_, &sa, 0)) {
- result->error_ = GetLastErrorString("CreatePipe(stdin)");
+ result->error_ = windows_util::GetLastErrorString("CreatePipe(stdin)");
goto cleanup;
}
@@ -155,12 +155,12 @@ Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeCreateProcess(
NULL);
if (stdout_process == INVALID_HANDLE_VALUE) {
- result->error_ = GetLastErrorString("CreateFile(stdout)");
+ result->error_ = windows_util::GetLastErrorString("CreateFile(stdout)");
goto cleanup;
}
} else {
if (!CreatePipe(&result->stdout_.handle_, &stdout_process, &sa, 0)) {
- result->error_ = GetLastErrorString("CreatePipe(stdout)");
+ result->error_ = windows_util::GetLastErrorString("CreatePipe(stdout)");
goto cleanup;
}
}
@@ -180,13 +180,13 @@ Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeCreateProcess(
NULL);
if (stderr_process == INVALID_HANDLE_VALUE) {
- result->error_ = GetLastErrorString("CreateFile(stderr)");
+ result->error_ = windows_util::GetLastErrorString("CreateFile(stderr)");
goto cleanup;
}
}
} else {
if (!CreatePipe(&result->stderr_.handle_, &stderr_process, &sa, 0)) {
- result->error_ = GetLastErrorString("CreatePipe(stderr)");
+ result->error_ = windows_util::GetLastErrorString("CreatePipe(stderr)");
goto cleanup;
}
}
@@ -196,7 +196,7 @@ Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeCreateProcess(
// allowed. Thus, we don't need to do any more setup here.
HANDLE job = CreateJobObject(NULL, NULL);
if (job == NULL) {
- result->error_ = GetLastErrorString("CreateJobObject()");
+ result->error_ = windows_util::GetLastErrorString("CreateJobObject()");
goto cleanup;
}
@@ -209,8 +209,9 @@ Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeCreateProcess(
JobObjectExtendedLimitInformation,
&job_info,
sizeof(job_info))) {
- result->error_ = GetLastErrorString("SetInformationJobObject()");
- goto cleanup;
+ result->error_ =
+ windows_util::GetLastErrorString("SetInformationJobObject()");
+ goto cleanup;
}
startup_info.hStdInput = stdin_process;
@@ -233,7 +234,7 @@ Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeCreateProcess(
&process_info);
if (!ok) {
- result->error_ = GetLastErrorString("CreateProcess()");
+ result->error_ = windows_util::GetLastErrorString("CreateProcess()");
goto cleanup;
}
@@ -253,14 +254,15 @@ Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeCreateProcess(
CloseHandle(result->job_);
result->job_ = INVALID_HANDLE_VALUE;
} else {
- result->error_ = GetLastErrorString("AssignProcessToJobObject()");
+ result->error_ =
+ windows_util::GetLastErrorString("AssignProcessToJobObject()");
goto cleanup;
}
}
// Now that we put the process in a new job object, we can start executing it
if (ResumeThread(thread) == -1) {
- result->error_ = GetLastErrorString("ResumeThread()");
+ result->error_ = windows_util::GetLastErrorString("ResumeThread()");
goto cleanup;
}
@@ -325,7 +327,7 @@ Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeWriteStdin(
if (!::WriteFile(process->stdin_, bytes + offset, length, &bytes_written,
NULL)) {
- process->error_ = GetLastErrorString("WriteFile()");
+ process->error_ = windows_util::GetLastErrorString("WriteFile()");
bytes_written = -1;
}
@@ -377,7 +379,7 @@ Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeReadStream(
stream->error_ = "";
bytes_read = 0;
} else {
- stream->error_ = GetLastErrorString("ReadFile()");
+ stream->error_ = windows_util::GetLastErrorString("ReadFile()");
bytes_read = -1;
}
} else {
@@ -394,7 +396,7 @@ Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeGetExitCode(
NativeProcess* process = reinterpret_cast<NativeProcess*>(process_long);
DWORD exit_code;
if (!GetExitCodeProcess(process->process_, &exit_code)) {
- process->error_ = GetLastErrorString("GetExitCodeProcess()");
+ process->error_ = windows_util::GetLastErrorString("GetExitCodeProcess()");
return -1;
}
@@ -471,12 +473,13 @@ Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeTerminate(
// In theory, CloseHandle() on process->job_ would work, too, since we set
// KILL_OBJECT_LIMIT_KILL_ON_JOB_CLOSE, but this is a little more explicit.
if (!TerminateJobObject(process->job_, 0)) {
- process->error_ = GetLastErrorString("TerminateJobObject()");
+ process->error_ =
+ windows_util::GetLastErrorString("TerminateJobObject()");
return JNI_FALSE;
}
} else if (process->process_ != INVALID_HANDLE_VALUE) {
if (!TerminateProcess(process->process_, 1)) {
- process->error_ = GetLastErrorString("TerminateProcess()");
+ process->error_ = windows_util::GetLastErrorString("TerminateProcess()");
return JNI_FALSE;
}
}
diff --git a/src/main/native/windows_error_handling.cc b/src/main/native/windows_util.cc
index dc14289729..b25bd2c114 100644
--- a/src/main/native/windows_error_handling.cc
+++ b/src/main/native/windows_util.cc
@@ -13,13 +13,20 @@
// limitations under the License.
#include <stdio.h>
+#include <stdlib.h>
#include <windows.h>
+#include <memory>
#include <string>
-#include "src/main/native/windows_error_handling.h"
+#include "src/main/native/windows_util.h"
-std::string GetLastErrorString(const std::string& cause) {
+namespace windows_util {
+
+using std::string;
+using std::unique_ptr;
+
+string GetLastErrorString(const string& cause) {
DWORD last_error = GetLastError();
if (last_error == 0) {
return "";
@@ -45,7 +52,19 @@ std::string GetLastErrorString(const std::string& cause) {
buf[sizeof(buf) - 1] = 0;
}
- std::string result = std::string(message);
+ string result = string(message);
LocalFree(message);
return cause + ": " + result;
}
+
+unique_ptr<wchar_t[]> JstringToWstring(JNIEnv* env, const jstring& jstr) {
+ const jsize len = env->GetStringLength(jstr);
+ const char* cstr_ptr = env->GetStringUTFChars(jstr, NULL);
+ unique_ptr<wchar_t[]> result(new wchar_t[len + 1]);
+ mbstowcs(result.get(), cstr_ptr, len);
+ result.get()[len] = L'\0';
+ env->ReleaseStringUTFChars(jstr, cstr_ptr);
+ return std::move(result);
+}
+
+} // namespace windows_util
diff --git a/src/main/native/windows_error_handling.h b/src/main/native/windows_util.h
index efbe95e7ad..48b88be191 100644
--- a/src/main/native/windows_error_handling.h
+++ b/src/main/native/windows_util.h
@@ -14,11 +14,23 @@
//
// INTERNAL header file for use by C++ code in this package.
-#ifndef BAZEL_SRC_MAIN_NATIVE_WINDOWS_ERROR_HANDLING_H__
-#define BAZEL_SRC_MAIN_NATIVE_WINDOWS_ERROR_HANDLING_H__
+#ifndef BAZEL_SRC_MAIN_NATIVE_WINDOWS_UTIL_H__
+#define BAZEL_SRC_MAIN_NATIVE_WINDOWS_UTIL_H__
+#include <jni.h>
+
+#include <memory>
#include <string>
-std::string GetLastErrorString(const std::string& cause);
+namespace windows_util {
+
+using std::string;
+using std::unique_ptr;
+
+string GetLastErrorString(const string& cause);
+
+unique_ptr<wchar_t[]> JstringToWstring(JNIEnv* env, const jstring& jstr);
+
+} // namespace windows_util
-#endif // BAZEL_SRC_MAIN_NATIVE_WINDOWS_ERROR_HANDLING_H__
+#endif // BAZEL_SRC_MAIN_NATIVE_WINDOWS_UTIL_H__