taldir

Directory service to resolve wallet mailboxes by messenger addresses
Log | Files | Refs | Submodules | README | LICENSE

path.go (2331B)


      1 package pqutil
      2 
      3 import (
      4 	"errors"
      5 	"fmt"
      6 	"io"
      7 	"os"
      8 	"os/user"
      9 	"path/filepath"
     10 	"runtime"
     11 	"syscall"
     12 )
     13 
     14 // Home gets the PostgreSQL configuration dir in the user's home directory:
     15 // %APPDATA%/postgresql on Windows, and $HOME/.postgresql/postgresql.crt
     16 // everywhere else.
     17 //
     18 // Returns an empy string if no home directory was found.
     19 //
     20 // Matches pqGetHomeDirectory() from PostgreSQL.
     21 // https://github.com/postgres/postgres/blob/2b117bb/src/interfaces/libpq/fe-connect.c#L8214
     22 func Home(subdir bool) string {
     23 	if runtime.GOOS == "windows" {
     24 		// pq uses SHGetFolderPath(), which is deprecated but x/sys/windows has
     25 		// KnownFolderPath(). We don't really want to pull that in though, so
     26 		// use APPDATA env. This is also what PostgreSQL uses in some other
     27 		// codepaths (get_home_path() for example).
     28 		ad := os.Getenv("APPDATA")
     29 		if ad == "" {
     30 			return ""
     31 		}
     32 		return filepath.Join(ad, "postgresql")
     33 	}
     34 
     35 	home, _ := os.UserHomeDir()
     36 	if home == "" {
     37 		u, err := user.Current()
     38 		if err != nil {
     39 			return ""
     40 		}
     41 		home = u.HomeDir
     42 	}
     43 	// libpq reads some files from ~/ and some from ~/.postgresql – on Windows
     44 	// it always uses %APPDATA%/postgresql.
     45 	if subdir {
     46 		home = filepath.Join(home, ".postgresql")
     47 	}
     48 	return home
     49 }
     50 
     51 // ErrNotExists reports if err is a "path doesn't exist" type error.
     52 //
     53 // fs.ErrNotExist is not enough, as "/dev/null/somefile" will return ENOTDIR
     54 // instead of ENOENT.
     55 func ErrNotExists(err error) bool {
     56 	perr := new(os.PathError)
     57 	if errors.As(err, &perr) && (perr.Err == syscall.ENOENT || perr.Err == syscall.ENOTDIR) {
     58 		return true
     59 	}
     60 	return false
     61 }
     62 
     63 var WarnFD io.Writer = os.Stderr
     64 
     65 // Pgpass gets the filepath to the pgpass file to use, returning "" if a pgpass
     66 // file shouldn't be used.
     67 func Pgpass(passfile string) string {
     68 	// Get passfile from the options.
     69 	if passfile == "" {
     70 		home := Home(false)
     71 		if home == "" {
     72 			return ""
     73 		}
     74 		passfile = filepath.Join(home, ".pgpass")
     75 	}
     76 
     77 	// On Win32, the directory is protected, so we don't have to check the file.
     78 	if runtime.GOOS != "windows" {
     79 		fi, err := os.Stat(passfile)
     80 		if err != nil {
     81 			return ""
     82 		}
     83 		if fi.Mode().Perm()&(0x77) != 0 {
     84 			fmt.Fprintf(WarnFD,
     85 				"WARNING: password file %q has group or world access; permissions should be u=rw (0600) or less\n",
     86 				passfile)
     87 			return ""
     88 		}
     89 	}
     90 	return passfile
     91 }