• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2024 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/files/drive_info.h"
6 
7 #include <sys/stat.h>
8 #include <sys/types.h>
9 
10 #include "base/files/file.h"
11 #include "base/files/file_path.h"
12 #include "base/files/file_util.h"
13 #include "base/files/scoped_file.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/stringprintf.h"
16 #include "build/build_config.h"
17 
18 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
19 #include <linux/kdev_t.h>
20 #endif
21 
22 namespace base {
23 
GetFileDriveInfo(const FilePath & file_path)24 std::optional<DriveInfo> GetFileDriveInfo(const FilePath& file_path) {
25   DriveInfo drive_info;
26 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_FUCHSIA)
27   drive_info.has_seek_penalty = false;
28   return drive_info;
29 #elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
30   constexpr char kRotationalFormat[] =
31       "/sys/dev/block/%lu:%lu/queue/rotational";
32   constexpr char kRemovableFormat[] = "/sys/dev/block/%lu:%lu/removable";
33   constexpr char kSizeFormat[] = "/sys/dev/block/%lu:%lu/size";
34   File file(file_path, File::FLAG_OPEN | File::FLAG_READ);
35   if (!file.IsValid()) {
36     return std::nullopt;
37   }
38 
39   struct stat path_stat;
40   int error = File::Fstat(file.GetPlatformFile(), &path_stat);
41   if (error < 0) {
42     return std::nullopt;
43   }
44 
45   std::string rotational_path = StringPrintf(
46       kRotationalFormat, MAJOR(path_stat.st_dev), MINOR(path_stat.st_dev));
47   std::string removable_path = StringPrintf(
48       kRemovableFormat, MAJOR(path_stat.st_dev), MINOR(path_stat.st_dev));
49   std::string size_path = StringPrintf(kSizeFormat, MAJOR(path_stat.st_dev),
50                                        MINOR(path_stat.st_dev));
51 
52   std::string rotates;
53   if (ReadFileToString(base::FilePath(rotational_path), &rotates) &&
54       rotates.length() == 1 && (rotates[0] == '0' || rotates[0] == '1')) {
55     drive_info.has_seek_penalty = rotates[0] == '1';
56   }
57 
58   std::string removable;
59   if (ReadFileToString(base::FilePath(removable_path), &removable) &&
60       removable.length() == 1 && (removable[0] == '0' || removable[0] == '1')) {
61     drive_info.is_removable = removable[0] == '1';
62   }
63 
64   std::string size;
65   uint64_t bytes;
66   if (ReadFileToString(FilePath(size_path), &size) &&
67       StringToUint64(size, &bytes)) {
68     drive_info.size_bytes = bytes;
69   }
70 
71   return drive_info;
72 #endif
73 }
74 
75 }  // namespace base
76