Subversion Repositories HelenOS

Rev

Rev 4317 | Rev 4491 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4317 Rev 4482
Line 30... Line 30...
30
 * @{
30
 * @{
31
 */
31
 */
32
/** @file
32
/** @file
33
 */
33
 */
34
 
34
 
35
#include <libc.h>
-
 
36
#include <unistd.h>
-
 
37
#include <stdio.h>
35
#include <stdio.h>
-
 
36
#include <unistd.h>
38
#include <io/io.h>
37
#include <fcntl.h>
39
#include <string.h>
38
#include <string.h>
40
#include <errno.h>
39
#include <errno.h>
41
#include <console.h>
40
#include <bool.h>
-
 
41
#include <malloc.h>
-
 
42
#include <io/klog.h>
-
 
43
#include <vfs/vfs.h>
-
 
44
#include <ipc/devmap.h>
-
 
45
 
-
 
46
FILE stdin_null = {
-
 
47
    .fd = -1,
-
 
48
    .error = true,
-
 
49
    .eof = true,
-
 
50
    .klog = false,
-
 
51
    .phone = -1
-
 
52
};
-
 
53
 
-
 
54
FILE stdout_klog = {
-
 
55
    .fd = -1,
-
 
56
    .error = false,
-
 
57
    .eof = false,
-
 
58
    .klog = true,
-
 
59
    .phone = -1
-
 
60
};
-
 
61
 
-
 
62
FILE *stdin = &stdin_null;
-
 
63
FILE *stdout = &stdout_klog;
-
 
64
FILE *stderr = &stdout_klog;
-
 
65
 
-
 
66
static bool parse_mode(const char *mode, int *flags)
-
 
67
{
-
 
68
    /* Parse mode except first character. */
-
 
69
    const char *mp = mode;
-
 
70
    if (*mp++ == 0) {
-
 
71
        errno = EINVAL;
-
 
72
        return false;
-
 
73
    }
42
 
74
   
43
const static char nl = '\n';
75
    if ((*mp == 'b') || (*mp == 't'))
-
 
76
        mp++;
44
 
77
   
-
 
78
    bool plus;
-
 
79
    if (*mp == '+') {
-
 
80
        mp++;
-
 
81
        plus = true;
-
 
82
    } else
-
 
83
        plus = false;
-
 
84
   
-
 
85
    if (*mp != 0) {
-
 
86
        errno = EINVAL;
-
 
87
        return false;
-
 
88
    }
-
 
89
   
-
 
90
    /* Parse first character of mode and determine flags for open(). */
-
 
91
    switch (mode[0]) {
-
 
92
    case 'r':
-
 
93
        *flags = plus ? O_RDWR : O_RDONLY;
-
 
94
        break;
-
 
95
    case 'w':
-
 
96
        *flags = (O_TRUNC | O_CREAT) | (plus ? O_RDWR : O_WRONLY);
-
 
97
        break;
-
 
98
    case 'a':
-
 
99
        /* TODO: a+ must read from beginning, append to the end. */
-
 
100
        if (plus) {
-
 
101
            errno = ENOTSUP;
-
 
102
            return false;
-
 
103
        }
-
 
104
        *flags = (O_APPEND | O_CREAT) | (plus ? O_RDWR : O_WRONLY);
-
 
105
    default:
-
 
106
        errno = EINVAL;
-
 
107
        return false;
-
 
108
    }
-
 
109
   
-
 
110
    return true;
-
 
111
}
-
 
112
 
-
 
113
/** Open a stream.
-
 
114
 *
-
 
115
 * @param path Path of the file to open.
-
 
116
 * @param mode Mode string, (r|w|a)[b|t][+].
-
 
117
 *
-
 
118
 */
45
int puts(const char *str)
119
FILE *fopen(const char *path, const char *mode)
46
{
120
{
47
    size_t count;
121
    int flags;
-
 
122
    if (!parse_mode(mode, &flags))
-
 
123
        return NULL;
-
 
124
   
-
 
125
    /* Open file. */
-
 
126
    FILE *stream = malloc(sizeof(FILE));
-
 
127
    if (stream == NULL) {
-
 
128
        errno = ENOMEM;
-
 
129
        return NULL;
-
 
130
    }
48
   
131
   
-
 
132
    stream->fd = open(path, flags, 0666);
49
    if (str == NULL)
133
    if (stream->fd < 0) {
-
 
134
        /* errno was set by open() */
-
 
135
        free(stream);
50
        return putnchars("(NULL)", 6);
136
        return NULL;
-
 
137
    }
51
   
138
   
52
    for (count = 0; str[count] != 0; count++);
139
    stream->error = false;
-
 
140
    stream->eof = false;
-
 
141
    stream->klog = false;
-
 
142
    stream->phone = -1;
53
   
143
   
-
 
144
    return stream;
-
 
145
}
-
 
146
 
54
    if (console_write((void *) str, count) == count) {
147
FILE *fopen_node(fs_node_t *node, const char *mode)
-
 
148
{
-
 
149
    int flags;
55
        if (console_write(&nl, 1) == 1)
150
    if (!parse_mode(mode, &flags))
-
 
151
        return NULL;
-
 
152
   
-
 
153
    /* Open file. */
-
 
154
    FILE *stream = malloc(sizeof(FILE));
-
 
155
    if (stream == NULL) {
-
 
156
        errno = ENOMEM;
-
 
157
        return NULL;
-
 
158
    }
-
 
159
   
-
 
160
    stream->fd = open_node(node, flags);
-
 
161
    if (stream->fd < 0) {
-
 
162
        /* errno was set by open_node() */
-
 
163
        free(stream);
56
            return 0;
164
        return NULL;
-
 
165
    }
-
 
166
   
-
 
167
    stream->error = false;
-
 
168
    stream->eof = false;
-
 
169
    stream->klog = false;
-
 
170
    stream->phone = -1;
-
 
171
   
-
 
172
    return stream;
57
    }
173
}
58
   
174
 
-
 
175
int fclose(FILE *stream)
-
 
176
{
-
 
177
    int rc = 0;
-
 
178
   
-
 
179
    fflush(stream);
-
 
180
   
-
 
181
    if (stream->phone >= 0)
-
 
182
        ipc_hangup(stream->phone);
-
 
183
   
-
 
184
    if (stream->fd >= 0)
-
 
185
        rc = close(stream->fd);
-
 
186
   
-
 
187
    if ((stream != &stdin_null) && (stream != &stdout_klog))
-
 
188
        free(stream);
-
 
189
   
-
 
190
    stream = NULL;
-
 
191
   
-
 
192
    if (rc != 0) {
-
 
193
        /* errno was set by close() */
59
    return EOF;
194
        return EOF;
60
}
195
    }
61
 
196
   
-
 
197
    return 0;
-
 
198
}
-
 
199
 
-
 
200
/** Read from a stream.
-
 
201
 *
62
/** Put count chars from buffer to stdout without adding newline
202
 * @param buf    Destination buffer.
63
 * @param buf Buffer with size at least count bytes - NULL pointer NOT allowed!
203
 * @param size   Size of each record.
64
 * @param count
204
 * @param nmemb  Number of records to read.
65
 * @return 0 on succes, EOF on fail
205
 * @param stream Pointer to the stream.
-
 
206
 *
66
 */
207
 */
67
int putnchars(const char *buf, size_t count)
208
size_t fread(void *buf, size_t size, size_t nmemb, FILE *stream)
68
{
209
{
69
    if (console_write((void *) buf, count) == count)
210
    size_t left = size * nmemb;
70
        return 0;
211
    size_t done = 0;
71
   
212
   
-
 
213
    while ((left > 0) && (!stream->error) && (!stream->eof)) {
-
 
214
        ssize_t rd = read(stream->fd, buf + done, left);
-
 
215
       
-
 
216
        if (rd < 0)
-
 
217
            stream->error = true;
-
 
218
        else if (rd == 0)
-
 
219
            stream->eof = true;
-
 
220
        else {
72
    return EOF;
221
            left -= rd;
-
 
222
            done += rd;
-
 
223
        }
73
}
224
    }
74
 
225
   
-
 
226
    return (done / size);
-
 
227
}
-
 
228
 
-
 
229
/** Write to a stream.
-
 
230
 *
-
 
231
 * @param buf    Source buffer.
-
 
232
 * @param size   Size of each record.
-
 
233
 * @param nmemb  Number of records to write.
75
/** Same as puts, but does not print newline at end
234
 * @param stream Pointer to the stream.
76
 *
235
 *
77
 */
236
 */
78
int putstr(const char *str)
237
size_t fwrite(const void *buf, size_t size, size_t nmemb, FILE *stream)
79
{
238
{
-
 
239
    size_t left = size * nmemb;
80
    size_t count;
240
    size_t done = 0;
81
   
241
   
82
    if (str == NULL)
242
    while ((left > 0) && (!stream->error)) {
83
        return putnchars("(NULL)", 6);
243
        ssize_t wr;
84
 
244
       
-
 
245
        if (stream->klog)
85
    for (count = 0; str[count] != 0; count++);
246
            wr = klog_write(buf + done, left);
-
 
247
        else
86
    if (console_write((void *) str, count) == count)
248
            wr = write(stream->fd, buf + done, left);
-
 
249
       
-
 
250
        if (wr <= 0)
-
 
251
            stream->error = true;
-
 
252
        else {
87
        return 0;
253
            left -= wr;
-
 
254
            done += wr;
-
 
255
        }
-
 
256
    }
88
   
257
   
89
    return EOF;
258
    return (done / size);
90
}
259
}
91
 
260
 
92
int putchar(int c)
261
int fputc(wchar_t c, FILE *stream)
93
{
262
{
94
    char buf[STR_BOUNDS(1)];
263
    char buf[STR_BOUNDS(1)];
95
    size_t offs;
264
    size_t sz = 0;
-
 
265
   
-
 
266
    if (chr_encode(c, buf, &sz, STR_BOUNDS(1)) == EOK) {
-
 
267
        size_t wr = fwrite(buf, sz, 1, stream);
96
 
268
       
97
    offs = 0;
269
        if (wr < sz)
98
    if (chr_encode(c, buf, &offs, STR_BOUNDS(1)) != EOK)
-
 
99
        return EOF;
270
            return EOF;
100
 
271
       
101
    if (console_write((void *) buf, offs) == offs)
-
 
102
        return c;
272
        return (int) c;
-
 
273
    }
103
 
274
   
104
    return EOF;
275
    return EOF;
105
}
276
}
106
 
277
 
107
int getchar(void)
278
int putchar(wchar_t c)
108
{
279
{
109
    unsigned char c;
280
    return fputc(c, stdout);
-
 
281
}
110
   
282
 
111
    console_flush();
283
int fputs(const char *str, FILE *stream)
-
 
284
{
112
    if (read_stdin((void *) &c, 1) == 1)
285
    return fwrite(str, str_size(str), 1, stream);
113
        return c;
286
}
114
   
287
 
-
 
288
int puts(const char *str)
-
 
289
{
-
 
290
    return fputs(str, stdout);
-
 
291
}
-
 
292
 
-
 
293
int fgetc(FILE *stream)
-
 
294
{
-
 
295
    char c;
-
 
296
   
-
 
297
    if (fread(&c, sizeof(char), 1, stream) < sizeof(char))
115
    return EOF;
298
        return EOF;
-
 
299
   
-
 
300
    return (int) c;
116
}
301
}
117
 
302
 
118
int fflush(FILE *f)
303
int getchar(void)
119
{
304
{
-
 
305
    return fgetc(stdin);
-
 
306
}
-
 
307
 
-
 
308
int fseek(FILE *stream, long offset, int origin)
-
 
309
{
-
 
310
    off_t rc = lseek(stream->fd, offset, origin);
-
 
311
    if (rc == (off_t) (-1)) {
120
    /* Dummy implementation */
312
        /* errno has been set by lseek. */
121
    (void) f;
313
        return -1;
-
 
314
    }
-
 
315
   
122
    console_flush();
316
    stream->eof = false;
-
 
317
   
123
    return 0;
318
    return 0;
124
}
319
}
125
 
320
 
-
 
321
int fflush(FILE *stream)
-
 
322
{
-
 
323
    if (stream->klog) {
-
 
324
        klog_update();
-
 
325
        return EOK;
-
 
326
    }
-
 
327
   
-
 
328
    if (stream->fd >= 0)
-
 
329
        return fsync(stream->fd);
-
 
330
   
-
 
331
    return ENOENT;
-
 
332
}
-
 
333
 
-
 
334
int feof(FILE *stream)
-
 
335
{
-
 
336
    return stream->eof;
-
 
337
}
-
 
338
 
-
 
339
int ferror(FILE *stream)
-
 
340
{
-
 
341
    return stream->error;
-
 
342
}
-
 
343
 
-
 
344
int fphone(FILE *stream)
-
 
345
{
-
 
346
    if (stream->fd >= 0) {
-
 
347
        if (stream->phone < 0)
-
 
348
            stream->phone = fd_phone(stream->fd);
-
 
349
       
-
 
350
        return stream->phone;
-
 
351
    }
-
 
352
   
-
 
353
    return -1;
-
 
354
}
-
 
355
 
-
 
356
void fnode(FILE *stream, fs_node_t *node)
-
 
357
{
-
 
358
    if (stream->fd >= 0) {
-
 
359
        fd_node(stream->fd, node);
-
 
360
    } else {
-
 
361
        node->fs_handle = 0;
-
 
362
        node->dev_handle = 0;
-
 
363
        node->index = 0;
-
 
364
    }
-
 
365
}
-
 
366
 
126
/** @}
367
/** @}
127
 */
368
 */