1 | /* |
2 | * libwebsockets - small server side websockets and web server implementation |
3 | * |
4 | * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com> |
5 | * |
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
7 | * of this software and associated documentation files (the "Software"), to |
8 | * deal in the Software without restriction, including without limitation the |
9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
10 | * sell copies of the Software, and to permit persons to whom the Software is |
11 | * furnished to do so, subject to the following conditions: |
12 | * |
13 | * The above copyright notice and this permission notice shall be included in |
14 | * all copies or substantial portions of the Software. |
15 | * |
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
22 | * IN THE SOFTWARE. |
23 | */ |
24 | |
25 | /*! \defgroup fops file operation wrapping |
26 | * |
27 | * ##File operation wrapping |
28 | * |
29 | * Use these helper functions if you want to access a file from the perspective |
30 | * of a specific wsi, which is usually the case. If you just want contextless |
31 | * file access, use the fops callbacks directly with NULL wsi instead of these |
32 | * helpers. |
33 | * |
34 | * If so, then it calls the platform handler or user overrides where present |
35 | * (as defined in info->fops) |
36 | * |
37 | * The advantage from all this is user code can be portable for file operations |
38 | * without having to deal with differences between platforms. |
39 | */ |
40 | //@{ |
41 | |
42 | /** struct lws_plat_file_ops - Platform-specific file operations |
43 | * |
44 | * These provide platform-agnostic ways to deal with filesystem access in the |
45 | * library and in the user code. |
46 | */ |
47 | |
48 | #if defined(LWS_PLAT_FREERTOS) |
49 | /* sdk preprocessor defs? compiler issue? gets confused with member names */ |
50 | #define LWS_FOP_OPEN _open |
51 | #define LWS_FOP_CLOSE _close |
52 | #define LWS_FOP_SEEK_CUR _seek_cur |
53 | #define LWS_FOP_READ _read |
54 | #define LWS_FOP_WRITE _write |
55 | #else |
56 | #define LWS_FOP_OPEN open |
57 | #define LWS_FOP_CLOSE close |
58 | #define LWS_FOP_SEEK_CUR seek_cur |
59 | #define LWS_FOP_READ read |
60 | #define LWS_FOP_WRITE write |
61 | #endif |
62 | |
63 | #define LWS_FOP_FLAGS_MASK ((1 << 23) - 1) |
64 | #define LWS_FOP_FLAG_COMPR_ACCEPTABLE_GZIP (1 << 24) |
65 | #define LWS_FOP_FLAG_COMPR_IS_GZIP (1 << 25) |
66 | #define LWS_FOP_FLAG_MOD_TIME_VALID (1 << 26) |
67 | #define LWS_FOP_FLAG_VIRTUAL (1 << 27) |
68 | |
69 | struct lws_plat_file_ops; |
70 | |
71 | struct lws_fop_fd { |
72 | lws_filefd_type fd; |
73 | /**< real file descriptor related to the file... */ |
74 | const struct lws_plat_file_ops *fops; |
75 | /**< fops that apply to this fop_fd */ |
76 | void *filesystem_priv; |
77 | /**< ignored by lws; owned by the fops handlers */ |
78 | lws_filepos_t pos; |
79 | /**< generic "position in file" */ |
80 | lws_filepos_t len; |
81 | /**< generic "length of file" */ |
82 | lws_fop_flags_t flags; |
83 | /**< copy of the returned flags */ |
84 | uint32_t mod_time; |
85 | /**< optional "modification time of file", only valid if .open() |
86 | * set the LWS_FOP_FLAG_MOD_TIME_VALID flag */ |
87 | }; |
88 | typedef struct lws_fop_fd *lws_fop_fd_t; |
89 | |
90 | struct lws_fops_index { |
91 | const char *sig; /* NULL or vfs signature, eg, ".zip/" */ |
92 | uint8_t len; /* length of above string */ |
93 | }; |
94 | |
95 | struct lws_plat_file_ops { |
96 | lws_fop_fd_t (*LWS_FOP_OPEN)(const struct lws_plat_file_ops *fops, |
97 | const char *filename, const char *vpath, |
98 | lws_fop_flags_t *flags); |
99 | /**< Open file (always binary access if plat supports it) |
100 | * vpath may be NULL, or if the fops understands it, the point at which |
101 | * the filename's virtual part starts. |
102 | * *flags & LWS_FOP_FLAGS_MASK should be set to O_RDONLY or O_RDWR. |
103 | * If the file may be gzip-compressed, |
104 | * LWS_FOP_FLAG_COMPR_ACCEPTABLE_GZIP is set. If it actually is |
105 | * gzip-compressed, then the open handler should OR |
106 | * LWS_FOP_FLAG_COMPR_IS_GZIP on to *flags before returning. |
107 | */ |
108 | int (*LWS_FOP_CLOSE)(lws_fop_fd_t *fop_fd); |
109 | /**< close file AND set the pointer to NULL */ |
110 | lws_fileofs_t (*LWS_FOP_SEEK_CUR)(lws_fop_fd_t fop_fd, |
111 | lws_fileofs_t offset_from_cur_pos); |
112 | /**< seek from current position */ |
113 | int (*LWS_FOP_READ)(lws_fop_fd_t fop_fd, lws_filepos_t *amount, |
114 | uint8_t *buf, lws_filepos_t len); |
115 | /**< Read from file, on exit *amount is set to amount actually read */ |
116 | int (*LWS_FOP_WRITE)(lws_fop_fd_t fop_fd, lws_filepos_t *amount, |
117 | uint8_t *buf, lws_filepos_t len); |
118 | /**< Write to file, on exit *amount is set to amount actually written */ |
119 | |
120 | struct lws_fops_index fi[3]; |
121 | /**< vfs path signatures implying use of this fops */ |
122 | |
123 | const struct lws_plat_file_ops *next; |
124 | /**< NULL or next fops in list */ |
125 | |
126 | /* Add new things just above here ---^ |
127 | * This is part of the ABI, don't needlessly break compatibility */ |
128 | }; |
129 | |
130 | /** |
131 | * lws_get_fops() - get current file ops |
132 | * |
133 | * \param context: context |
134 | */ |
135 | LWS_VISIBLE LWS_EXTERN struct lws_plat_file_ops * LWS_WARN_UNUSED_RESULT |
136 | lws_get_fops(struct lws_context *context); |
137 | LWS_VISIBLE LWS_EXTERN void |
138 | lws_set_fops(struct lws_context *context, const struct lws_plat_file_ops *fops); |
139 | /** |
140 | * lws_vfs_tell() - get current file position |
141 | * |
142 | * \param fop_fd: fop_fd we are asking about |
143 | */ |
144 | LWS_VISIBLE LWS_EXTERN lws_filepos_t LWS_WARN_UNUSED_RESULT |
145 | lws_vfs_tell(lws_fop_fd_t fop_fd); |
146 | /** |
147 | * lws_vfs_get_length() - get current file total length in bytes |
148 | * |
149 | * \param fop_fd: fop_fd we are asking about |
150 | */ |
151 | LWS_VISIBLE LWS_EXTERN lws_filepos_t LWS_WARN_UNUSED_RESULT |
152 | lws_vfs_get_length(lws_fop_fd_t fop_fd); |
153 | /** |
154 | * lws_vfs_get_mod_time() - get time file last modified |
155 | * |
156 | * \param fop_fd: fop_fd we are asking about |
157 | */ |
158 | LWS_VISIBLE LWS_EXTERN uint32_t LWS_WARN_UNUSED_RESULT |
159 | lws_vfs_get_mod_time(lws_fop_fd_t fop_fd); |
160 | /** |
161 | * lws_vfs_file_seek_set() - seek relative to start of file |
162 | * |
163 | * \param fop_fd: fop_fd we are seeking in |
164 | * \param offset: offset from start of file |
165 | */ |
166 | LWS_VISIBLE LWS_EXTERN lws_fileofs_t |
167 | lws_vfs_file_seek_set(lws_fop_fd_t fop_fd, lws_fileofs_t offset); |
168 | /** |
169 | * lws_vfs_file_seek_end() - seek relative to end of file |
170 | * |
171 | * \param fop_fd: fop_fd we are seeking in |
172 | * \param offset: offset from start of file |
173 | */ |
174 | LWS_VISIBLE LWS_EXTERN lws_fileofs_t |
175 | lws_vfs_file_seek_end(lws_fop_fd_t fop_fd, lws_fileofs_t offset); |
176 | |
177 | extern struct lws_plat_file_ops fops_zip; |
178 | |
179 | /** |
180 | * lws_plat_file_open() - open vfs filepath |
181 | * |
182 | * \param fops: file ops struct that applies to this descriptor |
183 | * \param vfs_path: filename to open |
184 | * \param flags: pointer to open flags |
185 | * |
186 | * The vfs_path is scanned for known fops signatures, and the open directed |
187 | * to any matching fops open. |
188 | * |
189 | * User code should use this api to perform vfs opens. |
190 | * |
191 | * returns semi-opaque handle |
192 | */ |
193 | LWS_VISIBLE LWS_EXTERN lws_fop_fd_t LWS_WARN_UNUSED_RESULT |
194 | lws_vfs_file_open(const struct lws_plat_file_ops *fops, const char *vfs_path, |
195 | lws_fop_flags_t *flags); |
196 | |
197 | /** |
198 | * lws_plat_file_close() - close file |
199 | * |
200 | * \param fop_fd: file handle to close |
201 | */ |
202 | static LWS_INLINE int |
203 | lws_vfs_file_close(lws_fop_fd_t *fop_fd) |
204 | { |
205 | if (*fop_fd && (*fop_fd)->fops) |
206 | return (*fop_fd)->fops->LWS_FOP_CLOSE(fop_fd); |
207 | |
208 | return 0; |
209 | } |
210 | |
211 | /** |
212 | * lws_plat_file_seek_cur() - close file |
213 | * |
214 | * |
215 | * \param fop_fd: file handle |
216 | * \param offset: position to seek to |
217 | */ |
218 | static LWS_INLINE lws_fileofs_t |
219 | lws_vfs_file_seek_cur(lws_fop_fd_t fop_fd, lws_fileofs_t offset) |
220 | { |
221 | return fop_fd->fops->LWS_FOP_SEEK_CUR(fop_fd, offset); |
222 | } |
223 | /** |
224 | * lws_plat_file_read() - read from file |
225 | * |
226 | * \param fop_fd: file handle |
227 | * \param amount: how much to read (rewritten by call) |
228 | * \param buf: buffer to write to |
229 | * \param len: max length |
230 | */ |
231 | static LWS_INLINE int LWS_WARN_UNUSED_RESULT |
232 | lws_vfs_file_read(lws_fop_fd_t fop_fd, lws_filepos_t *amount, |
233 | uint8_t *buf, lws_filepos_t len) |
234 | { |
235 | return fop_fd->fops->LWS_FOP_READ(fop_fd, amount, buf, len); |
236 | } |
237 | /** |
238 | * lws_plat_file_write() - write from file |
239 | * |
240 | * \param fop_fd: file handle |
241 | * \param amount: how much to write (rewritten by call) |
242 | * \param buf: buffer to read from |
243 | * \param len: max length |
244 | */ |
245 | static LWS_INLINE int LWS_WARN_UNUSED_RESULT |
246 | lws_vfs_file_write(lws_fop_fd_t fop_fd, lws_filepos_t *amount, |
247 | uint8_t *buf, lws_filepos_t len) |
248 | { |
249 | return fop_fd->fops->LWS_FOP_WRITE(fop_fd, amount, buf, len); |
250 | } |
251 | |
252 | /* these are the platform file operations implementations... they can |
253 | * be called directly and used in fops arrays |
254 | */ |
255 | |
256 | LWS_VISIBLE LWS_EXTERN lws_fop_fd_t |
257 | _lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename, |
258 | const char *vpath, lws_fop_flags_t *flags); |
259 | LWS_VISIBLE LWS_EXTERN int |
260 | _lws_plat_file_close(lws_fop_fd_t *fop_fd); |
261 | LWS_VISIBLE LWS_EXTERN lws_fileofs_t |
262 | _lws_plat_file_seek_cur(lws_fop_fd_t fop_fd, lws_fileofs_t offset); |
263 | LWS_VISIBLE LWS_EXTERN int |
264 | _lws_plat_file_read(lws_fop_fd_t fop_fd, lws_filepos_t *amount, |
265 | uint8_t *buf, lws_filepos_t len); |
266 | LWS_VISIBLE LWS_EXTERN int |
267 | _lws_plat_file_write(lws_fop_fd_t fop_fd, lws_filepos_t *amount, |
268 | uint8_t *buf, lws_filepos_t len); |
269 | |
270 | LWS_VISIBLE LWS_EXTERN int |
271 | lws_alloc_vfs_file(struct lws_context *context, const char *filename, |
272 | uint8_t **buf, lws_filepos_t *amount); |
273 | //@} |
274 | |