github.com/mit-dci/lit@v0.0.0-20221102210550-8c3d3b49f2ce/btcutil/appdata.go (about) 1 // Copyright (c) 2013-2014 The btcsuite developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 5 package btcutil 6 7 import ( 8 "os" 9 "os/user" 10 "path/filepath" 11 "runtime" 12 "strings" 13 "unicode" 14 ) 15 16 // appDataDir returns an operating system specific directory to be used for 17 // storing application data for an application. See AppDataDir for more 18 // details. This unexported version takes an operating system argument 19 // primarily to enable the testing package to properly test the function by 20 // forcing an operating system that is not the currently one. 21 func appDataDir(goos, appName string, roaming bool) string { 22 if appName == "" || appName == "." { 23 return "." 24 } 25 26 // The caller really shouldn't prepend the appName with a period, but 27 // if they do, handle it gracefully by stripping it. 28 if strings.HasPrefix(appName, ".") { 29 appName = appName[1:] 30 } 31 appNameUpper := string(unicode.ToUpper(rune(appName[0]))) + appName[1:] 32 appNameLower := string(unicode.ToLower(rune(appName[0]))) + appName[1:] 33 34 // Get the OS specific home directory via the Go standard lib. 35 var homeDir string 36 usr, err := user.Current() 37 if err == nil { 38 homeDir = usr.HomeDir 39 } 40 41 // Fall back to standard HOME environment variable that works 42 // for most POSIX OSes if the directory from the Go standard 43 // lib failed. 44 if err != nil || homeDir == "" { 45 homeDir = os.Getenv("HOME") 46 } 47 48 switch goos { 49 // Attempt to use the LOCALAPPDATA or APPDATA environment variable on 50 // Windows. 51 case "windows": 52 // Windows XP and before didn't have a LOCALAPPDATA, so fallback 53 // to regular APPDATA when LOCALAPPDATA is not set. 54 appData := os.Getenv("LOCALAPPDATA") 55 if roaming || appData == "" { 56 appData = os.Getenv("APPDATA") 57 } 58 59 if appData != "" { 60 return filepath.Join(appData, appNameUpper) 61 } 62 63 case "darwin": 64 if homeDir != "" { 65 return filepath.Join(homeDir, "Library", 66 "Application Support", appNameUpper) 67 } 68 69 case "plan9": 70 if homeDir != "" { 71 return filepath.Join(homeDir, appNameLower) 72 } 73 74 default: 75 if homeDir != "" { 76 return filepath.Join(homeDir, "."+appNameLower) 77 } 78 } 79 80 // Fall back to the current directory if all else fails. 81 return "." 82 } 83 84 // AppDataDir returns an operating system specific directory to be used for 85 // storing application data for an application. 86 // 87 // The appName parameter is the name of the application the data directory is 88 // being requested for. This function will prepend a period to the appName for 89 // POSIX style operating systems since that is standard practice. An empty 90 // appName or one with a single dot is treated as requesting the current 91 // directory so only "." will be returned. Further, the first character 92 // of appName will be made lowercase for POSIX style operating systems and 93 // uppercase for Mac and Windows since that is standard practice. 94 // 95 // The roaming parameter only applies to Windows where it specifies the roaming 96 // application data profile (%APPDATA%) should be used instead of the local one 97 // (%LOCALAPPDATA%) that is used by default. 98 // 99 // Example results: 100 // dir := AppDataDir("myapp", false) 101 // POSIX (Linux/BSD): ~/.myapp 102 // Mac OS: $HOME/Library/Application Support/Myapp 103 // Windows: %LOCALAPPDATA%\Myapp 104 // Plan 9: $home/myapp 105 func AppDataDir(appName string, roaming bool) string { 106 return appDataDir(runtime.GOOS, appName, roaming) 107 }