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