Subversion Repositories HelenOS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2008 Jiri Svoboda
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. /** @addtogroup libc
  30.  * @{
  31.  */
  32. /**
  33.  * @file
  34.  * @brief ANSI C Stream I/O.
  35.  */
  36.  
  37. #include <stdlib.h>
  38. #include <sys/types.h>
  39. #include <sys/stat.h>
  40. #include <fcntl.h>
  41. #include <unistd.h>
  42. #include <errno.h>
  43. #include <bool.h>
  44. #include <stdio.h>
  45.  
  46. /**
  47.  * Open a stream.
  48.  *
  49.  * @param file_name Name of the file to open.
  50.  * @param mode      Mode string, (r|w|a)[b|t][+].
  51.  */
  52. FILE *fopen(const char *file_name, const char *mode)
  53. {
  54.     FILE *f;
  55.     int flags;
  56.     bool plus;
  57.     const char *mp;
  58.  
  59.     /* Parse mode except first character. */
  60.  
  61.     mp = mode;
  62.     if (*mp++ == '\0') {
  63.         errno = EINVAL;
  64.         return NULL;
  65.     }
  66.  
  67.     if (*mp == 'b' || *mp == 't') ++mp;
  68.  
  69.     if (*mp == '+') {
  70.         ++mp;
  71.         plus = true;
  72.     } else {
  73.         plus = false;
  74.     }
  75.  
  76.     if (*mp != '\0') {
  77.         errno = EINVAL;
  78.         return NULL;
  79.     }
  80.  
  81.     /* Parse first character of mode and determine flags for open(). */
  82.  
  83.     switch (mode[0]) {
  84.     case 'r':
  85.         flags = plus ? O_RDWR : O_RDONLY;
  86.         break;
  87.     case 'w':
  88.         flags = (O_TRUNC | O_CREAT) | (plus ? O_RDWR : O_WRONLY);
  89.         break;
  90.     case 'a':
  91.         /* TODO: a+ must read from beginning, append to the end. */
  92.         if (plus) {
  93.             errno = ENOTSUP;
  94.             return NULL;
  95.         }
  96.         flags = (O_APPEND | O_CREAT) | (plus ? O_RDWR : O_WRONLY);
  97.     default:
  98.         errno = EINVAL;
  99.         return NULL;
  100.     }
  101.  
  102.     /* Open file. */
  103.    
  104.     f = malloc(sizeof(FILE));
  105.     if (f == NULL) {
  106.         errno = ENOMEM;
  107.         return NULL;
  108.     }
  109.  
  110.     f->fd = open(file_name, flags, 0666);
  111.     if (f->fd < 0) {
  112.         free(f);
  113.         return NULL; /* errno was set by open() */
  114.     }
  115.  
  116.     f->error = 0;
  117.     f->eof = 0;
  118.  
  119.     return f;
  120. }
  121.  
  122. /** Close a stream.
  123.  *
  124.  * @param f Pointer to stream.
  125.  * @return  0 on success, EOF on error.
  126.  */
  127. int fclose(FILE *f)
  128. {
  129.     int rc;
  130.  
  131.     rc = close(f->fd);
  132.     free(f);
  133.  
  134.     if (rc != 0)
  135.         return EOF; /* errno was set by close() */
  136.  
  137.     return 0;
  138. }
  139.  
  140. /** Read from a stream.
  141.  *
  142.  * @param buf   Destination buffer.
  143.  * @param size  Size of each record.
  144.  * @param nmemb Number of records to read.
  145.  * @param f Pointer to the stream.
  146.  */
  147. size_t fread(void *buf, size_t size, size_t nmemb, FILE *f)
  148. {
  149.     size_t left, done, n;
  150.  
  151.     left = size * nmemb;
  152.     done = 0;
  153.  
  154.     while (left > 0 && !f->error && !f->eof) {
  155.         n = read(f->fd, buf + done, left);
  156.  
  157.         if (n < 0) {
  158.             f->error = 1;
  159.         } else if (n == 0) {
  160.             f->eof = 1;
  161.         } else {
  162.             left -= n;
  163.             done += n;
  164.         }
  165.     }
  166.  
  167.     return done / size;
  168. }
  169.  
  170.  
  171. /** Write to a stream.
  172.  *
  173.  * @param buf   Source buffer.
  174.  * @param size  Size of each record.
  175.  * @param nmemb Number of records to write.
  176.  * @param f Pointer to the stream.
  177.  */
  178. size_t fwrite(const void *buf, size_t size, size_t nmemb, FILE *f)
  179. {
  180.     size_t left, done, n;
  181.  
  182.     left = size * nmemb;
  183.     done = 0;
  184.  
  185.     while (left > 0 && !f->error) {
  186.         n = write(f->fd, buf + done, left);
  187.  
  188.         if (n <= 0) {
  189.             f->error = 1;
  190.         } else {
  191.             left -= n;
  192.             done += n;
  193.         }
  194.     }
  195.  
  196.     return done / size;
  197. }
  198.  
  199. /** Return the end-of-file indicator of a stream. */
  200. int feof(FILE *f)
  201. {
  202.     return f->eof;
  203. }
  204.  
  205. /** Return the error indicator of a stream. */
  206. int ferror(FILE *f)
  207. {
  208.     return f->error;
  209. }
  210.  
  211. /** Clear the error and end-of-file indicators of a stream. */
  212. void clearerr(FILE *f)
  213. {
  214.     f->eof = 0;
  215.     f->error = 0;
  216. }
  217.  
  218. /** @}
  219.  */
  220.