The 9P protocol is the protocol for network file systems used in
Plan9.  Plan9 is not a widely used operating system, but it's widely
considered more true to the Unix spirit than Unix is, coming from some
of the same people who made Unix as well.

## Overview

To get a rough idea of the 9P protocol, consider a system where all
the original core Unix syscalls (`open`, `close`, `read`, `write`,
...)  are lifted to be remote procedure calls.  These can be sent over
the network, making file systems in Plan9 network transparent.

9P's RPCs are documented in Plan9's man page section 5
([mirror](http://man.cat-v.org/plan_9/5/)). The supported methods are:

 * Session control
   * `version` to negotiate the protocol version.
   * `attach` and `auth` for authenticating with the remote end and opening a session.
   * `flush` to cancel ongoing requests.
 * Basic file operations:
   * `open`
   * `clunk` (equivalent to `close`)
   * `read`
   * `write`
 * Working with directories
   * `walk` to descend a directory hierarchy.
   * `stat` and `wstat` for querying and modifying a directory entries
     (e.g. to rename files).
   * `remove` for removing file entries.

In addition, there is an `error` response which may be returned as
response to any of these requests.

The handle to a file is called "file ID" (fid) in Plan9 lingo.  This
can be thought of as a file descriptor.

The 9P protocol does away with a bunch of complexities that Unix, and
particularly Linux has started to have.  Some of the non-supported
features are:

 * There is no `mmap` support in the protocol.  This can't be done over the network.
   Presumably it can be emulated within limits if needed.
 * No `ioctl`.  Control-style operations are often done through reads and writes
   to special purpose files.  There are often textual command languages.
 * There is a more blurry line between different file types as in Unix,
   where you can distinguish named pipes, device files and regular files.

## Playing with Plan9port

An easy way to play with 9P is to install Plan9port, a Linux userspace
port of Plan9's core tools and wiring, which comes as installable
package with many Linux distributions.

Plan9port includes the Plan9 compiler, the acme text editor and other
things, including source code.  Many of these tools are exposing 9P
file systems over Unix sockets in the `/tmp/ns.$USER.$DISPLAY`
directory.  You can get your exact location by running the `namespace`
tool:

```sh
$ namespace
/tmp/ns.me:0
$
```

For example, you might want to start up the `factotum` authentication
service and have a peek at the created file system.  Plan9port's `9p`
tool lets you do simple accesses from the command line:

```sh
$ /usr/lib/plan9/bin/factotum
$ ls $(namespace)
factotum
$ 9p ls factotum
confirm
conv
ctl
log
needkey
proto
rpc
$
```

There are also public 9P services, such as the Plan9 "sources"
repository.  After the Bell Labs server went down, these continue to
be mirrored by services such as `sources.9p.io`.  The `9fs` script is
a wrapper for quickly mounting this remote service, but needs a little
modification for convenience:

```sh
$ cat $PLAN9/bin/9fs \
  | sed -e 's/sources.cs.bell-labs.com/sources.9p.io/' > ~/9fs
$ chmod +x ~/9fs
$ ~/9fs sources
$ 9p ls -l sources
d-rwxrwxr-x M 0 9grid  9grid       0 Jul 15  2018 9grid
--rw-rw-r-- M 0 bootes sys         0 Jun 24  2013 _sources
d-rwxrwxr-x M 0 adm    sys         0 Jul 15  2018 adm
d-rwxrwxr-x M 0 sys    sys         0 Oct 28 19:18 contrib
d-rwxrwxr-x M 0 bootes sys         0 Jul 15  2018 dist
d-rwxrwxr-x M 0 sys    sys         0 Jul 15  2018 extra
--rw-rw-r-- M 0 bootes adm   9142602 Jan 23  2015 lsr
d-rwxrwxr-x M 0 geoff  nix         0 Jul 15  2018 nix
d-rwxrwxrwx M 0 glenda sys         0 Jul 15  2018 patch
d-rwxrwxr-x M 0 sys    sys         0 Jul 15  2018 plan9
d-rwxrwxr-x M 0 sys    sys         0 Jul 15  2018 wiki
d-rwxrwxr-x M 0 xen    xen         0 Jul 15  2018 xen
$
```

> **💡 Hint**: To make browsing more convenient, you may also use the FUSE
> file system which comes with Plan9port:
>
> ```sh
> $ 9pfuse unix\!/tmp/ns.$USER.:0/sources /tmp/sources
> $ ls /tmp/sources
> 9grid  contrib  extra  nix    plan9     wiki
> adm    dist     lsr    patch  _sources  xen
> $
> ```
{.info}

## Looking under the hood

Let's first read a small file from the Plan9 sources repo:

```sh
$ 9p read sources/plan9/NOTICE
Copyright © 2002 Lucent Technologies Inc.
All Rights Reserved
$
```

To look under the hood of 9P, we can use the `9p` tool's `-D` option
to print all requests and responses.

```sh
$ 9p -D read sources/plan9/NOTICE
<- Tversion tag 0 msize 8192 version '9P2000'
-> Rversion tag 65535 msize 8192 version '9P2000'
<- Tauth tag 0 afid 0 uname me aname <nil>
-> Rerror tag 0 ename authentication rejected
<- Tattach tag 0 fid 0 afid -1 uname me aname
-> Rattach tag 0 qid (0000000000000002 0 d)
<- Twalk tag 0 fid 0 newfid 1 nwname 2 0:plan9 1:NOTICE
-> Rwalk tag 0 nwqid 2 0:(0000000000081aa0 78 d) 1:(0000000000081d2d 1 )
<- Topen tag 0 fid 1 mode 0
-> Ropen tag 0 qid (0000000000081d2d 1 ) iounit 8168
<- Tread tag 0 fid 1 offset 0 count 4096
-> Rread tag 0 count 63 '436f7079 72696768 7420c2a9 20323030 32204c75 ...'
Copyright © 2002 Lucent Technologies Inc.
All Rights Reserved
<- Tread tag 0 fid 1 offset 63 count 4096
-> Rread tag 0 count 0 ''
<- Tclunk tag 0 fid 1
-> Rclunk tag 0
$
```

The `9p` tool opens the Unix socket at `/tmp/ns.me.:0/sources` to talk
to the backend service.

The steps are:

 1. Version negotiation: Both sides confirm the 9P variant they want
    to speak.
 2. Authentication: The `auth` call is normally supposed to return an
    open file ID, over which to speak an authentication protocol. In
    this case, the service permits unauthenticated read accesses, so
    this is returning an error.
 3. Attaching to the service, retrieving the desired root directory,
    in this case it's just the root.
    (Note, the client picks which FID it would like to use for
    identifying files.)
 4. Walking down to the desired file from the root FID 0, yielding
    the new FID 1.
 5. Opening the FID for reading.
 6. Calling `read` until nothing is returned any more.
 7. Closing the FID with `clunk`.

## Some resources

 * [9p.cat-v.org/documentation](http://9p.cat-v.org/documentation/)
 * [Plan9 intro(5)](http://man.cat-v.org/plan_9/5/intro)
 * [Writing a 9P server form scratch](https://blog.aqwari.net/9p/)
