1
#![doc(html_logo_url = "https://raw.githubusercontent.com/sevki/jetstream/main/logo/JetStream.png")]
2
#![doc(
3
    html_favicon_url = "https://raw.githubusercontent.com/sevki/jetstream/main/logo/JetStream.png"
4
)]
5
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
6
// Copyright (c) 2024, Sevki <s@sevki.io>
7
// Copyright 2018 The ChromiumOS Authors
8
// Use of this source code is governed by a BSD-style license that can be
9
// found in the LICENSE file.
10

            
11
pub mod messages;
12
pub mod ninep_2000_l;
13

            
14
use std::io;
15

            
16
pub use self::messages::*;
17

            
18
pub fn error_to_rmessage(err: &io::Error) -> Rlerror {
19
    let errno = if let Some(errno) = err.raw_os_error() {
20
        errno
21
    } else {
22
        // Make a best-effort guess based on the kind.
23
        match err.kind() {
24
            io::ErrorKind::NotFound => libc::ENOENT,
25
            io::ErrorKind::PermissionDenied => libc::EPERM,
26
            io::ErrorKind::ConnectionRefused => libc::ECONNREFUSED,
27
            io::ErrorKind::ConnectionReset => libc::ECONNRESET,
28
            io::ErrorKind::ConnectionAborted => libc::ECONNABORTED,
29
            io::ErrorKind::NotConnected => libc::ENOTCONN,
30
            io::ErrorKind::AddrInUse => libc::EADDRINUSE,
31
            io::ErrorKind::AddrNotAvailable => libc::EADDRNOTAVAIL,
32
            io::ErrorKind::BrokenPipe => libc::EPIPE,
33
            io::ErrorKind::AlreadyExists => libc::EEXIST,
34
            io::ErrorKind::WouldBlock => libc::EWOULDBLOCK,
35
            io::ErrorKind::InvalidInput => libc::EINVAL,
36
            io::ErrorKind::InvalidData => libc::EINVAL,
37
            io::ErrorKind::TimedOut => libc::ETIMEDOUT,
38
            io::ErrorKind::WriteZero => libc::EIO,
39
            io::ErrorKind::Interrupted => libc::EINTR,
40
            io::ErrorKind::Other => libc::EIO,
41
            io::ErrorKind::UnexpectedEof => libc::EIO,
42
            _ => libc::EIO,
43
        }
44
    };
45

            
46
    Rlerror {
47
        ecode: errno as u32,
48
    }
49
}
50

            
51
// Tlopen and Tlcreate flags.  Taken from "include/net/9p/9p.h" in the linux tree.
52
pub const P9_RDONLY: u32 = 0o00000000;
53
pub const P9_WRONLY: u32 = 0o00000001;
54
pub const P9_RDWR: u32 = 0o00000002;
55
pub const P9_NOACCESS: u32 = 0o00000003;
56
pub const P9_CREATE: u32 = 0o00000100;
57
pub const P9_EXCL: u32 = 0o00000200;
58
pub const P9_NOCTTY: u32 = 0o00000400;
59
pub const P9_TRUNC: u32 = 0o00001000;
60
pub const P9_APPEND: u32 = 0o00002000;
61
pub const P9_NONBLOCK: u32 = 0o00004000;
62
pub const P9_DSYNC: u32 = 0o00010000;
63
pub const P9_FASYNC: u32 = 0o00020000;
64
pub const P9_DIRECT: u32 = 0o00040000;
65
pub const P9_LARGEFILE: u32 = 0o00100000;
66
pub const P9_DIRECTORY: u32 = 0o00200000;
67
pub const P9_NOFOLLOW: u32 = 0o00400000;
68
pub const P9_NOATIME: u32 = 0o01000000;
69
pub const _P9_CLOEXEC: u32 = 0o02000000;
70
pub const P9_SYNC: u32 = 0o04000000;
71

            
72
// Mapping from 9P flags to libc flags.
73
pub const MAPPED_FLAGS: [(u32, i32); 16] = [
74
    (P9_WRONLY, libc::O_WRONLY),
75
    (P9_RDWR, libc::O_RDWR),
76
    (P9_CREATE, libc::O_CREAT),
77
    (P9_EXCL, libc::O_EXCL),
78
    (P9_NOCTTY, libc::O_NOCTTY),
79
    (P9_TRUNC, libc::O_TRUNC),
80
    (P9_APPEND, libc::O_APPEND),
81
    (P9_NONBLOCK, libc::O_NONBLOCK),
82
    (P9_DSYNC, libc::O_DSYNC),
83
    (P9_FASYNC, 0), // Unsupported
84
    (P9_DIRECT, libc::O_DIRECT),
85
    (P9_LARGEFILE, libc::O_LARGEFILE),
86
    (P9_DIRECTORY, libc::O_DIRECTORY),
87
    (P9_NOFOLLOW, libc::O_NOFOLLOW),
88
    (P9_NOATIME, libc::O_NOATIME),
89
    (P9_SYNC, libc::O_SYNC),
90
];
91

            
92
// 9P Qid types.  Taken from "include/net/9p/9p.h" in the linux tree.
93
pub const P9_QTDIR: u8 = 0x80;
94
pub const _P9_QTAPPEND: u8 = 0x40;
95
pub const _P9_QTEXCL: u8 = 0x20;
96
pub const _P9_QTMOUNT: u8 = 0x10;
97
pub const _P9_QTAUTH: u8 = 0x08;
98
pub const _P9_QTTMP: u8 = 0x04;
99
pub const P9_QTSYMLINK: u8 = 0x02;
100
pub const _P9_QTLINK: u8 = 0x01;
101
pub const P9_QTFILE: u8 = 0x00;
102

            
103
// Bitmask values for the getattr request.
104
pub const _P9_GETATTR_MODE: u64 = 0x00000001;
105
pub const _P9_GETATTR_NLINK: u64 = 0x00000002;
106
pub const _P9_GETATTR_UID: u64 = 0x00000004;
107
pub const _P9_GETATTR_GID: u64 = 0x00000008;
108
pub const _P9_GETATTR_RDEV: u64 = 0x00000010;
109
pub const _P9_GETATTR_ATIME: u64 = 0x00000020;
110
pub const _P9_GETATTR_MTIME: u64 = 0x00000040;
111
pub const _P9_GETATTR_CTIME: u64 = 0x00000080;
112
pub const _P9_GETATTR_INO: u64 = 0x00000100;
113
pub const _P9_GETATTR_SIZE: u64 = 0x00000200;
114
pub const _P9_GETATTR_BLOCKS: u64 = 0x00000400;
115

            
116
pub const _P9_GETATTR_BTIME: u64 = 0x00000800;
117
pub const _P9_GETATTR_GEN: u64 = 0x00001000;
118
pub const _P9_GETATTR_DATA_VERSION: u64 = 0x00002000;
119

            
120
pub const P9_GETATTR_BASIC: u64 = 0x000007ff; /* Mask for fields up to BLOCKS */
121
pub const _P9_GETATTR_ALL: u64 = 0x00003fff; /* Mask for All fields above */
122

            
123
// Bitmask values for the setattr request.
124
pub const P9_SETATTR_MODE: u32 = 0x00000001;
125
pub const P9_SETATTR_UID: u32 = 0x00000002;
126
pub const P9_SETATTR_GID: u32 = 0x00000004;
127
pub const P9_SETATTR_SIZE: u32 = 0x00000008;
128
pub const P9_SETATTR_ATIME: u32 = 0x00000010;
129
pub const P9_SETATTR_MTIME: u32 = 0x00000020;
130
pub const P9_SETATTR_CTIME: u32 = 0x00000040;
131
pub const P9_SETATTR_ATIME_SET: u32 = 0x00000080;
132
pub const P9_SETATTR_MTIME_SET: u32 = 0x00000100;
133

            
134
// 9p lock constants. Taken from "include/net/9p/9p.h" in the linux kernel.
135
pub const _P9_LOCK_TYPE_RDLCK: u8 = 0;
136
pub const _P9_LOCK_TYPE_WRLCK: u8 = 1;
137
pub const P9_LOCK_TYPE_UNLCK: u8 = 2;
138
pub const _P9_LOCK_FLAGS_BLOCK: u8 = 1;
139
pub const _P9_LOCK_FLAGS_RECLAIM: u8 = 2;
140
pub const P9_LOCK_SUCCESS: u8 = 0;
141
pub const _P9_LOCK_BLOCKED: u8 = 1;
142
pub const _P9_LOCK_ERROR: u8 = 2;
143
pub const _P9_LOCK_GRACE: u8 = 3;
144

            
145
// Minimum and maximum message size that we'll expect from the client.
146
pub const MIN_MESSAGE_SIZE: u32 = 256;
147
pub const MAX_MESSAGE_SIZE: u32 = 64 * 1024 + 24; // 64 KiB of payload plus some extra for the header
148

            
149
pub enum Version {
150
    V9P2000 = 0,
151
    V9P2000U = 1,
152
    V9P2000L = 2,
153
    V9P2000Lu = 3,
154
    V9P2024q9p = 4,
155
}
156

            
157
impl From<&str> for Version {
158
    fn from(version: &str) -> Self {
159
        match version {
160
            "9P2000" => Version::V9P2000,
161
            "9P2000.u" => Version::V9P2000U,
162
            "9P2000.L" => Version::V9P2000L,
163
            "9P2000.Lu" => Version::V9P2000Lu,
164
            "9P2024.q9p" => Version::V9P2024q9p,
165
            _ => panic!("Invalid 9P version: {}", version),
166
        }
167
    }
168
}
169

            
170
impl From<String> for Version {
171
    fn from(version: String) -> Self {
172
        match version.as_str() {
173
            "9P2000" => Version::V9P2000,
174
            "9P2000.u" => Version::V9P2000U,
175
            "9P2000.L" => Version::V9P2000L,
176
            "9P2000.Lu" => Version::V9P2000Lu,
177
            "9P2024.q9p" => Version::V9P2024q9p,
178
            _ => panic!("Invalid 9P version: {}", version),
179
        }
180
    }
181
}
182

            
183
impl From<Version> for String {
184
    fn from(val: Version) -> Self {
185
        match val {
186
            Version::V9P2000 => "9P2000".to_string(),
187
            Version::V9P2000U => "9P2000.u".to_string(),
188
            Version::V9P2000L => "9P2000.L".to_string(),
189
            Version::V9P2000Lu => "9P2000.Lu".to_string(),
190
            Version::V9P2024q9p => "9P2024.q9p".to_string(),
191
        }
192
    }
193
}
194

            
195
impl From<Version> for &str {
196
    fn from(val: Version) -> Self {
197
        match val {
198
            Version::V9P2000 => "9P2000",
199
            Version::V9P2000U => "9P2000.u",
200
            Version::V9P2000L => "9P2000.L",
201
            Version::V9P2000Lu => "9P2000.Lu",
202
            Version::V9P2024q9p => "9P2024.q9p",
203
        }
204
    }
205
}
206

            
207
pub const DEFAULT_MSIZE: u32 = 8192;