1 /*
2  * Copyright (c) 2018 Linaro Limited
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #ifndef ZEPHYR_INCLUDE_SYS_FDTABLE_H_
7 #define ZEPHYR_INCLUDE_SYS_FDTABLE_H_
8 
9 #include <stdarg.h>
10 #include <time.h>
11 
12 /* FIXME: For native_posix ssize_t, off_t. */
13 #include <sys/types.h>
14 #include <zephyr/kernel.h>
15 #include <zephyr/sys/util.h>
16 
17 #ifdef CONFIG_PICOLIBC
18 #define ZVFS_O_APPEND 0x0400
19 #define ZVFS_O_CREAT  0x0040
20 #define ZVFS_O_TRUNC  0x0200
21 #else
22 #define ZVFS_O_APPEND 0x0008
23 #define ZVFS_O_CREAT  0x0200
24 #define ZVFS_O_TRUNC  0x0400
25 #endif
26 
27 #define ZVFS_O_RDONLY 00
28 #define ZVFS_O_WRONLY 01
29 #define ZVFS_O_RDWR   02
30 
31 #define ZVFS_O_EXCL     0x0800
32 #define ZVFS_O_NONBLOCK 0x4000
33 
34 #define ZVFS_F_DUPFD 0
35 #define ZVFS_F_GETFL 3
36 #define ZVFS_F_SETFL 4
37 
38 /* File mode bits */
39 #define ZVFS_MODE_IFMT   0170000
40 #define ZVFS_MODE_UNSPEC 0000000
41 #define ZVFS_MODE_IFIFO  0010000
42 #define ZVFS_MODE_IFCHR  0020000
43 #define ZVFS_MODE_IMSGQ  0030000
44 #define ZVFS_MODE_IFDIR  0040000
45 #define ZVFS_MODE_IFSEM  0050000
46 #define ZVFS_MODE_IFBLK  0060000
47 #define ZVFS_MODE_IFSHM  0070000
48 #define ZVFS_MODE_IFREG  0100000
49 #define ZVFS_MODE_IFLNK  0120000
50 #define ZVFS_MODE_IFSOCK 0140000
51 
52 #define ZVFS_POLLIN   BIT(0)
53 #define ZVFS_POLLPRI  BIT(1)
54 #define ZVFS_POLLOUT  BIT(2)
55 #define ZVFS_POLLERR  BIT(3)
56 #define ZVFS_POLLHUP  BIT(4)
57 #define ZVFS_POLLNVAL BIT(5)
58 
59 #ifdef __cplusplus
60 extern "C" {
61 #endif
62 
63 /* FIXME: use k_off_t and k_ssize_t to avoid the POSIX->Zephyr->POSIX dependency cycle */
64 #ifdef CONFIG_NEWLIB_LIBC
65 #ifndef _OFF_T_DECLARED
66 typedef __off_t off_t;
67 #define _OFF_T_DECLARED
68 #endif
69 #ifndef _SSIZE_T_DECLARED
70 typedef _ssize_t ssize_t;
71 #define _SSIZE_T_DECLARED
72 #endif
73 #endif
74 
75 /**
76  * File descriptor virtual method table.
77  * Currently all operations beyond read/write/close go thru ioctl method.
78  */
79 struct fd_op_vtable {
80 	union {
81 		ssize_t (*read)(void *obj, void *buf, size_t sz);
82 		ssize_t (*read_offs)(void *obj, void *buf, size_t sz, size_t offset);
83 	};
84 	union {
85 		ssize_t (*write)(void *obj, const void *buf, size_t sz);
86 		ssize_t (*write_offs)(void *obj, const void *buf, size_t sz, size_t offset);
87 	};
88 	union {
89 		int (*close)(void *obj);
90 		int (*close2)(void *obj, int fd);
91 	};
92 	int (*ioctl)(void *obj, unsigned int request, va_list args);
93 };
94 
95 /**
96  * @brief Reserve file descriptor.
97  *
98  * This function allows to reserve a space for file descriptor entry in
99  * the underlying table, and thus allows caller to fail fast if no free
100  * descriptor is available. If this function succeeds, zvfs_finalize_fd()
101  * or zvfs_free_fd() must be called mandatorily.
102  *
103  * @return Allocated file descriptor, or -1 in case of error (errno is set)
104  */
105 int zvfs_reserve_fd(void);
106 
107 /**
108  * @brief Finalize creation of file descriptor, with type.
109  *
110  * This function should be called exactly once after zvfs_reserve_fd(), and
111  * should not be called in any other case.
112  *
113  * The difference between this function and @ref zvfs_finalize_fd is that the
114  * latter does not relay type information of the created file descriptor.
115  *
116  * Values permitted for @a mode are one of `ZVFS_MODE_..`.
117  *
118  * @param fd File descriptor previously returned by zvfs_reserve_fd()
119  * @param obj pointer to I/O object structure
120  * @param vtable pointer to I/O operation implementations for the object
121  * @param mode File type as specified above.
122  */
123 void zvfs_finalize_typed_fd(int fd, void *obj, const struct fd_op_vtable *vtable, uint32_t mode);
124 
125 /**
126  * @brief Finalize creation of file descriptor.
127  *
128  * This function should be called exactly once after zvfs_reserve_fd(), and
129  * should not be called in any other case.
130  *
131  * @param fd File descriptor previously returned by zvfs_reserve_fd()
132  * @param obj pointer to I/O object structure
133  * @param vtable pointer to I/O operation implementations for the object
134  */
zvfs_finalize_fd(int fd,void * obj,const struct fd_op_vtable * vtable)135 static inline void zvfs_finalize_fd(int fd, void *obj, const struct fd_op_vtable *vtable)
136 {
137 	zvfs_finalize_typed_fd(fd, obj, vtable, ZVFS_MODE_UNSPEC);
138 }
139 
140 /**
141  * @brief Allocate file descriptor for underlying I/O object.
142  *
143  * This function combines operations of zvfs_reserve_fd() and zvfs_finalize_fd()
144  * in one step, and provided for convenience.
145  *
146  * @param obj pointer to I/O object structure
147  * @param vtable pointer to I/O operation implementations for the object
148  *
149  * @return Allocated file descriptor, or -1 in case of error (errno is set)
150  */
151 int zvfs_alloc_fd(void *obj, const struct fd_op_vtable *vtable);
152 
153 /**
154  * @brief Release reserved file descriptor.
155  *
156  * This function may be called once after zvfs_reserve_fd(), and should
157  * not be called in any other case.
158  *
159  * @param fd File descriptor previously returned by zvfs_reserve_fd()
160  */
161 void zvfs_free_fd(int fd);
162 
163 /**
164  * @brief Get underlying object pointer from file descriptor.
165  *
166  * This function is useful for functions other than read/write/ioctl
167  * to look up underlying I/O object by fd, optionally checking its
168  * type (using vtable reference). If fd refers to invalid entry,
169  * NULL will be returned with errno set to EBADF. If fd is valid,
170  * but vtable param is not NULL and doesn't match object's vtable,
171  * NULL is returned and errno set to err param.
172  *
173  * @param fd File descriptor previously returned by zvfs_reserve_fd()
174  * @param vtable Expected object vtable or NULL
175  * @param err errno value to set if object vtable doesn't match
176  *
177  * @return Object pointer or NULL, with errno set
178  */
179 void *zvfs_get_fd_obj(int fd, const struct fd_op_vtable *vtable, int err);
180 
181 /**
182  * @brief Get underlying object pointer and vtable pointer from file descriptor.
183  *
184  * @param fd File descriptor previously returned by zvfs_reserve_fd()
185  * @param vtable A pointer to a pointer variable to store the vtable
186  * @param lock An optional pointer to a pointer variable to store the mutex
187  *        preventing concurrent descriptor access. The lock is not taken,
188  *        it is just returned for the caller to use if necessary. Pass NULL
189  *        if the lock is not needed by the caller.
190  *
191  * @return Object pointer or NULL, with errno set
192  */
193 void *zvfs_get_fd_obj_and_vtable(int fd, const struct fd_op_vtable **vtable,
194 			      struct k_mutex **lock);
195 
196 /**
197  * @brief Get the mutex and condition variable associated with the given object and vtable.
198  *
199  * @param obj Object previously returned by a call to e.g. @ref zvfs_get_fd_obj.
200  * @param vtable A pointer the vtable associated with @p obj.
201  * @param lock An optional pointer to a pointer variable to store the mutex
202  *        preventing concurrent descriptor access. The lock is not taken,
203  *        it is just returned for the caller to use if necessary. Pass NULL
204  *        if the lock is not needed by the caller.
205  * @param cond An optional pointer to a pointer variable to store the condition variable
206  *        to notify waiting threads in the case of concurrent descriptor access. Pass NULL
207  *        if the condition variable is not needed by the caller.
208  *
209  * @return `true` on success, `false` otherwise.
210  */
211 bool zvfs_get_obj_lock_and_cond(void *obj, const struct fd_op_vtable *vtable, struct k_mutex **lock,
212 			     struct k_condvar **cond);
213 
214 /**
215  * @brief Call ioctl vmethod on an object using varargs.
216  *
217  * We need this helper function because ioctl vmethod is declared to
218  * take va_list and the only portable way to construct va_list is from
219  * function's ... parameters.
220  *
221  * @param vtable vtable containing ioctl function pointer
222  * @param obj Object to call ioctl on
223  * @param request ioctl request number
224  * @param ... Variadic arguments to ioctl
225  */
zvfs_fdtable_call_ioctl(const struct fd_op_vtable * vtable,void * obj,unsigned long request,...)226 static inline int zvfs_fdtable_call_ioctl(const struct fd_op_vtable *vtable, void *obj,
227 				       unsigned long request, ...)
228 {
229 	va_list args;
230 	int res;
231 
232 	va_start(args, request);
233 	res = vtable->ioctl(obj, request, args);
234 	va_end(args);
235 
236 	return res;
237 }
238 
239 struct zvfs_pollfd {
240 	int fd;
241 	short events;
242 	short revents;
243 };
244 
245 __syscall int zvfs_poll(struct zvfs_pollfd *fds, int nfds, int poll_timeout);
246 
247 struct zvfs_fd_set {
248 	uint32_t bitset[(CONFIG_ZVFS_OPEN_MAX + 31) / 32];
249 };
250 
251 /** @brief Number of file descriptors which can be added @ref zvfs_fd_set */
252 #define ZVFS_FD_SETSIZE (sizeof(((struct zvfs_fd_set *)0)->bitset) * 8)
253 
254 void ZVFS_FD_CLR(int fd, struct zvfs_fd_set *fdset);
255 int ZVFS_FD_ISSET(int fd, struct zvfs_fd_set *fdset);
256 void ZVFS_FD_SET(int fd, struct zvfs_fd_set *fdset);
257 void ZVFS_FD_ZERO(struct zvfs_fd_set *fdset);
258 
259 __syscall int zvfs_select(int nfds, struct zvfs_fd_set *ZRESTRICT readfds,
260 			  struct zvfs_fd_set *ZRESTRICT writefds,
261 			  struct zvfs_fd_set *ZRESTRICT errorfds,
262 			  const struct timespec *ZRESTRICT timeout, const void *ZRESTRICT sigmask);
263 
264 /**
265  * Request codes for fd_op_vtable.ioctl().
266  *
267  * Note that these codes are internal Zephyr numbers, for internal
268  * Zephyr operations (and subject to change without notice, not part
269  * of "stable ABI"). These are however expected to co-exist with
270  * "well-known" POSIX/Linux ioctl numbers, and not clash with them.
271  */
272 enum {
273 	/* Codes below 0x100 are reserved for fcntl() codes. */
274 	ZFD_IOCTL_FSYNC = 0x100,
275 	ZFD_IOCTL_LSEEK,
276 	ZFD_IOCTL_POLL_PREPARE,
277 	ZFD_IOCTL_POLL_UPDATE,
278 	ZFD_IOCTL_POLL_OFFLOAD,
279 	ZFD_IOCTL_SET_LOCK,
280 	ZFD_IOCTL_STAT,
281 	ZFD_IOCTL_TRUNCATE,
282 	ZFD_IOCTL_MMAP,
283 
284 	/* Codes above 0x5400 and below 0x5500 are reserved for termios, FIO, etc */
285 	ZFD_IOCTL_FIONREAD = 0x541B,
286 	ZFD_IOCTL_FIONBIO = 0x5421,
287 };
288 
289 #ifdef __cplusplus
290 }
291 #endif
292 
293 #include <zephyr/syscalls/fdtable.h>
294 
295 #endif /* ZEPHYR_INCLUDE_SYS_FDTABLE_H_ */
296