Menu

#902 [Linux] Respect XDG Base Directory Specification

closed
nobody
None
5
2022-10-17
2022-04-26
arturb
No

Please, for GNU/Linux systems consider utilising Freedesktop.org's XDG Base Directory Specification.

The specification standardizes a set of directories to be used on Linux systems to store user data.
The key variables are $XDG_CONFIG_HOME (for program config files), $XDG_DATA_HOME (for user data files) and $XDG_STATE_HOME (for state data files).

In particular,
1) the $XDG_CONFIG_HOME env. variable (default $HOME/.config) could be used as the base for the 'pwsafe' folder (not hidden; without the preceding . dot).
2) State variables, such as 'pwsafe.lck' could go to $XDG_STATE_HOME ($HOME/.local/state) or $XDG_CONFIG_HOME/pwsafe (if $XDG_STATE_HOME is not set).
3) There's also an $XDG_DATA_HOME ($HOME/.local/share) that could store the safe files.

With the current implementation, one can export PWS_PREFSDIR="${XDG_CONFIG_HOME}/pwsafe" to imitate the proposed behavious but that doesn't stop 'createuserprefsdir()' from creating the "${HOME}/.pwsafe" directory to store the 'pwsafe.lck' file.

The simplest and least work-intensive solution would be to allow 'createuserprefsdir()' to pick $XDG_CONFIG_HOME/pwsafe (if set) instead of $HOME/.pwsafe. My understanding is that all other functions that use 'createuserprefsdir()' through 'pws_os::getuserprefsdir()' would follow suit.

A further extension could involve aforementioned state and data files. Because pwsafe is unlikely to produce huge amounts of cache, state and data files, I would consider this of low, completionist importance.

XDG Specs in brief are available here: https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html

Discussion

  • Rony Shapiro

    Rony Shapiro - 2022-04-29

    Nice idea.

    Question is, how to treat existing users? E.g., if someone already has a ~/.pwsafe directory, do we silently migrate it to $XDG_CONFIG_HOME/pwsafe?

     
    • arturb

      arturb - 2022-04-30

      Emacs can serve as an example of how to deal with it:

      1) historically, the main Emacs config file (aka init file) was set to be one of the following in order: ~/.emacs.el, ~/.emacs, or ~/.emacs.d/init.el and this preference remains (the first file found is the one used). Important to note that the first two options are relics and aren't of interest to us.
      2) if no file is found in those places, XDG_CONFIG_HOME is checked (default ~/.config/) for the 'emacs' subdirectory/subfolder and it is used to read or store the config file.
      3) when no init file is found in either 1) or 2) and XDG_CONFIG_HOME is set, the program chooses to use $XDG_CONFIG_HOME/emacs/ directory.
      4) when no init file is found in either 1) or 2) and XDG_CONFIG_HOME is NOT set, the program chooses to use ~/.emacs.d/ directory.

      So very fittingly for our case, only two options are really ever considered - the hidden dir in ~/.emacs.d/ (~/.pwsafe/) or the XDG dir in $XDG_CONFIG_HOME/emacs/ ($XDG_CONFIG_HOME/pwsafe/).

      Adapting this preference structure to Password Safe:
      1) Check if ~/.pwsafe/ directory exists
      : IF yes -> use it
      : IF not -> check if $XDG_CONFIG_HOME is set
      2) Check if $XDG_CONFIG_HOME is set
      : IF yes -> use it
      optional
      : IF not -> check if $HOME/.config/ directory exists
      3) Check if $HOME/.config/ directory exists
      : IF yes -> use it
      /optional
      : IF not -> use ~/.pwsafe/

      The step between 2) and 3) of checking if $HOME/.config with the $XDG_CONFIG_HOME unset is a matter of interpretation.

      • Emacs chooses to skip this step, seemingly assuming that if variable is not set (even if the directory itself exists), then it is not to be used (this is inaccurately described in the Emacs manual chapter I link as a source below).
      • I think Music Player Daemon on the other hand checks for $HOME/.config -- the "optional" chunk above.
      • The XDG specification says: $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.

      Someone could interpret MPD to be more in line with this and Emacs less. I remain impartial, because the ultimate choice in both cases is up to the user's placement of their config (that is, steps 1 and 2 are decisive).

      Hopefully it makes it slightly clearer. I tested the Emacs behaviour I describe above. The source with a caveat below.

      Source: https://www.gnu.org/software/emacs/manual/html_node/emacs/Find-Init.html
      Imprtantly it says that "if neither the XDG location nor ~/.emacs.d exist, then Emacs will create ~/.emacs.d (and therefore use it during subsequent invocations)", which isn't precise -- because what is really decisive in case of Emacs is whether the variable $XDG_CONFIG_HOME is set or not, i.e. the directory that XDG specs expect as the default ($HOME/.config) may indeed exist with the variable being unset, in which case the ~/.emacs.d/ is chosen instead of the implied XDG location.

       

      Last edit: arturb 2022-04-30
      • arturb

        arturb - 2022-04-30

        Actually, I started testing a bit more and it's slightly more complicated and interestingly a bit different from what the GNU manual says.
        That said, I think it's best to keep things simple.
        So basically if ~/.pwsafe exists => user wants to use it
        If it doesn't, but XDG_CONFIG_HOME is set => user wants to use it (XDG).
        If it isn't set => either use ~/.pwsafe or check for either ($HOME/.config) or ($HOME/.config/pwsafe/pwsafe.cfg) and use that instead.

        I would assume that it's better to look for the config file in the last step because it is unlikely that someone would have an empty ~/.config/pwsafe/ dir.

        Something like that, considering my further testing:
        https://de.catbox.moe/esmbfb.png

         
        • Rony Shapiro

          Rony Shapiro - 2022-05-03

          Sounds (and looks) reasonable. Now I just need to find time to implement this...
          Any chance of a pull request?

           
          • arturb

            arturb - 2022-05-04

            Hey.
            I am not exactly a c++ programmer, but I can look into it and try to hack something so that at least you can have an easier job with it.
            Moreover, I decided to go through Emacs startup.el elisp code to see what exactly it is they are doing, and I expect to propose a coherent config dir decision procedure after I'm done with the analysis. It won't take long, but it's not a moment's endeavour either.
            That is to say, it's best if you don't work on this until you hear back from me.

             

            Last edit: arturb 2022-05-04
  • arturb

    arturb - 2022-06-12

    Hey ,

    Excuse the long silence - I am in the middle of a labourous period.

    I have read a bit about this topic and inspected some code here and there and concluded that it would be sensible to allow the following process for choosing the pwsafe config dir.

    Assumptions:
    1) Preference: $XDG_CONFIG_HOME -> $HOME/.config -> $HOME/.pwsafe.
    This is in line with the XDG spec in the sense that in case the XDG var is unset, the config dir should default to $HOME/.config - how much that is warranted is subject to a developer's interpretation, but I think it's sensible to follow it.
    2) This implies that $HOME/.pwsafe should never be chosen as the config dir without it being already present in the filesystem.

    The process for establishing the correct config dir could look as follows:
    1) Choose $HOME/.pwsafe if it exists and is viable
    2) Else: choose $XDG_CONFIG_HOME/pwsafe if $XDG_CONFIG_HOME var is set and the target dir is viable (which here means that it exists and is viable or doesn't exist and can be created)
    3) Else: choose $HOME/.config/pwsafe

    I attach a pseudo-implementation that needs proper implementation, but hopefully it can take some of the workload off of you. In the least, it may serve as a starting block or as a blueprint for a worthy implementation.

    The attachment is in the form of code snippet as diff would make little sense here - the code must leave much to be desired and I only add one new function (isviabledir) and modify one existing function (createuserprefsdir). Moreover, I tried to stay relatively close procedurally to the original code. Comments should clarify my thinking. If you digest it and find a more elegant way to solve it, all the better.

    ~Artur

     

    Last edit: arturb 2022-06-12
  • Rony Shapiro

    Rony Shapiro - 2022-06-18
    • status: open --> pending
     
  • Rony Shapiro

    Rony Shapiro - 2022-06-18

    Implemented in commit 066d6f327
    Will be in next release.

     
  • arturb

    arturb - 2022-07-16

    Thank you.

     
  • Rony Shapiro

    Rony Shapiro - 2022-10-17
    • Status: pending --> closed
     

Log in to post a comment.

MongoDB Logo MongoDB