source: mainline/uspace/lib/posix/stdio.c@ d9eaa43

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since d9eaa43 was a6d908c1, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 14 years ago

Small changes in includes.

  • Property mode set to 100644
File size: 14.5 KB
Line 
1/*
2 * Copyright (c) 2011 Jiri Zarevucky
3 * Copyright (c) 2011 Petr Koupy
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup libposix
31 * @{
32 */
33/** @file
34 */
35
36#define LIBPOSIX_INTERNAL
37
38/* Has to be first. */
39#include "stdbool.h"
40
41#include "internal/common.h"
42#include "stdio.h"
43
44#include "assert.h"
45#include "errno.h"
46#include "string.h"
47#include "sys/types.h"
48
49#include "libc/io/printf_core.h"
50#include "libc/str.h"
51
52
53/* not the best of solutions, but freopen and ungetc will eventually
54 * need to be implemented in libc anyway
55 */
56#include "../c/generic/private/stdio.h"
57
58/** Clears the stream's error and end-of-file indicators.
59 *
60 * @param stream Stream whose indicators shall be cleared.
61 */
62void posix_clearerr(FILE *stream)
63{
64 stream->error = 0;
65 stream->eof = 0;
66}
67
68/**
69 * Generate a pathname for the controlling terminal.
70 *
71 * @param s Allocated buffer to which the pathname shall be put.
72 * @return Either s or static location filled with the requested pathname.
73 */
74char *posix_ctermid(char *s)
75{
76 /* Currently always returns an error value (empty string). */
77 // TODO: return a real terminal path
78
79 static char dummy_path[L_ctermid] = {'\0'};
80
81 if (s == NULL) {
82 return dummy_path;
83 }
84
85 s[0] = '\0';
86 return s;
87}
88
89/**
90 * Push byte back into input stream.
91 *
92 * @param c Byte to be pushed back.
93 * @param stream Stream to where the byte shall be pushed.
94 * @return Provided byte on succes or EOF if not possible.
95 */
96int posix_ungetc(int c, FILE *stream)
97{
98 uint8_t b = (uint8_t) c;
99
100 bool can_unget =
101 /* Provided character is legal. */
102 c != EOF &&
103 /* Stream is consistent. */
104 !stream->error &&
105 /* Stream is buffered. */
106 stream->btype != _IONBF &&
107 /* Last operation on the stream was a read operation. */
108 stream->buf_state == _bs_read &&
109 /* Stream buffer is already allocated (i.e. there was already carried
110 * out either write or read operation on the stream). This is probably
111 * redundant check but let's be safe. */
112 stream->buf != NULL &&
113 /* There is still space in the stream to retreat. POSIX demands the
114 * possibility to unget at least 1 character. It should be always
115 * possible, assuming the last operation on the stream read at least 1
116 * character, because the buffer is refilled in the lazily manner. */
117 stream->buf_tail > stream->buf;
118
119 if (can_unget) {
120 --stream->buf_tail;
121 stream->buf_tail[0] = b;
122 stream->eof = false;
123 return (int) b;
124 } else {
125 return EOF;
126 }
127}
128
129/**
130 *
131 * @param lineptr
132 * @param n
133 * @param delimiter
134 * @param stream
135 * @return
136 */
137ssize_t posix_getdelim(char **restrict lineptr, size_t *restrict n,
138 int delimiter, FILE *restrict stream)
139{
140 // TODO
141 not_implemented();
142}
143
144/**
145 *
146 * @param lineptr
147 * @param n
148 * @param stream
149 * @return
150 */
151ssize_t posix_getline(char **restrict lineptr, size_t *restrict n,
152 FILE *restrict stream)
153{
154 // TODO
155 not_implemented();
156}
157
158/**
159 * Reopen a file stream.
160 *
161 * @param filename Pathname of a file to be reopened or NULL for changing
162 * the mode of the stream.
163 * @param mode Mode to be used for reopening the file or changing current
164 * mode of the stream.
165 * @param stream Current stream associated with the opened file.
166 * @return On success, either a stream of the reopened file or the provided
167 * stream with a changed mode. NULL otherwise.
168 */
169FILE *posix_freopen(
170 const char *restrict filename,
171 const char *restrict mode,
172 FILE *restrict stream)
173{
174 assert(mode != NULL);
175 assert(stream != NULL);
176
177 if (filename == NULL) {
178 // TODO
179
180 /* print error to stderr as well, to avoid hard to find problems
181 * with buggy apps that expect this to work
182 */
183 fprintf(stderr,
184 "ERROR: Application wants to use freopen() to change mode of opened stream.\n"
185 " libposix does not support that yet, the application may function improperly.\n");
186 errno = ENOTSUP;
187 return NULL;
188 }
189
190 FILE* copy = malloc(sizeof(FILE));
191 if (copy == NULL) {
192 errno = ENOMEM;
193 return NULL;
194 }
195 memcpy(copy, stream, sizeof(FILE));
196 fclose(copy); /* copy is now freed */
197
198 copy = fopen(filename, mode); /* open new stream */
199 if (copy == NULL) {
200 /* fopen() sets errno */
201 return NULL;
202 }
203
204 /* move the new stream to the original location */
205 memcpy(stream, copy, sizeof (FILE));
206 free(copy);
207
208 /* update references in the file list */
209 stream->link.next->prev = &stream->link;
210 stream->link.prev->next = &stream->link;
211
212 return stream;
213}
214
215/**
216 *
217 * @param buf
218 * @param size
219 * @param mode
220 * @return
221 */
222FILE *posix_fmemopen(void *restrict buf, size_t size,
223 const char *restrict mode)
224{
225 // TODO
226 not_implemented();
227}
228
229/**
230 *
231 * @param bufp
232 * @param sizep
233 * @return
234 */
235FILE *posix_open_memstream(char **bufp, size_t *sizep)
236{
237 // TODO
238 not_implemented();
239}
240
241/**
242 * Write error messages to standard error.
243 *
244 * @param s Error message.
245 */
246void posix_perror(const char *s)
247{
248 if (s == NULL || s[0] == '\0') {
249 fprintf(stderr, "%s\n", posix_strerror(errno));
250 } else {
251 fprintf(stderr, "%s: %s\n", s, posix_strerror(errno));
252 }
253}
254
255struct _posix_fpos {
256 off64_t offset;
257};
258
259/** Restores stream a to position previously saved with fgetpos().
260 *
261 * @param stream Stream to restore
262 * @param pos Position to restore
263 * @return Zero on success, non-zero (with errno set) on failure
264 */
265int posix_fsetpos(FILE *stream, const posix_fpos_t *pos)
266{
267 return fseek(stream, pos->offset, SEEK_SET);
268}
269
270/** Saves the stream's position for later use by fsetpos().
271 *
272 * @param stream Stream to save
273 * @param pos Place to store the position
274 * @return Zero on success, non-zero (with errno set) on failure
275 */
276int posix_fgetpos(FILE *restrict stream, posix_fpos_t *restrict pos)
277{
278 off64_t ret = ftell(stream);
279 if (ret == -1) {
280 return errno;
281 }
282 pos->offset = ret;
283 return 0;
284}
285
286/**
287 * Reposition a file-position indicator in a stream.
288 *
289 * @param stream Stream to seek in.
290 * @param offset Direction and amount of bytes to seek.
291 * @param whence From where to seek.
292 * @return Zero on success, -1 otherwise.
293 */
294int posix_fseek(FILE *stream, long offset, int whence)
295{
296 return fseek(stream, (off64_t) offset, whence);
297}
298
299/**
300 * Reposition a file-position indicator in a stream.
301 *
302 * @param stream Stream to seek in.
303 * @param offset Direction and amount of bytes to seek.
304 * @param whence From where to seek.
305 * @return Zero on success, -1 otherwise.
306 */
307int posix_fseeko(FILE *stream, posix_off_t offset, int whence)
308{
309 return fseek(stream, (off64_t) offset, whence);
310}
311
312/**
313 * Discover current file offset in a stream.
314 *
315 * @param stream Stream for which the offset shall be retrieved.
316 * @return Current offset or -1 if not possible.
317 */
318long posix_ftell(FILE *stream)
319{
320 return (long) ftell(stream);
321}
322
323/**
324 * Discover current file offset in a stream.
325 *
326 * @param stream Stream for which the offset shall be retrieved.
327 * @return Current offset or -1 if not possible.
328 */
329posix_off_t posix_ftello(FILE *stream)
330{
331 return (posix_off_t) ftell(stream);
332}
333
334/**
335 * Print formatted output to the opened file.
336 *
337 * @param fildes File descriptor of the opened file.
338 * @param format Format description.
339 * @return Either the number of printed characters or negative value on error.
340 */
341int posix_dprintf(int fildes, const char *restrict format, ...)
342{
343 va_list list;
344 va_start(list, format);
345 int result = posix_vdprintf(fildes, format, list);
346 va_end(list);
347 return result;
348}
349
350/**
351 * Write ordinary string to the opened file.
352 *
353 * @param str String to be written.
354 * @param size Size of the string (in bytes)..
355 * @param fd File descriptor of the opened file.
356 * @return The number of written characters.
357 */
358static int _dprintf_str_write(const char *str, size_t size, void *fd)
359{
360 ssize_t wr = write(*(int *) fd, str, size);
361 return str_nlength(str, wr);
362}
363
364/**
365 * Write wide string to the opened file.
366 *
367 * @param str String to be written.
368 * @param size Size of the string (in bytes).
369 * @param fd File descriptor of the opened file.
370 * @return The number of written characters.
371 */
372static int _dprintf_wstr_write(const wchar_t *str, size_t size, void *fd)
373{
374 size_t offset = 0;
375 size_t chars = 0;
376 size_t sz;
377 char buf[4];
378
379 while (offset < size) {
380 sz = 0;
381 if (chr_encode(str[chars], buf, &sz, sizeof(buf)) != EOK) {
382 break;
383 }
384
385 if (write(*(int *) fd, buf, sz) != (ssize_t) sz) {
386 break;
387 }
388
389 chars++;
390 offset += sizeof(wchar_t);
391 }
392
393 return chars;
394}
395
396/**
397 * Print formatted output to the opened file.
398 *
399 * @param fildes File descriptor of the opened file.
400 * @param format Format description.
401 * @param ap Print arguments.
402 * @return Either the number of printed characters or negative value on error.
403 */
404int posix_vdprintf(int fildes, const char *restrict format, va_list ap)
405{
406 printf_spec_t spec = {
407 .str_write = _dprintf_str_write,
408 .wstr_write = _dprintf_wstr_write,
409 .data = &fildes
410 };
411
412 return printf_core(format, &spec, ap);
413}
414
415/**
416 * Print formatted output to the string.
417 *
418 * @param s Output string.
419 * @param format Format description.
420 * @return Either the number of printed characters (excluding null byte) or
421 * negative value on error.
422 */
423int posix_sprintf(char *s, const char *format, ...)
424{
425 va_list list;
426 va_start(list, format);
427 int result = posix_vsprintf(s, format, list);
428 va_end(list);
429 return result;
430}
431
432/**
433 * Print formatted output to the string.
434 *
435 * @param s Output string.
436 * @param format Format description.
437 * @param ap Print arguments.
438 * @return Either the number of printed characters (excluding null byte) or
439 * negative value on error.
440 */
441int posix_vsprintf(char *s, const char *format, va_list ap)
442{
443 return vsnprintf(s, STR_NO_LIMIT, format, ap);
444}
445
446/**
447 * Convert formatted input from the stream.
448 *
449 * @param stream Input stream.
450 * @param format Format description.
451 * @return The number of converted output items or EOF on failure.
452 */
453int posix_fscanf(FILE *restrict stream, const char *restrict format, ...)
454{
455 va_list list;
456 va_start(list, format);
457 int result = posix_vfscanf(stream, format, list);
458 va_end(list);
459 return result;
460}
461
462/**
463 * Convert formatted input from the stream.
464 *
465 * @param stream Input stream.
466 * @param format Format description.
467 * @param arg Output items.
468 * @return The number of converted output items or EOF on failure.
469 */
470int posix_vfscanf(FILE *restrict stream, const char *restrict format, va_list arg)
471{
472 // TODO
473 not_implemented();
474}
475
476/**
477 * Convert formatted input from the standard input.
478 *
479 * @param format Format description.
480 * @return The number of converted output items or EOF on failure.
481 */
482int posix_scanf(const char *restrict format, ...)
483{
484 va_list list;
485 va_start(list, format);
486 int result = posix_vscanf(format, list);
487 va_end(list);
488 return result;
489}
490
491/**
492 * Convert formatted input from the standard input.
493 *
494 * @param format Format description.
495 * @param arg Output items.
496 * @return The number of converted output items or EOF on failure.
497 */
498int posix_vscanf(const char *restrict format, va_list arg)
499{
500 return posix_vfscanf(stdin, format, arg);
501}
502
503/**
504 * Convert formatted input from the string.
505 *
506 * @param s Input string.
507 * @param format Format description.
508 * @return The number of converted output items or EOF on failure.
509 */
510int posix_sscanf(const char *s, const char *format, ...)
511{
512 va_list list;
513 va_start(list, format);
514 int result = posix_vsscanf(s, format, list);
515 va_end(list);
516 return result;
517}
518
519/**
520 * Convert formatted input from the string.
521 *
522 * @param s Input string.
523 * @param format Format description.
524 * @param arg Output items.
525 * @return The number of converted output items or EOF on failure.
526 */
527int posix_vsscanf(
528 const char *restrict s, const char *restrict format, va_list arg)
529{
530 // TODO
531 not_implemented();
532}
533
534/**
535 * Acquire file stream for the thread.
536 *
537 * @param file File stream to lock.
538 */
539void posix_flockfile(FILE *file)
540{
541 /* dummy */
542}
543
544/**
545 * Acquire file stream for the thread (non-blocking).
546 *
547 * @param file File stream to lock.
548 * @return Zero for success and non-zero if the lock cannot be acquired.
549 */
550int posix_ftrylockfile(FILE *file)
551{
552 /* dummy */
553 return 0;
554}
555
556/**
557 * Relinquish the ownership of the locked file stream.
558 *
559 * @param file File stream to unlock.
560 */
561void posix_funlockfile(FILE *file)
562{
563 /* dummy */
564}
565
566/**
567 * Get a byte from a stream (thread-unsafe).
568 *
569 * @param stream Input file stream.
570 * @return Either read byte or EOF.
571 */
572int posix_getc_unlocked(FILE *stream)
573{
574 return getc(stream);
575}
576
577/**
578 * Get a byte from the standard input stream (thread-unsafe).
579 *
580 * @return Either read byte or EOF.
581 */
582int posix_getchar_unlocked(void)
583{
584 return getchar();
585}
586
587/**
588 * Put a byte on a stream (thread-unsafe).
589 *
590 * @param c Byte to output.
591 * @param stream Output file stream.
592 * @return Either written byte or EOF.
593 */
594int posix_putc_unlocked(int c, FILE *stream)
595{
596 return putc(c, stream);
597}
598
599/**
600 * Put a byte on the standard output stream (thread-unsafe).
601 *
602 * @param c Byte to output.
603 * @return Either written byte or EOF.
604 */
605int posix_putchar_unlocked(int c)
606{
607 return putchar(c);
608}
609
610/**
611 * Remove a file.
612 *
613 * @param path Pathname of the file that shall be removed.
614 * @return Zero on success, -1 otherwise.
615 */
616int posix_remove(const char *path)
617{
618 // FIXME: unlink() and rmdir() seem to be equivalent at the moment,
619 // but that does not have to be true forever
620 return unlink(path);
621}
622
623/**
624 *
625 * @param s
626 * @return
627 */
628char *posix_tmpnam(char *s)
629{
630 // TODO: low priority, just a compile-time dependency of binutils
631 not_implemented();
632}
633
634/** @}
635 */
Note: See TracBrowser for help on using the repository browser.