Walk an operand below .zfs or a symlink on its own (closes #142)
check / check (push) Canceled after 0s
check / check (push) Canceled after 0s
An operand under another was dropped as covered by it even when a directory between them was named .zfs or was a symlink. The walk of the outer operand enters neither, so the files under the inner operand went unscanned and their records were deleted. walkReaches now reports such an operand as not reached, so pruneRoots keeps it and walks it on its own. README lists both cases with the others. Judgement call: the new constant zfsDirName replaces the .zfs literal in operandWarning and subdirJob too, because goconst rejects a third copy. Model: opus-5-5
This commit is contained in:
@@ -48,6 +48,11 @@ const sampleWindow = 1024 * 1024
|
||||
// and hash worker pools.
|
||||
const workQueueDepth = 1024
|
||||
|
||||
// zfsDirName is the name of the directory in which ZFS shows a
|
||||
// filesystem's snapshots. The walk never enters one, since it would
|
||||
// list every file once per snapshot.
|
||||
const zfsDirName = ".zfs"
|
||||
|
||||
// errInterrupted reports a scan stopped by SIGINT or SIGTERM. runScan
|
||||
// has already printed its line, so run prints nothing more.
|
||||
var errInterrupted = errors.New("scan interrupted")
|
||||
@@ -272,9 +277,10 @@ func pruneRoots(roots []string, oneFS bool, rules walkRules,
|
||||
}
|
||||
|
||||
// walkReaches reports whether the walk of operand above reaches r, an
|
||||
// operand under it. That walk does not enter a default exclude in
|
||||
// rules, nor a directory that device puts on a filesystem in rules that
|
||||
// is not persistent, nor, with -x, one that device puts on a different
|
||||
// operand under it. That walk never follows a symlink. It does not
|
||||
// enter a directory named .zfs, nor a default exclude in rules, nor a
|
||||
// directory that device puts on a filesystem in rules that is not
|
||||
// persistent, nor, with -x, one that device puts on a different
|
||||
// filesystem than above, when device knows above's. It reaches every
|
||||
// regular file in a directory it enters, so for a regular-file operand
|
||||
// the directories checked start at its directory; they end below above.
|
||||
@@ -295,6 +301,15 @@ func walkReaches(above, r string, oneFS bool, rules walkRules,
|
||||
return false
|
||||
}
|
||||
|
||||
if filepath.Base(dir) == zfsDirName {
|
||||
return false
|
||||
}
|
||||
|
||||
fi, err = os.Lstat(dir)
|
||||
if err == nil && fi.Mode()&fs.ModeSymlink != 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
dev, ok := device(dir)
|
||||
if !ok {
|
||||
continue
|
||||
@@ -883,7 +898,7 @@ func operandWarning(root string, fi fs.FileInfo) string {
|
||||
case mode.IsRegular():
|
||||
return ""
|
||||
case mode.IsDir():
|
||||
if filepath.Base(root) != ".zfs" {
|
||||
if filepath.Base(root) != zfsDirName {
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -1153,7 +1168,7 @@ func subdirJob(ctx context.Context, p string, e fs.DirEntry,
|
||||
parent dirJob, oneFS bool, rules walkRules,
|
||||
events chan<- walkEvent,
|
||||
) (dirJob, bool) {
|
||||
if e.Name() == ".zfs" {
|
||||
if e.Name() == zfsDirName {
|
||||
return dirJob{}, false
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user