forked from ish-app/ish
-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathfd.h
193 lines (169 loc) · 5.6 KB
/
fd.h
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
#ifndef FD_H
#define FD_H
#include <dirent.h>
#include "emu/memory.h"
#include "util/list.h"
#include "util/ro_locks.h"
#include "util/sync.h"
#include "util/bits.h"
#include "fs/stat.h"
#include "fs/proc.h"
#include "fs/sockrestart.h"
// FIXME almost everything that uses the structs in this file does so without any kind of sane locking
struct fd {
atomic_uint refcount;
unsigned flags;
mode_t_ type; // just the S_IFMT part, it can't change
const struct fd_ops *ops;
struct list poll_fds;
lock_t poll_lock;
unsigned long offset;
// fd data
union {
// tty
struct {
struct tty *tty;
// links together fds pointing to the same tty
// locked by the tty
struct list tty_other_fds;
};
struct {
struct poll *poll;
} epollfd;
struct {
uint64_t val;
} eventfd;
struct {
struct timer *timer;
uint64_t expirations;
} timerfd;
struct {
int domain;
int type;
int protocol;
// These are only used as strong references, to keep the inode
// alive while there is a listener.
struct inode_data *unix_name_inode;
struct unix_abstract *unix_name_abstract;
uint8_t unix_name_len;
char unix_name[108];
struct fd *unix_peer; // locked by peer_lock, for simplicity
cond_t unix_got_peer;
// Queue of struct scm for sending file descriptors
// locked by fd->lock
struct list unix_scm;
struct ucred_ {
pid_t_ pid;
uid_t_ uid;
uid_t_ gid;
} unix_cred;
} socket;
// See app/Pasteboard.m
struct {
// UIPasteboard.changeCount
uint64_t generation;
// Buffer for written data
void* buffer;
// its capacity
size_t buffer_cap;
// length of actual data stored in the buffer
size_t buffer_len;
} clipboard;
// can fit anything in here
void *data;
};
// fs data
union {
struct {
struct proc_entry entry;
unsigned dir_index;
struct proc_data data;
} proc;
struct {
int num;
} devpts;
struct {
struct tmp_dirent *dirent;
struct tmp_dirent *dir_pos;
} tmpfs;
void *fs_data;
};
// fs/inode data
struct mount *mount;
int real_fd; // seeks on this fd require the lock TODO think about making a special lock just for that
DIR *dir;
struct inode_data *inode;
ino_t fake_inode;
struct statbuf stat; // for adhoc fs
struct fd_sockrestart sockrestart; // argh
// these are used for a variety of things related to the fd
lock_t lock;
cond_t cond;
};
typedef sdword_t fd_t;
#define AT_FDCWD_ -100
struct fd *fd_create(const struct fd_ops *ops);
struct fd *fd_retain(struct fd *fd);
int fd_close(struct fd *fd);
int fd_getflags(struct fd *fd);
int fd_setflags(struct fd *fd, int flags);
#define NAME_MAX 255
struct dir_entry {
qword_t inode;
char name[NAME_MAX + 1];
};
#define LSEEK_SET 0
#define LSEEK_CUR 1
#define LSEEK_END 2
struct fd_ops {
// required for files
// TODO make optional for non-files
ssize_t (*read)(struct fd *fd, void *buf, size_t bufsize);
ssize_t (*write)(struct fd *fd, const void *buf, size_t bufsize);
ssize_t (*pread)(struct fd *fd, void *buf, size_t bufsize, off_t off);
ssize_t (*pwrite)(struct fd *fd, const void *buf, size_t bufsize, off_t off);
off_t_ (*lseek)(struct fd *fd, off_t_ off, int whence);
// Reads a directory entry from the stream
// required for directories
int (*readdir)(struct fd *fd, struct dir_entry *entry);
// Return an opaque value representing the current point in the directory stream
// optional, fd->offset will be used instead
unsigned long (*telldir)(struct fd *fd);
// Seek to the location represented by a pointer returned from telldir
// optional, fd->offset will be used instead
void (*seekdir)(struct fd *fd, unsigned long ptr);
// map the file
int (*mmap)(struct fd *fd, struct mem *mem, page_t start, pages_t pages, off_t offset, int prot, int flags);
// returns a bitmask of operations that won't block
int (*poll)(struct fd *fd);
// returns the size needed for the output of ioctl, 0 if the arg is not a
// pointer, -1 for invalid command
ssize_t (*ioctl_size)(int cmd);
// if ioctl_size returns non-zero, arg must point to ioctl_size valid bytes
int (*ioctl)(struct fd *fd, int cmd, void *arg);
int (*fsync)(struct fd *fd);
int (*close)(struct fd *fd);
// handle F_GETFL, i.e. return open flags for this fd
int (*getflags)(struct fd *fd);
// handle F_SETFL, i.e. set O_NONBLOCK
int (*setflags)(struct fd *fd, dword_t arg);
};
struct fdtable {
atomic_uint refcount;
unsigned size;
struct fd **files;
bits_t *cloexec;
lock_t lock;
};
struct fdtable *fdtable_new(int size);
void fdtable_release(struct fdtable *table);
struct fdtable *fdtable_copy(struct fdtable *table);
void fdtable_free(struct fdtable *table);
void fdtable_do_cloexec(struct fdtable *table);
struct fd *fdtable_get(struct fdtable *table, fd_t f);
struct fd *f_get(fd_t f);
// steals a reference to the fd, gives it to the table on success and destroys it on error
// flags is checked for O_CLOEXEC and O_NONBLOCK
fd_t f_install(struct fd *fd, int flags);
int f_close(fd_t f);
#endif