Files
age/cmd/age-inspect/inspect.go
Filippo Valsorda e4c611f778 cmd,extra: restore the Version link-time variable
We don't need it in our builds, but it's useful for downstream packagers.

Fixes #671
Updates NixOS/nixpkgs#474666
Updates golang/go#77020
2025-12-28 12:49:37 +01:00

129 lines
3.3 KiB
Go

// Copyright 2025 The age Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"encoding/json"
"flag"
"fmt"
"log"
"os"
"runtime/debug"
"filippo.io/age/internal/inspect"
)
const usage = `Usage:
age-inspect [--json] [INPUT]
Options:
--json Output machine-readable JSON.
INPUT defaults to standard input. "-" may be used as INPUT to explicitly
read from standard input.`
// Version can be set at link time to override debug.BuildInfo.Main.Version when
// building manually without git history. It should look like "v1.2.3".
var Version string
func main() {
flag.Usage = func() { fmt.Fprintf(os.Stderr, "%s\n", usage) }
var (
versionFlag bool
jsonFlag bool
)
flag.BoolVar(&versionFlag, "version", false, "print the version")
flag.BoolVar(&jsonFlag, "json", false, "output machine-readable JSON")
flag.Parse()
if versionFlag {
if buildInfo, ok := debug.ReadBuildInfo(); ok && Version == "" {
Version = buildInfo.Main.Version
}
fmt.Println(Version)
return
}
if flag.NArg() > 1 {
flag.Usage()
os.Exit(1)
}
in := os.Stdin
var fileSize int64 = -1
if name := flag.Arg(0); name != "" && name != "-" {
f, err := os.Open(name)
if err != nil {
errorf("failed to open input file %q: %v", name, err)
}
defer f.Close()
in = f
if stat, err := f.Stat(); err == nil && stat.Mode().IsRegular() {
fileSize = stat.Size()
}
}
data, err := inspect.Inspect(in, fileSize)
if err != nil {
errorf("inspection failed: %v", err)
}
if jsonFlag {
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
if err := enc.Encode(data); err != nil {
errorf("failed to encode JSON output: %v", err)
}
} else {
name := flag.Arg(0)
if name == "" {
name = "<stdin>"
}
fmt.Printf("%s is an age file, version %q.\n", name, data.Version)
fmt.Printf("\n")
if data.Armor {
fmt.Printf("This file is ASCII-armored.\n")
fmt.Printf("\n")
}
fmt.Printf("This file is encrypted to the following recipient types:\n")
for _, t := range data.StanzaTypes {
fmt.Printf(" - %q\n", t)
}
fmt.Printf("\n")
switch data.Postquantum {
case "yes":
fmt.Printf("This file uses post-quantum encryption.\n")
fmt.Printf("\n")
case "no":
fmt.Printf("This file does NOT use post-quantum encryption.\n")
fmt.Printf("\n")
}
fmt.Printf("Size breakdown (assuming it decrypts successfully):\n")
fmt.Printf("\n")
fmt.Printf(" Header % 12d bytes\n", data.Sizes.Header)
if data.Armor {
fmt.Printf(" Armor overhead % 12d bytes\n", data.Sizes.Armor)
}
fmt.Printf(" Encryption overhead % 12d bytes\n", data.Sizes.Overhead)
fmt.Printf(" Payload % 12d bytes\n", data.Sizes.MinPayload)
fmt.Printf(" -------------------\n")
total := data.Sizes.Header + data.Sizes.Overhead + data.Sizes.MinPayload + data.Sizes.Armor
fmt.Printf(" Total % 12d bytes\n", total)
fmt.Printf("\n")
fmt.Printf("Tip: for machine-readable output, use --json.\n")
}
}
// l is a logger with no prefixes.
var l = log.New(os.Stderr, "", 0)
func errorf(format string, v ...any) {
l.Printf("age-inspect: error: "+format, v...)
l.Printf("age-inspect: report unexpected or unhelpful errors at https://filippo.io/age/report")
os.Exit(1)
}