Record the real uid and gid of backed-up files (closes #216)
check / check (pull_request) Successful in 5m51s
check / check (pull_request) Successful in 5m51s
The scanner read uid and gid by asserting the stat result to an interface with Uid() and Gid() methods. *syscall.Stat_t has Uid and Gid fields, not methods, so the assertion never matched and every file, directory and symlink was stored as 0:0; a restore as root then gave everything to root. The scanner now reads the fields of *syscall.Stat_t. The first backup after this change re-reads every file not owned by root, because its stored uid and gid no longer match the disk. When the tests run as root, as in the Docker build, the new test compares 0 with 0 and cannot catch the defect; a non-root run does. Model: opus-5-5
This commit is contained in:
@@ -11,6 +11,7 @@ import (
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
@@ -1142,12 +1143,9 @@ func (s *Scanner) buildSymlinkEntry(path string, info os.FileInfo) *database.Fil
|
||||
}
|
||||
|
||||
var uid, gid uint32
|
||||
if stat, ok := info.Sys().(interface {
|
||||
Uid() uint32
|
||||
Gid() uint32
|
||||
}); ok {
|
||||
uid = stat.Uid()
|
||||
gid = stat.Gid()
|
||||
if stat, ok := info.Sys().(*syscall.Stat_t); ok {
|
||||
uid = stat.Uid
|
||||
gid = stat.Gid
|
||||
}
|
||||
|
||||
return &database.File{
|
||||
@@ -1166,12 +1164,9 @@ func (s *Scanner) buildSymlinkEntry(path string, info os.FileInfo) *database.Fil
|
||||
// buildDirectoryEntry creates a File record for a directory.
|
||||
func (s *Scanner) buildDirectoryEntry(path string, info os.FileInfo) *database.File {
|
||||
var uid, gid uint32
|
||||
if stat, ok := info.Sys().(interface {
|
||||
Uid() uint32
|
||||
Gid() uint32
|
||||
}); ok {
|
||||
uid = stat.Uid()
|
||||
gid = stat.Gid()
|
||||
if stat, ok := info.Sys().(*syscall.Stat_t); ok {
|
||||
uid = stat.Uid
|
||||
gid = stat.Gid
|
||||
}
|
||||
|
||||
return &database.File{
|
||||
@@ -1204,16 +1199,10 @@ func (s *Scanner) recordNonRegularFile(ctx context.Context, ftp *FileToProcess)
|
||||
func (s *Scanner) checkFileInMemory(
|
||||
path string, info os.FileInfo, knownFiles map[string]*database.File,
|
||||
) (*database.File, bool) {
|
||||
// Get file stats
|
||||
stat, ok := info.Sys().(interface {
|
||||
Uid() uint32
|
||||
Gid() uint32
|
||||
})
|
||||
|
||||
var uid, gid uint32
|
||||
if ok {
|
||||
uid = stat.Uid()
|
||||
gid = stat.Gid()
|
||||
if stat, ok := info.Sys().(*syscall.Stat_t); ok {
|
||||
uid = stat.Uid
|
||||
gid = stat.Gid
|
||||
}
|
||||
|
||||
// Check against in-memory map first to get existing ID if available
|
||||
|
||||
Reference in New Issue
Block a user