package pg import ( "errors" "fmt" "io" "os" "path/filepath" "time" "github.com/balabanovds/pgcli/internal/core" "github.com/balabanovds/pgcli/internal/kube" ) type PgPassHandler struct { orig string bckp string deleteOriginal bool } func NewPgPassHandler() (*PgPassHandler, error) { if core.Homedir() == "" { return nil, fmt.Errorf("unable to figure out your home dir") } h := &PgPassHandler{} h.orig = filepath.Join(core.Homedir(), ".pgpass") h.bckp = fmt.Sprintf("%s-%d", h.orig, time.Now().UnixMilli()) if !h.fileExists(h.orig) { _, err := os.Create(h.orig) if err != nil { return nil, fmt.Errorf("failed to create .pgpass file for portforward: %w", err) } h.deleteOriginal = true } else { err := h.copyFile(h.orig, h.bckp) if err != nil { return nil, fmt.Errorf("failed to copy original file %s to backup %s: %w", h.orig, h.bckp, err) } } return h, nil } func (h *PgPassHandler) Close() error { if err := h.deleteFile(h.orig); err != nil { return fmt.Errorf("failed to delete file %s: %w", h.orig, err) } if err := h.copyFile(h.bckp, h.orig); err != nil { return fmt.Errorf("failed to copy file from %s to %s: %w", h.bckp, h.orig, err) } if h.deleteOriginal { if err := h.deleteFile(h.orig); err != nil { return fmt.Errorf("failed to delete file %s: %w", h.orig, err) } } if err := h.deleteFile(h.bckp); err != nil { return fmt.Errorf("failed to delete file %s: %w", h.bckp, err) } return nil } func (h *PgPassHandler) Append(sec *kube.Secret, localhost string, localport int) error { f, err := os.OpenFile(h.orig, os.O_APPEND|os.O_WRONLY, 0o600) if err != nil { return fmt.Errorf("failed to append data to file %s: %w", h.orig, err) } defer func() { if cerr := f.Close(); cerr != nil { fmt.Printf("failed to close file %s during appendL %s", h.orig, cerr) } }() _, err = fmt.Fprintf(f, "# added by programm pgpf\n%s:%d:%s:%s:%s\n", localhost, localport, sec.DBName, sec.User, sec.Password) return err } func (h *PgPassHandler) copyFile(src, dst string) error { src = filepath.Clean(src) fsrc, err := os.Open(src) if err != nil { return fmt.Errorf("failed to open file %s: %w", src, err) } defer func() { if cerr := fsrc.Close(); cerr != nil { fmt.Printf("failed to close source file %s during copy: %s\n", src, cerr) } }() dst = filepath.Clean(dst) fdst, err := os.OpenFile(dst, os.O_CREATE|os.O_WRONLY, 0o600) if err != nil { return fmt.Errorf("failed to open file %s: %w", dst, err) } defer func() { if cerr := fdst.Close(); cerr != nil { fmt.Printf("faled to close destination file %s during copy: %s\n", dst, cerr) } }() _, err = io.Copy(fdst, fsrc) if err != nil { return fmt.Errorf("failed to copy file from %s to %s: %w", src, dst, err) } return nil } func (h *PgPassHandler) fileExists(src string) bool { _, err := os.Stat(src) return err == nil || errors.Is(err, os.ErrNotExist) } func (h *PgPassHandler) deleteFile(src string) error { return os.Remove(src) }