Skip to main content

lib/wick.ex

defmodule Wick do
  @moduledoc """
  Build FUSE userspace filesystems on the BEAM.

  Wick has two layers and deliberately stops there — it does not impose
  a filesystem abstraction. You drive the protocol loop yourself; the
  [Writing a filesystem](writing-a-filesystem.html) guide walks through
  a complete read-only example.

  ## Transport

    * `Wick.Native` — opens `/dev/fuse`, arms `enif_select` readiness
      notifications, and does bounded `read_frame/1` / `write_frame/2`
      of protocol frames.
    * `Wick.Fusermount` — mounts and unmounts via the setuid
      `fusermount3` helper.

  ## Codec

    * `Wick.Protocol` — a pure-Elixir codec for the Linux FUSE kernel
      protocol (FUSE_KERNEL_VERSION 7.31). `decode_request/1` turns a
      kernel frame into an opcode, a `Wick.Protocol.InHeader`, and a
      request struct; `encode_response/3` builds the reply frame.

  ## The request/response loop

  A FUSE server is an event loop over a single mounted fd:

    1. `Wick.Fusermount.mount/2` returns a handle.
    2. `Wick.Native.select_read/1` arms one read-readiness
       notification; the owning process then receives
       `{:select, handle, :undefined, :ready_input}` when a request is
       waiting.
    3. `Wick.Native.read_frame/1` reads one request frame.
    4. `Wick.Protocol.decode_request/1` decodes it.
    5. You build a reply and write it with
       `Wick.Protocol.encode_response/3` and
       `Wick.Native.write_frame/2` (or `Wick.Protocol.encode_error/2`
       for an errno).
    6. Re-arm with `select_read/1` and repeat — the notification is
       one-shot.

  ## The INIT handshake

  The kernel's **first** request after a mount is `:init`, and nothing
  else works until you answer it with a `Wick.Protocol.Response.Init`
  carrying a compatible version (clamp the minor to 31) and your
  negotiated `max_write`. See the guide for the full handshake.

  > #### Linux only {: .info}
  >
  > The transport binds the Linux FUSE ABI, so `Wick.Native` and
  > `Wick.Fusermount` only run on Linux. `Wick.Protocol` is pure
  > Elixir and runs anywhere.
  """
end