feat: Start implementation of metadata encryption
This commit is contained in:
@@ -2,8 +2,10 @@ package cmd
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"context"
|
||||
"encoding/base32"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -35,7 +37,9 @@ const (
|
||||
srcFlag = "src"
|
||||
overwriteFlag = "overwrite"
|
||||
compressionLevelFlag = "compression-level"
|
||||
keyFlag = "key"
|
||||
|
||||
recipientFlag = "recipient"
|
||||
identityFlag = "identity"
|
||||
|
||||
compressionLevelFastest = "fastest"
|
||||
compressionLevelBalanced = "balanced"
|
||||
@@ -48,7 +52,8 @@ var (
|
||||
errUnknownCompressionLevel = errors.New("unknown compression level")
|
||||
errUnsupportedCompressionLevel = errors.New("unsupported compression level")
|
||||
|
||||
errKeyNotAccessible = errors.New("key not found or accessible")
|
||||
errRecipientNotAccessible = errors.New("recipient/public key not found or accessible")
|
||||
errIdentityNotAccessible = errors.New("identity/private key not found or accessible")
|
||||
)
|
||||
|
||||
type flusher interface {
|
||||
@@ -91,8 +96,12 @@ var archiveCmd = &cobra.Command{
|
||||
}
|
||||
|
||||
if viper.GetString(encryptionFlag) != encryptionFormatNoneKey {
|
||||
if _, err := os.Stat(viper.GetString(keyFlag)); err != nil {
|
||||
return errKeyNotAccessible
|
||||
if _, err := os.Stat(viper.GetString(recipientFlag)); err != nil {
|
||||
return errRecipientNotAccessible
|
||||
}
|
||||
|
||||
if _, err := os.Stat(viper.GetString(identityFlag)); err != nil {
|
||||
return errIdentityNotAccessible
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,13 +130,19 @@ var archiveCmd = &cobra.Command{
|
||||
}
|
||||
|
||||
pubkey := []byte{}
|
||||
privkey := []byte{}
|
||||
if viper.GetString(encryptionFlag) != encryptionFormatNoneKey {
|
||||
p, err := ioutil.ReadFile(viper.GetString(keyFlag))
|
||||
p, err := ioutil.ReadFile(viper.GetString(recipientFlag))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pubkey = p
|
||||
|
||||
privkey, err = ioutil.ReadFile(viper.GetString(identityFlag))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := archive(
|
||||
@@ -152,6 +167,7 @@ var archiveCmd = &cobra.Command{
|
||||
viper.GetBool(overwriteFlag),
|
||||
viper.GetString(compressionFlag),
|
||||
viper.GetString(encryptionFlag),
|
||||
privkey,
|
||||
)
|
||||
},
|
||||
}
|
||||
@@ -327,6 +343,10 @@ func archive(
|
||||
return err
|
||||
}
|
||||
|
||||
if err := encryptHeader(hdr, encryptionFormat, pubkey); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := tw.WriteHeader(hdr); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -406,6 +426,21 @@ func checkCompressionLevel(compressionLevel string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func encryptHeader(
|
||||
hdr *tar.Header,
|
||||
encryptionFormat string,
|
||||
pubkey []byte,
|
||||
) error {
|
||||
var err error
|
||||
|
||||
hdr.Name, err = encryptString(hdr.Name, encryptionFormat, pubkey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func addSuffix(name string, compressionFormat string, encryptionFormat string) (string, error) {
|
||||
switch compressionFormat {
|
||||
case compressionFormatGZipKey:
|
||||
@@ -458,6 +493,40 @@ func encrypt(
|
||||
}
|
||||
}
|
||||
|
||||
func encryptString(
|
||||
src string,
|
||||
encryptionFormat string,
|
||||
pubkey []byte,
|
||||
) (string, error) {
|
||||
switch encryptionFormat {
|
||||
case encryptionFormatAgeKey:
|
||||
recipient, err := age.ParseX25519Recipient(string(pubkey))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
out := &bytes.Buffer{}
|
||||
w, err := age.Encrypt(out, recipient)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if _, err := io.WriteString(w, src); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err := w.Close(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return base32.StdEncoding.EncodeToString(out.Bytes()), nil
|
||||
case encryptionFormatNoneKey:
|
||||
return src, nil
|
||||
default:
|
||||
return "", errUnsupportedEncryptionFormat
|
||||
}
|
||||
}
|
||||
|
||||
func compress(
|
||||
dst io.Writer,
|
||||
compressionFormat string,
|
||||
@@ -587,7 +656,8 @@ func init() {
|
||||
archiveCmd.PersistentFlags().StringP(srcFlag, "s", ".", "File or directory to archive")
|
||||
archiveCmd.PersistentFlags().BoolP(overwriteFlag, "o", false, "Start writing from the start instead of from the end of the tape or tar file")
|
||||
archiveCmd.PersistentFlags().StringP(compressionLevelFlag, "l", compressionLevelBalanced, fmt.Sprintf("Compression level to use (default %v, available are %v)", compressionLevelBalanced, knownCompressionLevels))
|
||||
archiveCmd.PersistentFlags().StringP(keyFlag, "k", "", "Path to public key of recipient to encrypt for")
|
||||
archiveCmd.PersistentFlags().StringP(recipientFlag, "r", "", "Path to public key of recipient to encrypt for")
|
||||
archiveCmd.PersistentFlags().StringP(identityFlag, "i", "", "Path to private key of recipient that has been encrypted for")
|
||||
|
||||
viper.AutomaticEnv()
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"archive/tar"
|
||||
"bufio"
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/pojntfx/stfs/pkg/controllers"
|
||||
@@ -26,6 +27,19 @@ var deleteCmd = &cobra.Command{
|
||||
Use: "delete",
|
||||
Aliases: []string{"del", "d", "rm"},
|
||||
Short: "Delete a file or directory from tape or tar file",
|
||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if viper.GetString(encryptionFlag) != encryptionFormatNoneKey {
|
||||
if _, err := os.Stat(viper.GetString(recipientFlag)); err != nil {
|
||||
return errRecipientNotAccessible
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil {
|
||||
return err
|
||||
@@ -35,70 +49,100 @@ var deleteCmd = &cobra.Command{
|
||||
boil.DebugMode = true
|
||||
}
|
||||
|
||||
dirty := false
|
||||
tw, _, cleanup, err := openTapeWriter(viper.GetString(tapeFlag))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer cleanup(&dirty)
|
||||
|
||||
metadataPersister := persisters.NewMetadataPersister(viper.GetString(metadataFlag))
|
||||
if err := metadataPersister.Open(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
headersToDelete := []*models.Header{}
|
||||
dbhdr, err := metadataPersister.GetHeader(context.Background(), viper.GetString(nameFlag))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
headersToDelete = append(headersToDelete, dbhdr)
|
||||
|
||||
// If the header refers to a directory, get it's children
|
||||
if dbhdr.Typeflag == tar.TypeDir {
|
||||
dbhdrs, err := metadataPersister.GetHeaderChildren(context.Background(), viper.GetString(nameFlag))
|
||||
pubkey := []byte{}
|
||||
if viper.GetString(encryptionFlag) != encryptionFormatNoneKey {
|
||||
p, err := ioutil.ReadFile(viper.GetString(recipientFlag))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
headersToDelete = append(headersToDelete, dbhdrs...)
|
||||
pubkey = p
|
||||
}
|
||||
|
||||
// Remove the headers from the index
|
||||
if err := metadataPersister.DeleteHeaders(context.Background(), headersToDelete); err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := formatting.PrintCSV(formatting.TARHeaderCSV); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Append deletion headers to the tape or tar file
|
||||
for _, dbhdr := range headersToDelete {
|
||||
hdr, err := converters.DBHeaderToTarHeader(dbhdr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hdr.Size = 0 // Don't try to seek after the record
|
||||
hdr.PAXRecords[pax.STFSRecordVersion] = pax.STFSRecordVersion1
|
||||
hdr.PAXRecords[pax.STFSRecordAction] = pax.STFSRecordActionDelete
|
||||
|
||||
if err := tw.WriteHeader(hdr); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dirty = true
|
||||
|
||||
if err := formatting.PrintCSV(formatting.GetTARHeaderAsCSV(-1, -1, hdr)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return delete(
|
||||
viper.GetString(tapeFlag),
|
||||
viper.GetString(metadataFlag),
|
||||
viper.GetString(nameFlag),
|
||||
viper.GetString(encryptionFlag),
|
||||
pubkey,
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
func delete(
|
||||
tape string,
|
||||
metadata string,
|
||||
name string,
|
||||
encryptionFormat string,
|
||||
pubkey []byte,
|
||||
) error {
|
||||
dirty := false
|
||||
tw, _, cleanup, err := openTapeWriter(tape)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer cleanup(&dirty)
|
||||
|
||||
metadataPersister := persisters.NewMetadataPersister(metadata)
|
||||
if err := metadataPersister.Open(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
headersToDelete := []*models.Header{}
|
||||
dbhdr, err := metadataPersister.GetHeader(context.Background(), name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
headersToDelete = append(headersToDelete, dbhdr)
|
||||
|
||||
// If the header refers to a directory, get it's children
|
||||
if dbhdr.Typeflag == tar.TypeDir {
|
||||
dbhdrs, err := metadataPersister.GetHeaderChildren(context.Background(), name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
headersToDelete = append(headersToDelete, dbhdrs...)
|
||||
}
|
||||
|
||||
// Remove the headers from the index
|
||||
if err := metadataPersister.DeleteHeaders(context.Background(), headersToDelete); err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := formatting.PrintCSV(formatting.TARHeaderCSV); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Append deletion headers to the tape or tar file
|
||||
for _, dbhdr := range headersToDelete {
|
||||
hdr, err := converters.DBHeaderToTarHeader(dbhdr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hdr.Size = 0 // Don't try to seek after the record
|
||||
hdr.PAXRecords[pax.STFSRecordVersion] = pax.STFSRecordVersion1
|
||||
hdr.PAXRecords[pax.STFSRecordAction] = pax.STFSRecordActionDelete
|
||||
|
||||
if err := encryptHeader(hdr, encryptionFormat, pubkey); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := tw.WriteHeader(hdr); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dirty = true
|
||||
|
||||
if err := formatting.PrintCSV(formatting.GetTARHeaderAsCSV(-1, -1, hdr)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func openTapeWriter(tape string) (tw *tar.Writer, isRegular bool, cleanup func(dirty *bool) error, err error) {
|
||||
stat, err := os.Stat(tape)
|
||||
if err == nil {
|
||||
@@ -169,6 +213,7 @@ func openTapeWriter(tape string) (tw *tar.Writer, isRegular bool, cleanup func(d
|
||||
func init() {
|
||||
deleteCmd.PersistentFlags().IntP(recordSizeFlag, "z", 20, "Amount of 512-bit blocks per record")
|
||||
deleteCmd.PersistentFlags().StringP(nameFlag, "n", "", "Name of the file to remove")
|
||||
deleteCmd.PersistentFlags().StringP(recipientFlag, "r", "", "Path to public key of recipient to encrypt for")
|
||||
|
||||
viper.AutomaticEnv()
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@ package cmd
|
||||
import (
|
||||
"archive/tar"
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/pojntfx/stfs/pkg/converters"
|
||||
@@ -19,6 +21,19 @@ var moveCmd = &cobra.Command{
|
||||
Use: "move",
|
||||
Aliases: []string{"mov", "m", "mv"},
|
||||
Short: "Move a file or directory on tape or tar file",
|
||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if viper.GetString(encryptionFlag) != encryptionFormatNoneKey {
|
||||
if _, err := os.Stat(viper.GetString(recipientFlag)); err != nil {
|
||||
return errRecipientNotAccessible
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil {
|
||||
return err
|
||||
@@ -28,76 +43,109 @@ var moveCmd = &cobra.Command{
|
||||
boil.DebugMode = true
|
||||
}
|
||||
|
||||
dirty := false
|
||||
tw, _, cleanup, err := openTapeWriter(viper.GetString(tapeFlag))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer cleanup(&dirty)
|
||||
|
||||
metadataPersister := persisters.NewMetadataPersister(viper.GetString(metadataFlag))
|
||||
if err := metadataPersister.Open(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
headersToMove := []*models.Header{}
|
||||
dbhdr, err := metadataPersister.GetHeader(context.Background(), viper.GetString(srcFlag))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
headersToMove = append(headersToMove, dbhdr)
|
||||
|
||||
// If the header refers to a directory, get it's children
|
||||
if dbhdr.Typeflag == tar.TypeDir {
|
||||
dbhdrs, err := metadataPersister.GetHeaderChildren(context.Background(), viper.GetString(srcFlag))
|
||||
pubkey := []byte{}
|
||||
if viper.GetString(encryptionFlag) != encryptionFormatNoneKey {
|
||||
p, err := ioutil.ReadFile(viper.GetString(recipientFlag))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
headersToMove = append(headersToMove, dbhdrs...)
|
||||
pubkey = p
|
||||
}
|
||||
|
||||
// Move the headers in the index
|
||||
if err := metadataPersister.MoveHeaders(context.Background(), headersToMove, viper.GetString(srcFlag), viper.GetString(dstFlag)); err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := formatting.PrintCSV(formatting.TARHeaderCSV); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Append move headers to the tape or tar file
|
||||
for _, dbhdr := range headersToMove {
|
||||
hdr, err := converters.DBHeaderToTarHeader(dbhdr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hdr.Size = 0 // Don't try to seek after the record
|
||||
hdr.Name = strings.TrimSuffix(viper.GetString(dstFlag), "/") + strings.TrimPrefix(hdr.Name, strings.TrimSuffix(viper.GetString(srcFlag), "/"))
|
||||
hdr.PAXRecords[pax.STFSRecordVersion] = pax.STFSRecordVersion1
|
||||
hdr.PAXRecords[pax.STFSRecordAction] = pax.STFSRecordActionUpdate
|
||||
hdr.PAXRecords[pax.STFSRecordReplacesName] = dbhdr.Name
|
||||
|
||||
if err := tw.WriteHeader(hdr); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dirty = true
|
||||
|
||||
if err := formatting.PrintCSV(formatting.GetTARHeaderAsCSV(-1, -1, hdr)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return move(
|
||||
viper.GetString(tapeFlag),
|
||||
viper.GetString(metadataFlag),
|
||||
viper.GetString(srcFlag),
|
||||
viper.GetString(dstFlag),
|
||||
viper.GetString(encryptionFlag),
|
||||
pubkey,
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
func move(
|
||||
tape string,
|
||||
metadata string,
|
||||
src string,
|
||||
dst string,
|
||||
encryptionFormat string,
|
||||
pubkey []byte,
|
||||
) error {
|
||||
dirty := false
|
||||
tw, _, cleanup, err := openTapeWriter(tape)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer cleanup(&dirty)
|
||||
|
||||
metadataPersister := persisters.NewMetadataPersister(metadata)
|
||||
if err := metadataPersister.Open(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
headersToMove := []*models.Header{}
|
||||
dbhdr, err := metadataPersister.GetHeader(context.Background(), src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
headersToMove = append(headersToMove, dbhdr)
|
||||
|
||||
// If the header refers to a directory, get it's children
|
||||
if dbhdr.Typeflag == tar.TypeDir {
|
||||
dbhdrs, err := metadataPersister.GetHeaderChildren(context.Background(), src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
headersToMove = append(headersToMove, dbhdrs...)
|
||||
}
|
||||
|
||||
// Move the headers in the index
|
||||
if err := metadataPersister.MoveHeaders(context.Background(), headersToMove, src, dst); err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := formatting.PrintCSV(formatting.TARHeaderCSV); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Append move headers to the tape or tar file
|
||||
for _, dbhdr := range headersToMove {
|
||||
hdr, err := converters.DBHeaderToTarHeader(dbhdr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hdr.Size = 0 // Don't try to seek after the record
|
||||
hdr.Name = strings.TrimSuffix(dst, "/") + strings.TrimPrefix(hdr.Name, strings.TrimSuffix(src, "/"))
|
||||
hdr.PAXRecords[pax.STFSRecordVersion] = pax.STFSRecordVersion1
|
||||
hdr.PAXRecords[pax.STFSRecordAction] = pax.STFSRecordActionUpdate
|
||||
hdr.PAXRecords[pax.STFSRecordReplacesName] = dbhdr.Name
|
||||
|
||||
if err := encryptHeader(hdr, encryptionFormat, pubkey); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := tw.WriteHeader(hdr); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dirty = true
|
||||
|
||||
if err := formatting.PrintCSV(formatting.GetTARHeaderAsCSV(-1, -1, hdr)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
moveCmd.PersistentFlags().IntP(recordSizeFlag, "z", 20, "Amount of 512-bit blocks per record")
|
||||
moveCmd.PersistentFlags().StringP(srcFlag, "s", "", "Current path of the file or directory to move")
|
||||
moveCmd.PersistentFlags().StringP(dstFlag, "d", "", "Path to move the file or directory to")
|
||||
moveCmd.PersistentFlags().StringP(recipientFlag, "r", "", "Path to public key of recipient to encrypt for")
|
||||
|
||||
viper.AutomaticEnv()
|
||||
|
||||
|
||||
@@ -3,8 +3,10 @@ package cmd
|
||||
import (
|
||||
"archive/tar"
|
||||
"bufio"
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"context"
|
||||
"encoding/base32"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
@@ -40,8 +42,8 @@ var recoveryFetchCmd = &cobra.Command{
|
||||
}
|
||||
|
||||
if viper.GetString(encryptionFlag) != encryptionFormatNoneKey {
|
||||
if _, err := os.Stat(viper.GetString(keyFlag)); err != nil {
|
||||
return errKeyNotAccessible
|
||||
if _, err := os.Stat(viper.GetString(identityFlag)); err != nil {
|
||||
return errIdentityNotAccessible
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +60,7 @@ var recoveryFetchCmd = &cobra.Command{
|
||||
|
||||
privkey := []byte{}
|
||||
if viper.GetString(encryptionFlag) != encryptionFormatNoneKey {
|
||||
p, err := ioutil.ReadFile(viper.GetString(keyFlag))
|
||||
p, err := ioutil.ReadFile(viper.GetString(identityFlag))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -127,6 +129,10 @@ func restoreFromRecordAndBlock(
|
||||
return err
|
||||
}
|
||||
|
||||
if err := decryptHeader(hdr, encryptionFormat, privkey); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if showHeader {
|
||||
if err := formatting.PrintCSV(formatting.TARHeaderCSV); err != nil {
|
||||
return err
|
||||
@@ -238,6 +244,56 @@ func decompress(
|
||||
}
|
||||
}
|
||||
|
||||
func decryptHeader(
|
||||
hdr *tar.Header,
|
||||
encryptionFormat string,
|
||||
privkey []byte,
|
||||
) error {
|
||||
var err error
|
||||
|
||||
hdr.Name, err = decryptString(hdr.Name, encryptionFormat, privkey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func decryptString(
|
||||
src string,
|
||||
encryptionFormat string,
|
||||
privkey []byte,
|
||||
) (string, error) {
|
||||
switch encryptionFormat {
|
||||
case encryptionFormatAgeKey:
|
||||
identity, err := age.ParseX25519Identity(string(privkey))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
decoded, err := base32.StdEncoding.DecodeString(src)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
r, err := age.Decrypt(bytes.NewBufferString(string(decoded)), identity)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
out := &bytes.Buffer{}
|
||||
if _, err := io.Copy(out, r); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return out.String(), nil
|
||||
case encryptionFormatNoneKey:
|
||||
return src, nil
|
||||
default:
|
||||
return "", errUnsupportedEncryptionFormat
|
||||
}
|
||||
}
|
||||
|
||||
func decrypt(
|
||||
src io.Reader,
|
||||
encryptionFormat string,
|
||||
@@ -265,11 +321,11 @@ func decrypt(
|
||||
|
||||
func init() {
|
||||
recoveryFetchCmd.PersistentFlags().IntP(recordSizeFlag, "z", 20, "Amount of 512-bit blocks per record")
|
||||
recoveryFetchCmd.PersistentFlags().IntP(recordFlag, "r", 0, "Record to seek too")
|
||||
recoveryFetchCmd.PersistentFlags().IntP(recordFlag, "k", 0, "Record to seek too")
|
||||
recoveryFetchCmd.PersistentFlags().IntP(blockFlag, "b", 0, "Block in record to seek too")
|
||||
recoveryFetchCmd.PersistentFlags().StringP(dstFlag, "d", "", "File to restore to (archived name by default)")
|
||||
recoveryFetchCmd.PersistentFlags().BoolP(previewFlag, "p", false, "Only read the header")
|
||||
recoveryFetchCmd.PersistentFlags().StringP(keyFlag, "k", "", "Path to private key of recipient that has been encrypted for")
|
||||
recoveryFetchCmd.PersistentFlags().StringP(identityFlag, "i", "", "Path to private key of recipient that has been encrypted for")
|
||||
|
||||
viper.AutomaticEnv()
|
||||
|
||||
|
||||
@@ -26,6 +26,19 @@ import (
|
||||
var recoveryIndexCmd = &cobra.Command{
|
||||
Use: "index",
|
||||
Short: "Index contents of tape or tar file",
|
||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if viper.GetString(encryptionFlag) != encryptionFormatNoneKey {
|
||||
if _, err := os.Stat(viper.GetString(identityFlag)); err != nil {
|
||||
return errIdentityNotAccessible
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil {
|
||||
return err
|
||||
@@ -35,6 +48,16 @@ var recoveryIndexCmd = &cobra.Command{
|
||||
boil.DebugMode = true
|
||||
}
|
||||
|
||||
privkey := []byte{}
|
||||
if viper.GetString(encryptionFlag) != encryptionFormatNoneKey {
|
||||
p, err := ioutil.ReadFile(viper.GetString(identityFlag))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
privkey = p
|
||||
}
|
||||
|
||||
return index(
|
||||
viper.GetString(tapeFlag),
|
||||
viper.GetString(metadataFlag),
|
||||
@@ -44,6 +67,7 @@ var recoveryIndexCmd = &cobra.Command{
|
||||
viper.GetBool(overwriteFlag),
|
||||
viper.GetString(compressionFlag),
|
||||
viper.GetString(encryptionFlag),
|
||||
privkey,
|
||||
)
|
||||
},
|
||||
}
|
||||
@@ -57,6 +81,7 @@ func index(
|
||||
overwrite bool,
|
||||
compressionFormat string,
|
||||
encryptionFormat string,
|
||||
privkey []byte,
|
||||
) error {
|
||||
if overwrite {
|
||||
f, err := os.OpenFile(metadata, os.O_WRONLY|os.O_CREATE, 0600)
|
||||
@@ -105,19 +130,19 @@ func index(
|
||||
}
|
||||
|
||||
nextTotalBlocks := math.Ceil(float64((curr)) / float64(controllers.BlockSize))
|
||||
record = int64(nextTotalBlocks) / int64(viper.GetInt(recordSizeFlag))
|
||||
block = int64(nextTotalBlocks) - (record * int64(viper.GetInt(recordSizeFlag)))
|
||||
record = int64(nextTotalBlocks) / int64(recordSize)
|
||||
block = int64(nextTotalBlocks) - (record * int64(recordSize))
|
||||
|
||||
if block < 0 {
|
||||
record--
|
||||
block = int64(viper.GetInt(recordSizeFlag)) - 1
|
||||
} else if block >= int64(viper.GetInt(recordSizeFlag)) {
|
||||
block = int64(recordSize) - 1
|
||||
} else if block >= int64(recordSize) {
|
||||
record++
|
||||
block = 0
|
||||
}
|
||||
|
||||
// Seek to record and block
|
||||
if _, err := f.Seek(int64((viper.GetInt(recordSizeFlag)*controllers.BlockSize*int(record))+int(block)*controllers.BlockSize), io.SeekStart); err != nil {
|
||||
if _, err := f.Seek(int64((recordSize*controllers.BlockSize*int(record))+int(block)*controllers.BlockSize), io.SeekStart); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -144,6 +169,10 @@ func index(
|
||||
break
|
||||
}
|
||||
|
||||
if err := decryptHeader(hdr, encryptionFormat, privkey); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := indexHeader(record, block, hdr, metadataPersister, compressionFormat, encryptionFormat); err != nil {
|
||||
return nil
|
||||
}
|
||||
@@ -217,6 +246,10 @@ func index(
|
||||
}
|
||||
}
|
||||
|
||||
if err := decryptHeader(hdr, encryptionFormat, privkey); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := indexHeader(record, block, hdr, metadataPersister, compressionFormat, encryptionFormat); err != nil {
|
||||
return nil
|
||||
}
|
||||
@@ -245,9 +278,10 @@ func index(
|
||||
|
||||
func init() {
|
||||
recoveryIndexCmd.PersistentFlags().IntP(recordSizeFlag, "z", 20, "Amount of 512-bit blocks per record")
|
||||
recoveryIndexCmd.PersistentFlags().IntP(recordFlag, "r", 0, "Record to seek too before counting")
|
||||
recoveryIndexCmd.PersistentFlags().IntP(recordFlag, "k", 0, "Record to seek too before counting")
|
||||
recoveryIndexCmd.PersistentFlags().IntP(blockFlag, "b", 0, "Block in record to seek too before counting")
|
||||
recoveryIndexCmd.PersistentFlags().BoolP(overwriteFlag, "o", false, "Remove the old index before starting to index")
|
||||
recoveryIndexCmd.PersistentFlags().StringP(identityFlag, "i", "", "Path to private key of recipient that has been encrypted for")
|
||||
|
||||
viper.AutomaticEnv()
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"os"
|
||||
|
||||
"github.com/pojntfx/stfs/pkg/controllers"
|
||||
"github.com/pojntfx/stfs/pkg/counters"
|
||||
@@ -18,6 +19,19 @@ import (
|
||||
var recoveryQueryCmd = &cobra.Command{
|
||||
Use: "query",
|
||||
Short: "Query contents of tape or tar file without the index",
|
||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if viper.GetString(encryptionFlag) != encryptionFormatNoneKey {
|
||||
if _, err := os.Stat(viper.GetString(identityFlag)); err != nil {
|
||||
return errIdentityNotAccessible
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil {
|
||||
return err
|
||||
@@ -27,186 +41,223 @@ var recoveryQueryCmd = &cobra.Command{
|
||||
boil.DebugMode = true
|
||||
}
|
||||
|
||||
f, isRegular, err := openTapeReadOnly(viper.GetString(tapeFlag))
|
||||
if err != nil {
|
||||
privkey := []byte{}
|
||||
if viper.GetString(encryptionFlag) != encryptionFormatNoneKey {
|
||||
p, err := ioutil.ReadFile(viper.GetString(identityFlag))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
privkey = p
|
||||
}
|
||||
|
||||
return query(
|
||||
viper.GetString(tapeFlag),
|
||||
viper.GetInt(recordFlag),
|
||||
viper.GetInt(blockFlag),
|
||||
viper.GetInt(recordSizeFlag),
|
||||
viper.GetString(encryptionFlag),
|
||||
privkey,
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
func query(
|
||||
tape string,
|
||||
record int,
|
||||
block int,
|
||||
recordSize int,
|
||||
encryptionFormat string,
|
||||
privkey []byte,
|
||||
) error {
|
||||
f, isRegular, err := openTapeReadOnly(tape)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
if isRegular {
|
||||
// Seek to record and block
|
||||
if _, err := f.Seek(int64((recordSize*controllers.BlockSize*record)+block*controllers.BlockSize), 0); err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
if isRegular {
|
||||
// Seek to record and block
|
||||
if _, err := f.Seek(int64((viper.GetInt(recordSizeFlag)*controllers.BlockSize*viper.GetInt(recordFlag))+viper.GetInt(blockFlag)*controllers.BlockSize), 0); err != nil {
|
||||
return err
|
||||
}
|
||||
tr := tar.NewReader(f)
|
||||
|
||||
tr := tar.NewReader(f)
|
||||
record := int64(record)
|
||||
block := int64(block)
|
||||
|
||||
record := viper.GetInt64(recordFlag)
|
||||
block := viper.GetInt64(blockFlag)
|
||||
|
||||
for {
|
||||
hdr, err := tr.Next()
|
||||
if err != nil {
|
||||
for {
|
||||
curr, err := f.Seek(0, io.SeekCurrent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nextTotalBlocks := math.Ceil(float64((curr)) / float64(controllers.BlockSize))
|
||||
record = int64(nextTotalBlocks) / int64(viper.GetInt(recordSizeFlag))
|
||||
block = int64(nextTotalBlocks) - (record * int64(viper.GetInt(recordSizeFlag)))
|
||||
|
||||
if block < 0 {
|
||||
record--
|
||||
block = int64(viper.GetInt(recordSizeFlag)) - 1
|
||||
} else if block >= int64(viper.GetInt(recordSizeFlag)) {
|
||||
record++
|
||||
block = 0
|
||||
}
|
||||
|
||||
// Seek to record and block
|
||||
if _, err := f.Seek(int64((viper.GetInt(recordSizeFlag)*controllers.BlockSize*int(record))+int(block)*controllers.BlockSize), io.SeekStart); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tr = tar.NewReader(f)
|
||||
|
||||
hdr, err = tr.Next()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
// EOF
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if hdr == nil {
|
||||
// EOF
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
if record == 0 && block == 0 {
|
||||
if err := formatting.PrintCSV(formatting.TARHeaderCSV); err != nil {
|
||||
for {
|
||||
hdr, err := tr.Next()
|
||||
if err != nil {
|
||||
for {
|
||||
curr, err := f.Seek(0, io.SeekCurrent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := formatting.PrintCSV(formatting.GetTARHeaderAsCSV(record, block, hdr)); err != nil {
|
||||
return err
|
||||
}
|
||||
nextTotalBlocks := math.Ceil(float64((curr)) / float64(controllers.BlockSize))
|
||||
record = int64(nextTotalBlocks) / int64(recordSize)
|
||||
block = int64(nextTotalBlocks) - (record * int64(recordSize))
|
||||
|
||||
curr, err := f.Seek(0, io.SeekCurrent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if block < 0 {
|
||||
record--
|
||||
block = int64(recordSize) - 1
|
||||
} else if block >= int64(recordSize) {
|
||||
record++
|
||||
block = 0
|
||||
}
|
||||
|
||||
if _, err := io.Copy(ioutil.Discard, tr); err != nil {
|
||||
return err
|
||||
}
|
||||
// Seek to record and block
|
||||
if _, err := f.Seek(int64((recordSize*controllers.BlockSize*int(record))+int(block)*controllers.BlockSize), io.SeekStart); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
currAndSize, err := f.Seek(0, io.SeekCurrent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tr = tar.NewReader(f)
|
||||
|
||||
nextTotalBlocks := math.Ceil(float64(curr+(currAndSize-curr)) / float64(controllers.BlockSize))
|
||||
record = int64(nextTotalBlocks) / int64(viper.GetInt(recordSizeFlag))
|
||||
block = int64(nextTotalBlocks) - (record * int64(viper.GetInt(recordSizeFlag)))
|
||||
|
||||
if block > int64(viper.GetInt(recordSizeFlag)) {
|
||||
record++
|
||||
block = 0
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Seek to record
|
||||
if err := controllers.SeekToRecordOnTape(f, int32(viper.GetInt(recordFlag))); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Seek to block
|
||||
br := bufio.NewReaderSize(f, controllers.BlockSize*viper.GetInt(recordSizeFlag))
|
||||
if _, err := br.Read(make([]byte, viper.GetInt(blockFlag)*controllers.BlockSize)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
record := viper.GetInt64(recordFlag)
|
||||
block := viper.GetInt64(blockFlag)
|
||||
|
||||
curr := int64((viper.GetInt(recordSizeFlag) * controllers.BlockSize * viper.GetInt(recordFlag)) + (viper.GetInt(blockFlag) * controllers.BlockSize))
|
||||
counter := &counters.CounterReader{Reader: br, BytesRead: int(curr)}
|
||||
|
||||
tr := tar.NewReader(counter)
|
||||
for {
|
||||
hdr, err := tr.Next()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
if err := controllers.GoToNextFileOnTape(f); err != nil {
|
||||
// EOD
|
||||
hdr, err = tr.Next()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
// EOF
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
record, err = controllers.GetCurrentRecordFromTape(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
block = 0
|
||||
|
||||
br = bufio.NewReaderSize(f, controllers.BlockSize*viper.GetInt(recordSizeFlag))
|
||||
curr := int64(int64(viper.GetInt(recordSizeFlag)) * controllers.BlockSize * record)
|
||||
counter := &counters.CounterReader{Reader: br, BytesRead: int(curr)}
|
||||
tr = tar.NewReader(counter)
|
||||
|
||||
continue
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if record == 0 && block == 0 {
|
||||
if err := formatting.PrintCSV(formatting.TARHeaderCSV); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := formatting.PrintCSV(formatting.GetTARHeaderAsCSV(record, block, hdr)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := io.Copy(ioutil.Discard, tr); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
currAndSize := int64(counter.BytesRead)
|
||||
|
||||
nextTotalBlocks := math.Ceil(float64(curr+(currAndSize-curr)) / float64(controllers.BlockSize))
|
||||
record = int64(nextTotalBlocks) / int64(viper.GetInt(recordSizeFlag))
|
||||
block = int64(nextTotalBlocks) - (record * int64(viper.GetInt(recordSizeFlag)))
|
||||
|
||||
if block > int64(viper.GetInt(recordSizeFlag)) {
|
||||
record++
|
||||
block = 0
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if hdr == nil {
|
||||
// EOF
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
if err := decryptHeader(hdr, encryptionFormat, privkey); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if record == 0 && block == 0 {
|
||||
if err := formatting.PrintCSV(formatting.TARHeaderCSV); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := formatting.PrintCSV(formatting.GetTARHeaderAsCSV(record, block, hdr)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
curr, err := f.Seek(0, io.SeekCurrent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := io.Copy(ioutil.Discard, tr); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
currAndSize, err := f.Seek(0, io.SeekCurrent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nextTotalBlocks := math.Ceil(float64(curr+(currAndSize-curr)) / float64(controllers.BlockSize))
|
||||
record = int64(nextTotalBlocks) / int64(recordSize)
|
||||
block = int64(nextTotalBlocks) - (record * int64(recordSize))
|
||||
|
||||
if block > int64(recordSize) {
|
||||
record++
|
||||
block = 0
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Seek to record
|
||||
if err := controllers.SeekToRecordOnTape(f, int32(record)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
// Seek to block
|
||||
br := bufio.NewReaderSize(f, controllers.BlockSize*recordSize)
|
||||
if _, err := br.Read(make([]byte, block*controllers.BlockSize)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
record := int64(record)
|
||||
block := int64(block)
|
||||
|
||||
curr := int64((recordSize * controllers.BlockSize * int(record)) + (int(block) * controllers.BlockSize))
|
||||
counter := &counters.CounterReader{Reader: br, BytesRead: int(curr)}
|
||||
|
||||
tr := tar.NewReader(counter)
|
||||
for {
|
||||
hdr, err := tr.Next()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
if err := controllers.GoToNextFileOnTape(f); err != nil {
|
||||
// EOD
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
record, err = controllers.GetCurrentRecordFromTape(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
block = 0
|
||||
|
||||
br = bufio.NewReaderSize(f, controllers.BlockSize*recordSize)
|
||||
curr := int64(int64(recordSize) * controllers.BlockSize * record)
|
||||
counter := &counters.CounterReader{Reader: br, BytesRead: int(curr)}
|
||||
tr = tar.NewReader(counter)
|
||||
|
||||
continue
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := decryptHeader(hdr, encryptionFormat, privkey); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if record == 0 && block == 0 {
|
||||
if err := formatting.PrintCSV(formatting.TARHeaderCSV); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := formatting.PrintCSV(formatting.GetTARHeaderAsCSV(record, block, hdr)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := io.Copy(ioutil.Discard, tr); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
currAndSize := int64(counter.BytesRead)
|
||||
|
||||
nextTotalBlocks := math.Ceil(float64(curr+(currAndSize-curr)) / float64(controllers.BlockSize))
|
||||
record = int64(nextTotalBlocks) / int64(recordSize)
|
||||
block = int64(nextTotalBlocks) - (record * int64(recordSize))
|
||||
|
||||
if block > int64(recordSize) {
|
||||
record++
|
||||
block = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
recoveryQueryCmd.PersistentFlags().IntP(recordSizeFlag, "z", 20, "Amount of 512-bit blocks per record")
|
||||
recoveryQueryCmd.PersistentFlags().IntP(recordFlag, "r", 0, "Record to seek too before counting")
|
||||
recoveryQueryCmd.PersistentFlags().IntP(recordFlag, "k", 0, "Record to seek too before counting")
|
||||
recoveryQueryCmd.PersistentFlags().IntP(blockFlag, "b", 0, "Block in record to seek too before counting")
|
||||
recoveryQueryCmd.PersistentFlags().StringP(identityFlag, "i", "", "Path to private key of recipient that has been encrypted for")
|
||||
|
||||
viper.AutomaticEnv()
|
||||
|
||||
|
||||
@@ -33,8 +33,8 @@ var restoreCmd = &cobra.Command{
|
||||
}
|
||||
|
||||
if viper.GetString(encryptionFlag) != encryptionFormatNoneKey {
|
||||
if _, err := os.Stat(viper.GetString(keyFlag)); err != nil {
|
||||
return errKeyNotAccessible
|
||||
if _, err := os.Stat(viper.GetString(identityFlag)); err != nil {
|
||||
return errIdentityNotAccessible
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ var restoreCmd = &cobra.Command{
|
||||
|
||||
privkey := []byte{}
|
||||
if viper.GetString(encryptionFlag) != encryptionFormatNoneKey {
|
||||
p, err := ioutil.ReadFile(viper.GetString(keyFlag))
|
||||
p, err := ioutil.ReadFile(viper.GetString(identityFlag))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -145,7 +145,7 @@ func init() {
|
||||
restoreCmd.PersistentFlags().StringP(srcFlag, "s", "", "File or directory to restore")
|
||||
restoreCmd.PersistentFlags().StringP(dstFlag, "d", "", "File or directory restore to (archived name by default)")
|
||||
restoreCmd.PersistentFlags().BoolP(flattenFlag, "f", false, "Ignore the folder hierarchy on the tape or tar file")
|
||||
restoreCmd.PersistentFlags().StringP(keyFlag, "k", "", "Path to private key of recipient that has been encrypted for")
|
||||
restoreCmd.PersistentFlags().StringP(identityFlag, "i", "", "Path to private key of recipient that has been encrypted for")
|
||||
|
||||
viper.AutomaticEnv()
|
||||
|
||||
|
||||
@@ -36,8 +36,12 @@ var updateCmd = &cobra.Command{
|
||||
}
|
||||
|
||||
if viper.GetString(encryptionFlag) != encryptionFormatNoneKey {
|
||||
if _, err := os.Stat(viper.GetString(keyFlag)); err != nil {
|
||||
return errKeyNotAccessible
|
||||
if _, err := os.Stat(viper.GetString(recipientFlag)); err != nil {
|
||||
return errRecipientNotAccessible
|
||||
}
|
||||
|
||||
if _, err := os.Stat(viper.GetString(identityFlag)); err != nil {
|
||||
return errIdentityNotAccessible
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,13 +67,19 @@ var updateCmd = &cobra.Command{
|
||||
}
|
||||
|
||||
pubkey := []byte{}
|
||||
privkey := []byte{}
|
||||
if viper.GetString(encryptionFlag) != encryptionFormatNoneKey {
|
||||
p, err := ioutil.ReadFile(viper.GetString(keyFlag))
|
||||
p, err := ioutil.ReadFile(viper.GetString(recipientFlag))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pubkey = p
|
||||
|
||||
privkey, err = ioutil.ReadFile(viper.GetString(identityFlag))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := update(
|
||||
@@ -94,6 +104,7 @@ var updateCmd = &cobra.Command{
|
||||
false,
|
||||
viper.GetString(compressionFlag),
|
||||
viper.GetString(encryptionFlag),
|
||||
privkey,
|
||||
)
|
||||
},
|
||||
}
|
||||
@@ -226,6 +237,10 @@ func update(
|
||||
return err
|
||||
}
|
||||
|
||||
if err := encryptHeader(hdr, encryptionFormat, pubkey); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := tw.WriteHeader(hdr); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -289,6 +304,10 @@ func update(
|
||||
return err
|
||||
}
|
||||
|
||||
if err := encryptHeader(hdr, encryptionFormat, pubkey); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := tw.WriteHeader(hdr); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -305,7 +324,8 @@ func init() {
|
||||
updateCmd.PersistentFlags().StringP(srcFlag, "s", "", "Path of the file or directory to update")
|
||||
updateCmd.PersistentFlags().BoolP(overwriteFlag, "o", false, "Replace the content on the tape or tar file")
|
||||
updateCmd.PersistentFlags().StringP(compressionLevelFlag, "l", compressionLevelBalanced, fmt.Sprintf("Compression level to use (default %v, available are %v)", compressionLevelBalanced, knownCompressionLevels))
|
||||
updateCmd.PersistentFlags().StringP(keyFlag, "k", "", "Path to public key of recipient to encrypt for")
|
||||
updateCmd.PersistentFlags().StringP(recipientFlag, "r", "", "Path to public key of recipient to encrypt for")
|
||||
updateCmd.PersistentFlags().StringP(identityFlag, "i", "", "Path to private key of recipient that has been encrypted for")
|
||||
|
||||
viper.AutomaticEnv()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user