Skip to content

Use XDG basedir spec on Linux #76

@mochaaP

Description

@mochaaP

https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html

Why: we already use the equivalents on other platforms (Application Support, AppData, etc.) on other platforms. This behavior could be aligned on Linux. seealso: https://xdgbasedirectoryspecification.com/

Code below is attached to explain the new logic and I will make a PR once we finalize the behavior details. See the comments for further discussion.

Details

diff --git a/java/zylib/src/main/java/com/google/security/zynamics/zylib/system/SystemHelpers.java b/java/zylib/src/main/java/com/google/security/zynamics/zylib/system/SystemHelpers.java
index aa8754b9..eddf021c 100644
--- a/java/zylib/src/main/java/com/google/security/zynamics/zylib/system/SystemHelpers.java
+++ b/java/zylib/src/main/java/com/google/security/zynamics/zylib/system/SystemHelpers.java
@@ -38,7 +38,7 @@ public final class SystemHelpers {
       // Win32 function.
       result = System.getenv("ProgramData");
     } else if (isRunningLinux()) {
-      result = "/etc/opt";
+      result = "/etc/xdg";
     } else if (isRunningMacOSX()) {
       result = "/Library/Application Support";
     } else {
@@ -76,9 +76,15 @@ public final class SystemHelpers {
       // function.
       result = System.getenv("APPDATA");
     } else {
-      result = System.getProperty("user.home");
-      if (isRunningMacOSX()) {
-        result += "/Library/Application Support";
+      result = System.getenv("XDG_DATA_HOME");
+      if (result == null || !result.startsWith("/")) {
+        result = System.getProperty("user.home");
+        if (isRunningLinux()) {
+            result += "/.local/share";
+        }
+        if (isRunningMacOSX()) { // Since there isn't a standard way to get this path on macOS (at least I'm not aware of), should we also put this codepath in here?
+          result += "/Library/Application Support";
+        }
       }
     }
     return FileUtils.ensureTrailingSlash(result);
@@ -93,7 +99,7 @@ public final class SystemHelpers {
    */
   public static String getApplicationDataDirectory(final String product) {
     return getApplicationDataDirectory()
-        + (isRunningLinux() ? "." + product.toLowerCase() : product)
+        + (isRunningLinux() ? product.toLowerCase() : product)
         + File.separator;
   }
 
diff --git a/util/process.cc b/util/process.cc
index 6fdeb42..bc46b04 100644
--- a/util/process.cc
+++ b/util/process.cc
@@ -241,15 +241,25 @@ absl::StatusOr<std::string> GetOrCreateAppDataDirectory(
     absl::string_view product_name) {
   std::string path;
 #ifndef _WIN32
-  const char* home_dir = getenv("HOME");
-  if (!home_dir) {
-    return absl::NotFoundError("Home directory not set");
+  std::string data_home;
+  const char* data_home_env = getenv("XDG_DATA_HOME");
+  if (data_home_env && data_home_env[0] == '/') {
+    data_home = data_home_env;
+  } else {
+    const char* home_dir = getenv("HOME");
+    if (!home_dir) {
+      return absl::NotFoundError("Home directory not set");
+    }
+#ifdef __APPLE__
+    data_home = JoinPath(home_dir, "Library", "Application Support");
+#else
+    data_home = JoinPath(home_dir, ".local", "share");
+#endif  // __APPLE__
   }
 #ifdef __APPLE__
-  path = JoinPath(home_dir, "Library", "Application Support", product_name);
+  path = JoinPath(data_home, product_name);
 #else
-  path = JoinPath(home_dir,
-                  absl::StrCat(".", absl::AsciiStrToLower(product_name)));
+  path = JoinPath(data_home, absl::AsciiStrToLower(product_name));
 #endif  // __APPLE__
 #else
   char buffer[MAX_PATH] = {0};
@@ -270,7 +280,7 @@ absl::StatusOr<std::string> GetCommonAppDataDirectory(
 #ifdef __APPLE__
   path = JoinPath("/Library", "Application Support", product_name);
 #else
-  path = JoinPath("/etc/opt/", absl::AsciiStrToLower(product_name));
+  path = JoinPath("/etc", "xdg", absl::AsciiStrToLower(product_name));
 #endif  // __APPLE__
 #else
   char buffer[MAX_PATH] = {0};

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions