refactor: Use explicit reader/writer instead of filepath for drive
This commit is contained in:
@@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/pojntfx/stfs/pkg/config"
|
"github.com/pojntfx/stfs/pkg/config"
|
||||||
"github.com/pojntfx/stfs/pkg/operations"
|
"github.com/pojntfx/stfs/pkg/operations"
|
||||||
"github.com/pojntfx/stfs/pkg/recovery"
|
"github.com/pojntfx/stfs/pkg/recovery"
|
||||||
|
"github.com/pojntfx/stfs/pkg/tape"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
@@ -30,7 +31,7 @@ var archiveCmd = &cobra.Command{
|
|||||||
Use: "archive",
|
Use: "archive",
|
||||||
Aliases: []string{"arc", "a", "c"},
|
Aliases: []string{"arc", "a", "c"},
|
||||||
Short: "Archive a file or directory to tape or tar file",
|
Short: "Archive a file or directory to tape or tar file",
|
||||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil {
|
if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -83,10 +84,27 @@ var archiveCmd = &cobra.Command{
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
writer, writerIsRegular, err := tape.OpenTapeWriteOnly(
|
||||||
|
viper.GetString(driveFlag),
|
||||||
|
viper.GetInt(recordSizeFlag),
|
||||||
|
viper.GetBool(overwriteFlag),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer writer.Close()
|
||||||
|
reader, readerIsRegular, err := tape.OpenTapeReadOnly(
|
||||||
|
viper.GetString(driveFlag),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer reader.Close()
|
||||||
|
|
||||||
hdrs, err := operations.Archive(
|
hdrs, err := operations.Archive(
|
||||||
config.StateConfig{
|
config.DriveWriterConfig{
|
||||||
Drive: viper.GetString(driveFlag),
|
Drive: writer,
|
||||||
Metadata: viper.GetString(metadataFlag),
|
DriveIsRegular: writerIsRegular,
|
||||||
},
|
},
|
||||||
config.PipeConfig{
|
config.PipeConfig{
|
||||||
Compression: viper.GetString(compressionFlag),
|
Compression: viper.GetString(compressionFlag),
|
||||||
@@ -101,7 +119,6 @@ var archiveCmd = &cobra.Command{
|
|||||||
|
|
||||||
viper.GetInt(recordSizeFlag),
|
viper.GetInt(recordSizeFlag),
|
||||||
viper.GetString(fromFlag),
|
viper.GetString(fromFlag),
|
||||||
viper.GetBool(overwriteFlag),
|
|
||||||
viper.GetString(compressionLevelFlag),
|
viper.GetString(compressionLevelFlag),
|
||||||
|
|
||||||
logging.NewLogger().PrintHeader,
|
logging.NewLogger().PrintHeader,
|
||||||
@@ -110,9 +127,21 @@ var archiveCmd = &cobra.Command{
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
index := 1 // Ignore the first header, which is the last header which we already indexed
|
||||||
|
if viper.GetBool(overwriteFlag) {
|
||||||
|
index = 0 // If we are starting fresh, index from start
|
||||||
|
}
|
||||||
|
|
||||||
return recovery.Index(
|
return recovery.Index(
|
||||||
config.StateConfig{
|
config.DriveReaderConfig{
|
||||||
Drive: viper.GetString(driveFlag),
|
Drive: reader,
|
||||||
|
DriveIsRegular: readerIsRegular,
|
||||||
|
},
|
||||||
|
config.DriveConfig{
|
||||||
|
Drive: reader,
|
||||||
|
DriveIsRegular: readerIsRegular,
|
||||||
|
},
|
||||||
|
config.MetadataConfig{
|
||||||
Metadata: viper.GetString(metadataFlag),
|
Metadata: viper.GetString(metadataFlag),
|
||||||
},
|
},
|
||||||
config.PipeConfig{
|
config.PipeConfig{
|
||||||
@@ -130,7 +159,7 @@ var archiveCmd = &cobra.Command{
|
|||||||
int(lastIndexedRecord),
|
int(lastIndexedRecord),
|
||||||
int(lastIndexedBlock),
|
int(lastIndexedBlock),
|
||||||
viper.GetBool(overwriteFlag),
|
viper.GetBool(overwriteFlag),
|
||||||
1, // Ignore the first header, which is the last header which we already indexed
|
index,
|
||||||
|
|
||||||
func(hdr *tar.Header, i int) error {
|
func(hdr *tar.Header, i int) error {
|
||||||
if len(hdrs) <= i {
|
if len(hdrs) <= i {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"github.com/pojntfx/stfs/internal/logging"
|
"github.com/pojntfx/stfs/internal/logging"
|
||||||
"github.com/pojntfx/stfs/pkg/config"
|
"github.com/pojntfx/stfs/pkg/config"
|
||||||
"github.com/pojntfx/stfs/pkg/operations"
|
"github.com/pojntfx/stfs/pkg/operations"
|
||||||
|
"github.com/pojntfx/stfs/pkg/tape"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
@@ -17,7 +18,7 @@ var deleteCmd = &cobra.Command{
|
|||||||
Use: "delete",
|
Use: "delete",
|
||||||
Aliases: []string{"del", "d", "rm"},
|
Aliases: []string{"del", "d", "rm"},
|
||||||
Short: "Delete a file or directory from tape or tar file",
|
Short: "Delete a file or directory from tape or tar file",
|
||||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil {
|
if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -49,9 +50,37 @@ var deleteCmd = &cobra.Command{
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
writer, writerIsRegular, err := tape.OpenTapeWriteOnly(
|
||||||
|
viper.GetString(driveFlag),
|
||||||
|
viper.GetInt(recordSizeFlag),
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer writer.Close()
|
||||||
|
reader, readerIsRegular, err := tape.OpenTapeReadOnly(
|
||||||
|
viper.GetString(driveFlag),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer reader.Close()
|
||||||
|
|
||||||
return operations.Delete(
|
return operations.Delete(
|
||||||
config.StateConfig{
|
config.DriveWriterConfig{
|
||||||
Drive: viper.GetString(driveFlag),
|
Drive: writer,
|
||||||
|
DriveIsRegular: writerIsRegular,
|
||||||
|
},
|
||||||
|
config.DriveReaderConfig{
|
||||||
|
Drive: reader,
|
||||||
|
DriveIsRegular: readerIsRegular,
|
||||||
|
},
|
||||||
|
config.DriveConfig{
|
||||||
|
Drive: reader,
|
||||||
|
DriveIsRegular: readerIsRegular,
|
||||||
|
},
|
||||||
|
config.MetadataConfig{
|
||||||
Metadata: viper.GetString(metadataFlag),
|
Metadata: viper.GetString(metadataFlag),
|
||||||
},
|
},
|
||||||
config.PipeConfig{
|
config.PipeConfig{
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/pojntfx/stfs/pkg/config"
|
||||||
"github.com/pojntfx/stfs/pkg/hardware"
|
"github.com/pojntfx/stfs/pkg/hardware"
|
||||||
|
"github.com/pojntfx/stfs/pkg/tape"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
@@ -14,9 +16,18 @@ var driveEjectCmd = &cobra.Command{
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reader, readerIsRegular, err := tape.OpenTapeReadOnly(
|
||||||
|
viper.GetString(driveFlag),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer reader.Close()
|
||||||
|
|
||||||
return hardware.Eject(
|
return hardware.Eject(
|
||||||
hardware.DriveConfig{
|
config.DriveConfig{
|
||||||
Drive: viper.GetString(driveFlag),
|
Drive: reader,
|
||||||
|
DriveIsRegular: readerIsRegular,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/pojntfx/stfs/pkg/config"
|
||||||
"github.com/pojntfx/stfs/pkg/hardware"
|
"github.com/pojntfx/stfs/pkg/hardware"
|
||||||
|
"github.com/pojntfx/stfs/pkg/tape"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
@@ -16,9 +18,18 @@ var driveTellCmd = &cobra.Command{
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reader, readerIsRegular, err := tape.OpenTapeReadOnly(
|
||||||
|
viper.GetString(driveFlag),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer reader.Close()
|
||||||
|
|
||||||
currentRecord, err := hardware.Tell(
|
currentRecord, err := hardware.Tell(
|
||||||
hardware.DriveConfig{
|
config.DriveConfig{
|
||||||
Drive: viper.GetString(driveFlag),
|
Drive: reader,
|
||||||
|
DriveIsRegular: readerIsRegular,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pojntfx/stfs/internal/logging"
|
"github.com/pojntfx/stfs/internal/logging"
|
||||||
|
"github.com/pojntfx/stfs/pkg/config"
|
||||||
"github.com/pojntfx/stfs/pkg/inventory"
|
"github.com/pojntfx/stfs/pkg/inventory"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
@@ -21,7 +22,7 @@ var findCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if _, err := inventory.Find(
|
if _, err := inventory.Find(
|
||||||
inventory.MetadataConfig{
|
config.MetadataConfig{
|
||||||
Metadata: viper.GetString(metadataFlag),
|
Metadata: viper.GetString(metadataFlag),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ var keygenCmd = &cobra.Command{
|
|||||||
Encryption: viper.GetString(encryptionFlag),
|
Encryption: viper.GetString(encryptionFlag),
|
||||||
Signature: viper.GetString(signatureFlag),
|
Signature: viper.GetString(signatureFlag),
|
||||||
},
|
},
|
||||||
utility.PasswordConfig{
|
config.PasswordConfig{
|
||||||
Password: viper.GetString(passwordFlag),
|
Password: viper.GetString(passwordFlag),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pojntfx/stfs/internal/logging"
|
"github.com/pojntfx/stfs/internal/logging"
|
||||||
|
"github.com/pojntfx/stfs/pkg/config"
|
||||||
"github.com/pojntfx/stfs/pkg/inventory"
|
"github.com/pojntfx/stfs/pkg/inventory"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
@@ -17,7 +18,7 @@ var listCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if _, err := inventory.List(
|
if _, err := inventory.List(
|
||||||
inventory.MetadataConfig{
|
config.MetadataConfig{
|
||||||
Metadata: viper.GetString(metadataFlag),
|
Metadata: viper.GetString(metadataFlag),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"github.com/pojntfx/stfs/internal/logging"
|
"github.com/pojntfx/stfs/internal/logging"
|
||||||
"github.com/pojntfx/stfs/pkg/config"
|
"github.com/pojntfx/stfs/pkg/config"
|
||||||
"github.com/pojntfx/stfs/pkg/operations"
|
"github.com/pojntfx/stfs/pkg/operations"
|
||||||
|
"github.com/pojntfx/stfs/pkg/tape"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
@@ -13,7 +14,7 @@ var moveCmd = &cobra.Command{
|
|||||||
Use: "move",
|
Use: "move",
|
||||||
Aliases: []string{"mov", "m", "mv"},
|
Aliases: []string{"mov", "m", "mv"},
|
||||||
Short: "Move a file or directory on tape or tar file",
|
Short: "Move a file or directory on tape or tar file",
|
||||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil {
|
if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -45,9 +46,37 @@ var moveCmd = &cobra.Command{
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
writer, writerIsRegular, err := tape.OpenTapeWriteOnly(
|
||||||
|
viper.GetString(driveFlag),
|
||||||
|
viper.GetInt(recordSizeFlag),
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer writer.Close()
|
||||||
|
reader, readerIsRegular, err := tape.OpenTapeReadOnly(
|
||||||
|
viper.GetString(driveFlag),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer reader.Close()
|
||||||
|
|
||||||
return operations.Move(
|
return operations.Move(
|
||||||
config.StateConfig{
|
config.DriveWriterConfig{
|
||||||
Drive: viper.GetString(driveFlag),
|
Drive: writer,
|
||||||
|
DriveIsRegular: writerIsRegular,
|
||||||
|
},
|
||||||
|
config.DriveConfig{
|
||||||
|
Drive: reader,
|
||||||
|
DriveIsRegular: readerIsRegular,
|
||||||
|
},
|
||||||
|
config.DriveReaderConfig{
|
||||||
|
Drive: reader,
|
||||||
|
DriveIsRegular: readerIsRegular,
|
||||||
|
},
|
||||||
|
config.MetadataConfig{
|
||||||
Metadata: viper.GetString(metadataFlag),
|
Metadata: viper.GetString(metadataFlag),
|
||||||
},
|
},
|
||||||
config.PipeConfig{
|
config.PipeConfig{
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import (
|
|||||||
"github.com/pojntfx/stfs/internal/keys"
|
"github.com/pojntfx/stfs/internal/keys"
|
||||||
"github.com/pojntfx/stfs/internal/logging"
|
"github.com/pojntfx/stfs/internal/logging"
|
||||||
"github.com/pojntfx/stfs/pkg/config"
|
"github.com/pojntfx/stfs/pkg/config"
|
||||||
"github.com/pojntfx/stfs/pkg/hardware"
|
|
||||||
"github.com/pojntfx/stfs/pkg/recovery"
|
"github.com/pojntfx/stfs/pkg/recovery"
|
||||||
|
"github.com/pojntfx/stfs/pkg/tape"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
@@ -20,7 +20,7 @@ const (
|
|||||||
var recoveryFetchCmd = &cobra.Command{
|
var recoveryFetchCmd = &cobra.Command{
|
||||||
Use: "fetch",
|
Use: "fetch",
|
||||||
Short: "Fetch a file or directory from tape or tar file by record and block without the index",
|
Short: "Fetch a file or directory from tape or tar file by record and block without the index",
|
||||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil {
|
if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -52,9 +52,22 @@ var recoveryFetchCmd = &cobra.Command{
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reader, readerIsRegular, err := tape.OpenTapeReadOnly(
|
||||||
|
viper.GetString(driveFlag),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer reader.Close()
|
||||||
|
|
||||||
return recovery.Fetch(
|
return recovery.Fetch(
|
||||||
hardware.DriveConfig{
|
config.DriveReaderConfig{
|
||||||
Drive: viper.GetString(driveFlag),
|
Drive: reader,
|
||||||
|
DriveIsRegular: readerIsRegular,
|
||||||
|
},
|
||||||
|
config.DriveConfig{
|
||||||
|
Drive: reader,
|
||||||
|
DriveIsRegular: readerIsRegular,
|
||||||
},
|
},
|
||||||
config.PipeConfig{
|
config.PipeConfig{
|
||||||
Compression: viper.GetString(compressionFlag),
|
Compression: viper.GetString(compressionFlag),
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/pojntfx/stfs/internal/signature"
|
"github.com/pojntfx/stfs/internal/signature"
|
||||||
"github.com/pojntfx/stfs/pkg/config"
|
"github.com/pojntfx/stfs/pkg/config"
|
||||||
"github.com/pojntfx/stfs/pkg/recovery"
|
"github.com/pojntfx/stfs/pkg/recovery"
|
||||||
|
"github.com/pojntfx/stfs/pkg/tape"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
@@ -16,7 +17,7 @@ import (
|
|||||||
var recoveryIndexCmd = &cobra.Command{
|
var recoveryIndexCmd = &cobra.Command{
|
||||||
Use: "index",
|
Use: "index",
|
||||||
Short: "Index contents of tape or tar file",
|
Short: "Index contents of tape or tar file",
|
||||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil {
|
if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -48,9 +49,24 @@ var recoveryIndexCmd = &cobra.Command{
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reader, readerIsRegular, err := tape.OpenTapeReadOnly(
|
||||||
|
viper.GetString(driveFlag),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer reader.Close()
|
||||||
|
|
||||||
return recovery.Index(
|
return recovery.Index(
|
||||||
config.StateConfig{
|
config.DriveReaderConfig{
|
||||||
Drive: viper.GetString(driveFlag),
|
Drive: reader,
|
||||||
|
DriveIsRegular: readerIsRegular,
|
||||||
|
},
|
||||||
|
config.DriveConfig{
|
||||||
|
Drive: reader,
|
||||||
|
DriveIsRegular: readerIsRegular,
|
||||||
|
},
|
||||||
|
config.MetadataConfig{
|
||||||
Metadata: viper.GetString(metadataFlag),
|
Metadata: viper.GetString(metadataFlag),
|
||||||
},
|
},
|
||||||
config.PipeConfig{
|
config.PipeConfig{
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import (
|
|||||||
"github.com/pojntfx/stfs/internal/keys"
|
"github.com/pojntfx/stfs/internal/keys"
|
||||||
"github.com/pojntfx/stfs/internal/logging"
|
"github.com/pojntfx/stfs/internal/logging"
|
||||||
"github.com/pojntfx/stfs/pkg/config"
|
"github.com/pojntfx/stfs/pkg/config"
|
||||||
"github.com/pojntfx/stfs/pkg/hardware"
|
|
||||||
"github.com/pojntfx/stfs/pkg/recovery"
|
"github.com/pojntfx/stfs/pkg/recovery"
|
||||||
|
"github.com/pojntfx/stfs/pkg/tape"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
@@ -13,7 +13,7 @@ import (
|
|||||||
var recoveryQueryCmd = &cobra.Command{
|
var recoveryQueryCmd = &cobra.Command{
|
||||||
Use: "query",
|
Use: "query",
|
||||||
Short: "Query contents of tape or tar file without the index",
|
Short: "Query contents of tape or tar file without the index",
|
||||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil {
|
if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -45,9 +45,18 @@ var recoveryQueryCmd = &cobra.Command{
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reader, readerIsRegular, err := tape.OpenTapeReadOnly(
|
||||||
|
viper.GetString(driveFlag),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer reader.Close()
|
||||||
|
|
||||||
if _, err := recovery.Query(
|
if _, err := recovery.Query(
|
||||||
hardware.DriveConfig{
|
config.DriveConfig{
|
||||||
Drive: viper.GetString(driveFlag),
|
Drive: reader,
|
||||||
|
DriveIsRegular: readerIsRegular,
|
||||||
},
|
},
|
||||||
config.PipeConfig{
|
config.PipeConfig{
|
||||||
Compression: viper.GetString(compressionFlag),
|
Compression: viper.GetString(compressionFlag),
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"github.com/pojntfx/stfs/internal/logging"
|
"github.com/pojntfx/stfs/internal/logging"
|
||||||
"github.com/pojntfx/stfs/pkg/config"
|
"github.com/pojntfx/stfs/pkg/config"
|
||||||
"github.com/pojntfx/stfs/pkg/operations"
|
"github.com/pojntfx/stfs/pkg/operations"
|
||||||
|
"github.com/pojntfx/stfs/pkg/tape"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
@@ -17,7 +18,7 @@ var restoreCmd = &cobra.Command{
|
|||||||
Use: "restore",
|
Use: "restore",
|
||||||
Aliases: []string{"res", "r", "x"},
|
Aliases: []string{"res", "r", "x"},
|
||||||
Short: "Restore a file or directory from tape or tar file",
|
Short: "Restore a file or directory from tape or tar file",
|
||||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil {
|
if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -49,9 +50,24 @@ var restoreCmd = &cobra.Command{
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reader, readerIsRegular, err := tape.OpenTapeReadOnly(
|
||||||
|
viper.GetString(driveFlag),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer reader.Close()
|
||||||
|
|
||||||
return operations.Restore(
|
return operations.Restore(
|
||||||
config.StateConfig{
|
config.DriveReaderConfig{
|
||||||
Drive: viper.GetString(driveFlag),
|
Drive: reader,
|
||||||
|
DriveIsRegular: readerIsRegular,
|
||||||
|
},
|
||||||
|
config.DriveConfig{
|
||||||
|
Drive: reader,
|
||||||
|
DriveIsRegular: readerIsRegular,
|
||||||
|
},
|
||||||
|
config.MetadataConfig{
|
||||||
Metadata: viper.GetString(metadataFlag),
|
Metadata: viper.GetString(metadataFlag),
|
||||||
},
|
},
|
||||||
config.PipeConfig{
|
config.PipeConfig{
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/pojntfx/stfs/pkg/config"
|
"github.com/pojntfx/stfs/pkg/config"
|
||||||
"github.com/pojntfx/stfs/pkg/operations"
|
"github.com/pojntfx/stfs/pkg/operations"
|
||||||
"github.com/pojntfx/stfs/pkg/recovery"
|
"github.com/pojntfx/stfs/pkg/recovery"
|
||||||
|
"github.com/pojntfx/stfs/pkg/tape"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
@@ -20,7 +21,7 @@ var updateCmd = &cobra.Command{
|
|||||||
Use: "update",
|
Use: "update",
|
||||||
Aliases: []string{"upd", "u"},
|
Aliases: []string{"upd", "u"},
|
||||||
Short: "Update a file or directory's content and metadata on tape or tar file",
|
Short: "Update a file or directory's content and metadata on tape or tar file",
|
||||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil {
|
if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -66,10 +67,27 @@ var updateCmd = &cobra.Command{
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
writer, writerIsRegular, err := tape.OpenTapeWriteOnly(
|
||||||
|
viper.GetString(driveFlag),
|
||||||
|
viper.GetInt(recordSizeFlag),
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer writer.Close()
|
||||||
|
reader, readerIsRegular, err := tape.OpenTapeReadOnly(
|
||||||
|
viper.GetString(driveFlag),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer reader.Close()
|
||||||
|
|
||||||
hdrs, err := operations.Update(
|
hdrs, err := operations.Update(
|
||||||
config.StateConfig{
|
config.DriveWriterConfig{
|
||||||
Drive: viper.GetString(driveFlag),
|
Drive: writer,
|
||||||
Metadata: viper.GetString(metadataFlag),
|
DriveIsRegular: writerIsRegular,
|
||||||
},
|
},
|
||||||
config.PipeConfig{
|
config.PipeConfig{
|
||||||
Compression: viper.GetString(compressionFlag),
|
Compression: viper.GetString(compressionFlag),
|
||||||
@@ -94,8 +112,15 @@ var updateCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
return recovery.Index(
|
return recovery.Index(
|
||||||
config.StateConfig{
|
config.DriveReaderConfig{
|
||||||
Drive: viper.GetString(driveFlag),
|
Drive: reader,
|
||||||
|
DriveIsRegular: readerIsRegular,
|
||||||
|
},
|
||||||
|
config.DriveConfig{
|
||||||
|
Drive: reader,
|
||||||
|
DriveIsRegular: readerIsRegular,
|
||||||
|
},
|
||||||
|
config.MetadataConfig{
|
||||||
Metadata: viper.GetString(metadataFlag),
|
Metadata: viper.GetString(metadataFlag),
|
||||||
},
|
},
|
||||||
config.PipeConfig{
|
config.PipeConfig{
|
||||||
|
|||||||
@@ -1,79 +0,0 @@
|
|||||||
package tape
|
|
||||||
|
|
||||||
import (
|
|
||||||
"archive/tar"
|
|
||||||
"bufio"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/pojntfx/stfs/internal/ioext"
|
|
||||||
"github.com/pojntfx/stfs/internal/mtio"
|
|
||||||
)
|
|
||||||
|
|
||||||
func OpenTapeWriteOnly(drive string, recordSize int, overwrite bool) (tw *tar.Writer, isRegular bool, cleanup func(dirty *bool) error, err error) {
|
|
||||||
stat, err := os.Stat(drive)
|
|
||||||
if err == nil {
|
|
||||||
isRegular = stat.Mode().IsRegular()
|
|
||||||
} else {
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
isRegular = true
|
|
||||||
} else {
|
|
||||||
return nil, false, nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var f *os.File
|
|
||||||
if isRegular {
|
|
||||||
f, err = os.OpenFile(drive, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
|
|
||||||
if err != nil {
|
|
||||||
return nil, false, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// No need to go to end manually due to `os.O_APPEND`
|
|
||||||
} else {
|
|
||||||
f, err = os.OpenFile(drive, os.O_APPEND|os.O_WRONLY, os.ModeCharDevice)
|
|
||||||
if err != nil {
|
|
||||||
return nil, false, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if !overwrite {
|
|
||||||
// Go to end of tape
|
|
||||||
if err := mtio.GoToEndOfTape(f); err != nil {
|
|
||||||
return nil, false, nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var bw *bufio.Writer
|
|
||||||
var counter *ioext.CounterWriter
|
|
||||||
if isRegular {
|
|
||||||
tw = tar.NewWriter(f)
|
|
||||||
} else {
|
|
||||||
bw = bufio.NewWriterSize(f, mtio.BlockSize*recordSize)
|
|
||||||
counter = &ioext.CounterWriter{Writer: bw, BytesRead: 0}
|
|
||||||
tw = tar.NewWriter(counter)
|
|
||||||
}
|
|
||||||
|
|
||||||
return tw, isRegular, func(dirty *bool) error {
|
|
||||||
// Only write the trailer if we wrote to the archive
|
|
||||||
if *dirty {
|
|
||||||
if err := tw.Close(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if !isRegular {
|
|
||||||
if mtio.BlockSize*recordSize-counter.BytesRead > 0 {
|
|
||||||
// Fill the rest of the record with zeros
|
|
||||||
if _, err := bw.Write(make([]byte, mtio.BlockSize*recordSize-counter.BytesRead)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := bw.Flush(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return f.Close()
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
46
internal/tarext/write.go
Normal file
46
internal/tarext/write.go
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
package tarext
|
||||||
|
|
||||||
|
import (
|
||||||
|
"archive/tar"
|
||||||
|
"bufio"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/pojntfx/stfs/internal/ioext"
|
||||||
|
"github.com/pojntfx/stfs/internal/mtio"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewTapeWriter(f io.Writer, isRegular bool, recordSize int) (tw *tar.Writer, cleanup func(dirty *bool) error, err error) {
|
||||||
|
var bw *bufio.Writer
|
||||||
|
var counter *ioext.CounterWriter
|
||||||
|
if isRegular {
|
||||||
|
tw = tar.NewWriter(f)
|
||||||
|
} else {
|
||||||
|
bw = bufio.NewWriterSize(f, mtio.BlockSize*recordSize)
|
||||||
|
counter = &ioext.CounterWriter{Writer: bw, BytesRead: 0}
|
||||||
|
tw = tar.NewWriter(counter)
|
||||||
|
}
|
||||||
|
|
||||||
|
return tw, func(dirty *bool) error {
|
||||||
|
// Only write the trailer if we wrote to the archive
|
||||||
|
if *dirty {
|
||||||
|
if err := tw.Close(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isRegular {
|
||||||
|
if mtio.BlockSize*recordSize-counter.BytesRead > 0 {
|
||||||
|
// Fill the rest of the record with zeros
|
||||||
|
if _, err := bw.Write(make([]byte, mtio.BlockSize*recordSize-counter.BytesRead)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := bw.Flush(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
@@ -1,7 +1,26 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
type StateConfig struct {
|
import (
|
||||||
Drive string
|
"io"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DriveReaderConfig struct {
|
||||||
|
Drive io.ReadSeeker
|
||||||
|
DriveIsRegular bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type DriveWriterConfig struct {
|
||||||
|
Drive io.Writer
|
||||||
|
DriveIsRegular bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type DriveConfig struct {
|
||||||
|
Drive *os.File
|
||||||
|
DriveIsRegular bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type MetadataConfig struct {
|
||||||
Metadata string
|
Metadata string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16,3 +35,7 @@ type CryptoConfig struct {
|
|||||||
Identity interface{}
|
Identity interface{}
|
||||||
Password string
|
Password string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PasswordConfig struct {
|
||||||
|
Password string
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
package hardware
|
|
||||||
|
|
||||||
type DriveConfig struct {
|
|
||||||
Drive string
|
|
||||||
}
|
|
||||||
@@ -1,19 +1,12 @@
|
|||||||
package hardware
|
package hardware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/pojntfx/stfs/internal/mtio"
|
"github.com/pojntfx/stfs/internal/mtio"
|
||||||
|
"github.com/pojntfx/stfs/pkg/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Eject(
|
func Eject(
|
||||||
state DriveConfig,
|
state config.DriveConfig,
|
||||||
) error {
|
) error {
|
||||||
f, err := os.OpenFile(state.Drive, os.O_RDONLY, os.ModeCharDevice)
|
return mtio.EjectTape(state.Drive)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
return mtio.EjectTape(f)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,12 @@
|
|||||||
package hardware
|
package hardware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/pojntfx/stfs/internal/mtio"
|
"github.com/pojntfx/stfs/internal/mtio"
|
||||||
|
"github.com/pojntfx/stfs/pkg/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Tell(
|
func Tell(
|
||||||
state DriveConfig,
|
state config.DriveConfig,
|
||||||
) (int64, error) {
|
) (int64, error) {
|
||||||
f, err := os.OpenFile(state.Drive, os.O_RDONLY, os.ModeCharDevice)
|
return mtio.GetCurrentRecordFromTape(state.Drive)
|
||||||
if err != nil {
|
|
||||||
return -1, err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
return mtio.GetCurrentRecordFromTape(f)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
package inventory
|
|
||||||
|
|
||||||
type MetadataConfig struct {
|
|
||||||
Metadata string
|
|
||||||
}
|
|
||||||
@@ -8,10 +8,11 @@ import (
|
|||||||
"github.com/pojntfx/stfs/internal/converters"
|
"github.com/pojntfx/stfs/internal/converters"
|
||||||
models "github.com/pojntfx/stfs/internal/db/sqlite/models/metadata"
|
models "github.com/pojntfx/stfs/internal/db/sqlite/models/metadata"
|
||||||
"github.com/pojntfx/stfs/internal/persisters"
|
"github.com/pojntfx/stfs/internal/persisters"
|
||||||
|
"github.com/pojntfx/stfs/pkg/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Find(
|
func Find(
|
||||||
state MetadataConfig,
|
state config.MetadataConfig,
|
||||||
|
|
||||||
expression string,
|
expression string,
|
||||||
|
|
||||||
|
|||||||
@@ -7,10 +7,11 @@ import (
|
|||||||
"github.com/pojntfx/stfs/internal/converters"
|
"github.com/pojntfx/stfs/internal/converters"
|
||||||
models "github.com/pojntfx/stfs/internal/db/sqlite/models/metadata"
|
models "github.com/pojntfx/stfs/internal/db/sqlite/models/metadata"
|
||||||
"github.com/pojntfx/stfs/internal/persisters"
|
"github.com/pojntfx/stfs/internal/persisters"
|
||||||
|
"github.com/pojntfx/stfs/pkg/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
func List(
|
func List(
|
||||||
state MetadataConfig,
|
state config.MetadataConfig,
|
||||||
|
|
||||||
name string,
|
name string,
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import (
|
|||||||
"github.com/pojntfx/stfs/internal/signature"
|
"github.com/pojntfx/stfs/internal/signature"
|
||||||
"github.com/pojntfx/stfs/internal/statext"
|
"github.com/pojntfx/stfs/internal/statext"
|
||||||
"github.com/pojntfx/stfs/internal/suffix"
|
"github.com/pojntfx/stfs/internal/suffix"
|
||||||
"github.com/pojntfx/stfs/internal/tape"
|
"github.com/pojntfx/stfs/internal/tarext"
|
||||||
"github.com/pojntfx/stfs/pkg/config"
|
"github.com/pojntfx/stfs/pkg/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -29,73 +29,21 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func Archive(
|
func Archive(
|
||||||
state config.StateConfig,
|
writer config.DriveWriterConfig,
|
||||||
pipes config.PipeConfig,
|
pipes config.PipeConfig,
|
||||||
crypto config.CryptoConfig,
|
crypto config.CryptoConfig,
|
||||||
|
|
||||||
recordSize int,
|
recordSize int,
|
||||||
from string,
|
from string,
|
||||||
overwrite bool,
|
|
||||||
compressionLevel string,
|
compressionLevel string,
|
||||||
|
|
||||||
onHeader func(hdr *models.Header),
|
onHeader func(hdr *models.Header),
|
||||||
) ([]*tar.Header, error) {
|
) ([]*tar.Header, error) {
|
||||||
dirty := false
|
dirty := false
|
||||||
tw, isRegular, cleanup, err := tape.OpenTapeWriteOnly(state.Drive, recordSize, overwrite)
|
tw, cleanup, err := tarext.NewTapeWriter(writer.Drive, writer.DriveIsRegular, recordSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []*tar.Header{}, err
|
return []*tar.Header{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if overwrite {
|
|
||||||
if isRegular {
|
|
||||||
if err := cleanup(&dirty); err != nil { // dirty will always be false here
|
|
||||||
return []*tar.Header{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
f, err := os.OpenFile(state.Drive, os.O_WRONLY|os.O_CREATE, 0600)
|
|
||||||
if err != nil {
|
|
||||||
return []*tar.Header{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear the file's content
|
|
||||||
if err := f.Truncate(0); err != nil {
|
|
||||||
return []*tar.Header{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := f.Close(); err != nil {
|
|
||||||
return []*tar.Header{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
tw, isRegular, cleanup, err = tape.OpenTapeWriteOnly(state.Drive, recordSize, overwrite)
|
|
||||||
if err != nil {
|
|
||||||
return []*tar.Header{}, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if err := cleanup(&dirty); err != nil { // dirty will always be false here
|
|
||||||
return []*tar.Header{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
f, err := os.OpenFile(state.Drive, os.O_WRONLY, os.ModeCharDevice)
|
|
||||||
if err != nil {
|
|
||||||
return []*tar.Header{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Seek to the start of the tape
|
|
||||||
if err := mtio.SeekToRecordOnTape(f, 0); err != nil {
|
|
||||||
return []*tar.Header{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := f.Close(); err != nil {
|
|
||||||
return []*tar.Header{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
tw, isRegular, cleanup, err = tape.OpenTapeWriteOnly(state.Drive, recordSize, overwrite)
|
|
||||||
if err != nil {
|
|
||||||
return []*tar.Header{}, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
defer cleanup(&dirty)
|
defer cleanup(&dirty)
|
||||||
|
|
||||||
headers := []*tar.Header{}
|
headers := []*tar.Header{}
|
||||||
@@ -143,7 +91,7 @@ func Archive(
|
|||||||
encryptor,
|
encryptor,
|
||||||
pipes.Compression,
|
pipes.Compression,
|
||||||
compressionLevel,
|
compressionLevel,
|
||||||
isRegular,
|
writer.DriveIsRegular,
|
||||||
recordSize,
|
recordSize,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -155,12 +103,12 @@ func Archive(
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
signer, sign, err := signature.Sign(file, isRegular, pipes.Signature, crypto.Identity)
|
signer, sign, err := signature.Sign(file, writer.DriveIsRegular, pipes.Signature, crypto.Identity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if isRegular {
|
if writer.DriveIsRegular {
|
||||||
if _, err := io.Copy(compressor, signer); err != nil {
|
if _, err := io.Copy(compressor, signer); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -219,7 +167,7 @@ func Archive(
|
|||||||
hdrToAppend := *hdr
|
hdrToAppend := *hdr
|
||||||
headers = append(headers, &hdrToAppend)
|
headers = append(headers, &hdrToAppend)
|
||||||
|
|
||||||
if err := signature.SignHeader(hdr, isRegular, pipes.Signature, crypto.Identity); err != nil {
|
if err := signature.SignHeader(hdr, writer.DriveIsRegular, pipes.Signature, crypto.Identity); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,7 +195,7 @@ func Archive(
|
|||||||
encryptor,
|
encryptor,
|
||||||
pipes.Compression,
|
pipes.Compression,
|
||||||
compressionLevel,
|
compressionLevel,
|
||||||
isRegular,
|
writer.DriveIsRegular,
|
||||||
recordSize,
|
recordSize,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -259,7 +207,7 @@ func Archive(
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if isRegular {
|
if writer.DriveIsRegular {
|
||||||
if _, err := io.Copy(compressor, file); err != nil {
|
if _, err := io.Copy(compressor, file); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,13 +10,16 @@ import (
|
|||||||
"github.com/pojntfx/stfs/internal/persisters"
|
"github.com/pojntfx/stfs/internal/persisters"
|
||||||
"github.com/pojntfx/stfs/internal/records"
|
"github.com/pojntfx/stfs/internal/records"
|
||||||
"github.com/pojntfx/stfs/internal/signature"
|
"github.com/pojntfx/stfs/internal/signature"
|
||||||
"github.com/pojntfx/stfs/internal/tape"
|
"github.com/pojntfx/stfs/internal/tarext"
|
||||||
"github.com/pojntfx/stfs/pkg/config"
|
"github.com/pojntfx/stfs/pkg/config"
|
||||||
"github.com/pojntfx/stfs/pkg/recovery"
|
"github.com/pojntfx/stfs/pkg/recovery"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Delete(
|
func Delete(
|
||||||
state config.StateConfig,
|
writer config.DriveWriterConfig,
|
||||||
|
reader config.DriveReaderConfig,
|
||||||
|
drive config.DriveConfig,
|
||||||
|
metadata config.MetadataConfig,
|
||||||
pipes config.PipeConfig,
|
pipes config.PipeConfig,
|
||||||
crypto config.CryptoConfig,
|
crypto config.CryptoConfig,
|
||||||
|
|
||||||
@@ -26,13 +29,13 @@ func Delete(
|
|||||||
onHeader func(hdr *models.Header),
|
onHeader func(hdr *models.Header),
|
||||||
) error {
|
) error {
|
||||||
dirty := false
|
dirty := false
|
||||||
tw, isRegular, cleanup, err := tape.OpenTapeWriteOnly(state.Drive, recordSize, false)
|
tw, cleanup, err := tarext.NewTapeWriter(writer.Drive, writer.DriveIsRegular, recordSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer cleanup(&dirty)
|
defer cleanup(&dirty)
|
||||||
|
|
||||||
metadataPersister := persisters.NewMetadataPersister(state.Metadata)
|
metadataPersister := persisters.NewMetadataPersister(metadata.Metadata)
|
||||||
if err := metadataPersister.Open(); err != nil {
|
if err := metadataPersister.Open(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -60,7 +63,7 @@ func Delete(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Append deletion hdrs to the tape or tar file
|
// Append deletion hdrs to the tape or tar file
|
||||||
hdrs := []*tar.Header{}
|
hdrs := []tar.Header{}
|
||||||
for _, dbhdr := range headersToDelete {
|
for _, dbhdr := range headersToDelete {
|
||||||
hdr, err := converters.DBHeaderToTarHeader(dbhdr)
|
hdr, err := converters.DBHeaderToTarHeader(dbhdr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -71,7 +74,18 @@ func Delete(
|
|||||||
hdr.PAXRecords[records.STFSRecordVersion] = records.STFSRecordVersion1
|
hdr.PAXRecords[records.STFSRecordVersion] = records.STFSRecordVersion1
|
||||||
hdr.PAXRecords[records.STFSRecordAction] = records.STFSRecordActionDelete
|
hdr.PAXRecords[records.STFSRecordAction] = records.STFSRecordActionDelete
|
||||||
|
|
||||||
if err := signature.SignHeader(hdr, isRegular, pipes.Signature, crypto.Identity); err != nil {
|
hdrs = append(hdrs, *hdr)
|
||||||
|
|
||||||
|
if onHeader != nil {
|
||||||
|
dbhdr, err := converters.TarHeaderToDBHeader(-1, -1, -1, -1, hdr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
onHeader(dbhdr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := signature.SignHeader(hdr, writer.DriveIsRegular, pipes.Signature, crypto.Identity); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,21 +98,12 @@ func Delete(
|
|||||||
}
|
}
|
||||||
|
|
||||||
dirty = true
|
dirty = true
|
||||||
|
|
||||||
if onHeader != nil {
|
|
||||||
dbhdr, err := converters.TarHeaderToDBHeader(-1, -1, -1, -1, hdr)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
onHeader(dbhdr)
|
|
||||||
}
|
|
||||||
|
|
||||||
hdrs = append(hdrs, hdr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return recovery.Index(
|
return recovery.Index(
|
||||||
state,
|
reader,
|
||||||
|
drive,
|
||||||
|
metadata,
|
||||||
pipes,
|
pipes,
|
||||||
crypto,
|
crypto,
|
||||||
|
|
||||||
@@ -113,7 +118,7 @@ func Delete(
|
|||||||
return config.ErrTarHeaderMissing
|
return config.ErrTarHeaderMissing
|
||||||
}
|
}
|
||||||
|
|
||||||
*hdr = *hdrs[i]
|
*hdr = hdrs[i]
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -11,13 +11,16 @@ import (
|
|||||||
"github.com/pojntfx/stfs/internal/persisters"
|
"github.com/pojntfx/stfs/internal/persisters"
|
||||||
"github.com/pojntfx/stfs/internal/records"
|
"github.com/pojntfx/stfs/internal/records"
|
||||||
"github.com/pojntfx/stfs/internal/signature"
|
"github.com/pojntfx/stfs/internal/signature"
|
||||||
"github.com/pojntfx/stfs/internal/tape"
|
"github.com/pojntfx/stfs/internal/tarext"
|
||||||
"github.com/pojntfx/stfs/pkg/config"
|
"github.com/pojntfx/stfs/pkg/config"
|
||||||
"github.com/pojntfx/stfs/pkg/recovery"
|
"github.com/pojntfx/stfs/pkg/recovery"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Move(
|
func Move(
|
||||||
state config.StateConfig,
|
writer config.DriveWriterConfig,
|
||||||
|
drive config.DriveConfig,
|
||||||
|
reader config.DriveReaderConfig,
|
||||||
|
metadata config.MetadataConfig,
|
||||||
pipes config.PipeConfig,
|
pipes config.PipeConfig,
|
||||||
crypto config.CryptoConfig,
|
crypto config.CryptoConfig,
|
||||||
|
|
||||||
@@ -28,13 +31,13 @@ func Move(
|
|||||||
onHeader func(hdr *models.Header),
|
onHeader func(hdr *models.Header),
|
||||||
) error {
|
) error {
|
||||||
dirty := false
|
dirty := false
|
||||||
tw, isRegular, cleanup, err := tape.OpenTapeWriteOnly(state.Drive, recordSize, false)
|
tw, cleanup, err := tarext.NewTapeWriter(writer.Drive, writer.DriveIsRegular, recordSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer cleanup(&dirty)
|
defer cleanup(&dirty)
|
||||||
|
|
||||||
metadataPersister := persisters.NewMetadataPersister(state.Metadata)
|
metadataPersister := persisters.NewMetadataPersister(metadata.Metadata)
|
||||||
if err := metadataPersister.Open(); err != nil {
|
if err := metadataPersister.Open(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -62,7 +65,7 @@ func Move(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Append move headers to the tape or tar file
|
// Append move headers to the tape or tar file
|
||||||
hdrs := []*tar.Header{}
|
hdrs := []tar.Header{}
|
||||||
for _, dbhdr := range headersToMove {
|
for _, dbhdr := range headersToMove {
|
||||||
hdr, err := converters.DBHeaderToTarHeader(dbhdr)
|
hdr, err := converters.DBHeaderToTarHeader(dbhdr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -75,7 +78,18 @@ func Move(
|
|||||||
hdr.PAXRecords[records.STFSRecordAction] = records.STFSRecordActionUpdate
|
hdr.PAXRecords[records.STFSRecordAction] = records.STFSRecordActionUpdate
|
||||||
hdr.PAXRecords[records.STFSRecordReplacesName] = dbhdr.Name
|
hdr.PAXRecords[records.STFSRecordReplacesName] = dbhdr.Name
|
||||||
|
|
||||||
if err := signature.SignHeader(hdr, isRegular, pipes.Signature, crypto.Identity); err != nil {
|
hdrs = append(hdrs, *hdr)
|
||||||
|
|
||||||
|
if onHeader != nil {
|
||||||
|
dbhdr, err := converters.TarHeaderToDBHeader(-1, -1, -1, -1, hdr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
onHeader(dbhdr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := signature.SignHeader(hdr, writer.DriveIsRegular, pipes.Signature, crypto.Identity); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,21 +102,12 @@ func Move(
|
|||||||
}
|
}
|
||||||
|
|
||||||
dirty = true
|
dirty = true
|
||||||
|
|
||||||
if onHeader != nil {
|
|
||||||
dbhdr, err := converters.TarHeaderToDBHeader(-1, -1, -1, -1, hdr)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
onHeader(dbhdr)
|
|
||||||
}
|
|
||||||
|
|
||||||
hdrs = append(hdrs, hdr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return recovery.Index(
|
return recovery.Index(
|
||||||
state,
|
reader,
|
||||||
|
drive,
|
||||||
|
metadata,
|
||||||
pipes,
|
pipes,
|
||||||
crypto,
|
crypto,
|
||||||
|
|
||||||
@@ -117,7 +122,7 @@ func Move(
|
|||||||
return config.ErrTarHeaderMissing
|
return config.ErrTarHeaderMissing
|
||||||
}
|
}
|
||||||
|
|
||||||
*hdr = *hdrs[i]
|
*hdr = hdrs[i]
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -11,12 +11,13 @@ import (
|
|||||||
models "github.com/pojntfx/stfs/internal/db/sqlite/models/metadata"
|
models "github.com/pojntfx/stfs/internal/db/sqlite/models/metadata"
|
||||||
"github.com/pojntfx/stfs/internal/persisters"
|
"github.com/pojntfx/stfs/internal/persisters"
|
||||||
"github.com/pojntfx/stfs/pkg/config"
|
"github.com/pojntfx/stfs/pkg/config"
|
||||||
"github.com/pojntfx/stfs/pkg/hardware"
|
|
||||||
"github.com/pojntfx/stfs/pkg/recovery"
|
"github.com/pojntfx/stfs/pkg/recovery"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Restore(
|
func Restore(
|
||||||
state config.StateConfig,
|
reader config.DriveReaderConfig,
|
||||||
|
drive config.DriveConfig,
|
||||||
|
metadata config.MetadataConfig,
|
||||||
pipes config.PipeConfig,
|
pipes config.PipeConfig,
|
||||||
crypto config.CryptoConfig,
|
crypto config.CryptoConfig,
|
||||||
|
|
||||||
@@ -27,7 +28,7 @@ func Restore(
|
|||||||
|
|
||||||
onHeader func(hdr *models.Header),
|
onHeader func(hdr *models.Header),
|
||||||
) error {
|
) error {
|
||||||
metadataPersister := persisters.NewMetadataPersister(state.Metadata)
|
metadataPersister := persisters.NewMetadataPersister(metadata.Metadata)
|
||||||
if err := metadataPersister.Open(); err != nil {
|
if err := metadataPersister.Open(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -78,9 +79,8 @@ func Restore(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := recovery.Fetch(
|
if err := recovery.Fetch(
|
||||||
hardware.DriveConfig{
|
reader,
|
||||||
Drive: state.Drive,
|
drive,
|
||||||
},
|
|
||||||
pipes,
|
pipes,
|
||||||
crypto,
|
crypto,
|
||||||
|
|
||||||
|
|||||||
@@ -18,12 +18,12 @@ import (
|
|||||||
"github.com/pojntfx/stfs/internal/signature"
|
"github.com/pojntfx/stfs/internal/signature"
|
||||||
"github.com/pojntfx/stfs/internal/statext"
|
"github.com/pojntfx/stfs/internal/statext"
|
||||||
"github.com/pojntfx/stfs/internal/suffix"
|
"github.com/pojntfx/stfs/internal/suffix"
|
||||||
"github.com/pojntfx/stfs/internal/tape"
|
"github.com/pojntfx/stfs/internal/tarext"
|
||||||
"github.com/pojntfx/stfs/pkg/config"
|
"github.com/pojntfx/stfs/pkg/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Update(
|
func Update(
|
||||||
state config.StateConfig,
|
writer config.DriveWriterConfig,
|
||||||
pipes config.PipeConfig,
|
pipes config.PipeConfig,
|
||||||
crypto config.CryptoConfig,
|
crypto config.CryptoConfig,
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ func Update(
|
|||||||
onHeader func(hdr *models.Header),
|
onHeader func(hdr *models.Header),
|
||||||
) ([]*tar.Header, error) {
|
) ([]*tar.Header, error) {
|
||||||
dirty := false
|
dirty := false
|
||||||
tw, isRegular, cleanup, err := tape.OpenTapeWriteOnly(state.Drive, recordSize, false)
|
tw, cleanup, err := tarext.NewTapeWriter(writer.Drive, writer.DriveIsRegular, recordSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []*tar.Header{}, err
|
return []*tar.Header{}, err
|
||||||
}
|
}
|
||||||
@@ -86,7 +86,7 @@ func Update(
|
|||||||
encryptor,
|
encryptor,
|
||||||
pipes.Compression,
|
pipes.Compression,
|
||||||
compressionLevel,
|
compressionLevel,
|
||||||
isRegular,
|
writer.DriveIsRegular,
|
||||||
recordSize,
|
recordSize,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -98,12 +98,12 @@ func Update(
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
signer, sign, err := signature.Sign(file, isRegular, pipes.Signature, crypto.Identity)
|
signer, sign, err := signature.Sign(file, writer.DriveIsRegular, pipes.Signature, crypto.Identity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if isRegular {
|
if writer.DriveIsRegular {
|
||||||
if _, err := io.Copy(compressor, signer); err != nil {
|
if _, err := io.Copy(compressor, signer); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -165,7 +165,7 @@ func Update(
|
|||||||
hdrToAppend := *hdr
|
hdrToAppend := *hdr
|
||||||
headers = append(headers, &hdrToAppend)
|
headers = append(headers, &hdrToAppend)
|
||||||
|
|
||||||
if err := signature.SignHeader(hdr, isRegular, pipes.Signature, crypto.Identity); err != nil {
|
if err := signature.SignHeader(hdr, writer.DriveIsRegular, pipes.Signature, crypto.Identity); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,7 +191,7 @@ func Update(
|
|||||||
encryptor,
|
encryptor,
|
||||||
pipes.Compression,
|
pipes.Compression,
|
||||||
compressionLevel,
|
compressionLevel,
|
||||||
isRegular,
|
writer.DriveIsRegular,
|
||||||
recordSize,
|
recordSize,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -203,7 +203,7 @@ func Update(
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if isRegular {
|
if writer.DriveIsRegular {
|
||||||
if _, err := io.Copy(compressor, file); err != nil {
|
if _, err := io.Copy(compressor, file); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -244,7 +244,7 @@ func Update(
|
|||||||
hdrToAppend := *hdr
|
hdrToAppend := *hdr
|
||||||
headers = append(headers, &hdrToAppend)
|
headers = append(headers, &hdrToAppend)
|
||||||
|
|
||||||
if err := signature.SignHeader(hdr, isRegular, pipes.Signature, crypto.Identity); err != nil {
|
if err := signature.SignHeader(hdr, writer.DriveIsRegular, pipes.Signature, crypto.Identity); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,13 +14,12 @@ import (
|
|||||||
"github.com/pojntfx/stfs/internal/mtio"
|
"github.com/pojntfx/stfs/internal/mtio"
|
||||||
"github.com/pojntfx/stfs/internal/records"
|
"github.com/pojntfx/stfs/internal/records"
|
||||||
"github.com/pojntfx/stfs/internal/signature"
|
"github.com/pojntfx/stfs/internal/signature"
|
||||||
"github.com/pojntfx/stfs/internal/tape"
|
|
||||||
"github.com/pojntfx/stfs/pkg/config"
|
"github.com/pojntfx/stfs/pkg/config"
|
||||||
"github.com/pojntfx/stfs/pkg/hardware"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Fetch(
|
func Fetch(
|
||||||
state hardware.DriveConfig,
|
reader config.DriveReaderConfig,
|
||||||
|
drive config.DriveConfig,
|
||||||
pipes config.PipeConfig,
|
pipes config.PipeConfig,
|
||||||
crypto config.CryptoConfig,
|
crypto config.CryptoConfig,
|
||||||
|
|
||||||
@@ -32,28 +31,22 @@ func Fetch(
|
|||||||
|
|
||||||
onHeader func(hdr *models.Header),
|
onHeader func(hdr *models.Header),
|
||||||
) error {
|
) error {
|
||||||
f, isRegular, err := tape.OpenTapeReadOnly(state.Drive)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
var tr *tar.Reader
|
var tr *tar.Reader
|
||||||
if isRegular {
|
if reader.DriveIsRegular {
|
||||||
// Seek to record and block
|
// Seek to record and block
|
||||||
if _, err := f.Seek(int64((recordSize*mtio.BlockSize*record)+block*mtio.BlockSize), io.SeekStart); err != nil {
|
if _, err := reader.Drive.Seek(int64((recordSize*mtio.BlockSize*record)+block*mtio.BlockSize), io.SeekStart); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
tr = tar.NewReader(f)
|
tr = tar.NewReader(reader.Drive)
|
||||||
} else {
|
} else {
|
||||||
// Seek to record
|
// Seek to record
|
||||||
if err := mtio.SeekToRecordOnTape(f, int32(record)); err != nil {
|
if err := mtio.SeekToRecordOnTape(drive.Drive, int32(record)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Seek to block
|
// Seek to block
|
||||||
br := bufio.NewReaderSize(f, mtio.BlockSize*recordSize)
|
br := bufio.NewReaderSize(drive.Drive, mtio.BlockSize*recordSize)
|
||||||
if _, err := br.Read(make([]byte, block*mtio.BlockSize)); err != nil {
|
if _, err := br.Read(make([]byte, block*mtio.BlockSize)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -70,7 +63,7 @@ func Fetch(
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := signature.VerifyHeader(hdr, isRegular, pipes.Signature, crypto.Recipient); err != nil {
|
if err := signature.VerifyHeader(hdr, drive.DriveIsRegular, pipes.Signature, crypto.Recipient); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,7 +120,7 @@ func Fetch(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
verifier, verify, err := signature.Verify(decompressor, isRegular, pipes.Signature, crypto.Recipient, sig)
|
verifier, verify, err := signature.Verify(decompressor, drive.DriveIsRegular, pipes.Signature, crypto.Recipient, sig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,13 @@ import (
|
|||||||
"github.com/pojntfx/stfs/internal/persisters"
|
"github.com/pojntfx/stfs/internal/persisters"
|
||||||
"github.com/pojntfx/stfs/internal/records"
|
"github.com/pojntfx/stfs/internal/records"
|
||||||
"github.com/pojntfx/stfs/internal/suffix"
|
"github.com/pojntfx/stfs/internal/suffix"
|
||||||
"github.com/pojntfx/stfs/internal/tape"
|
|
||||||
"github.com/pojntfx/stfs/pkg/config"
|
"github.com/pojntfx/stfs/pkg/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Index(
|
func Index(
|
||||||
state config.StateConfig,
|
reader config.DriveReaderConfig,
|
||||||
|
drive config.DriveConfig,
|
||||||
|
metadata config.MetadataConfig,
|
||||||
pipes config.PipeConfig,
|
pipes config.PipeConfig,
|
||||||
crypto config.CryptoConfig,
|
crypto config.CryptoConfig,
|
||||||
|
|
||||||
@@ -45,7 +46,7 @@ func Index(
|
|||||||
onHeader func(hdr *models.Header),
|
onHeader func(hdr *models.Header),
|
||||||
) error {
|
) error {
|
||||||
if overwrite {
|
if overwrite {
|
||||||
f, err := os.OpenFile(state.Metadata, os.O_WRONLY|os.O_CREATE, 0600)
|
f, err := os.OpenFile(metadata.Metadata, os.O_WRONLY|os.O_CREATE, 0600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -59,24 +60,18 @@ func Index(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
metadataPersister := persisters.NewMetadataPersister(state.Metadata)
|
metadataPersister := persisters.NewMetadataPersister(metadata.Metadata)
|
||||||
if err := metadataPersister.Open(); err != nil {
|
if err := metadataPersister.Open(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
f, isRegular, err := tape.OpenTapeReadOnly(state.Drive)
|
if reader.DriveIsRegular {
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
if isRegular {
|
|
||||||
// Seek to record and block
|
// Seek to record and block
|
||||||
if _, err := f.Seek(int64((recordSize*mtio.BlockSize*record)+block*mtio.BlockSize), 0); err != nil {
|
if _, err := reader.Drive.Seek(int64((recordSize*mtio.BlockSize*record)+block*mtio.BlockSize), 0); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
tr := tar.NewReader(f)
|
tr := tar.NewReader(reader.Drive)
|
||||||
|
|
||||||
record := int64(record)
|
record := int64(record)
|
||||||
block := int64(block)
|
block := int64(block)
|
||||||
@@ -86,7 +81,7 @@ func Index(
|
|||||||
hdr, err := tr.Next()
|
hdr, err := tr.Next()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
for {
|
for {
|
||||||
curr, err := f.Seek(0, io.SeekCurrent)
|
curr, err := reader.Drive.Seek(0, io.SeekCurrent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -104,11 +99,11 @@ func Index(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Seek to record and block
|
// Seek to record and block
|
||||||
if _, err := f.Seek(int64((recordSize*mtio.BlockSize*int(record))+int(block)*mtio.BlockSize), io.SeekStart); err != nil {
|
if _, err := reader.Drive.Seek(int64((recordSize*mtio.BlockSize*int(record))+int(block)*mtio.BlockSize), io.SeekStart); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
tr = tar.NewReader(f)
|
tr = tar.NewReader(reader.Drive)
|
||||||
|
|
||||||
hdr, err = tr.Next()
|
hdr, err = tr.Next()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -135,7 +130,7 @@ func Index(
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := verifyHeader(hdr, isRegular); err != nil {
|
if err := verifyHeader(hdr, reader.DriveIsRegular); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +139,7 @@ func Index(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
curr, err := f.Seek(0, io.SeekCurrent)
|
curr, err := reader.Drive.Seek(0, io.SeekCurrent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -153,7 +148,7 @@ func Index(
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
currAndSize, err := f.Seek(0, io.SeekCurrent)
|
currAndSize, err := reader.Drive.Seek(0, io.SeekCurrent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -171,12 +166,12 @@ func Index(
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Seek to record
|
// Seek to record
|
||||||
if err := mtio.SeekToRecordOnTape(f, int32(record)); err != nil {
|
if err := mtio.SeekToRecordOnTape(drive.Drive, int32(record)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Seek to block
|
// Seek to block
|
||||||
br := bufio.NewReaderSize(f, mtio.BlockSize*recordSize)
|
br := bufio.NewReaderSize(drive.Drive, mtio.BlockSize*recordSize)
|
||||||
if _, err := br.Read(make([]byte, block*mtio.BlockSize)); err != nil {
|
if _, err := br.Read(make([]byte, block*mtio.BlockSize)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -193,19 +188,19 @@ func Index(
|
|||||||
hdr, err := tr.Next()
|
hdr, err := tr.Next()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
if err := mtio.GoToNextFileOnTape(f); err != nil {
|
if err := mtio.GoToNextFileOnTape(drive.Drive); err != nil {
|
||||||
// EOD
|
// EOD
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
record, err = mtio.GetCurrentRecordFromTape(f)
|
record, err = mtio.GetCurrentRecordFromTape(drive.Drive)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
block = 0
|
block = 0
|
||||||
|
|
||||||
br = bufio.NewReaderSize(f, mtio.BlockSize*recordSize)
|
br = bufio.NewReaderSize(drive.Drive, mtio.BlockSize*recordSize)
|
||||||
curr = int64(int64(recordSize) * mtio.BlockSize * record)
|
curr = int64(int64(recordSize) * mtio.BlockSize * record)
|
||||||
counter = &ioext.CounterReader{Reader: br, BytesRead: int(curr)}
|
counter = &ioext.CounterReader{Reader: br, BytesRead: int(curr)}
|
||||||
tr = tar.NewReader(counter)
|
tr = tar.NewReader(counter)
|
||||||
@@ -221,7 +216,7 @@ func Index(
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := verifyHeader(hdr, isRegular); err != nil {
|
if err := verifyHeader(hdr, drive.DriveIsRegular); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,13 +13,11 @@ import (
|
|||||||
"github.com/pojntfx/stfs/internal/ioext"
|
"github.com/pojntfx/stfs/internal/ioext"
|
||||||
"github.com/pojntfx/stfs/internal/mtio"
|
"github.com/pojntfx/stfs/internal/mtio"
|
||||||
"github.com/pojntfx/stfs/internal/signature"
|
"github.com/pojntfx/stfs/internal/signature"
|
||||||
"github.com/pojntfx/stfs/internal/tape"
|
|
||||||
"github.com/pojntfx/stfs/pkg/config"
|
"github.com/pojntfx/stfs/pkg/config"
|
||||||
"github.com/pojntfx/stfs/pkg/hardware"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Query(
|
func Query(
|
||||||
state hardware.DriveConfig,
|
state config.DriveConfig,
|
||||||
pipes config.PipeConfig,
|
pipes config.PipeConfig,
|
||||||
crypto config.CryptoConfig,
|
crypto config.CryptoConfig,
|
||||||
|
|
||||||
@@ -29,21 +27,15 @@ func Query(
|
|||||||
|
|
||||||
onHeader func(hdr *models.Header),
|
onHeader func(hdr *models.Header),
|
||||||
) ([]*tar.Header, error) {
|
) ([]*tar.Header, error) {
|
||||||
f, isRegular, err := tape.OpenTapeReadOnly(state.Drive)
|
|
||||||
if err != nil {
|
|
||||||
return []*tar.Header{}, err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
headers := []*tar.Header{}
|
headers := []*tar.Header{}
|
||||||
|
|
||||||
if isRegular {
|
if state.DriveIsRegular {
|
||||||
// Seek to record and block
|
// Seek to record and block
|
||||||
if _, err := f.Seek(int64((recordSize*mtio.BlockSize*record)+block*mtio.BlockSize), 0); err != nil {
|
if _, err := state.Drive.Seek(int64((recordSize*mtio.BlockSize*record)+block*mtio.BlockSize), 0); err != nil {
|
||||||
return []*tar.Header{}, err
|
return []*tar.Header{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
tr := tar.NewReader(f)
|
tr := tar.NewReader(state.Drive)
|
||||||
|
|
||||||
record := int64(record)
|
record := int64(record)
|
||||||
block := int64(block)
|
block := int64(block)
|
||||||
@@ -52,7 +44,7 @@ func Query(
|
|||||||
hdr, err := tr.Next()
|
hdr, err := tr.Next()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
for {
|
for {
|
||||||
curr, err := f.Seek(0, io.SeekCurrent)
|
curr, err := state.Drive.Seek(0, io.SeekCurrent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []*tar.Header{}, err
|
return []*tar.Header{}, err
|
||||||
}
|
}
|
||||||
@@ -70,11 +62,11 @@ func Query(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Seek to record and block
|
// Seek to record and block
|
||||||
if _, err := f.Seek(int64((recordSize*mtio.BlockSize*int(record))+int(block)*mtio.BlockSize), io.SeekStart); err != nil {
|
if _, err := state.Drive.Seek(int64((recordSize*mtio.BlockSize*int(record))+int(block)*mtio.BlockSize), io.SeekStart); err != nil {
|
||||||
return []*tar.Header{}, err
|
return []*tar.Header{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
tr = tar.NewReader(f)
|
tr = tar.NewReader(state.Drive)
|
||||||
|
|
||||||
hdr, err = tr.Next()
|
hdr, err = tr.Next()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -101,7 +93,7 @@ func Query(
|
|||||||
return []*tar.Header{}, err
|
return []*tar.Header{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := signature.VerifyHeader(hdr, isRegular, pipes.Signature, crypto.Recipient); err != nil {
|
if err := signature.VerifyHeader(hdr, state.DriveIsRegular, pipes.Signature, crypto.Recipient); err != nil {
|
||||||
return []*tar.Header{}, err
|
return []*tar.Header{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,7 +108,7 @@ func Query(
|
|||||||
|
|
||||||
headers = append(headers, hdr)
|
headers = append(headers, hdr)
|
||||||
|
|
||||||
curr, err := f.Seek(0, io.SeekCurrent)
|
curr, err := state.Drive.Seek(0, io.SeekCurrent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []*tar.Header{}, err
|
return []*tar.Header{}, err
|
||||||
}
|
}
|
||||||
@@ -125,7 +117,7 @@ func Query(
|
|||||||
return []*tar.Header{}, err
|
return []*tar.Header{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
currAndSize, err := f.Seek(0, io.SeekCurrent)
|
currAndSize, err := state.Drive.Seek(0, io.SeekCurrent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []*tar.Header{}, err
|
return []*tar.Header{}, err
|
||||||
}
|
}
|
||||||
@@ -141,12 +133,12 @@ func Query(
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Seek to record
|
// Seek to record
|
||||||
if err := mtio.SeekToRecordOnTape(f, int32(record)); err != nil {
|
if err := mtio.SeekToRecordOnTape(state.Drive, int32(record)); err != nil {
|
||||||
return []*tar.Header{}, err
|
return []*tar.Header{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Seek to block
|
// Seek to block
|
||||||
br := bufio.NewReaderSize(f, mtio.BlockSize*recordSize)
|
br := bufio.NewReaderSize(state.Drive, mtio.BlockSize*recordSize)
|
||||||
if _, err := br.Read(make([]byte, block*mtio.BlockSize)); err != nil {
|
if _, err := br.Read(make([]byte, block*mtio.BlockSize)); err != nil {
|
||||||
return []*tar.Header{}, err
|
return []*tar.Header{}, err
|
||||||
}
|
}
|
||||||
@@ -162,19 +154,19 @@ func Query(
|
|||||||
hdr, err := tr.Next()
|
hdr, err := tr.Next()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
if err := mtio.GoToNextFileOnTape(f); err != nil {
|
if err := mtio.GoToNextFileOnTape(state.Drive); err != nil {
|
||||||
// EOD
|
// EOD
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
record, err = mtio.GetCurrentRecordFromTape(f)
|
record, err = mtio.GetCurrentRecordFromTape(state.Drive)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []*tar.Header{}, err
|
return []*tar.Header{}, err
|
||||||
}
|
}
|
||||||
block = 0
|
block = 0
|
||||||
|
|
||||||
br = bufio.NewReaderSize(f, mtio.BlockSize*recordSize)
|
br = bufio.NewReaderSize(state.Drive, mtio.BlockSize*recordSize)
|
||||||
curr := int64(int64(recordSize) * mtio.BlockSize * record)
|
curr := int64(int64(recordSize) * mtio.BlockSize * record)
|
||||||
counter := &ioext.CounterReader{Reader: br, BytesRead: int(curr)}
|
counter := &ioext.CounterReader{Reader: br, BytesRead: int(curr)}
|
||||||
tr = tar.NewReader(counter)
|
tr = tar.NewReader(counter)
|
||||||
@@ -189,7 +181,7 @@ func Query(
|
|||||||
return []*tar.Header{}, err
|
return []*tar.Header{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := signature.VerifyHeader(hdr, isRegular, pipes.Signature, crypto.Recipient); err != nil {
|
if err := signature.VerifyHeader(hdr, state.DriveIsRegular, pipes.Signature, crypto.Recipient); err != nil {
|
||||||
return []*tar.Header{}, err
|
return []*tar.Header{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
75
pkg/tape/write.go
Normal file
75
pkg/tape/write.go
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
package tape
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/pojntfx/stfs/internal/mtio"
|
||||||
|
)
|
||||||
|
|
||||||
|
func OpenTapeWriteOnly(drive string, recordSize int, overwrite bool) (f *os.File, isRegular bool, err error) {
|
||||||
|
stat, err := os.Stat(drive)
|
||||||
|
if err == nil {
|
||||||
|
isRegular = stat.Mode().IsRegular()
|
||||||
|
} else {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
isRegular = true
|
||||||
|
} else {
|
||||||
|
return nil, false, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if overwrite {
|
||||||
|
if isRegular {
|
||||||
|
f, err := os.OpenFile(drive, os.O_WRONLY|os.O_CREATE, 0600)
|
||||||
|
if err != nil {
|
||||||
|
return nil, false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the file's content
|
||||||
|
if err := f.Truncate(0); err != nil {
|
||||||
|
return nil, false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := f.Close(); err != nil {
|
||||||
|
return nil, false, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
f, err := os.OpenFile(drive, os.O_WRONLY, os.ModeCharDevice)
|
||||||
|
if err != nil {
|
||||||
|
return nil, false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seek to the start of the tape
|
||||||
|
if err := mtio.SeekToRecordOnTape(f, 0); err != nil {
|
||||||
|
return nil, false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := f.Close(); err != nil {
|
||||||
|
return nil, false, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if isRegular {
|
||||||
|
f, err = os.OpenFile(drive, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
|
||||||
|
if err != nil {
|
||||||
|
return nil, false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// No need to go to end manually due to `os.O_APPEND`
|
||||||
|
} else {
|
||||||
|
f, err = os.OpenFile(drive, os.O_APPEND|os.O_WRONLY, os.ModeCharDevice)
|
||||||
|
if err != nil {
|
||||||
|
return nil, false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !overwrite {
|
||||||
|
// Go to end of tape
|
||||||
|
if err := mtio.GoToEndOfTape(f); err != nil {
|
||||||
|
return nil, false, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return f, isRegular, nil
|
||||||
|
}
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
package utility
|
|
||||||
|
|
||||||
type PasswordConfig struct {
|
|
||||||
Password string
|
|
||||||
}
|
|
||||||
@@ -15,7 +15,7 @@ import (
|
|||||||
|
|
||||||
func Keygen(
|
func Keygen(
|
||||||
pipes config.PipeConfig,
|
pipes config.PipeConfig,
|
||||||
password PasswordConfig,
|
password config.PasswordConfig,
|
||||||
) (privkey []byte, pubkey []byte, err error) {
|
) (privkey []byte, pubkey []byte, err error) {
|
||||||
if pipes.Encryption != config.NoneKey {
|
if pipes.Encryption != config.NoneKey {
|
||||||
priv, pub, err := generateEncryptionKey(pipes.Encryption, password.Password)
|
priv, pub, err := generateEncryptionKey(pipes.Encryption, password.Password)
|
||||||
|
|||||||
Reference in New Issue
Block a user