GP-1164: Reorganizing Ghidra's user settings/cache/temp directories to support XDG

This commit is contained in:
Ryan Kurtz 2023-12-19 08:22:40 -05:00
parent 8bfcb02166
commit 3c30ada14c
50 changed files with 919 additions and 222 deletions

View file

@ -0,0 +1,310 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package utility.application;
import static utility.application.ApplicationUtilities.*;
import static utility.application.XdgUtils.*;
import java.io.File;
import java.util.*;
import generic.jar.ResourceFile;
import ghidra.GhidraApplicationLayout;
import ghidra.GhidraLaunchable;
import ghidra.framework.ApplicationProperties;
import ghidra.framework.OperatingSystem;
import ghidra.util.SystemUtilities;
import utilities.util.FileUtilities;
/**
* Interactive utility to discover and delete artifacts that Ghidra lays down on the filesystem
*/
public class AppCleaner implements GhidraLaunchable {
/**
* Launches the {@link AppCleaner}
*
* @param layout The application layout to use for the launch
* @param args One argument is expected: the name of the application to clean. All other
* arguments are ignored.
* @throws Exception if there was a problem with the launch
*/
@Override
public void launch(GhidraApplicationLayout layout, String[] args) throws Exception {
if (args.length != 1) {
System.out.println("Expected 1 argument but got " + args.length);
System.exit(1);
}
String appName = args[0];
System.out.println("\nDiscovering " + appName + " artifact directories....");
// Discover directories
Set<File> discoveredSet = new LinkedHashSet<>();
discoveredSet.addAll(findSettingsDirs(appName, layout));
discoveredSet.addAll(findCacheDirs(appName, layout));
discoveredSet.addAll(findTempDirs(appName, layout));
List<File> discoveredDirs = new ArrayList<>(discoveredSet);
// Exit if we didn't discover any directories
if (discoveredDirs.isEmpty()) {
System.out.println("NONE FOUND");
return;
}
// Output discovered directories and prompt user
File potentialParentDir = null;
for (int i = 0; i < discoveredDirs.size(); i++) {
File d = discoveredDirs.get(i);
File parentDir = d.getParentFile();
boolean indent = parentDir.equals(potentialParentDir);
System.out.println("%2d)%s %s".formatted(i + 1, indent ? " " : "", d));
if (!indent) {
potentialParentDir = d;
}
}
System.out.println("*) All");
System.out.println("0) Exit");
System.out.print("Enter a directory to delete: ");
// Get user choice and delete
String choice = null;
try (Scanner scanner = new Scanner(System.in)){
List<File> failures = new ArrayList<>();
choice = scanner.nextLine().trim();
switch (choice) {
case "0":
System.out.println("Exiting...");
return;
case "*":
for (File dir : discoveredDirs) {
if (dir.isDirectory()) {
if (!FileUtilities.deleteDir(dir)) {
failures.add(dir);
}
}
}
break;
default:
File dir = discoveredDirs.get(Integer.parseInt(choice) - 1);
if (!FileUtilities.deleteDir(dir)) {
failures.add(dir);
}
}
System.out.println(failures.isEmpty() ? "SUCCESS" : "Failed to delete:");
failures.forEach(dir -> System.out.println(" " + dir));
}
catch (NoSuchElementException e) {
// User likely hit ctrl+c to exit
}
catch (NumberFormatException | IndexOutOfBoundsException e) {
System.out.println("Invalid entry: \"" + choice + "\"");
}
}
/**
* Finds user settings directories
*
* @param appName The name of the application
* @param layout The layout
* @return A {@link Set} of discovered user settings directories, ordered such that
* parent directories are directly followed by their subdirectories, if applicable
* @see ApplicationUtilities#getDefaultUserSettingsDir(ApplicationProperties, ResourceFile)
* @see ApplicationUtilities#getLegacyUserSettingsDir(ApplicationProperties, ResourceFile)
*/
private Set<File> findSettingsDirs(String appName, ApplicationLayout layout) {
Set<File> discoveredDirs = new LinkedHashSet<>();
appName = appName.toLowerCase();
String userNameAndAppName = SystemUtilities.getUserName() + "-" + appName;
// Legacy default settings directory
getDirFromProperty("user.home", "." + appName).ifPresent(dir -> {
discoveredDirs.add(dir);
discoveredDirs.addAll(getSubdirs(dir));
});
// Current default settings directory
File settingsDir = layout.getUserSettingsDir();
File settingsParentDir = settingsDir.getParentFile();
if (settingsParentDir != null && (settingsParentDir.getName().equals(appName) ||
settingsParentDir.getName().equals(userNameAndAppName))) {
discoveredDirs.add(settingsParentDir);
discoveredDirs.addAll(getSubdirs(settingsParentDir));
}
// Application system property override (likely not set for AppCleaner)
getDirFromProperty(PROPERTY_SETTINGS_DIR, appName).ifPresent(dir -> {
discoveredDirs.add(dir);
discoveredDirs.addAll(getSubdirs(dir));
});
getDirFromProperty(PROPERTY_SETTINGS_DIR, userNameAndAppName).ifPresent(dir -> {
discoveredDirs.add(dir);
discoveredDirs.addAll(getSubdirs(dir));
});
// XDG environment variable override
getDirFromEnv(XDG_CONFIG_HOME, appName).ifPresent(dir -> {
discoveredDirs.add(dir);
discoveredDirs.addAll(getSubdirs(dir));
});
getDirFromEnv(XDG_CONFIG_HOME, userNameAndAppName).ifPresent(dir -> {
discoveredDirs.add(dir);
discoveredDirs.addAll(getSubdirs(dir));
});
return discoveredDirs;
}
/**
* Finds user cache directories
*
* @param appName The name of the application
* @param layout The layout
* @return A {@link Set} of discovered user cache directories, ordered such that
* parent directories are directly followed by their subdirectories, if applicable
* @see ApplicationUtilities#getDefaultUserCacheDir(ApplicationProperties)
*/
private Set<File> findCacheDirs(String appName, ApplicationLayout layout) {
Set<File> discoveredDirs = new LinkedHashSet<>();
// Legacy cache directories
if (OperatingSystem.CURRENT_OPERATING_SYSTEM.equals(OperatingSystem.WINDOWS)) {
getDirFromEnv("LOCALAPPDATA", appName).ifPresent(discoveredDirs::add);
}
else {
String legacyName = SystemUtilities.getUserName() + "-" + appName;
getDirFromProperty("java.io.tmpdir", legacyName).ifPresent(discoveredDirs::add);
}
// Newer cache directories always use a lowercase application name
appName = appName.toLowerCase();
String userNameAndAppName = SystemUtilities.getUserName() + "-" + appName;
// Current cache directories
File cacheDir = layout.getUserCacheDir();
if (cacheDir != null && cacheDir.isDirectory()) {
discoveredDirs.add(cacheDir);
}
// Application system property override (likely not set for AppCleaner)
getDirFromProperty(PROPERTY_CACHE_DIR, appName).ifPresent(discoveredDirs::add);
getDirFromProperty(PROPERTY_CACHE_DIR, userNameAndAppName).ifPresent(discoveredDirs::add);
// XDG environment variable override
getDirFromEnv(XDG_CACHE_HOME, appName).ifPresent(discoveredDirs::add);
getDirFromEnv(XDG_CACHE_HOME, userNameAndAppName).ifPresent(discoveredDirs::add);
return discoveredDirs;
}
/**
* Finds user temp directories
*
* @param appName The name of the application
* @param layout The layout
* @return A {@link Set} of discovered user temp directories, ordered such that
* parent directories are directly followed by their subdirectories, if applicable
* @see ApplicationUtilities#getDefaultUserTempDir(String)
*/
private Set<File> findTempDirs(String appName, ApplicationLayout layout) {
Set<File> discoveredDirs = new LinkedHashSet<>();
// Legacy temp directories
String legacyName = SystemUtilities.getUserName() + "-" + appName;
if (OperatingSystem.CURRENT_OPERATING_SYSTEM.equals(OperatingSystem.WINDOWS)) {
getDirFromEnv("TEMP", legacyName).ifPresent(discoveredDirs::add);
}
else {
getDirFromProperty("java.io.tmpdir", legacyName).ifPresent(discoveredDirs::add);
}
// Newer temp directories always use a lowercase application name
appName = appName.toLowerCase();
String userNameAndAppName = SystemUtilities.getUserName() + "-" + appName;
// Current temp directories
File tempDir = layout.getUserTempDir();
if (tempDir != null && tempDir.isDirectory()) {
discoveredDirs.add(tempDir);
}
// Application system property override (likely not set for AppCleaner)
getDirFromProperty(PROPERTY_TEMP_DIR, appName).ifPresent(discoveredDirs::add);
getDirFromProperty(PROPERTY_TEMP_DIR, userNameAndAppName).ifPresent(discoveredDirs::add);
// XDG environment variable override
getDirFromEnv(XDG_RUNTIME_DIR, appName).ifPresent(discoveredDirs::add);
getDirFromEnv(XDG_RUNTIME_DIR, userNameAndAppName).ifPresent(discoveredDirs::add);
return discoveredDirs;
}
/**
* Gets the subdirectory of the given name found within the directory specified by the given
* system property
*
* @param propertyName The name of the system property
* @param subdirName The name of the subdirectory within the directory specified by the given
* system property
* @return The subdirectory of the given name found within the directory specified by the given
* systemProperty
*/
private Optional<File> getDirFromProperty(String propertyName, String subdirName) {
String path = System.getProperty(propertyName, "").trim();
if (!path.isEmpty()) {
File dir = new File(path, subdirName);
if (dir.isDirectory()) {
return Optional.of(dir);
}
}
return Optional.empty();
}
/**
* Gets the subdirectory of the given name found within the directory specified by the given
* environment variable
*
* @param envName The name of the environment variable
* @param subdirName The name of the subdirectory within the directory specified by the given
* environment variable
* @return The subdirectory of the given name found within the directory specified by the given
* environment variable
*/
private Optional<File> getDirFromEnv(String envName, String subdirName) {
String path = System.getenv(envName);
if (path != null && !path.isBlank()) {
File dir = new File(path, subdirName);
if (dir.isDirectory()) {
return Optional.of(dir);
}
}
return Optional.empty();
}
/**
* Gets the direct sub-directories of the given directory (non-recursive)
*
* @param dir The directory to get the sub-directories of
* @return The direct sub-directories of the given directory
*/
private List<File> getSubdirs(File dir) {
File[] listing = dir.listFiles(File::isDirectory);
return listing != null ? Arrays.asList(listing) : List.of();
}
}

View file

@ -15,11 +15,11 @@
*/
package utility.application;
import ghidra.framework.PluggableServiceRegistry;
import java.io.File;
import java.io.IOException;
import utilities.util.FileUtilities;
import ghidra.framework.PluggableServiceRegistry;
import ghidra.util.Msg;
public class ApplicationSettings {
static {
@ -46,6 +46,13 @@ public class ApplicationSettings {
* application version.
*/
protected File doGetUserApplicationSettingsDirectory() {
return FileUtilities.createTempDirectory("application.settings_");
try {
return ApplicationUtilities.getDefaultUserTempDir("application.settings");
}
catch (IOException e) {
Msg.error(ApplicationSettings.class, "Error creating application.settings directory",
e);
return null;
}
}
}

View file

@ -23,12 +23,28 @@ import generic.jar.ResourceFile;
import ghidra.framework.*;
import ghidra.util.Msg;
import ghidra.util.SystemUtilities;
import utilities.util.FileUtilities;
/**
* Utility class for default application things.
*/
public class ApplicationUtilities {
/**
* Name of system property used to override the location of the user temporary directory
*/
public static final String PROPERTY_TEMP_DIR = "application.tempdir";
/**
* Name of system property used to override the location of the user cache directory
*/
public static final String PROPERTY_CACHE_DIR = "application.cachedir";
/**
* Name of system property used to override the location of the user settings directory
*/
public static final String PROPERTY_SETTINGS_DIR = "application.settingsdir";
/**
* Searches for default application root directories.
*
@ -137,85 +153,145 @@ public class ApplicationUtilities {
}
/**
* Gets the default application's user temp directory.
* Gets the application's default user temp directory.
* <p>
* NOTE: This method does not create the directory.
*
* @param applicationProperties The application properties.
* @return The default application's user temp directory.
* @throws FileNotFoundException if the user temp directory could not be determined.
* @param applicationName The application name.
* @return The application's default user temp directory. The returned {@link File} will
* represent an absolute path.
* @throws FileNotFoundException if the absolute path of the user temp directory could not be
* determined.
*/
public static File getDefaultUserTempDir(ApplicationProperties applicationProperties)
throws FileNotFoundException {
String tmpdir = System.getProperty("java.io.tmpdir");
if (tmpdir == null || tmpdir.isEmpty()) {
throw new FileNotFoundException("System property \"java.io.tmpdir\" is not set!");
public static File getDefaultUserTempDir(String applicationName) throws FileNotFoundException {
String appName = applicationName.toLowerCase();
// Look for Ghidra-specific system property
File tempOverrideDir = getSystemPropertyFile(PROPERTY_TEMP_DIR, false);
if (tempOverrideDir != null) {
return new File(tempOverrideDir, getUserSpecificDirName(tempOverrideDir, appName));
}
return new File(tmpdir,
SystemUtilities.getUserName() + "-" + applicationProperties.getApplicationName());
// Look for XDG environment variable
File xdgRuntimeDir = getEnvFile(XdgUtils.XDG_RUNTIME_DIR, false);
if (xdgRuntimeDir != null) {
return new File(xdgRuntimeDir, getUserSpecificDirName(xdgRuntimeDir, appName));
}
File javaTmpDir = getJavaTmpDir();
return new File(javaTmpDir, getUserSpecificDirName(javaTmpDir, appName));
}
/**
* Gets the default application's user cache directory.
* Gets the application's default user cache directory.
* <p>
* NOTE: This method does not create the directory.
*
* @param applicationProperties The application properties.
* @return The default application's user cache directory.
* @throws FileNotFoundException if the user cache directory could not be determined.
* @return The application's default user cache directory. The returned {@link File} will
* represent an absolute path.
* @throws FileNotFoundException if the absolute path of the user cache directory could not be
* determined.
*/
public static File getDefaultUserCacheDir(ApplicationProperties applicationProperties)
throws FileNotFoundException {
// Look for preset cache directory
String cachedir = System.getProperty("application.cachedir", "").trim();
if (!cachedir.isEmpty()) {
return new File(cachedir,
SystemUtilities.getUserName() + "-" + applicationProperties.getApplicationName());
String appName = applicationProperties.getApplicationName().toLowerCase();
// Look for Ghidra-specific system property
File cacheOverrideDir = getSystemPropertyFile(PROPERTY_CACHE_DIR, false);
if (cacheOverrideDir != null) {
return new File(cacheOverrideDir, getUserSpecificDirName(cacheOverrideDir, appName));
}
// Handle Windows specially
if (OperatingSystem.CURRENT_OPERATING_SYSTEM == OperatingSystem.WINDOWS) {
File localAppDataDir = null;
String localAppDataDirPath = System.getenv("LOCALAPPDATA"); // e.g., /Users/myname/AppData/Local
if (localAppDataDirPath != null && !localAppDataDirPath.isEmpty()) {
localAppDataDir = new File(localAppDataDirPath);
}
else {
String userHome = System.getProperty("user.home");
if (userHome != null) {
localAppDataDir = new File(userHome, "AppData\\Local");
if (!localAppDataDir.isDirectory()) {
localAppDataDir = new File(userHome, "Local Settings");
}
}
}
if (localAppDataDir != null && localAppDataDir.isDirectory()) {
return new File(localAppDataDir, applicationProperties.getApplicationName());
}
// Look for XDG environment variable
File xdgCacheHomeDir = getEnvFile(XdgUtils.XDG_CACHE_HOME, false);
if (xdgCacheHomeDir != null) {
return new File(xdgCacheHomeDir, getUserSpecificDirName(xdgCacheHomeDir, appName));
}
// Use user temp directory if platform specific scheme does not exist above or it failed
return getDefaultUserTempDir(applicationProperties);
// Use platform-specific default location
String userDirName = SystemUtilities.getUserName() + "-" + appName;
return switch (OperatingSystem.CURRENT_OPERATING_SYSTEM) {
case WINDOWS -> new File(getEnvFile("LOCALAPPDATA", true), appName);
case LINUX -> new File("/var/tmp/" + userDirName);
case MAC_OS_X -> new File("/var/tmp/" + userDirName);
default -> throw new FileNotFoundException(
"Failed to find the user cache directory: Unsupported operating system.");
};
}
/**
* Gets the default application's user settings directory.
* Gets the application's default user settings directory.
* <p>
* NOTE: This method does not create the directory.
*
* @param applicationProperties The application properties.
* @param installationDirectory The application installation directory.
* @return The application's user settings directory.
* @throws FileNotFoundException if the user settings directory could not be determined.
* @return The application's default user settings directory. The returned {@link File} will
* represent an absolute path.
* @throws FileNotFoundException if the absolute path of the user settings directory could not
* be determined.
*/
public static File getDefaultUserSettingsDir(ApplicationProperties applicationProperties,
ResourceFile installationDirectory) throws FileNotFoundException {
String homedir = System.getProperty("user.home");
if (homedir == null || homedir.isEmpty()) {
throw new FileNotFoundException("System property \"user.home\" is not set!");
String appName = applicationProperties.getApplicationName().toLowerCase();
ApplicationIdentifier applicationIdentifier =
new ApplicationIdentifier(applicationProperties);
String versionedName = applicationIdentifier.toString();
if (SystemUtilities.isInDevelopmentMode()) {
// Add the application's installation directory name to this variable, so that each
// branch's project user directory is unique.
versionedName += "_location_" + installationDirectory.getName();
}
// Look for Ghidra-specific system property
File settingsOverrideDir = getSystemPropertyFile(PROPERTY_SETTINGS_DIR, false);
if (settingsOverrideDir != null) {
return new File(settingsOverrideDir,
getUserSpecificDirName(settingsOverrideDir, appName) + "/" + versionedName);
}
// Look for XDG environment variable
File xdgConfigHomeDir = getEnvFile(XdgUtils.XDG_CONFIG_HOME, false);
if (xdgConfigHomeDir != null) {
return new File(xdgConfigHomeDir,
getUserSpecificDirName(xdgConfigHomeDir, appName) + "/" + versionedName);
}
File userHomeDir = getJavaUserHomeDir();
String versionedSubdir = appName + "/" + versionedName;
return switch (OperatingSystem.CURRENT_OPERATING_SYSTEM) {
case WINDOWS -> new File(getEnvFile("APPDATA", true), versionedSubdir);
case LINUX -> new File(userHomeDir, ".config/" + versionedSubdir);
case MAC_OS_X -> new File(userHomeDir, "Library/" + versionedSubdir);
default -> throw new FileNotFoundException(
"Failed to find the user settings directory: Unsupported operating system.");
};
}
/**
* Gets the application's legacy (pre-Ghida 11.1) user settings directory.
* <p>
* NOTE: This method does not create the directory.
*
* @param applicationProperties The application properties.
* @param installationDirectory The application installation directory.
* @return The application's legacy user settings directory. The returned {@link File} will
* represent an absolute path.
* @throws FileNotFoundException if the absolute path of the legacy user settings directory
* could not be determined.
*/
public static File getLegacyUserSettingsDir(ApplicationProperties applicationProperties,
ResourceFile installationDirectory) throws FileNotFoundException {
ApplicationIdentifier applicationIdentifier =
new ApplicationIdentifier(applicationProperties);
File userSettingsParentDir =
new File(homedir, "." + applicationIdentifier.getApplicationName());
new File(getJavaUserHomeDir(), "." + applicationIdentifier.getApplicationName());
String userSettingsDirName = "." + applicationIdentifier;
@ -227,4 +303,108 @@ public class ApplicationUtilities {
return new File(userSettingsParentDir, userSettingsDirName);
}
/**
* Gets Java's temporary directory in absolute form
*
* @return Java's temporary directory in absolute form
* @throws FileNotFoundException if Java's temporary directory is not defined or it is not an
* absolute path
*/
private static File getJavaTmpDir() throws FileNotFoundException {
return getSystemPropertyFile("java.io.tmpdir", true);
}
/**
* Gets Java's user home directory in absolute form
*
* @return Java's user home directory in absolute form
* @throws FileNotFoundException if Java's user home directory is not defined or it is not an
* absolute path
*/
private static File getJavaUserHomeDir() throws FileNotFoundException {
return getSystemPropertyFile("user.home", true);
}
/**
* Gets the absolute form {@link File} value of the system property by the given name
*
* @param name The system property name
* @param required True if given system property is required to be set; otherwise, false
* @return The absolute form {@link File} value of the system property by the given name, or
* null if it isn't set
* @throws FileNotFoundException if the property value was not an absolute path, or if it is
* required and not set
*/
private static File getSystemPropertyFile(String name, boolean required)
throws FileNotFoundException {
String path = System.getProperty(name);
if (path == null || path.isBlank()) {
if (required) {
throw new FileNotFoundException(
"Required system property \"%s\" is not set!".formatted(name));
}
return null;
}
path = path.trim();
File file = new File(path);
if (!file.isAbsolute()) {
throw new FileNotFoundException(
"System property \"%s\" is not an absolute path: \"%s\"".formatted(name, path));
}
return file;
}
/**
* Gets the absolute form {@link File} value of the environment variable by the given name
*
* @param name The environment variable name
* @param required True if the given environment variable is required to be set; otherwise,
* false
* @return The absolute form {@link File} value of the environment variable by the given name,
* or null if it isn't set
* @throws FileNotFoundException if the property value was not an absolute path, or if it is
* required and not set
*/
private static File getEnvFile(String name, boolean required) throws FileNotFoundException {
String path = System.getenv(name);
if (path == null || path.isBlank()) {
if (required) {
throw new FileNotFoundException(
"Required environment variable \"%s\" is not set!".formatted(name));
}
return null;
}
path = path.trim();
File file = new File(path);
if (!file.isAbsolute()) {
throw new FileNotFoundException(
"Environment variable \"%s\" is not an absolute path: \"%s\"".formatted(name,
path));
}
return file;
}
/**
* Gets a directory name that can be used to create a user-specific sub-directory in
* {@code parentDir}. If the {@code parentDir} is contained within the user's home directory,
* the given {@code appName} can simply be used since it will live in a user-specific location.
* Otherwise, the user's name will get prepended to the {@code appName} so it does not collide
* with other users' directories in the shared directory space.
* @param parentDir The parent directory where we'd like to create a user-specific sub-directory
* @param appName The application name
* @return A directory name that can be used to create a user-specific sub-directory in
* {@code parentDir}.
* @throws FileNotFoundException if Java's user home directory is not defined or it is not an
* absolute path
*/
private static String getUserSpecificDirName(File parentDir, String appName)
throws FileNotFoundException {
String userSpecificDirName = appName;
if (!FileUtilities.isPathContainedWithin(getJavaUserHomeDir(), parentDir)) {
userSpecificDirName = SystemUtilities.getUserName() + "-" + appName;
}
return userSpecificDirName;
}
}

View file

@ -15,7 +15,7 @@
*/
package utility.application;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
@ -32,9 +32,9 @@ public class DummyApplicationLayout extends ApplicationLayout {
/**
* Constructs a new dummy application layout object.
* @param name the application name
* @throws FileNotFoundException if there was a problem getting a user directory.
* @throws IOException if there was a problem getting a user directory.
*/
public DummyApplicationLayout(String name) throws FileNotFoundException {
public DummyApplicationLayout(String name) throws IOException {
// Application properties
applicationProperties = new ApplicationProperties(name);
@ -48,7 +48,8 @@ public class DummyApplicationLayout extends ApplicationLayout {
applicationRootDirs.add(cwd);
// User directories
userTempDir = ApplicationUtilities.getDefaultUserTempDir(applicationProperties);
userTempDir =
ApplicationUtilities.getDefaultUserTempDir(applicationProperties.getApplicationName());
extensionInstallationDirs = Collections.emptyList();
}

View file

@ -0,0 +1,76 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package utility.application;
/**
* Class to support the "XDG Base Directory Specification"
* <p>
* Based off version 0.8
*
* @see <a href="https://specifications.freedesktop.org/basedir-spec/basedir-spec-0.8.html">basedir-spec-0.8.html</a>
*/
public class XdgUtils {
/**
* $XDG_DATA_HOME defines the base directory relative to which user-specific data files should
* be stored. If $XDG_DATA_HOME is either not set or empty, a default equal to
* $HOME/.local/share should be used.
*/
public static final String XDG_DATA_HOME = "XDG_DATA_HOME";
/**
* $XDG_CONFIG_HOME defines the base directory relative to which user-specific configuration
* files should be stored. If $XDG_CONFIG_HOME is either not set or empty, a default equal to
* $HOME/.config should be used.
*/
public static final String XDG_CONFIG_HOME = "XDG_CONFIG_HOME";
/**
* $XDG_STATE_HOME defines the base directory relative to which user-specific state files should
* be stored. If $XDG_STATE_HOME is either not set or empty, a default equal to
* $HOME/.local/state should be used.
*/
public static final String XDG_STATE_HOME = "XDG_STATE_HOME";
/**
* $XDG_DATA_DIRS defines the preference-ordered set of base directories to search for data
* files in addition to the $XDG_DATA_HOME base directory. The directories in $XDG_DATA_DIRS
* should be separated with a colon ':'.
*/
public static final String XDG_DATA_DIRS = "XDG_DATA_DIRS";
/**
* $XDG_CONFIG_DIRS defines the preference-ordered set of base directories to search for
* configuration files in addition to the $XDG_CONFIG_HOME base directory. The directories in
* $XDG_CONFIG_DIRS should be separated with a colon ':'.
*/
public static final String XDG_CONFIG_DIRS = "XDG_CONFIG_DIRS";
/**
* $XDG_CACHE_HOME defines the base directory relative to which user-specific non-essential
* data files should be stored. If $XDG_CACHE_HOME is either not set or empty, a default equal
* to $HOME/.cache should be used.
*/
public static final String XDG_CACHE_HOME = "XDG_CACHE_HOME";
/**
* $XDG_RUNTIME_DIR defines the base directory relative to which user-specific non-essential
* runtime files and other file objects (such as sockets, named pipes, ...) should be stored.
* The directory MUST be owned by the user, and he MUST be the only one having read and write
* access to it. Its Unix access mode MUST be 0700.
*/
public static final String XDG_RUNTIME_DIR = "XDG_RUNTIME_DIR";
}