XDG Basedir directories for Windows
Asked Answered
C

2

29

I have made a Racket library for convenience in accessing the XDG Basedir directories. As I want the library to be useable on Windows as well (for cross-platform programs), I have it use standard Windows directories as the defaults when the XDG environment variables are unset.

I am currently using the following:

  • $XDG_DATA_HOME = %LOCALAPPDATA%
  • $XDG_DATA_DIRS = %APPDATA%
  • $XDG_CONFIG_HOME = %LOCALAPPDATA%
  • $XDG_CONFIG_DIRS = %APPDATA%
  • $XDG_CACHE_HOME = %TEMP%
  • $XDG_RUNTIME_DIR = %TEMP%

My question is whether there are better defaults than those. I know that %TEMP% as the $XDG_RUNTIME_DIR is wrong, since it really should be on a ramfs like /tmp, but I don't know of any directory on Windows that is like that. In Windows it seems that there is no good option to have data and configuration directories separate, so I am using the same directories for them. My gut feeling is that %LOCALAPPDATA% is a better choice for the writable $XDG_*_HOME variables and having the "roaming" configuration in the $XDG_*_DIRS lists to be read and generally not overwritten. But would corporate Windows users that have a roaming configuration find that strange and disagree?

Cortezcortical answered 8/5, 2017 at 17:13 Comment(3)
Based on how this is accomplished in the Haskell equivalent library, I think what you've done is correct.Harbison
XDG_DATA_DIRS should not be in the user's profile, because its value is /usr/local/share/:/usr/share/ on POSIX systems by default. Those directories are for all normal users, not just the current one, so you should pick the AppData for all users, which is C:\ProgramData which seems to be %PROGRAMDATA% as well as %ALLUSERSPROFILE% these days. Long story short: $XDG_DATA_DIRS = %PROGRAMDATA%.Nonexistence
Moreover $XDG_CONFIG_HOME should be %APPDATA% so it gets shared across the devices in the same domain. $XDG_DATA_HOME should then use %LOCALAPPDATA as suggested. In the main specification these folders are not the same by default and I think this should also be the case in Windows environments.Nonexistence
R
37

I have implemented such functionality in libraries for the JVM and Rust. Here is what I learned:

Deal with application names, because your users can't or won't.

Provide APIs that compute the full path (including the application name!) to configuration, cache, etc. directories. Not doing this will result in code that is guaranteed to be wrong on at least 2 of 3 major platforms, as the conventions differ dramatically.

Consider an application written by company MegaCorp (web address MegaCorp.co.uk) named Foo App. Under Linux, the path segment naming the application should be fooapp/ (lower-cased, no spaces), on Windows it should be MegaCorp\Foo App\ (note the two folders), and on macOS it should be uk.co.MegaCorp.Foo-App (invalid characters replaced with -).

Have a clear definition of the purpose of each directory.

For instance, my library does not offer a runtimeDir on macOS or Windows, because XDG_RUNTIME_DIR is very different from e. g. %TEMP% on Windows.

This is a potential source of security issues, as the runtime dir on Linux guarantees that it can only be accessed by the owner, is deleted when the user logs off, etc.

Also, I only offer fontDir on Linux and macOS. Windows does have a font directory, but unlike on Linux and macOS, it is not user-writable.

On the other hand, I offer both dataDir (%APPDATA%) and dataLocalDir (%LOCALAPPDATA%) across all three platforms. On macOS and Linux those directories return the same path – this is an explicit design decision, considering how users would write code if one of those directories would not be available: Users would either forget to handle it, or just fallback to the other directory. With the chosen design this just works out of the box, without users needing to think about it.

Avoid issues before the user encounters them.

This is why the general cache, config etc. directory paths return %LOCALAPPDATA% and %APPDATA%, but application-specific cache and config directory paths return %LOCALAPPDATA%\Company\Application\cache and %APPDATA%\Company\Application\config.

Note the sub-directories! This is to guarantee a clean separation of an application's cache, config and data directory, regardless of what weird Windows settings a user might have.

Split use cases into separate modules.

There are three distinct modules in my library, with clearly defined, separated use cases:

BaseDirs, which queries the paths of user-invisible standard directories (cache, config, data, executable, runtime directories) and strongly suggests using ProjectDirs instead.

ProjectDirs, which computes the location of cache, config or data directories for your own application or project, which are derived from the standard directories.

UserDirs, which queries the paths of user-facing standard directories (Audio, Documents, Downloads, etc.).

While BaseDirs and UserDirs have fairly uninteresting constructors (new()), ProjectDirs provides this factory method:

ProjectDirs::from(qualifier: &str, organization: &str, application: &str)

This method ensures that users end up with correct, standards-compliant paths to their applications' cache, config, etc. directories – without them needing to be aware of all the intricacies of each individual platform.


One last suggestion: I would keep a library named "XDG Basedir Library" focused on Linux, and publish a library with a more general name, like "Standard Directory Library" that deals with Linux, Windows, etc. to avoid confusion.

Hope this was helpful!

Rapparee answered 11/4, 2018 at 20:4 Comment(1)
For those who want anyway to distinguish dataDir and dataLocalDir, see the following MSDN-blog link : web.archive.org/web/20130810020857/http://blogs.msdn.com/b/… This should give the equivalences (XDG_DATA_HOME ⇔ CSIDL_APPDATA) and (XDG_CACHE_HOME ⇔ CSIDL_LOCAL_APPDATA).Lunatic
E
-1

Keep in mind, that on Windows there is a savegame folder specified since Windows Vista.

It's called "%USERPROFILE%\Saved Games".

FOLDERID_SavedGames https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid?redirectedfrom=MSDN#constants

Epiphenomenalism answered 5/12, 2021 at 22:17 Comment(1)
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From ReviewGratify

© 2022 - 2024 — McMap. All rights reserved.