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 FILE *create_stream(int fh
,int oflag
) {
32 FILE *stream
= malloc(sizeof(FILE));
34 stream
->oflag
= oflag
;
37 stream
->buf
= malloc(BUFSIZ
);
38 stream
->bufcur
= stream
->buf
;
43 static void stdio_exit() {
55 stdin
= create_stream(STDIN_FILENO
,O_RDONLY
);
56 stdout
= create_stream(STDOUT_FILENO
,O_WRONLY
);
57 stderr
= create_stream(STDERR_FILENO
,O_WRONLY
);
62 * Converts a oflag string to a oflag number
63 * @param oflag Mode string
67 static int oflag_str2num(const char *oflag
) {
69 if (oflag
[0]=='r') m
= O_RDONLY
;
70 else if (oflag
[0]=='w') m
= O_CREAT
|O_WRONLY
|O_TRUNC
;
71 else if (oflag
[0]=='a') m
= O_CREAT
|O_APPEND
|O_TRUNC
;
73 if (oflag
[1]=='+' && m
!=-1) m
|= O_RDONLY
|O_WRONLY
;
78 * Creates a name for a temporary file
82 char *tmpnam(char *buf1
) {
83 static unsigned int tmp_num
= 0;
84 static char *buf2
[L_tmpnam
];
85 char *buf
= buf1
!=NULL
?buf1
:memset(buf2
,0,L_tmpnam
);
86 snprintf(buf
,L_tmpnam
,"%s/%04x",P_tmpdir
,tmp_num
++);
91 * Clears error in file
92 * @param file Filehandle
94 void clearerr(FILE *file
) {
99 * Gets whether stream reached EOF
100 * @param stream Stream
103 int feof(FILE *stream
) {
104 if (check_stream(stream
)) return stream
->eof
;
112 * Gets current error of stream
113 * @param steam Stream
114 * @return Error number
116 int ferror(FILE *stream
) {
117 if (check_stream(stream
)) return stream
->error
;
126 * @param stream Stream
127 * @return 0=success; -1=failure
129 int fclose(FILE *stream
) {
130 if (check_stream(stream
)) {
131 if (fflush(stream
)==0) {
132 if (close(stream
->fh
)==0) {
143 * Opens a file with Filedescriptor
144 * @param fh Filedescriptor
148 FILE *fdopen(int fh
,const char *oflag
) {
149 return create_stream(fh
,oflag_str2num(oflag
));
153 * Maps a stream pointer to a file descriptor
154 * @param stream Stream
155 * @return Filedescriptor
157 int fileno(FILE *stream
) {
158 if (check_stream(stream
)) return stream
->fh
;
167 * @param name Path to file
172 FILE *fopen(const char *name
,const char *oflag
) {
173 int m
= oflag_str2num(oflag
);
175 int fh
= open(name
,m
,0777);
177 //if ((m&O_TRUNC)==O_TRUNC) ftruncate(fh,0);
178 return create_stream(fh
,m
);
186 * @param stream Stream to flush
189 int fflush(FILE *stream
) {
192 /*if (stream->fh==STDOUT_FILENO) ret = syscall_call(SYSCALL_PUTSN,3,0,stream->buf,stream->bufcur-stream->buf)==-1?EOF:0;
193 else if (stream->fh==STDERR_FILENO) 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
)) {
296 ret
= read(stream
->fh
,ptr
,size
);
298 if (ret
<size
) stream
->eof
= 1;
309 int fgetpos(FILE *stream
,fpos_t *pos
) {
310 if (check_stream(stream
)) {
311 *pos
= ftello(stream
);
320 int fsetpos(FILE *stream
,fpos_t *pos
) {
321 if (check_stream(stream
)) {
322 fseeko(stream
,*pos
,SEEK_SET
);
331 FILE *freopen(const char *filename
,const char *oflag
,FILE *stream
) {
332 if (check_stream(stream
)) {
335 stream
->oflag
= oflag_str2num(oflag
);
338 stream
->fh
= open(filename
,stream
->oflag
);
347 /// @todo Implement me
348 int fscanf(FILE *stream
,const char *format
,...) {
352 /// @todo Implement me
353 int ungetc(int c
,FILE *stream
) {