github.com/haraldrudell/parl@v0.4.176/pos/homedir.go (about) 1 /* 2 © 2021–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/) 3 ISC License 4 */ 5 6 // Package parlos provides simplified functions for home-directory and hostname. 7 package pos 8 9 import ( 10 "errors" 11 "os" 12 "os/user" 13 "path" 14 "strconv" 15 16 "github.com/haraldrudell/parl/perrors" 17 ) 18 19 // UserHomeDir obtains the absolute path to the process owning user’s 20 // home directory 21 // - does not rely on environment 22 // - should never fail. if it does, panic is thrown 23 func UserHomeDir() (homeDir string) { 24 25 // try getting home directory from account configuration 26 homeDir = getProcessOwnerHomeDir() 27 28 // if that fails, try shell environment 29 if homeDir == "" { 30 var err error 31 homeDir, err = os.UserHomeDir() // use $HOME environment variable 32 if err != nil { 33 panic(perrors.Errorf("os.UserHomeDir: '%w'", err)) 34 } 35 if homeDir == "" { 36 panic(perrors.New("failed to obtain home directory")) 37 } 38 } 39 return 40 } 41 42 // UserHome obtains the absolute path to the process owning user’s 43 // home directory 44 // - does not rely on environment 45 func UserHome() (homeDir string, err error) { 46 if homeDir = getProcessOwnerHomeDir(); homeDir == "" { 47 err = perrors.NewPF("failed to obtain user ID or userData") 48 } 49 return 50 } 51 52 // HomeDir creates levels of directories in users’s home. 53 // if directories do not exist, they are created with permissions u=rwx. 54 // This should never fail, when it does, panic is thrown 55 func HomeDir(relPaths string) (dir string) { 56 homeDir := UserHomeDir() 57 dir = path.Join(homeDir, relPaths) 58 if err := os.MkdirAll(dir, 0700); err != nil { 59 if !errors.Is(err, os.ErrExist) { 60 panic(perrors.Errorf("os.MkdirAll: %w", err)) 61 } 62 } 63 return 64 } 65 66 // getProcessOwnerHomeDir retrives a user’s home directory 67 // based on account configuration. 68 // This is required for Linux system services that do not 69 // have an environment 70 // Best effort: errors are ignored 71 func getProcessOwnerHomeDir() (homeDir string) { 72 73 // get process user ID 74 userID := os.Geteuid() 75 if userID == -1 { // on Windows, -1 is returned 76 return // FAIL: user ID not found 77 } 78 79 // lookup the user ID 80 userdata, err := user.LookupId(strconv.Itoa(userID)) 81 if err != nil { 82 return // FAIL: user data not found 83 } 84 85 return userdata.HomeDir // path to the user's home directory 86 }