Changes in uspace/lib/c/generic/io/io.c [e86a617a:59f388a] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/io/io.c
re86a617a r59f388a 35 35 #include <stdio.h> 36 36 #include <unistd.h> 37 #include <fcntl.h>38 37 #include <assert.h> 39 38 #include <str.h> … … 45 44 #include <vfs/vfs.h> 46 45 #include <vfs/vfs_sess.h> 46 #include <vfs/inbox.h> 47 47 #include <ipc/loc.h> 48 48 #include <adt/list.h> … … 55 55 static FILE stdin_null = { 56 56 .fd = -1, 57 .pos = 0, 57 58 .error = true, 58 59 .eof = true, … … 69 70 static FILE stdout_kio = { 70 71 .fd = -1, 72 .pos = 0, 71 73 .error = false, 72 74 .eof = false, … … 83 85 static FILE stderr_kio = { 84 86 .fd = -1, 87 .pos = 0, 85 88 .error = false, 86 89 .eof = false, … … 101 104 static LIST_INITIALIZE(files); 102 105 103 void __stdio_init(int filc) 104 { 105 if (filc > 0) { 106 stdin = fdopen(0, "r"); 106 void __stdio_init(void) 107 { 108 /* The first three standard file descriptors are assigned for compatibility. 109 * This will probably be removed later. 110 */ 111 112 int infd = inbox_get("stdin"); 113 if (infd >= 0) { 114 int stdinfd = vfs_clone(infd, -1, false); 115 assert(stdinfd == 0); 116 vfs_open(stdinfd, MODE_READ); 117 stdin = fdopen(stdinfd, "r"); 107 118 } else { 108 119 stdin = &stdin_null; … … 110 121 } 111 122 112 if (filc > 1) { 113 stdout = fdopen(1, "w"); 123 int outfd = inbox_get("stdout"); 124 if (outfd >= 0) { 125 int stdoutfd = vfs_clone(outfd, -1, false); 126 assert(stdoutfd <= 1); 127 while (stdoutfd < 1) 128 stdoutfd = vfs_clone(outfd, -1, false); 129 vfs_open(stdoutfd, MODE_APPEND); 130 stdout = fdopen(stdoutfd, "a"); 114 131 } else { 115 132 stdout = &stdout_kio; … … 117 134 } 118 135 119 if (filc > 2) { 120 stderr = fdopen(2, "w"); 136 int errfd = inbox_get("stderr"); 137 if (errfd >= 0) { 138 int stderrfd = vfs_clone(errfd, -1, false); 139 assert(stderrfd <= 2); 140 while (stderrfd < 2) 141 stderrfd = vfs_clone(errfd, -1, false); 142 vfs_open(stderrfd, MODE_APPEND); 143 stderr = fdopen(stderrfd, "a"); 121 144 } else { 122 145 stderr = &stderr_kio; … … 133 156 } 134 157 135 static bool parse_mode(const char * mode, int *flags)158 static bool parse_mode(const char *fmode, int *mode, bool *create, bool *truncate) 136 159 { 137 160 /* Parse mode except first character. */ 138 const char *mp = mode;161 const char *mp = fmode; 139 162 if (*mp++ == 0) { 140 163 errno = EINVAL; … … 156 179 return false; 157 180 } 158 159 /* Parse first character of mode and determine flags for open(). */ 160 switch (mode[0]) { 181 182 *create = false; 183 *truncate = false; 184 185 /* Parse first character of fmode and determine mode for vfs_open(). */ 186 switch (fmode[0]) { 161 187 case 'r': 162 * flags = plus ? O_RDWR : O_RDONLY;188 *mode = plus ? MODE_READ | MODE_WRITE : MODE_READ; 163 189 break; 164 190 case 'w': 165 *flags = (O_TRUNC | O_CREAT) | (plus ? O_RDWR : O_WRONLY); 191 *mode = plus ? MODE_READ | MODE_WRITE : MODE_WRITE; 192 *create = true; 193 if (!plus) 194 *truncate = true; 166 195 break; 167 196 case 'a': … … 171 200 return false; 172 201 } 173 *flags = (O_APPEND | O_CREAT) | (plus ? O_RDWR : O_WRONLY); 202 203 *mode = MODE_APPEND | (plus ? MODE_READ | MODE_WRITE : MODE_WRITE); 204 *create = true; 174 205 break; 175 206 default: … … 245 276 * 246 277 */ 247 FILE *fopen(const char *path, const char *mode) 248 { 249 int flags; 250 if (!parse_mode(mode, &flags)) 278 FILE *fopen(const char *path, const char *fmode) 279 { 280 int mode; 281 bool create; 282 bool truncate; 283 284 if (!parse_mode(fmode, &mode, &create, &truncate)) 251 285 return NULL; 252 286 … … 257 291 return NULL; 258 292 } 259 260 stream->fd = open(path, flags, 0666); 261 if (stream->fd < 0) { 262 /* errno was set by open() */ 293 294 int flags = WALK_REGULAR; 295 if (create) 296 flags |= WALK_MAY_CREATE; 297 int file = vfs_lookup(path, flags); 298 if (file < 0) { 299 errno = file; 263 300 free(stream); 264 301 return NULL; 265 302 } 266 303 304 int rc = vfs_open(file, mode); 305 if (rc != EOK) { 306 errno = rc; 307 vfs_put(file); 308 free(stream); 309 return NULL; 310 } 311 312 if (truncate) { 313 rc = vfs_resize(file, 0); 314 if (rc != EOK) { 315 errno = rc; 316 vfs_put(file); 317 free(stream); 318 return NULL; 319 } 320 } 321 322 stream->fd = file; 323 stream->pos = 0; 267 324 stream->error = false; 268 325 stream->eof = false; … … 288 345 289 346 stream->fd = fd; 347 stream->pos = 0; 290 348 stream->error = false; 291 349 stream->eof = false; … … 312 370 313 371 if (stream->fd >= 0) 314 rc = close(stream->fd);372 rc = vfs_put(stream->fd); 315 373 316 374 list_remove(&stream->link); … … 373 431 static size_t _fread(void *buf, size_t size, size_t nmemb, FILE *stream) 374 432 { 375 size_t left, done;376 377 433 if (size == 0 || nmemb == 0) 378 434 return 0; 379 435 380 left = size * nmemb; 381 done = 0; 382 383 while ((left > 0) && (!stream->error) && (!stream->eof)) { 384 ssize_t rd = read(stream->fd, buf + done, left); 385 386 if (rd < 0) { 387 /* errno was set by read() */ 388 stream->error = true; 389 } else if (rd == 0) { 390 stream->eof = true; 391 } else { 392 left -= rd; 393 done += rd; 394 } 395 } 396 397 return (done / size); 436 ssize_t rd = vfs_read(stream->fd, &stream->pos, buf, size * nmemb); 437 if (rd < 0) { 438 errno = rd; 439 stream->error = true; 440 rd = 0; 441 } else if (rd == 0) { 442 stream->eof = true; 443 } 444 445 return (rd / size); 398 446 } 399 447 … … 410 458 static size_t _fwrite(const void *buf, size_t size, size_t nmemb, FILE *stream) 411 459 { 412 size_t left;413 size_t done;414 int rc;415 416 460 if (size == 0 || nmemb == 0) 417 461 return 0; 418 462 419 left = size * nmemb; 420 done = 0; 421 422 while ((left > 0) && (!stream->error)) { 423 ssize_t wr; 424 size_t uwr; 425 426 if (stream->kio) { 427 uwr = 0; 428 rc = kio_write(buf + done, left, &uwr); 429 if (rc != EOK) 430 errno = rc; 463 ssize_t wr; 464 if (stream->kio) { 465 size_t nwritten; 466 wr = kio_write(buf, size * nmemb, &nwritten); 467 if (wr != EOK) { 468 stream->error = true; 469 wr = 0; 431 470 } else { 432 wr = write(stream->fd, buf + done, left); 433 if (wr >= 0) { 434 uwr = (size_t)wr; 435 rc = EOK; 436 } else { 437 /* errno was set by write */ 438 uwr = 0; 439 rc = errno; 440 } 471 wr = nwritten; 441 472 } 442 443 if (rc != EOK) { 444 /* errno was set above */ 473 } else { 474 wr = vfs_write(stream->fd, &stream->pos, buf, size * nmemb); 475 if (wr < 0) { 476 errno = wr; 445 477 stream->error = true; 446 } else { 447 left -= uwr; 448 done += uwr; 478 wr = 0; 449 479 } 450 480 } 451 481 452 if ( done> 0)482 if (wr > 0) 453 483 stream->need_sync = true; 454 484 455 return ( done/ size);485 return (wr / size); 456 486 } 457 487 … … 466 496 stream->buf_head = stream->buf_tail = stream->buf; 467 497 468 rc = read(stream->fd, stream->buf, stream->buf_size);498 rc = vfs_read(stream->fd, &stream->pos, stream->buf, stream->buf_size); 469 499 if (rc < 0) { 470 /* errno was set by read() */500 errno = rc; 471 501 stream->error = true; 472 502 return; … … 493 523 494 524 /* If buffer has prefetched read data, we need to seek back. */ 495 if (bytes_used > 0 && stream->buf_state == _bs_read) { 496 off64_t rc; 497 rc = lseek(stream->fd, - (ssize_t) bytes_used, SEEK_CUR); 498 if (rc == (off64_t)-1) { 499 /* errno was set by lseek */ 500 stream->error = 1; 501 return; 502 } 503 } 525 if (bytes_used > 0 && stream->buf_state == _bs_read) 526 stream->pos -= bytes_used; 504 527 505 528 /* If buffer has unwritten data, we need to write them out. */ … … 773 796 int fseek(FILE *stream, off64_t offset, int whence) 774 797 { 775 off64_t rc;798 int rc; 776 799 777 800 if (stream->error) 778 return EOF;801 return -1; 779 802 780 803 _fflushbuf(stream); 781 804 if (stream->error) { 782 805 /* errno was set by _fflushbuf() */ 783 return EOF;806 return -1; 784 807 } 785 808 786 809 stream->ungetc_chars = 0; 787 810 788 rc = lseek(stream->fd, offset, whence); 789 if (rc == (off64_t) (-1)) { 790 /* errno has been set by lseek() */ 791 return EOF; 811 struct stat st; 812 switch (whence) { 813 case SEEK_SET: 814 stream->pos = offset; 815 break; 816 case SEEK_CUR: 817 stream->pos += offset; 818 break; 819 case SEEK_END: 820 rc = vfs_stat(stream->fd, &st); 821 if (rc != EOK) { 822 errno = rc; 823 stream->error = true; 824 return -1; 825 } 826 stream->pos = st.size + offset; 827 break; 792 828 } 793 829 … … 798 834 off64_t ftell(FILE *stream) 799 835 { 800 off64_t pos; 801 836 /* The native position is too large for the C99-ish interface. */ 837 if (stream->pos - stream->ungetc_chars > INT64_MAX) 838 return EOF; 839 802 840 if (stream->error) 803 841 return EOF; … … 809 847 } 810 848 811 pos = lseek(stream->fd, 0, SEEK_CUR); 812 if (pos == (off64_t) -1) { 813 /* errno was set by lseek */ 814 return (off64_t) -1; 815 } 816 817 return pos - stream->ungetc_chars; 849 return stream->pos - stream->ungetc_chars; 818 850 } 819 851 … … 840 872 841 873 if ((stream->fd >= 0) && (stream->need_sync)) { 874 int rc; 875 842 876 /** 843 877 * Better than syncing always, but probably still not the … … 845 879 */ 846 880 stream->need_sync = false; 847 if (fsync(stream->fd) != 0) { 848 /* errno was set by fsync() */ 881 rc = vfs_sync(stream->fd); 882 if (rc != EOK) { 883 errno = rc; 849 884 return EOF; 850 885 }
Note:
See TracChangeset
for help on using the changeset viewer.