Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/posix/stdio.c

    r08053f7 r823a929  
    3636#define LIBPOSIX_INTERNAL
    3737
    38 /* Has to be first. */
    39 #include "stdbool.h"
     38#include <assert.h>
     39#include <errno.h>
    4040
    4141#include "internal/common.h"
    4242#include "stdio.h"
    43 
    44 #include "assert.h"
    45 #include "errno.h"
    4643#include "string.h"
    47 #include "sys/types.h"
    48 
    49 #include "libc/io/printf_core.h"
    50 #include "libc/str.h"
    51 #include "libc/malloc.h"
    52 
    53 
    54 /* not the best of solutions, but freopen and ungetc will eventually
     44
     45/* not the best of solutions, but freopen will eventually
    5546 * need to be implemented in libc anyway
    5647 */
    5748#include "../c/generic/private/stdio.h"
    5849
    59 /** Clears the stream's error and end-of-file indicators.
    60  *
    61  * @param stream Stream whose indicators shall be cleared.
    62  */
    63 void posix_clearerr(FILE *stream)
    64 {
    65         stream->error = 0;
    66         stream->eof = 0;
    67 }
    68 
    69 /**
    70  * Generate a pathname for the controlling terminal.
    71  *
    72  * @param s Allocated buffer to which the pathname shall be put.
    73  * @return Either s or static location filled with the requested pathname.
    74  */
    75 char *posix_ctermid(char *s)
    76 {
    77         /* Currently always returns an error value (empty string). */
    78         // TODO: return a real terminal path
    79 
    80         static char dummy_path[L_ctermid] = {'\0'};
    81 
    82         if (s == NULL) {
    83                 return dummy_path;
    84         }
    85 
    86         s[0] = '\0';
    87         return s;
    88 }
    89 
    90 /**
    91  * Push byte back into input stream.
    92  *
    93  * @param c Byte to be pushed back.
    94  * @param stream Stream to where the byte shall be pushed.
    95  * @return Provided byte on success or EOF if not possible.
     50/**
     51 *
     52 * @param c
     53 * @param stream
     54 * @return
    9655 */
    9756int posix_ungetc(int c, FILE *stream)
    9857{
    99         uint8_t b = (uint8_t) c;
    100 
    101         bool can_unget =
    102                 /* Provided character is legal. */
    103             c != EOF &&
    104                 /* Stream is consistent. */
    105             !stream->error &&
    106                 /* Stream is buffered. */
    107             stream->btype != _IONBF &&
    108                 /* Last operation on the stream was a read operation. */
    109             stream->buf_state == _bs_read &&
    110                 /* Stream buffer is already allocated (i.e. there was already carried
    111                  * out either write or read operation on the stream). This is probably
    112                  * redundant check but let's be safe. */
    113             stream->buf != NULL &&
    114                 /* There is still space in the stream to retreat. POSIX demands the
    115                  * possibility to unget at least 1 character. It should be always
    116                  * possible, assuming the last operation on the stream read at least 1
    117                  * character, because the buffer is refilled in the lazily manner. */
    118             stream->buf_tail > stream->buf;
    119 
    120         if (can_unget) {
    121                 --stream->buf_tail;
    122                 stream->buf_tail[0] = b;
    123                 stream->eof = false;
    124                 return (int) b;
    125         } else {
    126                 return EOF;
    127         }
    128 }
    129 
    130 /**
    131  * Read a stream until the delimiter (or EOF) is encountered.
    132  *
    133  * @param lineptr Pointer to the output buffer in which there will be stored
    134  *     nul-terminated string together with the delimiter (if encountered).
    135  *     Will be resized if necessary.
    136  * @param n Pointer to the size of the output buffer. Will be increased if
    137  *     necessary.
    138  * @param delimiter Delimiter on which to finish reading the stream.
    139  * @param stream Input stream.
    140  * @return Number of fetched characters (including delimiter if encountered)
    141  *     or -1 on error (set in errno).
    142  */
    143 ssize_t posix_getdelim(char **restrict lineptr, size_t *restrict n,
    144     int delimiter, FILE *restrict stream)
    145 {
    146         /* Check arguments for sanity. */
    147         if (!lineptr || !n) {
    148                 errno = EINVAL;
    149                 return -1;
    150         }
    151 
    152         size_t alloc_step = 80; /* Buffer size gain during reallocation. */
    153         char *pos = *lineptr; /* Next free byte of the output buffer. */
    154         size_t cnt = 0; /* Number of fetched characters. */
    155         int c = fgetc(stream); /* Current input character. Might be EOF. */
    156 
    157         do {
    158                 /* Mask EOF as NUL to terminate string. */
    159                 if (c == EOF) {
    160                         c = '\0';
    161                 }
    162 
    163                 /* Ensure there is still space left in the buffer. */
    164                 if (pos == *lineptr + *n) {
    165                         *lineptr = realloc(*lineptr, *n + alloc_step);
    166                         if (*lineptr) {
    167                                 pos = *lineptr + *n;
    168                                 *n += alloc_step;
    169                         } else {
    170                                 errno = ENOMEM;
    171                                 return -1;
    172                         }
    173                 }
    174 
    175                 /* Store the fetched character. */
    176                 *pos = c;
    177 
    178                 /* Fetch the next character according to the current character. */
    179                 if (c != '\0') {
    180                         ++pos;
    181                         ++cnt;
    182                         if (c == delimiter) {
    183                                 /* Delimiter was just stored. Provide EOF as the next
    184                                  * character - it will be masked as NUL and output string
    185                                  * will be properly terminated. */
    186                                 c = EOF;
    187                         } else {
    188                                 /* Neither delimiter nor EOF were encountered. Just fetch
    189                                  * the next character from the stream. */
    190                                 c = fgetc(stream);
    191                         }
    192                 }
    193         } while (c != '\0');
    194 
    195         if (errno == EOK && cnt > 0) {
    196                 return cnt;
    197         } else {
    198                 /* Either some error occured or the stream was already at EOF. */
    199                 return -1;
    200         }
    201 }
    202 
    203 /**
    204  * Read a stream until the newline (or EOF) is encountered.
    205  *
    206  * @param lineptr Pointer to the output buffer in which there will be stored
    207  *     nul-terminated string together with the delimiter (if encountered).
    208  *     Will be resized if necessary.
    209  * @param n Pointer to the size of the output buffer. Will be increased if
    210  *     necessary.
    211  * @param stream Input stream.
    212  * @return Number of fetched characters (including newline if encountered)
    213  *     or -1 on error (set in errno).
    214  */
    215 ssize_t posix_getline(char **restrict lineptr, size_t *restrict n,
    216     FILE *restrict stream)
    217 {
    218         return posix_getdelim(lineptr, n, '\n', stream);
    219 }
    220 
    221 /**
    222  * Reopen a file stream.
    223  *
    224  * @param filename Pathname of a file to be reopened or NULL for changing
    225  *     the mode of the stream.
    226  * @param mode Mode to be used for reopening the file or changing current
    227  *     mode of the stream.
    228  * @param stream Current stream associated with the opened file.
    229  * @return On success, either a stream of the reopened file or the provided
    230  *     stream with a changed mode. NULL otherwise.
     58        // TODO
     59        not_implemented();
     60}
     61
     62/**
     63 *
     64 * @param filename
     65 * @param mode
     66 * @param stream
     67 * @return
    23168 */
    23269FILE *posix_freopen(
     
    278115/**
    279116 *
    280  * @param buf
    281  * @param size
    282  * @param mode
    283  * @return
    284  */
    285 FILE *posix_fmemopen(void *restrict buf, size_t size,
    286     const char *restrict mode)
    287 {
    288         // TODO
    289         not_implemented();
    290 }
    291 
    292 /**
    293  *
    294  * @param bufp
    295  * @param sizep
    296  * @return
    297  */
    298 FILE *posix_open_memstream(char **bufp, size_t *sizep)
    299 {
    300         // TODO
    301         not_implemented();
    302 }
    303 
    304 /**
    305  * Write error messages to standard error.
    306  *
    307  * @param s Error message.
     117 * @param s
    308118 */
    309119void posix_perror(const char *s)
    310120{
    311         if (s == NULL || s[0] == '\0') {
    312                 fprintf(stderr, "%s\n", posix_strerror(errno));
    313         } else {
    314                 fprintf(stderr, "%s: %s\n", s, posix_strerror(errno));
    315         }
    316 }
    317 
    318 struct _posix_fpos {
    319         off64_t offset;
    320 };
    321 
    322 /** Restores stream a to position previously saved with fgetpos().
    323  *
    324  * @param stream Stream to restore
    325  * @param pos Position to restore
    326  * @return Zero on success, non-zero (with errno set) on failure
    327  */
    328 int posix_fsetpos(FILE *stream, const posix_fpos_t *pos)
    329 {
    330         return fseek(stream, pos->offset, SEEK_SET);
    331 }
    332 
    333 /** Saves the stream's position for later use by fsetpos().
    334  *
    335  * @param stream Stream to save
    336  * @param pos Place to store the position
    337  * @return Zero on success, non-zero (with errno set) on failure
    338  */
    339 int posix_fgetpos(FILE *restrict stream, posix_fpos_t *restrict pos)
    340 {
    341         off64_t ret = ftell(stream);
    342         if (ret == -1) {
    343                 return errno;
    344         }
    345         pos->offset = ret;
    346         return 0;
    347 }
    348 
    349 /**
    350  * Reposition a file-position indicator in a stream.
    351  *
    352  * @param stream Stream to seek in.
    353  * @param offset Direction and amount of bytes to seek.
    354  * @param whence From where to seek.
    355  * @return Zero on success, -1 otherwise.
    356  */
    357 int posix_fseek(FILE *stream, long offset, int whence)
    358 {
    359         return fseek(stream, (off64_t) offset, whence);
    360 }
    361 
    362 /**
    363  * Reposition a file-position indicator in a stream.
    364  *
    365  * @param stream Stream to seek in.
    366  * @param offset Direction and amount of bytes to seek.
    367  * @param whence From where to seek.
    368  * @return Zero on success, -1 otherwise.
     121        // TODO
     122        not_implemented();
     123}
     124
     125/**
     126 *
     127 * @param stream
     128 * @param offset
     129 * @param whence
     130 * @return
    369131 */
    370132int posix_fseeko(FILE *stream, posix_off_t offset, int whence)
    371133{
    372         return fseek(stream, (off64_t) offset, whence);
    373 }
    374 
    375 /**
    376  * Discover current file offset in a stream.
    377  *
    378  * @param stream Stream for which the offset shall be retrieved.
    379  * @return Current offset or -1 if not possible.
    380  */
    381 long posix_ftell(FILE *stream)
    382 {
    383         return (long) ftell(stream);
    384 }
    385 
    386 /**
    387  * Discover current file offset in a stream.
    388  *
    389  * @param stream Stream for which the offset shall be retrieved.
    390  * @return Current offset or -1 if not possible.
     134        // TODO
     135        not_implemented();
     136}
     137
     138/**
     139 *
     140 * @param stream
     141 * @return
    391142 */
    392143posix_off_t posix_ftello(FILE *stream)
    393144{
    394         return (posix_off_t) ftell(stream);
    395 }
    396 
    397 /**
    398  * Print formatted output to the opened file.
    399  *
    400  * @param fildes File descriptor of the opened file.
    401  * @param format Format description.
    402  * @return Either the number of printed characters or negative value on error.
    403  */
    404 int posix_dprintf(int fildes, const char *restrict format, ...)
    405 {
    406         va_list list;
    407         va_start(list, format);
    408         int result = posix_vdprintf(fildes, format, list);
    409         va_end(list);
    410         return result;
    411 }
    412 
    413 /**
    414  * Write ordinary string to the opened file.
    415  *
    416  * @param str String to be written.
    417  * @param size Size of the string (in bytes)..
    418  * @param fd File descriptor of the opened file.
    419  * @return The number of written characters.
    420  */
    421 static int _dprintf_str_write(const char *str, size_t size, void *fd)
    422 {
    423         ssize_t wr = write(*(int *) fd, str, size);
    424         return str_nlength(str, wr);
    425 }
    426 
    427 /**
    428  * Write wide string to the opened file.
    429  *
    430  * @param str String to be written.
    431  * @param size Size of the string (in bytes).
    432  * @param fd File descriptor of the opened file.
    433  * @return The number of written characters.
    434  */
    435 static int _dprintf_wstr_write(const wchar_t *str, size_t size, void *fd)
    436 {
    437         size_t offset = 0;
    438         size_t chars = 0;
    439         size_t sz;
    440         char buf[4];
    441        
    442         while (offset < size) {
    443                 sz = 0;
    444                 if (chr_encode(str[chars], buf, &sz, sizeof(buf)) != EOK) {
    445                         break;
    446                 }
    447                
    448                 if (write(*(int *) fd, buf, sz) != (ssize_t) sz) {
    449                         break;
    450                 }
    451                
    452                 chars++;
    453                 offset += sizeof(wchar_t);
    454         }
    455        
    456         return chars;
    457 }
    458 
    459 /**
    460  * Print formatted output to the opened file.
    461  *
    462  * @param fildes File descriptor of the opened file.
    463  * @param format Format description.
    464  * @param ap Print arguments.
    465  * @return Either the number of printed characters or negative value on error.
    466  */
    467 int posix_vdprintf(int fildes, const char *restrict format, va_list ap)
    468 {
    469         printf_spec_t spec = {
    470                 .str_write = _dprintf_str_write,
    471                 .wstr_write = _dprintf_wstr_write,
    472                 .data = &fildes
    473         };
    474        
    475         return printf_core(format, &spec, ap);
    476 }
    477 
    478 /**
    479  * Print formatted output to the string.
    480  *
    481  * @param s Output string.
    482  * @param format Format description.
    483  * @return Either the number of printed characters (excluding null byte) or
    484  *     negative value on error.
    485  */
    486 int posix_sprintf(char *s, const char *restrict format, ...)
    487 {
    488         va_list list;
    489         va_start(list, format);
    490         int result = posix_vsprintf(s, format, list);
    491         va_end(list);
    492         return result;
    493 }
    494 
    495 /**
    496  * Print formatted output to the string.
    497  *
    498  * @param s Output string.
    499  * @param format Format description.
    500  * @param ap Print arguments.
    501  * @return Either the number of printed characters (excluding null byte) or
    502  *     negative value on error.
    503  */
    504 int posix_vsprintf(char *s, const char *restrict format, va_list ap)
    505 {
    506         return vsnprintf(s, STR_NO_LIMIT, format, ap);
    507 }
    508 
    509 /**
    510  * Convert formatted input from the stream.
    511  *
    512  * @param stream Input stream.
    513  * @param format Format description.
    514  * @return The number of converted output items or EOF on failure.
    515  */
    516 int posix_fscanf(FILE *restrict stream, const char *restrict format, ...)
    517 {
    518         va_list list;
    519         va_start(list, format);
    520         int result = posix_vfscanf(stream, format, list);
    521         va_end(list);
    522         return result;
    523 }
    524 
    525 /**
    526  * Convert formatted input from the standard input.
    527  *
    528  * @param format Format description.
    529  * @return The number of converted output items or EOF on failure.
    530  */
    531 int posix_scanf(const char *restrict format, ...)
    532 {
    533         va_list list;
    534         va_start(list, format);
    535         int result = posix_vscanf(format, list);
    536         va_end(list);
    537         return result;
    538 }
    539 
    540 /**
    541  * Convert formatted input from the standard input.
    542  *
    543  * @param format Format description.
    544  * @param arg Output items.
    545  * @return The number of converted output items or EOF on failure.
    546  */
    547 int posix_vscanf(const char *restrict format, va_list arg)
    548 {
    549         return posix_vfscanf(stdin, format, arg);
    550 }
    551 
    552 /**
    553  * Convert formatted input from the string.
    554  *
    555  * @param s Input string.
    556  * @param format Format description.
    557  * @return The number of converted output items or EOF on failure.
    558  */
    559 int posix_sscanf(const char *restrict s, const char *restrict format, ...)
    560 {
    561         va_list list;
    562         va_start(list, format);
    563         int result = posix_vsscanf(s, format, list);
    564         va_end(list);
    565         return result;
    566 }
    567 
    568 /**
    569  * Acquire file stream for the thread.
    570  *
    571  * @param file File stream to lock.
    572  */
    573 void posix_flockfile(FILE *file)
    574 {
    575         /* dummy */
    576 }
    577 
    578 /**
    579  * Acquire file stream for the thread (non-blocking).
    580  *
    581  * @param file File stream to lock.
    582  * @return Zero for success and non-zero if the lock cannot be acquired.
    583  */
    584 int posix_ftrylockfile(FILE *file)
    585 {
    586         /* dummy */
    587         return 0;
    588 }
    589 
    590 /**
    591  * Relinquish the ownership of the locked file stream.
    592  *
    593  * @param file File stream to unlock.
    594  */
    595 void posix_funlockfile(FILE *file)
    596 {
    597         /* dummy */
    598 }
    599 
    600 /**
    601  * Get a byte from a stream (thread-unsafe).
    602  *
    603  * @param stream Input file stream.
    604  * @return Either read byte or EOF.
    605  */
    606 int posix_getc_unlocked(FILE *stream)
    607 {
    608         return getc(stream);
    609 }
    610 
    611 /**
    612  * Get a byte from the standard input stream (thread-unsafe).
    613  *
    614  * @return Either read byte or EOF.
    615  */
    616 int posix_getchar_unlocked(void)
    617 {
    618         return getchar();
    619 }
    620 
    621 /**
    622  * Put a byte on a stream (thread-unsafe).
    623  *
    624  * @param c Byte to output.
    625  * @param stream Output file stream.
    626  * @return Either written byte or EOF.
    627  */
    628 int posix_putc_unlocked(int c, FILE *stream)
    629 {
    630         return putc(c, stream);
    631 }
    632 
    633 /**
    634  * Put a byte on the standard output stream (thread-unsafe).
    635  *
    636  * @param c Byte to output.
    637  * @return Either written byte or EOF.
    638  */
    639 int posix_putchar_unlocked(int c)
    640 {
    641         return putchar(c);
    642 }
    643 
    644 /**
    645  * Remove a file.
    646  *
    647  * @param path Pathname of the file that shall be removed.
    648  * @return Zero on success, -1 otherwise.
     145        // TODO
     146        not_implemented();
     147}
     148
     149/**
     150 *
     151 * @param s
     152 * @param format
     153 * @param ...
     154 * @return
     155 */
     156int posix_sprintf(char *s, const char *format, ...)
     157{
     158        // TODO
     159        not_implemented();
     160}
     161
     162/**
     163 *
     164 * @param s
     165 * @param format
     166 * @param ...
     167 * @return
     168 */
     169int posix_vsprintf(char *s, const char *format, va_list ap)
     170{
     171        // TODO: low priority, just a compile-time dependency of binutils
     172        not_implemented();
     173}
     174
     175/**
     176 *
     177 * @param s
     178 * @param format
     179 * @param ...
     180 * @return
     181 */
     182int posix_sscanf(const char *s, const char *format, ...)
     183{
     184        // TODO
     185        not_implemented();
     186}
     187
     188/**
     189 *
     190 * @param path
     191 * @return
    649192 */
    650193int posix_remove(const char *path)
    651194{
    652         // FIXME: unlink() and rmdir() seem to be equivalent at the moment,
    653         //        but that does not have to be true forever
    654         return unlink(path);
     195        // TODO: low priority, just a compile-time dependency of binutils
     196        not_implemented();
    655197}
    656198
Note: See TracChangeset for help on using the changeset viewer.