View Javadoc
1   /*
2    * Copyright 2020-2022 The OSHI Project Contributors
3    * SPDX-License-Identifier: MIT
4    */
5   package oshi.driver.unix.freebsd.disk;
6   
7   import java.util.ArrayList;
8   import java.util.Comparator;
9   import java.util.HashMap;
10  import java.util.List;
11  import java.util.Map;
12  import java.util.stream.Collectors;
13  
14  import oshi.annotation.concurrent.ThreadSafe;
15  import oshi.hardware.HWPartition;
16  import oshi.util.Constants;
17  import oshi.util.ExecutingCommand;
18  import oshi.util.ParseUtil;
19  
20  /**
21   * Utility to query geom part list
22   */
23  @ThreadSafe
24  public final class GeomPartList {
25  
26      private static final String GEOM_PART_LIST = "geom part list";
27      private static final String STAT_FILESIZE = "stat -f %i /dev/";
28  
29      private GeomPartList() {
30      }
31  
32      /**
33       * Queries partition data using geom, mount, and stat commands
34       *
35       * @return A map with disk name as the key and a List of partitions as the value
36       */
37      public static Map<String, List<HWPartition>> queryPartitions() {
38          Map<String, String> mountMap = Mount.queryPartitionToMountMap();
39          // Map of device name to partitions, to be returned
40          Map<String, List<HWPartition>> partitionMap = new HashMap<>();
41          // The Disk Store associated with a partition, key to the map
42          String diskName = null;
43          // List to hold partitions, will be added as value to the map
44          List<HWPartition> partList = new ArrayList<>();
45          // Parameters needed for constructor.
46          String partName = null; // Non-null identifies a valid partition
47          String identification = Constants.UNKNOWN;
48          String type = Constants.UNKNOWN;
49          String uuid = Constants.UNKNOWN;
50          long size = 0;
51          String mountPoint = "";
52  
53          List<String> geom = ExecutingCommand.runNative(GEOM_PART_LIST);
54          for (String line : geom) {
55              line = line.trim();
56              // Marks the DiskStore device for a partition.
57              if (line.startsWith("Geom name:")) {
58                  // Save any previous partition list in the map
59                  if (diskName != null && !partList.isEmpty()) {
60                      // Store map (old diskName)
61                      partitionMap.put(diskName, partList);
62                      // Reset the list
63                      partList = new ArrayList<>();
64                  }
65                  // Now use new diskName
66                  diskName = line.substring(line.lastIndexOf(' ') + 1);
67              }
68              // If we don't have a valid store, don't bother parsing anything
69              if (diskName != null) {
70                  // Marks the beginning of partition data
71                  if (line.contains("Name:")) {
72                      // Add the current partition to the list, if any
73                      if (partName != null) {
74                          // FreeBSD Major # is 0.
75                          // Minor # is filesize of /dev entry.
76                          int minor = ParseUtil
77                                  .parseIntOrDefault(ExecutingCommand.getFirstAnswer(STAT_FILESIZE + partName), 0);
78                          partList.add(new HWPartition(identification, partName, type, uuid, size, 0, minor, mountPoint));
79                          partName = null;
80                          identification = Constants.UNKNOWN;
81                          type = Constants.UNKNOWN;
82                          uuid = Constants.UNKNOWN;
83                          size = 0;
84                      }
85                      // Verify new entry is a partition
86                      // (will happen in 'providers' section)
87                      String part = line.substring(line.lastIndexOf(' ') + 1);
88                      if (part.startsWith(diskName)) {
89                          partName = part;
90                          identification = part;
91                          mountPoint = mountMap.getOrDefault(part, "");
92                      }
93                  }
94                  // If we don't have a valid partition, don't parse anything until we do.
95                  if (partName != null) {
96                      String[] split = ParseUtil.whitespaces.split(line);
97                      if (split.length >= 2) {
98                          if (line.startsWith("Mediasize:")) {
99                              size = ParseUtil.parseLongOrDefault(split[1], 0L);
100                         } else if (line.startsWith("rawuuid:")) {
101                             uuid = split[1];
102                         } else if (line.startsWith("type:")) {
103                             type = split[1];
104                         }
105                     }
106                 }
107             }
108         }
109         if (diskName != null) {
110             // Process last partition
111             if (partName != null) {
112                 int minor = ParseUtil.parseIntOrDefault(ExecutingCommand.getFirstAnswer(STAT_FILESIZE + partName), 0);
113                 partList.add(new HWPartition(identification, partName, type, uuid, size, 0, minor, mountPoint));
114             }
115             // Process last diskstore
116             if (!partList.isEmpty()) {
117                 partList = partList.stream().sorted(Comparator.comparing(HWPartition::getName))
118                         .collect(Collectors.toList());
119                 partitionMap.put(diskName, partList);
120             }
121         }
122         return partitionMap;
123     }
124 }