feat: Add support for tape drives to LZ4 compressor

This commit is contained in:
Felicitas Pojtinger
2021-12-05 21:41:29 +01:00
parent 10449b8e65
commit e4f99776c4
2 changed files with 42 additions and 20 deletions

View File

@@ -64,6 +64,10 @@ var (
errMissingTarHeader = errors.New("tar header is missing")
errRecipientUnparsable = errors.New("recipient could not be parsed")
errCompressionFormatRequiresLargerRecordSize = errors.New("this compression format requires a larger record size")
errCompressionFormatOnlyRegularSupport = errors.New("this compression format only supports regular files, not i.e. tape drives")
)
var archiveCmd = &cobra.Command{
@@ -833,8 +837,27 @@ func compress(
return nil, errUnsupportedCompressionLevel
}
opts := []lz4.Option{lz4.CompressionLevelOption(l), lz4.ConcurrencyOption(-1)}
if !isRegular {
maxSize := getNearestPowerOf2Lower(controllers.BlockSize * recordSize)
if uint32(maxSize) < uint32(lz4.Block64Kb) {
return nil, errCompressionFormatRequiresLargerRecordSize
}
if uint32(maxSize) < uint32(lz4.Block256Kb) {
opts = append(opts, lz4.BlockSizeOption(lz4.Block64Kb))
} else if uint32(maxSize) < uint32(lz4.Block1Mb) {
opts = append(opts, lz4.BlockSizeOption(lz4.Block256Kb))
} else if uint32(maxSize) < uint32(lz4.Block4Mb) {
opts = append(opts, lz4.BlockSizeOption(lz4.Block1Mb))
} else {
opts = append(opts, lz4.BlockSizeOption(lz4.Block4Mb))
}
}
lz := lz4.NewWriter(dst)
if err := lz.Apply(lz4.ConcurrencyOption(-1), lz4.CompressionLevelOption(l)); err != nil {
if err := lz.Apply(opts...); err != nil {
return nil, err
}
@@ -852,24 +875,22 @@ func compress(
return nil, errUnsupportedCompressionLevel
}
var zz *zstd.Encoder
if isRegular {
z, err := zstd.NewWriter(dst, zstd.WithEncoderLevel(l))
if err != nil {
return nil, err
}
zz = z
} else {
z, err := zstd.NewWriter(dst, zstd.WithWindowSize(getNearestPowerOf2Lower(controllers.BlockSize*recordSize)))
if err != nil {
return nil, err
}
zz = z
opts := []zstd.EOption{zstd.WithEncoderLevel(l)}
if !isRegular {
opts = append(opts, zstd.WithWindowSize(getNearestPowerOf2Lower(controllers.BlockSize*recordSize)))
}
zz, err := zstd.NewWriter(dst, opts...)
if err != nil {
return nil, err
}
return zz, nil
case compressionFormatBrotliKey:
// TODO: Add support for tape drives
if !isRegular {
return nil, errCompressionFormatOnlyRegularSupport
}
l := brotli.DefaultCompression
switch compressionLevel {
case compressionLevelFastest:
@@ -888,7 +909,6 @@ func compress(
case compressionFormatBzip2Key:
fallthrough
case compressionFormatBzip2ParallelKey:
// TODO: Add support for tape drives
l := bzip2.DefaultCompression
switch compressionLevel {
case compressionLevelFastest:
@@ -917,16 +937,18 @@ func compress(
}
func getNearestPowerOf2Lower(n int) int {
power := int(math.Log2(float64(n))) // Truncation is intentional, see https://www.geeksforgeeks.org/highest-power-2-less-equal-given-number/
return int(math.Pow(2, float64(getNearestLogOf2Lower(n)))) // Truncation is intentional, see https://www.geeksforgeeks.org/highest-power-2-less-equal-given-number/
}
return int(math.Pow(2, float64(power))) // Truncation is intentional, see https://www.geeksforgeeks.org/highest-power-2-less-equal-given-number/
func getNearestLogOf2Lower(n int) int {
return int(math.Log2(float64(n))) // Truncation is intentional, see https://www.geeksforgeeks.org/highest-power-2-less-equal-given-number/
}
func init() {
archiveCmd.PersistentFlags().IntP(recordSizeFlag, "z", 20, "Amount of 512-bit blocks per record")
archiveCmd.PersistentFlags().StringP(fromFlag, "f", ".", "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). Has no effect when on tape, where --record-size is used instead.", compressionLevelBalanced, knownCompressionLevels))
archiveCmd.PersistentFlags().StringP(compressionLevelFlag, "l", compressionLevelBalanced, fmt.Sprintf("Compression level to use (default %v, available are %v)", compressionLevelBalanced, knownCompressionLevels))
archiveCmd.PersistentFlags().StringP(recipientFlag, "r", "", "Path to public key of recipient to encrypt for")
archiveCmd.PersistentFlags().StringP(identityFlag, "i", "", "Path to private key to sign with")
archiveCmd.PersistentFlags().StringP(passwordFlag, "p", "", "Password for the private key")

View File

@@ -365,7 +365,7 @@ func init() {
updateCmd.PersistentFlags().IntP(recordSizeFlag, "z", 20, "Amount of 512-bit blocks per record")
updateCmd.PersistentFlags().StringP(fromFlag, "f", "", "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). Has no effect when on tape, where --record-size is used instead.", compressionLevelBalanced, knownCompressionLevels))
updateCmd.PersistentFlags().StringP(compressionLevelFlag, "l", compressionLevelBalanced, fmt.Sprintf("Compression level to use (default %v, available are %v)", compressionLevelBalanced, knownCompressionLevels))
updateCmd.PersistentFlags().StringP(recipientFlag, "r", "", "Path to public key of recipient to encrypt for")
updateCmd.PersistentFlags().StringP(identityFlag, "i", "", "Path to private key to sign with")
updateCmd.PersistentFlags().StringP(passwordFlag, "p", "", "Password for the private key")