import type { Files } from '../../workspace/files.ts';
import type { SessionState } from '../../workspace/session/session.ts';
import { type WorkspaceBinding } from '../binding.ts';
import type { MountType, PipeWriter, RunResult, SandboxPipe } from '../types.ts';
/** A served prefix's SFTP server, as `session` (node's PipeServer). */
export interface PipeServer {
    /** Answer the client's requests on its pipe until it closes it. */
    serve(reader: ReadableStream<Uint8Array>, writer: PipeWriter): Promise<void>;
    /** Land every write the client has been told is done. */
    sync(): Promise<void>;
}
/**
 * Where node puts the SFTP server a served prefix's pipe runs: as
 * `session`, each request run by `run`. Core has none of its own:
 * MountCore and ssh2 are node's.
 */
export declare function registerPipeServer(make: (files: Files, session: SessionState, run: (op: () => Promise<void>) => Promise<void>) => PipeServer): void;
/**
 * Each mountpoint a `/proc/mounts` lists, with its type. The kernel
 * escapes a space in a path as `\040`; that is undone. A point mounted
 * twice keeps the later (top) entry's type.
 */
export declare function mountTable(text: string): Map<string, string>;
/**
 * The prefixes a sandbox mounts: each one under no other. A prefix under
 * another is served through it. The root and the workspace's devices are
 * left out: a sandbox's `/` and `/dev` are its own, and nothing can be
 * mounted over them.
 */
export declare function topPrefixes(prefixes: Iterable<string>): string[];
/**
 * The workspace prefixes one sandbox sees, by its `mountType`.
 *
 * `ssh`: every prefix the session sees is served from the host over SFTP,
 * and the sandbox mounts each with `sshfs -o passive` on a pipe the
 * provider holds open, so every file op in the sandbox is an op of the
 * session, held to its hides, modes and policies. `fuse`: a mirage in the
 * sandbox serves its prefixes itself and the host serves none. `both`: a
 * prefix the sandbox already mounts is its own, and the host serves the
 * rest. A prefix the sandbox serves itself is out of the session's rules'
 * reach, so a line is refused while a hide, rule or mode cap covers
 * anything under one, hidden mounts included.
 *
 * Each line first brings the mounts in step with the workspace: a mount
 * added or shown since is served, one hidden is dropped, and a server
 * that ended is started again. While a rule reaches under a prefix, the
 * sandbox's own mounts are read again for each line, so one it mounted
 * since is refused too. A server runs outside the line that started it,
 * so it answers as the session alone and never with a grant that line was
 * given. What the host serves shows one session's view, and a program a line starts may outlive it, so under `ssh` and
 * `both` the sandbox belongs to the first session it serves or runs a line
 * for, until it is closed: a line of another session is refused rather
 * than shown, or showing, the first one's view, and so is a session made
 * again under the same id, which a program the first one started could
 * otherwise read through. Under `fuse` the host serves nothing, and any
 * session may run.
 */
export declare class SandboxMounts {
    private readonly runtime;
    private readonly mountType;
    private readonly run;
    private readonly openPipe;
    private session;
    private readonly lines;
    private readonly served;
    private seen;
    private lock;
    /**
     * @param runtime the runtime's name, for messages.
     * @param mountType ssh, fuse or both.
     * @param run runs one setup command in the sandbox.
     * @param openPipe starts a command in the sandbox with its stdin and
     *   stdout held open.
     */
    constructor(runtime: string, mountType: MountType, run: (line: string, signal?: AbortSignal) => Promise<RunResult>, openPipe: (command: string) => Promise<SandboxPipe>);
    get fileEffectsDispatched(): boolean;
    /**
     * Bring the mounts in step, then refuse a line that may not run: one the
     * session's restrictions reach past the dispatcher is refused as a policy
     * refuses it (126), one the sandbox cannot serve because another session
     * holds it fails (1). Null when the line may run.
     */
    admit(binding: WorkspaceBinding | null, signal?: AbortSignal): Promise<RunResult | null>;
    /** Unmount every served prefix and end its SFTP server. */
    close(): Promise<void>;
    /**
     * Land every write a served prefix's server has acknowledged.
     *
     * sshfs answers close(2) once the file's writes are acknowledged and
     * sends the SFTP close that lands them afterwards, so a line can end
     * before they land. Its programs have closed their files by then, so
     * this lands every one, outside the line as that close would, and
     * `fileEffectsDispatched` holds. Each landing keeps the line's write
     * admission alone: a capture waiting for the line lets it through rather
     * than waiting on it. Then the line lends its admission to no more
     * requests, and waits out the ones it lent it to, so a capture never
     * reads past one still running.
     */
    sync(): Promise<void>;
    /**
     * Run one served request with the write admission of the latest line
     * running in the sandbox, from its `admit` to its `sync`, and none
     * between lines. A program's file op then counts as its line's, so a
     * capture waiting for that line lets it land rather than holding it while
     * the line waits on it.
     */
    private lend;
    private unserved;
    private locked;
    private reconcile;
    private serve;
    /** Remove the helper's setup log; keeping it only costs a file. */
    private dropLog;
    private table;
    private drop;
    private unmount;
}
//# sourceMappingURL=mounts.d.ts.map