Absorb: ask for the passphrase once the archive starts arriving
With gpg --decrypt x.tar.gpg | vault absorb, vault printed its prompt while gpg was still writing to the terminal, which buried it, so the command looked hung. Peek at standard input first: the upstream program has finished with the terminal by the time data arrives, and an empty pipe now fails without asking at all. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
1403be8b1c
commit
730877823e
@@ -581,7 +581,11 @@ vault absorb old < archive.tar.gz
|
|||||||
|
|
||||||
Each file is encrypted straight from the stream, so nothing is unpacked to
|
Each file is encrypted straight from the stream, so nothing is unpacked to
|
||||||
disk first. Directories need no entry of their own; links, devices and any
|
disk first. Directories need no entry of their own; links, devices and any
|
||||||
name that tries to climb out with \file{..} are skipped with a note. If the
|
name that tries to climb out with \file{..} are skipped with a note.
|
||||||
|
vault asks for your passphrase only once the archive starts arriving, so
|
||||||
|
when it comes out of something that asks first, like
|
||||||
|
\cmd{gpg --decrypt secrets.tar.gpg | vault absorb}, gpg's prompt comes
|
||||||
|
and goes before vault's appears. If the
|
||||||
archive stops halfway through a file, that file isn't stored and vault
|
archive stops halfway through a file, that file isn't stored and vault
|
||||||
stops; everything before it is already safely in.
|
stops; everything before it is already safely in.
|
||||||
|
|
||||||
|
|||||||
+6
-2
@@ -35,8 +35,12 @@ or
|
|||||||
is dropped.
|
is dropped.
|
||||||
.PP
|
.PP
|
||||||
The passphrase prompt reads from the terminal, not standard input, so
|
The passphrase prompt reads from the terminal, not standard input, so
|
||||||
it still works with an archive piped in. The vault is locked exclusively
|
it still works with an archive piped in. It waits until the archive starts
|
||||||
for the whole run.
|
arriving, so a program feeding the pipe, such as
|
||||||
|
.BR gpg (1)
|
||||||
|
asking for its own passphrase, has finished with the terminal first.
|
||||||
|
An empty pipe fails without asking at all.
|
||||||
|
The vault is locked exclusively for the whole run.
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.TP
|
.TP
|
||||||
.BI \-\-key " PATH"
|
.BI \-\-key " PATH"
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -158,10 +159,17 @@ func main() {
|
|||||||
if len(pos) == 1 {
|
if len(pos) == 1 {
|
||||||
dest = strings.Trim(pos[0], "/")
|
dest = strings.Trim(pos[0], "/")
|
||||||
}
|
}
|
||||||
|
// Wait for the archive to start arriving before asking for the
|
||||||
|
// passphrase, so a program feeding the pipe (gpg, ssh) has finished
|
||||||
|
// with the terminal and cannot bury the prompt.
|
||||||
|
in := bufio.NewReader(os.Stdin)
|
||||||
|
if _, err := in.Peek(1); err != nil {
|
||||||
|
fail("nothing to absorb on standard input")
|
||||||
|
}
|
||||||
s := open(*keyPath, *vaultDir, true)
|
s := open(*keyPath, *vaultDir, true)
|
||||||
cat, err := s.catalogue()
|
cat, err := s.catalogue()
|
||||||
check(err)
|
check(err)
|
||||||
check(absorb(s, cat, os.Stdin, dest))
|
check(absorb(s, cat, in, dest))
|
||||||
case "list", "ls":
|
case "list", "ls":
|
||||||
want(0, 1)
|
want(0, 1)
|
||||||
prefix := ""
|
prefix := ""
|
||||||
|
|||||||
Reference in New Issue
Block a user