| // Copyright 2017 The Bazel Authors. All rights reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #ifndef WIN32_LEAN_AND_MEAN |
| #define WIN32_LEAN_AND_MEAN |
| #endif |
| |
| #include <windows.h> |
| |
| #include <memory> |
| #include <sstream> |
| #include <string> |
| |
| #include "src/main/native/jni.h" |
| #include "src/main/native/windows/file.h" |
| #include "src/main/native/windows/jni-util.h" |
| #include "src/main/native/windows/util.h" |
| |
| static bool CanReportError(JNIEnv* env, jobjectArray error_msg_holder) { |
| return error_msg_holder != nullptr && |
| env->GetArrayLength(error_msg_holder) > 0; |
| } |
| |
| static void ReportLastError(const std::wstring& error_str, JNIEnv* env, |
| jobjectArray error_msg_holder) { |
| jstring error_msg = env->NewString( |
| reinterpret_cast<const jchar*>(error_str.c_str()), error_str.size()); |
| env->SetObjectArrayElement(error_msg_holder, 0, error_msg); |
| } |
| |
| extern "C" JNIEXPORT jint JNICALL |
| Java_com_google_devtools_build_lib_windows_WindowsFileOperations_nativeIsSymlinkOrJunction( |
| JNIEnv* env, jclass clazz, jstring path, jbooleanArray result_holder, |
| jobjectArray error_msg_holder) { |
| std::wstring wpath(bazel::windows::GetJavaWstring(env, path)); |
| std::wstring error; |
| bool is_sym = false; |
| int result = |
| bazel::windows::IsSymlinkOrJunction(wpath.c_str(), &is_sym, &error); |
| if (result == bazel::windows::IsSymlinkOrJunctionResult::kSuccess) { |
| jboolean is_sym_jbool = is_sym ? JNI_TRUE : JNI_FALSE; |
| env->SetBooleanArrayRegion(result_holder, 0, 1, &is_sym_jbool); |
| } else { |
| if (!error.empty() && CanReportError(env, error_msg_holder)) { |
| ReportLastError( |
| bazel::windows::MakeErrorMessage(WSTR(__FILE__), __LINE__, |
| L"nativeIsJunction", wpath, error), |
| env, error_msg_holder); |
| } |
| } |
| return static_cast<jint>(result); |
| } |
| |
| extern "C" JNIEXPORT jboolean JNICALL |
| Java_com_google_devtools_build_lib_windows_WindowsFileOperations_nativeGetLongPath( |
| JNIEnv* env, jclass clazz, jstring path, jobjectArray result_holder, |
| jobjectArray error_msg_holder) { |
| std::unique_ptr<WCHAR[]> result; |
| std::wstring wpath(bazel::windows::GetJavaWstring(env, path)); |
| std::wstring error(bazel::windows::GetLongPath(wpath.c_str(), &result)); |
| if (!error.empty()) { |
| if (CanReportError(env, error_msg_holder)) { |
| ReportLastError( |
| bazel::windows::MakeErrorMessage(WSTR(__FILE__), __LINE__, |
| L"nativeGetLongPath", wpath, error), |
| env, error_msg_holder); |
| } |
| return JNI_FALSE; |
| } |
| env->SetObjectArrayElement( |
| result_holder, 0, |
| env->NewString(reinterpret_cast<const jchar*>(result.get()), |
| wcslen(result.get()))); |
| return JNI_TRUE; |
| } |
| |
| extern "C" JNIEXPORT jint JNICALL |
| Java_com_google_devtools_build_lib_windows_WindowsFileOperations_nativeCreateJunction( |
| JNIEnv* env, jclass clazz, jstring name, jstring target, |
| jobjectArray error_msg_holder) { |
| std::wstring wname(bazel::windows::GetJavaWstring(env, name)); |
| std::wstring wtarget(bazel::windows::GetJavaWstring(env, target)); |
| std::wstring error; |
| int result = bazel::windows::CreateJunction(wname, wtarget, &error); |
| if (result != bazel::windows::CreateJunctionResult::kSuccess && |
| !error.empty() && CanReportError(env, error_msg_holder)) { |
| ReportLastError(bazel::windows::MakeErrorMessage( |
| WSTR(__FILE__), __LINE__, L"nativeCreateJunction", |
| wname + L", " + wtarget, error), |
| env, error_msg_holder); |
| } |
| return static_cast<jint>(result); |
| } |
| |
| extern "C" JNIEXPORT jint JNICALL |
| Java_com_google_devtools_build_lib_windows_WindowsFileOperations_nativeCreateSymlink( |
| JNIEnv* env, jclass clazz, jstring name, jstring target, |
| jobjectArray error_msg_holder) { |
| std::wstring wname(bazel::windows::GetJavaWstring(env, name)); |
| std::wstring wtarget(bazel::windows::GetJavaWstring(env, target)); |
| std::wstring error; |
| int result = bazel::windows::CreateSymlink(wname, wtarget, &error); |
| if (result != bazel::windows::CreateSymlinkResult::kSuccess && |
| !error.empty() && CanReportError(env, error_msg_holder)) { |
| ReportLastError(bazel::windows::MakeErrorMessage( |
| WSTR(__FILE__), __LINE__, L"nativeCreateSymlink", |
| wname + L", " + wtarget, error), |
| env, error_msg_holder); |
| } |
| return static_cast<jint>(result); |
| } |
| |
| extern "C" JNIEXPORT jint JNICALL |
| Java_com_google_devtools_build_lib_windows_WindowsFileOperations_nativeReadSymlinkOrJunction( |
| JNIEnv* env, jclass clazz, jstring name, jobjectArray target_holder, |
| jobjectArray error_msg_holder) { |
| std::wstring wname(bazel::windows::GetJavaWstring(env, name)); |
| std::wstring target, error; |
| int result = bazel::windows::ReadSymlinkOrJunction(wname, &target, &error); |
| if (result == bazel::windows::ReadSymlinkOrJunctionResult::kSuccess) { |
| env->SetObjectArrayElement( |
| target_holder, 0, |
| env->NewString(reinterpret_cast<const jchar*>(target.c_str()), |
| target.size())); |
| } else { |
| if (!error.empty() && CanReportError(env, error_msg_holder)) { |
| ReportLastError(bazel::windows::MakeErrorMessage( |
| WSTR(__FILE__), __LINE__, |
| L"nativeReadSymlinkOrJunction", wname, error), |
| env, error_msg_holder); |
| } |
| } |
| return static_cast<jint>(result); |
| } |
| |
| extern "C" JNIEXPORT jint JNICALL |
| Java_com_google_devtools_build_lib_windows_WindowsFileOperations_nativeDeletePath( |
| JNIEnv* env, jclass clazz, jstring path, jobjectArray error_msg_holder) { |
| std::wstring wpath(bazel::windows::GetJavaWstring(env, path)); |
| std::wstring error; |
| int result = bazel::windows::DeletePath(wpath, &error); |
| if (result != bazel::windows::DeletePathResult::kSuccess && !error.empty() && |
| CanReportError(env, error_msg_holder)) { |
| ReportLastError( |
| bazel::windows::MakeErrorMessage(WSTR(__FILE__), __LINE__, |
| L"nativeDeletePath", wpath, error), |
| env, error_msg_holder); |
| } |
| return result; |
| } |