Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
983f554ac0 |
@@ -253,11 +253,8 @@ always decrypt what it encrypted. Output goes to `-o` or standard output;
|
||||
A regular file already at the `-o` path is replaced, and the new file has mode
|
||||
`0600`. A symlink there is followed, and what it points at is treated the same
|
||||
way, so the link keeps pointing where it did; a symlink that points at nothing
|
||||
is refused. A named pipe or a device, such as `/dev/null`, is written to
|
||||
directly. `-o /dev/stdout` writes to the tool's own standard output, as leaving
|
||||
out `-o` does, and `-o /dev/stderr` to its standard error; a file either stream
|
||||
is redirected to is written as the redirect says and never replaced, so with
|
||||
`>>` the output follows what the file already held.
|
||||
is refused. A named pipe or a device, such as `/dev/null` or `/dev/stdout`, is
|
||||
written to directly.
|
||||
|
||||
### `keyfunc age decrypt [-n N] [-o <file>] [<file>]`
|
||||
|
||||
@@ -306,12 +303,11 @@ already at the named path as it was, and exit with status 1. That holds for a
|
||||
signal that has reached `keyfunc` when its input ends; a later one leaves the
|
||||
whole file in place. Ctrl-C on a pipeline ends the input at the same moment, and
|
||||
on Linux `keyfunc` sees the signal first, though no system promises that. A
|
||||
named pipe or a device at the `-o` path, `/dev/stdout` or `/dev/stderr`, is
|
||||
written to directly, and the signal ends the tool there as it ends any other
|
||||
command. While `ssh to` or `ssh install` has `ssh` or `sftp` running, the signal
|
||||
ends that program instead, the tool removes its agent socket or working files,
|
||||
and it exits with status 1, or for `ssh to` with `ssh`'s own status if `ssh`
|
||||
reported one.
|
||||
named pipe or a device at the `-o` path is written to directly, and the signal
|
||||
ends the tool there as it ends any other command. While `ssh to` or
|
||||
`ssh install` has `ssh` or `sftp` running, the signal ends that program instead,
|
||||
the tool removes its agent socket or working files, and it exits with status 1,
|
||||
or for `ssh to` with `ssh`'s own status if `ssh` reported one.
|
||||
|
||||
## Entrypoints
|
||||
|
||||
|
||||
+5
-11
@@ -141,10 +141,7 @@ func runDecrypt(cmd *cobra.Command, args []string) error {
|
||||
|
||||
// through opens the input the arguments ask for and hands it to the
|
||||
// work, with the file --output names to write to, or the command's own
|
||||
// output when it names none or names /dev/stdout, and the command's own
|
||||
// error output when it names /dev/stderr. Those two are the streams the
|
||||
// tool already has, so whatever they are redirected to is written as
|
||||
// the redirect says, never replaced.
|
||||
// output when it names none.
|
||||
func through(
|
||||
cmd *cobra.Command, args []string,
|
||||
work func(io.Writer, io.Reader) error,
|
||||
@@ -161,14 +158,11 @@ func through(
|
||||
return fmt.Errorf("reading the output file: %w", err)
|
||||
}
|
||||
|
||||
switch name {
|
||||
case "", "/dev/stdout":
|
||||
if name == "" {
|
||||
return work(cmd.OutOrStdout(), src)
|
||||
case "/dev/stderr":
|
||||
return work(cmd.ErrOrStderr(), src)
|
||||
default:
|
||||
return output(name, src, work)
|
||||
}
|
||||
|
||||
return output(name, src, work)
|
||||
}
|
||||
|
||||
// input returns what to read from: the named file, or the command's
|
||||
@@ -210,7 +204,7 @@ func output(
|
||||
case info.Mode().IsRegular():
|
||||
return replace(name, src, work)
|
||||
case info.Mode().Type() == fs.ModeSymlink:
|
||||
// os.Stat follows the link as opening it would. /dev/fd/1
|
||||
// os.Stat follows the link as opening it would. /dev/stdout
|
||||
// needs that: it reaches a pipe or a terminal through a link
|
||||
// that names no path.
|
||||
info, err = os.Stat(name)
|
||||
|
||||
@@ -151,34 +151,6 @@ func TestANamedPipeAtTheOutputPathIsWrittenToAndStaysAPipe(t *testing.T) {
|
||||
require.Equal(t, "the secret\n", run(t, "age", "decrypt", sealedFile))
|
||||
}
|
||||
|
||||
func TestDevStdoutAddsToTheFileStandardOutputIsAppendedTo(t *testing.T) {
|
||||
t.Setenv(mnemonic.Variable, example())
|
||||
|
||||
sealed := filepath.Join(t.TempDir(), "notes.age")
|
||||
run(t, "age", "encrypt", "-o", sealed, written(t, "notes.txt", "the secret\n"))
|
||||
|
||||
// What the shell's ">> notes.out" gives the tool as standard output.
|
||||
existing := written(t, "notes.out", "what was already there\n")
|
||||
|
||||
//nolint:gosec // the test made this path itself
|
||||
appended, err := os.OpenFile(existing, os.O_WRONLY|os.O_APPEND, 0)
|
||||
require.NoError(t, err)
|
||||
|
||||
defer func() { _ = appended.Close() }()
|
||||
|
||||
//nolint:gosec // this test's own binary as the tool
|
||||
command := exec.CommandContext(
|
||||
t.Context(), os.Args[0], "age", "decrypt", "-o", "/dev/stdout", sealed,
|
||||
)
|
||||
command.Env = append(os.Environ(), runAsTool+"=1")
|
||||
command.Stdout = appended
|
||||
|
||||
require.NoError(t, command.Run())
|
||||
require.Equal(t,
|
||||
"what was already there\nthe secret\n", read(t, existing),
|
||||
)
|
||||
}
|
||||
|
||||
func TestASignalStopsAnEncryptionAndLeavesNoFile(t *testing.T) {
|
||||
t.Setenv(mnemonic.Variable, example())
|
||||
|
||||
|
||||
Reference in New Issue
Block a user