1 /******************************************************************************
2 @file stream_file.c
4 @brief TIMAC 2.0 API Treat a file as a stream.
6 Group: WCS LPC
7 $Target Devices: Linux: AM335x, Embedded Devices: CC1310, CC1350, CC1352$
9 ******************************************************************************
10 $License: BSD3 2016 $
12 Copyright (c) 2015, Texas Instruments Incorporated
13 All rights reserved.
15 Redistribution and use in source and binary forms, with or without
16 modification, are permitted provided that the following conditions
17 are met:
19 * Redistributions of source code must retain the above copyright
20 notice, this list of conditions and the following disclaimer.
22 * Redistributions in binary form must reproduce the above copyright
23 notice, this list of conditions and the following disclaimer in the
24 documentation and/or other materials provided with the distribution.
26 * Neither the name of Texas Instruments Incorporated nor the names of
27 its contributors may be used to endorse or promote products derived
28 from this software without specific prior written permission.
30 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
31 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
32 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
33 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
34 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
35 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
36 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
37 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
38 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
39 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
40 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 ******************************************************************************
42 $Release Name: TI-15.4Stack Linux x64 SDK$
43 $Release Date: Sept 27, 2017 (2.04.00.13)$
44 *****************************************************************************/
46 #include "compiler.h"
48 #include "stream.h"
49 #include "unix_fdrw.h"
50 #include "log.h"
52 #define _STREAM_IMPLIMENTOR_ 1
53 #include "stream_private.h"
55 #include <string.h>
57 /*!
58 * @brief [private] recover our file pointer
59 * @param pIO - the io stream to extract from
60 * @return FILE pointer
61 */
62 static FILE *get_fp(struct io_stream *pIO)
63 {
64 return ((FILE *)(pIO->opaque_ptr));
65 }
67 /*
68 * See stream.h
69 */
70 void STREAM_FILE_init(void)
71 {
72 STREAM_stdout = STREAM_createFpFile(stdout);
73 STREAM_stderr = STREAM_createFpFile(stderr);
74 STREAM_stdin = STREAM_createFpFile(stdin);
75 /* Give default values for these */
76 STREAM_debug_stdin = STREAM_stdin;
77 STREAM_debug_stdout = STREAM_stdout;
78 }
80 /*!
81 * @brief close a file based stream
82 * @param pIO - stream to close
83 */
84 static void _file_close_fn(struct io_stream *pIO)
85 {
86 FILE *fp;
88 fp = get_fp(pIO);
89 if(fp)
90 {
91 fclose(fp);
92 pIO->opaque_ptr = 0;
93 }
94 /* make it unusable */
95 memset((void *)(pIO), 0, sizeof(*pIO));
96 }
98 /*!
99 * @brief [private] Write to a FILE based stream
100 * @param pIO - io stream
101 * @param pData - buffer holding data
102 * @param n - number of bytes to write
103 * @param timeout_mSecs - standard timeout scheme
104 *
105 * @return actual number of bytes written, or negative on error
106 */
107 static int _file_wr_fn(struct io_stream *pIO,
108 const void *pData,
109 size_t n,
110 int timeout_mSecs)
111 {
112 int r;
113 size_t _r;
114 FILE *fp;
116 /* not used */
117 (void)(timeout_mSecs);
119 fp = get_fp(pIO);
120 if(fp)
121 {
122 _r = fwrite(pData, sizeof(char), n,fp);
123 if(_r != n)
124 {
125 r = -1;
126 }
127 else
128 {
129 r = (int)(n);
130 }
131 }
132 else
133 {
134 r = -1;
135 }
136 return (r);
137 }
139 /*!
140 * @brief [private] Read from a FILE based stream
141 * @param pIO - io stream
142 * @param pData - buffer to put data into
143 * @param n - number of bytes to read
144 * @param timeout_mSecs - standard timeout scheme
145 *
146 * @return actual number of bytes read, or negative on error
147 */
148 static int _file_rd_fn(struct io_stream *pIO,
149 void *pData,
150 size_t n,
151 int timeout_mSecs)
152 {
153 FILE *fp;
154 int r;
155 size_t _r;
156 /* not used */
157 (void)(timeout_mSecs);
159 fp = get_fp(pIO);
160 if(fp)
161 {
162 _r = fread(pData, sizeof(char), n,fp);
163 if(_r == n)
164 {
165 r = (int)(n);
166 }
167 else
168 {
169 r = -1;
170 }
171 }
172 else
173 {
174 r = -1;
175 }
176 return (r);
177 }
179 /*!
180 * @brief [private] Determine if the file stream is readable
181 * @param pIO - io stream
182 * @param timeout_mSec - standard timeout scheme
183 * @returns true if readable
184 */
185 static bool _file_poll_rx_avail(struct io_stream *pIO, int timeout_mSec)
186 {
187 FILE *fp;
188 struct unix_fdrw rw;
190 /* not used for files */
191 (void)(timeout_mSec);
193 fp = get_fp(pIO);
194 if(fp == NULL)
195 {
196 return (false);
197 }
199 if(feof(fp) || ferror(fp))
200 {
201 return (false);
202 }
204 memset((void *)(&rw), 0, sizeof(rw));
206 rw.fd = fileno(fp);
207 rw.rw = 'r';
208 rw.log_prefix = "fileio";
209 rw.log_why = LOG_NOTHING;
210 rw.log_why_raw = LOG_NOTHING;
211 rw.mSecs_timeout = timeout_mSec;
212 rw.type = 'f';
214 if(POLL_readable(&rw))
215 {
216 return (true);
217 }
218 else
219 {
220 return (false);
221 }
222 }
224 /*!
225 * @brief [private] file flush function
226 * @param pIO - the io stream to flush
227 *
228 * @return 0 success, negative error
229 */
230 static int _file_flush_fn(struct io_stream *pIO)
231 {
232 FILE *fp;
234 /* recover our file pointer */
235 fp = get_fp(pIO);
237 /* bad? */
238 if(!fp)
239 {
240 return (-1);
241 }
243 /* flush */
244 fflush(fp);
245 /* return error or not */
246 if(ferror(fp))
247 {
248 return (-1);
249 }
250 else
251 {
252 return (0);
253 }
254 }
256 /*!
257 * \var _file_funcs
258 *
259 * \brief [private] to file implimentation, io functions for FILES
260 */
261 static const struct io_stream_funcs _file_funcs =
262 {
263 .name = "file",
264 .wr_fn = _file_wr_fn,
265 .rd_fn = _file_rd_fn,
266 .close_fn = _file_close_fn,
267 .flush_fn = _file_flush_fn,
268 .poll_fn = _file_poll_rx_avail
269 };
271 static FILE *is_dev_std(const char *fn)
272 {
273 /* required because Windows does not */
274 /* support these names like linux */
275 if(0 == strcmp(fn, "/dev/stdout"))
276 {
277 return (stdout);
278 }
279 if(0 == strcmp(fn, "/dev/stdin"))
280 {
281 return (stdin);
282 }
283 if(0 == strcmp(fn, "/dev/stderr"))
284 {
285 return (stderr);
286 }
287 return (NULL);
288 }
290 /*
291 * See stream_file.h
292 */
293 intptr_t STREAM_createWrFile(const char *filename)
294 {
295 intptr_t r;
296 FILE *fp;
297 bool must_close;
299 must_close = false;
300 fp = is_dev_std(filename);
301 if(fp)
302 {
303 if(fp == stdin)
304 {
305 fp = NULL;
306 }
307 }
308 if(fp == NULL)
309 {
310 must_close = true;
311 fp = fopen(filename, "w");
312 if(fp == NULL)
313 {
314 LOG_perror(filename);
315 return (0);
316 }
317 }
318 r = STREAM_createFpFile(fp);
319 if( r == 0 )
320 {
321 if( must_close )
322 {
323 fclose(fp);
324 }
325 LOG_perror(filename);
326 }
327 return (r);
328 }
330 /*
331 * See stream_file.h
332 */
333 intptr_t STREAM_createRdFile(const char *filename)
334 {
335 intptr_t r;
336 FILE *fp;
337 bool must_close;
339 must_close = false;
340 fp = is_dev_std(filename);
341 if(fp)
342 {
343 if(fp != stdin)
344 {
345 fp = NULL;
346 }
347 }
348 if(fp == NULL)
349 {
350 must_close = true;
351 fp = fopen(filename, "r");
352 if(fp == NULL)
353 {
354 LOG_perror(filename);
355 return (0);
356 }
357 }
358 r = STREAM_createFpFile(fp);
359 if(r == 0)
360 {
361 if( must_close )
362 {
363 fclose(fp);
364 }
365 LOG_perror(filename);
366 }
367 return (r);
368 }
370 /*
371 * See stream_file.h
372 */
373 intptr_t STREAM_createFpFile(FILE *fp)
374 {
375 struct io_stream *pIO;
377 if(fp == NULL)
378 {
379 return (0);
380 }
382 pIO = STREAM_createPrivate(&_file_funcs, (intptr_t)(fp));
383 return (STREAM_structToH(pIO));
384 }
386 FILE *STREAM_getFp(intptr_t h)
387 {
388 struct io_stream *pIO;
389 pIO = STREAM_hToStruct(h);
390 if( pIO == NULL )
391 {
392 return NULL;
393 }
394 if(pIO->pFuncs != &_file_funcs)
395 {
396 return (NULL);
397 }
398 return (get_fp(pIO));
399 }
401 /*
402 * See stream_file.h
403 */
404 bool STREAM_isFile(intptr_t h)
405 {
406 struct io_stream *pIO;
408 pIO = STREAM_hToStruct(h);
409 if(pIO==NULL)
410 {
411 return (false);
412 }
413 if(pIO->pFuncs == &_file_funcs)
414 {
415 return (true);
416 }
417 else
418 {
419 return (false);
420 }
421 }
423 /*
424 * ========================================
425 * Texas Instruments Micro Controller Style
426 * ========================================
427 * Local Variables:
428 * mode: c
429 * c-file-style: "bsd"
430 * tab-width: 4
431 * c-basic-offset: 4
432 * indent-tabs-mode: nil
433 * End:
434 * vim:set filetype=c tabstop=4 shiftwidth=4 expandtab=true
435 */