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 <sys/types.h>
11 /* FIXME: For native_posix ssize_t, off_t. */
12 #include <zephyr/fs/fs.h>
13 #include <zephyr/kernel.h>
14 #include <zephyr/sys/util.h>
15 
16 /* File mode bits */
17 #define ZVFS_MODE_IFMT   0170000
18 #define ZVFS_MODE_UNSPEC 0000000
19 #define ZVFS_MODE_IFIFO  0010000
20 #define ZVFS_MODE_IFCHR  0020000
21 #define ZVFS_MODE_IMSGQ  0030000
22 #define ZVFS_MODE_IFDIR  0040000
23 #define ZVFS_MODE_IFSEM  0050000
24 #define ZVFS_MODE_IFBLK  0060000
25 #define ZVFS_MODE_IFSHM  0070000
26 #define ZVFS_MODE_IFREG  0100000
27 #define ZVFS_MODE_IFLNK  0120000
28 #define ZVFS_MODE_IFSOCK 0140000
29 
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33 
34 /**
35  * File descriptor virtual method table.
36  * Currently all operations beyond read/write/close go thru ioctl method.
37  */
38 struct fd_op_vtable {
39 	union {
40 		ssize_t (*read)(void *obj, void *buf, size_t sz);
41 		ssize_t (*read_offs)(void *obj, void *buf, size_t sz, size_t offset);
42 	};
43 	union {
44 		ssize_t (*write)(void *obj, const void *buf, size_t sz);
45 		ssize_t (*write_offs)(void *obj, const void *buf, size_t sz, size_t offset);
46 	};
47 	int (*close)(void *obj);
48 	int (*ioctl)(void *obj, unsigned int request, va_list args);
49 };
50 
51 /**
52  * @brief Reserve file descriptor.
53  *
54  * This function allows to reserve a space for file descriptor entry in
55  * the underlying table, and thus allows caller to fail fast if no free
56  * descriptor is available. If this function succeeds, zvfs_finalize_fd()
57  * or zvfs_free_fd() must be called mandatorily.
58  *
59  * @return Allocated file descriptor, or -1 in case of error (errno is set)
60  */
61 int zvfs_reserve_fd(void);
62 
63 /**
64  * @brief Finalize creation of file descriptor, with type.
65  *
66  * This function should be called exactly once after zvfs_reserve_fd(), and
67  * should not be called in any other case.
68  *
69  * The difference between this function and @ref zvfs_finalize_fd is that the
70  * latter does not relay type information of the created file descriptor.
71  *
72  * Values permitted for @a mode are one of `ZVFS_MODE_..`.
73  *
74  * @param fd File descriptor previously returned by zvfs_reserve_fd()
75  * @param obj pointer to I/O object structure
76  * @param vtable pointer to I/O operation implementations for the object
77  * @param mode File type as specified above.
78  */
79 void zvfs_finalize_typed_fd(int fd, void *obj, const struct fd_op_vtable *vtable, uint32_t mode);
80 
81 /**
82  * @brief Finalize creation of file descriptor.
83  *
84  * This function should be called exactly once after zvfs_reserve_fd(), and
85  * should not be called in any other case.
86  *
87  * @param fd File descriptor previously returned by zvfs_reserve_fd()
88  * @param obj pointer to I/O object structure
89  * @param vtable pointer to I/O operation implementations for the object
90  */
zvfs_finalize_fd(int fd,void * obj,const struct fd_op_vtable * vtable)91 static inline void zvfs_finalize_fd(int fd, void *obj, const struct fd_op_vtable *vtable)
92 {
93 	zvfs_finalize_typed_fd(fd, obj, vtable, ZVFS_MODE_UNSPEC);
94 }
95 
96 /**
97  * @brief Allocate file descriptor for underlying I/O object.
98  *
99  * This function combines operations of zvfs_reserve_fd() and zvfs_finalize_fd()
100  * in one step, and provided for convenience.
101  *
102  * @param obj pointer to I/O object structure
103  * @param vtable pointer to I/O operation implementations for the object
104  *
105  * @return Allocated file descriptor, or -1 in case of error (errno is set)
106  */
107 int zvfs_alloc_fd(void *obj, const struct fd_op_vtable *vtable);
108 
109 /**
110  * @brief Release reserved file descriptor.
111  *
112  * This function may be called once after zvfs_reserve_fd(), and should
113  * not be called in any other case.
114  *
115  * @param fd File descriptor previously returned by zvfs_reserve_fd()
116  */
117 void zvfs_free_fd(int fd);
118 
119 /**
120  * @brief Get underlying object pointer from file descriptor.
121  *
122  * This function is useful for functions other than read/write/ioctl
123  * to look up underlying I/O object by fd, optionally checking its
124  * type (using vtable reference). If fd refers to invalid entry,
125  * NULL will be returned with errno set to EBADF. If fd is valid,
126  * but vtable param is not NULL and doesn't match object's vtable,
127  * NULL is returned and errno set to err param.
128  *
129  * @param fd File descriptor previously returned by zvfs_reserve_fd()
130  * @param vtable Expected object vtable or NULL
131  * @param err errno value to set if object vtable doesn't match
132  *
133  * @return Object pointer or NULL, with errno set
134  */
135 void *zvfs_get_fd_obj(int fd, const struct fd_op_vtable *vtable, int err);
136 
137 /**
138  * @brief Get underlying object pointer and vtable pointer from file descriptor.
139  *
140  * @param fd File descriptor previously returned by zvfs_reserve_fd()
141  * @param vtable A pointer to a pointer variable to store the vtable
142  * @param lock An optional pointer to a pointer variable to store the mutex
143  *        preventing concurrent descriptor access. The lock is not taken,
144  *        it is just returned for the caller to use if necessary. Pass NULL
145  *        if the lock is not needed by the caller.
146  *
147  * @return Object pointer or NULL, with errno set
148  */
149 void *zvfs_get_fd_obj_and_vtable(int fd, const struct fd_op_vtable **vtable,
150 			      struct k_mutex **lock);
151 
152 /**
153  * @brief Get the mutex and condition variable associated with the given object and vtable.
154  *
155  * @param obj Object previously returned by a call to e.g. @ref zvfs_get_fd_obj.
156  * @param vtable A pointer the vtable associated with @p obj.
157  * @param lock An optional pointer to a pointer variable to store the mutex
158  *        preventing concurrent descriptor access. The lock is not taken,
159  *        it is just returned for the caller to use if necessary. Pass NULL
160  *        if the lock is not needed by the caller.
161  * @param cond An optional pointer to a pointer variable to store the condition variable
162  *        to notify waiting threads in the case of concurrent descriptor access. Pass NULL
163  *        if the condition variable is not needed by the caller.
164  *
165  * @return `true` on success, `false` otherwise.
166  */
167 bool zvfs_get_obj_lock_and_cond(void *obj, const struct fd_op_vtable *vtable, struct k_mutex **lock,
168 			     struct k_condvar **cond);
169 
170 /**
171  * @brief Call ioctl vmethod on an object using varargs.
172  *
173  * We need this helper function because ioctl vmethod is declared to
174  * take va_list and the only portable way to construct va_list is from
175  * function's ... parameters.
176  *
177  * @param vtable vtable containing ioctl function pointer
178  * @param obj Object to call ioctl on
179  * @param request ioctl request number
180  * @param ... Variadic arguments to ioctl
181  */
zvfs_fdtable_call_ioctl(const struct fd_op_vtable * vtable,void * obj,unsigned long request,...)182 static inline int zvfs_fdtable_call_ioctl(const struct fd_op_vtable *vtable, void *obj,
183 				       unsigned long request, ...)
184 {
185 	va_list args;
186 	int res;
187 
188 	va_start(args, request);
189 	res = vtable->ioctl(obj, request, args);
190 	va_end(args);
191 
192 	return res;
193 }
194 
195 /**
196  * Request codes for fd_op_vtable.ioctl().
197  *
198  * Note that these codes are internal Zephyr numbers, for internal
199  * Zephyr operations (and subject to change without notice, not part
200  * of "stable ABI"). These are however expected to co-exist with
201  * "well-known" POSIX/Linux ioctl numbers, and not clash with them.
202  */
203 enum {
204 	/* Codes below 0x100 are reserved for fcntl() codes. */
205 	ZFD_IOCTL_FSYNC = 0x100,
206 	ZFD_IOCTL_LSEEK,
207 	ZFD_IOCTL_POLL_PREPARE,
208 	ZFD_IOCTL_POLL_UPDATE,
209 	ZFD_IOCTL_POLL_OFFLOAD,
210 	ZFD_IOCTL_SET_LOCK,
211 	ZFD_IOCTL_STAT,
212 	ZFD_IOCTL_TRUNCATE,
213 	ZFD_IOCTL_MMAP,
214 
215 	/* Codes above 0x5400 and below 0x5500 are reserved for termios, FIO, etc */
216 	ZFD_IOCTL_FIONREAD = 0x541B,
217 	ZFD_IOCTL_FIONBIO = 0x5421,
218 };
219 
220 #ifdef __cplusplus
221 }
222 #endif
223 
224 #endif /* ZEPHYR_INCLUDE_SYS_FDTABLE_H_ */
225