1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//! Asynchronous 9P2000.L filesystem server library for Rust.
//!
//! This crate provides a tokio-based async implementation of the 9P2000.L protocol,
//! allowing you to build virtual filesystem servers that can be mounted using the
//! Linux kernel's v9fs module.
//!
//! # Overview
//!
//! The 9P protocol was originally developed for the Plan 9 distributed operating system.
//! 9P2000.L is an extended variant that adds Linux-specific features like proper
//! permission handling, symbolic links, and other POSIX semantics.
//!
//! # Getting Started
//!
//! To create a 9P filesystem server, you need to:
//!
//! 1. Define a type to represent your per-fid state (or use `()` for stateless fids)
//! 2. Implement the [`srv::Filesystem`] trait for your filesystem type
//! 3. Start the server with [`srv::srv_async`] or related functions
//!
//! # Example
//!
//! ```no_run
//! use rs9p::{srv::{Filesystem, FId, srv_async}, Result, FCall};
//! use async_trait::async_trait;
//!
//! // Define your filesystem
//! #[derive(Clone)]
//! struct MyFs;
//!
//! // Define per-fid state (or use () if you don't need state)
//! #[derive(Default)]
//! struct MyFId {
//! // Your per-fid data here
//! }
//!
//! #[async_trait]
//! impl Filesystem for MyFs {
//! type FId = MyFId;
//!
//! async fn rattach(
//! &self,
//! fid: &FId<Self::FId>,
//! _afid: Option<&FId<Self::FId>>,
//! _uname: &str,
//! _aname: &str,
//! _n_uname: u32,
//! ) -> Result<FCall> {
//! // Initialize the root fid and return its qid
//! Ok(FCall::RAttach {
//! qid: rs9p::QId {
//! typ: rs9p::QIdType::DIR,
//! version: 0,
//! path: 0,
//! }
//! })
//! }
//!
//! // Implement other required methods...
//! }
//!
//! #[tokio::main]
//! async fn main() -> Result<()> {
//! let fs = MyFs;
//! srv_async(fs, "tcp!127.0.0.1!564").await
//! }
//! ```
//!
//! # Protocol Details
//!
//! ## Message Flow
//!
//! 1. **Version Negotiation**: Client sends `TVersion`, server responds with `RVersion`
//! 2. **Authentication** (optional): `TAuth`/`RAuth` exchange
//! 3. **Attach**: Client attaches to the filesystem root with `TAttach`
//! 4. **Operations**: Client performs file operations (`walk`, `open`, `read`, `write`, etc.)
//! 5. **Cleanup**: Client clunks fids with `TClunk` to release resources
//!
//! ## FId Management
//!
//! A "fid" (file identifier) is a 32-bit handle used by the client to reference a file
//! or directory. The server must track the mapping between fids and filesystem objects.
//!
//! **Important invariants:**
//! - Each fid is unique per connection
//! - FIds persist across operations until explicitly clunked
//! - Walking to a new fid creates a new fid (the old one remains valid)
//! - After `TClunk`, the fid is invalid and will be removed
//!
//! # Error Handling
//!
//! Return errors using the [`error::Error`] type. The server will automatically
//! convert these to `RlError` messages with appropriate error codes (errno).
//!
//! Common error codes:
//! - `ENOENT` - File not found
//! - `EACCES` / `EPERM` - Permission denied
//! - `EISDIR` - Is a directory (when file expected)
//! - `ENOTDIR` - Not a directory (when directory expected)
//! - `EBADF` - Bad file descriptor (invalid fid)
//! - `ELOOP` - Too many levels of symbolic links
//!
//! # Transport
//!
//! The library supports multiple transports:
//! - **TCP**: `"tcp!host!port"` (e.g., `"tcp!0.0.0.0!564"`)
//! - **Unix Domain Sockets**: `"unix!path!suffix"` (e.g., `"unix!/tmp/socket!0"`)
//!
//! # Feature Flags
//!
//! This crate uses workspace dependencies and requires:
//! - `tokio` with `full` features for async runtime
//! - `async-trait` for trait async methods
//!
//! # Safety
//!
//! This crate forbids unsafe code (`#![forbid(unsafe_code)]`) and relies on Rust's
//! type system for memory safety. All filesystem operations are async and designed
//! to be cancellation-safe.
pub use crateError;
pub use crateerrno;
pub use cratestring as errstr;
pub use crate*;
pub use crateResult;