1
2
3
4
5 package oshi.software.os.unix.solaris;
6
7 import static oshi.software.os.unix.solaris.SolarisOperatingSystem.HAS_KSTAT2;
8 import static oshi.util.Memoizer.defaultExpiration;
9
10 import java.io.File;
11 import java.nio.file.PathMatcher;
12 import java.util.ArrayList;
13 import java.util.HashMap;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.function.Supplier;
17
18 import com.sun.jna.platform.unix.solaris.LibKstat.Kstat;
19
20 import oshi.annotation.concurrent.ThreadSafe;
21 import oshi.software.common.AbstractFileSystem;
22 import oshi.software.os.OSFileStore;
23 import oshi.util.ExecutingCommand;
24 import oshi.util.FileSystemUtil;
25 import oshi.util.FileUtil;
26 import oshi.util.Memoizer;
27 import oshi.util.ParseUtil;
28 import oshi.util.platform.unix.solaris.KstatUtil;
29 import oshi.util.platform.unix.solaris.KstatUtil.KstatChain;
30 import oshi.util.tuples.Pair;
31
32
33
34
35
36
37 @ThreadSafe
38 public class SolarisFileSystem extends AbstractFileSystem {
39
40 private static final Supplier<Pair<Long, Long>> FILE_DESC = Memoizer
41 .memoize(SolarisFileSystem::queryFileDescriptors, defaultExpiration());
42
43 public static final String OSHI_SOLARIS_FS_PATH_EXCLUDES = "oshi.os.solaris.filesystem.path.excludes";
44 public static final String OSHI_SOLARIS_FS_PATH_INCLUDES = "oshi.os.solaris.filesystem.path.includes";
45 public static final String OSHI_SOLARIS_FS_VOLUME_EXCLUDES = "oshi.os.solaris.filesystem.volume.excludes";
46 public static final String OSHI_SOLARIS_FS_VOLUME_INCLUDES = "oshi.os.solaris.filesystem.volume.includes";
47
48 private static final List<PathMatcher> FS_PATH_EXCLUDES = FileSystemUtil
49 .loadAndParseFileSystemConfig(OSHI_SOLARIS_FS_PATH_EXCLUDES);
50 private static final List<PathMatcher> FS_PATH_INCLUDES = FileSystemUtil
51 .loadAndParseFileSystemConfig(OSHI_SOLARIS_FS_PATH_INCLUDES);
52 private static final List<PathMatcher> FS_VOLUME_EXCLUDES = FileSystemUtil
53 .loadAndParseFileSystemConfig(OSHI_SOLARIS_FS_VOLUME_EXCLUDES);
54 private static final List<PathMatcher> FS_VOLUME_INCLUDES = FileSystemUtil
55 .loadAndParseFileSystemConfig(OSHI_SOLARIS_FS_VOLUME_INCLUDES);
56
57 @Override
58 public List<OSFileStore> getFileStores(boolean localOnly) {
59 return getFileStoreMatching(null, localOnly);
60 }
61
62
63 static List<OSFileStore> getFileStoreMatching(String nameToMatch) {
64 return getFileStoreMatching(nameToMatch, false);
65 }
66
67 private static List<OSFileStore> getFileStoreMatching(String nameToMatch, boolean localOnly) {
68 List<OSFileStore> fsList = new ArrayList<>();
69
70
71 Map<String, Long> inodeFreeMap = new HashMap<>();
72 Map<String, Long> inodeTotalMap = new HashMap<>();
73 String key = null;
74 String total = null;
75 String free = null;
76 String command = "df -g" + (localOnly ? " -l" : "");
77 for (String line : ExecutingCommand.runNative(command)) {
78
79
80
81
82
83
84 if (line.startsWith("/")) {
85 key = ParseUtil.whitespaces.split(line)[0];
86 total = null;
87 } else if (line.contains("available") && line.contains("total files")) {
88 total = ParseUtil.getTextBetweenStrings(line, "available", "total files").trim();
89 } else if (line.contains("free files")) {
90 free = ParseUtil.getTextBetweenStrings(line, "", "free files").trim();
91 if (key != null && total != null) {
92 inodeFreeMap.put(key, ParseUtil.parseLongOrDefault(free, 0L));
93 inodeTotalMap.put(key, ParseUtil.parseLongOrDefault(total, 0L));
94 key = null;
95 }
96 }
97 }
98
99
100 for (String fs : ExecutingCommand.runNative("cat /etc/mnttab")) {
101 String[] split = ParseUtil.whitespaces.split(fs);
102 if (split.length < 5) {
103 continue;
104 }
105
106
107
108
109
110 String volume = split[0];
111 String path = split[1];
112 String type = split[2];
113 String options = split[3];
114
115
116 if ((localOnly && NETWORK_FS_TYPES.contains(type))
117 || !path.equals("/") && (PSEUDO_FS_TYPES.contains(type) || FileSystemUtil.isFileStoreExcluded(path,
118 volume, FS_PATH_INCLUDES, FS_PATH_EXCLUDES, FS_VOLUME_INCLUDES, FS_VOLUME_EXCLUDES))) {
119 continue;
120 }
121
122 String name = path.substring(path.lastIndexOf('/') + 1);
123
124 if (name.isEmpty()) {
125 name = volume.substring(volume.lastIndexOf('/') + 1);
126 }
127
128 if (nameToMatch != null && !nameToMatch.equals(name)) {
129 continue;
130 }
131 File f = new File(path);
132 long totalSpace = f.getTotalSpace();
133 long usableSpace = f.getUsableSpace();
134 long freeSpace = f.getFreeSpace();
135
136 String description;
137 if (volume.startsWith("/dev") || path.equals("/")) {
138 description = "Local Disk";
139 } else if (volume.equals("tmpfs")) {
140 description = "Ram Disk";
141 } else if (NETWORK_FS_TYPES.contains(type)) {
142 description = "Network Disk";
143 } else {
144 description = "Mount Point";
145 }
146
147 fsList.add(new SolarisOSFileStore(name, volume, name, path, options, "", "", description, type, freeSpace,
148 usableSpace, totalSpace, inodeFreeMap.containsKey(path) ? inodeFreeMap.get(path) : 0L,
149 inodeTotalMap.containsKey(path) ? inodeTotalMap.get(path) : 0L));
150 }
151 return fsList;
152 }
153
154 @Override
155 public long getOpenFileDescriptors() {
156 if (HAS_KSTAT2) {
157
158 return FILE_DESC.get().getA();
159 }
160 try (KstatChain kc = KstatUtil.openChain()) {
161 Kstat ksp = kc.lookup(null, -1, "file_cache");
162
163 if (ksp != null && kc.read(ksp)) {
164 return KstatUtil.dataLookupLong(ksp, "buf_inuse");
165 }
166 }
167 return 0L;
168 }
169
170 @Override
171 public long getMaxFileDescriptors() {
172 if (HAS_KSTAT2) {
173
174 return FILE_DESC.get().getB();
175 }
176 try (KstatChain kc = KstatUtil.openChain()) {
177 Kstat ksp = kc.lookup(null, -1, "file_cache");
178
179 if (ksp != null && kc.read(ksp)) {
180 return KstatUtil.dataLookupLong(ksp, "buf_max");
181 }
182 }
183 return 0L;
184 }
185
186 @Override
187 public long getMaxFileDescriptorsPerProcess() {
188 final List<String> lines = FileUtil.readFile("/etc/system");
189 for (final String line : lines) {
190 if (line.startsWith("set rlim_fd_max")) {
191 return ParseUtil.parseLastLong(line, 65536L);
192 }
193 }
194 return 65536L;
195 }
196
197 private static Pair<Long, Long> queryFileDescriptors() {
198 Object[] results = KstatUtil.queryKstat2("kstat:/kmem_cache/kmem_default/file_cache", "buf_inuse", "buf_max");
199 long inuse = results[0] == null ? 0L : (long) results[0];
200 long max = results[1] == null ? 0L : (long) results[1];
201 return new Pair<>(inuse, max);
202 }
203 }