Fix noinlineerr findings: internal/vaultik (refs #61)

This commit is contained in:
2026-08-07 16:59:56 +00:00
parent 919229f224
commit e7b49d58ab
10 changed files with 123 additions and 56 deletions

View File

@@ -32,11 +32,13 @@ func TestFetchAndDecryptBlobVerifiesHash(t *testing.T) {
t.Fatalf("creating blobgen writer: %v", err) t.Fatalf("creating blobgen writer: %v", err)
} }
if _, err := writer.Write(plaintext); err != nil { _, err = writer.Write(plaintext)
if err != nil {
t.Fatalf("writing plaintext: %v", err) t.Fatalf("writing plaintext: %v", err)
} }
if err := writer.Close(); err != nil { err = writer.Close()
if err != nil {
t.Fatalf("closing writer: %v", err) t.Fatalf("closing writer: %v", err)
} }
@@ -75,7 +77,8 @@ func TestFetchAndDecryptBlobVerifiesHash(t *testing.T) {
t.Fatalf("reading stream: %v", err) t.Fatalf("reading stream: %v", err)
} }
if err := rc.Close(); err != nil { err = rc.Close()
if err != nil {
t.Fatalf("close (hash verification) failed: %v", err) t.Fatalf("close (hash verification) failed: %v", err)
} }

View File

@@ -275,7 +275,9 @@ func (c *blobDiskCache) ReadAt(key string, offset, length int64) ([]byte, error)
defer func() { _ = f.Close() }() defer func() { _ = f.Close() }()
buf := make([]byte, length) buf := make([]byte, length)
if _, err := f.ReadAt(buf, offset); err != nil {
_, err = f.ReadAt(buf, offset)
if err != nil {
return nil, err return nil, err
} }

View File

@@ -15,7 +15,9 @@ func TestBlobDiskCache_BasicGetPut(t *testing.T) {
defer func() { _ = cache.Close() }() defer func() { _ = cache.Close() }()
data := []byte("hello world") data := []byte("hello world")
if err := cache.Put("key1", data); err != nil {
err = cache.Put("key1", data)
if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -74,7 +76,9 @@ func TestBlobDiskCache_OversizedEntryRejected(t *testing.T) {
defer func() { _ = cache.Close() }() defer func() { _ = cache.Close() }()
data := make([]byte, 200) data := make([]byte, 200)
if err := cache.Put("big", data); err != nil {
err = cache.Put("big", data)
if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -90,11 +94,13 @@ func TestBlobDiskCache_UpdateInPlace(t *testing.T) {
} }
defer func() { _ = cache.Close() }() defer func() { _ = cache.Close() }()
if err := cache.Put("key1", []byte("v1")); err != nil { err = cache.Put("key1", []byte("v1"))
if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := cache.Put("key1", []byte("version2")); err != nil { err = cache.Put("key1", []byte("version2"))
if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -124,11 +130,14 @@ func TestBlobDiskCache_ReadAt(t *testing.T) {
defer func() { _ = cache.Close() }() defer func() { _ = cache.Close() }()
data := make([]byte, 1024) data := make([]byte, 1024)
if _, err := rand.Read(data); err != nil {
_, err = rand.Read(data)
if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := cache.Put("blob1", data); err != nil { err = cache.Put("blob1", data)
if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -158,11 +167,13 @@ func TestBlobDiskCache_Close(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if err := cache.Put("key1", []byte("data")); err != nil { err = cache.Put("key1", []byte("data"))
if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := cache.Close(); err != nil { err = cache.Close()
if err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
@@ -175,11 +186,14 @@ func TestBlobDiskCache_LRUOrder(t *testing.T) {
defer func() { _ = cache.Close() }() defer func() { _ = cache.Close() }()
d := make([]byte, 100) d := make([]byte, 100)
if err := cache.Put("a", d); err != nil {
err = cache.Put("a", d)
if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := cache.Put("b", d); err != nil { err = cache.Put("b", d)
if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -187,7 +201,8 @@ func TestBlobDiskCache_LRUOrder(t *testing.T) {
cache.Get("a") cache.Get("a")
// Adding "c" should evict "b" (LRU), not "a" // Adding "c" should evict "b" (LRU), not "a"
if err := cache.Put("c", d); err != nil { err = cache.Put("c", d)
if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@@ -79,7 +79,8 @@ func parseSnapshotName(snapshotID string) string {
// d/day/days, w/week/weeks, mo/month/months, y/year/years, plus standard Go // d/day/days, w/week/weeks, mo/month/months, y/year/years, plus standard Go
// duration units (h, m, s). // duration units (h, m, s).
func parseDuration(s string) (time.Duration, error) { func parseDuration(s string) (time.Duration, error) {
if d, err := time.ParseDuration(s); err == nil { d, err := time.ParseDuration(s)
if err == nil {
return d, nil return d, nil
} }

View File

@@ -97,7 +97,8 @@ func (v *Vaultik) ShowInfo() error {
v.printfStdout("Index Path: %s\n", v.Config.IndexPath) v.printfStdout("Index Path: %s\n", v.Config.IndexPath)
// Check if index file exists and get its size // Check if index file exists and get its size
if info, err := v.Fs.Stat(v.Config.IndexPath); err == nil { info, err := v.Fs.Stat(v.Config.IndexPath)
if err == nil {
v.printfStdout("Index Size: %s\n", humanize.Bytes(uint64(info.Size()))) v.printfStdout("Index Size: %s\n", humanize.Bytes(uint64(info.Size())))
// Get snapshot count from database // Get snapshot count from database
@@ -201,7 +202,8 @@ func (v *Vaultik) RemoteInfo(jsonOutput bool) error {
v.populateRemoteInfoResult(result, snapshotMetadata, snapshotIDs, referencedBlobs) v.populateRemoteInfoResult(result, snapshotMetadata, snapshotIDs, referencedBlobs)
if err := v.scanRemoteBlobStorage(result, referencedBlobs, jsonOutput); err != nil { err = v.scanRemoteBlobStorage(result, referencedBlobs, jsonOutput)
if err != nil {
return err return err
} }

View File

@@ -29,13 +29,14 @@ func (v *Vaultik) NukeRemote(force bool) error {
v.UI.Begin("Removing all snapshot metadata from backup destination store.") v.UI.Begin("Removing all snapshot metadata from backup destination store.")
if _, err := v.RemoveAllSnapshots(&RemoveOptions{Force: true}); err != nil { _, err := v.RemoveAllSnapshots(&RemoveOptions{Force: true})
if err != nil {
return fmt.Errorf("removing all snapshots: %w", err) return fmt.Errorf("removing all snapshots: %w", err)
} }
v.UI.Begin("Removing any blobs still present in backup destination store.") v.UI.Begin("Removing any blobs still present in backup destination store.")
err := v.PruneBlobs(&PruneOptions{Force: true}) err = v.PruneBlobs(&PruneOptions{Force: true})
if err != nil { if err != nil {
return fmt.Errorf("pruning blobs: %w", err) return fmt.Errorf("pruning blobs: %w", err)
} }
@@ -74,7 +75,8 @@ func (v *Vaultik) Prune(opts *PruneOptions) error {
return fmt.Errorf("reconciling local snapshots with remote: %w", err) return fmt.Errorf("reconciling local snapshots with remote: %w", err)
} }
if _, err := v.PruneDatabase(); err != nil { _, err = v.PruneDatabase()
if err != nil {
return fmt.Errorf("pruning local database: %w", err) return fmt.Errorf("pruning local database: %w", err)
} }
@@ -121,7 +123,9 @@ func (v *Vaultik) PruneBlobs(opts *PruneOptions) error {
v.printfStdout("\nDelete %d unreferenced blob(s)? [y/N] ", len(unreferencedBlobs)) v.printfStdout("\nDelete %d unreferenced blob(s)? [y/N] ", len(unreferencedBlobs))
var confirm string var confirm string
if _, err := v.scanStdin(&confirm); err != nil {
_, err = v.scanStdin(&confirm)
if err != nil {
v.printlnStdout("Cancelled") v.printlnStdout("Cancelled")
return nil return nil

View File

@@ -483,14 +483,16 @@ func (v *Vaultik) downloadSnapshotDB(snapshotID string, identity age.Identity) (
tempPath := tempFile.Name() tempPath := tempFile.Name()
// Write the binary SQLite database directly // Write the binary SQLite database directly
if _, err := tempFile.Write(dbData); err != nil { _, err = tempFile.Write(dbData)
if err != nil {
_ = tempFile.Close() _ = tempFile.Close()
_ = v.Fs.Remove(tempPath) _ = v.Fs.Remove(tempPath)
return nil, fmt.Errorf("writing database file: %w", err) return nil, fmt.Errorf("writing database file: %w", err)
} }
if err := tempFile.Close(); err != nil { err = tempFile.Close()
if err != nil {
_ = v.Fs.Remove(tempPath) _ = v.Fs.Remove(tempPath)
return nil, fmt.Errorf("closing temp file: %w", err) return nil, fmt.Errorf("closing temp file: %w", err)
@@ -559,7 +561,9 @@ func (v *Vaultik) buildChunkToBlobMap(ctx context.Context, repos *database.Repos
bc database.BlobChunk bc database.BlobChunk
blobIDStr, chunkHashStr string blobIDStr, chunkHashStr string
) )
if err := rows.Scan(&blobIDStr, &chunkHashStr, &bc.Offset, &bc.Length); err != nil {
err = rows.Scan(&blobIDStr, &chunkHashStr, &bc.Offset, &bc.Length)
if err != nil {
return nil, fmt.Errorf("scanning blob_chunk: %w", err) return nil, fmt.Errorf("scanning blob_chunk: %w", err)
} }
@@ -762,11 +766,13 @@ func (s *restoreSession) restoreRegularFile(file *database.File, targetPath stri
"ms_sweeper", sweeperDur.Milliseconds(), "ms_sweeper", sweeperDur.Milliseconds(),
) )
if err := outFile.Close(); err != nil { err = outFile.Close()
if err != nil {
return fmt.Errorf("closing output file: %w", err) return fmt.Errorf("closing output file: %w", err)
} }
if err := s.v.Fs.Chmod(targetPath, os.FileMode(file.Mode)); err != nil { err = s.v.Fs.Chmod(targetPath, os.FileMode(file.Mode))
if err != nil {
log.Debug("Failed to set file permissions", "path", targetPath, "error", err) log.Debug("Failed to set file permissions", "path", targetPath, "error", err)
} }
@@ -779,7 +785,8 @@ func (s *restoreSession) restoreRegularFile(file *database.File, targetPath stri
} }
} }
if err := s.v.Fs.Chtimes(targetPath, file.MTime, file.MTime); err != nil { err = s.v.Fs.Chtimes(targetPath, file.MTime, file.MTime)
if err != nil {
log.Debug("Failed to set file mtime", "path", targetPath, "error", err) log.Debug("Failed to set file mtime", "path", targetPath, "error", err)
} }

View File

@@ -119,7 +119,8 @@ func (s *restoreSweeper) blobStillNeeded(blobHash string) (bool, error) {
} }
} }
if err := rows.Err(); err != nil { err = rows.Err()
if err != nil {
return true, err return true, err
} }

View File

@@ -56,7 +56,8 @@ func (v *Vaultik) CreateSnapshot(opts *SnapshotCreateOptions) error {
// Prune the database before starting: delete incomplete snapshots and orphaned data. // Prune the database before starting: delete incomplete snapshots and orphaned data.
// This ensures the database is consistent before we start a new snapshot. // This ensures the database is consistent before we start a new snapshot.
// Since we use locking, only one vaultik instance accesses the DB at a time. // Since we use locking, only one vaultik instance accesses the DB at a time.
if _, err := v.PruneDatabase(); err != nil { _, err = v.PruneDatabase()
if err != nil {
return fmt.Errorf("prune database: %w", err) return fmt.Errorf("prune database: %w", err)
} }
@@ -195,7 +196,8 @@ func (v *Vaultik) createNamedSnapshot(opts *SnapshotCreateOptions, hostname, sna
v.collectUploadStats(scanner, stats) v.collectUploadStats(scanner, stats)
if err := v.finalizeSnapshotMetadata(snapshotID, stats); err != nil { err = v.finalizeSnapshotMetadata(snapshotID, stats)
if err != nil {
return err return err
} }
@@ -395,7 +397,8 @@ func (v *Vaultik) getSnapshotBlobSizes(snapshotID string) (compressed int64, unc
} }
for _, hash := range blobHashes { for _, hash := range blobHashes {
if blob, err := v.Repositories.Blobs.GetByHash(v.ctx, hash); err == nil && blob != nil { blob, err := v.Repositories.Blobs.GetByHash(v.ctx, hash)
if err == nil && blob != nil {
compressed += blob.CompressedSize compressed += blob.CompressedSize
uncompressed += blob.UncompressedSize uncompressed += blob.UncompressedSize
} }
@@ -453,7 +456,8 @@ func (v *Vaultik) ListSnapshots(jsonOutput bool) error {
return encoder.Encode(snapshots) return encoder.Encode(snapshots)
} }
if err := v.printSnapshotTable(snapshots); err != nil { err = v.printSnapshotTable(snapshots)
if err != nil {
return err return err
} }
@@ -552,15 +556,18 @@ func (v *Vaultik) snapshotInfoFromLocal(ls *database.Snapshot) SnapshotInfo {
func (v *Vaultik) printSnapshotTable(snapshots []SnapshotInfo) error { func (v *Vaultik) printSnapshotTable(snapshots []SnapshotInfo) error {
w := tabwriter.NewWriter(v.Stdout, 0, 0, 3, ' ', 0) w := tabwriter.NewWriter(v.Stdout, 0, 0, 3, ' ', 0)
if _, err := fmt.Fprintln(w, "CONFIGURED SNAPSHOTS:"); err != nil { _, err := fmt.Fprintln(w, "CONFIGURED SNAPSHOTS:")
if err != nil {
return err return err
} }
if _, err := fmt.Fprintln(w, "NAME\tPATHS"); err != nil { _, err = fmt.Fprintln(w, "NAME\tPATHS")
if err != nil {
return err return err
} }
if _, err := fmt.Fprintln(w, "────\t─────"); err != nil { _, err = fmt.Fprintln(w, "────\t─────")
if err != nil {
return err return err
} }
@@ -568,16 +575,20 @@ func (v *Vaultik) printSnapshotTable(snapshots []SnapshotInfo) error {
snap := v.Config.Snapshots[name] snap := v.Config.Snapshots[name]
paths := strings.Join(snap.Paths, ", ") paths := strings.Join(snap.Paths, ", ")
if _, err := fmt.Fprintf(w, "%s\t%s\n", name, paths); err != nil {
_, err = fmt.Fprintf(w, "%s\t%s\n", name, paths)
if err != nil {
return err return err
} }
} }
if _, err := fmt.Fprintln(w); err != nil { _, err = fmt.Fprintln(w)
if err != nil {
return err return err
} }
if _, err := fmt.Fprintln(w, "REMOTE SNAPSHOTS:"); err != nil { _, err = fmt.Fprintln(w, "REMOTE SNAPSHOTS:")
if err != nil {
return err return err
} }
@@ -599,12 +610,13 @@ func (v *Vaultik) printSnapshotTable(snapshots []SnapshotInfo) error {
newChunks = formatBytes(snap.NewChunkSize) newChunks = formatBytes(snap.NewChunkSize)
} }
if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", _, err = fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n",
snap.ID, snap.ID,
snap.Timestamp.Format("2006-01-02 15:04:05"), snap.Timestamp.Format("2006-01-02 15:04:05"),
formatBytes(snap.CompressedSize), formatBytes(snap.CompressedSize),
uncompressed, uncompressed,
newChunks); err != nil { newChunks)
if err != nil {
return err return err
} }
} }
@@ -626,11 +638,13 @@ type SnapshotPurgeOptions struct {
// snapshot name, not the latest globally. This prevents `home` and `system` // snapshot name, not the latest globally. This prevents `home` and `system`
// snapshots from cannibalizing each other. // snapshots from cannibalizing each other.
func (v *Vaultik) PurgeSnapshotsWithOptions(opts *SnapshotPurgeOptions) error { func (v *Vaultik) PurgeSnapshotsWithOptions(opts *SnapshotPurgeOptions) error {
if err := v.EnsureStorageBinding(); err != nil { err := v.EnsureStorageBinding()
if err != nil {
return err return err
} }
// Sync with remote first // Sync with remote first
if err := v.syncWithRemote(); err != nil { err = v.syncWithRemote()
if err != nil {
return fmt.Errorf("syncing with remote: %w", err) return fmt.Errorf("syncing with remote: %w", err)
} }
@@ -731,7 +745,9 @@ func (v *Vaultik) confirmAndExecutePurge(toDelete []SnapshotInfo, force, quiet b
v.printfStdout("\nDelete %d snapshot(s)? [y/N] ", len(toDelete)) v.printfStdout("\nDelete %d snapshot(s)? [y/N] ", len(toDelete))
var confirm string var confirm string
if _, err := v.scanStdin(&confirm); err != nil {
_, err := v.scanStdin(&confirm)
if err != nil {
// Treat EOF or error as "no" // Treat EOF or error as "no"
v.printlnStdout("Cancelled") v.printlnStdout("Cancelled")
@@ -829,7 +845,8 @@ func (v *Vaultik) VerifySnapshotWithOptions(snapshotID string, opts *VerifyOptio
v.printfStdout(" Total size: %s\n", humanize.Bytes(uint64(manifest.TotalCompressedSize))) v.printfStdout(" Total size: %s\n", humanize.Bytes(uint64(manifest.TotalCompressedSize)))
if manifest.Timestamp != "" { if manifest.Timestamp != "" {
if t, err := time.Parse(time.RFC3339, manifest.Timestamp); err == nil { t, err := time.Parse(time.RFC3339, manifest.Timestamp)
if err == nil {
v.printfStdout(" Created: %s\n", t.Format("2006-01-02 15:04:05 MST")) v.printfStdout(" Created: %s\n", t.Format("2006-01-02 15:04:05 MST"))
} }
} }
@@ -849,7 +866,9 @@ func (v *Vaultik) VerifySnapshotWithOptions(snapshotID string, opts *VerifyOptio
// Snapshot ID format: hostname[_name]_<RFC3339> // Snapshot ID format: hostname[_name]_<RFC3339>
func (v *Vaultik) printVerifyHeader(snapshotID string, opts *VerifyOptions) { func (v *Vaultik) printVerifyHeader(snapshotID string, opts *VerifyOptions) {
var snapshotTime time.Time var snapshotTime time.Time
if t, err := parseSnapshotTimestamp(snapshotID); err == nil {
t, err := parseSnapshotTimestamp(snapshotID)
if err == nil {
snapshotTime = t snapshotTime = t
} }
@@ -945,7 +964,8 @@ func (v *Vaultik) outputVerifyJSON(result *VerifyResult) error {
// human ID is hashed via RemoteSnapshotKey and compared against the // human ID is hashed via RemoteSnapshotKey and compared against the
// remote listing. // remote listing.
func (v *Vaultik) CleanupLocalSnapshots() error { func (v *Vaultik) CleanupLocalSnapshots() error {
if err := v.EnsureStorageBinding(); err != nil { err := v.EnsureStorageBinding()
if err != nil {
return err return err
} }
@@ -1137,7 +1157,9 @@ func (v *Vaultik) RemoveSnapshot(snapshotID string, opts *RemoveOptions) (*Remov
} }
var confirm string var confirm string
if _, err := v.scanStdin(&confirm); err != nil {
_, err = v.scanStdin(&confirm)
if err != nil {
v.printlnStdout("Cancelled") v.printlnStdout("Cancelled")
return result, nil return result, nil
@@ -1205,7 +1227,8 @@ func (v *Vaultik) RemoveSnapshot(snapshotID string, opts *RemoveOptions) (*Remov
// "remove --all" leaves nothing behind, even when the local DB and // "remove --all" leaves nothing behind, even when the local DB and
// remote storage have diverged. // remote storage have diverged.
func (v *Vaultik) RemoveAllSnapshots(opts *RemoveOptions) (*RemoveResult, error) { func (v *Vaultik) RemoveAllSnapshots(opts *RemoveOptions) (*RemoveResult, error) {
if err := v.EnsureStorageBinding(); err != nil { err := v.EnsureStorageBinding()
if err != nil {
return nil, err return nil, err
} }
@@ -1563,7 +1586,8 @@ func (v *Vaultik) PruneDatabase() (*PruneResult, error) {
blobCountBefore, _ := v.getTableCount("blobs") blobCountBefore, _ := v.getTableCount("blobs")
// Run the cleanup // Run the cleanup
if err := v.SnapshotManager.CleanupOrphanedData(v.ctx); err != nil { err = v.SnapshotManager.CleanupOrphanedData(v.ctx)
if err != nil {
return nil, fmt.Errorf("cleanup orphaned data: %w", err) return nil, fmt.Errorf("cleanup orphaned data: %w", err)
} }

View File

@@ -90,7 +90,8 @@ func (v *Vaultik) RunDeepVerify(snapshotID string, opts *VerifyOptions) error {
result.TotalSize = totalSize result.TotalSize = totalSize
if err := v.runVerificationSteps(manifest, dbBlobs, tempDB, opts, result, totalSize); err != nil { err = v.runVerificationSteps(manifest, dbBlobs, tempDB, opts, result, totalSize)
if err != nil {
return err return err
} }
@@ -337,7 +338,8 @@ func (v *Vaultik) verifyBlob(blobInfo snapshot.BlobInfo, db *sql.DB) error {
return err return err
} }
if err := v.verifyBlobFinalIntegrity(decompressor, blobHasher, blobInfo.Hash); err != nil { err = v.verifyBlobFinalIntegrity(decompressor, blobHasher, blobInfo.Hash)
if err != nil {
return err return err
} }
@@ -396,7 +398,9 @@ func (v *Vaultik) verifyBlobChunks(db *sql.DB, blobHash string, decompressor io.
if offset > totalRead { if offset > totalRead {
// Skip to the correct offset // Skip to the correct offset
skipBytes := offset - totalRead skipBytes := offset - totalRead
if _, err := io.CopyN(io.Discard, decompressor, skipBytes); err != nil {
_, err = io.CopyN(io.Discard, decompressor, skipBytes)
if err != nil {
return 0, fmt.Errorf("failed to skip to offset %d: %w", offset, err) return 0, fmt.Errorf("failed to skip to offset %d: %w", offset, err)
} }
@@ -405,7 +409,9 @@ func (v *Vaultik) verifyBlobChunks(db *sql.DB, blobHash string, decompressor io.
// Read chunk data // Read chunk data
chunkData := make([]byte, length) chunkData := make([]byte, length)
if _, err := io.ReadFull(decompressor, chunkData); err != nil {
_, err = io.ReadFull(decompressor, chunkData)
if err != nil {
return 0, fmt.Errorf("failed to read chunk at offset %d: %w", offset, err) return 0, fmt.Errorf("failed to read chunk at offset %d: %w", offset, err)
} }
@@ -424,7 +430,8 @@ func (v *Vaultik) verifyBlobChunks(db *sql.DB, blobHash string, decompressor io.
chunkCount++ chunkCount++
} }
if err := rows.Err(); err != nil { err = rows.Err()
if err != nil {
return 0, fmt.Errorf("error iterating blob chunks: %w", err) return 0, fmt.Errorf("error iterating blob chunks: %w", err)
} }
@@ -490,7 +497,8 @@ func (v *Vaultik) getBlobsFromDatabase(snapshotID string, db *sql.DB) ([]snapsho
}) })
} }
if err := rows.Err(); err != nil { err = rows.Err()
if err != nil {
return nil, fmt.Errorf("error iterating blobs: %w", err) return nil, fmt.Errorf("error iterating blobs: %w", err)
} }