refactor: Decompose query func

This commit is contained in:
Felicitas Pojtinger
2021-12-06 22:37:40 +01:00
parent bf0866550a
commit dd312727e1
2 changed files with 229 additions and 222 deletions

View File

@@ -1,19 +1,9 @@
package cmd package cmd
import ( import (
"archive/tar"
"bufio"
"io"
"io/ioutil"
"math"
"github.com/pojntfx/stfs/internal/controllers"
"github.com/pojntfx/stfs/internal/counters"
"github.com/pojntfx/stfs/internal/encryption"
"github.com/pojntfx/stfs/internal/formatting"
"github.com/pojntfx/stfs/internal/keys" "github.com/pojntfx/stfs/internal/keys"
"github.com/pojntfx/stfs/internal/signature" "github.com/pojntfx/stfs/pkg/config"
"github.com/pojntfx/stfs/internal/tape" "github.com/pojntfx/stfs/pkg/recovery"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
"github.com/volatiletech/sqlboiler/v4/boil" "github.com/volatiletech/sqlboiler/v4/boil"
@@ -62,220 +52,33 @@ var recoveryQueryCmd = &cobra.Command{
return err return err
} }
return query( if _, err := recovery.Query(
viper.GetString(driveFlag), config.StateConfig{
Drive: viper.GetString(driveFlag),
Metadata: viper.GetString(metadataFlag),
},
config.PipeConfig{
Compression: viper.GetString(compressionFlag),
Encryption: viper.GetString(encryptionFlag),
Signature: viper.GetString(signatureFlag),
},
config.CryptoConfig{
Recipient: recipient,
Identity: identity,
Password: viper.GetString(passwordFlag),
},
viper.GetInt(recordSizeFlag),
viper.GetInt(recordFlag), viper.GetInt(recordFlag),
viper.GetInt(blockFlag), viper.GetInt(blockFlag),
viper.GetInt(recordSizeFlag), ); err != nil {
viper.GetString(encryptionFlag), return err
identity, }
viper.GetString(signatureFlag),
recipient, return nil
)
}, },
} }
func query(
drive string,
record int,
block int,
recordSize int,
encryptionFormat string,
identity interface{},
signatureFormat string,
recipient interface{},
) error {
f, isRegular, err := tape.OpenTapeReadOnly(drive)
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
}
tr := tar.NewReader(f)
record := int64(record)
block := int64(block)
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(recordSize)
block = int64(nextTotalBlocks) - (record * int64(recordSize))
if block < 0 {
record--
block = int64(recordSize) - 1
} else if block >= int64(recordSize) {
record++
block = 0
}
// 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
}
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 err := encryption.DecryptHeader(hdr, encryptionFormat, identity); err != nil {
return err
}
if err := signature.VerifyHeader(hdr, isRegular, signatureFormat, recipient); 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
}
// 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 := encryption.DecryptHeader(hdr, encryptionFormat, identity); err != nil {
return err
}
if err := signature.VerifyHeader(hdr, isRegular, signatureFormat, recipient); 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() { func init() {
recoveryQueryCmd.PersistentFlags().IntP(recordSizeFlag, "z", 20, "Amount of 512-bit blocks per record") recoveryQueryCmd.PersistentFlags().IntP(recordSizeFlag, "z", 20, "Amount of 512-bit blocks per record")
recoveryQueryCmd.PersistentFlags().IntP(recordFlag, "k", 0, "Record to seek too before counting") recoveryQueryCmd.PersistentFlags().IntP(recordFlag, "k", 0, "Record to seek too before counting")

View File

@@ -2,7 +2,17 @@ package recovery
import ( import (
"archive/tar" "archive/tar"
"bufio"
"io"
"io/ioutil"
"math"
"github.com/pojntfx/stfs/internal/controllers"
"github.com/pojntfx/stfs/internal/counters"
"github.com/pojntfx/stfs/internal/encryption"
"github.com/pojntfx/stfs/internal/formatting"
"github.com/pojntfx/stfs/internal/signature"
"github.com/pojntfx/stfs/internal/tape"
"github.com/pojntfx/stfs/pkg/config" "github.com/pojntfx/stfs/pkg/config"
) )
@@ -15,5 +25,199 @@ func Query(
record int, record int,
block int, block int,
) ([]*tar.Header, error) { ) ([]*tar.Header, error) {
return nil, nil f, isRegular, err := tape.OpenTapeReadOnly(state.Drive)
if err != nil {
return []*tar.Header{}, err
}
defer f.Close()
headers := []*tar.Header{}
if isRegular {
// Seek to record and block
if _, err := f.Seek(int64((recordSize*controllers.BlockSize*record)+block*controllers.BlockSize), 0); err != nil {
return []*tar.Header{}, err
}
tr := tar.NewReader(f)
record := int64(record)
block := int64(block)
for {
hdr, err := tr.Next()
if err != nil {
for {
curr, err := f.Seek(0, io.SeekCurrent)
if err != nil {
return []*tar.Header{}, err
}
nextTotalBlocks := math.Ceil(float64((curr)) / float64(controllers.BlockSize))
record = int64(nextTotalBlocks) / int64(recordSize)
block = int64(nextTotalBlocks) - (record * int64(recordSize))
if block < 0 {
record--
block = int64(recordSize) - 1
} else if block >= int64(recordSize) {
record++
block = 0
}
// Seek to record and block
if _, err := f.Seek(int64((recordSize*controllers.BlockSize*int(record))+int(block)*controllers.BlockSize), io.SeekStart); err != nil {
return []*tar.Header{}, 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 err := encryption.DecryptHeader(hdr, pipes.Encryption, crypto.Identity); err != nil {
return []*tar.Header{}, err
}
if err := signature.VerifyHeader(hdr, isRegular, pipes.Signature, crypto.Recipient); err != nil {
return []*tar.Header{}, err
}
if record == 0 && block == 0 {
if err := formatting.PrintCSV(formatting.TARHeaderCSV); err != nil {
return []*tar.Header{}, err
}
}
if err := formatting.PrintCSV(formatting.GetTARHeaderAsCSV(record, block, hdr)); err != nil {
return []*tar.Header{}, err
}
headers = append(headers, hdr)
curr, err := f.Seek(0, io.SeekCurrent)
if err != nil {
return []*tar.Header{}, err
}
if _, err := io.Copy(ioutil.Discard, tr); err != nil {
return []*tar.Header{}, err
}
currAndSize, err := f.Seek(0, io.SeekCurrent)
if err != nil {
return []*tar.Header{}, 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 []*tar.Header{}, err
}
// Seek to block
br := bufio.NewReaderSize(f, controllers.BlockSize*recordSize)
if _, err := br.Read(make([]byte, block*controllers.BlockSize)); err != nil {
return []*tar.Header{}, 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 []*tar.Header{}, 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 []*tar.Header{}, err
}
}
if err := encryption.DecryptHeader(hdr, pipes.Encryption, crypto.Identity); err != nil {
return []*tar.Header{}, err
}
if err := signature.VerifyHeader(hdr, isRegular, pipes.Signature, crypto.Recipient); err != nil {
return []*tar.Header{}, err
}
if record == 0 && block == 0 {
if err := formatting.PrintCSV(formatting.TARHeaderCSV); err != nil {
return []*tar.Header{}, err
}
}
if err := formatting.PrintCSV(formatting.GetTARHeaderAsCSV(record, block, hdr)); err != nil {
return []*tar.Header{}, err
}
headers = append(headers, hdr)
if _, err := io.Copy(ioutil.Discard, tr); err != nil {
return []*tar.Header{}, 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 headers, nil
} }