
# Driver Interface

**`FsDriver` and the four structural types it is built from — the whole shape a driver has to have.**

```ts
import { S_IFDIR, S_IFMT, S_IFREG } from "mountx";
import type { DirentLike, FileHandleLike, FsDriver, StatsLike } from "mountx";
```

Prose version, with a complete driver you can run: [Writing a driver](/guide/drivers/custom).

## `FsDriver`

Three required methods; everything else optional, and **missing means the capability is absent**.

```ts
interface FsDriver {
  readonly capabilities?: FsCapabilities;
  readonly mountx?: MountxExtensions;

  // required
  stat(path: string): Promise<StatsLike>;
  readdir(path: string, options: { withFileTypes: true }): Promise<DirentLike[]>;
  open(path: string, flags?: string | number, mode?: number): Promise<FileHandleLike>;

  // optional
  lstat?(path: string): Promise<StatsLike>;
  statfs?(path: string): Promise<StatsFsLike>;
  mkdir?(path: string, options?: MkdirOptions): Promise<string | undefined>;
  rmdir?(path: string): Promise<void>;
  unlink?(path: string): Promise<void>;
  rename?(oldPath: string, newPath: string): Promise<void>;
  link?(existingPath: string, newPath: string): Promise<void>;
  symlink?(target: string, path: string, type?: string | null): Promise<void>;
  readlink?(path: string): Promise<string>;
  chmod?(path: string, mode: number): Promise<void>;
  chown?(path: string, uid: number, gid: number): Promise<void>;
  lchown?(path: string, uid: number, gid: number): Promise<void>;
  truncate?(path: string, length?: number): Promise<void>;
  utimes?(path: string, atime: TimeLike, mtime: TimeLike): Promise<void>;
  lutimes?(path: string, atime: TimeLike, mtime: TimeLike): Promise<void>;
}
```

Every `path` is **absolute, POSIX-style and normalized** before your driver sees it.

`FullFsDriver` is the same with every optional method required — the memory and node-fs drivers satisfy it, and so does `node:fs/promises`. `FsDriverMethod` is the union of the optional method names.

The two `readonly` members are on their own page: [Capabilities](/reference/capabilities).

## Structural types

All four are the _smallest_ shapes the transports need, so Node's own `Stats`, `StatsFs`, `Dirent` and `FileHandle` satisfy them unmodified.

### `StatsLike`

```ts
interface StatsLike {
  dev: number;
  ino: number;
  mode: number; // S_IFMT type bits | permission bits
  nlink: number;
  uid: number;
  gid: number;
  rdev: number;
  size: number;
  blksize: number;
  blocks: number;
  atimeMs: number;
  mtimeMs: number;
  ctimeMs: number;
  birthtimeMs: number;
  isFile(): boolean;
  isDirectory(): boolean;
  isSymbolicLink(): boolean;
  isBlockDevice(): boolean;
  isCharacterDevice(): boolean;
  isFIFO(): boolean;
  isSocket(): boolean;
}
```

### `DirentLike`

`{ name: string; parentPath?: string }` plus the same seven type predicates.

### `StatsFsLike`

`{ type, bsize, blocks, bfree, bavail, files, ffree }` — for `statfs(2)` and `df`.

### `FileHandleLike`

```ts
interface FileHandleLike {
  readonly fd?: number;
  read(
    buffer: Uint8Array,
    offset?: number | null,
    length?: number | null,
    position?: number | null,
  ): Promise<{ bytesRead: number; buffer: Uint8Array }>;
  write(
    buffer: Uint8Array,
    offset?: number | null,
    length?: number | null,
    position?: number | null,
  ): Promise<{ bytesWritten: number; buffer: Uint8Array }>;
  stat(): Promise<StatsLike>;
  truncate(length?: number): Promise<void>;
  close(): Promise<void>;
  sync?(): Promise<void>; // absent = nothing to flush
  datasync?(): Promise<void>;
}
```

Whether that handle is _real per-open state_ is the [`handles` capability](/reference/capabilities), one of the two that cannot be inferred.

## File-type constants

`S_IFMT`, `S_IFREG`, `S_IFDIR`, `S_IFLNK`, `S_IFBLK`, `S_IFCHR`, `S_IFIFO`, `S_IFSOCK` — the POSIX mode bits, for building and interrogating `StatsLike.mode`.

```ts
import { S_IFDIR, S_IFMT } from "mountx";

const isDirectory = (mode: number) => (mode & S_IFMT) === S_IFDIR;
```

## Next

- [Capabilities](/reference/capabilities) — what a driver declares, and what is inferred from the methods above.
- [Errors](/reference/errors) — what to throw out of them.
