import { type SetAttrFields } from '../../../../types.ts';
import type { MutationJournal } from './journal.ts';
import type { ErrnoCodes, FlushFailure, FSHost, FSNode, FSStream, FSType, SetAttr, SyncVFS } from './types.ts';
/**
 * The metadata a `setattr` actually changes, or null when it changes
 * none of it.
 *
 * Emscripten hands this callback more than a guest's chmod and utime:
 * a stamp arrives beside a resize and beside a mode, and a write that
 * moved no field would still journal an op. Sending one costs a
 * dispatch and, worse, splits two writes the journal would otherwise
 * coalesce. Comparing against the node costs one read.
 *
 * The one case comparing cannot catch is a create, whose finalizing
 * chmod does lower a real mode; `PyodideFs.fresh` is what suppresses
 * that one.
 *
 * `ctime` is never included: no POSIX call sets it directly, so a mount
 * has nothing to write it to. `size` is not metadata here either, it is
 * the resize branch's bytes.
 *
 * Args:
 *   node: the node as it stands before the write.
 *   attr: the fields Emscripten passed, times as epoch ms.
 */
export declare function changedAttrs(node: FSNode, attr: SetAttr): SetAttrFields | null;
/**
 * An Emscripten filesystem backed by a mirage mount.
 *
 * This is the pyodide runtime's interception layer. Mounting it at a mount
 * prefix puts mirage below the guest's syscall boundary, where every
 * spelling of an operation (`open`, `os.open`, `pathlib`, `shutil`'s
 * fd-relative walk) arrives as the same callback. Nothing is patched
 * inside the interpreter.
 *
 * Callbacks are synchronous: lookups, reads and writes wait for the host
 * through SyncVFS, which needs the worker. A file's stream reads and
 * writes through a handle on the run's open-file core, which holds its
 * bytes as every other runtime's open files are held; names and metadata
 * enter the journal and land at once, in guest order.
 *
 * The node table lives in `NodeTable`; what is left here is one method
 * per Emscripten callback, plus the errno translation only this layer
 * performs.
 */
export declare class PyodideFs {
    private readonly sync;
    private readonly deferred;
    private readonly streams;
    readonly type: FSType;
    private readonly host;
    private readonly errno;
    private readonly journal;
    private readonly nodes;
    private readonly mountOf;
    private fresh;
    /**
     * Args:
     *   host: the Emscripten FS namespace (`pyodide.FS`).
     *   errno: Emscripten's errno table (`pyodide.ERRNO_CODES`).
     *   journal: the write-ahead log guest mutations are recorded on.
     *   prefix: the mount prefix this filesystem serves.
     *   mountOf: the mirage mount owning a path (`RuntimeFiles.mountOf`).
     *     One mountpoint serves every mirage mount nested under its
     *     prefix, so this is the only boundary fact left to check ops
     *     against; Emscripten's own cross-mount checks cannot see it.
     *   sync: the worker's blocking way to the mounts.
     *   deferred: the refusals the mount gave a path whose call has not
     *     come yet, shared by every mountpoint as the journal is.
     *   streams: the file streams that hold a core handle, shared the same
     *     way, which the run's end closes.
     */
    constructor(host: FSHost, errno: ErrnoCodes, journal: MutationJournal, prefix: string, mountOf: (path: string) => string | null, sync: SyncVFS, deferred?: Map<string, FlushFailure>, streams?: Set<FSStream>);
    private getattr;
    /**
     * One node's stat, its inode named by `path`.
     *
     * Args:
     *   node: the node to describe.
     *   path: the name its inode is reported under.
     *   fh: the core handle a stream stats through, which counts what it
     *     holds; absent stats the node's path.
     */
    private attrOf;
    private setattr;
    /**
     * Resize a file whose name is gone through a stream that writes it: its
     * bytes are only what the core's handles on it hold.
     *
     * Args:
     *   node: the file with no name left.
     *   size: the length it is left at.
     */
    private resizeHeld;
    private lookup;
    private mknod;
    private rename;
    private unlink;
    /**
     * A file whose name the mount removed or replaced. One a stream has open
     * reads and writes on through the core, which keeps its bytes; marked
     * only once the mount took the change, so a refused removal leaves it
     * named.
     *
     * Args:
     *   node: the file that lost its name.
     */
    private orphan;
    private rmdir;
    /**
     * The directory's names, asking the mount for any it has gained.
     *
     * The first listing is classified, since Emscripten's getdents reads
     * every name's kind off its node. A node is never re-asked about once
     * placed, so a later listing asks for names alone and stats only the
     * names the tree lacks, rather than classifying every entry again.
     */
    private readdir;
    invalidate(): void;
    /**
     * Send the journal to the mount now, in guest order. An entry the mount
     * refuses fails the call that touched its path with the mount's errno,
     * this call or that file's next one (its close), as a deferred write
     * error does; until then nothing more for that path reaches the mount,
     * and every other file's entries still land. Without a worker there is
     * no mount to send to yet, and the journal waits for the run's end.
     *
     * Args:
     *   paths: the paths this call touched.
     */
    private settle;
    private readThrough;
    private placeEntry;
    /**
     * Restamp a node placed from an unclassified row with what the mount
     * said it is.
     *
     * The listing that placed it swallowed a failed stat so the rest of
     * the directory could list; the guest's own stat is where that
     * failure belongs, so that stat asks the mount rather than answering
     * from the guess. Its answer turns the node into a directory if that
     * is what it is.
     *
     * Args:
     *   node: the node to classify.
     *   stat: the row the guest's stat got.
     */
    private classifyNode;
    /**
     * Create a symlink node and record it for the mounts.
     *
     * A link is namespace state, which is exactly why this can be served:
     * the op reaches the node table rather than a backend, so a link lands
     * on an s3 or notion mount whose store has no such thing. The target
     * is stored as typed and never resolved here.
     *
     * Args:
     *   parent: directory the link is created in.
     *   name: the link's own name.
     *   target: what it points at, verbatim.
     */
    private symlink;
    /**
     * The target of a symlink node.
     *
     * Args:
     *   node: the node to read.
     */
    private readlink;
    /**
     * Open a file's stream on the run's core, which judges, holds and lands
     * it as it does every runtime's open files. Emscripten made the open's
     * create and truncate before it got here; what is left is how the
     * stream reads and writes.
     */
    private streamOpen;
    /**
     * The core handle a file's stream reads and writes through. One a run's
     * end closed opens again, as long as its file still has a name: the
     * core held the file for that run only. A guest that exited
     * (`os._exit`, caught) has no files left. `create` makes the file the
     * open's own mknod named.
     */
    private handleOf;
    /** Land what the stream wrote and let its handle go. */
    private streamClose;
    private streamRead;
    private streamWrite;
    private llseek;
}
//# sourceMappingURL=fs.d.ts.map