Ignore:
File:
1 edited

Legend:

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

    r6afc9d7 r4636a60  
    4343#include <stdio.h>
    4444#include <sys/stat.h>
    45 #include <sys/statfs.h>
    4645#include <sys/types.h>
    4746#include <ipc/services.h>
     
    7574       
    7675        while (vfs_sess == NULL)
    77                 vfs_sess = service_connect_blocking(SERVICE_VFS, INTERFACE_VFS,
    78                     0);
     76                vfs_sess = service_connect_blocking(EXCHANGE_PARALLEL, SERVICE_VFS,
     77                    0, 0);
    7978       
    8079        fibril_mutex_unlock(&vfs_mutex);
     
    9392}
    9493
    95 char *vfs_absolutize(const char *path, size_t *retlen)
     94int _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
     117int _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
     126char *absolutize(const char *path, size_t *retlen)
    96127{
    97128        char *ncwd_path;
     
    101132        size_t size = str_size(path);
    102133        if (*path != '/') {
    103                 if (cwd_path == NULL) {
     134                if (!cwd_path) {
    104135                        fibril_mutex_unlock(&cwd_mutex);
    105136                        return NULL;
    106137                }
    107138                ncwd_path_nc = malloc(cwd_size + 1 + size + 1);
    108                 if (ncwd_path_nc == NULL) {
     139                if (!ncwd_path_nc) {
    109140                        fibril_mutex_unlock(&cwd_mutex);
    110141                        return NULL;
     
    115146        } else {
    116147                ncwd_path_nc = malloc(size + 1);
    117                 if (ncwd_path_nc == NULL) {
     148                if (!ncwd_path_nc) {
    118149                        fibril_mutex_unlock(&cwd_mutex);
    119150                        return NULL;
     
    123154        str_append(ncwd_path_nc, cwd_size + 1 + size + 1, path);
    124155        ncwd_path = canonify(ncwd_path_nc, retlen);
    125         if (ncwd_path == NULL) {
     156        if (!ncwd_path) {
    126157                fibril_mutex_unlock(&cwd_mutex);
    127158                free(ncwd_path_nc);
     
    135166        ncwd_path = str_dup(ncwd_path);
    136167        free(ncwd_path_nc);
    137         if (ncwd_path == NULL) {
     168        if (!ncwd_path) {
    138169                fibril_mutex_unlock(&cwd_mutex);
    139170                return NULL;
     
    143174}
    144175
    145 int vfs_mount(const char *fs_name, const char *mp, const char *fqsn,
     176int mount(const char *fs_name, const char *mp, const char *fqsn,
    146177    const char *opts, unsigned int flags, unsigned int instance)
    147178{
     
    171202       
    172203        size_t mpa_size;
    173         char *mpa = vfs_absolutize(mp, &mpa_size);
    174         if (mpa == NULL) {
     204        char *mpa = absolutize(mp, &mpa_size);
     205        if (!mpa) {
    175206                if (null_id != -1)
    176207                        loc_null_destroy(null_id);
     
    229260        }
    230261       
    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        
    247262        vfs_exchange_end(exch);
    248263        free(mpa);
     
    255270}
    256271
    257 int vfs_unmount(const char *mp)
     272int unmount(const char *mp)
    258273{
    259274        sysarg_t rc;
     
    263278        char *mpa;
    264279       
    265         mpa = vfs_absolutize(mp, &mpa_size);
    266         if (mpa == NULL)
     280        mpa = absolutize(mp, &mpa_size);
     281        if (!mpa)
    267282                return ENOMEM;
    268283       
     
    289304}
    290305
    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  */
     306static 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
    341319int open(const char *path, int oflag, ...)
    342320{
     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       
    343328        size_t abs_size;
    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  */
     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
    368363int close(int fildes)
    369364{
     
    374369        vfs_exchange_end(exch);
    375370       
    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)
     371        return (int) rc;
     372}
     373
     374// TODO: Versioning for read.
     375
     376ssize_t read(int fildes, void *buf, size_t nbyte)
    399377{
    400378        sysarg_t rc;
     
    402380        aid_t req;
    403381       
    404         if (nbyte > DATA_XFER_LIMIT)
    405                 nbyte = DATA_XFER_LIMIT;
    406        
    407382        async_exch_t *exch = vfs_exchange_begin();
    408383       
    409384        req = async_send_1(exch, VFS_IN_READ, fildes, &answer);
    410         rc = async_data_read_start(exch, (void *) buf, nbyte);
     385        rc = async_data_read_start(exch, (void *)buf, nbyte);
    411386        if (rc != EOK) {
    412387                vfs_exchange_end(exch);
    413                
     388
    414389                sysarg_t rc_orig;
    415390                async_wait_for(req, &rc_orig);
    416                
     391
    417392                if (rc_orig == EOK)
    418                         return rc;
     393                        return (ssize_t) rc;
    419394                else
    420                         return rc_orig;
    421         }
    422        
     395                        return (ssize_t) rc_orig;
     396        }
    423397        vfs_exchange_end(exch);
    424398        async_wait_for(req, &rc);
    425        
    426         if (rc != EOK)
     399        if (rc == EOK)
     400                return (ssize_t) IPC_GET_ARG1(answer);
     401        else
    427402                return rc;
    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)
     403}
     404
     405ssize_t write(int fildes, const void *buf, size_t nbyte)
    447406{
    448407        sysarg_t rc;
     
    450409        aid_t req;
    451410       
    452         if (nbyte > DATA_XFER_LIMIT)
    453                 nbyte = DATA_XFER_LIMIT;
    454        
    455411        async_exch_t *exch = vfs_exchange_begin();
    456412       
    457413        req = async_send_1(exch, VFS_IN_WRITE, fildes, &answer);
    458         rc = async_data_write_start(exch, (void *) buf, nbyte);
     414        rc = async_data_write_start(exch, (void *)buf, nbyte);
    459415        if (rc != EOK) {
    460416                vfs_exchange_end(exch);
    461                
     417
    462418                sysarg_t rc_orig;
    463419                async_wait_for(req, &rc_orig);
    464                
     420
    465421                if (rc_orig == EOK)
    466                         return rc;
     422                        return (ssize_t) rc;
    467423                else
    468                         return rc_orig;
    469         }
    470        
     424                        return (ssize_t) rc_orig;
     425        }
    471426        vfs_exchange_end(exch);
    472427        async_wait_for(req, &rc);
    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.
     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).
    485438 *
    486439 * @param fildes        File descriptor
     
    488441 * @param nbytes        Number of bytes to read
    489442 *
    490  * @return              On success, nonnegative number of bytes read.
    491  *                      On failure, -1 and sets errno.
     443 * @return              On success, positive number of bytes read.
     444 *                      On failure, negative error code from read().
    492445 */
    493 ssize_t read(int fildes, void *buf, size_t nbyte)
     446ssize_t read_all(int fildes, void *buf, size_t nbyte)
    494447{
    495448        ssize_t cnt = 0;
    496449        size_t nread = 0;
    497450        uint8_t *bp = (uint8_t *) buf;
    498         int rc;
    499        
     451
    500452        do {
    501453                bp += cnt;
    502454                nread += cnt;
    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        
     455                cnt = read(fildes, bp, nbyte - nread);
     456        } while (cnt > 0 && (nbyte - nread - cnt) > 0);
     457
     458        if (cnt < 0)
     459                return cnt;
     460
    511461        return nread + cnt;
    512462}
    513463
    514 /** Write data.
     464/** Write entire buffer.
    515465 *
    516466 * This function fails if it cannot write exactly @a len bytes to the file.
     
    520470 * @param nbytes        Number of bytes to write
    521471 *
    522  * @return              On success, nonnegative number of bytes written.
    523  *                      On failure, -1 and sets errno.
     472 * @return              EOK on error, return value from write() if writing
     473 *                      failed.
    524474 */
    525 ssize_t write(int fildes, const void *buf, size_t nbyte)
     475ssize_t write_all(int fildes, const void *buf, size_t nbyte)
    526476{
    527477        ssize_t cnt = 0;
    528478        ssize_t nwritten = 0;
    529479        const uint8_t *bp = (uint8_t *) buf;
    530         int rc;
    531480
    532481        do {
    533482                bp += cnt;
    534483                nwritten += cnt;
    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         }
     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;
    542492
    543493        return nbyte;
    544494}
    545495
    546 /** Synchronize file.
    547  *
    548  * @param fildes File descriptor
    549  * @return 0 on success. On error returns -1 and sets errno.
    550  */
    551496int fsync(int fildes)
    552497{
     
    555500        vfs_exchange_end(exch);
    556501       
    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  */
     502        return (int) rc;
     503}
     504
    574505off64_t lseek(int fildes, off64_t offset, int whence)
    575506{
     
    584515        vfs_exchange_end(exch);
    585516       
    586         if (rc != EOK) {
    587                 errno = rc;
     517        if (rc != EOK)
    588518                return (off64_t) -1;
    589         }
    590519       
    591520        return (off64_t) MERGE_LOUP32(newoff_lo, newoff_hi);
    592521}
    593522
    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  */
    603523int ftruncate(int fildes, aoff64_t length)
    604524{
     
    610530        vfs_exchange_end(exch);
    611531       
    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  */
     532        return (int) rc;
     533}
     534
    627535int fstat(int fildes, struct stat *stat)
    628536{
     
    636544        if (rc != EOK) {
    637545                vfs_exchange_end(exch);
    638                
     546
    639547                sysarg_t rc_orig;
    640548                async_wait_for(req, &rc_orig);
    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        
     549
     550                if (rc_orig == EOK)
     551                        return (ssize_t) rc;
     552                else
     553                        return (ssize_t) rc_orig;
     554        }
    652555        vfs_exchange_end(exch);
    653556        async_wait_for(req, &rc);
    654        
    655         if (rc != EOK) {
     557
     558        return rc;
     559}
     560
     561int stat(const char *path, struct stat *stat)
     562{
     563        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
     579DIR *opendir(const char *dirname)
     580{
     581        DIR *dirp = malloc(sizeof(DIR));
     582        if (!dirp) {
     583                errno = ENOMEM;
     584                return NULL;
     585        }
     586       
     587        size_t abs_size;
     588        char *abs = absolutize(dirname, &abs_size);
     589        if (!abs) {
     590                free(dirp);
     591                errno = ENOMEM;
     592                return NULL;
     593        }
     594       
     595        int ret = _vfs_walk(-1, abs, WALK_DIRECTORY);
     596        free(abs);
     597       
     598        if (ret < 0) {
     599                free(dirp);
     600                errno = ret;
     601                return NULL;
     602        }
     603       
     604        int rc = _vfs_open(ret, MODE_READ);
     605        if (rc < 0) {
     606                free(dirp);
     607                close(ret);
    656608                errno = rc;
    657                 return -1;
    658         }
    659        
     609                return NULL;
     610        }
     611       
     612        dirp->fd = ret;
     613        return dirp;
     614}
     615
     616struct 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;
     621        return &dirp->res;
     622}
     623
     624void rewinddir(DIR *dirp)
     625{
     626        (void) lseek(dirp->fd, 0, SEEK_SET);
     627}
     628
     629int closedir(DIR *dirp)
     630{
     631        (void) close(dirp->fd);
     632        free(dirp);
    660633        return 0;
    661634}
    662635
    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  */
    670 int stat(const char *path, struct stat *stat)
     636int 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
     653static int _vfs_unlink2(int parent, const char *path, int expect, int wflag)
     654{
     655        sysarg_t rc;
     656        aid_t req;
     657       
     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
     674int unlink(const char *path)
     675{
     676        size_t pa_size;
     677        char *pa = absolutize(path, &pa_size);
     678        if (!pa) {
     679                return ENOMEM;
     680        }
     681       
     682        return _vfs_unlink2(-1, pa, -1, 0);
     683}
     684
     685int 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
     696int rename(const char *old, const char *new)
    671697{
    672698        sysarg_t rc;
     
    674700        aid_t req;
    675701       
    676         size_t pa_size;
    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  */
    726 DIR *opendir(const char *dirname)
    727 {
    728         DIR *dirp = malloc(sizeof(DIR));
    729         int fd = -1;
    730        
    731         if (dirp == NULL) {
    732                 errno = ENOMEM;
    733                 return NULL;
    734         }
    735        
    736         size_t abs_size;
    737         char *abs = vfs_absolutize(dirname, &abs_size);
    738         if (abs == NULL) {
    739                 free(dirp);
    740                 errno = ENOMEM;
    741                 return NULL;
    742         }
    743        
    744         int rc = open_internal(abs, abs_size, L_DIRECTORY, 0, &fd);
    745         free(abs);
    746        
    747         if (rc != EOK) {
    748                 free(dirp);
    749                 errno = rc;
    750                 return NULL;
    751         }
    752        
    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) {
    770                 errno = rc;
    771                 return NULL;
    772         }
    773        
    774         (void) len;
    775         return &dirp->res;
    776 }
    777 
    778 /** Rewind directory position to the beginning.
    779  *
    780  * @param dirp Open directory
    781  */
    782 void rewinddir(DIR *dirp)
    783 {
    784         (void) lseek(dirp->fd, 0, SEEK_SET);
    785 }
    786 
    787 /** Close directory.
    788  *
    789  * @param dirp Open directory
    790  * @return 0 on success. On error returns -1 and sets errno.
    791  */
    792 int closedir(DIR *dirp)
    793 {
    794         int rc;
    795        
    796         rc = close(dirp->fd);
    797         free(dirp);
    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  */
    809 int mkdir(const char *path, mode_t mode)
    810 {
    811         sysarg_t rc;
    812         aid_t req;
    813        
    814         size_t pa_size;
    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)
     702        size_t olda_size;
     703        char *olda = absolutize(old, &olda_size);
     704        if (!olda)
    869705                return ENOMEM;
    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 
    882                 if (rc_orig == EOK)
    883                         return (int) rc;
    884                 else
    885                         return (int) rc_orig;
    886         }
    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         }
    948706
    949707        size_t newa_size;
    950         char *newa = vfs_absolutize(new, &newa_size);
    951         if (newa == NULL) {
     708        char *newa = absolutize(new, &newa_size);
     709        if (!newa) {
    952710                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);
     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);
    960717        rc = async_data_write_start(exch, olda, olda_size);
    961718        if (rc != EOK) {
     
    964721                free(newa);
    965722                async_wait_for(req, &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;
     723                if (rc_orig == EOK)
     724                        return (int) rc;
     725                else
     726                        return (int) rc_orig;
    973727        }
    974728        rc = async_data_write_start(exch, newa, newa_size);
     
    978732                free(newa);
    979733                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;
     734                if (rc_orig == EOK)
     735                        return (int) rc;
     736                else
     737                        return (int) rc_orig;
    987738        }
    988739        vfs_exchange_end(exch);
     
    990741        free(newa);
    991742        async_wait_for(req, &rc);
    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  */
     743        return rc;
     744}
     745
    1016746int chdir(const char *path)
    1017747{
    1018748        size_t abs_size;
    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) {
     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) {
    1030755                free(abs);
    1031                 errno = rc;
    1032                 return -1;
     756                return ENOENT;
    1033757        }
    1034758       
     
    1037761        if (cwd_fd >= 0)
    1038762                close(cwd_fd);
     763       
    1039764       
    1040765        if (cwd_path)
     
    1046771       
    1047772        fibril_mutex_unlock(&cwd_mutex);
    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  */
     773        return EOK;
     774}
     775
    1057776char *getcwd(char *buf, size_t size)
    1058777{
    1059         if (size == 0) {
    1060                 errno = EINVAL;
    1061                 return NULL;
    1062         }
     778        if (size == 0)
     779                return NULL;
    1063780       
    1064781        fibril_mutex_lock(&cwd_mutex);
     
    1066783        if ((cwd_size == 0) || (size < cwd_size + 1)) {
    1067784                fibril_mutex_unlock(&cwd_mutex);
    1068                 errno = ERANGE;
    1069785                return NULL;
    1070786        }
     
    1076792}
    1077793
    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)
     794async_sess_t *fd_session(exch_mgmt_t mgmt, int fildes)
    1088795{
    1089796        struct stat stat;
    1090797        int rc = fstat(fildes, &stat);
    1091         if (rc != 0)
    1092                 return NULL;
    1093        
    1094         if (stat.service == 0)
    1095                 return NULL;
    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  */
     798        if (rc != 0) {
     799                errno = rc;
     800                return NULL;
     801        }
     802       
     803        if (!stat.service) {
     804                errno = ENOENT;
     805                return NULL;
     806        }
     807       
     808        return loc_service_connect(mgmt, stat.service, 0);
     809}
     810
    1108811int dup2(int oldfd, int newfd)
    1109812{
     
    1116819       
    1117820        if (rc == EOK)
    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)
     821                return (int) ret;
     822       
     823        return (int) rc;
     824}
     825
     826int fd_wait(void)
    1129827{
    1130828        async_exch_t *exch = vfs_exchange_begin();
     
    1141839}
    1142840
    1143 int vfs_get_mtab_list(list_t *mtab_list)
     841int get_mtab_list(list_t *mtab_list)
    1144842{
    1145843        sysarg_t rc;
     
    1161859
    1162860                mtab_ent = malloc(sizeof(mtab_ent_t));
    1163                 if (mtab_ent == NULL) {
     861                if (!mtab_ent) {
    1164862                        rc = ENOMEM;
    1165863                        goto exit;
     
    1202900}
    1203901
    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 
    1245902/** @}
    1246903 */
Note: See TracChangeset for help on using the changeset viewer.