| // 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. |
| |
| #include <fstream> |
| #include <memory> |
| #include <string> |
| #include <unordered_map> |
| |
| #include "src/main/cpp/util/path_platform.h" |
| #include "src/main/cpp/util/strings.h" |
| #include "src/tools/launcher/util/data_parser.h" |
| #include "src/tools/launcher/util/launcher_util.h" |
| |
| namespace bazel { |
| namespace launcher { |
| |
| using std::ifstream; |
| using std::ios; |
| using std::make_unique; |
| using std::string; |
| using std::unique_ptr; |
| using std::wstring; |
| |
| int64_t LaunchDataParser::ReadDataSize(ifstream* binary) { |
| int64_t data_size; |
| binary->seekg(0 - sizeof(data_size), ios::end); |
| binary->read(reinterpret_cast<char*>(&data_size), sizeof(data_size)); |
| return data_size; |
| } |
| |
| void LaunchDataParser::ReadLaunchData(ifstream* binary, char* launch_data, |
| int64_t data_size) { |
| binary->seekg(0 - data_size - sizeof(data_size), ios::end); |
| binary->read(launch_data, data_size); |
| } |
| |
| bool LaunchDataParser::ParseLaunchData(LaunchInfo* launch_info, |
| const char* launch_data, |
| int64_t data_size) { |
| int64_t start, end, equal; |
| start = 0; |
| while (start < data_size) { |
| // Move start to point to the next non-null character. |
| while (launch_data[start] == '\0' && start < data_size) { |
| start++; |
| } |
| // Move end to the next null character or end of the string, |
| // also find the first equal symbol appears. |
| end = start; |
| equal = -1; |
| while (launch_data[end] != '\0' && end < data_size) { |
| if (equal == -1 && launch_data[end] == '=') { |
| equal = end; |
| } |
| end++; |
| } |
| if (equal == -1) { |
| PrintError(L"Cannot find equal symbol in line: %hs", |
| string(launch_data + start, end - start).c_str()); |
| return false; |
| } else if (start == equal) { |
| PrintError(L"Key is empty string in line: %hs", |
| string(launch_data + start, end - start).c_str()); |
| return false; |
| } else { |
| string key(launch_data + start, equal - start); |
| string value(launch_data + equal + 1, end - equal - 1); |
| if (launch_info->find(key) != launch_info->end()) { |
| PrintError(L"Duplicated launch info key: %hs", key.c_str()); |
| return false; |
| } |
| launch_info->insert(make_pair(key, blaze_util::CstringToWstring(value))); |
| } |
| start = end + 1; |
| } |
| return true; |
| } |
| |
| bool LaunchDataParser::GetLaunchInfo(const wstring& binary_path, |
| LaunchInfo* launch_info) { |
| unique_ptr<ifstream> binary = |
| make_unique<ifstream>(AsAbsoluteWindowsPath(binary_path.c_str()).c_str(), |
| ios::binary | ios::in); |
| if (!binary->good()) { |
| PrintError(L"Cannot open the binary to read launch data"); |
| return false; |
| } |
| int64_t data_size = ReadDataSize(binary.get()); |
| if (data_size == 0) { |
| PrintError(L"No data appended, cannot launch anything!"); |
| return false; |
| } |
| unique_ptr<char[]> launch_data(new char[data_size]); |
| ReadLaunchData(binary.get(), launch_data.get(), data_size); |
| if (!ParseLaunchData(launch_info, launch_data.get(), data_size)) { |
| return false; |
| } |
| return true; |
| } |
| |
| } // namespace launcher |
| } // namespace bazel |