stdio.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. #include <stdio.h>
  2. #include <syscall.h>
  3. #include <string.h>
  4. #include <sys/types.h>
  5. #include <unistd.h>
  6. #include <fcntl.h>
  7. #include <errno.h>
  8. #include <_xlog.h>
  9. struct _FILE {
  10. int fd;
  11. char * read_buf;
  12. int available;
  13. int offset;
  14. int read_from;
  15. int ungetc;
  16. int eof;
  17. int bufsiz;
  18. };
  19. FILE _stdin = {
  20. .fd = 0,
  21. .read_buf = NULL,
  22. .available = 0,
  23. .offset = 0,
  24. .read_from = 0,
  25. .ungetc = -1,
  26. .eof = 0,
  27. .bufsiz = BUFSIZ,
  28. };
  29. FILE _stdout = {
  30. .fd = 1,
  31. .read_buf = NULL,
  32. .available = 0,
  33. .offset = 0,
  34. .read_from = 0,
  35. .ungetc = -1,
  36. .eof = 0,
  37. .bufsiz = BUFSIZ,
  38. };
  39. FILE _stderr = {
  40. .fd = 2,
  41. .read_buf = NULL,
  42. .available = 0,
  43. .offset = 0,
  44. .read_from = 0,
  45. .ungetc = -1,
  46. .eof = 0,
  47. .bufsiz = BUFSIZ,
  48. };
  49. FILE * stdin = &_stdin;
  50. FILE * stdout = &_stdout;
  51. FILE * stderr = &_stderr;
  52. void __stdio_init_buffers(void) {
  53. _stdin.read_buf = malloc(BUFSIZ);
  54. //_stdout.read_buf = malloc(BUFSIZ);
  55. //_stderr.read_buf = malloc(BUFSIZ);
  56. }
  57. #if 0
  58. static char * stream_id(FILE * stream) {
  59. static char out[] = "stream\0\0\0\0\0\0";
  60. if (stream == &_stdin) return "stdin";
  61. if (stream == &_stdout) return "stdout";
  62. if (stream == &_stderr) return "stderr";
  63. sprintf(out, "stream %d", fileno(stream));
  64. return out;
  65. }
  66. #endif
  67. extern char * _argv_0;
  68. int setvbuf(FILE * stream, char * buf, int mode, size_t size) {
  69. if (mode != _IOLBF) {
  70. return -1; /* Unsupported */
  71. }
  72. if (buf) {
  73. if (stream->read_buf) {
  74. free(stream->read_buf);
  75. }
  76. stream->read_buf = buf;
  77. stream->bufsiz = size;
  78. }
  79. return 0;
  80. }
  81. static size_t read_bytes(FILE * f, char * out, size_t len) {
  82. size_t r_out = 0;
  83. //fprintf(stderr, "%s: Read %d bytes from %s\n", _argv_0, len, stream_id(f));
  84. //fprintf(stderr, "%s: off[%d] avail[%d] read[%d]\n", _argv_0, f->offset, f->available, f->read_from);
  85. while (len > 0) {
  86. if (f->ungetc >= 0) {
  87. *out = f->ungetc;
  88. len--;
  89. out++;
  90. r_out++;
  91. f->ungetc = -1;
  92. continue;
  93. }
  94. if (f->available == 0) {
  95. if (f->offset == f->bufsiz) {
  96. f->offset = 0;
  97. }
  98. ssize_t r = read(fileno(f), &f->read_buf[f->offset], f->bufsiz - f->offset);
  99. if (r < 0) {
  100. //fprintf(stderr, "error condition\n");
  101. return r_out;
  102. } else {
  103. f->read_from = f->offset;
  104. f->available = r;
  105. f->offset += f->available;
  106. }
  107. }
  108. if (f->available == 0) {
  109. /* EOF condition */
  110. //fprintf(stderr, "%s: no bytes available, returning read value of %d\n", _argv_0, r_out);
  111. f->eof = 1;
  112. return r_out;
  113. }
  114. //fprintf(stderr, "%s: reading until %d reaches %d or %d reaches 0\n", _argv_0, f->read_from, f->offset, len);
  115. while (f->read_from < f->offset && len > 0 && f->available > 0) {
  116. *out = f->read_buf[f->read_from];
  117. len--;
  118. f->read_from++;
  119. f->available--;
  120. out++;
  121. r_out += 1;
  122. }
  123. }
  124. //fprintf(stderr, "%s: read completed, returning read value of %d\n", _argv_0, r_out);
  125. return r_out;
  126. }
  127. static void parse_mode(const char * mode, int * flags_, int * mask_) {
  128. const char * x = mode;
  129. int flags = 0;
  130. int mask = 0;
  131. while (*x) {
  132. if (*x == 'a') {
  133. flags |= O_WRONLY;
  134. flags |= O_APPEND;
  135. flags |= O_CREAT;
  136. }
  137. if (*x == 'w') {
  138. flags |= O_WRONLY;
  139. flags |= O_CREAT;
  140. flags |= O_TRUNC;
  141. mask = 0666;
  142. }
  143. if (*x == '+') {
  144. flags |= O_RDWR;
  145. flags &= ~(O_APPEND); /* uh... */
  146. }
  147. ++x;
  148. }
  149. *flags_ = flags;
  150. *mask_ = mask;
  151. }
  152. FILE * fopen(const char *path, const char *mode) {
  153. int flags, mask;
  154. parse_mode(mode, &flags, &mask);
  155. int fd = syscall_open(path, flags, mask);
  156. if (fd < 0) {
  157. errno = -fd;
  158. return NULL;
  159. }
  160. FILE * out = malloc(sizeof(FILE));
  161. out->fd = fd;
  162. out->read_buf = malloc(BUFSIZ);
  163. out->bufsiz = BUFSIZ;
  164. out->available = 0;
  165. out->read_from = 0;
  166. out->offset = 0;
  167. out->ungetc = -1;
  168. out->eof = 0;
  169. return out;
  170. }
  171. /* This is very wrong */
  172. FILE * freopen(const char *path, const char *mode, FILE * stream) {
  173. if (path) {
  174. if (stream) {
  175. fclose(stream);
  176. }
  177. int flags, mask;
  178. parse_mode(mode, &flags, &mask);
  179. int fd = syscall_open(path, flags, mask);
  180. stream->fd = fd;
  181. stream->available = 0;
  182. stream->read_from = 0;
  183. stream->offset = 0;
  184. stream->ungetc = -1;
  185. stream->eof = 0;
  186. if (fd < 0) {
  187. errno = -fd;
  188. return NULL;
  189. }
  190. }
  191. return stream;
  192. }
  193. int ungetc(int c, FILE * stream) {
  194. if (stream->ungetc > 0)
  195. return EOF;
  196. return (stream->ungetc = c);
  197. }
  198. FILE * fdopen(int fd, const char *mode){
  199. FILE * out = malloc(sizeof(FILE));
  200. out->fd = fd;
  201. out->read_buf = malloc(BUFSIZ);
  202. out->bufsiz = BUFSIZ;
  203. out->available = 0;
  204. out->read_from = 0;
  205. out->offset = 0;
  206. out->ungetc = -1;
  207. out->eof = 0;
  208. return out;
  209. }
  210. int _fwouldblock(FILE * stream) {
  211. return !stream->available;
  212. }
  213. int fclose(FILE * stream) {
  214. int out = syscall_close(stream->fd);
  215. free(stream->read_buf);
  216. if (stream == &_stdin || stream == &_stdout || stream == &_stderr) {
  217. return out;
  218. } else {
  219. free(stream);
  220. return out;
  221. }
  222. }
  223. int fseek(FILE * stream, long offset, int whence) {
  224. //fprintf(stderr, "%s: seek called, resetting\n", _argv_0);
  225. stream->offset = 0;
  226. stream->read_from = 0;
  227. stream->available = 0;
  228. stream->ungetc = -1;
  229. stream->eof = 0;
  230. int resp = syscall_lseek(stream->fd,offset,whence);
  231. if (resp < 0) {
  232. errno = -resp;
  233. return -1;
  234. }
  235. return 0;
  236. }
  237. long ftell(FILE * stream) {
  238. //fprintf(stderr, "%s: tell called, resetting\n", _argv_0);
  239. stream->offset = 0;
  240. stream->read_from = 0;
  241. stream->available = 0;
  242. stream->ungetc = -1;
  243. stream->eof = 0;
  244. long resp = syscall_lseek(stream->fd, 0, SEEK_CUR);
  245. if (resp < 0) {
  246. errno = -resp;
  247. return -1;
  248. }
  249. return resp;
  250. }
  251. size_t fread(void *ptr, size_t size, size_t nmemb, FILE * stream) {
  252. char * tracking = (char*)ptr;
  253. for (size_t i = 0; i < nmemb; ++i) {
  254. int r = read_bytes(stream, tracking, size);
  255. if (r < 0) {
  256. return -1;
  257. }
  258. tracking += r;
  259. if (r < (int)size) {
  260. return i;
  261. }
  262. }
  263. return nmemb;
  264. }
  265. size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE * stream) {
  266. char * tracking = (char*)ptr;
  267. for (size_t i = 0; i < nmemb; ++i) {
  268. int r = syscall_write(stream->fd, tracking, size);
  269. if (r < 0) {
  270. errno = -r;
  271. _XLOG("write error in fwrite");
  272. return -1;
  273. }
  274. tracking += r;
  275. if (r < (int)size) {
  276. return i;
  277. }
  278. }
  279. return nmemb;
  280. }
  281. int fileno(FILE * stream) {
  282. return stream->fd;
  283. }
  284. int fflush(FILE * stream) {
  285. return 0;
  286. }
  287. int fputs(const char *s, FILE *stream) {
  288. fwrite(s, strlen(s), 1, stream);
  289. /* eof? */
  290. return 0;
  291. }
  292. int fputc(int c, FILE *stream) {
  293. char data[] = {c};
  294. fwrite(data, 1, 1, stream);
  295. return c;
  296. }
  297. int fgetc(FILE * stream) {
  298. char buf[1];
  299. int r;
  300. r = fread(buf, 1, 1, stream);
  301. if (r < 0) {
  302. stream->eof = 1;
  303. return EOF;
  304. } else if (r == 0) {
  305. stream->eof = 1;
  306. return EOF;
  307. }
  308. return (unsigned char)buf[0];
  309. }
  310. char *fgets(char *s, int size, FILE *stream) {
  311. int c;
  312. char * out = s;
  313. while ((c = fgetc(stream)) > 0) {
  314. *s++ = c;
  315. size--;
  316. if (size == 0) {
  317. return out;
  318. }
  319. *s = '\0';
  320. if (c == '\n') {
  321. return out;
  322. }
  323. }
  324. if (c == EOF) {
  325. stream->eof = 1;
  326. if (out == s) {
  327. return NULL;
  328. } else {
  329. return out;
  330. }
  331. }
  332. return NULL;
  333. }
  334. int putchar(int c) {
  335. return fputc(c, stdout);
  336. }
  337. void rewind(FILE *stream) {
  338. fseek(stream, 0, SEEK_SET);
  339. }
  340. void setbuf(FILE * stream, char * buf) {
  341. // ...
  342. }
  343. int feof(FILE * stream) {
  344. return stream->eof;
  345. }
  346. void clearerr(FILE * stream) {
  347. stream->eof = 0;
  348. }
  349. int ferror(FILE * stream) {
  350. return 0; /* TODO */
  351. }