43 #include <sys/types.h>
48 #include <google/protobuf/compiler/importer.h>
49 #include <google/protobuf/compiler/parser.h>
50 #include <google/protobuf/io/tokenizer.h>
51 #include <google/protobuf/io/zero_copy_stream_impl.h>
52 #include <google/protobuf/stubs/strutil.h>
53 #include <google/protobuf/io/io_win32.h>
66 using google::protobuf::io::win32::access;
74 #if defined(_WIN32) || defined(__CYGWIN__)
75 return text.size() >= 3 &&
text[1] ==
':' && isalpha(
text[0]) &&
76 (
text[2] ==
'/' ||
text[2] ==
'\\') &&
text.find_last_of(
':') == 1;
88 class SourceTreeDescriptorDatabase::SingleFileErrorCollector
89 :
public io::ErrorCollector {
119 fallback_database_(nullptr),
121 using_validation_error_collector_(
false),
122 validation_error_collector_(this) {}
151 io::Tokenizer tokenizer(
input.get(), &file_error_collector);
155 parser.RecordErrorsTo(&file_error_collector);
163 return parser.Parse(&tokenizer,
output) && !file_error_collector.had_errors();
190 if (owner_->error_collector_ == NULL)
return;
197 owner_->source_locations_.Find(
descriptor, location, &
line, &column);
206 if (owner_->error_collector_ == NULL)
return;
213 owner_->source_locations_.Find(
descriptor, location, &
line, &column);
222 : database_(source_tree),
224 pool_.EnforceWeakDependencies(
true);
225 database_.RecordErrorsTo(error_collector);
236 pool_.AddUnusedImportTrackFile(file_name, is_error);
240 pool_.ClearUnusedImportTrackFiles();
255 return str[
str.size() - 1];
290 std::vector<std::string> canonical_parts;
291 std::vector<std::string> parts =
Split(
297 canonical_parts.push_back(part);
301 if (!
path.empty() &&
path[0] ==
'/') {
338 if (old_prefix.empty()) {
348 result->assign(new_prefix);
354 if (
filename.size() == old_prefix.size()) {
362 int after_prefix_start = -1;
363 if (
filename[old_prefix.size()] ==
'/') {
364 after_prefix_start = old_prefix.size() + 1;
365 }
else if (
filename[old_prefix.size() - 1] ==
'/') {
368 after_prefix_start = old_prefix.size();
370 if (after_prefix_start != -1) {
378 result->assign(new_prefix);
380 result->append(after_prefix);
398 int mapping_index = -1;
401 for (
int i = 0;
i < mappings_.size();
i++) {
403 if (
ApplyMapping(canonical_disk_file, mappings_[i].disk_path,
404 mappings_[i].virtual_path, virtual_file)) {
411 if (mapping_index == -1) {
417 for (
int i = 0;
i < mapping_index;
i++) {
418 if (
ApplyMapping(*virtual_file, mappings_[i].virtual_path,
419 mappings_[i].disk_path, shadowing_disk_file)) {
420 if (
access(shadowing_disk_file->c_str(),
F_OK) >= 0) {
426 shadowing_disk_file->clear();
431 std::unique_ptr<io::ZeroCopyInputStream>
stream(OpenDiskFile(disk_file));
441 std::unique_ptr<io::ZeroCopyInputStream>
stream(
442 OpenVirtualFile(virtual_file, disk_file));
447 return OpenVirtualFile(
filename, NULL);
451 return last_error_message_;
461 last_error_message_ =
462 "Backslashes, consecutive slashes, \".\", or \"..\" "
463 "are not allowed in the virtual path";
467 for (
const auto& mapping : mappings_) {
469 if (
ApplyMapping(virtual_file, mapping.virtual_path, mapping.disk_path,
473 if (disk_file != NULL) {
474 *disk_file = temp_disk_file;
479 if (errno == EACCES) {
481 last_error_message_ =
482 "Read access is denied for file: " + temp_disk_file;
487 last_error_message_ =
"File not found.";
497 }
while (
ret != 0 && errno == EINTR);
499 if (
ret == 0 && sb.st_mode & S_IFDIR) {
500 last_error_message_ =
"Input file is a directory.";
504 if (
ret == 0 && S_ISDIR(sb.st_mode)) {
505 last_error_message_ =
"Input file is a directory.";
512 }
while (file_descriptor < 0 && errno == EINTR);
513 if (file_descriptor >= 0) {
514 io::FileInputStream*
result =
new io::FileInputStream(file_descriptor);
515 result->SetCloseOnDelete(
true);