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 static unsigned int tmp_num
;
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
);
65 * Converts a oflag string to a oflag number
66 * @param oflag Mode string
70 static int oflag_str2num(const char *oflag
) {
72 if (oflag
[0]=='r') m
= O_RDONLY
;
73 else if (oflag
[0]=='w') m
= O_CREAT
|O_WRONLY
|O_TRUNC
;
74 else if (oflag
[0]=='a') m
= O_CREAT
|O_APPEND
|O_TRUNC
;
76 if (oflag
[1]=='+') m
|= O_RDONLY
|O_WRONLY
;
81 * Creates a name for a temporary file
85 char *tmpnam(char *buf1
) {
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
);
176 int fh
= open(name
,m
,0777);
178 //if ((m&O_TRUNC)==O_TRUNC) ftruncate(fh,0);
179 return create_stream(fh
,m
);
186 * @param stream Stream to flush
189 int fflush(FILE *stream
) {
192 if (stream
==stdout
) ret
= syscall_call(SYSCALL_PUTSN
,3,0,stream
->buf
,stream
->bufcur
-stream
->buf
)==-1?EOF
:0;
193 else if (stream
==stderr
) ret
= syscall_call(SYSCALL_PUTSN
,3,1,stream
->buf
,stream
->bufcur
-stream
->buf
)==-1?EOF
:0;
195 ret
= write(stream
->fh
,stream
->buf
,stream
->bufcur
-stream
->buf
);
196 if (ret
>0 && ret
<(stream
->bufcur
-stream
->buf
)) {
201 stream
->bufcur
= stream
->buf
;
208 * Print string to stdout
210 * @return How many bytes put
212 int puts(const char *s
) {
213 int ret
= fputs(s
,stdout
);
223 * @param ptr Buffer to get data from
224 * @param size How many bytes to write
225 * @param stream Stream to write to
226 * @return How many elements written
228 size_t _fwrite(const void *ptr
,size_t size
,FILE *stream
) {
229 if (size
==0) return 0;
230 if (check_stream(stream
)) {
231 if (stream
->oflag
&O_WRONLY
) {
232 if (stream
->dobuf
/*&& size<BUFSIZ*/) {
233 if (stream
->bufcur
+size
>stream
->buf
+BUFSIZ
) fflush(stream
);
234 if (size
>BUFSIZ
) size
= BUFSIZ
;
235 memcpy(stream
->bufcur
,ptr
,size
);
236 stream
->bufcur
+= size
;
237 if (memchr(ptr
,'\n',size
)!=NULL
) fflush(stream
);
241 int ret
= write(stream
->fh
,ptr
,size
);
242 if (ret
>0 && ret
<(stream
->bufcur
-stream
->buf
)) stream
->eof
= 1;
258 * Gets string from file
259 * @param s Destination for string
260 * @param n How many bytes to read
261 * @param stream Stream to read from
264 char *fgets(char *s
,int n
,FILE *stream
) {
266 if (check_stream(stream
)) {
267 for (i
=0;i
<n
-1;i
++) {
272 stream
->error
= errno
;
275 if (s
[i
]==0 || s
[i
]=='\n') break;
288 * @param ptr Buffer to store data
289 * @param size How many bytes to read
290 * @param stream Stream to read from
291 * @return How many elements read
293 size_t _fread(void *ptr
,size_t size
,FILE *stream
) {
294 if (check_stream(stream
)) {
295 int ret
= read(stream
->fh
,ptr
,size
);
297 if (ret
<size
) stream
->eof
= 1;
308 int fgetpos(FILE *stream
,fpos_t *pos
) {
309 if (check_stream(stream
)) {
310 *pos
= ftello(stream
);
319 int fsetpos(FILE *stream
,fpos_t *pos
) {
320 if (check_stream(stream
)) {
321 fseeko(stream
,*pos
,SEEK_SET
);
330 FILE *freopen(const char *filename
,const char *oflag
,FILE *stream
) {
331 if (check_stream(stream
)) {
334 stream
->oflag
= oflag_str2num(oflag
);
337 stream
->fh
= open(filename
,stream
->oflag
);
346 /// @todo Implement me
347 int fscanf(FILE *stream
,const char *format
,...) {