Changeset 368ee04 in mainline for uspace/lib/c/generic


Ignore:
Timestamp:
2017-04-05T18:10:39Z (9 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
93ad8166
Parents:
39f892a9 (diff), 2166728 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge from lp:~jakub/helenos/vfs-2.5-cherrypick

This merge cherry-picks some of the changesets from Jiri Zarevucky's:

lp:~zarevucky-jiri/helenos/vfs-2.5

and then continues independently, yet sometime in a similar vein.

Roughly speaking, Jiri's branch is merged entirely up to its revision
1926 and then cherry-picked on and off until its revision 1965. Among
these changes are:

  • relativization of the API,
  • client-side roots,
  • server-side mounts,
  • inbox for passing arbitrary files from parent to child,
  • some streamlining and cleanup.

Additional changes include:

  • addressing issues introduced by the above changes,
  • client-side I/O cursors (file positions),
  • all HelenOS file system APIs begin with the vfs_ prefix and can be used after including vfs/vfs.h,
  • removal of some POSIX-ish headers and definitions,
  • additional cleanup.
Location:
uspace/lib/c/generic
Files:
2 added
11 edited
1 moved

Legend:

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

    r39f892a9 r368ee04  
    3333 */
    3434
    35 #ifndef LIBC_SYS_STAT_H_
    36 #define LIBC_SYS_STAT_H_
     35#include <vfs/vfs.h>
     36#include <stdlib.h>
     37#include <dirent.h>
     38#include <sys/types.h>
     39#include <errno.h>
     40#include <assert.h>
    3741
    38 #include <sys/types.h>
    39 #include <stdbool.h>
    40 #include <ipc/vfs.h>
    41 #include <ipc/loc.h>
     42/** Open directory.
     43 *
     44 * @param dirname Directory pathname
     45 *
     46 * @return Non-NULL pointer on success. On error returns @c NULL and sets errno.
     47 */
     48DIR *opendir(const char *dirname)
     49{
     50        DIR *dirp = malloc(sizeof(DIR));
     51        if (!dirp) {
     52                errno = ENOMEM;
     53                return NULL;
     54        }
     55       
     56        int fd = vfs_lookup(dirname, WALK_DIRECTORY);
     57        if (fd < 0) {
     58                free(dirp);
     59                errno = fd;
     60                return NULL;
     61        }
     62       
     63        int rc = vfs_open(fd, MODE_READ);
     64        if (rc < 0) {
     65                free(dirp);
     66                vfs_put(fd);
     67                errno = rc;
     68                return NULL;
     69        }
     70       
     71        dirp->fd = fd;
     72        dirp->pos = 0;
     73        return dirp;
     74}
    4275
    43 struct stat {
    44         fs_handle_t fs_handle;
    45         service_id_t service_id;
    46         fs_index_t index;
    47         unsigned int lnkcnt;
    48         bool is_file;
    49         bool is_directory;
    50         aoff64_t size;
    51         service_id_t service;
    52 };
     76/** Read directory entry.
     77 *
     78 * @param dirp Open directory
     79 * @return Non-NULL pointer to directory entry on success. On error returns
     80 *         @c NULL and sets errno.
     81 */
     82struct dirent *readdir(DIR *dirp)
     83{
     84        int rc;
     85        ssize_t len = 0;
     86       
     87        rc = vfs_read_short(dirp->fd, dirp->pos, &dirp->res.d_name[0],
     88            NAME_MAX + 1, &len);
     89        if (rc != EOK) {
     90                errno = rc;
     91                return NULL;
     92        }
     93       
     94        dirp->pos += len;
     95       
     96        return &dirp->res;
     97}
    5398
    54 extern int fstat(int, struct stat *);
    55 extern int stat(const char *, struct stat *);
    56 extern int mkdir(const char *, mode_t);
     99/** Rewind directory position to the beginning.
     100 *
     101 * @param dirp Open directory
     102 */
     103void rewinddir(DIR *dirp)
     104{
     105        dirp->pos = 0;
     106}
    57107
    58 #endif
     108/** Close directory.
     109 *
     110 * @param dirp Open directory
     111 * @return 0 on success. On error returns -1 and sets errno.
     112 */
     113int closedir(DIR *dirp)
     114{
     115        int rc;
     116       
     117        rc = vfs_put(dirp->fd);
     118        free(dirp);
     119
     120        /* On error errno was set by close() */
     121        return rc;
     122}
    59123
    60124/** @}
  • uspace/lib/c/generic/elf/elf_load.c

    r39f892a9 r368ee04  
    4141#include <stdio.h>
    4242#include <stdlib.h>
     43#include <vfs/vfs.h>
    4344
    4445#ifdef CONFIG_RTLD
     
    5051/** Load ELF program.
    5152 *
    52  * @param file_name File name
     53 * @param file File handle
    5354 * @param info Place to store ELF program information
    5455 * @return EOK on success or non-zero error code
    5556 */
    56 int elf_load(const char *file_name, elf_info_t *info)
     57int elf_load(int file, elf_info_t *info)
    5758{
    5859#ifdef CONFIG_RTLD
     
    6162        int rc;
    6263
    63         rc = elf_load_file(file_name, 0, 0, &info->finfo);
     64        rc = elf_load_file(file, 0, 0, &info->finfo);
    6465        if (rc != EE_OK) {
    6566                DPRINTF("Failed to load executable '%s'.\n", file_name);
  • uspace/lib/c/generic/elf/elf_mod.c

    r39f892a9 r368ee04  
    4444 */
    4545
     46#include <errno.h>
    4647#include <stdio.h>
     48#include <vfs/vfs.h>
    4749#include <sys/types.h>
    4850#include <align.h>
     
    5052#include <as.h>
    5153#include <elf/elf.h>
    52 #include <unistd.h>
    53 #include <fcntl.h>
    5454#include <smc.h>
    5555#include <loader/pcb.h>
    5656#include <entry_point.h>
     57#include <str_error.h>
     58#include <stdlib.h>
    5759
    5860#include <elf/elf_load.h>
     
    8284 * pointed to by @a info.
    8385 *
    84  * @param file_name Path to the ELF file.
     86 * @param file      ELF file.
    8587 * @param so_bias   Bias to use if the file is a shared object.
    8688 * @param info      Pointer to a structure for storing information
     
    9092 *
    9193 */
    92 int elf_load_file(const char *file_name, size_t so_bias, eld_flags_t flags,
    93     elf_finfo_t *info)
     94int elf_load_file(int file, size_t so_bias, eld_flags_t flags, elf_finfo_t *info)
    9495{
    9596        elf_ld_t elf;
    9697
    97         int fd;
    98         int rc;
    99 
    100         fd = open(file_name, O_RDONLY);
    101         if (fd < 0) {
    102                 DPRINTF("failed opening file\n");
    103                 return -1;
    104         }
    105 
    106         elf.fd = fd;
     98        int ofile = vfs_clone(file, -1, true);
     99        int rc = vfs_open(ofile, MODE_READ);
     100        if (rc != EOK) {
     101                return rc;
     102        }
     103
     104        elf.fd = ofile;
    107105        elf.info = info;
    108106        elf.flags = flags;
     
    110108        rc = elf_load_module(&elf, so_bias);
    111109
    112         close(fd);
    113 
     110        vfs_put(ofile);
     111        return rc;
     112}
     113
     114int elf_load_file_name(const char *path, size_t so_bias, eld_flags_t flags,
     115    elf_finfo_t *info)
     116{
     117        int file = vfs_lookup(path, 0);
     118        int rc = elf_load_file(file, so_bias, flags, info);
     119        vfs_put(file);
    114120        return rc;
    115121}
     
    129135        elf_header_t header_buf;
    130136        elf_header_t *header = &header_buf;
     137        aoff64_t pos = 0;
    131138        int i, rc;
    132139
    133         rc = read(elf->fd, header, sizeof(elf_header_t));
     140        rc = vfs_read(elf->fd, &pos, header, sizeof(elf_header_t));
    134141        if (rc != sizeof(elf_header_t)) {
    135142                DPRINTF("Read error.\n");
     
    189196                elf_segment_header_t segment_hdr;
    190197
    191                 /* Seek to start of segment header */
    192                 lseek(elf->fd, header->e_phoff
    193                         + i * sizeof(elf_segment_header_t), SEEK_SET);
    194 
    195                 rc = read(elf->fd, &segment_hdr,
     198                pos = header->e_phoff + i * sizeof(elf_segment_header_t);
     199                rc = vfs_read(elf->fd, &pos, &segment_hdr,
    196200                    sizeof(elf_segment_header_t));
    197201                if (rc != sizeof(elf_segment_header_t)) {
     
    211215                elf_section_header_t section_hdr;
    212216
    213                 /* Seek to start of section header */
    214                 lseek(elf->fd, header->e_shoff
    215                     + i * sizeof(elf_section_header_t), SEEK_SET);
    216 
    217                 rc = read(elf->fd, &section_hdr,
     217                pos = header->e_shoff + i * sizeof(elf_section_header_t);
     218                rc = vfs_read(elf->fd, &pos, &section_hdr,
    218219                    sizeof(elf_section_header_t));
    219220                if (rc != sizeof(elf_section_header_t)) {
     
    327328        uintptr_t seg_addr;
    328329        size_t mem_sz;
     330        aoff64_t pos;
    329331        ssize_t rc;
    330332
     
    384386         * Load segment data
    385387         */
    386         rc = lseek(elf->fd, entry->p_offset, SEEK_SET);
     388        pos = entry->p_offset;
     389        rc = vfs_read(elf->fd, &pos, seg_ptr, entry->p_filesz);
    387390        if (rc < 0) {
    388                 printf("seek error\n");
     391                DPRINTF("read error\n");
    389392                return EE_INVALID;
    390         }
    391 
    392 /*      rc = read(fd, (void *)(entry->p_vaddr + bias), entry->p_filesz);
    393         if (rc < 0) { printf("read error\n"); return EE_INVALID; }*/
    394 
    395         /* Long reads are not possible yet. Load segment piecewise. */
    396 
    397         unsigned left, now;
    398         uint8_t *dp;
    399 
    400         left = entry->p_filesz;
    401         dp = seg_ptr;
    402 
    403         while (left > 0) {
    404                 now = 16384;
    405                 if (now > left) now = left;
    406 
    407                 rc = read(elf->fd, dp, now);
    408 
    409                 if (rc != (ssize_t) now) {
    410                         DPRINTF("Read error.\n");
    411                         return EE_INVALID;
    412                 }
    413 
    414                 left -= now;
    415                 dp += now;
    416393        }
    417394
  • uspace/lib/c/generic/io/io.c

    r39f892a9 r368ee04  
    3535#include <stdio.h>
    3636#include <unistd.h>
    37 #include <fcntl.h>
    3837#include <assert.h>
    3938#include <str.h>
     
    4544#include <vfs/vfs.h>
    4645#include <vfs/vfs_sess.h>
     46#include <vfs/inbox.h>
    4747#include <ipc/loc.h>
    4848#include <adt/list.h>
     
    5555static FILE stdin_null = {
    5656        .fd = -1,
     57        .pos = 0,
    5758        .error = true,
    5859        .eof = true,
     
    6970static FILE stdout_kio = {
    7071        .fd = -1,
     72        .pos = 0,
    7173        .error = false,
    7274        .eof = false,
     
    8385static FILE stderr_kio = {
    8486        .fd = -1,
     87        .pos = 0,
    8588        .error = false,
    8689        .eof = false,
     
    101104static LIST_INITIALIZE(files);
    102105
    103 void __stdio_init(int filc)
    104 {
    105         if (filc > 0) {
    106                 stdin = fdopen(0, "r");
     106void __stdio_init(void)
     107{
     108        /* The first three standard file descriptors are assigned for compatibility.
     109         * This will probably be removed later.
     110         */
     111         
     112        int infd = inbox_get("stdin");
     113        if (infd >= 0) {
     114                int stdinfd = vfs_clone(infd, -1, false);
     115                assert(stdinfd == 0);
     116                vfs_open(stdinfd, MODE_READ);
     117                stdin = fdopen(stdinfd, "r");
    107118        } else {
    108119                stdin = &stdin_null;
     
    110121        }
    111122       
    112         if (filc > 1) {
    113                 stdout = fdopen(1, "w");
     123        int outfd = inbox_get("stdout");
     124        if (outfd >= 0) {
     125                int stdoutfd = vfs_clone(outfd, -1, false);
     126                assert(stdoutfd <= 1);
     127                while (stdoutfd < 1)
     128                        stdoutfd = vfs_clone(outfd, -1, false);
     129                vfs_open(stdoutfd, MODE_APPEND);
     130                stdout = fdopen(stdoutfd, "a");
    114131        } else {
    115132                stdout = &stdout_kio;
     
    117134        }
    118135       
    119         if (filc > 2) {
    120                 stderr = fdopen(2, "w");
     136        int errfd = inbox_get("stderr");
     137        if (errfd >= 0) {
     138                int stderrfd = vfs_clone(errfd, -1, false);
     139                assert(stderrfd <= 2);
     140                while (stderrfd < 2)
     141                        stderrfd = vfs_clone(errfd, -1, false);
     142                vfs_open(stderrfd, MODE_APPEND);
     143                stderr = fdopen(stderrfd, "a");
    121144        } else {
    122145                stderr = &stderr_kio;
     
    133156}
    134157
    135 static bool parse_mode(const char *mode, int *flags)
     158static bool parse_mode(const char *fmode, int *mode, bool *create, bool *truncate)
    136159{
    137160        /* Parse mode except first character. */
    138         const char *mp = mode;
     161        const char *mp = fmode;
    139162        if (*mp++ == 0) {
    140163                errno = EINVAL;
     
    156179                return false;
    157180        }
    158        
    159         /* Parse first character of mode and determine flags for open(). */
    160         switch (mode[0]) {
     181
     182        *create = false;
     183        *truncate = false;
     184       
     185        /* Parse first character of fmode and determine mode for vfs_open(). */
     186        switch (fmode[0]) {
    161187        case 'r':
    162                 *flags = plus ? O_RDWR : O_RDONLY;
     188                *mode = plus ? MODE_READ | MODE_WRITE : MODE_READ;
    163189                break;
    164190        case 'w':
    165                 *flags = (O_TRUNC | O_CREAT) | (plus ? O_RDWR : O_WRONLY);
     191                *mode = plus ? MODE_READ | MODE_WRITE : MODE_WRITE;
     192                *create = true;
     193                if (!plus)
     194                        *truncate = true;
    166195                break;
    167196        case 'a':
     
    171200                        return false;
    172201                }
    173                 *flags = (O_APPEND | O_CREAT) | (plus ? O_RDWR : O_WRONLY);
     202
     203                *mode = MODE_APPEND | (plus ? MODE_READ | MODE_WRITE : MODE_WRITE);
     204                *create = true;
    174205                break;
    175206        default:
     
    245276 *
    246277 */
    247 FILE *fopen(const char *path, const char *mode)
    248 {
    249         int flags;
    250         if (!parse_mode(mode, &flags))
     278FILE *fopen(const char *path, const char *fmode)
     279{
     280        int mode;
     281        bool create;
     282        bool truncate;
     283
     284        if (!parse_mode(fmode, &mode, &create, &truncate))
    251285                return NULL;
    252286       
     
    257291                return NULL;
    258292        }
    259        
    260         stream->fd = open(path, flags, 0666);
    261         if (stream->fd < 0) {
    262                 /* errno was set by open() */
     293
     294        int flags = WALK_REGULAR;
     295        if (create)
     296                flags |= WALK_MAY_CREATE;
     297        int file = vfs_lookup(path, flags);
     298        if (file < 0) {
     299                errno = file;
    263300                free(stream);
    264301                return NULL;
    265302        }
    266        
     303
     304        int rc = vfs_open(file, mode);
     305        if (rc != EOK) {
     306                errno = rc;
     307                vfs_put(file);
     308                free(stream);
     309                return NULL;
     310        }
     311       
     312        if (truncate) {
     313                rc = vfs_resize(file, 0);
     314                if (rc != EOK) {
     315                        errno = rc;
     316                        vfs_put(file);
     317                        free(stream);
     318                        return NULL;
     319                }
     320        }
     321
     322        stream->fd = file;
     323        stream->pos = 0;
    267324        stream->error = false;
    268325        stream->eof = false;
     
    288345       
    289346        stream->fd = fd;
     347        stream->pos = 0;
    290348        stream->error = false;
    291349        stream->eof = false;
     
    312370       
    313371        if (stream->fd >= 0)
    314                 rc = close(stream->fd);
     372                rc = vfs_put(stream->fd);
    315373       
    316374        list_remove(&stream->link);
     
    373431static size_t _fread(void *buf, size_t size, size_t nmemb, FILE *stream)
    374432{
    375         size_t left, done;
    376 
    377433        if (size == 0 || nmemb == 0)
    378434                return 0;
    379435
    380         left = size * nmemb;
    381         done = 0;
    382        
    383         while ((left > 0) && (!stream->error) && (!stream->eof)) {
    384                 ssize_t rd = read(stream->fd, buf + done, left);
    385                
    386                 if (rd < 0) {
    387                         /* errno was set by read() */
    388                         stream->error = true;
    389                 } else if (rd == 0) {
    390                         stream->eof = true;
    391                 } else {
    392                         left -= rd;
    393                         done += rd;
    394                 }
    395         }
    396        
    397         return (done / size);
     436        ssize_t rd = vfs_read(stream->fd, &stream->pos, buf, size * nmemb);
     437        if (rd < 0) {
     438                errno = rd;
     439                stream->error = true;
     440                rd = 0;
     441        } else if (rd == 0) {
     442                stream->eof = true;
     443        }
     444       
     445        return (rd / size);
    398446}
    399447
     
    410458static size_t _fwrite(const void *buf, size_t size, size_t nmemb, FILE *stream)
    411459{
    412         size_t left;
    413         size_t done;
    414         int rc;
    415 
    416460        if (size == 0 || nmemb == 0)
    417461                return 0;
    418462
    419         left = size * nmemb;
    420         done = 0;
    421 
    422         while ((left > 0) && (!stream->error)) {
    423                 ssize_t wr;
    424                 size_t uwr;
    425                
    426                 if (stream->kio) {
    427                         uwr = 0;
    428                         rc = kio_write(buf + done, left, &uwr);
    429                         if (rc != EOK)
    430                                 errno = rc;
     463        ssize_t wr;
     464        if (stream->kio) {
     465                size_t nwritten;
     466                wr = kio_write(buf, size * nmemb, &nwritten);
     467                if (wr != EOK) {
     468                        stream->error = true;
     469                        wr = 0;
    431470                } else {
    432                         wr = write(stream->fd, buf + done, left);
    433                         if (wr >= 0) {
    434                                 uwr = (size_t)wr;
    435                                 rc = EOK;
    436                         } else {
    437                                 /* errno was set by write */
    438                                 uwr = 0;
    439                                 rc = errno;
    440                         }
     471                        wr = nwritten;
    441472                }
    442                
    443                 if (rc != EOK) {
    444                         /* errno was set above */
     473        } else {
     474                wr = vfs_write(stream->fd, &stream->pos, buf, size * nmemb);
     475                if (wr < 0) {
     476                        errno = wr;
    445477                        stream->error = true;
    446                 } else {
    447                         left -= uwr;
    448                         done += uwr;
     478                        wr = 0;
    449479                }
    450480        }
    451481
    452         if (done > 0)
     482        if (wr > 0)
    453483                stream->need_sync = true;
    454484       
    455         return (done / size);
     485        return (wr / size);
    456486}
    457487
     
    466496        stream->buf_head = stream->buf_tail = stream->buf;
    467497
    468         rc = read(stream->fd, stream->buf, stream->buf_size);
     498        rc = vfs_read(stream->fd, &stream->pos, stream->buf, stream->buf_size);
    469499        if (rc < 0) {
    470                 /* errno was set by read() */
     500                errno = rc;
    471501                stream->error = true;
    472502                return;
     
    493523
    494524        /* If buffer has prefetched read data, we need to seek back. */
    495         if (bytes_used > 0 && stream->buf_state == _bs_read) {
    496                 off64_t rc;
    497                 rc = lseek(stream->fd, - (ssize_t) bytes_used, SEEK_CUR);
    498                 if (rc == (off64_t)-1) {
    499                         /* errno was set by lseek */
    500                         stream->error = 1;
    501                         return;
    502                 }
    503         }
     525        if (bytes_used > 0 && stream->buf_state == _bs_read)
     526                stream->pos -= bytes_used;
    504527
    505528        /* If buffer has unwritten data, we need to write them out. */
     
    773796int fseek(FILE *stream, off64_t offset, int whence)
    774797{
    775         off64_t rc;
     798        int rc;
    776799
    777800        if (stream->error)
    778                 return EOF;
     801                return -1;
    779802
    780803        _fflushbuf(stream);
    781804        if (stream->error) {
    782805                /* errno was set by _fflushbuf() */
    783                 return EOF;
     806                return -1;
    784807        }
    785808
    786809        stream->ungetc_chars = 0;
    787810
    788         rc = lseek(stream->fd, offset, whence);
    789         if (rc == (off64_t) (-1)) {
    790                 /* errno has been set by lseek() */
    791                 return EOF;
     811        struct stat st;
     812        switch (whence) {
     813        case SEEK_SET:
     814                stream->pos = offset;
     815                break;
     816        case SEEK_CUR:
     817                stream->pos += offset;
     818                break;
     819        case SEEK_END:
     820                rc = vfs_stat(stream->fd, &st);
     821                if (rc != EOK) {
     822                        errno = rc;
     823                        stream->error = true;
     824                        return -1;     
     825                }
     826                stream->pos = st.size + offset;
     827                break;
    792828        }
    793829
     
    798834off64_t ftell(FILE *stream)
    799835{
    800         off64_t pos;
    801        
     836        /* The native position is too large for the C99-ish interface. */
     837        if (stream->pos - stream->ungetc_chars > INT64_MAX)
     838                return EOF;
     839
    802840        if (stream->error)
    803841                return EOF;
     
    809847        }
    810848
    811         pos = lseek(stream->fd, 0, SEEK_CUR);
    812         if (pos == (off64_t) -1) {
    813                 /* errno was set by lseek */
    814                 return (off64_t) -1;
    815         }
    816        
    817         return pos - stream->ungetc_chars;
     849        return stream->pos - stream->ungetc_chars;
    818850}
    819851
     
    840872       
    841873        if ((stream->fd >= 0) && (stream->need_sync)) {
     874                int rc;
     875
    842876                /**
    843877                 * Better than syncing always, but probably still not the
     
    845879                 */
    846880                stream->need_sync = false;
    847                 if (fsync(stream->fd) != 0) {
    848                         /* errno was set by fsync() */
     881                rc = vfs_sync(stream->fd);
     882                if (rc != EOK) {
     883                        errno = rc;
    849884                        return EOF;
    850885                }
  • uspace/lib/c/generic/io/logctl.c

    r39f892a9 r368ee04  
    3939#include <ns.h>
    4040#include <str.h>
     41#include <vfs/vfs.h>
    4142
    4243/** IPC session with the logger service. */
     
    122123}
    123124
     125/** Set logger's VFS root.
     126 *
     127 * @return Error code or EOK on success.
     128 */
     129int logctl_set_root(void)
     130{
     131        async_exch_t *exchange = NULL;
     132        int rc = start_logger_exchange(&exchange);
     133        if (rc != EOK)
     134                return rc;
     135
     136        aid_t reg_msg = async_send_0(exchange, LOGGER_CONTROL_SET_ROOT, NULL);
     137        async_exch_t *vfs_exch = vfs_exchange_begin();
     138        rc = vfs_pass_handle(vfs_exch, vfs_root(), exchange);
     139        vfs_exchange_end(vfs_exch);
     140        sysarg_t reg_msg_rc;
     141        async_wait_for(reg_msg, &reg_msg_rc);
     142
     143        async_exchange_end(exchange);
     144
     145        if (rc != EOK)
     146                return rc;
     147
     148        return (int) reg_msg_rc;
     149}
     150
    124151/** @}
    125152 */
  • uspace/lib/c/generic/libc.c

    r39f892a9 r368ee04  
    4848#include <task.h>
    4949#include <loader/pcb.h>
     50#include <vfs/vfs.h>
     51#include <vfs/inbox.h>
    5052#include "private/libc.h"
    5153#include "private/async.h"
     
    107109                argc = 0;
    108110                argv = NULL;
    109                 __stdio_init(0);
     111                __stdio_init();
    110112        } else {
    111113                argc = __pcb->argc;
    112114                argv = __pcb->argv;
    113                 __stdio_init(__pcb->filc);
    114                 (void) chdir(__pcb->cwd);
     115                __inbox_init(__pcb->inbox, __pcb->inbox_entries);
     116                __stdio_init();
     117                vfs_root_set(inbox_get("root"));
     118                (void) vfs_cwd_set(__pcb->cwd);
    115119        }
    116120       
  • uspace/lib/c/generic/loader.c

    r39f892a9 r368ee04  
    124124                return ENOMEM;
    125125       
    126         if (getcwd(cwd, MAX_PATH_LEN + 1) == NULL)
     126        if (vfs_cwd_get(cwd, MAX_PATH_LEN + 1) != EOK)
    127127                str_cpy(cwd, MAX_PATH_LEN + 1, "/");
    128128       
     
    147147}
    148148
    149 /** Set pathname of the program to load.
    150  *
    151  * Sets the name of the program file to load. The name can be relative
    152  * to the current working directory (it will be absolutized before
    153  * sending to the loader).
     149/** Set the program to load.
    154150 *
    155151 * @param ldr  Loader connection structure.
    156  * @param path Pathname of the program file.
    157  *
    158  * @return Zero on success or negative error code.
    159  *
    160  */
    161 int loader_set_pathname(loader_t *ldr, const char *path)
    162 {
    163         size_t pa_len;
    164         char *pa = vfs_absolutize(path, &pa_len);
    165         if (!pa)
    166                 return ENOMEM;
    167        
    168         /* Send program pathname */
    169         async_exch_t *exch = async_exchange_begin(ldr->sess);
    170        
     152 * @param name Name to set for the spawned program.
     153 * @param file Program file.
     154 *
     155 * @return Zero on success or negative error code.
     156 *
     157 */
     158int loader_set_program(loader_t *ldr, const char *name, int file)
     159{
     160        async_exch_t *exch = async_exchange_begin(ldr->sess);
     161
    171162        ipc_call_t answer;
    172         aid_t req = async_send_0(exch, LOADER_SET_PATHNAME, &answer);
    173         sysarg_t rc = async_data_write_start(exch, (void *) pa, pa_len);
    174        
    175         async_exchange_end(exch);
    176         free(pa);
    177        
     163        aid_t req = async_send_0(exch, LOADER_SET_PROGRAM, &answer);
     164
     165        sysarg_t rc = async_data_write_start(exch, name, str_size(name) + 1);
     166        if (rc == EOK) {
     167                async_exch_t *vfs_exch = vfs_exchange_begin();
     168                rc = vfs_pass_handle(vfs_exch, file, exch);
     169                vfs_exchange_end(vfs_exch);
     170        }
     171
     172        async_exchange_end(exch);
     173
    178174        if (rc != EOK) {
    179175                async_forget(req);
    180176                return (int) rc;
    181177        }
    182        
     178
    183179        async_wait_for(req, &rc);
    184180        return (int) rc;
    185181}
     182
     183/** Set the program to load by path.
     184 *
     185 * @param ldr  Loader connection structure.
     186 * @param path Program path.
     187 *
     188 * @return Zero on success or negative error code.
     189 *
     190 */
     191int loader_set_program_path(loader_t *ldr, const char *path)
     192{
     193        const char *name = str_rchr(path, '/');
     194        if (name == NULL) {
     195                name = path;
     196        } else {
     197                name++;
     198        }
     199       
     200        int fd = vfs_lookup(path, 0);
     201        if (fd < 0) {
     202                return fd;
     203        }
     204       
     205        int rc = loader_set_program(ldr, name, fd);
     206        vfs_put(fd);
     207        return rc;
     208}
     209
    186210
    187211/** Set command-line arguments for the program.
     
    244268}
    245269
    246 /** Set preset files for the program.
    247  *
    248  * Sets the vector of preset files to be passed to the loaded
    249  * program. By convention, the first three files represent stdin,
    250  * stdout and stderr respectively.
    251  *
    252  * @param ldr   Loader connection structure.
    253  * @param files NULL-terminated array of pointers to files.
    254  *
    255  * @return Zero on success or negative error code.
    256  *
    257  */
    258 int loader_set_files(loader_t *ldr, int * const files[])
    259 {
    260         /* Send serialized files to the loader */
     270/** Add a file to the task's inbox.
     271 *
     272 * @param ldr        Loader connection structure.
     273 * @param name       Identification of the file.
     274 * @param file       The file's descriptor.
     275 *
     276 * @return Zero on success or negative error code.
     277 *
     278 */
     279int loader_add_inbox(loader_t *ldr, const char *name, int file)
     280{
    261281        async_exch_t *exch = async_exchange_begin(ldr->sess);
    262282        async_exch_t *vfs_exch = vfs_exchange_begin();
    263283       
    264         int i;
    265         for (i = 0; files[i]; i++);
    266 
    267         ipc_call_t answer;
    268         aid_t req = async_send_1(exch, LOADER_SET_FILES, i, &answer);
    269 
    270         sysarg_t rc = EOK;
    271        
    272         for (i = 0; files[i]; i++) {
    273                 rc = async_state_change_start(exch, VFS_PASS_HANDLE, *files[i],
    274                     0, vfs_exch);
    275                 if (rc != EOK)
    276                         break;
    277         }
    278        
    279         vfs_exchange_end(vfs_exch);
    280         async_exchange_end(exch);
    281 
    282         if (rc != EOK) {
    283                 async_forget(req);
    284                 return (int) rc;
    285         }
    286        
    287         async_wait_for(req, &rc);
     284        aid_t req = async_send_0(exch, LOADER_ADD_INBOX, NULL);
     285       
     286        sysarg_t rc = async_data_write_start(exch, name, str_size(name) + 1);
     287        if (rc == EOK) {
     288                rc = vfs_pass_handle(vfs_exch, file, exch);
     289        }
     290       
     291        async_exchange_end(vfs_exch);
     292        async_exchange_end(exch);
     293       
     294        if (rc == EOK) {
     295                async_wait_for(req, &rc);
     296        } else {
     297                async_forget(req);
     298        }
     299       
    288300        return (int) rc;
    289301}
  • uspace/lib/c/generic/private/io.h

    r39f892a9 r368ee04  
    3636#define LIBC_PRIVATE_IO_H_
    3737
    38 extern void __stdio_init(int);
     38#include <loader/pcb.h>
     39
     40extern void __stdio_init(void);
    3941extern void __stdio_done(void);
     42
     43extern void __inbox_init(struct pcb_inbox_entry *entries, int count);
    4044
    4145#endif
  • uspace/lib/c/generic/private/stdio.h

    r39f892a9 r368ee04  
    4949        /** Underlying file descriptor. */
    5050        int fd;
     51
     52        /** File position. */
     53        aoff64_t pos;
    5154       
    5255        /** Error indicator. */
  • uspace/lib/c/generic/rtld/module.c

    r39f892a9 r368ee04  
    3838#include <elf/elf_load.h>
    3939#include <errno.h>
    40 #include <fcntl.h>
    4140#include <loader/pcb.h>
    4241#include <stdio.h>
     
    196195        DPRINTF("load '%s' at 0x%x\n", name_buf, m->bias);
    197196
    198         rc = elf_load_file(name_buf, m->bias, ELDF_RW, &info);
     197        rc = elf_load_file_name(name_buf, m->bias, ELDF_RW, &info);
    199198        if (rc != EE_OK) {
    200199                printf("Failed to load '%s'\n", name_buf);
  • uspace/lib/c/generic/task.c

    r39f892a9 r368ee04  
    4848#include "private/ns.h"
    4949#include <vfs/vfs.h>
     50#include <unistd.h>
    5051
    5152task_id_t task_get_id(void)
     
    107108{
    108109        /* Send default files */
    109         int *files[4];
    110         int fd_stdin;
    111         int fd_stdout;
    112         int fd_stderr;
    113        
    114         if ((stdin != NULL) && (vfs_fhandle(stdin, &fd_stdin) == EOK))
    115                 files[0] = &fd_stdin;
    116         else
    117                 files[0] = NULL;
    118        
    119         if ((stdout != NULL) && (vfs_fhandle(stdout, &fd_stdout) == EOK))
    120                 files[1] = &fd_stdout;
    121         else
    122                 files[1] = NULL;
    123        
    124         if ((stderr != NULL) && (vfs_fhandle(stderr, &fd_stderr) == EOK))
    125                 files[2] = &fd_stderr;
    126         else
    127                 files[2] = NULL;
    128        
    129         files[3] = NULL;
    130        
    131         return task_spawnvf(id, wait, path, args, files);
     110       
     111        int fd_stdin = -1;
     112        int fd_stdout = -1;
     113        int fd_stderr = -1;
     114       
     115        if (stdin != NULL) {
     116                (void) vfs_fhandle(stdin, &fd_stdin);
     117        }
     118       
     119        if (stdout != NULL) {
     120                (void) vfs_fhandle(stdout, &fd_stdout);
     121        }
     122
     123        if (stderr != NULL) {
     124                (void) vfs_fhandle(stderr, &fd_stderr);
     125        }
     126       
     127        return task_spawnvf(id, wait, path, args, fd_stdin, fd_stdout,
     128            fd_stderr);
    132129}
    133130
     
    138135 * Files are passed as null-terminated array of pointers to fdi_node_t.
    139136 *
    140  * @param id    If not NULL, the ID of the task is stored here on success.
    141  * @param wait  If not NULL, setup waiting for task's return value and store
    142  *              the information necessary for waiting here on success.
    143  * @param path  Pathname of the binary to execute.
    144  * @param argv  Command-line arguments.
    145  * @param files Standard files to use.
     137 * @param id      If not NULL, the ID of the task is stored here on success.
     138 * @param wait    If not NULL, setup waiting for task's return value and store
     139 * @param path    Pathname of the binary to execute.
     140 * @param argv    Command-line arguments.
     141 * @param std_in  File to use as stdin.
     142 * @param std_out File to use as stdout.
     143 * @param std_err File to use as stderr.
    146144 *
    147145 * @return Zero on success or negative error code.
     
    149147 */
    150148int task_spawnvf(task_id_t *id, task_wait_t *wait, const char *path,
    151     const char *const args[], int *const files[])
     149    const char *const args[], int fd_stdin, int fd_stdout, int fd_stderr)
    152150{
    153151        /* Connect to a program loader. */
     
    169167                goto error;
    170168       
    171         /* Send program pathname. */
    172         rc = loader_set_pathname(ldr, path);
     169        /* Send program binary. */
     170        rc = loader_set_program_path(ldr, path);
    173171        if (rc != EOK)
    174172                goto error;
     
    180178       
    181179        /* Send files */
    182         rc = loader_set_files(ldr, files);
    183         if (rc != EOK)
    184                 goto error;
     180        int root = vfs_root();
     181        if (root >= 0) {
     182                rc = loader_add_inbox(ldr, "root", root);
     183                vfs_put(root);
     184                if (rc != EOK)
     185                        goto error;
     186        }
     187       
     188        if (fd_stdin >= 0) {
     189                rc = loader_add_inbox(ldr, "stdin", fd_stdin);
     190                if (rc != EOK)
     191                        goto error;
     192        }
     193       
     194        if (fd_stdout >= 0) {
     195                rc = loader_add_inbox(ldr, "stdout", fd_stdout);
     196                if (rc != EOK)
     197                        goto error;
     198        }
     199       
     200        if (fd_stderr >= 0) {
     201                rc = loader_add_inbox(ldr, "stderr", fd_stderr);
     202                if (rc != EOK)
     203                        goto error;
     204        }               
    185205       
    186206        /* Load the program. */
  • uspace/lib/c/generic/vfs/vfs.c

    r39f892a9 r368ee04  
    3333 */
    3434
     35#include <vfs/vfs.h>
    3536#include <vfs/canonify.h>
    36 #include <vfs/vfs.h>
     37#include <vfs/vfs_mtab.h>
    3738#include <vfs/vfs_sess.h>
    3839#include <macros.h>
    3940#include <stdlib.h>
    40 #include <unistd.h>
    41 #include <dirent.h>
    42 #include <fcntl.h>
    43 #include <stdio.h>
    44 #include <sys/stat.h>
    45 #include <sys/statfs.h>
    4641#include <sys/types.h>
    4742#include <ipc/services.h>
     
    5651#include <ipc/loc.h>
    5752
     53/*
     54 * This file contains the implementation of the native HelenOS file system API.
     55 *
     56 * The API supports client-side file system roots, client-side IO cursors and
     57 * uses file handles as a primary means to refer to files. In order to call the
     58 * API functions, one just includes vfs/vfs.h.
     59 *
     60 * The API functions come in two main flavors:
     61 *
     62 * - functions that operate on integer file handles, such as:
     63 *   vfs_walk(), vfs_open(), vfs_read(), vfs_link(), ...
     64 * 
     65 * - functions that operate on paths, such as:
     66 *   vfs_lookup(), vfs_link_path(), vfs_unlink_path(), vfs_rename_path(), ...
     67 *
     68 * There is usually a corresponding path function for each file handle function
     69 * that exists mostly as a convenience wrapper, except for cases when only a
     70 * path version exists due to file system consistency considerations (see
     71 * vfs_rename_path()). Sometimes one of the versions does not make sense, in
     72 * which case it is also omitted.
     73 *
     74 * Besides of that, the API provides some convenience wrappers for frequently
     75 * performed pairs of operations, for example there is a combo API for
     76 * vfs_lookup() and vfs_open(): vfs_lookup_open().
     77 *
     78 * Some of the functions here return a file handle that can be passed to other
     79 * functions. Note that a file handle does not automatically represent a file
     80 * from which one can read or to which one can write. In order to do so, the
     81 * file handle must be opened first for reading/writing using vfs_open().
     82 *
     83 * All file handles, no matter whether opened or not, must be eventually
     84 * returned to the system using vfs_put(). Non-returned file handles are in use
     85 * and consume system resources.
     86 *
     87 * Functions that return int return a negative error code on error and do not
     88 * set errno. Depending on function, success is signalled by returning either
     89 * EOK or a non-negative file handle.
     90 *
     91 * An example life-cycle of a file handle is as follows:
     92 *
     93 *      #include <vfs/vfs.h>
     94 *
     95 *      int file = vfs_lookup("/foo/bar/foobar", WALK_REGULAR);
     96 *      if (file < 0)
     97 *              return file;
     98 *      int rc = vfs_open(file, MODE_READ);
     99 *      if (rc != EOK) {
     100 *              (void) vfs_put(file);
     101 *              return rc;
     102 *      }
     103 *      aoff64_t pos = 42;
     104 *      char buf[512];
     105 *      ssize_t size = vfs_read(file, &pos, buf, sizeof(buf));
     106 *      if (size < 0) {
     107 *              vfs_put(file);
     108 *              return size;
     109 *      }
     110 *
     111 *      // buf is now filled with data from file
     112 *
     113 *      vfs_put(file);
     114 */
     115
    58116static FIBRIL_MUTEX_INITIALIZE(vfs_mutex);
    59117static async_sess_t *vfs_sess = NULL;
     
    65123static size_t cwd_size = 0;
    66124
    67 /** Start an async exchange on the VFS session.
    68  *
    69  * @return New exchange.
    70  *
    71  */
    72 async_exch_t *vfs_exchange_begin(void)
    73 {
    74         fibril_mutex_lock(&vfs_mutex);
    75        
    76         while (vfs_sess == NULL)
    77                 vfs_sess = service_connect_blocking(SERVICE_VFS, INTERFACE_VFS,
    78                     0);
    79        
    80         fibril_mutex_unlock(&vfs_mutex);
    81        
    82         return async_exchange_begin(vfs_sess);
    83 }
    84 
    85 /** Finish an async exchange on the VFS session.
    86  *
    87  * @param exch Exchange to be finished.
    88  *
    89  */
    90 void vfs_exchange_end(async_exch_t *exch)
    91 {
    92         async_exchange_end(exch);
    93 }
    94 
     125static FIBRIL_MUTEX_INITIALIZE(root_mutex);
     126static int root_fd = -1;
     127
     128static int get_parent_and_child(const char *path, char **child)
     129{
     130        size_t size;
     131        char *apath = vfs_absolutize(path, &size);
     132        if (!apath)
     133                return ENOMEM;
     134
     135        char *slash = str_rchr(apath, L'/');
     136        int parent;
     137        if (slash == apath) {
     138                parent = vfs_root();
     139                *child = apath;
     140        } else {
     141                *slash = '\0';
     142                parent = vfs_lookup(apath, WALK_DIRECTORY);
     143                if (parent < 0) {
     144                        free(apath);
     145                        return parent;
     146                }
     147                *slash = '/';
     148                *child = str_dup(slash);
     149                free(apath);
     150                if (!*child) {
     151                        vfs_put(parent);
     152                        return ENOMEM;
     153                }
     154        }
     155
     156        return parent;
     157}
     158
     159/** Make a potentially relative path absolute
     160 *
     161 * This function coverts a current-working-directory-relative path into a
     162 * well-formed, absolute path. The caller is responsible for deallocating the
     163 * returned buffer.
     164 *
     165 * @param[in] path      Path to be absolutized
     166 * @param[out] retlen   Length of the absolutized path
     167 *
     168 * @return              New buffer holding the absolutized path or NULL
     169 */
    95170char *vfs_absolutize(const char *path, size_t *retlen)
    96171{
     
    143218}
    144219
    145 int vfs_mount(const char *fs_name, const char *mp, const char *fqsn,
     220/** Clone a file handle
     221 *
     222 * The caller can choose whether to clone an existing file handle into another
     223 * already existing file handle (in which case it is first closed) or to a new
     224 * file handle allocated either from low or high indices.
     225 *
     226 * @param file_from     Source file handle
     227 * @param file_to       Destination file handle or -1
     228 * @param high          If file_to is -1, high controls whether the new file
     229 *                      handle will be allocated from high indices
     230 *
     231 * @return              New file handle on success or a negative error code
     232 */
     233int vfs_clone(int file_from, int file_to, bool high)
     234{
     235        async_exch_t *vfs_exch = vfs_exchange_begin();
     236        int rc = async_req_3_0(vfs_exch, VFS_IN_CLONE, (sysarg_t) file_from,
     237            (sysarg_t) file_to, (sysarg_t) high);
     238        vfs_exchange_end(vfs_exch);
     239        return rc;
     240}
     241
     242/** Get current working directory path
     243 *
     244 * @param[out] buf      Buffer
     245 * @param size          Size of @a buf
     246 *
     247 * @return              EOK on success or a non-negative error code
     248 */
     249int vfs_cwd_get(char *buf, size_t size)
     250{
     251        fibril_mutex_lock(&cwd_mutex);
     252       
     253        if ((cwd_size == 0) || (size < cwd_size + 1)) {
     254                fibril_mutex_unlock(&cwd_mutex);
     255                return ERANGE;
     256        }
     257       
     258        str_cpy(buf, size, cwd_path);
     259        fibril_mutex_unlock(&cwd_mutex);
     260       
     261        return EOK;
     262}
     263
     264/** Change working directory
     265 *
     266 * @param path  Path of the new working directory
     267 *
     268 * @return      EOK on success or a negative error code
     269 */
     270int vfs_cwd_set(const char *path)
     271{
     272        size_t abs_size;
     273        char *abs = vfs_absolutize(path, &abs_size);
     274        if (!abs)
     275                return ENOMEM;
     276       
     277        int fd = vfs_lookup(abs, WALK_DIRECTORY);
     278        if (fd < 0) {
     279                free(abs);
     280                return fd;
     281        }
     282       
     283        fibril_mutex_lock(&cwd_mutex);
     284       
     285        if (cwd_fd >= 0)
     286                vfs_put(cwd_fd);
     287       
     288        if (cwd_path)
     289                free(cwd_path);
     290       
     291        cwd_fd = fd;
     292        cwd_path = abs;
     293        cwd_size = abs_size;
     294       
     295        fibril_mutex_unlock(&cwd_mutex);
     296        return EOK;
     297}
     298
     299/** Start an async exchange on the VFS session
     300 *
     301 * @return      New exchange
     302 */
     303async_exch_t *vfs_exchange_begin(void)
     304{
     305        fibril_mutex_lock(&vfs_mutex);
     306       
     307        while (vfs_sess == NULL) {
     308                vfs_sess = service_connect_blocking(SERVICE_VFS, INTERFACE_VFS,
     309                    0);
     310        }
     311       
     312        fibril_mutex_unlock(&vfs_mutex);
     313       
     314        return async_exchange_begin(vfs_sess);
     315}
     316
     317/** Finish an async exchange on the VFS session
     318 *
     319 * @param exch  Exchange to be finished
     320 */
     321void vfs_exchange_end(async_exch_t *exch)
     322{
     323        async_exchange_end(exch);
     324}
     325
     326/** Open session to service represented by a special file
     327 *
     328 * Given that the file referred to by @a file represents a service,
     329 * open a session to that service.
     330 *
     331 * @param file  File handle representing a service
     332 * @param iface Interface to connect to (XXX Should be automatic)
     333 *
     334 * @return      Session pointer on success.
     335 * @return      @c NULL or error.
     336 */
     337async_sess_t *vfs_fd_session(int file, iface_t iface)
     338{
     339        struct stat stat;
     340        int rc = vfs_stat(file, &stat);
     341        if (rc != 0)
     342                return NULL;
     343       
     344        if (stat.service == 0)
     345                return NULL;
     346       
     347        return loc_service_connect(stat.service, iface, 0);
     348}
     349
     350/** Link a file or directory
     351 *
     352 * Create a new name and an empty file or an empty directory in a parent
     353 * directory. If child with the same name already exists, the function returns
     354 * a failure, the existing file remains untouched and no file system object
     355 * is created.
     356 *
     357 * @param parent        File handle of the parent directory node
     358 * @param child         New name to be linked
     359 * @param kind          Kind of the object to be created: KIND_FILE or
     360 *                      KIND_DIRECTORY
     361 * @param[out] linkedfd If not NULL, will receive a file handle to the linked
     362 *                      child
     363 * @return              EOK on success or a negative error code
     364 */
     365int vfs_link(int parent, const char *child, vfs_file_kind_t kind, int *linkedfd)
     366{
     367        int flags = (kind == KIND_DIRECTORY) ? WALK_DIRECTORY : WALK_REGULAR;
     368        int file = vfs_walk(parent, child, WALK_MUST_CREATE | flags);
     369
     370        if (file < 0)
     371                return file;
     372
     373        if (linkedfd)
     374                *linkedfd = file;
     375        else
     376                vfs_put(file);
     377
     378        return EOK;
     379}
     380
     381/** Link a file or directory
     382 *
     383 * Create a new name and an empty file or an empty directory at given path.
     384 * If a link with the same name already exists, the function returns
     385 * a failure, the existing file remains untouched and no file system object
     386 * is created.
     387 *
     388 * @param path          New path to be linked
     389 * @param kind          Kind of the object to be created: KIND_FILE or
     390 *                      KIND_DIRECTORY
     391 * @param[out] linkedfd If not NULL, will receive a file handle to the linked
     392 *                      child
     393 * @return              EOK on success or a negative error code
     394 */
     395int vfs_link_path(const char *path, vfs_file_kind_t kind, int *linkedfd)
     396{
     397        char *child;
     398        int parent = get_parent_and_child(path, &child);
     399        if (parent < 0)
     400                return parent;
     401
     402        int rc = vfs_link(parent, child, kind, linkedfd);
     403
     404        free(child);
     405        vfs_put(parent);
     406        return rc;
     407}       
     408
     409/** Lookup a path relative to the local root
     410 *
     411 * @param path  Path to be looked up
     412 * @param flags Walk flags
     413 *
     414 * @return      File handle representing the result on success or a negative
     415 *              error code on error
     416 */
     417int vfs_lookup(const char *path, int flags)
     418{
     419        size_t size;
     420        char *p = vfs_absolutize(path, &size);
     421        if (!p)
     422                return ENOMEM;
     423        int root = vfs_root();
     424        if (root < 0) {
     425                free(p);
     426                return ENOENT;
     427        }
     428        int rc = vfs_walk(root, p, flags);
     429        vfs_put(root);
     430        free(p);
     431        return rc;
     432}
     433
     434/** Lookup a path relative to the local root and open the result
     435 *
     436 * This function is a convenience combo for vfs_lookup() and vfs_open().
     437 *
     438 * @param path  Path to be looked up
     439 * @param flags Walk flags
     440 * @param mode  Mode in which to open file in
     441 *
     442 * @return      EOK on success or a negative error code
     443 */
     444int vfs_lookup_open(const char *path, int flags, int mode)
     445{
     446        int file = vfs_lookup(path, flags);
     447        if (file < 0)
     448                return file;
     449
     450        int rc = vfs_open(file, mode);
     451        if (rc != EOK) {
     452                vfs_put(file);
     453                return rc;
     454        }
     455       
     456        return file;
     457}
     458
     459/** Mount a file system
     460 *
     461 * @param[in] mp                File handle representing the mount-point
     462 * @param[in] fs_name           File system name
     463 * @param[in] serv              Service representing the mountee
     464 * @param[in] opts              Mount options for the endpoint file system
     465 * @param[in] flags             Mount flags
     466 * @param[in] instance          Instance number of the file system server
     467 * @param[out] mountedfd        File handle of the mounted root if not NULL
     468 *
     469 * @return                      EOK on success or a negative error code
     470 */
     471int vfs_mount(int mp, const char *fs_name, service_id_t serv, const char *opts,
     472    unsigned int flags, unsigned int instance, int *mountedfd)
     473{
     474        sysarg_t rc, rc1;
     475       
     476        if (!mountedfd)
     477                flags |= VFS_MOUNT_NO_REF;
     478        if (mp < 0)
     479                flags |= VFS_MOUNT_CONNECT_ONLY;
     480       
     481        ipc_call_t answer;
     482        async_exch_t *exch = vfs_exchange_begin();
     483        aid_t req = async_send_4(exch, VFS_IN_MOUNT, mp, serv, flags, instance,
     484            &answer);
     485
     486        rc1 = async_data_write_start(exch, (void *) opts, str_size(opts));
     487        if (rc1 == EOK) {
     488                rc1 = async_data_write_start(exch, (void *) fs_name,
     489                    str_size(fs_name));
     490        }
     491
     492        vfs_exchange_end(exch);
     493
     494        async_wait_for(req, &rc);
     495
     496        if (mountedfd)
     497                *mountedfd = (int) IPC_GET_ARG1(answer);
     498       
     499        if (rc != EOK)
     500                return rc;
     501        return rc1;
     502}
     503
     504/** Mount a file system
     505 *
     506 * @param[in] mp                Path representing the mount-point
     507 * @param[in] fs_name           File system name
     508 * @param[in] fqsn              Fully qualified service name of the mountee
     509 * @param[in] opts              Mount options for the endpoint file system
     510 * @param[in] flags             Mount flags
     511 * @param[in] instance          Instance number of the file system server
     512 *
     513 * @return                      EOK on success or a negative error code
     514 */
     515int vfs_mount_path(const char *mp, const char *fs_name, const char *fqsn,
    146516    const char *opts, unsigned int flags, unsigned int instance)
    147517{
     
    150520       
    151521        if (str_cmp(fqsn, "") == 0) {
    152                 /* No device specified, create a fresh
    153                    null/%d device instead */
     522                /*
     523                 * No device specified, create a fresh null/%d device instead.
     524                */
    154525                null_id = loc_null_create();
    155526               
     
    161532        }
    162533       
     534        if (flags & IPC_FLAG_BLOCKING)
     535                flags = VFS_MOUNT_BLOCKING;
     536        else
     537                flags = 0;
     538       
    163539        service_id_t service_id;
    164540        int res = loc_service_get_id(fqsn, &service_id, flags);
     
    179555        }
    180556       
    181         async_exch_t *exch = vfs_exchange_begin();
    182 
    183         sysarg_t rc_orig;
    184         aid_t req = async_send_3(exch, VFS_IN_MOUNT, service_id, flags,
    185             instance, NULL);
    186         sysarg_t rc = async_data_write_start(exch, (void *) mpa, mpa_size);
    187         if (rc != EOK) {
    188                 vfs_exchange_end(exch);
    189                 free(mpa);
    190                 async_wait_for(req, &rc_orig);
     557        fibril_mutex_lock(&root_mutex);
     558       
     559        int rc;
     560       
     561        if (str_cmp(mpa, "/") == 0) {
     562                /* Mounting root. */
    191563               
    192                 if (null_id != -1)
    193                         loc_null_destroy(null_id);
     564                if (root_fd >= 0) {
     565                        fibril_mutex_unlock(&root_mutex);
     566                        if (null_id != -1)
     567                                loc_null_destroy(null_id);
     568                        return EBUSY;
     569                }
    194570               
    195                 if (rc_orig == EOK)
    196                         return (int) rc;
    197                 else
    198                         return (int) rc_orig;
    199         }
    200        
    201         rc = async_data_write_start(exch, (void *) opts, str_size(opts));
    202         if (rc != EOK) {
    203                 vfs_exchange_end(exch);
    204                 free(mpa);
    205                 async_wait_for(req, &rc_orig);
     571                int root;
     572                rc = vfs_mount(-1, fs_name, service_id, opts, flags, instance,
     573                    &root);
     574                if (rc == EOK)
     575                        root_fd = root;
     576        } else {
     577                if (root_fd < 0) {
     578                        fibril_mutex_unlock(&root_mutex);
     579                        if (null_id != -1)
     580                                loc_null_destroy(null_id);
     581                        return EINVAL;
     582                }
    206583               
    207                 if (null_id != -1)
    208                         loc_null_destroy(null_id);
    209                
    210                 if (rc_orig == EOK)
    211                         return (int) rc;
    212                 else
    213                         return (int) rc_orig;
    214         }
    215        
    216         rc = async_data_write_start(exch, (void *) fs_name, str_size(fs_name));
    217         if (rc != EOK) {
    218                 vfs_exchange_end(exch);
    219                 free(mpa);
    220                 async_wait_for(req, &rc_orig);
    221                
    222                 if (null_id != -1)
    223                         loc_null_destroy(null_id);
    224                
    225                 if (rc_orig == EOK)
    226                         return (int) rc;
    227                 else
    228                         return (int) rc_orig;
    229         }
    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        
    247         vfs_exchange_end(exch);
    248         free(mpa);
    249         async_wait_for(req, &rc);
     584                int mpfd = vfs_walk(root_fd, mpa, WALK_DIRECTORY);
     585                if (mpfd >= 0) {
     586                        rc = vfs_mount(mpfd, fs_name, service_id, opts, flags,
     587                            instance, NULL);
     588                        vfs_put(mpfd);
     589                } else {
     590                        rc = mpfd;
     591                }
     592        }
     593       
     594        fibril_mutex_unlock(&root_mutex);
    250595       
    251596        if ((rc != EOK) && (null_id != -1))
     
    255600}
    256601
    257 int vfs_unmount(const char *mp)
    258 {
    259         sysarg_t rc;
    260         sysarg_t rc_orig;
    261         aid_t req;
    262         size_t mpa_size;
    263         char *mpa;
    264        
    265         mpa = vfs_absolutize(mp, &mpa_size);
    266         if (mpa == NULL)
    267                 return ENOMEM;
    268        
    269         async_exch_t *exch = vfs_exchange_begin();
    270        
    271         req = async_send_0(exch, VFS_IN_UNMOUNT, NULL);
    272         rc = async_data_write_start(exch, (void *) mpa, mpa_size);
    273         if (rc != EOK) {
    274                 vfs_exchange_end(exch);
    275                 free(mpa);
    276                 async_wait_for(req, &rc_orig);
    277                 if (rc_orig == EOK)
    278                         return (int) rc;
    279                 else
    280                         return (int) rc_orig;
    281         }
    282        
    283 
    284         vfs_exchange_end(exch);
    285         free(mpa);
    286         async_wait_for(req, &rc);
    287        
    288         return (int) rc;
    289 }
    290 
    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        
     602
     603/** Open a file handle for I/O
     604 *
     605 * @param file  File handle to enable I/O on
     606 * @param mode  Mode in which to open file in
     607 *
     608 * @return      EOK on success or a negative error code
     609 */
     610int vfs_open(int file, int mode)
     611{
     612        async_exch_t *exch = vfs_exchange_begin();
     613        int rc = async_req_2_0(exch, VFS_IN_OPEN, file, mode);
     614        vfs_exchange_end(exch);
     615       
     616        return rc;
     617}
     618
     619/** Pass a file handle to another VFS client
     620 *
     621 * @param vfs_exch      Donor's VFS exchange
     622 * @param file          Donor's file handle to pass
     623 * @param exch          Exchange to the acceptor
     624 *
     625 * @return              EOK on success or a negative error code
     626 */
     627int vfs_pass_handle(async_exch_t *vfs_exch, int file, async_exch_t *exch)
     628{
     629        return async_state_change_start(exch, VFS_PASS_HANDLE, (sysarg_t) file,
     630            0, vfs_exch);
     631}
     632
     633/** Stop working with a file handle
     634 *
     635 * @param file  File handle to put
     636 *
     637 * @return      EOK on success or a negative error code
     638 */
     639int vfs_put(int file)
     640{
     641        async_exch_t *exch = vfs_exchange_begin();
     642        int rc = async_req_1_0(exch, VFS_IN_PUT, file);
     643        vfs_exchange_end(exch);
     644       
     645        return rc;
     646}
     647
     648/** Receive a file handle from another VFS client
     649 *
     650 * @param high   If true, the received file handle will be allocated from high
     651 *               indices
     652 *
     653 * @return       EOK on success or a negative error code
     654 */
     655int vfs_receive_handle(bool high)
     656{
     657        ipc_callid_t callid;
     658        if (!async_state_change_receive(&callid, NULL, NULL, NULL)) {
     659                async_answer_0(callid, EINVAL);
     660                return EINVAL;
     661        }
     662
     663        async_exch_t *vfs_exch = vfs_exchange_begin();
     664
     665        async_state_change_finalize(callid, vfs_exch);
     666
     667        sysarg_t ret;
     668        sysarg_t rc = async_req_1_1(vfs_exch, VFS_IN_WAIT_HANDLE, high, &ret);
     669
     670        async_exchange_end(vfs_exch);
     671
    325672        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  */
    341 int open(const char *path, int oflag, ...)
    342 {
    343         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  */
    368 int close(int fildes)
    369 {
    370         sysarg_t rc;
    371        
    372         async_exch_t *exch = vfs_exchange_begin();
    373         rc = async_req_1_0(exch, VFS_IN_CLOSE, fildes);
    374         vfs_exchange_end(exch);
    375        
    376         if (rc != EOK) {
    377                 errno = rc;
    378                 return -1;
    379         }
    380        
    381         return 0;
    382 }
    383 
    384 /** Read bytes from file.
     673                return rc;
     674        return ret;
     675}
     676
     677/** Read data
     678 *
     679 * Read up to @a nbytes bytes from file if available. This function always reads
     680 * all the available bytes up to @a nbytes.
     681 *
     682 * @param file          File handle to read from
     683 * @param[inout] pos    Position to read from, updated by the actual bytes read
     684 * @param buf           Buffer, @a nbytes bytes long
     685 * @param nbytes        Number of bytes to read
     686 *
     687 * @return              On success, non-negative number of bytes read
     688 * @return              On failure, a negative error code
     689 */
     690ssize_t vfs_read(int file, aoff64_t *pos, void *buf, size_t nbyte)
     691{
     692        ssize_t cnt = 0;
     693        size_t nread = 0;
     694        uint8_t *bp = (uint8_t *) buf;
     695        int rc;
     696       
     697        do {
     698                bp += cnt;
     699                nread += cnt;
     700                *pos += cnt;
     701                rc = vfs_read_short(file, *pos, bp, nbyte - nread, &cnt);
     702        } while (rc == EOK && cnt > 0 && (nbyte - nread - cnt) > 0);
     703       
     704        if (rc != EOK)
     705                return rc;
     706       
     707        *pos += cnt;
     708        return nread + cnt;
     709}
     710
     711/** Read bytes from a file
    385712 *
    386713 * Read up to @a nbyte bytes from file. The actual number of bytes read
     
    389716 * return success with zero bytes read.
    390717 *
    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)
     718 * @param file          File handle to read from
     719 * @param[in] pos       Position to read from
     720 * @param buf           Buffer to read from
     721 * @param nbyte         Maximum number of bytes to read
     722 * @param[out] nread    Actual number of bytes read (0 or more)
     723 *
     724 * @return              EOK on success or a negative error code
     725 */
     726int vfs_read_short(int file, aoff64_t pos, void *buf, size_t nbyte,
     727    ssize_t *nread)
    399728{
    400729        sysarg_t rc;
     
    407736        async_exch_t *exch = vfs_exchange_begin();
    408737       
    409         req = async_send_1(exch, VFS_IN_READ, fildes, &answer);
     738        req = async_send_3(exch, VFS_IN_READ, file, LOWER32(pos),
     739            UPPER32(pos), &answer);
    410740        rc = async_data_read_start(exch, (void *) buf, nbyte);
     741
     742        vfs_exchange_end(exch);
     743       
     744        if (rc == EOK)
     745                async_wait_for(req, &rc);
     746        else
     747                async_forget(req);
     748       
     749        if (rc != EOK)
     750                return rc;
     751       
     752        *nread = (ssize_t) IPC_GET_ARG1(answer);
     753        return EOK;
     754}
     755
     756/** Rename a file or directory
     757 *
     758 * There is no file-handle-based variant to disallow attempts to introduce loops
     759 * and breakage in the directory tree when relinking eg. a node under its own
     760 * descendant.  The path-based variant is not susceptible because the VFS can
     761 * prevent this lexically by comparing the paths.
     762 *
     763 * @param old   Old path
     764 * @param new   New path
     765 *
     766 * @return      EOK on success or a negative error code
     767 */
     768int vfs_rename_path(const char *old, const char *new)
     769{
     770        sysarg_t rc;
     771        sysarg_t rc_orig;
     772        aid_t req;
     773       
     774        size_t olda_size;
     775        char *olda = vfs_absolutize(old, &olda_size);
     776        if (olda == NULL)
     777                return ENOMEM;
     778
     779        size_t newa_size;
     780        char *newa = vfs_absolutize(new, &newa_size);
     781        if (newa == NULL) {
     782                free(olda);
     783                return ENOMEM;
     784        }
     785       
     786        async_exch_t *exch = vfs_exchange_begin();
     787        int root = vfs_root();
     788        if (root < 0) {
     789                free(olda);
     790                free(newa);
     791                return ENOENT;
     792        }
     793       
     794        req = async_send_1(exch, VFS_IN_RENAME, root, NULL);
     795        rc = async_data_write_start(exch, olda, olda_size);
    411796        if (rc != EOK) {
    412797                vfs_exchange_end(exch);
    413                
    414                 sysarg_t rc_orig;
     798                free(olda);
     799                free(newa);
     800                vfs_put(root);
    415801                async_wait_for(req, &rc_orig);
    416                
    417                 if (rc_orig == EOK)
    418                         return rc;
    419                 else
    420                         return rc_orig;
    421         }
    422        
    423         vfs_exchange_end(exch);
    424         async_wait_for(req, &rc);
    425        
    426         if (rc != EOK)
     802                if (rc_orig != EOK)
     803                        rc = rc_orig;
    427804                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)
    447 {
    448         sysarg_t rc;
    449         ipc_call_t answer;
    450         aid_t req;
    451        
    452         if (nbyte > DATA_XFER_LIMIT)
    453                 nbyte = DATA_XFER_LIMIT;
    454        
    455         async_exch_t *exch = vfs_exchange_begin();
    456        
    457         req = async_send_1(exch, VFS_IN_WRITE, fildes, &answer);
    458         rc = async_data_write_start(exch, (void *) buf, nbyte);
     805        }
     806        rc = async_data_write_start(exch, newa, newa_size);
    459807        if (rc != EOK) {
    460808                vfs_exchange_end(exch);
    461                
    462                 sysarg_t rc_orig;
     809                free(olda);
     810                free(newa);
     811                vfs_put(root);
    463812                async_wait_for(req, &rc_orig);
    464                
    465                 if (rc_orig == EOK)
    466                         return rc;
    467                 else
    468                         return rc_orig;
    469         }
    470        
    471         vfs_exchange_end(exch);
     813                if (rc_orig != EOK)
     814                        rc = rc_orig;
     815                return rc;
     816        }
     817        vfs_exchange_end(exch);
     818        free(olda);
     819        free(newa);
     820        vfs_put(root);
    472821        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.
    485  *
    486  * @param fildes        File descriptor
    487  * @param buf           Buffer, @a nbytes bytes long
    488  * @param nbytes        Number of bytes to read
    489  *
    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)
    494 {
    495         ssize_t cnt = 0;
    496         size_t nread = 0;
    497         uint8_t *bp = (uint8_t *) buf;
    498         int rc;
    499        
    500         do {
    501                 bp += cnt;
    502                 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        
    511         return nread + cnt;
    512 }
    513 
    514 /** Write data.
    515  *
    516  * This function fails if it cannot write exactly @a len bytes to the file.
    517  *
    518  * @param fildes        File descriptor
    519  * @param buf           Data, @a nbytes bytes long
    520  * @param nbytes        Number of bytes to write
    521  *
    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)
    526 {
    527         ssize_t cnt = 0;
    528         ssize_t nwritten = 0;
    529         const uint8_t *bp = (uint8_t *) buf;
    530         int rc;
    531 
    532         do {
    533                 bp += cnt;
    534                 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         }
    542 
    543         return nbyte;
    544 }
    545 
    546 /** Synchronize file.
    547  *
    548  * @param fildes File descriptor
    549  * @return 0 on success. On error returns -1 and sets errno.
    550  */
    551 int fsync(int fildes)
    552 {
    553         async_exch_t *exch = vfs_exchange_begin();
    554         sysarg_t rc = async_req_1_0(exch, VFS_IN_SYNC, fildes);
    555         vfs_exchange_end(exch);
    556        
    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  */
    574 off64_t lseek(int fildes, off64_t offset, int whence)
    575 {
    576         async_exch_t *exch = vfs_exchange_begin();
    577        
    578         sysarg_t newoff_lo;
    579         sysarg_t newoff_hi;
    580         sysarg_t rc = async_req_4_2(exch, VFS_IN_SEEK, fildes,
    581             LOWER32(offset), UPPER32(offset), whence,
    582             &newoff_lo, &newoff_hi);
    583        
    584         vfs_exchange_end(exch);
    585        
    586         if (rc != EOK) {
    587                 errno = rc;
    588                 return (off64_t) -1;
    589         }
    590        
    591         return (off64_t) MERGE_LOUP32(newoff_lo, newoff_hi);
    592 }
    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  */
    603 int ftruncate(int fildes, aoff64_t length)
    604 {
    605         sysarg_t rc;
    606        
    607         async_exch_t *exch = vfs_exchange_begin();
    608         rc = async_req_3_0(exch, VFS_IN_TRUNCATE, fildes,
    609             LOWER32(length), UPPER32(length));
    610         vfs_exchange_end(exch);
    611        
    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  */
    627 int fstat(int fildes, struct stat *stat)
     822
     823        return rc;
     824}
     825
     826/** Resize file to a specified length
     827 *
     828 * Resize file so that its size is exactly @a length.
     829 *
     830 * @param file          File handle to resize
     831 * @param length        New length
     832 *
     833 * @return              EOK on success or a negative error code
     834 */
     835int vfs_resize(int file, aoff64_t length)
     836{
     837        async_exch_t *exch = vfs_exchange_begin();
     838        int rc = async_req_3_0(exch, VFS_IN_RESIZE, file, LOWER32(length),
     839            UPPER32(length));
     840        vfs_exchange_end(exch);
     841       
     842        return rc;
     843}
     844
     845/** Return a new file handle representing the local root
     846 *
     847 * @return      A clone of the local root file handle or a negative error code
     848 */
     849int vfs_root(void)
     850{
     851        fibril_mutex_lock(&root_mutex);
     852        int r;
     853        if (root_fd < 0)
     854                r = ENOENT;
     855        else
     856                r = vfs_clone(root_fd, -1, true);
     857        fibril_mutex_unlock(&root_mutex);
     858        return r;
     859}
     860
     861/** Set a new local root
     862 *
     863 * Note that it is still possible to have file handles for other roots and pass
     864 * them to the API functions. Functions like vfs_root() and vfs_lookup() will
     865 * however consider the file set by this function to be the root.
     866 *
     867 * @param nroot The new local root file handle
     868 */
     869void vfs_root_set(int nroot)
     870{
     871        fibril_mutex_lock(&root_mutex);
     872        if (root_fd >= 0)
     873                vfs_put(root_fd);
     874        root_fd = vfs_clone(nroot, -1, true);
     875        fibril_mutex_unlock(&root_mutex);
     876}
     877
     878/** Get file information
     879 *
     880 * @param file          File handle to get information about
     881 * @param[out] stat     Place to store file information
     882 *
     883 * @return              EOK on success or a negative error code
     884 */
     885int vfs_stat(int file, struct stat *stat)
    628886{
    629887        sysarg_t rc;
     
    632890        async_exch_t *exch = vfs_exchange_begin();
    633891       
    634         req = async_send_1(exch, VFS_IN_FSTAT, fildes, NULL);
     892        req = async_send_1(exch, VFS_IN_STAT, file, NULL);
    635893        rc = async_data_read_start(exch, (void *) stat, sizeof(struct stat));
    636894        if (rc != EOK) {
     
    642900                if (rc_orig != EOK)
    643901                        rc = rc_orig;
    644                 if (rc != EOK) {
    645                         errno = rc;
    646                         return -1;
    647                 }
    648902               
    649                 return 0;
     903                return rc;
    650904        }
    651905       
     
    653907        async_wait_for(req, &rc);
    654908       
    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  */
    670 int stat(const char *path, struct stat *stat)
    671 {
    672         sysarg_t rc;
    673         sysarg_t rc_orig;
     909        return rc;
     910}
     911
     912/** Get file information
     913 *
     914 * @param path          File path to get information about
     915 * @param[out] stat     Place to store file information
     916 *
     917 * @return              EOK on success or a negative error code
     918 */
     919int vfs_stat_path(const char *path, struct stat *stat)
     920{
     921        int file = vfs_lookup(path, 0);
     922        if (file < 0)
     923                return file;
     924       
     925        int rc = vfs_stat(file, stat);
     926
     927        vfs_put(file);
     928
     929        return rc;
     930}
     931
     932/** Get filesystem statistics
     933 *
     934 * @param file          File located on the queried file system
     935 * @param[out] st       Buffer for storing information
     936 *
     937 * @return              EOK on success or a negative error code
     938 */
     939int vfs_statfs(int file, struct statfs *st)
     940{
     941        sysarg_t rc, ret;
    674942        aid_t req;
    675        
    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)
     943
     944        async_exch_t *exch = vfs_exchange_begin();
     945
     946        req = async_send_1(exch, VFS_IN_STATFS, file, NULL);
     947        rc = async_data_read_start(exch, (void *) st, sizeof(*st));
     948
     949        vfs_exchange_end(exch);
     950        async_wait_for(req, &ret);
     951
     952        rc = (ret != EOK ? ret : rc);
     953
     954        return rc;
     955}
     956
     957/** Get filesystem statistics
     958 *
     959 * @param file          Path pointing to the queried file system
     960 * @param[out] st       Buffer for storing information
     961 *
     962 * @return              EOK on success or a negative error code
     963 */
     964int vfs_statfs_path(const char *path, struct statfs *st)
     965{
     966        int file = vfs_lookup(path, 0);
     967        if (file < 0)
     968                return file;
     969       
     970        int rc = vfs_statfs(file, st);
     971
     972        vfs_put(file);
     973
     974        return rc;
     975}
     976
     977/** Synchronize file
     978 *
     979 * @param file  File handle to synchronize
     980 *
     981 * @return      EOK on success or a negative error code
     982 */
     983int vfs_sync(int file)
     984{
     985        async_exch_t *exch = vfs_exchange_begin();
     986        int rc = async_req_1_0(exch, VFS_IN_SYNC, file);
     987        vfs_exchange_end(exch);
     988       
     989        return rc;
     990}
     991
     992/** Unlink a file or directory
     993 *
     994 * Unlink a name from a parent directory. The caller can supply the file handle
     995 * of the unlinked child in order to detect a possible race with vfs_link() and
     996 * avoid unlinking a wrong file. If the last link for a file or directory is
     997 * removed, the FS implementation will deallocate its resources.
     998 *
     999 * @param parent        File handle of the parent directory node
     1000 * @param child         Old name to be unlinked
     1001 * @param expect        File handle of the unlinked child
     1002 *
     1003 * @return              EOK on success or a negative error code
     1004 */
     1005int vfs_unlink(int parent, const char *child, int expect)
    8101006{
    8111007        sysarg_t rc;
    8121008        aid_t req;
    8131009       
    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);
     1010        async_exch_t *exch = vfs_exchange_begin();
     1011       
     1012        req = async_send_2(exch, VFS_IN_UNLINK, parent, expect, NULL);
     1013        rc = async_data_write_start(exch, child, str_size(child));
     1014       
     1015        vfs_exchange_end(exch);
     1016       
     1017        sysarg_t rc_orig;
     1018        async_wait_for(req, &rc_orig);
     1019       
     1020        if (rc_orig != EOK)
     1021                return (int) rc_orig;
     1022        return rc;
     1023}
     1024
     1025/** Unlink a file or directory
     1026 *
     1027 * Unlink a path. If the last link for a file or directory is removed, the FS
     1028 * implementation will deallocate its resources.
     1029 *
     1030 * @param path          Old path to be unlinked
     1031 *
     1032 * @return              EOK on success or a negative error code
     1033 */
     1034int vfs_unlink_path(const char *path)
     1035{
     1036        int expect = vfs_lookup(path, 0);
     1037        if (expect < 0)
     1038                return expect;
     1039
     1040        char *child;
     1041        int parent = get_parent_and_child(path, &child);
     1042        if (parent < 0) {
     1043                vfs_put(expect);
     1044                return parent;
     1045        }
     1046
     1047        int rc = vfs_unlink(parent, child, expect);
     1048       
     1049        free(child);
     1050        vfs_put(parent);
     1051        vfs_put(expect);
     1052        return rc;
     1053}
     1054
     1055/** Unmount a file system
     1056 *
     1057 * @param mp    File handle representing the mount-point
     1058 *
     1059 * @return      EOK on success or a negative error code
     1060 */
     1061int vfs_unmount(int mp)
     1062{
     1063        async_exch_t *exch = vfs_exchange_begin();
     1064        int rc = async_req_1_0(exch, VFS_IN_UNMOUNT, mp);
     1065        vfs_exchange_end(exch);
     1066        return rc;
     1067}
     1068
     1069/** Unmount a file system
     1070 *
     1071 * @param mpp   Mount-point path
     1072 *
     1073 * @return      EOK on success or a negative error code
     1074 */
     1075int vfs_unmount_path(const char *mpp)
     1076{
     1077        int mp = vfs_lookup(mpp, WALK_MOUNT_POINT | WALK_DIRECTORY);
     1078        if (mp < 0)
     1079                return mp;
     1080       
     1081        int rc = vfs_unmount(mp);
     1082        vfs_put(mp);
     1083        return rc;
     1084}
     1085
     1086/** Walk a path starting in a parent node
     1087 *
     1088 * @param parent        File handle of the parent node where the walk starts
     1089 * @param path          Parent-relative path to be walked
     1090 * @param flags         Flags influencing the walk
     1091 *
     1092 * @retrun              File handle representing the result on success or
     1093 *                      a negative error code on error
     1094 */
     1095int vfs_walk(int parent, const char *path, int flags)
     1096{
     1097        async_exch_t *exch = vfs_exchange_begin();
     1098       
     1099        ipc_call_t answer;
     1100        aid_t req = async_send_2(exch, VFS_IN_WALK, parent, flags, &answer);
     1101        sysarg_t rc = async_data_write_start(exch, path, str_size(path));
     1102        vfs_exchange_end(exch);
    8281103               
    829                 sysarg_t rc_orig;
    830                 async_wait_for(req, &rc_orig);
     1104        sysarg_t rc_orig;
     1105        async_wait_for(req, &rc_orig);
     1106
     1107        if (rc_orig != EOK)
     1108                return (int) rc_orig;
    8311109               
    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)
     1110        if (rc != EOK)
     1111                return (int) rc;
     1112       
     1113        return (int) IPC_GET_ARG1(answer);
     1114}
     1115
     1116/** Write data
     1117 *
     1118 * This function fails if it cannot write exactly @a len bytes to the file.
     1119 *
     1120 * @param file          File handle to write to
     1121 * @param[inout] pos    Position to write to, updated by the actual bytes
     1122 *                      written
     1123 * @param buf           Data, @a nbytes bytes long
     1124 * @param nbytes        Number of bytes to write
     1125 *
     1126 * @return              On success, non-negative number of bytes written
     1127 * @return              On failure, a negative error code
     1128 */
     1129ssize_t vfs_write(int file, aoff64_t *pos, const void *buf, size_t nbyte)
     1130{
     1131        ssize_t cnt = 0;
     1132        ssize_t nwritten = 0;
     1133        const uint8_t *bp = (uint8_t *) buf;
     1134        int rc;
     1135
     1136        do {
     1137                bp += cnt;
     1138                nwritten += cnt;
     1139                *pos += cnt;
     1140                rc = vfs_write_short(file, *pos, bp, nbyte - nwritten, &cnt);
     1141        } while (rc == EOK && ((ssize_t )nbyte - nwritten - cnt) > 0);
     1142
     1143        if (rc != EOK)
     1144                return rc;
     1145
     1146        *pos += cnt;
     1147        return nbyte;
     1148}
     1149
     1150/** Write bytes to a file
     1151 *
     1152 * Write up to @a nbyte bytes from file. The actual number of bytes written
     1153 * may be lower, but greater than zero.
     1154 *
     1155 * @param file          File handle to write to
     1156 * @param[in] pos       Position to write to
     1157 * @param buf           Buffer to write to
     1158 * @param nbyte         Maximum number of bytes to write
     1159 * @param[out] nread    Actual number of bytes written (0 or more)
     1160 *
     1161 * @return              EOK on success or a negative error code
     1162 */
     1163int vfs_write_short(int file, aoff64_t pos, const void *buf, size_t nbyte,
     1164    ssize_t *nwritten)
    8621165{
    8631166        sysarg_t rc;
     1167        ipc_call_t answer;
    8641168        aid_t req;
    8651169       
    866         size_t pa_size;
    867         char *pa = vfs_absolutize(path, &pa_size);
    868         if (pa == NULL)
    869                 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         }
    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);
    961         if (rc != EOK) {
    962                 vfs_exchange_end(exch);
    963                 free(olda);
    964                 free(newa);
    965                 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;
    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;
    987         }
    988         vfs_exchange_end(exch);
    989         free(olda);
    990         free(newa);
    991         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  */
    1016 int chdir(const char *path)
    1017 {
    1018         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) {
    1030                 free(abs);
    1031                 errno = rc;
    1032                 return -1;
    1033         }
    1034        
    1035         fibril_mutex_lock(&cwd_mutex);
    1036        
    1037         if (cwd_fd >= 0)
    1038                 close(cwd_fd);
    1039        
    1040         if (cwd_path)
    1041                 free(cwd_path);
    1042        
    1043         cwd_fd = fd;
    1044         cwd_path = abs;
    1045         cwd_size = abs_size;
    1046        
    1047         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  */
    1057 char *getcwd(char *buf, size_t size)
    1058 {
    1059         if (size == 0) {
    1060                 errno = EINVAL;
    1061                 return NULL;
    1062         }
    1063        
    1064         fibril_mutex_lock(&cwd_mutex);
    1065        
    1066         if ((cwd_size == 0) || (size < cwd_size + 1)) {
    1067                 fibril_mutex_unlock(&cwd_mutex);
    1068                 errno = ERANGE;
    1069                 return NULL;
    1070         }
    1071        
    1072         str_cpy(buf, size, cwd_path);
    1073         fibril_mutex_unlock(&cwd_mutex);
    1074        
    1075         return buf;
    1076 }
    1077 
    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)
    1088 {
    1089         struct stat stat;
    1090         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  */
    1108 int dup2(int oldfd, int newfd)
    1109 {
    1110         async_exch_t *exch = vfs_exchange_begin();
    1111        
    1112         sysarg_t ret;
    1113         sysarg_t rc = async_req_2_1(exch, VFS_IN_DUP, oldfd, newfd, &ret);
     1170        if (nbyte > DATA_XFER_LIMIT)
     1171                nbyte = DATA_XFER_LIMIT;
     1172       
     1173        async_exch_t *exch = vfs_exchange_begin();
     1174       
     1175        req = async_send_3(exch, VFS_IN_WRITE, file, LOWER32(pos),
     1176            UPPER32(pos), &answer);
     1177        rc = async_data_write_start(exch, (void *) buf, nbyte);
    11141178       
    11151179        vfs_exchange_end(exch);
    11161180       
    11171181        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)
    1129 {
    1130         async_exch_t *exch = vfs_exchange_begin();
    1131        
    1132         sysarg_t ret;
    1133         sysarg_t rc = async_req_0_1(exch, VFS_IN_WAIT_HANDLE, &ret);
    1134        
    1135         vfs_exchange_end(exch);
    1136        
    1137         if (rc == EOK)
    1138                 return (int) ret;
    1139        
    1140         return (int) rc;
    1141 }
    1142 
    1143 int vfs_get_mtab_list(list_t *mtab_list)
    1144 {
    1145         sysarg_t rc;
    1146         aid_t req;
    1147         size_t i;
    1148         sysarg_t num_mounted_fs;
    1149        
    1150         async_exch_t *exch = vfs_exchange_begin();
    1151 
    1152         req = async_send_0(exch, VFS_IN_MTAB_GET, NULL);
    1153 
    1154         /* Ask VFS how many filesystems are mounted */
    1155         rc = async_req_0_1(exch, VFS_IN_PING, &num_mounted_fs);
     1182                async_wait_for(req, &rc);
     1183        else
     1184                async_forget(req);
     1185
    11561186        if (rc != EOK)
    1157                 goto exit;
    1158 
    1159         for (i = 0; i < num_mounted_fs; ++i) {
    1160                 mtab_ent_t *mtab_ent;
    1161 
    1162                 mtab_ent = malloc(sizeof(mtab_ent_t));
    1163                 if (mtab_ent == NULL) {
    1164                         rc = ENOMEM;
    1165                         goto exit;
    1166                 }
    1167 
    1168                 memset(mtab_ent, 0, sizeof(mtab_ent_t));
    1169 
    1170                 rc = async_data_read_start(exch, (void *) mtab_ent->mp,
    1171                     MAX_PATH_LEN);
    1172                 if (rc != EOK)
    1173                         goto exit;
    1174 
    1175                 rc = async_data_read_start(exch, (void *) mtab_ent->opts,
    1176                         MAX_MNTOPTS_LEN);
    1177                 if (rc != EOK)
    1178                         goto exit;
    1179 
    1180                 rc = async_data_read_start(exch, (void *) mtab_ent->fs_name,
    1181                         FS_NAME_MAXLEN);
    1182                 if (rc != EOK)
    1183                         goto exit;
    1184 
    1185                 sysarg_t p[2];
    1186 
    1187                 rc = async_req_0_2(exch, VFS_IN_PING, &p[0], &p[1]);
    1188                 if (rc != EOK)
    1189                         goto exit;
    1190 
    1191                 mtab_ent->instance = p[0];
    1192                 mtab_ent->service_id = p[1];
    1193 
    1194                 link_initialize(&mtab_ent->link);
    1195                 list_append(&mtab_ent->link, mtab_list);
    1196         }
    1197 
    1198 exit:
    1199         async_wait_for(req, &rc);
    1200         vfs_exchange_end(exch);
    1201         return rc;
    1202 }
    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;
     1187                return rc;
     1188       
     1189        *nwritten = (ssize_t) IPC_GET_ARG1(answer);
     1190        return EOK;
    12431191}
    12441192
Note: See TracChangeset for help on using the changeset viewer.