Resolve scan operands to their real paths (closes #144)
check / check (push) Canceled after 0s
check / check (push) Canceled after 0s
scan now resolves every operand with its symlinks followed before the walk, and uses that real path for pruning, walking, records and warnings. A relative operand is joined to the working directory as the kernel reports it, so a ".." after a symlink counts from its target, as with realpath. A symlink operand is scanned at its target instead of skipped. An operand given through a symlink below another operand, to a directory outside it, is walked on its own instead of dropped with its records deleted. An operand that cannot be resolved is a fatal error naming the operand as given. The walk itself still follows no symlink. Model: opus-5-5
This commit is contained in:
@@ -348,17 +348,24 @@ default. An operand may be a directory or a regular file.
|
||||
|
||||
- `scan` with no operand is a usage error. The usage text goes to stderr, and
|
||||
the exit code is 2.
|
||||
- An operand that does not exist is a fatal error. `scan` then stops before it
|
||||
walks anything, and exits 1.
|
||||
- Each operand is made absolute before the walk. A relative operand is joined to
|
||||
the working directory as `pwd` prints it, with its symlinks kept. A `.` or
|
||||
`..` in it is resolved as text, and symlinks are not followed. Each record is
|
||||
stored under that absolute path.
|
||||
- An operand that does not exist is a fatal error, and so is a symlink whose
|
||||
target does not exist. `scan` then stops before it walks anything, and exits
|
||||
with code 1.
|
||||
- Each operand is resolved to its real path before the walk, as `realpath`
|
||||
prints it. A relative operand is joined to the working directory as `pwd -P`
|
||||
prints it. Every symlink in the path is then followed. A `..` after a symlink
|
||||
counts from the directory the symlink leads to. From then on the operand is
|
||||
that real path. Its files are recorded under it, and warnings name it.
|
||||
- An operand that is a symlink is scanned at its target's real path. After a
|
||||
`cd` through a symlink, `scan .` records its files under the real path of the
|
||||
working directory.
|
||||
- All operands belong to one scan, and one walk covers them all at once (see
|
||||
"Concurrency").
|
||||
- An operand that repeats another is dropped before the walk.
|
||||
- An operand that repeats another is dropped before the walk. Two operands
|
||||
repeat each other when their real paths are the same.
|
||||
- An operand under another operand is dropped the same way, unless one of the
|
||||
cases below applies. No path is then walked twice.
|
||||
cases below applies. This too is judged on real paths. No path is then walked
|
||||
twice.
|
||||
- An operand under another is kept, and walked on its own, when the inner
|
||||
operand or a directory between the two is one of these:
|
||||
- a default exclude (see "Rules for the walk");
|
||||
@@ -369,25 +376,21 @@ default. An operand may be a directory or a regular file.
|
||||
memory (see "Rules for the walk"). The outer operand's walk does not enter
|
||||
such a directory, so the inner operand is walked on its own.
|
||||
|
||||
- No other case keeps an operand under another. An operand reached through a
|
||||
symlinked directory below the outer operand is dropped too. The outer
|
||||
operand's walk does not follow the symlink, so no file under the inner operand
|
||||
is scanned. The records that an earlier scan left under it are deleted. The
|
||||
`-x` case above also covers an operand reached that way.
|
||||
- An operand that is neither a regular file nor a directory is not scanned.
|
||||
`scan` prints a warning naming the path and what it is. It counts the operand
|
||||
as skipped and drops it. An operand beneath a symlink operand is scanned all
|
||||
the same. The scan keeps the records beneath a dropped operand, unless another
|
||||
operand covers them. After a `cd` through a symlink, `scan .` names the
|
||||
symlink and is skipped as a symlink operand. `scan sub` in that directory
|
||||
records its files under the symlink's path. `report` can then list each as a
|
||||
duplicate of the same file recorded under its real path.
|
||||
- No other case keeps an operand under another.
|
||||
- With `/srv/link` a symlink to a directory outside `/srv`,
|
||||
`scan /srv /srv/link/sub` walks `sub` on its own, at its real path.
|
||||
- An operand that is neither a regular file nor a directory is not scanned. Such
|
||||
an operand is, for example, a symlink to a device node. `scan` prints a
|
||||
warning naming the real path and what it is. It counts the operand as skipped
|
||||
and drops it. The scan keeps the records beneath a dropped operand, unless
|
||||
another operand covers them.
|
||||
- An operand at or inside a directory named `.zfs` is never scanned, whether
|
||||
given alone or under another operand. The check looks at the path as given and
|
||||
at the path with its symlinks resolved. `scan` prints a warning naming the
|
||||
path, counts the operand as skipped and drops it. The records beneath it are
|
||||
kept, unless it lies under another operand. Then they are deleted, because
|
||||
that operand's walk never enters `.zfs` (see "Rules for the walk").
|
||||
given alone or under another operand. The check looks at the real path, so a
|
||||
symlink into a `.zfs` directory is not scanned either. `scan` prints a warning
|
||||
naming the real path, counts the operand as skipped and drops it. The records
|
||||
beneath it are kept, unless it lies under another operand. Then they are
|
||||
deleted, because that operand's walk never enters `.zfs` (see "Rules for the
|
||||
walk").
|
||||
- An operand on a filesystem that is not persistent is dropped too. `scan`
|
||||
prints a line naming it and its filesystem type, and does not count it as
|
||||
skipped.
|
||||
@@ -484,12 +487,12 @@ walk practical on large or busy storage pools.
|
||||
The walk knows them by device ID and inode number. The device ID is the
|
||||
number by which the kernel tells filesystems apart. The inode number tells
|
||||
the files of one filesystem apart. So the walk passes over them whatever
|
||||
path leads to them. The walk follows no symlink it finds. It does open each
|
||||
operand at the path given, even when that path runs through a symlinked
|
||||
directory. Such an operand can lead to the database files, and the walk
|
||||
passes over them there as well. The walk prints no line for the database
|
||||
files and does not count them as skipped. A record that an earlier scan left
|
||||
for one of them is deleted.
|
||||
path leads to them. The walk follows no symlink it finds. It opens each
|
||||
operand at its real path, not the path given. An operand given through a
|
||||
symlink can lead to the database files, and the walk passes over them there
|
||||
as well. The walk prints no line for the database files and does not count
|
||||
them as skipped. A record that an earlier scan left for one of them is
|
||||
deleted.
|
||||
|
||||
- By default the walk enters directories on other filesystems than its
|
||||
operand's. With `-x`, it never enters a directory on a different filesystem
|
||||
@@ -1138,7 +1141,7 @@ showing the count it stopped at.
|
||||
- `0`: success, even when files were skipped with warnings.
|
||||
- `1`: a fatal error, or a `scan` stopped by `SIGINT` or `SIGTERM`. A fatal
|
||||
error is one of these:
|
||||
- an operand that does not exist, or whose details `scan` cannot read;
|
||||
- an operand that does not exist, or whose real path `scan` cannot find;
|
||||
- a list of mounted filesystems that `scan` cannot read;
|
||||
- another `scan` holding the lock (see "The scan lock");
|
||||
- a database, its directory or its lock file that cannot be created or
|
||||
|
||||
Reference in New Issue
Block a user