Autopsy 4.22.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
PlatformUtil.java
Go to the documentation of this file.
1/*
2 * Autopsy Forensic Browser
3 *
4 * Copyright 2012-2019 Basis Technology Corp.
5 * Contact: carrier <at> sleuthkit <dot> org
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19package org.sleuthkit.autopsy.coreutils;
20
21import java.io.BufferedInputStream;
22import java.io.BufferedOutputStream;
23import java.io.BufferedReader;
24import java.io.File;
25import java.io.FileInputStream;
26import java.io.FileOutputStream;
27import java.io.IOException;
28import java.io.InputStream;
29import java.io.InputStreamReader;
30import java.io.OutputStream;
31import java.lang.management.ManagementFactory;
32import java.lang.management.MemoryMXBean;
33import java.lang.management.MemoryUsage;
34import java.nio.charset.Charset;
35import java.nio.charset.StandardCharsets;
36import java.nio.file.Path;
37import java.nio.file.Paths;
38import java.util.ArrayList;
39import java.util.Arrays;
40import java.util.List;
41import java.util.Map;
42import java.util.regex.Pattern;
43import java.util.stream.Stream;
44import javax.swing.filechooser.FileSystemView;
45import org.apache.commons.io.FilenameUtils;
46import org.openide.modules.InstalledFileLocator;
47import org.openide.modules.Places;
48import org.openide.util.NbBundle;
49import org.sleuthkit.datamodel.SleuthkitJNI;
50import org.sleuthkit.datamodel.TskCoreException;
51
56public class PlatformUtil {
57
58 private static final String PYTHON_MODULES_SUBDIRECTORY = "python_modules"; //NON-NLS
59 private static final String CLASSIFIERS_SUBDIRECTORY = "object_detection_classifiers"; //NON-NLS
60 private static final String OCR_LANGUAGE_SUBDIRECTORY = "ocr_language_packs"; //NON-NLS
61 private static final String OCR_LANGUAGE_PACK_EXT = "traineddata";
62 private static String javaPath = null;
63 public static final String OS_NAME_UNKNOWN = NbBundle.getMessage(PlatformUtil.class, "PlatformUtil.nameUnknown");
64 public static final String OS_VERSION_UNKNOWN = NbBundle.getMessage(PlatformUtil.class, "PlatformUtil.verUnknown");
65 public static final String OS_ARCH_UNKNOWN = NbBundle.getMessage(PlatformUtil.class, "PlatformUtil.archUnknown");
66 private static volatile long pid = -1;
67 private static volatile MemoryMXBean memoryManager = null;
68
74 public static String getInstallPath() {
75 File coreFolder = InstalledFileLocator.getDefault().locate("core", PlatformUtil.class.getPackage().getName(), false); //NON-NLS
76 File rootPath = coreFolder.getParentFile().getParentFile();
77 return rootPath.getAbsolutePath();
78 }
79
86 public static String getInstallModulesPath() {
87 File coreFolder = InstalledFileLocator.getDefault().locate("core", PlatformUtil.class.getPackage().getName(), false); //NON-NLS
88
89 File rootPath = coreFolder.getParentFile();
90 String modulesPath = rootPath.getAbsolutePath() + File.separator + "modules"; //NON-NLS
91 File modulesPathF = new File(modulesPath);
92 if (modulesPathF.exists() && modulesPathF.isDirectory()) {
93 return modulesPath;
94 } else {
95 rootPath = rootPath.getParentFile();
96 modulesPath = rootPath.getAbsolutePath() + File.separator + "modules"; //NON-NLS
97 modulesPathF = new File(modulesPath);
98 if (modulesPathF.exists() && modulesPathF.isDirectory()) {
99 return modulesPath;
100 } else {
101 return null;
102 }
103 }
104
105 }
106
113 public static String getUserModulesPath() {
114 return getUserDirectory().getAbsolutePath() + File.separator + "modules"; //NON-NLS
115 }
116
122 public static String getUserPythonModulesPath() {
123 return getUserDirectory().getAbsolutePath() + File.separator + PYTHON_MODULES_SUBDIRECTORY;
124 }
125
131 public static String getOcrLanguagePacksPath() {
132 return getUserDirectory().getAbsolutePath() + File.separator + OCR_LANGUAGE_SUBDIRECTORY;
133 }
134
140 public static List<String> getOcrLanguagePacks() {
141 File languagePackRootDir = new File(getOcrLanguagePacksPath());
142
143 List<String> languagePacks = new ArrayList<>();
144 for (File languagePack : languagePackRootDir.listFiles()) {
145 String fileExt = FilenameUtils.getExtension(languagePack.getName());
146 if (!languagePack.isDirectory() && OCR_LANGUAGE_PACK_EXT.equals(fileExt)) {
147 String packageName = FilenameUtils.getBaseName(languagePack.getName());
148 languagePacks.add(packageName);
149 }
150 }
151
152 return languagePacks;
153 }
154
160 public static String getObjectDetectionClassifierPath() {
161 return getUserDirectory().getAbsolutePath() + File.separator + CLASSIFIERS_SUBDIRECTORY;
162 }
163
171 public synchronized static String getJavaPath() {
172 if (javaPath != null) {
173 return javaPath;
174 }
175
176 // by default, use Java that came with Autopsy
177 File jrePath = new File(getInstallPath() + File.separator + "jre");
178 if (jrePath.exists() && jrePath.isDirectory()) {
179 System.out.println(
180 NbBundle.getMessage(PlatformUtil.class,
181 "PlatformUtil.jrePath.jreDir.msg",
182 jrePath.getAbsolutePath()));
183 javaPath = jrePath.getAbsolutePath() + File.separator + "bin" + File.separator + "java"; //NON-NLS
184 } else if (System.getProperty("java.home") != null && !(System.getProperty("java.home").isEmpty())) {
185 // if OS knows where Java is located
186 return System.getProperty("java.home") + File.separator + "bin" + File.separator + "java"; //NON-NLS
187 } else {
188 //else use system installed java in PATH env variable
189 javaPath = "java"; //NON-NLS
190 }
191
192 System.out.println(NbBundle.getMessage(PlatformUtil.class, "PlatformUtil.jrePath.usingJavaPath.msg", javaPath));
193
194 return javaPath;
195 }
196
203 public static File getUserDirectory() {
204 return Places.getUserDirectory();
205 }
206
212 public static List<String> getProjectsDirs() {
213 List<String> ret = new ArrayList<>();
214 String projectDir = System.getProperty("netbeans.dirs");
215 if (projectDir == null) {
216 return ret;
217 }
218 String[] split = projectDir.split(";");
219 if (split == null || split.length == 0) {
220 return ret;
221 }
222 ret.addAll(Arrays.asList(split));
223
224 return ret;
225 }
226
232 public static String getUserConfigDirectory() {
233 return Places.getUserDirectory() + File.separator + "config"; //NON-NLS
234 }
235
241 public static String getModuleConfigDirectory() {
242 return Paths.get(getUserConfigDirectory(), "ModuleConfig").toString();
243 }
244
250 public static String getLogDirectory() {
251 return Places.getUserDirectory().getAbsolutePath() + File.separator
252 + "var" + File.separator + "log" + File.separator; //NON-NLS
253 }
254
255 public static String getDefaultPlatformFileEncoding() {
256 return System.getProperty("file.encoding");
257 }
258
259 public static String getDefaultPlatformCharset() {
260 return Charset.defaultCharset().name();
261 }
262
263 public static String getLogFileEncoding() {
264 return Charset.forName("UTF-8").name();
265 }
266
281 public static <T> boolean extractResourceToUserConfigDir(final Class<T> resourceClass, final String resourceFileName, boolean overWrite) throws IOException {
282 Path resourceFilePath = Paths.get(getUserConfigDirectory(), resourceFileName);
283 final File resourceFile = resourceFilePath.toFile();
284 if (resourceFile.exists() && !overWrite) {
285 return false;
286 }
287
288 InputStream inputStream = resourceClass.getResourceAsStream(resourceFileName);
289 if (null == inputStream) {
290 return false;
291 }
292
293 resourceFile.getParentFile().mkdirs();
294 try (InputStream in = new BufferedInputStream(inputStream)) {
295 try (OutputStream out = new BufferedOutputStream(new FileOutputStream(resourceFile))) {
296 int readBytes;
297 while ((readBytes = in.read()) != -1) {
298 out.write(readBytes);
299 }
300 }
301 }
302 return true;
303 }
304
310 public static String getOSName() {
311 return System.getProperty("os.name", OS_NAME_UNKNOWN); //NON-NLS
312 }
313
319 public static String getOSVersion() {
320 return System.getProperty("os.version", OS_VERSION_UNKNOWN); //NON-NLS
321 }
322
328 public static String getOSArch() {
329 return System.getProperty("os.arch", OS_ARCH_UNKNOWN); //NON-NLS
330 }
331
337 public static boolean isWindowsOS() {
338 return PlatformUtil.getOSName().toLowerCase().contains("windows"); //NON-NLS
339 }
340
346 public static boolean isLinuxOS() {
347 return PlatformUtil.getOSName().toLowerCase().contains("linux"); //NON-NLS
348 }
349
355 public static boolean isMacOS() {
356 return PlatformUtil.getOSName().toLowerCase().contains("mac"); //NON-NLS
357 }
358
366 public static String getOSFilePath(String origFilePath) {
367 if (isWindowsOS()) {
368 return "\"" + origFilePath + "\"";
369 } else {
370 return origFilePath;
371 }
372 }
373
381 public static boolean is64BitOS() {
382 if (System.getProperty("os.name").contains("Windows")) { //NON-NLS
383 return (System.getenv("ProgramFiles(x86)") != null); //NON-NLS
384 } else {
385 return (System.getProperty("os.arch").contains("64")); //NON-NLS
386 }
387 }
388
395 public static boolean is64BitJVM() {
396 return (System.getProperty("sun.arch.data.model").equals("64"));
397 }
398
405 public static List<LocalDisk> getPhysicalDrives() {
406 List<LocalDisk> drives = new ArrayList<>();
407 // Windows drives
409 int n = 0;
410 int breakCount = 0;
411 while (true) {
412 String path = "\\\\.\\PhysicalDrive" + n; //NON-NLS
413 if (canReadDrive(path)) {
414 try {
415 drives.add(new LocalDisk("Drive " + n, path, SleuthkitJNI.findDeviceSize(path))); //NON-NLS
416 } catch (TskCoreException ex) {
417 // Don't add the drive because we can't read the size
418 }
419 n++;
420 } else {
421 if (breakCount > 4) { // Give up after 4 non-existent drives
422 break;
423 }
424 breakCount++;
425 n++;
426 }
427 }
428 // Linux drives
429 } else {
430 File dev = new File("/dev/");
431 File[] files = dev.listFiles();
432 for (File f : files) {
433 String name = f.getName();
434 if ((name.contains("hd") || name.contains("sd") || name.contains("disk")) && f.canRead() && name.length() <= 5) { //NON-NLS
435 String path = "/dev/" + name; //NON-NLS
436 if (canReadDrive(path)) {
437 try {
438 drives.add(new LocalDisk(path, path, SleuthkitJNI.findDeviceSize(path)));
439 } catch (TskCoreException ex) {
440 // Don't add the drive because we can't read the size
441 }
442 }
443 }
444 }
445
446 }
447 return drives;
448 }
449
456 public static List<LocalDisk> getPartitions() {
457 List<LocalDisk> drives = new ArrayList<>();
458 FileSystemView fsv = FileSystemView.getFileSystemView();
460 File[] f = File.listRoots();
461 for (File f1 : f) {
462 String name = fsv.getSystemDisplayName(f1);
463 // Check if it is a drive, readable, and not mapped to the network
464 if (f1.canRead() && !name.contains("\\\\") && (fsv.isDrive(f1) || fsv.isFloppyDrive(f1))) {
465 String path = f1.getPath();
466 String diskPath = "\\\\.\\" + path.substring(0, path.length() - 1);
467 if (canReadDrive(diskPath)) {
468 drives.add(new LocalDisk(fsv.getSystemDisplayName(f1), diskPath, f1.getTotalSpace()));
469 }
470 }
471 }
472 } else {
473 File dev = new File("/dev/");
474 File[] files = dev.listFiles();
475 for (File f : files) {
476 String name = f.getName();
477 if ((name.contains("hd") || name.contains("sd") || name.contains("disk")) && f.canRead() && name.length() <= 7) { //NON-NLS
478 String path = "/dev/" + name; //NON-NLS
479 if (canReadDrive(path)) {
480 drives.add(new LocalDisk(path, path, f.getTotalSpace()));
481 }
482 }
483 }
484 }
485 return drives;
486 }
487
503 private static boolean canReadDrive(String diskPath) {
504 BufferedInputStream br = null;
505 try {
506 File tmp = new File(diskPath);
507 br = new BufferedInputStream(new FileInputStream(tmp));
508 int b = br.read();
509 return b != -1;
510 } catch (IOException ex) {
511 return false;
512 } finally {
513 try {
514 if (br != null) {
515 br.close();
516 }
517 } catch (IOException ex) {
518 }
519 }
520 }
521
527 public static synchronized long getPID() {
528 // taken from https://stackoverflow.com/a/7303433/2375948
529 return ProcessHandle.current().pid();
530 }
531
542 public static synchronized long getJavaPID(String sigarSubQuery) {
543 long[] pids = getJavaPIDs(sigarSubQuery);
544 return pids == null || pids.length < 1
545 ? -1
546 : pids[0];
547 }
548
556 private static String convertSqlLikeToRegex(String originalLikeStatement) {
557 if (originalLikeStatement == null) {
558 return "";
559 }
560
561 // Build the regex by quoting each literal segment and replacing wildcards.
562 // The original implementation incorrectly called Pattern.quote() on the
563 // entire string before substituting wildcards, which placed the substituted
564 // ".*" and "." inside the \Q...\E literal region where they are not treated
565 // as regex metacharacters.
566 StringBuilder regex = new StringBuilder();
567 StringBuilder literal = new StringBuilder();
568
569 char[] chars = originalLikeStatement.toCharArray();
570 for (int i = 0; i < chars.length; i++) {
571 char cur = chars[i];
572 if (cur == '%' || cur == '_') {
573 // Doubled wildcard (e.g. %% or __) is treated as an escaped literal.
574 if (i + 1 < chars.length && chars[i + 1] == cur) {
575 literal.append(cur);
576 i++;
577 } else {
578 if (literal.length() > 0) {
579 regex.append(Pattern.quote(literal.toString()));
580 literal.setLength(0);
581 }
582 regex.append(cur == '%' ? ".*" : "."); //NON-NLS
583 }
584 } else {
585 literal.append(cur);
586 }
587 }
588
589 if (literal.length() > 0) {
590 regex.append(Pattern.quote(literal.toString()));
591 }
592
593 return regex.toString();
594 }
595
604 public static synchronized long[] getJavaPIDs(String argsSubQuery) {
605 // Previously this method used WMIC on Windows and "ps -ef | grep" on
606 // Linux/Mac by constructing shell commands with Runtime.getRuntime().exec().
607 // Those approaches had a shell injection vulnerability (argsSubQuery was
608 // interpolated directly into the WMIC query string), and the Linux pipe
609 // was likely broken because exec(String) does not invoke a shell.
610 // Both were replaced with ProcessHandle (requires Java 9+, fine since
611 // Autopsy now requires Java 21).
612 //
613 // Known limitation: on Windows, ProcessHandle.Info.commandLine() returns
614 // Optional.empty() for processes owned by other users or running as a
615 // service. The old WMIC approach did not have this restriction. In
616 // practice this should not matter because Autopsy starts Solr under the
617 // same user account, but if getJavaPIDs() ever starts returning empty
618 // results when a matching process is known to exist, cross-user
619 // visibility is the first thing to investigate.
620 String regexStr = ".*java.*" + convertSqlLikeToRegex(argsSubQuery) + ".*"; //NON-NLS
621 try {
622 Pattern pattern = Pattern.compile(regexStr, Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
623 return ProcessHandle.allProcesses()
624 .filter(ph -> ph.info().commandLine()
625 .map(cmd -> pattern.matcher(cmd).matches())
626 .orElse(false))
627 .mapToLong(ProcessHandle::pid)
628 .toArray();
629 } catch (Exception ex) {
630 System.out.println("An exception occurred while fetching java pids with query: " + argsSubQuery + " : " + ex.getMessage());
631 return null;
632 }
633 }
634
640 public static synchronized void killProcess(long pid) {
641 String cmd = isWindowsOS()
642 ? "taskkill /F /PID " + pid
643 : "kill " + pid;
644
645 try {
646 Runtime.getRuntime().exec(cmd);
647 } catch (IOException ex) {
648 System.out.println("An exception occurred while killing process pid: " + pid);
649 ex.printStackTrace();
650 }
651 }
652
658 public static synchronized long getProcessVirtualMemoryUsed() {
659 // taken from https://stackoverflow.com/a/17376879/2375948
660 return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
661 }
662
668 public static String getJvmMemInfo() {
669 synchronized (PlatformUtil.class) {
670 if (memoryManager == null) {
671 memoryManager = ManagementFactory.getMemoryMXBean();
672 }
673 }
674 final MemoryUsage heap = memoryManager.getHeapMemoryUsage();
675 final MemoryUsage nonHeap = memoryManager.getNonHeapMemoryUsage();
676
677 return NbBundle.getMessage(PlatformUtil.class,
678 "PlatformUtil.getJvmMemInfo.usageText",
679 heap.toString(), nonHeap.toString());
680 }
681
687 public static String getPhysicalMemInfo() {
688 final Runtime runTime = Runtime.getRuntime();
689 final long maxMemory = runTime.maxMemory();
690 final long totalMemory = runTime.totalMemory();
691 final long freeMemory = runTime.freeMemory();
692 return NbBundle.getMessage(PlatformUtil.class,
693 "PlatformUtil.getPhysicalMemInfo.usageText",
694 Long.toString(maxMemory), Long.toString(totalMemory), Long.toString(freeMemory));
695 }
696
702 public static String getAllMemUsageInfo() {
703 return NbBundle.getMessage(PlatformUtil.class,
704 "PlatformUtil.getAllMemUsageInfo.usageText",
707 }
708}
static synchronized long getJavaPID(String sigarSubQuery)
static String getOSFilePath(String origFilePath)
static String convertSqlLikeToRegex(String originalLikeStatement)
static synchronized long[] getJavaPIDs(String argsSubQuery)
static synchronized long getProcessVirtualMemoryUsed()
static< T > boolean extractResourceToUserConfigDir(final Class< T > resourceClass, final String resourceFileName, boolean overWrite)
static volatile MemoryMXBean memoryManager
static boolean canReadDrive(String diskPath)
static synchronized void killProcess(long pid)

Copyright © 2012-2024 Sleuth Kit Labs. Generated on:
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.