source: mainline/uspace/lib/libc/generic/io/stdio.c@ 6b21292

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 6b21292 was 1c1002a, checked in by Jiri Svoboda <jirik.svoboda@…>, 17 years ago

fprintf(), vfprintf().

  • Property mode set to 100644
File size: 5.2 KB
Line 
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
46FILE *stdin, *stdout, *stderr;
47
48/**
49 * Open a stream.
50 *
51 * @param file_name Name of the file to open.
52 * @param mode Mode string, (r|w|a)[b|t][+].
53 */
54FILE *fopen(const char *file_name, const char *mode)
55{
56 FILE *f;
57 int flags;
58 bool plus;
59 const char *mp;
60
61 /* Parse mode except first character. */
62
63 mp = mode;
64 if (*mp++ == '\0') {
65 errno = EINVAL;
66 return NULL;
67 }
68
69 if (*mp == 'b' || *mp == 't') ++mp;
70
71 if (*mp == '+') {
72 ++mp;
73 plus = true;
74 } else {
75 plus = false;
76 }
77
78 if (*mp != '\0') {
79 errno = EINVAL;
80 return NULL;
81 }
82
83 /* Parse first character of mode and determine flags for open(). */
84
85 switch (mode[0]) {
86 case 'r':
87 flags = plus ? O_RDWR : O_RDONLY;
88 break;
89 case 'w':
90 flags = (O_TRUNC | O_CREAT) | (plus ? O_RDWR : O_WRONLY);
91 break;
92 case 'a':
93 /* TODO: a+ must read from beginning, append to the end. */
94 if (plus) {
95 errno = ENOTSUP;
96 return NULL;
97 }
98 flags = (O_APPEND | O_CREAT) | (plus ? O_RDWR : O_WRONLY);
99 default:
100 errno = EINVAL;
101 return NULL;
102 }
103
104 /* Open file. */
105
106 f = malloc(sizeof(FILE));
107 if (f == NULL) {
108 errno = ENOMEM;
109 return NULL;
110 }
111
112 f->fd = open(file_name, flags, 0666);
113 if (f->fd < 0) {
114 free(f);
115 return NULL; /* errno was set by open() */
116 }
117
118 f->error = 0;
119 f->eof = 0;
120
121 return f;
122}
123
124/** Close a stream.
125 *
126 * @param f Pointer to stream.
127 * @return 0 on success, EOF on error.
128 */
129int fclose(FILE *f)
130{
131 int rc;
132
133 rc = close(f->fd);
134 free(f);
135
136 if (rc != 0)
137 return EOF; /* errno was set by close() */
138
139 return 0;
140}
141
142/** Read from a stream.
143 *
144 * @param buf Destination buffer.
145 * @param size Size of each record.
146 * @param nmemb Number of records to read.
147 * @param f Pointer to the stream.
148 */
149size_t fread(void *buf, size_t size, size_t nmemb, FILE *f)
150{
151 size_t left, done, n;
152
153 left = size * nmemb;
154 done = 0;
155
156 while (left > 0 && !f->error && !f->eof) {
157 n = read(f->fd, buf + done, left);
158
159 if (n < 0) {
160 f->error = 1;
161 } else if (n == 0) {
162 f->eof = 1;
163 } else {
164 left -= n;
165 done += n;
166 }
167 }
168
169 return done / size;
170}
171
172
173/** Write to a stream.
174 *
175 * @param buf Source buffer.
176 * @param size Size of each record.
177 * @param nmemb Number of records to write.
178 * @param f Pointer to the stream.
179 */
180size_t fwrite(const void *buf, size_t size, size_t nmemb, FILE *f)
181{
182 size_t left, done, n;
183
184 left = size * nmemb;
185 done = 0;
186
187 while (left > 0 && !f->error) {
188 n = write(f->fd, buf + done, left);
189
190 if (n <= 0) {
191 f->error = 1;
192 } else {
193 left -= n;
194 done += n;
195 }
196 }
197
198 return done / size;
199}
200
201/** Return the end-of-file indicator of a stream. */
202int feof(FILE *f)
203{
204 return f->eof;
205}
206
207/** Return the error indicator of a stream. */
208int ferror(FILE *f)
209{
210 return f->error;
211}
212
213/** Clear the error and end-of-file indicators of a stream. */
214void clearerr(FILE *f)
215{
216 f->eof = 0;
217 f->error = 0;
218}
219
220/** Read character from a stream. */
221int fgetc(FILE *f)
222{
223 unsigned char c;
224 size_t n;
225
226 n = fread(&c, sizeof(c), 1, f);
227 if (n < 1) return EOF;
228
229 return (int) c;
230}
231
232/** Write character to a stream. */
233int fputc(int c, FILE *f)
234{
235 unsigned char cc;
236 size_t n;
237
238 cc = (unsigned char) c;
239 n = fwrite(&cc, sizeof(cc), 1, f);
240 if (n < 1) return EOF;
241
242 return (int) cc;
243}
244
245/** Write string to a stream. */
246int fputs(const char *s, FILE *f)
247{
248 int rc;
249
250 rc = 0;
251
252 while (*s && rc >= 0) {
253 rc = fputc(*s++, f);
254 }
255
256 if (rc < 0) return EOF;
257
258 return 0;
259}
260
261/** Seek to position in stream. */
262int fseek(FILE *f, long offset, int origin)
263{
264 off_t rc;
265
266 rc = lseek(f->fd, offset, origin);
267 if (rc == (off_t) (-1)) {
268 /* errno has been set by lseek. */
269 return -1;
270 }
271
272 f->eof = 0;
273
274 return 0;
275}
276
277/** @}
278 */
Note: See TracBrowser for help on using the repository browser.