package main import ( "errors" "fmt" "os" "path/filepath" "github.com/spf13/cobra" "github.com/safing/jess/filesig" ) func init() { rootCmd.AddCommand(checksum) checksum.AddCommand(checksumAdd) checksum.AddCommand(checksumVerify) } var ( checksum = &cobra.Command{ Use: "checksum", Short: "add or verify embedded checksums", } checksumAddUsage = "usage: checksum add <file>" checksumAdd = &cobra.Command{ Use: "add <file>", Short: "add an embedded checksum to a file", Long: "add an embedded checksum to a file (support file types: txt, json, yaml)", RunE: handleChecksumAdd, } checksumVerifyUsage = "usage: checksum verify <file>" checksumVerify = &cobra.Command{ Use: "verify <file>", Short: "verify the embedded checksum of a file", Long: "verify the embedded checksum of a file (support file types: txt, json, yaml)", RunE: handleChecksumVerify, } ) func handleChecksumAdd(cmd *cobra.Command, args []string) error { // Check args. if len(args) != 1 { return errors.New(checksumAddUsage) } filename := args[0] data, err := os.ReadFile(filename) if err != nil { return fmt.Errorf("failed to read file: %w", err) } switch filepath.Ext(filename) { case ".json": data, err = filesig.AddJSONChecksum(data) case ".yml", ".yaml": data, err = filesig.AddYAMLChecksum(data, filesig.TextPlacementAfterComment) case ".txt": data, err = filesig.AddTextFileChecksum(data, "#", filesig.TextPlacementAfterComment) default: return errors.New("unsupported file format") } if err != nil { return err } // Write back to disk. fileInfo, err := os.Stat(filename) if err != nil { return fmt.Errorf("failed to stat file: %w", err) } err = os.WriteFile(filename, data, fileInfo.Mode().Perm()) if err != nil { return fmt.Errorf("failed to write back file with checksum: %w", err) } fmt.Println("checksum added") return nil } func handleChecksumVerify(cmd *cobra.Command, args []string) error { // Check args. if len(args) != 1 { return errors.New(checksumVerifyUsage) } filename := args[0] data, err := os.ReadFile(filename) if err != nil { return fmt.Errorf("failed to read file: %w", err) } switch filepath.Ext(filename) { case ".json": err = filesig.VerifyJSONChecksum(data) case ".yml", ".yaml": err = filesig.VerifyYAMLChecksum(data) case ".txt": err = filesig.VerifyTextFileChecksum(data, "#") default: return errors.New("unsupported file format") } if err != nil { return err } fmt.Println("checksum verified") return nil }