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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
#![allow(non_camel_case_types)]

use core::ffi;

/// The primary signed integer type for the current platform.
pub type int = ffi::c_int;

/// The primary unsigned integer type for the current platform.
pub type uint = ffi::c_uint;

/// The short signed integer type for the current platform.
pub type short = ffi::c_short;

/// The short unsigned integer type for the current platform.
pub type ushort = ffi::c_ushort;

/// The signed long integer type for the current platform.
pub type long = ffi::c_long;

/// The unsigned long integer type for the current platform.
pub type ulong = ffi::c_ulong;

/// The signed long long integer type for the current platform.
pub type longlong = ffi::c_long;

/// The unsigned long long integer type for the current platform.
pub type ulonglong = ffi::c_ulong;

/// The signed size type (or "pointer difference" type) for the current platform.
pub type ssize_t = isize;

/// The unsigned size type for the current platform.
pub type size_t = usize;

/// The type used for characters on the current platform.
pub type char = ffi::c_char;

/// The type used for unsigned characters on the current platform.
pub type uchar = ffi::c_uchar;

/// The type used for void pointers on the current platform.
pub type void = ffi::c_void;

/// The type used to represent file modes on the current platform.
pub type mode_t = uint;

/// The type used to represent file sizes and offsets into files on the current platform.
pub type off_t = long;

/// The type used to represent larger file sizes and offsets into files on the current platform.
pub type loff_t = ffi::c_longlong;

/// The type used for process identifiers (PIDs) on the current platform.
pub type pid_t = int;

/// The type used for representing socket addresses in the raw system calls.
///
/// This is a type of unknown length, because the actual length of a socket
/// address depends on the address family. When reading a socket address of
/// an unknown address family, use a pointer to a [`sockaddr_storage`] as a
/// placeholder type and then convert based on the returned `family`.
///
/// **Warning:** It is not meaningful to ask the compiler for the size of
/// this type; it will return an arbitrary placeholder value. If you need
/// sufficient storage for an arbitrary address, use [`sockaddr_storage`]
/// instead.
#[repr(C)]
pub struct sockaddr {
    pub family: sa_family_t,

    // Intentionally not public to discourage using values of this type;
    // it's here primarily as a placeholder type for arguments that are
    // pointers to arbitrary addresses.
    data: [u8; 14],
}

/// Represents the upper limit for the size of any [`sockaddr`] value, across
/// all address families.
///
/// This is a reasonable default type to use when retrieving a socket address
/// from the kernel without knowledge of its address family. It is guaranteed
/// at least as large as the largest address type the kernel can return.
/// After the value is populated, use `family` to convert to a more specific
/// address type.
#[repr(C, align(8))]
pub struct sockaddr_storage {
    pub family: sa_family_t,
    pub data: [u8; 128 - core::mem::size_of::<sa_family_t>()],
}

/// The type used for representing the length of a socket address.
pub type socklen_t = int;

/// The type used to represent user ids.
pub type uid_t = uint;

/// The type used to represent group ids.
pub type gid_t = uint;

/// Seek relative to the beginning of the file.
pub const SEEK_SET: int = 0;

/// Seek relative to the current file position.
pub const SEEK_CUR: int = 1;

/// Seek relative to the end of the file.
pub const SEEK_END: int = 2;

/// Seek to the next data.
pub const SEEK_DATA: int = 3;

/// Seek to the next hole.
pub const SEEK_HOLE: int = 4;

pub const O_ACCMODE: int = 0o00000003;
pub const O_RDONLY: int = 0o00000000;
pub const O_WRONLY: int = 0o00000001;
pub const O_RDWR: int = 0o00000002;
pub const O_CREAT: int = 0o00000100;
pub const O_EXCL: int = 0o00000200;
pub const O_NOCTTY: int = 0o00000400;
pub const O_TRUNC: int = 0o00001000;
pub const O_APPEND: int = 0o00002000;
pub const O_NONBLOCK: int = 0o00004000;
pub const O_DSYNC: int = 0o00010000;
pub const O_DIRECT: int = 0o00040000;
pub const O_LARGEFILE: int = 0o00100000;
pub const O_DIRECTORY: int = 0o00200000;
pub const O_NOFOLLOW: int = 0o00400000;
pub const O_NOATIME: int = 0o01000000;
pub const O_CLOEXEC: int = 0o02000000;
pub const O_SYNC: int = 0o04000000 | O_DSYNC;
pub const O_PATH: int = 0o010000000;
pub const O_TMPFILE: int = 0o020000000 | O_DIRECTORY;
pub const O_TMPFILE_MASK: int = 0o020000000 | O_DIRECTORY | O_CREAT;
pub const O_NDELAY: int = O_NONBLOCK;

/// A file descriptor request object for use with [`crate::poll`].
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct pollfd {
    pub fd: int,
    pub events: short,
    pub revents: short,
}

// The type used to specify the number of file descriptors when calling [`crate::poll`].
pub type nfds_t = uint;

pub const POLLIN: short = 0x0001;
pub const POLLPRI: short = 0x0002;
pub const POLLOUT: short = 0x0004;
pub const POLLERR: short = 0x0008;
pub const POLLHUP: short = 0x0010;
pub const POLLNVAL: short = 0x0020;

/// A type used with [`crate::readv`] and [`crate::writev`].
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct iovec {
    pub iov_base: *mut void,
    pub iov_len: size_t,
}

/// A type used with [`crate::epoll_ctl`].
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct epoll_event {
    pub events: u32,
    pub data: epoll_data,
}

/// A type used with [`crate::epoll_ctl`].
#[derive(Clone, Copy)]
#[repr(C)]
pub union epoll_data {
    pub ptr: *mut void,
    pub fd: int,
    pub u32: u32,
    pub u64: u64,
}

impl core::fmt::Debug for epoll_data {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        f.debug_struct("epoll_data").finish_non_exhaustive()
    }
}

/// A type used with some [`crate::fcntl`] commands.
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct flock {
    pub l_type: short,
    pub l_whence: short,
    pub l_start: off_t,
    pub l_len: off_t,
    pub l_pid: pid_t,
    // TODO: MIPS Linux has an extra field l_sysid and some padding.
    // We don't support MIPS yet so we're ignoring that, but we'll
    // need to deal with that if we add MIPS support later.
    // Sparc also has padding, but no other extra fields.
}

/// The type for representing socket address families.
pub type sa_family_t = ushort;

/// The type for representing socket communication model types.
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub enum sock_type {
    SOCK_STREAM = 1,
    SOCK_DGRAM = 2,
    SOCK_RAW = 3,
    SOCK_RDM = 4,
    SOCK_SEQPACKET = 5,
    SOCK_DCCP = 6,
    SOCK_PACKET = 10,
}

/// Used for time in seconds.
pub type time_t = long;

/// Used for time in microseconds.
pub type suseconds_t = long;

/// Representation of time as separate seconds and nanoseconds.
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct timespec {
    tv_sec: long,
    tv_nsec: long,
}

/// Representation of time as separate seconds and microseconds.
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct timeval {
    tv_sec: long,
    tv_usec: suseconds_t,
}

/// Used for [`crate::getdents`].
#[derive(Debug)]
#[repr(C)]
pub struct linux_dirent {
    pub d_ino: ulong,
    pub d_off: ulong,
    pub d_reclen: ushort,
    pub d_name: [char],
}

/// 64-bit offset.
pub type off64_t = longlong;

// 64-bit inode number.
pub type ino64_t = ulonglong;

/// Used for [`crate::getdents64`].
#[derive(Debug)]
#[repr(C)]
pub struct linux_dirent64 {
    pub d_ino: ino64_t,
    pub d_off: off64_t,
    pub d_reclen: ushort,
    pub d_type: uchar,
    pub d_name: [char],
}

/// Used for [`crate::io_uring_setup`].
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct io_uring_params {
    pub sq_entries: u32,
    pub cq_entries: u32,
    pub flags: u32,
    pub sq_thread_cpu: u32,
    pub sq_thread_idle: u32,
    pub features: u32,
    pub wq_fd: u32,
    pub resv: [u32; 3],
    pub sq_off: io_sqring_offsets,
    pub cq_off: io_cqring_offsets,
}

/// Used with [`io_uring_params`].
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct io_sqring_offsets {
    pub head: u32,
    pub tail: u32,
    pub ring_mask: u32,
    pub ring_entries: u32,
    pub flags: u32,
    pub dropped: u32,
    pub array: u32,
    pub resv: [u32; 3],
}

/// Used with [`io_uring_params`].
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct io_cqring_offsets {
    pub head: u32,
    pub tail: u32,
    pub ring_mask: u32,
    pub ring_entries: u32,
    pub overflow: u32,
    pub cqes: u32,
    pub flags: u32,
    pub resv: [u32; 3],
}

pub use crate::sigset::sigset_t;

// Also include architecture-specific types.
pub use crate::raw::types::*;