2 meinOS - A unix-like x86 microkernel operating system
3 Copyright (C) 2008 Janosch Gräf <janosch.graef@gmx.net>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <sys/types.h>
29 #define check_stream(stream) ((stream)!=NULL && (stream)->fh>=0)
31 //#define _STDIO_DEBUG
33 static FILE *create_stream(int fh
,int oflag
) {
34 FILE *stream
= malloc(sizeof(FILE));
36 stream
->oflag
= oflag
;
39 stream
->buf
= malloc(BUFSIZ
);
40 stream
->bufcur
= stream
->buf
;
45 static void stdio_exit() {
57 stdin
= create_stream(STDIN_FILENO
,O_RDONLY
);
58 stdout
= create_stream(STDOUT_FILENO
,O_WRONLY
);
59 stderr
= create_stream(STDERR_FILENO
,O_WRONLY
);
64 * Converts a oflag string to a oflag number
65 * @param oflag Mode string
69 static int oflag_str2num(const char *oflag
) {
71 if (oflag
[0]=='r') m
= O_RDONLY
;
72 else if (oflag
[0]=='w') m
= O_CREAT
|O_WRONLY
|O_TRUNC
;
73 else if (oflag
[0]=='a') m
= O_CREAT
|O_APPEND
|O_TRUNC
;
75 if (oflag
[1]=='+' && m
!=-1) m
|= O_RDONLY
|O_WRONLY
;
80 * Creates a name for a temporary file
84 char *tmpnam(char *buf1
) {
85 static unsigned int tmp_num
= 0;
86 static char *buf2
[L_tmpnam
];
87 char *buf
= buf1
!=NULL
?buf1
:memset(buf2
,0,L_tmpnam
);
88 snprintf(buf
,L_tmpnam
,"%s/%04x",P_tmpdir
,tmp_num
++);
93 * Clears error in file
94 * @param file Filehandle
96 void clearerr(FILE *file
) {
101 * Gets whether stream reached EOF
102 * @param stream Stream
105 int feof(FILE *stream
) {
106 if (check_stream(stream
)) return stream
->eof
;
114 * Gets current error of stream
115 * @param steam Stream
116 * @return Error number
118 int ferror(FILE *stream
) {
119 if (check_stream(stream
)) return stream
->error
;
128 * @param stream Stream
129 * @return 0=success; -1=failure
131 int fclose(FILE *stream
) {
132 if (check_stream(stream
)) {
133 if (fflush(stream
)==0) {
134 if (close(stream
->fh
)==0) {
145 * Opens a file with Filedescriptor
146 * @param fh Filedescriptor
150 FILE *fdopen(int fh
,const char *oflag
) {
151 return create_stream(fh
,oflag_str2num(oflag
));
155 * Maps a stream pointer to a file descriptor
156 * @param stream Stream
157 * @return Filedescriptor
159 int fileno(FILE *stream
) {
160 if (check_stream(stream
)) return stream
->fh
;
169 * @param name Path to file
174 FILE *fopen(const char *name
,const char *oflag
) {
175 int m
= oflag_str2num(oflag
);
177 int fh
= open(name
,m
,0777);
179 if ((m
&O_TRUNC
)) ftruncate(fh
,0);
180 return create_stream(fh
,m
);
188 * @param stream Stream to flush
191 int fflush(FILE *stream
) {
195 if (stream
->fh
==STDOUT_FILENO
) ret
= syscall_call(SYSCALL_PUTSN
,3,0,stream
->buf
,stream
->bufcur
-stream
->buf
)==-1?EOF
:0;
196 else if (stream
->fh
==STDERR_FILENO
) ret
= syscall_call(SYSCALL_PUTSN
,3,1,stream
->buf
,stream
->bufcur
-stream
->buf
)==-1?EOF
:0;
199 ret
= write(stream
->fh
,stream
->buf
,stream
->bufcur
-stream
->buf
);
200 if (ret
>0 && ret
<(stream
->bufcur
-stream
->buf
)) {
207 stream
->bufcur
= stream
->buf
;
214 * Print string to stdout
216 * @return How many bytes put
218 int puts(const char *s
) {
219 int ret
= fputs(s
,stdout
);
229 * @param ptr Buffer to get data from
230 * @param size How many bytes to write
231 * @param stream Stream to write to
232 * @return How many elements written
234 size_t _fwrite(const void *ptr
,size_t size
,FILE *stream
) {
235 if (size
==0) return 0;
236 if (check_stream(stream
)) {
237 if (stream
->oflag
&O_WRONLY
) {
238 if (stream
->dobuf
/*&& size<BUFSIZ*/) {
239 if (stream
->bufcur
+size
>stream
->buf
+BUFSIZ
) fflush(stream
);
240 if (size
>BUFSIZ
) size
= BUFSIZ
;
241 memcpy(stream
->bufcur
,ptr
,size
);
242 stream
->bufcur
+= size
;
243 if (memchr(ptr
,'\n',size
)!=NULL
) fflush(stream
);
247 int ret
= write(stream
->fh
,ptr
,size
);
248 if (ret
>0 && ret
<(stream
->bufcur
-stream
->buf
)) stream
->eof
= 1;
264 * Gets string from file
265 * @param s Destination for string
266 * @param n How many bytes to read
267 * @param stream Stream to read from
270 char *fgets(char *s
,int n
,FILE *stream
) {
272 if (check_stream(stream
)) {
273 for (i
=0;i
<n
-1;i
++) {
278 stream
->error
= errno
;
281 if (s
[i
]==0 || s
[i
]=='\n') break;
294 * @param ptr Buffer to store data
295 * @param size How many bytes to read
296 * @param stream Stream to read from
297 * @return How many elements read
299 size_t _fread(void *ptr
,size_t size
,FILE *stream
) {
300 if (check_stream(stream
)) {
302 ret
= read(stream
->fh
,ptr
,size
);
304 if (ret
<size
) stream
->eof
= 1;
315 int fgetpos(FILE *stream
,fpos_t *pos
) {
316 if (check_stream(stream
)) {
317 *pos
= ftello(stream
);
326 int fsetpos(FILE *stream
,fpos_t *pos
) {
327 if (check_stream(stream
)) {
328 fseeko(stream
,*pos
,SEEK_SET
);
337 FILE *freopen(const char *filename
,const char *oflag
,FILE *stream
) {
338 if (check_stream(stream
)) {
341 stream
->oflag
= oflag_str2num(oflag
);
344 stream
->fh
= open(filename
,stream
->oflag
);
353 /// @todo Implement me
354 int fscanf(FILE *stream
,const char *format
,...) {
358 /// @todo Implement me
359 int ungetc(int c
,FILE *stream
) {