Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: os: Add SysConfigDir() Function #63858

Open
nnzv opened this issue Oct 31, 2023 · 5 comments
Open

proposal: os: Add SysConfigDir() Function #63858

nnzv opened this issue Oct 31, 2023 · 5 comments
Labels
Milestone

Comments

@nnzv
Copy link

nnzv commented Oct 31, 2023

Abstract

This proposal suggests adding a new function, SysConfigDir(), to the os package in the Go standard library. This function will help Go applications find the default directory for system-wide configuration data in a consistent way across different operating systems.

Background

Right now, os package has a function called UserConfigDir() that's good for getting the directory for user-specific configuration data. But there's no similar function for getting the directory for system-wide configuration data. Many Go apps need this to store configuration files that should be shared among all users on a system.

Proposal

I propose adding a new function, SysConfigDir(), to the os package. This function will return the directory path for system-wide configuration data. It will work the same way on all supported operating systems, just like UserConfigDir(). The way it works will be different depending on the operating system, following the conventions of that system.

Rationale

Here's why we need to add SysConfigDir():

  1. Consistency: Having a standard way to get the system-wide configuration directory makes things simpler for developers. It keeps things the same no matter which operating system you're on.

  2. Best Practices: It encourages developers to follow the best practices for managing configuration. It guides them to use the right directories and avoid problems like hardcoded paths or conflicts.

  3. User-Friendly: Just like UserConfigDir(), SysConfigDir() gives developers an easy way to find system-wide configuration directories, even on systems with different ways of doing things.

Compatibility

Adding SysConfigDir() won't mess up existing code. It's a new feature that we're adding to the os package, so it doesn't affect anything that's already there.

Implementation

Here's how we'll make SysConfigDir() work:

  1. Figure out which operating system you're using (like Windows, Unix, Plan9).
  2. Use the right way to find the system-wide configuration directory based on how that operating system does things.
  3. Give you the directory path, or return error if couldn't figure it out.
@nnzv nnzv added the Proposal label Oct 31, 2023
@gopherbot gopherbot added this to the Proposal milestone Oct 31, 2023
@apparentlymart
Copy link

This is an interesting idea!

Do you know if all of the operating systems that Go supports have a clear single answer to this question? It might help to extend the proposal by specifying exactly how it should behave on each operating system, or at least on a subset of operating systems you're familiar with.

os.UserConfigDir today has the limitation that it only returns what the base directory is and says nothing about what naming scheme is expected inside that directory. For example, on Windows I think it's conventional to make two levels of subdirectory like Vendor Name\Application Name and then create files under that, whereas on macOS it's conventional to use a reverse-DNS-shaped name, like org.golang or com.example.appname. I expect SysConfigDir as proposed has a similar limitation, but perhaps it doesn't really matter if it hasn't mattered for os.UserConfigDir. 🤷‍♂️

@mauri870
Copy link
Member

mauri870 commented Nov 1, 2023

The UserConfigDir proposal for for cross-reference #29960

I also like the idea, to me it sounds like just the right amount of indirection for a functionality like this, if we start adding too many constraints on how a user should be using it we might make it less useful overall.

Maybe smth along these lines would work for a SysConfigDir:

// SysConfigDir returns the default root directory to use for system-wide
// configuration data. Applications should use this directory for storing
// configuration files that are accessible system-wide.
//
// On Unix systems, it returns /etc.
// On Darwin, it returns /Library/Preferences.
// On Windows, it returns %ProgramData%.
// On Plan 9, it returns /lib.
//
// If the location cannot be determined, it will return an error.
func SysConfigDir() (string, error) {
	var dir string
	switch runtime.GOOS {
	case "windows":
		dir = os.Getenv("ProgramData")
		if dir == "" {
			return "", errors.New("%ProgramData% is not defined")
		}
	case "darwin":
		dir = "/Library/Preferences"
	case "plan9":
		dir = "/lib"
	default: // Unix
		dir = "/etc"
	}
	return dir, nil
}

@nnzv
Copy link
Author

nnzv commented Nov 1, 2023

@mauri870 I've contemplated using the ProgramData environment variable in Windows too, but its documentation advises against it: https://learn.microsoft.com/en-us/windows-hardware/customize/desktop/unattend/microsoft-windows-shell-setup-folderlocations-programdata

@nnzv
Copy link
Author

nnzv commented Nov 1, 2023

You can try using the CSIDL_COMMON_APPDATA constant in Windows with the golang.org/x/sys/windows package:

package main

import (
    "fmt"
    "golang.org/x/sys/windows"
)

func main() {
    path, err := windows.KnownFolderPath(windows.FOLDERID_ProgramData, 0)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(path)
}

But, using an external package here could make things more complicated.

@mauri870
Copy link
Member

mauri870 commented Nov 1, 2023

The description for FOLDERID_ProgramData sounds dead center to what we need, not sure about pulling x/sys/windows in os tho, I think we need a more lightweight solution.

Either way it seems like every platform has a folder dedicated to it, we just have to sort out how to get to it.

Let's wait to see what folks have to say about the proposal.

/cc @ianlancetaylor @robpike

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: Incoming
Development

No branches or pull requests

4 participants