| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "tools/gn/filesystem_utils.h" | 5 #include "tools/gn/filesystem_utils.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/files/file_util.h" | 9 #include "base/files/file_util.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 669 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 680 std::string GetOutputSubdirName(const Label& toolchain_label, bool is_default) { | 680 std::string GetOutputSubdirName(const Label& toolchain_label, bool is_default) { |
| 681 // The default toolchain has no subdir. | 681 // The default toolchain has no subdir. |
| 682 if (is_default) | 682 if (is_default) |
| 683 return std::string(); | 683 return std::string(); |
| 684 | 684 |
| 685 // For now just assume the toolchain name is always a valid dir name. We may | 685 // For now just assume the toolchain name is always a valid dir name. We may |
| 686 // want to clean up the in the future. | 686 // want to clean up the in the future. |
| 687 return toolchain_label.name() + "/"; | 687 return toolchain_label.name() + "/"; |
| 688 } | 688 } |
| 689 | 689 |
| 690 bool ContentsEqual(const base::FilePath& file_path, const std::string& data) { | |
| 691 // Compare file and stream sizes first. Quick and will save us some time if | |
| 692 // they are different sizes. | |
| 693 int64_t file_size; | |
| 694 if (!base::GetFileSize(file_path, &file_size) || | |
| 695 static_cast<size_t>(file_size) != data.size()) { | |
| 696 return false; | |
| 697 } | |
| 698 | |
| 699 std::string file_data; | |
| 700 file_data.resize(file_size); | |
| 701 if (!base::ReadFileToString(file_path, &file_data)) | |
| 702 return false; | |
| 703 | |
| 704 return file_data == data; | |
| 705 } | |
| 706 | |
| 707 bool WriteFileIfChanged(const base::FilePath& file_path, | |
| 708 const std::string& data, | |
| 709 Err* err) { | |
| 710 if (ContentsEqual(file_path, data)) | |
| 711 return true; | |
| 712 | |
| 713 // Create the directory if necessary. | |
| 714 if (!base::CreateDirectory(file_path.DirName())) { | |
| 715 if (err) { | |
| 716 *err = | |
| 717 Err(Location(), "Unable to create directory.", | |
| 718 "I was using \"" + FilePathToUTF8(file_path.DirName()) + "\"."); | |
| 719 } | |
| 720 return false; | |
| 721 } | |
| 722 | |
| 723 int size = static_cast<int>(data.size()); | |
| 724 bool write_success = false; | |
| 725 | |
| 726 #if defined(OS_WIN) | |
| 727 // On Windows, provide a custom implementation of base::WriteFile. Sometimes | |
| 728 // the base version fails, especially on the bots. The guess is that Windows | |
| 729 // Defender or other antivirus programs still have the file open (after | |
| 730 // checking for the read) when the write happens immediately after. This | |
| 731 // version opens with FILE_SHARE_READ (normally not what you want when | |
| 732 // replacing the entire contents of the file) which lets us continue even if | |
| 733 // another program has the file open for reading. See http://crbug.com/468437 | |
| 734 base::win::ScopedHandle file(::CreateFile(file_path.value().c_str(), | |
| 735 GENERIC_WRITE, FILE_SHARE_READ, | |
| 736 NULL, CREATE_ALWAYS, 0, NULL)); | |
| 737 if (file.IsValid()) { | |
| 738 DWORD written; | |
| 739 BOOL result = ::WriteFile(file.Get(), data.c_str(), size, &written, NULL); | |
| 740 if (result) { | |
| 741 if (static_cast<int>(written) == size) { | |
| 742 write_success = true; | |
| 743 } else { | |
| 744 // Didn't write all the bytes. | |
| 745 LOG(ERROR) << "wrote" << written << " bytes to " | |
| 746 << base::UTF16ToUTF8(file_path.value()) << " expected " | |
| 747 << size; | |
| 748 } | |
| 749 } else { | |
| 750 // WriteFile failed. | |
| 751 PLOG(ERROR) << "writing file " << base::UTF16ToUTF8(file_path.value()) | |
| 752 << " failed"; | |
| 753 } | |
| 754 } else { | |
| 755 PLOG(ERROR) << "CreateFile failed for path " | |
| 756 << base::UTF16ToUTF8(file_path.value()); | |
| 757 } | |
| 758 #else | |
| 759 write_success = base::WriteFile(file_path, data.c_str(), size) == size; | |
| 760 #endif | |
| 761 | |
| 762 if (!write_success && err) { | |
| 763 *err = Err(Location(), "Unable to write file.", | |
| 764 "I was writing \"" + FilePathToUTF8(file_path) + "\"."); | |
| 765 } | |
| 766 | |
| 767 return write_success; | |
| 768 } | |
| 769 | |
| 770 SourceDir GetToolchainOutputDir(const Settings* settings) { | 690 SourceDir GetToolchainOutputDir(const Settings* settings) { |
| 771 return settings->toolchain_output_subdir().AsSourceDir( | 691 return settings->toolchain_output_subdir().AsSourceDir( |
| 772 settings->build_settings()); | 692 settings->build_settings()); |
| 773 } | 693 } |
| 774 | 694 |
| 775 SourceDir GetToolchainOutputDir(const BuildSettings* build_settings, | 695 SourceDir GetToolchainOutputDir(const BuildSettings* build_settings, |
| 776 const Label& toolchain_label, bool is_default) { | 696 const Label& toolchain_label, bool is_default) { |
| 777 std::string result = build_settings->build_dir().value(); | 697 std::string result = build_settings->build_dir().value(); |
| 778 result.append(GetOutputSubdirName(toolchain_label, is_default)); | 698 result.append(GetOutputSubdirName(toolchain_label, is_default)); |
| 779 return SourceDir(SourceDir::SWAP_IN, &result); | 699 return SourceDir(SourceDir::SWAP_IN, &result); |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 915 | 835 |
| 916 SourceDir GetCurrentOutputDir(const Scope* scope) { | 836 SourceDir GetCurrentOutputDir(const Scope* scope) { |
| 917 return GetOutputDirForSourceDirAsOutputFile( | 837 return GetOutputDirForSourceDirAsOutputFile( |
| 918 scope->settings(), scope->GetSourceDir()).AsSourceDir( | 838 scope->settings(), scope->GetSourceDir()).AsSourceDir( |
| 919 scope->settings()->build_settings()); | 839 scope->settings()->build_settings()); |
| 920 } | 840 } |
| 921 | 841 |
| 922 SourceDir GetCurrentGenDir(const Scope* scope) { | 842 SourceDir GetCurrentGenDir(const Scope* scope) { |
| 923 return GetGenDirForSourceDir(scope->settings(), scope->GetSourceDir()); | 843 return GetGenDirForSourceDir(scope->settings(), scope->GetSourceDir()); |
| 924 } | 844 } |
| OLD | NEW |