Immense cleanup of libc, implemening login program. Slight changes to ACL handling...
[tpg/acess2.git] / Usermode / Libraries / libc.so_src / fileIO.c
1 /*\r
2 AcessOS Basic C Library\r
3 */\r
4 #include "config.h"\r
5 #include <acess/sys.h>\r
6 #include <stdlib.h>\r
7 #include <stdio.h>\r
8 #include <string.h>\r
9 #include "lib.h"\r
10 #include "stdio_int.h"\r
11 \r
12 #define DEBUG_BUILD     0\r
13 \r
14 // === CONSTANTS ===\r
15 #define _stdin  0\r
16 #define _stdout 1\r
17 \r
18 // === PROTOTYPES ===\r
19 EXPORT void     itoa(char *buf, unsigned long num, int base, int minLength, char pad);\r
20 struct sFILE    *get_file_struct();\r
21 \r
22 // === GLOBALS ===\r
23 struct sFILE    _iob[STDIO_MAX_STREAMS];        // IO Buffer\r
24 struct sFILE    *stdin = &_iob[0];      // Standard Input\r
25 struct sFILE    *stdout = &_iob[1];     // Standard Output\r
26 struct sFILE    *stderr = &_iob[2];     // Standard Error\r
27 \r
28 // === CODE ===\r
29 /**\r
30  * \fn FILE *freopen(FILE *fp, char *file, char *mode)\r
31  */\r
32 EXPORT FILE *freopen(FILE *fp, char *file, char *mode)\r
33 {\r
34          int    openFlags = 0;\r
35          int    i;\r
36         \r
37         // Sanity Check Arguments\r
38         if(!fp || !file || !mode)       return NULL;\r
39         \r
40         if(fp->Flags) {\r
41                 fflush(fp);\r
42                 close(fp->FD);\r
43         }\r
44         \r
45         // Get main mode\r
46         switch(mode[0])\r
47         {\r
48         case 'r':       fp->Flags = FILE_FLAG_MODE_READ;        break;\r
49         case 'w':       fp->Flags = FILE_FLAG_MODE_WRITE;       break;\r
50         case 'a':       fp->Flags = FILE_FLAG_MODE_APPEND;      break;\r
51         case 'x':       fp->Flags = FILE_FLAG_MODE_EXEC;        break;\r
52         default:\r
53                 return NULL;\r
54         }\r
55         // Get Modifiers\r
56         for(i=1;mode[i];i++)\r
57         {\r
58                 switch(mode[i])\r
59                 {\r
60                 case '+':       fp->Flags |= FILE_FLAG_M_EXT;\r
61                 }\r
62         }\r
63         \r
64         // Get Open Flags\r
65         switch(mode[0])\r
66         {\r
67         // Read\r
68         case 'r':       openFlags = OPENFLAG_READ;\r
69                 if(fp->Flags & FILE_FLAG_M_EXT)\r
70                         openFlags |= OPENFLAG_WRITE;\r
71                 break;\r
72         // Write\r
73         case 'w':       openFlags = OPENFLAG_WRITE;\r
74                 if(fp->Flags & FILE_FLAG_M_EXT)\r
75                         openFlags |= OPENFLAG_READ;\r
76                 break;\r
77         // Execute\r
78         case 'x':       openFlags = OPENFLAG_EXEC;\r
79                 break;\r
80         }\r
81         \r
82         //Open File\r
83         fp->FD = reopen(fp->FD, file, openFlags);\r
84         if(fp->FD == -1) {\r
85                 fp->Flags = 0;\r
86                 return NULL;\r
87         }\r
88         \r
89         if(mode[0] == 'a') {\r
90                 seek(fp->FD, 0, SEEK_END);      //SEEK_END\r
91         }\r
92         \r
93         return fp;\r
94 }\r
95 /**\r
96  \fn FILE *fopen(char *file, char *mode)\r
97  \brief Opens a file and returns the pointer\r
98  \param file    String - Filename to open\r
99  \param mode    Mode to open in\r
100 */\r
101 EXPORT FILE *fopen(char *file, char *mode)\r
102 {\r
103         FILE    *retFile;\r
104         \r
105         // Sanity Check Arguments\r
106         if(!file || !mode)      return NULL;\r
107         \r
108         // Create Return Structure\r
109         retFile = get_file_struct();\r
110         \r
111         return freopen(retFile, file, mode);\r
112 }\r
113 \r
114 EXPORT void fclose(FILE *fp)\r
115 {\r
116         close(fp->FD);\r
117         free(fp);\r
118 }\r
119 \r
120 EXPORT void fflush(FILE *fp)\r
121 {\r
122         ///\todo Implement\r
123 }\r
124 \r
125 /**\r
126  * \fn int fprintfv(FILE *fp, const char *format, va_list args)\r
127  * \brief Print to a file from a variable argument list\r
128  */\r
129 EXPORT int fprintfv(FILE *fp, const char *format, va_list args)\r
130 {\r
131         va_list tmpList = args;\r
132          int    size;\r
133         char    *buf;\r
134          \r
135         if(!fp || !format)      return -1;\r
136         \r
137         size = ssprintfv((char*)format, tmpList);\r
138         \r
139         buf = (char*)malloc(size+1);\r
140         buf[size] = '\0';\r
141         \r
142         // Print\r
143         sprintfv(buf, (char*)format, args);\r
144         \r
145         // Write to stream\r
146         write(fp->FD, size+1, buf);\r
147         \r
148         // Free buffer\r
149         free(buf);\r
150         \r
151         // Return written byte count\r
152         return size;\r
153 }\r
154 \r
155 /**\r
156  * \fn int fprintf(FILE *fp, const char *format, ...)\r
157  * \brief Print a formatted string to a stream\r
158  */\r
159 EXPORT int fprintf(FILE *fp, const char *format, ...)\r
160 {\r
161         va_list args;\r
162          int    ret;\r
163         \r
164         // Get Size\r
165         va_start(args, format);\r
166         ret = fprintfv(fp, (char*)format, args);\r
167         va_end(args);\r
168         \r
169         return ret;\r
170 }\r
171 \r
172 /**\r
173  */\r
174 EXPORT size_t fwrite(void *ptr, size_t size, size_t num, FILE *fp)\r
175 {\r
176          int    ret;\r
177         if(!fp || !fp->FD)      return -1;\r
178         \r
179         ret = write(fp->FD, size*num, ptr);\r
180         \r
181         return ret;\r
182 }\r
183 \r
184 /**\r
185  * \fn EXPORT int fputc(int c, FILE *fp)\r
186  * \brief Write a single character to the stream\r
187  */\r
188 EXPORT int fputc(int c, FILE *fp)\r
189 {\r
190         if(!fp || !fp->FD)      return -1;\r
191         return write(fp->FD, 1, &c);\r
192 }\r
193 \r
194 /**\r
195  * \fn EXPORT int fgetc(FILE *fp)\r
196  * \brief Read a character from the stream\r
197  */\r
198 EXPORT int fgetc(FILE *fp)\r
199 {\r
200          int    ret = 0;\r
201         if(!fp) return -1;\r
202         if(read(fp->FD, 1, &ret) == -1) return -1;\r
203         return ret;\r
204 }\r
205 \r
206 // --- INTERNAL ---\r
207 /**\r
208  * \fn FILE *get_file_struct()\r
209  * \brief Returns a file descriptor structure\r
210  */\r
211 FILE *get_file_struct()\r
212 {\r
213          int    i;\r
214         for(i=0;i<STDIO_MAX_STREAMS;i++)\r
215         {\r
216                 if(_iob[i].Flags == 0)  return &_iob[i];\r
217         }\r
218         return NULL;\r
219 }\r
220 \r
221 EXPORT int putchar(int ch)\r
222 {\r
223         return write(_stdout, 1, (char*)&ch);\r
224 }\r
225 \r
226 EXPORT int      puts(const char *str)\r
227 {\r
228          int    len;\r
229         \r
230         if(!str)        return 0;\r
231         len = strlen(str);\r
232         \r
233         len = write(_stdout, len, (char*)str);\r
234         write(_stdout, 1, "\n");\r
235         return len;\r
236 }\r
237 \r
238 //sprintfv\r
239 /**\r
240  \fn EXPORT void sprintfv(char *buf, const char *format, va_list args)\r
241  \brief Prints a formatted string to a buffer\r
242  \param buf     Pointer - Destination Buffer\r
243  \param format  String - Format String\r
244  \param args    VarArgs List - Arguments\r
245 */\r
246 EXPORT void sprintfv(char *buf, const char *format, va_list args)\r
247 {\r
248         char    tmp[33];\r
249          int    c, arg, minSize;\r
250          int    pos = 0;\r
251         char    *p;\r
252         char    pad;\r
253 \r
254         tmp[32] = '\0';\r
255         \r
256         while((c = *format++) != 0)\r
257         {\r
258                 //SysDebug("c = '%c'\n", c);\r
259                 if (c != '%') {\r
260                         buf[pos++] = c;\r
261                         continue;\r
262                 }\r
263                 \r
264                 c = *format++;\r
265                 if(c == '%') {\r
266                         buf[pos++] = '%';\r
267                         continue;\r
268                 }\r
269                 \r
270                 // Padding\r
271                 if(c == '0') {\r
272                         pad = '0';\r
273                         c = *format++;\r
274                 } else\r
275                         pad = ' ';\r
276                 minSize = 0;\r
277                 if('1' <= c && c <= '9')\r
278                 {\r
279                         while('0' <= c && c <= '9')\r
280                         {\r
281                                 minSize *= 10;\r
282                                 minSize += c - '0';\r
283                                 c = *format++;\r
284                         }\r
285                 }\r
286         \r
287                 p = tmp;\r
288         \r
289                 // Get Argument\r
290                 arg = va_arg(args, int);\r
291                 // Get Type\r
292                 switch (c) {\r
293                 case 'd':\r
294                 case 'i':\r
295                         if(arg < 0) {\r
296                                 buf[pos++] = '-';\r
297                                 arg = -arg;\r
298                         }\r
299                         itoa(tmp, arg, 10, minSize, pad);\r
300                         goto sprintf_puts;\r
301                 //      break;\r
302                 case 'u':\r
303                         itoa(tmp, arg, 10, minSize, pad);\r
304                         goto sprintf_puts;\r
305                 //      break;\r
306                 case 'x':\r
307                         itoa(tmp, arg, 16, minSize, pad);\r
308                         goto sprintf_puts;\r
309                 //      break;\r
310                 case 'o':\r
311                         itoa(tmp, arg, 8, minSize, pad);\r
312                         goto sprintf_puts;\r
313                 //      break;\r
314                 case 'b':\r
315                         itoa(tmp, arg, 2, minSize, pad);\r
316                         goto sprintf_puts;\r
317                 //      break;\r
318 \r
319                 case 's':\r
320                         p = (void*)arg;\r
321                 sprintf_puts:\r
322                         if(!p)  p = "(null)";\r
323                         while(*p)       buf[pos++] = *p++;\r
324                         break;\r
325 \r
326                 default:\r
327                         buf[pos++] = arg;\r
328                         break;\r
329                 }\r
330     }\r
331         buf[pos++] = '\0';\r
332 }\r
333 /*\r
334 ssprintfv\r
335 - Size, Stream, Print Formated, Variable Argument List\r
336 */\r
337 /**\r
338  \fn EXPORT int ssprintfv(char *format, va_list args)\r
339  \brief Gets the total character count from a formatted string\r
340  \param format  String - Format String\r
341  \param args    VarArgs - Argument List\r
342 */\r
343 EXPORT int ssprintfv(char *format, va_list args)\r
344 {\r
345         char    tmp[33];\r
346          int    c, arg, minSize;\r
347          int    len = 0;\r
348         char    *p;\r
349         char    pad;\r
350 \r
351         tmp[32] = '\0';\r
352         \r
353         while((c = *format++) != 0)\r
354         {\r
355                 if (c != '%') {\r
356                         len++;\r
357                         continue;\r
358                 }\r
359                 \r
360                 c = *format++;\r
361                 \r
362                 // Literal '%'\r
363                 if(c == '%') {\r
364                         len++;\r
365                         continue;\r
366                 }\r
367                 \r
368                 // Padding\r
369                 if(c == '0') {\r
370                         pad = '0';\r
371                         c = *format++;\r
372                 } else\r
373                         pad = ' ';\r
374                 minSize = 0;\r
375                 if('1' <= c && c <= '9')\r
376                 {\r
377                         while('0' <= c && c <= '9')\r
378                         {\r
379                                 minSize *= 10;\r
380                                 minSize += c - '0';\r
381                                 c = *format++;\r
382                         }\r
383                 }\r
384                 \r
385                 p = tmp;\r
386                 arg = va_arg(args, int);\r
387                 switch (c) {                    \r
388                 case 'd':\r
389                 case 'i':\r
390                         if(arg < 0) {\r
391                                 len ++;\r
392                                 arg = -arg;\r
393                         }\r
394                         itoa(tmp, arg, 10, minSize, pad);\r
395                         goto sprintf_puts;\r
396                 case 'u':\r
397                         itoa(tmp, arg, 10, minSize, pad);\r
398                         goto sprintf_puts;\r
399                 case 'x':\r
400                         itoa(tmp, arg, 16, minSize, pad);\r
401                         goto sprintf_puts;\r
402                 case 'o':\r
403                         itoa(tmp, arg, 8, minSize, pad);\r
404                         p = tmp;\r
405                         goto sprintf_puts;\r
406                 case 'b':\r
407                         itoa(tmp, arg, 2, minSize, pad);\r
408                         goto sprintf_puts;\r
409 \r
410                 case 's':\r
411                         p = (char*)arg;\r
412                 sprintf_puts:\r
413                         if(!p)  p = "(null)";\r
414                         while(*p)       len++, p++;\r
415                         break;\r
416 \r
417                 default:\r
418                         len ++;\r
419                         break;\r
420                 }\r
421     }\r
422         return len;\r
423 }\r
424 \r
425 const char cUCDIGITS[] = "0123456789ABCDEF";\r
426 /**\r
427  * \fn static void itoa(char *buf, unsigned long num, int base, int minLength, char pad)\r
428  * \brief Convert an integer into a character string\r
429  */\r
430 EXPORT void itoa(char *buf, unsigned long num, int base, int minLength, char pad)\r
431 {\r
432         char    tmpBuf[32];\r
433          int    pos=0, i;\r
434 \r
435         if(!buf)        return;\r
436         if(base > 16) {\r
437                 buf[0] = 0;\r
438                 return;\r
439         }\r
440         \r
441         while(num > base-1) {\r
442                 tmpBuf[pos] = cUCDIGITS[ num % base ];\r
443                 num = (long) num / base;                //Shift {number} right 1 digit\r
444                 pos++;\r
445         }\r
446 \r
447         tmpBuf[pos++] = cUCDIGITS[ num % base ];                //Last digit of {number}\r
448         i = 0;\r
449         minLength -= pos;\r
450         while(minLength-- > 0)  buf[i++] = pad;\r
451         while(pos-- > 0)                buf[i++] = tmpBuf[pos]; //Reverse the order of characters\r
452         buf[i] = 0;\r
453 }\r
454 \r
455 /**\r
456  * \fn EXPORT int printf(const char *format, ...)\r
457  * \brief Print a string to stdout\r
458  */\r
459 EXPORT int printf(const char *format, ...)\r
460 {\r
461         #if 0\r
462          int    size;\r
463         char    *buf;\r
464         va_list args;\r
465         \r
466         va_start(args, format);\r
467         size = ssprintfv((char*)format, args);\r
468         va_end(args);\r
469         \r
470         buf = (char*)malloc(size+1);\r
471         buf[size] = '\0';\r
472         \r
473         va_start(args, format);\r
474         sprintfv(buf, (char*)format, args);\r
475         va_end(args);\r
476         \r
477         \r
478         write(_stdout, size+1, buf);\r
479         \r
480         free(buf);\r
481         return size;\r
482         #endif\r
483         \r
484          int    ret;\r
485         va_list args;\r
486         va_start(args, format);\r
487         ret = fprintfv(stdout, (char*)format, args);\r
488         va_end(args);\r
489         return ret;\r
490 }\r
491 \r
492 /**\r
493  * \fn EXPORT int sprintf(const char *buf, char *format, ...)\r
494  * \brief Print a formatted string to a buffer\r
495  */\r
496 EXPORT int sprintf(char *buf, const char *format, ...)\r
497 {\r
498         va_list args;\r
499         va_start(args, format);\r
500         sprintfv((char*)buf, (char*)format, args);\r
501         va_end(args);\r
502         return 1;\r
503 }\r

UCC git Repository :: git.ucc.asn.au