check / check (push) Canceled after 0s
scan never records or reads anything on a filesystem that is not persistent (tmpfs, proc, sysfs and the like), however it reaches it; no flag turns this off. It notes each such filesystem's device ID as it starts: on Linux from /proc/self/mountinfo, on macOS by lstat of each listed mount point. Below an operand the walk also skips the default excludes, a path list per system (Linux, macOS, and Windows, not used yet); --no-default-excludes turns off only those. A default exclude that is itself an operand gets no skip line. The tests stop at once, saying why, when TMPDIR is not on a persistent filesystem. Judgement call: an unreadable mount list fails the scan, and no flag gets round it. Judgement call: a file on such a filesystem below an operand gets the same line as a directory. Judgement call: such an operand that another operand's walk also reaches is named twice. Unverified: whether macOS's mount list gives the device lstat reports, so macOS keeps lstat, and a hidden mount there can still add another filesystem's device. Unverified: the macOS code is never built or run here; bind mounts need root to test. Model: opus-5-5
53 lines
1.2 KiB
Go
53 lines
1.2 KiB
Go
//go:build darwin
|
|
|
|
package main
|
|
|
|
import (
|
|
"slices"
|
|
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
// nonPersistentFilesystems returns the device ID of every mounted
|
|
// filesystem that is not persistent, with its type, from the system's
|
|
// list of mounted filesystems. The device ID is read with lstat on the
|
|
// mount point. Where one filesystem is mounted over another on the same
|
|
// mount point, the later one in the list counts. A mount point that
|
|
// lstat cannot reach is left out.
|
|
func nonPersistentFilesystems() (map[uint64]string, error) {
|
|
// The first call counts the filesystems, the second lists them.
|
|
n, err := unix.Getfsstat(nil, unix.MNT_NOWAIT)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
list := make([]unix.Statfs_t, n)
|
|
|
|
n, err = unix.Getfsstat(list, unix.MNT_NOWAIT)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
mounts := make(map[string]string, n)
|
|
|
|
for _, st := range list[:n] {
|
|
mounts[unix.ByteSliceToString(st.Mntonname[:])] =
|
|
unix.ByteSliceToString(st.Fstypename[:])
|
|
}
|
|
|
|
types := nonPersistentFilesystemTypes()
|
|
devices := make(map[uint64]string)
|
|
|
|
for mountPoint, fsType := range mounts {
|
|
if !slices.Contains(types, fsType) {
|
|
continue
|
|
}
|
|
|
|
if dev, ok := deviceOfPath(mountPoint); ok {
|
|
devices[dev] = fsType
|
|
}
|
|
}
|
|
|
|
return devices, nil
|
|
}
|