Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/vfs/vfs.c

    r4636a60 r6afc9d7  
    4343#include <stdio.h>
    4444#include <sys/stat.h>
     45#include <sys/statfs.h>
    4546#include <sys/types.h>
    4647#include <ipc/services.h>
     
    7475       
    7576        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);
    7879       
    7980        fibril_mutex_unlock(&vfs_mutex);
     
    9293}
    9394
    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)
     95char *vfs_absolutize(const char *path, size_t *retlen)
    12796{
    12897        char *ncwd_path;
     
    132101        size_t size = str_size(path);
    133102        if (*path != '/') {
    134                 if (!cwd_path) {
     103                if (cwd_path == NULL) {
    135104                        fibril_mutex_unlock(&cwd_mutex);
    136105                        return NULL;
    137106                }
    138107                ncwd_path_nc = malloc(cwd_size + 1 + size + 1);
    139                 if (!ncwd_path_nc) {
     108                if (ncwd_path_nc == NULL) {
    140109                        fibril_mutex_unlock(&cwd_mutex);
    141110                        return NULL;
     
    146115        } else {
    147116                ncwd_path_nc = malloc(size + 1);
    148                 if (!ncwd_path_nc) {
     117                if (ncwd_path_nc == NULL) {
    149118                        fibril_mutex_unlock(&cwd_mutex);
    150119                        return NULL;
     
    154123        str_append(ncwd_path_nc, cwd_size + 1 + size + 1, path);
    155124        ncwd_path = canonify(ncwd_path_nc, retlen);
    156         if (!ncwd_path) {
     125        if (ncwd_path == NULL) {
    157126                fibril_mutex_unlock(&cwd_mutex);
    158127                free(ncwd_path_nc);
     
    166135        ncwd_path = str_dup(ncwd_path);
    167136        free(ncwd_path_nc);
    168         if (!ncwd_path) {
     137        if (ncwd_path == NULL) {
    169138                fibril_mutex_unlock(&cwd_mutex);
    170139                return NULL;
     
    174143}
    175144
    176 int mount(const char *fs_name, const char *mp, const char *fqsn,
     145int vfs_mount(const char *fs_name, const char *mp, const char *fqsn,
    177146    const char *opts, unsigned int flags, unsigned int instance)
    178147{
     
    202171       
    203172        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) {
    206175                if (null_id != -1)
    207176                        loc_null_destroy(null_id);
     
    260229        }
    261230       
     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       
    262247        vfs_exchange_end(exch);
    263248        free(mpa);
     
    270255}
    271256
    272 int unmount(const char *mp)
     257int vfs_unmount(const char *mp)
    273258{
    274259        sysarg_t rc;
     
    278263        char *mpa;
    279264       
    280         mpa = absolutize(mp, &mpa_size);
    281         if (!mpa)
     265        mpa = vfs_absolutize(mp, &mpa_size);
     266        if (mpa == NULL)
    282267                return ENOMEM;
    283268       
     
    304289}
    305290
    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 */
     301static 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 */
    319341int open(const char *path, int oflag, ...)
    320342{
    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        
    328343        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 */
    363368int close(int fildes)
    364369{
     
    369374        vfs_exchange_end(exch);
    370375       
    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 */
     398static int _read_short(int fildes, void *buf, size_t nbyte, ssize_t *nread)
    377399{
    378400        sysarg_t rc;
     
    380402        aid_t req;
    381403       
     404        if (nbyte > DATA_XFER_LIMIT)
     405                nbyte = DATA_XFER_LIMIT;
     406       
    382407        async_exch_t *exch = vfs_exchange_begin();
    383408       
    384409        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               
    389414                sysarg_t rc_orig;
    390415                async_wait_for(req, &rc_orig);
    391 
     416               
    392417                if (rc_orig == EOK)
    393                         return (ssize_t) rc;
     418                        return rc;
    394419                else
    395                         return (ssize_t) rc_orig;
    396         }
     420                        return rc_orig;
     421        }
     422       
    397423        vfs_exchange_end(exch);
    398424        async_wait_for(req, &rc);
    399         if (rc == EOK)
    400                 return (ssize_t) IPC_GET_ARG1(answer);
    401         else
     425       
     426        if (rc != EOK)
    402427                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 */
     445static int _write_short(int fildes, const void *buf, size_t nbyte,
     446    ssize_t *nwritten)
    406447{
    407448        sysarg_t rc;
     
    409450        aid_t req;
    410451       
     452        if (nbyte > DATA_XFER_LIMIT)
     453                nbyte = DATA_XFER_LIMIT;
     454       
    411455        async_exch_t *exch = vfs_exchange_begin();
    412456       
    413457        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               
    418462                sysarg_t rc_orig;
    419463                async_wait_for(req, &rc_orig);
    420 
     464               
    421465                if (rc_orig == EOK)
    422                         return (ssize_t) rc;
     466                        return rc;
    423467                else
    424                         return (ssize_t) rc_orig;
    425         }
     468                        return rc_orig;
     469        }
     470       
    426471        vfs_exchange_end(exch);
    427472        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.
    438485 *
    439486 * @param fildes        File descriptor
     
    441488 * @param nbytes        Number of bytes to read
    442489 *
    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 */
     493ssize_t read(int fildes, void *buf, size_t nbyte)
    447494{
    448495        ssize_t cnt = 0;
    449496        size_t nread = 0;
    450497        uint8_t *bp = (uint8_t *) buf;
    451 
     498        int rc;
     499       
    452500        do {
    453501                bp += cnt;
    454502                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       
    461511        return nread + cnt;
    462512}
    463513
    464 /** Write entire buffer.
     514/** Write data.
    465515 *
    466516 * This function fails if it cannot write exactly @a len bytes to the file.
     
    470520 * @param nbytes        Number of bytes to write
    471521 *
    472  * @return              EOK on error, return value from write() if writing
    473  *                      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 */
     525ssize_t write(int fildes, const void *buf, size_t nbyte)
    476526{
    477527        ssize_t cnt = 0;
    478528        ssize_t nwritten = 0;
    479529        const uint8_t *bp = (uint8_t *) buf;
     530        int rc;
    480531
    481532        do {
    482533                bp += cnt;
    483534                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        }
    492542
    493543        return nbyte;
    494544}
    495545
     546/** Synchronize file.
     547 *
     548 * @param fildes File descriptor
     549 * @return 0 on success. On error returns -1 and sets errno.
     550 */
    496551int fsync(int fildes)
    497552{
     
    500555        vfs_exchange_end(exch);
    501556       
    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 */
    505574off64_t lseek(int fildes, off64_t offset, int whence)
    506575{
     
    515584        vfs_exchange_end(exch);
    516585       
    517         if (rc != EOK)
     586        if (rc != EOK) {
     587                errno = rc;
    518588                return (off64_t) -1;
     589        }
    519590       
    520591        return (off64_t) MERGE_LOUP32(newoff_lo, newoff_hi);
    521592}
    522593
     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 */
    523603int ftruncate(int fildes, aoff64_t length)
    524604{
     
    530610        vfs_exchange_end(exch);
    531611       
    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 */
    535627int fstat(int fildes, struct stat *stat)
    536628{
     
    544636        if (rc != EOK) {
    545637                vfs_exchange_end(exch);
    546 
     638               
    547639                sysarg_t rc_orig;
    548640                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       
    555652        vfs_exchange_end(exch);
    556653        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 */
    561670int stat(const char *path, struct stat *stat)
    562671{
     672        sysarg_t rc;
     673        sysarg_t rc_orig;
     674        aid_t req;
     675       
    563676        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 */
    579726DIR *opendir(const char *dirname)
    580727{
    581728        DIR *dirp = malloc(sizeof(DIR));
    582         if (!dirp) {
     729        int fd = -1;
     730       
     731        if (dirp == NULL) {
    583732                errno = ENOMEM;
    584733                return NULL;
     
    586735       
    587736        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) {
    590739                free(dirp);
    591740                errno = ENOMEM;
     
    593742        }
    594743       
    595         int ret = _vfs_walk(-1, abs, WALK_DIRECTORY);
     744        int rc = open_internal(abs, abs_size, L_DIRECTORY, 0, &fd);
    596745        free(abs);
    597746       
    598         if (ret < 0) {
     747        if (rc != EOK) {
    599748                free(dirp);
    600                 errno = ret;
     749                errno = rc;
    601750                return NULL;
    602751        }
    603752       
    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 */
     763struct 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) {
    608770                errno = rc;
    609771                return NULL;
    610772        }
    611773       
    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;
    621775        return &dirp->res;
    622776}
    623777
     778/** Rewind directory position to the beginning.
     779 *
     780 * @param dirp Open directory
     781 */
    624782void rewinddir(DIR *dirp)
    625783{
     
    627785}
    628786
     787/** Close directory.
     788 *
     789 * @param dirp Open directory
     790 * @return 0 on success. On error returns -1 and sets errno.
     791 */
    629792int closedir(DIR *dirp)
    630793{
    631         (void) close(dirp->fd);
     794        int rc;
     795       
     796        rc = close(dirp->fd);
    632797        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 */
    636809int 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)
    654810{
    655811        sysarg_t rc;
    656812        aid_t req;
    657813       
    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 {
    676814        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 */
     861static 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)
    679869                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
    723882                if (rc_orig == EOK)
    724883                        return (int) rc;
     
    726885                        return (int) rc_orig;
    727886        }
    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 */
     898int 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 */
     916int 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 */
     936int 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);
    729961        if (rc != EOK) {
    730962                vfs_exchange_end(exch);
     
    732964                free(newa);
    733965                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;
    738987        }
    739988        vfs_exchange_end(exch);
     
    741990        free(newa);
    742991        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 */
     1006int 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 */
    7461016int chdir(const char *path)
    7471017{
    7481018        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) {
    7551030                free(abs);
    756                 return ENOENT;
     1031                errno = rc;
     1032                return -1;
    7571033        }
    7581034       
     
    7611037        if (cwd_fd >= 0)
    7621038                close(cwd_fd);
    763        
    7641039       
    7651040        if (cwd_path)
     
    7711046       
    7721047        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 */
    7761057char *getcwd(char *buf, size_t size)
    7771058{
    778         if (size == 0)
     1059        if (size == 0) {
     1060                errno = EINVAL;
    7791061                return NULL;
     1062        }
    7801063       
    7811064        fibril_mutex_lock(&cwd_mutex);
     
    7831066        if ((cwd_size == 0) || (size < cwd_size + 1)) {
    7841067                fibril_mutex_unlock(&cwd_mutex);
     1068                errno = ERANGE;
    7851069                return NULL;
    7861070        }
     
    7921076}
    7931077
    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 */
     1087async_sess_t *vfs_fd_session(int fildes, iface_t iface)
    7951088{
    7961089        struct stat stat;
    7971090        int rc = fstat(fildes, &stat);
    798         if (rc != 0) {
    799                 errno = rc;
     1091        if (rc != 0)
    8001092                return NULL;
    801         }
    802        
    803         if (!stat.service) {
    804                 errno = ENOENT;
     1093       
     1094        if (stat.service == 0)
    8051095                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 */
    8111108int dup2(int oldfd, int newfd)
    8121109{
     
    8191116       
    8201117        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
     1128int vfs_fd_wait(void)
    8271129{
    8281130        async_exch_t *exch = vfs_exchange_begin();
     
    8391141}
    8401142
    841 int get_mtab_list(list_t *mtab_list)
     1143int vfs_get_mtab_list(list_t *mtab_list)
    8421144{
    8431145        sysarg_t rc;
     
    8591161
    8601162                mtab_ent = malloc(sizeof(mtab_ent_t));
    861                 if (!mtab_ent) {
     1163                if (mtab_ent == NULL) {
    8621164                        rc = ENOMEM;
    8631165                        goto exit;
     
    9001202}
    9011203
     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 */
     1210int 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
     1231exit:
     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
    9021245/** @}
    9031246 */
Note: See TracChangeset for help on using the changeset viewer.