• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/system/sys_info.h"
6 
7 #include <fidl/fuchsia.buildinfo/cpp/fidl.h>
8 #include <fidl/fuchsia.hwinfo/cpp/fidl.h>
9 #include <sys/statvfs.h>
10 #include <zircon/syscalls.h>
11 
12 #include <string>
13 
14 #include "base/containers/flat_map.h"
15 #include "base/files/file_util.h"
16 #include "base/fuchsia/fuchsia_logging.h"
17 #include "base/fuchsia/system_info.h"
18 #include "base/logging.h"
19 #include "base/no_destructor.h"
20 #include "base/notimplemented.h"
21 #include "base/numerics/clamped_math.h"
22 #include "base/synchronization/lock.h"
23 #include "base/threading/scoped_blocking_call.h"
24 #include "build/build_config.h"
25 
26 namespace base {
27 
28 namespace {
29 
GetDiskSpaceInfo(const FilePath & path,int64_t * available_bytes,int64_t * total_bytes)30 bool GetDiskSpaceInfo(const FilePath& path,
31                       int64_t* available_bytes,
32                       int64_t* total_bytes) {
33   struct statvfs stats;
34   if (statvfs(path.value().c_str(), &stats) != 0) {
35     PLOG(ERROR) << "statvfs() for path:" << path;
36     return false;
37   }
38 
39   if (available_bytes) {
40     ClampedNumeric<int64_t> available_blocks(stats.f_bavail);
41     *available_bytes = available_blocks * stats.f_frsize;
42   }
43 
44   if (total_bytes) {
45     ClampedNumeric<int64_t> total_blocks(stats.f_blocks);
46     *total_bytes = total_blocks * stats.f_frsize;
47   }
48 
49   return true;
50 }
51 
52 struct TotalDiskSpace {
53   Lock lock;
54   flat_map<FilePath, int64_t> space_map GUARDED_BY(lock);
55 };
56 
GetTotalDiskSpace()57 TotalDiskSpace& GetTotalDiskSpace() {
58   static NoDestructor<TotalDiskSpace> total_disk_space;
59   return *total_disk_space;
60 }
61 
62 // Returns the total-disk-space set for the volume containing |path|. If
63 // |volume_path| is non-null then it receives the path to the relevant volume.
64 // Returns -1, and does not modify |volume_path|, if no match is found. Also
65 // returns -1 if |path| is not absolute.
GetAmountOfTotalDiskSpaceAndVolumePath(const FilePath & path,FilePath * volume_path)66 int64_t GetAmountOfTotalDiskSpaceAndVolumePath(const FilePath& path,
67                                                FilePath* volume_path) {
68   if (!path.IsAbsolute()) {
69     return -1;
70   }
71   TotalDiskSpace& total_disk_space = GetTotalDiskSpace();
72 
73   AutoLock l(total_disk_space.lock);
74   int64_t result = -1;
75   FilePath matched_path;
76   for (const auto& path_and_size : total_disk_space.space_map) {
77     if (path_and_size.first == path || path_and_size.first.IsParent(path)) {
78       // If a deeper path was already matched then ignore this entry.
79       if (!matched_path.empty() && !matched_path.IsParent(path_and_size.first))
80         continue;
81       matched_path = path_and_size.first;
82       result = path_and_size.second;
83     }
84   }
85 
86   if (volume_path)
87     *volume_path = matched_path;
88   return result;
89 }
90 
91 }  // namespace
92 
93 // static
AmountOfPhysicalMemoryImpl()94 uint64_t SysInfo::AmountOfPhysicalMemoryImpl() {
95   return zx_system_get_physmem();
96 }
97 
98 // static
AmountOfAvailablePhysicalMemoryImpl()99 uint64_t SysInfo::AmountOfAvailablePhysicalMemoryImpl() {
100   // TODO(crbug.com/42050649): Implement this when Fuchsia supports it.
101   NOTIMPLEMENTED_LOG_ONCE();
102   return 0;
103 }
104 
105 // static
NumberOfProcessors()106 int SysInfo::NumberOfProcessors() {
107   return static_cast<int>(zx_system_get_num_cpus());
108 }
109 
110 // static
AmountOfVirtualMemory()111 uint64_t SysInfo::AmountOfVirtualMemory() {
112   // Fuchsia does not provide this type of information.
113   // Return zero to indicate that there is unlimited available virtual memory.
114   return 0;
115 }
116 
117 // static
OperatingSystemName()118 std::string SysInfo::OperatingSystemName() {
119   return "Fuchsia";
120 }
121 
122 // static
AmountOfFreeDiskSpace(const FilePath & path)123 int64_t SysInfo::AmountOfFreeDiskSpace(const FilePath& path) {
124   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
125 
126   // First check whether there is a soft-quota that applies to |path|.
127   FilePath volume_path;
128   const int64_t total_space =
129       GetAmountOfTotalDiskSpaceAndVolumePath(path, &volume_path);
130   if (total_space >= 0) {
131     // TODO(crbug.com/42050202): Replace this with an efficient implementation.
132     const int64_t used_space = ComputeDirectorySize(volume_path);
133     return std::max(0l, total_space - used_space);
134   }
135 
136   // Report the actual amount of free space in |path|'s filesystem.
137   int64_t available;
138   if (GetDiskSpaceInfo(path, &available, nullptr))
139     return available;
140 
141   return -1;
142 }
143 
144 // static
AmountOfTotalDiskSpace(const FilePath & path)145 int64_t SysInfo::AmountOfTotalDiskSpace(const FilePath& path) {
146   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
147 
148   if (path.empty())
149     return -1;
150 
151   // Return the soft-quota that applies to |path|, if one is configured.
152   int64_t total_space = GetAmountOfTotalDiskSpaceAndVolumePath(path, nullptr);
153   if (total_space >= 0)
154     return total_space;
155 
156   // Report the actual space in |path|'s filesystem.
157   if (GetDiskSpaceInfo(path, nullptr, &total_space))
158     return total_space;
159 
160   return -1;
161 }
162 
163 // static
SetAmountOfTotalDiskSpace(const FilePath & path,int64_t bytes)164 void SysInfo::SetAmountOfTotalDiskSpace(const FilePath& path, int64_t bytes) {
165   DCHECK(path.IsAbsolute());
166   TotalDiskSpace& total_disk_space = GetTotalDiskSpace();
167   AutoLock l(total_disk_space.lock);
168   if (bytes >= 0)
169     total_disk_space.space_map[path] = bytes;
170   else
171     total_disk_space.space_map.erase(path);
172 }
173 
174 // static
OperatingSystemVersion()175 std::string SysInfo::OperatingSystemVersion() {
176   const auto& build_info = GetCachedBuildInfo();
177   return build_info.version().value_or("");
178 }
179 
180 // static
OperatingSystemVersionNumbers(int32_t * major_version,int32_t * minor_version,int32_t * bugfix_version)181 void SysInfo::OperatingSystemVersionNumbers(int32_t* major_version,
182                                             int32_t* minor_version,
183                                             int32_t* bugfix_version) {
184   // TODO(crbug.com/42050501): Implement this when Fuchsia supports it.
185   NOTIMPLEMENTED_LOG_ONCE();
186   *major_version = 0;
187   *minor_version = 0;
188   *bugfix_version = 0;
189 }
190 
191 // static
OperatingSystemArchitecture()192 std::string SysInfo::OperatingSystemArchitecture() {
193 #if defined(ARCH_CPU_X86_64)
194   return "x86_64";
195 #elif defined(ARCH_CPU_ARM64)
196   return "aarch64";
197 #else
198 #error Unsupported architecture.
199 #endif
200 }
201 
202 // static
CPUModelName()203 std::string SysInfo::CPUModelName() {
204   // TODO(crbug.com/40191727): Implement this when Fuchsia supports it.
205   NOTIMPLEMENTED_LOG_ONCE();
206   return std::string();
207 }
208 
209 // static
VMAllocationGranularity()210 size_t SysInfo::VMAllocationGranularity() {
211   return static_cast<size_t>(getpagesize());
212 }
213 
214 // static
NumberOfEfficientProcessorsImpl()215 int SysInfo::NumberOfEfficientProcessorsImpl() {
216   NOTIMPLEMENTED();
217   return 0;
218 }
219 
GetHardwareInfoSync()220 SysInfo::HardwareInfo SysInfo::GetHardwareInfoSync() {
221   const auto product_info = GetProductInfo();
222 
223   return {
224       .manufacturer = product_info.manufacturer().value_or(""),
225       .model = product_info.model().value_or(""),
226   };
227 }
228 
229 }  // namespace base
230