Documentation
¶
Overview ¶
Package regularfile opens a file named by a pathname only when it is a regular file on a filesystem that stores bytes, without waiting on it and without opening a device.
ONE OPEN, IN ONE PLACE. A plain open of a FIFO blocks until somebody writes to it, before any stat a caller could make, and no timeout in billet bounds that wait; a plain open of a device is an operation on the device (a watchdog is armed by its open); a plain read of a regular-mode file on procfs can wait for the kernel's next message. Every file billet reads by a pathname it did not create this instant, a configuration, a lock file, an environment file systemd names, a certificate, a record of its own under a root-owned directory, is a name a host could put something else at, and a check that hangs or arms a device before it can refuse is neither yes, no nor could-not-tell. On Linux the name is opened for its identity alone (O_PATH), the descriptor is fstat'ed and its filesystem asked for, and only a regular file on an ordinary filesystem is reopened for reading, non-blocking, through /proc/self/fd on the inode already held, so nothing is read or opened before the refusal and no pathname is resolved a second time. Elsewhere there is no identity-only open: the file is opened read-only and non-blocking, which returns at once on a FIFO, and the descriptor is fstat'ed before anything is read; a device there IS opened and then refused, which the caller's platform decides is acceptable.
FSTAT ON THE DESCRIPTOR, NOT STAT ON THE PATH, so what is refused and what is read are the same object. A stat of the name answers about whatever the name meant at that instant, and a replacement between the stat and the open is read for the original.
WHAT THIS DOES NOT BOUND: a read from ordinary storage that stalls (a network filesystem, a failing disk) is not refused here; the pseudo-filesystem rule is an enumerated denylist, and one outside it that dispatches reads to a driver would be read; and a write lease on the file is broken, not waited for: its holder is signalled and the lease marked for downgrade before the kernel answers EWOULDBLOCK. Each is the platform's residual and is said to be.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrNotRegular = errors.New("not a regular file")
ErrNotRegular is the refusal of anything but a regular file. It is wrapped in an *os.PathError naming the path, beside the mode that was found.
var ErrReopen = errors.New("could not reopen the held file for reading")
ErrReopen is the failure to turn a held identity descriptor into a readable one. IT NEVER WRAPS THE CAUSE'S ERRNO: a reopen that failed for want of /proc/self/fd is not the file's absence, and a caller that recognises fs.ErrNotExist as "absent" must never see it here.
var ErrTooLarge = errors.New("larger than the limit")
ErrTooLarge is ReadFile's refusal of a file longer than its limit; the limit is a statement about what billet wrote, and a longer file is not that.
var ErrUnsupportedFilesystem = errors.New("not on a filesystem that stores bytes")
ErrUnsupportedFilesystem is the refusal of a regular-mode file on a kernel pseudo-filesystem (procfs, sysfs and their kind), whose reads are not reads of stored bytes and can wait.
Functions ¶
func Open ¶
Open opens path for reading only when it is a regular file on an ordinary filesystem, and returns the readable descriptor with the fstat that admitted it. A missing file is an *os.PathError wrapping fs.ErrNotExist, as os.Open returns; anything that is not a regular file is an *os.PathError wrapping ErrNotRegular; a pseudo-filesystem is one wrapping ErrUnsupportedFilesystem; a reopen that failed is one wrapping ErrReopen and nothing a caller reads as absence.
func ReadAllLimited ¶
ReadAllLimited reads the rest of an already admitted descriptor under the same rule as ReadFile: at most limit bytes, a longer file refused rather than cut.
func ReadFile ¶
ReadFile reads the whole of a regular file of at most limit bytes through Open. A longer file is refused with ErrTooLarge, never truncated, because a caller's limit says what a file billet wrote can be, and the hash or the parse of a prefix would describe something that was never the file.