Coder Social home page Coder Social logo

adrg / xdg Goto Github PK

View Code? Open in Web Editor NEW
589.0 7.0 30.0 199 KB

Go implementation of the XDG Base Directory Specification and XDG user directories

Home Page: https://pkg.go.dev/github.com/adrg/xdg

License: MIT License

Go 100.00%
xdg go golang specification library golang-library golang-package xdg-basedir xdg-user-dirs cross-platform

xdg's Introduction

xdg logo

Go implementation of the XDG Base Directory Specification and XDG user directories.

Build status Code coverage pkg.go.dev documentation MIT license
Go report card Awesome Go GitHub contributors GitHub open issues Buy me a coffee

Provides an implementation of the XDG Base Directory Specification. The specification defines a set of standard paths for storing application files, including data and configuration files. For portability and flexibility reasons, applications should use the XDG defined locations instead of hardcoding paths. The package also includes the locations of well known user directories, as well as other common directories such as fonts and applications.

The current implementation supports most flavors of Unix, Windows, macOS and Plan 9.
On Windows, where XDG environment variables are not usually set, the package uses Known Folders as defaults. Therefore, appropriate locations are used for common folders which may have been redirected.

See usage examples below. Full documentation can be found at https://pkg.go.dev/github.com/adrg/xdg.

Installation

go get github.com/adrg/xdg

Default locations

The package defines sensible defaults for XDG variables which are empty or not present in the environment.

  • On Unix-like operating systems, XDG environment variables are typically defined. Appropriate default locations are used for the environment variables which are not set.
  • On Windows, XDG environment variables are usually not set. If that is the case, the package relies on the appropriate Known Folders. Sensible fallback locations are used for the folders which are not set.

XDG Base Directory

Unix-like operating systems

Unix

macOS

Plan 9

XDG_DATA_HOME ~/.local/share ~/Library/Application Support $home/lib
XDG_DATA_DIRS /usr/local/share
/usr/share
/Library/Application Support /lib
XDG_CONFIG_HOME ~/.config ~/Library/Application Support $home/lib
XDG_CONFIG_DIRS /etc/xdg ~/Library/Preferences
/Library/Application Support
/Library/Preferences
/lib
XDG_STATE_HOME ~/.local/state ~/Library/Application Support $home/lib/state
XDG_CACHE_HOME ~/.cache ~/Library/Caches $home/lib/cache
XDG_RUNTIME_DIR /run/user/UID ~/Library/Application Support /tmp
Microsoft Windows

Known Folder(s)

Fallback(s)

XDG_DATA_HOME LocalAppData %LOCALAPPDATA%
XDG_DATA_DIRS RoamingAppData
ProgramData
%APPADATA%
%ProgramData%
XDG_CONFIG_HOME LocalAppData %LOCALAPPDATA%
XDG_CONFIG_DIRS ProgramData
RoamingAppData
%ProgramData%
%APPDATA%
XDG_STATE_HOME LocalAppData %LOCALAPPDATA%
XDG_CACHE_HOME LocalAppData\cache %LOCALAPPDATA%\cache
XDG_RUNTIME_DIR LocalAppData %LOCALAPPDATA%

XDG user directories

Unix-like operating systems

Unix

macOS

Plan 9

XDG_DESKTOP_DIR ~/Desktop ~/Desktop $home/desktop
XDG_DOWNLOAD_DIR ~/Downloads ~/Downloads $home/downloads
XDG_DOCUMENTS_DIR ~/Documents ~/Documents $home/documents
XDG_MUSIC_DIR ~/Music ~/Music $home/music
XDG_PICTURES_DIR ~/Pictures ~/Pictures $home/pictures
XDG_VIDEOS_DIR ~/Videos ~/Movies $home/videos
XDG_TEMPLATES_DIR ~/Templates ~/Templates $home/templates
XDG_PUBLICSHARE_DIR ~/Public ~/Public $home/public
Microsoft Windows

Known Folder(s)

Fallback(s)

XDG_DESKTOP_DIR Desktop %USERPROFILE%\Desktop
XDG_DOWNLOAD_DIR Downloads %USERPROFILE%\Downloads
XDG_DOCUMENTS_DIR Documents %USERPROFILE%\Documents
XDG_MUSIC_DIR Music %USERPROFILE%\Music
XDG_PICTURES_DIR Pictures %USERPROFILE%\Pictures
XDG_VIDEOS_DIR Videos %USERPROFILE%\Videos
XDG_TEMPLATES_DIR Templates %APPDATA%\Microsoft\Windows\Templates
XDG_PUBLICSHARE_DIR Public %PUBLIC%

Other directories

Unix-like operating systems

Unix

macOS

Plan 9

Home $HOME $HOME $home
Applications $XDG_DATA_HOME/applications
~/.local/share/applications
/usr/local/share/applications
/usr/share/applications
$XDG_DATA_DIRS/applications
/Applications $home/bin
/bin
Fonts $XDG_DATA_HOME/fonts
~/.fonts
~/.local/share/fonts
/usr/local/share/fonts
/usr/share/fonts
$XDG_DATA_DIRS/fonts
~/Library/Fonts
/Library/Fonts
/System/Library/Fonts
/Network/Library/Fonts
$home/lib/font
/lib/font
Microsoft Windows

Known Folder(s)

Fallback(s)

Home Profile %USERPROFILE%
Applications Programs
CommonPrograms
%APPDATA%\Microsoft\Windows\Start Menu\Programs
%ProgramData%\Microsoft\Windows\Start Menu\Programs
Fonts Fonts
-
%SystemRoot%\Fonts
%LOCALAPPDATA%\Microsoft\Windows\Fonts

Usage

XDG Base Directory

package main

import (
	"log"

	"github.com/adrg/xdg"
)

func main() {
	// XDG Base Directory paths.
	log.Println("Home data directory:", xdg.DataHome)
	log.Println("Data directories:", xdg.DataDirs)
	log.Println("Home config directory:", xdg.ConfigHome)
	log.Println("Config directories:", xdg.ConfigDirs)
	log.Println("Home state directory:", xdg.StateHome)
	log.Println("Cache directory:", xdg.CacheHome)
	log.Println("Runtime directory:", xdg.RuntimeDir)

	// Other common directories.
	log.Println("Home directory:", xdg.Home)
	log.Println("Application directories:", xdg.ApplicationDirs)
	log.Println("Font directories:", xdg.FontDirs)

	// Obtain a suitable location for application config files.
	// ConfigFile takes one parameter which must contain the name of the file,
	// but it can also contain a set of parent directories. If the directories
	// don't exist, they will be created relative to the base config directory.
	configFilePath, err := xdg.ConfigFile("appname/config.yaml")
	if err != nil {
		log.Fatal(err)
	}
	log.Println("Save the config file at:", configFilePath)

	// For other types of application files use:
	// xdg.DataFile()
	// xdg.StateFile()
	// xdg.CacheFile()
	// xdg.RuntimeFile()

	// Finding application config files.
	// SearchConfigFile takes one parameter which must contain the name of
	// the file, but it can also contain a set of parent directories relative
	// to the config search paths (xdg.ConfigHome and xdg.ConfigDirs).
	configFilePath, err = xdg.SearchConfigFile("appname/config.yaml")
	if err != nil {
		log.Fatal(err)
	}
	log.Println("Config file was found at:", configFilePath)

	// For other types of application files use:
	// xdg.SearchDataFile()
	// xdg.SearchStateFile()
	// xdg.SearchCacheFile()
	// xdg.SearchRuntimeFile()
}

XDG user directories

package main

import (
	"log"

	"github.com/adrg/xdg"
)

func main() {
	// XDG user directories.
	log.Println("Desktop directory:", xdg.UserDirs.Desktop)
	log.Println("Download directory:", xdg.UserDirs.Download)
	log.Println("Documents directory:", xdg.UserDirs.Documents)
	log.Println("Music directory:", xdg.UserDirs.Music)
	log.Println("Pictures directory:", xdg.UserDirs.Pictures)
	log.Println("Videos directory:", xdg.UserDirs.Videos)
	log.Println("Templates directory:", xdg.UserDirs.Templates)
	log.Println("Public directory:", xdg.UserDirs.PublicShare)
}

Stargazers over time

Stargazers over time

Contributing

Contributions in the form of pull requests, issues or just general feedback, are always welcome.
See CONTRIBUTING.MD.

Contributors: adrg, wichert, bouncepaw, gabriel-vasile, KalleDK, nvkv, djdv, rrjjvv, GreyXor, Rican7.

References

For more information see:

License

Copyright (c) 2014 Adrian-George Bostan.

This project is licensed under the MIT license. See LICENSE for more details.

xdg's People

Contributors

adrg avatar bouncepaw avatar dependabot[bot] avatar gabriel-vasile avatar greyxor avatar kalledk avatar rican7 avatar wichert avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

xdg's Issues

macOS: do not use ~/Library/Preferences

~/Library/Preferences is reserved for .plist files - one should never create application-specific subdirectories in there, but each application is supposed to just have ONE .plist file in there, named using its bundle ID.

This differs from XDG_CONFIG_HOME as that one expects per-app directories.

See also:

Instead, XDG_CONFIG_HOME should be ~/Library/Application Support, too.

Provide CacheDir function

It would be great if you could provide a function func CacheDir(appname string) (string, error) that (in contrast to CacheFile) only creates the cache dir for appname.

What do you think?

createPath might be doing to much

We should check if that path exists, as we shouldn't create this "part" of the folder imho.

As in all the folders in the name variable is okay to create, but the folders in the paths could be system folders.

A "constructed" case would be a root user running a program with this, might end up creating /usr/local/share, even if /usr/share is the only path there.

I understand that this would create a problem with paths like ~/.local/state as that wouldn't be created, and I could see a reason for that to be created.

A solution to this might be a few functions to create the XDG_BASE places, and let createPath only handle the relative part.

func main() {
  // For homes that we need to create files in
  xdg.CreateCacheHome()
  xdg.CreateConfigHome()
}

xdg/utils.go

Lines 63 to 71 in aad56ae

func createPath(name string, paths []string) (string, error) {
var searchedPaths []string
for _, p := range paths {
path := filepath.Join(p, name)
dir := filepath.Dir(path)
if exists(dir) {
return path, nil
}

Support more XDG directories

Please also support those directories:

  • USER_DIRECTORY_DESKTOP
  • USER_DIRECTORY_DOCUMENTS
  • USER_DIRECTORY_DOWNLOAD
  • USER_DIRECTORY_MUSIC
  • USER_DIRECTORY_PICTURES
  • USER_DIRECTORY_PUBLIC_SHARE
  • USER_DIRECTORY_TEMPLATES
  • USER_DIRECTORY_VIDEOS
  • USER_N_DIRECTORIES

`Create` may set up wrong permissions for some directories in the path

Hi, I have noticed that it might not be correct to create all directories with 0o700 permissions:

if err := os.MkdirAll(dir, os.ModeDir|0o700); err == nil {
return p, nil
}

To be specific, the permission of XDG_RUNTIME_DIR is supposed to be 700 but its parent, usually /run/user/, is not. And if above code runs in a part of system daemon and has root privileges, some services that run as normal user may crash. This issue occurs when the system doesn't previously set up /run/user/, hence it's created alongside app/.

Should not change permissions without consent

xdg/base_dirs.go

Lines 52 to 55 in aad56ae

// The runtime directory must be owned by the user.
if err = chown(bd.runtime, os.Getuid(), os.Getgid()); err != nil {
return "", err
}

I think this should give an error with wrong permissions, and not try to set permissions on it own. This path could already contain files from other programs, that "by error" rely on these permissions, and by changing them maybe break them.

Parse ~/.config/user-dirs.dirs file

I am testing this library using fedora and arch Linux and it seems like none of the distributions are setting the env vars for XDG User Directories.

[a@localhost-live test]$ cat /home/a/.config/user-dirs.dirs
# This file is written by xdg-user-dirs-update
# If you want to change or add directories, just edit the line you're
# interested in. All local changes will be retained on the next run.
# Format is XDG_xxx_DIR="$HOME/yyy", where yyy is a shell-escaped
# homedir-relative path, or XDG_xxx_DIR="/yyy", where /yyy is an
# absolute path. No other format is supported.
# 
XDG_DESKTOP_DIR="$HOME/Pulpit"
XDG_DOWNLOAD_DIR="$HOME/Pobrane"
XDG_TEMPLATES_DIR="$HOME/Szablony"
XDG_PUBLICSHARE_DIR="$HOME/Publiczny"
XDG_DOCUMENTS_DIR="$HOME/Dokumenty"
XDG_MUSIC_DIR="$HOME/Muzyka"
XDG_PICTURES_DIR="$HOME/Obrazy"
XDG_VIDEOS_DIR="$HOME/Wideo"
[a@localhost-live test]$ ./main 
2022/02/04 18:14:32 Desktop directory: /home/a/Desktop
2022/02/04 18:14:32 Download directory: /home/a/Downloads
2022/02/04 18:14:32 Documents directory: /home/a/Documents
2022/02/04 18:14:32 Music directory: /home/a/Music
2022/02/04 18:14:32 Pictures directory: /home/a/Pictures
2022/02/04 18:14:32 Videos directory: /home/a/Videos
2022/02/04 18:14:32 Templates directory: /home/a/Templates
2022/02/04 18:14:32 Public directory: /home/a/Public

Firefox for example reads the ~/.config/user-dirs.dirs directly.

[a@localhost-live test]$ cat firefox-strace | grep .config/user-dirs
openat(AT_FDCWD, "/home/a/.config/user-dirs.dirs", O_RDONLY) = 53

Dupplicate `homeDir`'s implementation

Function homeDir from all paths_{windows | darwin | unix | plan9}.go does exactly the same thing as os.UserHomeDir. I believe it can be moved to a commons.go file to reduce the amount of os specific code and rely more on built-in functionality.

Plan 9 support

When building my project Mycorrhiza, a user complained that it doesn't build on Plan 9 operating system. From the error messages I understood that the problem is that initBaseDirs and initUserDirs is not implemented for Plan 9, I'd love to see that implemented.

Remove might be a bit to harsh

xdg/base_dirs.go

Lines 57 to 60 in aad56ae

// For security reasons, the runtime directory cannot be a symlink.
if err = os.Remove(bd.runtime); err != nil {
return "", err
}

Shouldn't this just give an error? It feels like deleting a file without "consent" is a bit harsh.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.