| // Copyright 2017 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "base/system/sys_info.h" |
| |
| #include <fidl/fuchsia.buildinfo/cpp/fidl.h> |
| #include <fidl/fuchsia.hwinfo/cpp/fidl.h> |
| #include <sys/statvfs.h> |
| #include <zircon/syscalls.h> |
| |
| #include <string> |
| |
| #include "base/containers/flat_map.h" |
| #include "base/files/file_util.h" |
| #include "base/fuchsia/fuchsia_logging.h" |
| #include "base/fuchsia/system_info.h" |
| #include "base/logging.h" |
| #include "base/no_destructor.h" |
| #include "base/numerics/clamped_math.h" |
| #include "base/strings/string_piece.h" |
| #include "base/synchronization/lock.h" |
| #include "base/threading/scoped_blocking_call.h" |
| #include "build/build_config.h" |
| |
| namespace base { |
| |
| namespace { |
| |
| bool GetDiskSpaceInfo(const FilePath& path, |
| int64_t* available_bytes, |
| int64_t* total_bytes) { |
| struct statvfs stats; |
| if (statvfs(path.value().c_str(), &stats) != 0) { |
| PLOG(ERROR) << "statvfs() for path:" << path; |
| return false; |
| } |
| |
| if (available_bytes) { |
| ClampedNumeric<int64_t> available_blocks(stats.f_bavail); |
| *available_bytes = available_blocks * stats.f_frsize; |
| } |
| |
| if (total_bytes) { |
| ClampedNumeric<int64_t> total_blocks(stats.f_blocks); |
| *total_bytes = total_blocks * stats.f_frsize; |
| } |
| |
| return true; |
| } |
| |
| struct TotalDiskSpace { |
| Lock lock; |
| flat_map<FilePath, int64_t> space_map GUARDED_BY(lock); |
| }; |
| |
| TotalDiskSpace& GetTotalDiskSpace() { |
| static NoDestructor<TotalDiskSpace> total_disk_space; |
| return *total_disk_space; |
| } |
| |
| // Returns the total-disk-space set for the volume containing |path|. If |
| // |volume_path| is non-null then it receives the path to the relevant volume. |
| // Returns -1, and does not modify |volume_path|, if no match is found. Also |
| // returns -1 if |path| is not absolute. |
| int64_t GetAmountOfTotalDiskSpaceAndVolumePath(const FilePath& path, |
| FilePath* volume_path) { |
| if (!path.IsAbsolute()) { |
| return -1; |
| } |
| TotalDiskSpace& total_disk_space = GetTotalDiskSpace(); |
| |
| AutoLock l(total_disk_space.lock); |
| int64_t result = -1; |
| FilePath matched_path; |
| for (const auto& path_and_size : total_disk_space.space_map) { |
| if (path_and_size.first == path || path_and_size.first.IsParent(path)) { |
| // If a deeper path was already matched then ignore this entry. |
| if (!matched_path.empty() && !matched_path.IsParent(path_and_size.first)) |
| continue; |
| matched_path = path_and_size.first; |
| result = path_and_size.second; |
| } |
| } |
| |
| if (volume_path) |
| *volume_path = matched_path; |
| return result; |
| } |
| |
| } // namespace |
| |
| // static |
| uint64_t SysInfo::AmountOfPhysicalMemoryImpl() { |
| return zx_system_get_physmem(); |
| } |
| |
| // static |
| uint64_t SysInfo::AmountOfAvailablePhysicalMemoryImpl() { |
| // TODO(crbug.com/986608): Implement this when Fuchsia supports it. |
| NOTIMPLEMENTED_LOG_ONCE(); |
| return 0; |
| } |
| |
| // static |
| int SysInfo::NumberOfProcessors() { |
| return static_cast<int>(zx_system_get_num_cpus()); |
| } |
| |
| // static |
| uint64_t SysInfo::AmountOfVirtualMemory() { |
| // Fuchsia does not provide this type of information. |
| // Return zero to indicate that there is unlimited available virtual memory. |
| return 0; |
| } |
| |
| // static |
| std::string SysInfo::OperatingSystemName() { |
| return "Fuchsia"; |
| } |
| |
| // static |
| int64_t SysInfo::AmountOfFreeDiskSpace(const FilePath& path) { |
| ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK); |
| |
| // First check whether there is a soft-quota that applies to |path|. |
| FilePath volume_path; |
| const int64_t total_space = |
| GetAmountOfTotalDiskSpaceAndVolumePath(path, &volume_path); |
| if (total_space >= 0) { |
| // TODO(crbug.com/1148334): Replace this with an efficient implementation. |
| const int64_t used_space = ComputeDirectorySize(volume_path); |
| return std::max(0l, total_space - used_space); |
| } |
| |
| // Report the actual amount of free space in |path|'s filesystem. |
| int64_t available; |
| if (GetDiskSpaceInfo(path, &available, nullptr)) |
| return available; |
| |
| return -1; |
| } |
| |
| // static |
| int64_t SysInfo::AmountOfTotalDiskSpace(const FilePath& path) { |
| ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK); |
| |
| if (path.empty()) |
| return -1; |
| |
| // Return the soft-quota that applies to |path|, if one is configured. |
| int64_t total_space = GetAmountOfTotalDiskSpaceAndVolumePath(path, nullptr); |
| if (total_space >= 0) |
| return total_space; |
| |
| // Report the actual space in |path|'s filesystem. |
| if (GetDiskSpaceInfo(path, nullptr, &total_space)) |
| return total_space; |
| |
| return -1; |
| } |
| |
| // static |
| void SysInfo::SetAmountOfTotalDiskSpace(const FilePath& path, int64_t bytes) { |
| DCHECK(path.IsAbsolute()); |
| TotalDiskSpace& total_disk_space = GetTotalDiskSpace(); |
| AutoLock l(total_disk_space.lock); |
| if (bytes >= 0) |
| total_disk_space.space_map[path] = bytes; |
| else |
| total_disk_space.space_map.erase(path); |
| } |
| |
| // static |
| std::string SysInfo::OperatingSystemVersion() { |
| const auto& build_info = GetCachedBuildInfo(); |
| return build_info.version().value_or(""); |
| } |
| |
| // static |
| void SysInfo::OperatingSystemVersionNumbers(int32_t* major_version, |
| int32_t* minor_version, |
| int32_t* bugfix_version) { |
| // TODO(crbug.com/1348711): Implement this when Fuchsia supports it. |
| NOTIMPLEMENTED_LOG_ONCE(); |
| *major_version = 0; |
| *minor_version = 0; |
| *bugfix_version = 0; |
| } |
| |
| // static |
| std::string SysInfo::OperatingSystemArchitecture() { |
| #if defined(ARCH_CPU_X86_64) |
| return "x86_64"; |
| #elif defined(ARCH_CPU_ARM64) |
| return "aarch64"; |
| #else |
| #error Unsupported architecture. |
| #endif |
| } |
| |
| // static |
| std::string SysInfo::CPUModelName() { |
| // TODO(crbug.com/1233859): Implement this when Fuchsia supports it. |
| NOTIMPLEMENTED_LOG_ONCE(); |
| return std::string(); |
| } |
| |
| // static |
| size_t SysInfo::VMAllocationGranularity() { |
| return static_cast<size_t>(getpagesize()); |
| } |
| |
| // static |
| int SysInfo::NumberOfEfficientProcessorsImpl() { |
| NOTIMPLEMENTED(); |
| return 0; |
| } |
| |
| SysInfo::HardwareInfo SysInfo::GetHardwareInfoSync() { |
| const auto product_info = GetProductInfo(); |
| |
| return { |
| .manufacturer = product_info.manufacturer().value_or(""), |
| .model = product_info.model().value_or(""), |
| }; |
| } |
| |
| } // namespace base |