mirror of
https://github.com/FiloSottile/age.git
synced 2026-01-09 13:23:07 +00:00
cmd/age: lazily open output file at first write
This avoids leaving behind an empty file when an error occurs before we write the header (for example, because the passphrase is invalid). Do a best-effort check before taking user input for whether the file exists so we don't waste user effort. An error might still happen after user input if other kind of open errors happen (for example, a permission issue, or disk full). Fixes #159 Fixes #57 Closes #169
This commit is contained in:
committed by
Filippo Valsorda
parent
02ee8b969a
commit
97b6569a66
@@ -167,11 +167,11 @@ func main() {
|
||||
stdinInUse = true
|
||||
}
|
||||
if name := outFlag; name != "" && name != "-" {
|
||||
f, err := os.OpenFile(name, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0666)
|
||||
if err != nil {
|
||||
logFatalf("Error: failed to open output file %q: %v", name, err)
|
||||
if _, err := os.Stat(name); err == nil {
|
||||
logFatalf("Error: output file %q exists", name)
|
||||
}
|
||||
defer f.Close()
|
||||
f, close := lazyOpener(name)
|
||||
defer close()
|
||||
out = f
|
||||
} else if terminal.IsTerminal(int(os.Stdout.Fd())) {
|
||||
if armorFlag {
|
||||
@@ -330,6 +330,33 @@ func passphrasePrompt() (string, error) {
|
||||
return string(pass), nil
|
||||
}
|
||||
|
||||
type WriterFunc func(p []byte) (n int, err error)
|
||||
|
||||
func (f WriterFunc) Write(p []byte) (n int, err error) { return f(p) }
|
||||
|
||||
// lazyOpener returns a Writer that opens the named file upon the first Write,
|
||||
// and a function that calls Close on the file if it has been successfully
|
||||
// opened, and returns nil otherwise.
|
||||
func lazyOpener(name string) (w io.Writer, close func() error) {
|
||||
var f *os.File
|
||||
var openErr error
|
||||
write := func(p []byte) (n int, err error) {
|
||||
if f == nil && openErr == nil {
|
||||
f, openErr = os.OpenFile(name, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0666)
|
||||
}
|
||||
if openErr != nil {
|
||||
return 0, openErr
|
||||
}
|
||||
return f.Write(p)
|
||||
}
|
||||
return WriterFunc(write), func() error {
|
||||
if f != nil {
|
||||
return f.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func logFatalf(format string, v ...interface{}) {
|
||||
_log.Printf(format, v...)
|
||||
_log.Fatalf("[ Did age not do what you expected? Could an error be more useful?" +
|
||||
|
||||
Reference in New Issue
Block a user