Changes in uspace/lib/c/generic/vfs/vfs.c [4636a60:6afc9d7] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/vfs/vfs.c
r4636a60 r6afc9d7 43 43 #include <stdio.h> 44 44 #include <sys/stat.h> 45 #include <sys/statfs.h> 45 46 #include <sys/types.h> 46 47 #include <ipc/services.h> … … 74 75 75 76 while (vfs_sess == NULL) 76 vfs_sess = service_connect_blocking( EXCHANGE_PARALLEL, SERVICE_VFS,77 0 , 0);77 vfs_sess = service_connect_blocking(SERVICE_VFS, INTERFACE_VFS, 78 0); 78 79 79 80 fibril_mutex_unlock(&vfs_mutex); … … 92 93 } 93 94 94 int _vfs_walk(int parent, const char *path, int flags) 95 { 96 async_exch_t *exch = vfs_exchange_begin(); 97 98 ipc_call_t answer; 99 aid_t req = async_send_2(exch, VFS_IN_WALK, parent, flags, &answer); 100 sysarg_t rc = async_data_write_start(exch, path, str_size(path)); 101 vfs_exchange_end(exch); 102 103 sysarg_t rc_orig; 104 async_wait_for(req, &rc_orig); 105 106 if (rc_orig != EOK) { 107 return (int) rc_orig; 108 } 109 110 if (rc != EOK) { 111 return (int) rc; 112 } 113 114 return (int) IPC_GET_ARG1(answer); 115 } 116 117 int _vfs_open(int fildes, int mode) 118 { 119 async_exch_t *exch = vfs_exchange_begin(); 120 sysarg_t rc = async_req_2_0(exch, VFS_IN_OPEN2, fildes, mode); 121 vfs_exchange_end(exch); 122 123 return (int) rc; 124 } 125 126 char *absolutize(const char *path, size_t *retlen) 95 char *vfs_absolutize(const char *path, size_t *retlen) 127 96 { 128 97 char *ncwd_path; … … 132 101 size_t size = str_size(path); 133 102 if (*path != '/') { 134 if ( !cwd_path) {103 if (cwd_path == NULL) { 135 104 fibril_mutex_unlock(&cwd_mutex); 136 105 return NULL; 137 106 } 138 107 ncwd_path_nc = malloc(cwd_size + 1 + size + 1); 139 if ( !ncwd_path_nc) {108 if (ncwd_path_nc == NULL) { 140 109 fibril_mutex_unlock(&cwd_mutex); 141 110 return NULL; … … 146 115 } else { 147 116 ncwd_path_nc = malloc(size + 1); 148 if ( !ncwd_path_nc) {117 if (ncwd_path_nc == NULL) { 149 118 fibril_mutex_unlock(&cwd_mutex); 150 119 return NULL; … … 154 123 str_append(ncwd_path_nc, cwd_size + 1 + size + 1, path); 155 124 ncwd_path = canonify(ncwd_path_nc, retlen); 156 if ( !ncwd_path) {125 if (ncwd_path == NULL) { 157 126 fibril_mutex_unlock(&cwd_mutex); 158 127 free(ncwd_path_nc); … … 166 135 ncwd_path = str_dup(ncwd_path); 167 136 free(ncwd_path_nc); 168 if ( !ncwd_path) {137 if (ncwd_path == NULL) { 169 138 fibril_mutex_unlock(&cwd_mutex); 170 139 return NULL; … … 174 143 } 175 144 176 int mount(const char *fs_name, const char *mp, const char *fqsn,145 int vfs_mount(const char *fs_name, const char *mp, const char *fqsn, 177 146 const char *opts, unsigned int flags, unsigned int instance) 178 147 { … … 202 171 203 172 size_t mpa_size; 204 char *mpa = absolutize(mp, &mpa_size);205 if ( !mpa) {173 char *mpa = vfs_absolutize(mp, &mpa_size); 174 if (mpa == NULL) { 206 175 if (null_id != -1) 207 176 loc_null_destroy(null_id); … … 260 229 } 261 230 231 /* Ask VFS whether it likes fs_name. */ 232 rc = async_req_0_0(exch, VFS_IN_PING); 233 if (rc != EOK) { 234 vfs_exchange_end(exch); 235 free(mpa); 236 async_wait_for(req, &rc_orig); 237 238 if (null_id != -1) 239 loc_null_destroy(null_id); 240 241 if (rc_orig == EOK) 242 return (int) rc; 243 else 244 return (int) rc_orig; 245 } 246 262 247 vfs_exchange_end(exch); 263 248 free(mpa); … … 270 255 } 271 256 272 int unmount(const char *mp)257 int vfs_unmount(const char *mp) 273 258 { 274 259 sysarg_t rc; … … 278 263 char *mpa; 279 264 280 mpa = absolutize(mp, &mpa_size);281 if ( !mpa)265 mpa = vfs_absolutize(mp, &mpa_size); 266 if (mpa == NULL) 282 267 return ENOMEM; 283 268 … … 304 289 } 305 290 306 static int walk_flags(int oflags) 307 { 308 int flags = 0; 309 if (oflags & O_CREAT) { 310 if (oflags & O_EXCL) { 311 flags |= WALK_MUST_CREATE; 312 } else { 313 flags |= WALK_MAY_CREATE; 314 } 315 } 316 return flags; 317 } 318 291 /** Open file (internal). 292 * 293 * @param abs Absolute path to file 294 * @param abs_size Size of @a abs string 295 * @param lflag L_xxx flags 296 * @param oflag O_xxx flags 297 * @param fd Place to store new file descriptor 298 * 299 * @return EOK on success, non-zero error code on error 300 */ 301 static int open_internal(const char *abs, size_t abs_size, int lflag, int oflag, 302 int *fd) 303 { 304 async_exch_t *exch = vfs_exchange_begin(); 305 306 ipc_call_t answer; 307 aid_t req = async_send_3(exch, VFS_IN_OPEN, lflag, oflag, 0, &answer); 308 sysarg_t rc = async_data_write_start(exch, abs, abs_size); 309 310 if (rc != EOK) { 311 vfs_exchange_end(exch); 312 313 sysarg_t rc_orig; 314 async_wait_for(req, &rc_orig); 315 316 if (rc_orig == EOK) 317 return (int) rc; 318 else 319 return (int) rc_orig; 320 } 321 322 vfs_exchange_end(exch); 323 async_wait_for(req, &rc); 324 325 if (rc != EOK) 326 return (int) rc; 327 328 *fd = (int) IPC_GET_ARG1(answer); 329 return EOK; 330 } 331 332 /** Open file. 333 * 334 * @param path File path 335 * @param oflag O_xxx flags 336 * @param mode File mode (only with O_CREAT) 337 * 338 * @return Nonnegative file descriptor on success. On error -1 is returned 339 * and errno is set. 340 */ 319 341 int open(const char *path, int oflag, ...) 320 342 { 321 // FIXME: Some applications call this incorrectly.322 if ((oflag & (O_RDONLY|O_WRONLY|O_RDWR)) == 0) {323 oflag |= O_RDWR;324 }325 326 assert((((oflag & O_RDONLY) != 0) + ((oflag & O_WRONLY) != 0) + ((oflag & O_RDWR) != 0)) == 1);327 328 343 size_t abs_size; 329 char *abs = absolutize(path, &abs_size); 330 if (!abs) { 331 return ENOMEM; 332 } 333 334 int ret = _vfs_walk(-1, abs, walk_flags(oflag) | WALK_REGULAR); 335 if (ret < 0) { 336 return ret; 337 } 338 339 int mode = 340 ((oflag & O_RDWR) ? MODE_READ|MODE_WRITE : 0) | 341 ((oflag & O_RDONLY) ? MODE_READ : 0) | 342 ((oflag & O_WRONLY) ? MODE_WRITE : 0) | 343 ((oflag & O_APPEND) ? MODE_APPEND : 0); 344 345 int rc = _vfs_open(ret, mode); 346 if (rc < 0) { 347 // _vfs_put(ret); 348 close(ret); 349 return rc; 350 } 351 352 if (oflag & O_TRUNC) { 353 assert(oflag & O_WRONLY || oflag & O_RDWR); 354 assert(!(oflag & O_APPEND)); 355 356 // _vfs_resize 357 (void) ftruncate(ret, 0); 358 } 359 360 return ret; 361 } 362 344 char *abs = vfs_absolutize(path, &abs_size); 345 int fd = -1; 346 347 if (abs == NULL) { 348 errno = ENOMEM; 349 return -1; 350 } 351 352 int rc = open_internal(abs, abs_size, L_FILE, oflag, &fd); 353 free(abs); 354 355 if (rc != EOK) { 356 errno = rc; 357 return -1; 358 } 359 360 return fd; 361 } 362 363 /** Close file. 364 * 365 * @param fildes File descriptor 366 * @return Zero on success. On error -1 is returned and errno is set. 367 */ 363 368 int close(int fildes) 364 369 { … … 369 374 vfs_exchange_end(exch); 370 375 371 return (int) rc; 372 } 373 374 // TODO: Versioning for read. 375 376 ssize_t read(int fildes, void *buf, size_t nbyte) 376 if (rc != EOK) { 377 errno = rc; 378 return -1; 379 } 380 381 return 0; 382 } 383 384 /** Read bytes from file. 385 * 386 * Read up to @a nbyte bytes from file. The actual number of bytes read 387 * may be lower, but greater than zero if there are any bytes available. 388 * If there are no bytes available for reading, then the function will 389 * return success with zero bytes read. 390 * 391 * @param fildes File descriptor 392 * @param buf Buffer 393 * @param nbyte Maximum number of bytes to read 394 * @param nread Place to store actual number of bytes read (0 or more) 395 * 396 * @return EOK on success, non-zero error code on error. 397 */ 398 static int _read_short(int fildes, void *buf, size_t nbyte, ssize_t *nread) 377 399 { 378 400 sysarg_t rc; … … 380 402 aid_t req; 381 403 404 if (nbyte > DATA_XFER_LIMIT) 405 nbyte = DATA_XFER_LIMIT; 406 382 407 async_exch_t *exch = vfs_exchange_begin(); 383 408 384 409 req = async_send_1(exch, VFS_IN_READ, fildes, &answer); 385 rc = async_data_read_start(exch, (void *) buf, nbyte);386 if (rc != EOK) { 387 vfs_exchange_end(exch); 388 410 rc = async_data_read_start(exch, (void *) buf, nbyte); 411 if (rc != EOK) { 412 vfs_exchange_end(exch); 413 389 414 sysarg_t rc_orig; 390 415 async_wait_for(req, &rc_orig); 391 416 392 417 if (rc_orig == EOK) 393 return (ssize_t)rc;418 return rc; 394 419 else 395 return (ssize_t) rc_orig; 396 } 420 return rc_orig; 421 } 422 397 423 vfs_exchange_end(exch); 398 424 async_wait_for(req, &rc); 399 if (rc == EOK) 400 return (ssize_t) IPC_GET_ARG1(answer); 401 else 425 426 if (rc != EOK) 402 427 return rc; 403 } 404 405 ssize_t write(int fildes, const void *buf, size_t nbyte) 428 429 *nread = (ssize_t) IPC_GET_ARG1(answer); 430 return EOK; 431 } 432 433 /** Write bytes to file. 434 * 435 * Write up to @a nbyte bytes from file. The actual number of bytes written 436 * may be lower, but greater than zero. 437 * 438 * @param fildes File descriptor 439 * @param buf Buffer 440 * @param nbyte Maximum number of bytes to write 441 * @param nread Place to store actual number of bytes written (0 or more) 442 * 443 * @return EOK on success, non-zero error code on error. 444 */ 445 static int _write_short(int fildes, const void *buf, size_t nbyte, 446 ssize_t *nwritten) 406 447 { 407 448 sysarg_t rc; … … 409 450 aid_t req; 410 451 452 if (nbyte > DATA_XFER_LIMIT) 453 nbyte = DATA_XFER_LIMIT; 454 411 455 async_exch_t *exch = vfs_exchange_begin(); 412 456 413 457 req = async_send_1(exch, VFS_IN_WRITE, fildes, &answer); 414 rc = async_data_write_start(exch, (void *) buf, nbyte);415 if (rc != EOK) { 416 vfs_exchange_end(exch); 417 458 rc = async_data_write_start(exch, (void *) buf, nbyte); 459 if (rc != EOK) { 460 vfs_exchange_end(exch); 461 418 462 sysarg_t rc_orig; 419 463 async_wait_for(req, &rc_orig); 420 464 421 465 if (rc_orig == EOK) 422 return (ssize_t)rc;466 return rc; 423 467 else 424 return (ssize_t) rc_orig; 425 } 468 return rc_orig; 469 } 470 426 471 vfs_exchange_end(exch); 427 472 async_wait_for(req, &rc); 428 if (rc == EOK) 429 return (ssize_t) IPC_GET_ARG1(answer); 430 else 431 return -1; 432 } 433 434 /** Read entire buffer. 435 * 436 * In face of short reads this function continues reading until either 437 * the entire buffer is read or no more data is available (at end of file). 473 474 if (rc != EOK) 475 return rc; 476 477 *nwritten = (ssize_t) IPC_GET_ARG1(answer); 478 return EOK; 479 } 480 481 /** Read data. 482 * 483 * Read up to @a nbytes bytes from file if available. This function always reads 484 * all the available bytes up to @a nbytes. 438 485 * 439 486 * @param fildes File descriptor … … 441 488 * @param nbytes Number of bytes to read 442 489 * 443 * @return On success, positive number of bytes read.444 * On failure, negative error code from read().445 */ 446 ssize_t read _all(int fildes, void *buf, size_t nbyte)490 * @return On success, nonnegative number of bytes read. 491 * On failure, -1 and sets errno. 492 */ 493 ssize_t read(int fildes, void *buf, size_t nbyte) 447 494 { 448 495 ssize_t cnt = 0; 449 496 size_t nread = 0; 450 497 uint8_t *bp = (uint8_t *) buf; 451 498 int rc; 499 452 500 do { 453 501 bp += cnt; 454 502 nread += cnt; 455 cnt = read(fildes, bp, nbyte - nread); 456 } while (cnt > 0 && (nbyte - nread - cnt) > 0); 457 458 if (cnt < 0) 459 return cnt; 460 503 rc = _read_short(fildes, bp, nbyte - nread, &cnt); 504 } while (rc == EOK && cnt > 0 && (nbyte - nread - cnt) > 0); 505 506 if (rc != EOK) { 507 errno = rc; 508 return -1; 509 } 510 461 511 return nread + cnt; 462 512 } 463 513 464 /** Write entire buffer.514 /** Write data. 465 515 * 466 516 * This function fails if it cannot write exactly @a len bytes to the file. … … 470 520 * @param nbytes Number of bytes to write 471 521 * 472 * @return EOK on error, return value from write() if writing473 * failed.474 */ 475 ssize_t write _all(int fildes, const void *buf, size_t nbyte)522 * @return On success, nonnegative number of bytes written. 523 * On failure, -1 and sets errno. 524 */ 525 ssize_t write(int fildes, const void *buf, size_t nbyte) 476 526 { 477 527 ssize_t cnt = 0; 478 528 ssize_t nwritten = 0; 479 529 const uint8_t *bp = (uint8_t *) buf; 530 int rc; 480 531 481 532 do { 482 533 bp += cnt; 483 534 nwritten += cnt; 484 cnt = write(fildes, bp, nbyte - nwritten); 485 } while (cnt > 0 && ((ssize_t )nbyte - nwritten - cnt) > 0); 486 487 if (cnt < 0) 488 return cnt; 489 490 if ((ssize_t)nbyte - nwritten - cnt > 0) 491 return EIO; 535 rc = _write_short(fildes, bp, nbyte - nwritten, &cnt); 536 } while (rc == EOK && ((ssize_t )nbyte - nwritten - cnt) > 0); 537 538 if (rc != EOK) { 539 errno = rc; 540 return -1; 541 } 492 542 493 543 return nbyte; 494 544 } 495 545 546 /** Synchronize file. 547 * 548 * @param fildes File descriptor 549 * @return 0 on success. On error returns -1 and sets errno. 550 */ 496 551 int fsync(int fildes) 497 552 { … … 500 555 vfs_exchange_end(exch); 501 556 502 return (int) rc; 503 } 504 557 if (rc != EOK) { 558 errno = rc; 559 return -1; 560 } 561 562 return 0; 563 } 564 565 /** Seek to a position. 566 * 567 * @param fildes File descriptor 568 * @param offset Offset 569 * @param whence SEEK_SET, SEEK_CUR or SEEK_END 570 * 571 * @return On success the nonnegative offset from start of file. On error 572 * returns (off64_t)-1 and sets errno. 573 */ 505 574 off64_t lseek(int fildes, off64_t offset, int whence) 506 575 { … … 515 584 vfs_exchange_end(exch); 516 585 517 if (rc != EOK) 586 if (rc != EOK) { 587 errno = rc; 518 588 return (off64_t) -1; 589 } 519 590 520 591 return (off64_t) MERGE_LOUP32(newoff_lo, newoff_hi); 521 592 } 522 593 594 /** Truncate file to a specified length. 595 * 596 * Truncate file so that its size is exactly @a length 597 * 598 * @param fildes File descriptor 599 * @param length Length 600 * 601 * @return 0 on success, -1 on error and sets errno. 602 */ 523 603 int ftruncate(int fildes, aoff64_t length) 524 604 { … … 530 610 vfs_exchange_end(exch); 531 611 532 return (int) rc; 533 } 534 612 if (rc != EOK) { 613 errno = rc; 614 return -1; 615 } 616 617 return 0; 618 } 619 620 /** Get file status. 621 * 622 * @param fildes File descriptor 623 * @param stat Place to store file information 624 * 625 * @return 0 on success, -1 on error and sets errno. 626 */ 535 627 int fstat(int fildes, struct stat *stat) 536 628 { … … 544 636 if (rc != EOK) { 545 637 vfs_exchange_end(exch); 546 638 547 639 sysarg_t rc_orig; 548 640 async_wait_for(req, &rc_orig); 549 550 if (rc_orig == EOK) 551 return (ssize_t) rc; 552 else 553 return (ssize_t) rc_orig; 554 } 641 642 if (rc_orig != EOK) 643 rc = rc_orig; 644 if (rc != EOK) { 645 errno = rc; 646 return -1; 647 } 648 649 return 0; 650 } 651 555 652 vfs_exchange_end(exch); 556 653 async_wait_for(req, &rc); 557 558 return rc; 559 } 560 654 655 if (rc != EOK) { 656 errno = rc; 657 return -1; 658 } 659 660 return 0; 661 } 662 663 /** Get file status. 664 * 665 * @param path Path to file 666 * @param stat Place to store file information 667 * 668 * @return 0 on success, -1 on error and sets errno. 669 */ 561 670 int stat(const char *path, struct stat *stat) 562 671 { 672 sysarg_t rc; 673 sysarg_t rc_orig; 674 aid_t req; 675 563 676 size_t pa_size; 564 char *pa = absolutize(path, &pa_size); 565 if (!pa) { 566 return ENOMEM; 567 } 568 569 int fd = _vfs_walk(-1, pa, 0); 570 if (fd < 0) { 571 return fd; 572 } 573 574 int rc = fstat(fd, stat); 575 close(fd); 576 return rc; 577 } 578 677 char *pa = vfs_absolutize(path, &pa_size); 678 if (pa == NULL) { 679 errno = ENOMEM; 680 return -1; 681 } 682 683 async_exch_t *exch = vfs_exchange_begin(); 684 685 req = async_send_0(exch, VFS_IN_STAT, NULL); 686 rc = async_data_write_start(exch, pa, pa_size); 687 if (rc != EOK) { 688 vfs_exchange_end(exch); 689 free(pa); 690 async_wait_for(req, &rc_orig); 691 if (rc_orig != EOK) 692 rc = rc_orig; 693 if (rc != EOK) { 694 errno = rc; 695 return -1; 696 } 697 } 698 rc = async_data_read_start(exch, stat, sizeof(struct stat)); 699 if (rc != EOK) { 700 vfs_exchange_end(exch); 701 free(pa); 702 async_wait_for(req, &rc_orig); 703 if (rc_orig != EOK) 704 rc = rc_orig; 705 if (rc != EOK) { 706 errno = rc; 707 return -1; 708 } 709 } 710 vfs_exchange_end(exch); 711 free(pa); 712 async_wait_for(req, &rc); 713 if (rc != EOK) { 714 errno = rc; 715 return -1; 716 } 717 return 0; 718 } 719 720 /** Open directory. 721 * 722 * @param dirname Directory pathname 723 * 724 * @return Non-NULL pointer on success. On error returns @c NULL and sets errno. 725 */ 579 726 DIR *opendir(const char *dirname) 580 727 { 581 728 DIR *dirp = malloc(sizeof(DIR)); 582 if (!dirp) { 729 int fd = -1; 730 731 if (dirp == NULL) { 583 732 errno = ENOMEM; 584 733 return NULL; … … 586 735 587 736 size_t abs_size; 588 char *abs = absolutize(dirname, &abs_size);589 if ( !abs) {737 char *abs = vfs_absolutize(dirname, &abs_size); 738 if (abs == NULL) { 590 739 free(dirp); 591 740 errno = ENOMEM; … … 593 742 } 594 743 595 int r et = _vfs_walk(-1, abs, WALK_DIRECTORY);744 int rc = open_internal(abs, abs_size, L_DIRECTORY, 0, &fd); 596 745 free(abs); 597 746 598 if (r et < 0) {747 if (rc != EOK) { 599 748 free(dirp); 600 errno = r et;749 errno = rc; 601 750 return NULL; 602 751 } 603 752 604 int rc = _vfs_open(ret, MODE_READ); 605 if (rc < 0) { 606 free(dirp); 607 close(ret); 753 dirp->fd = fd; 754 return dirp; 755 } 756 757 /** Read directory entry. 758 * 759 * @param dirp Open directory 760 * @return Non-NULL pointer to directory entry on success. On error returns 761 * @c NULL and sets errno. 762 */ 763 struct dirent *readdir(DIR *dirp) 764 { 765 int rc; 766 ssize_t len; 767 768 rc = _read_short(dirp->fd, &dirp->res.d_name[0], NAME_MAX + 1, &len); 769 if (rc != EOK) { 608 770 errno = rc; 609 771 return NULL; 610 772 } 611 773 612 dirp->fd = ret; 613 return dirp; 614 } 615 616 struct dirent *readdir(DIR *dirp) 617 { 618 ssize_t len = read(dirp->fd, &dirp->res.d_name[0], NAME_MAX + 1); 619 if (len <= 0) 620 return NULL; 774 (void) len; 621 775 return &dirp->res; 622 776 } 623 777 778 /** Rewind directory position to the beginning. 779 * 780 * @param dirp Open directory 781 */ 624 782 void rewinddir(DIR *dirp) 625 783 { … … 627 785 } 628 786 787 /** Close directory. 788 * 789 * @param dirp Open directory 790 * @return 0 on success. On error returns -1 and sets errno. 791 */ 629 792 int closedir(DIR *dirp) 630 793 { 631 (void) close(dirp->fd); 794 int rc; 795 796 rc = close(dirp->fd); 632 797 free(dirp); 633 return 0; 634 } 635 798 799 /* On error errno was set by close() */ 800 return rc; 801 } 802 803 /** Create directory. 804 * 805 * @param path Path 806 * @param mode File mode 807 * @return 0 on success. On error returns -1 and sets errno. 808 */ 636 809 int mkdir(const char *path, mode_t mode) 637 {638 size_t pa_size;639 char *pa = absolutize(path, &pa_size);640 if (!pa) {641 return ENOMEM;642 }643 644 int ret = _vfs_walk(-1, pa, WALK_MUST_CREATE | WALK_DIRECTORY);645 if (ret < 0) {646 return ret;647 }648 649 close(ret);650 return EOK;651 }652 653 static int _vfs_unlink2(int parent, const char *path, int expect, int wflag)654 810 { 655 811 sysarg_t rc; 656 812 aid_t req; 657 813 658 async_exch_t *exch = vfs_exchange_begin();659 660 req = async_send_3(exch, VFS_IN_UNLINK2, parent, expect, wflag, NULL);661 rc = async_data_write_start(exch, path, str_size(path));662 663 vfs_exchange_end(exch);664 665 sysarg_t rc_orig;666 async_wait_for(req, &rc_orig);667 668 if (rc_orig != EOK) {669 return (int) rc_orig;670 }671 return rc;672 }673 674 int unlink(const char *path)675 {676 814 size_t pa_size; 677 char *pa = absolutize(path, &pa_size); 678 if (!pa) { 815 char *pa = vfs_absolutize(path, &pa_size); 816 if (pa == NULL) { 817 errno = ENOMEM; 818 return -1; 819 } 820 821 async_exch_t *exch = vfs_exchange_begin(); 822 823 req = async_send_1(exch, VFS_IN_MKDIR, mode, NULL); 824 rc = async_data_write_start(exch, pa, pa_size); 825 if (rc != EOK) { 826 vfs_exchange_end(exch); 827 free(pa); 828 829 sysarg_t rc_orig; 830 async_wait_for(req, &rc_orig); 831 832 if (rc_orig != EOK) 833 rc = rc_orig; 834 835 if (rc != EOK) { 836 errno = rc; 837 return -1; 838 } 839 840 return 0; 841 } 842 843 vfs_exchange_end(exch); 844 free(pa); 845 async_wait_for(req, &rc); 846 847 if (rc != EOK) { 848 errno = rc; 849 return -1; 850 } 851 852 return 0; 853 } 854 855 /** Unlink a file or directory. 856 * 857 * @param path Path to file or empty directory 858 * @param lflag L_xxx flag (L_NONE, L_FILE or L_DIRECTORY) 859 * @return EOK on success, non-zero error code on error 860 */ 861 static int _unlink(const char *path, int lflag) 862 { 863 sysarg_t rc; 864 aid_t req; 865 866 size_t pa_size; 867 char *pa = vfs_absolutize(path, &pa_size); 868 if (pa == NULL) 679 869 return ENOMEM; 680 } 681 682 return _vfs_unlink2(-1, pa, -1, 0); 683 } 684 685 int rmdir(const char *path) 686 { 687 size_t pa_size; 688 char *pa = absolutize(path, &pa_size); 689 if (!pa) { 690 return ENOMEM; 691 } 692 693 return _vfs_unlink2(-1, pa, -1, WALK_DIRECTORY); 694 } 695 696 int rename(const char *old, const char *new) 697 { 698 sysarg_t rc; 699 sysarg_t rc_orig; 700 aid_t req; 701 702 size_t olda_size; 703 char *olda = absolutize(old, &olda_size); 704 if (!olda) 705 return ENOMEM; 706 707 size_t newa_size; 708 char *newa = absolutize(new, &newa_size); 709 if (!newa) { 710 free(olda); 711 return ENOMEM; 712 } 713 714 async_exch_t *exch = vfs_exchange_begin(); 715 716 req = async_send_1(exch, VFS_IN_RENAME, -1, NULL); 717 rc = async_data_write_start(exch, olda, olda_size); 718 if (rc != EOK) { 719 vfs_exchange_end(exch); 720 free(olda); 721 free(newa); 722 async_wait_for(req, &rc_orig); 870 871 async_exch_t *exch = vfs_exchange_begin(); 872 873 req = async_send_1(exch, VFS_IN_UNLINK, lflag, NULL); 874 rc = async_data_write_start(exch, pa, pa_size); 875 if (rc != EOK) { 876 vfs_exchange_end(exch); 877 free(pa); 878 879 sysarg_t rc_orig; 880 async_wait_for(req, &rc_orig); 881 723 882 if (rc_orig == EOK) 724 883 return (int) rc; … … 726 885 return (int) rc_orig; 727 886 } 728 rc = async_data_write_start(exch, newa, newa_size); 887 vfs_exchange_end(exch); 888 free(pa); 889 async_wait_for(req, &rc); 890 return rc; 891 } 892 893 /** Unlink file or directory. 894 * 895 * @param path Path 896 * @return EOk on success, error code on error 897 */ 898 int unlink(const char *path) 899 { 900 int rc; 901 902 rc = _unlink(path, L_NONE); 903 if (rc != EOK) { 904 errno = rc; 905 return -1; 906 } 907 908 return 0; 909 } 910 911 /** Remove empty directory. 912 * 913 * @param path Path 914 * @return 0 on success. On error returns -1 and sets errno. 915 */ 916 int rmdir(const char *path) 917 { 918 int rc; 919 920 rc = _unlink(path, L_DIRECTORY); 921 if (rc != EOK) { 922 errno = rc; 923 return -1; 924 } 925 926 return 0; 927 } 928 929 /** Rename directory entry. 930 * 931 * @param old Old name 932 * @param new New name 933 * 934 * @return 0 on success. On error returns -1 and sets errno. 935 */ 936 int rename(const char *old, const char *new) 937 { 938 sysarg_t rc; 939 sysarg_t rc_orig; 940 aid_t req; 941 942 size_t olda_size; 943 char *olda = vfs_absolutize(old, &olda_size); 944 if (olda == NULL) { 945 errno = ENOMEM; 946 return -1; 947 } 948 949 size_t newa_size; 950 char *newa = vfs_absolutize(new, &newa_size); 951 if (newa == NULL) { 952 free(olda); 953 errno = ENOMEM; 954 return -1; 955 } 956 957 async_exch_t *exch = vfs_exchange_begin(); 958 959 req = async_send_0(exch, VFS_IN_RENAME, NULL); 960 rc = async_data_write_start(exch, olda, olda_size); 729 961 if (rc != EOK) { 730 962 vfs_exchange_end(exch); … … 732 964 free(newa); 733 965 async_wait_for(req, &rc_orig); 734 if (rc_orig == EOK) 735 return (int) rc; 736 else 737 return (int) rc_orig; 966 if (rc_orig != EOK) 967 rc = rc_orig; 968 if (rc != EOK) { 969 errno = rc; 970 return -1; 971 } 972 return 0; 973 } 974 rc = async_data_write_start(exch, newa, newa_size); 975 if (rc != EOK) { 976 vfs_exchange_end(exch); 977 free(olda); 978 free(newa); 979 async_wait_for(req, &rc_orig); 980 if (rc_orig != EOK) 981 rc = rc_orig; 982 if (rc != EOK) { 983 errno = rc; 984 return -1; 985 } 986 return 0; 738 987 } 739 988 vfs_exchange_end(exch); … … 741 990 free(newa); 742 991 async_wait_for(req, &rc); 743 return rc; 744 } 745 992 993 if (rc != EOK) { 994 errno = rc; 995 return -1; 996 } 997 998 return 0; 999 } 1000 1001 /** Remove directory entry. 1002 * 1003 * @param path Path 1004 * @return 0 on success. On error returns -1 and sets errno. 1005 */ 1006 int remove(const char *path) 1007 { 1008 return unlink(path); 1009 } 1010 1011 /** Change working directory. 1012 * 1013 * @param path Path 1014 * @return 0 on success. On error returns -1 and sets errno. 1015 */ 746 1016 int chdir(const char *path) 747 1017 { 748 1018 size_t abs_size; 749 char *abs = absolutize(path, &abs_size); 750 if (!abs) 751 return ENOMEM; 752 753 int fd = _vfs_walk(-1, abs, WALK_DIRECTORY); 754 if (fd < 0) { 1019 char *abs = vfs_absolutize(path, &abs_size); 1020 int fd = -1; 1021 1022 if (abs == NULL) { 1023 errno = ENOMEM; 1024 return -1; 1025 } 1026 1027 int rc = open_internal(abs, abs_size, L_DIRECTORY, O_DESC, &fd); 1028 1029 if (rc != EOK) { 755 1030 free(abs); 756 return ENOENT; 1031 errno = rc; 1032 return -1; 757 1033 } 758 1034 … … 761 1037 if (cwd_fd >= 0) 762 1038 close(cwd_fd); 763 764 1039 765 1040 if (cwd_path) … … 771 1046 772 1047 fibril_mutex_unlock(&cwd_mutex); 773 return EOK; 774 } 775 1048 return 0; 1049 } 1050 1051 /** Get current working directory path. 1052 * 1053 * @param buf Buffer 1054 * @param size Size of @a buf 1055 * @return On success returns @a buf. On failure returns @c NULL and sets errno. 1056 */ 776 1057 char *getcwd(char *buf, size_t size) 777 1058 { 778 if (size == 0) 1059 if (size == 0) { 1060 errno = EINVAL; 779 1061 return NULL; 1062 } 780 1063 781 1064 fibril_mutex_lock(&cwd_mutex); … … 783 1066 if ((cwd_size == 0) || (size < cwd_size + 1)) { 784 1067 fibril_mutex_unlock(&cwd_mutex); 1068 errno = ERANGE; 785 1069 return NULL; 786 1070 } … … 792 1076 } 793 1077 794 async_sess_t *fd_session(exch_mgmt_t mgmt, int fildes) 1078 /** Open session to service represented by a special file. 1079 * 1080 * Given that the file referred to by @a fildes represents a service, 1081 * open a session to that service. 1082 * 1083 * @param fildes File descriptor 1084 * @param iface Interface to connect to (XXX Should be automatic) 1085 * @return On success returns session pointer. On error returns @c NULL. 1086 */ 1087 async_sess_t *vfs_fd_session(int fildes, iface_t iface) 795 1088 { 796 1089 struct stat stat; 797 1090 int rc = fstat(fildes, &stat); 798 if (rc != 0) { 799 errno = rc; 1091 if (rc != 0) 800 1092 return NULL; 801 } 802 803 if (!stat.service) { 804 errno = ENOENT; 1093 1094 if (stat.service == 0) 805 1095 return NULL; 806 } 807 808 return loc_service_connect(mgmt, stat.service, 0); 809 } 810 1096 1097 return loc_service_connect(stat.service, iface, 0); 1098 } 1099 1100 /** Duplicate open file. 1101 * 1102 * Duplicate open file under a new file descriptor. 1103 * 1104 * @param oldfd Old file descriptor 1105 * @param newfd New file descriptor 1106 * @return 0 on success. On error -1 is returned and errno is set 1107 */ 811 1108 int dup2(int oldfd, int newfd) 812 1109 { … … 819 1116 820 1117 if (rc == EOK) 821 return (int) ret; 822 823 return (int) rc; 824 } 825 826 int fd_wait(void) 1118 rc = ret; 1119 1120 if (rc != EOK) { 1121 errno = rc; 1122 return -1; 1123 } 1124 1125 return 0; 1126 } 1127 1128 int vfs_fd_wait(void) 827 1129 { 828 1130 async_exch_t *exch = vfs_exchange_begin(); … … 839 1141 } 840 1142 841 int get_mtab_list(list_t *mtab_list)1143 int vfs_get_mtab_list(list_t *mtab_list) 842 1144 { 843 1145 sysarg_t rc; … … 859 1161 860 1162 mtab_ent = malloc(sizeof(mtab_ent_t)); 861 if ( !mtab_ent) {1163 if (mtab_ent == NULL) { 862 1164 rc = ENOMEM; 863 1165 goto exit; … … 900 1202 } 901 1203 1204 /** Get filesystem statistics. 1205 * 1206 * @param path Mount point path 1207 * @param st Buffer for storing information 1208 * @return 0 on success. On error -1 is returned and errno is set. 1209 */ 1210 int statfs(const char *path, struct statfs *st) 1211 { 1212 sysarg_t rc, rc_orig; 1213 aid_t req; 1214 size_t pa_size; 1215 1216 char *pa = vfs_absolutize(path, &pa_size); 1217 if (pa == NULL) { 1218 errno = ENOMEM; 1219 return -1; 1220 } 1221 1222 async_exch_t *exch = vfs_exchange_begin(); 1223 1224 req = async_send_0(exch, VFS_IN_STATFS, NULL); 1225 rc = async_data_write_start(exch, pa, pa_size); 1226 if (rc != EOK) 1227 goto exit; 1228 1229 rc = async_data_read_start(exch, (void *) st, sizeof(*st)); 1230 1231 exit: 1232 vfs_exchange_end(exch); 1233 free(pa); 1234 async_wait_for(req, &rc_orig); 1235 rc = (rc_orig != EOK ? rc_orig : rc); 1236 1237 if (rc != EOK) { 1238 errno = rc; 1239 return -1; 1240 } 1241 1242 return 0; 1243 } 1244 902 1245 /** @} 903 1246 */
Note:
See TracChangeset
for help on using the changeset viewer.