Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 3ba431a in mainline


Ignore:
Timestamp:
2017-04-03T20:39:12Z (3 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
master
Children:
2c40637
Parents:
ca7506f
Message:

Sort functions in vfs/vfs.[ch] alphabetically

Location:
uspace/lib/c
Files:
2 edited

Legend:

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

    rca7506f r3ba431a  
    126126static int root_fd = -1;
    127127
    128 /** Return a new file handle representing the local root
    129  *
    130  * @return      A clone of the local root file handle or a negative error code
    131  */
    132 int vfs_root(void)
    133 {
    134         fibril_mutex_lock(&root_mutex);
    135         int r;
    136         if (root_fd < 0)
    137                 r = ENOENT;
    138         else
    139                 r = vfs_clone(root_fd, -1, true);
    140         fibril_mutex_unlock(&root_mutex);
    141         return r;
    142 }
    143 
    144 /** Set a new local root
    145  *
    146  * Note that it is still possible to have file handles for other roots and pass
    147  * them to the API functions. Functions like vfs_root() and vfs_lookup() will
    148  * however consider the file set by this function to be the root.
    149  *
    150  * @param nroot The new local root file handle
    151  */
    152 
    153 void vfs_root_set(int nroot)
    154 {
    155         fibril_mutex_lock(&root_mutex);
    156         if (root_fd >= 0)
    157                 vfs_put(root_fd);
    158         root_fd = vfs_clone(nroot, -1, true);
    159         fibril_mutex_unlock(&root_mutex);
    160 }
    161 
    162 /** Start an async exchange on the VFS session
    163  *
    164  * @return      New exchange
    165  */
    166 async_exch_t *vfs_exchange_begin(void)
    167 {
    168         fibril_mutex_lock(&vfs_mutex);
    169        
    170         while (vfs_sess == NULL) {
    171                 vfs_sess = service_connect_blocking(SERVICE_VFS, INTERFACE_VFS,
    172                     0);
    173         }
    174        
    175         fibril_mutex_unlock(&vfs_mutex);
    176        
    177         return async_exchange_begin(vfs_sess);
    178 }
    179 
    180 /** Finish an async exchange on the VFS session
    181  *
    182  * @param exch  Exchange to be finished
    183  */
    184 void vfs_exchange_end(async_exch_t *exch)
    185 {
    186         async_exchange_end(exch);
    187 }
    188 
    189 /** Walk a path starting in a parent node
    190  *
    191  * @param parent        File handle of the parent node where the walk starts
    192  * @param path          Parent-relative path to be walked
    193  * @param flags         Flags influencing the walk
    194  *
    195  * @retrun              File handle representing the result on success or
    196  *                      a negative error code on error
    197  */
    198 int vfs_walk(int parent, const char *path, int flags)
    199 {
    200         async_exch_t *exch = vfs_exchange_begin();
    201        
    202         ipc_call_t answer;
    203         aid_t req = async_send_2(exch, VFS_IN_WALK, parent, flags, &answer);
    204         sysarg_t rc = async_data_write_start(exch, path, str_size(path));
    205         vfs_exchange_end(exch);
    206                
    207         sysarg_t rc_orig;
    208         async_wait_for(req, &rc_orig);
    209 
    210         if (rc_orig != EOK)
    211                 return (int) rc_orig;
    212                
    213         if (rc != EOK)
    214                 return (int) rc;
    215        
    216         return (int) IPC_GET_ARG1(answer);
    217 }
    218 
    219 /** Lookup a path relative to the local root
    220  *
    221  * @param path  Path to be looked up
    222  * @param flags Walk flags
    223  *
    224  * @return      File handle representing the result on success or a negative
    225  *              error code on error
    226  */
    227 int vfs_lookup(const char *path, int flags)
     128static int get_parent_and_child(const char *path, char **child)
    228129{
    229130        size_t size;
    230         char *p = vfs_absolutize(path, &size);
    231         if (!p)
     131        char *apath = vfs_absolutize(path, &size);
     132        if (!apath)
    232133                return ENOMEM;
    233         int root = vfs_root();
    234         if (root < 0) {
    235                 free(p);
    236                 return ENOENT;
    237         }
    238         int rc = vfs_walk(root, p, flags);
    239         vfs_put(root);
    240         free(p);
    241         return rc;
    242 }
    243 
    244 /** Open a file handle for I/O
    245  *
    246  * @param file  File handle to enable I/O on
    247  * @param mode  Mode in which to open file in
    248  *
    249  * @return      EOK on success or a negative error code
    250  */
    251 int vfs_open(int file, int mode)
    252 {
    253         async_exch_t *exch = vfs_exchange_begin();
    254         int rc = async_req_2_0(exch, VFS_IN_OPEN, file, mode);
    255         vfs_exchange_end(exch);
    256        
    257         return rc;
    258 }
    259 
    260 /** Lookup a path relative to the local root and open the result
    261  *
    262  * This function is a convenience combo for vfs_lookup() and vfs_open().
    263  *
    264  * @param path  Path to be looked up
    265  * @param flags Walk flags
    266  * @param mode  Mode in which to open file in
    267  *
    268  * @return      EOK on success or a negative error code
    269  */
    270 int vfs_lookup_open(const char *path, int flags, int mode)
    271 {
    272         int file = vfs_lookup(path, flags);
    273         if (file < 0)
    274                 return file;
    275 
    276         int rc = vfs_open(file, mode);
    277         if (rc != EOK) {
    278                 vfs_put(file);
    279                 return rc;
    280         }
    281        
    282         return file;
     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;
    283157}
    284158
     
    344218}
    345219
     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 * @return              EOK on success or a negative error code
     362 */
     363int vfs_link(int parent, const char *child, vfs_file_kind_t kind)
     364{
     365        int flags = (kind == KIND_DIRECTORY) ? WALK_DIRECTORY : WALK_REGULAR;
     366        int file = vfs_walk(parent, child, WALK_MUST_CREATE | flags);
     367
     368        if (file < 0)
     369                return file;
     370
     371        vfs_put(file);
     372
     373        return EOK;
     374}
     375
     376/** Link a file or directory
     377 *
     378 * Create a new name and an empty file or an empty directory at given path.
     379 * If a link with the same name already exists, the function returns
     380 * a failure, the existing file remains untouched and no file system object
     381 * is created.
     382 *
     383 * @param path          New path to be linked
     384 * @param kind          Kind of the object to be created: KIND_FILE or
     385 *                      KIND_DIRECTORY
     386 * @return              EOK on success or a negative error code
     387 */
     388int vfs_link_path(const char *path, vfs_file_kind_t kind)
     389{
     390        char *child;
     391        int parent = get_parent_and_child(path, &child);
     392        if (parent < 0)
     393                return parent;
     394
     395        int rc = vfs_link(parent, child, kind);
     396
     397        free(child);
     398        vfs_put(parent);
     399        return rc;
     400}       
     401
     402/** Lookup a path relative to the local root
     403 *
     404 * @param path  Path to be looked up
     405 * @param flags Walk flags
     406 *
     407 * @return      File handle representing the result on success or a negative
     408 *              error code on error
     409 */
     410int vfs_lookup(const char *path, int flags)
     411{
     412        size_t size;
     413        char *p = vfs_absolutize(path, &size);
     414        if (!p)
     415                return ENOMEM;
     416        int root = vfs_root();
     417        if (root < 0) {
     418                free(p);
     419                return ENOENT;
     420        }
     421        int rc = vfs_walk(root, p, flags);
     422        vfs_put(root);
     423        free(p);
     424        return rc;
     425}
     426
     427/** Lookup a path relative to the local root and open the result
     428 *
     429 * This function is a convenience combo for vfs_lookup() and vfs_open().
     430 *
     431 * @param path  Path to be looked up
     432 * @param flags Walk flags
     433 * @param mode  Mode in which to open file in
     434 *
     435 * @return      EOK on success or a negative error code
     436 */
     437int vfs_lookup_open(const char *path, int flags, int mode)
     438{
     439        int file = vfs_lookup(path, flags);
     440        if (file < 0)
     441                return file;
     442
     443        int rc = vfs_open(file, mode);
     444        if (rc != EOK) {
     445                vfs_put(file);
     446                return rc;
     447        }
     448       
     449        return file;
     450}
     451
    346452/** Mount a file system
    347453 *
     
    387493                return rc;
    388494        return rc1;
    389 }
    390 
    391 /** Unmount a file system
    392  *
    393  * @param mp    File handle representing the mount-point
    394  *
    395  * @return      EOK on success or a negative error code
    396  */
    397 int vfs_unmount(int mp)
    398 {
    399         async_exch_t *exch = vfs_exchange_begin();
    400         int rc = async_req_1_0(exch, VFS_IN_UNMOUNT, mp);
    401         vfs_exchange_end(exch);
    402         return rc;
    403495}
    404496
     
    501593}
    502594
    503 /** Unmount a file system
    504  *
    505  * @param mpp   Mount-point path
     595
     596/** Open a file handle for I/O
     597 *
     598 * @param file  File handle to enable I/O on
     599 * @param mode  Mode in which to open file in
    506600 *
    507601 * @return      EOK on success or a negative error code
    508602 */
    509 int vfs_unmount_path(const char *mpp)
    510 {
    511         int mp = vfs_lookup(mpp, WALK_MOUNT_POINT | WALK_DIRECTORY);
    512         if (mp < 0)
    513                 return mp;
    514        
    515         int rc = vfs_unmount(mp);
    516         vfs_put(mp);
    517         return rc;
     603int vfs_open(int file, int mode)
     604{
     605        async_exch_t *exch = vfs_exchange_begin();
     606        int rc = async_req_2_0(exch, VFS_IN_OPEN, file, mode);
     607        vfs_exchange_end(exch);
     608       
     609        return rc;
     610}
     611
     612/** Pass a file handle to another VFS client
     613 *
     614 * @param vfs_exch      Donor's VFS exchange
     615 * @param file          Donor's file handle to pass
     616 * @param exch          Exchange to the acceptor
     617 *
     618 * @return              EOK on success or a negative error code
     619 */
     620int vfs_pass_handle(async_exch_t *vfs_exch, int file, async_exch_t *exch)
     621{
     622        return async_state_change_start(exch, VFS_PASS_HANDLE, (sysarg_t) file,
     623            0, vfs_exch);
    518624}
    519625
     
    533639}
    534640
    535 /** Read bytes from a file
    536  *
    537  * Read up to @a nbyte bytes from file. The actual number of bytes read
    538  * may be lower, but greater than zero if there are any bytes available.
    539  * If there are no bytes available for reading, then the function will
    540  * return success with zero bytes read.
    541  *
    542  * @param file          File handle to read from
    543  * @param[in] pos       Position to read from
    544  * @param buf           Buffer to read from
    545  * @param nbyte         Maximum number of bytes to read
    546  * @param[out] nread    Actual number of bytes read (0 or more)
    547  *
    548  * @return              EOK on success or a negative error code
    549  */
    550 int vfs_read_short(int file, aoff64_t pos, void *buf, size_t nbyte,
    551     ssize_t *nread)
    552 {
    553         sysarg_t rc;
    554         ipc_call_t answer;
    555         aid_t req;
    556        
    557         if (nbyte > DATA_XFER_LIMIT)
    558                 nbyte = DATA_XFER_LIMIT;
    559        
    560         async_exch_t *exch = vfs_exchange_begin();
    561        
    562         req = async_send_3(exch, VFS_IN_READ, file, LOWER32(pos),
    563             UPPER32(pos), &answer);
    564         rc = async_data_read_start(exch, (void *) buf, nbyte);
    565 
    566         vfs_exchange_end(exch);
    567        
    568         if (rc == EOK)
    569                 async_wait_for(req, &rc);
    570         else
    571                 async_forget(req);
    572        
     641/** Receive a file handle from another VFS client
     642 *
     643 * @param high   If true, the received file handle will be allocated from high
     644 *               indices
     645 *
     646 * @return       EOK on success or a negative error code
     647 */
     648int vfs_receive_handle(bool high)
     649{
     650        ipc_callid_t callid;
     651        if (!async_state_change_receive(&callid, NULL, NULL, NULL)) {
     652                async_answer_0(callid, EINVAL);
     653                return EINVAL;
     654        }
     655
     656        async_exch_t *vfs_exch = vfs_exchange_begin();
     657
     658        async_state_change_finalize(callid, vfs_exch);
     659
     660        sysarg_t ret;
     661        sysarg_t rc = async_req_1_1(vfs_exch, VFS_IN_WAIT_HANDLE, high, &ret);
     662
     663        async_exchange_end(vfs_exch);
     664
    573665        if (rc != EOK)
    574666                return rc;
    575        
    576         *nread = (ssize_t) IPC_GET_ARG1(answer);
    577         return EOK;
    578 }
    579 
    580 /** Write bytes to a file
    581  *
    582  * Write up to @a nbyte bytes from file. The actual number of bytes written
    583  * may be lower, but greater than zero.
    584  *
    585  * @param file          File handle to write to
    586  * @param[in] pos       Position to write to
    587  * @param buf           Buffer to write to
    588  * @param nbyte         Maximum number of bytes to write
    589  * @param[out] nread    Actual number of bytes written (0 or more)
    590  *
    591  * @return              EOK on success or a negative error code
    592  */
    593 int vfs_write_short(int file, aoff64_t pos, const void *buf, size_t nbyte,
    594     ssize_t *nwritten)
    595 {
    596         sysarg_t rc;
    597         ipc_call_t answer;
    598         aid_t req;
    599        
    600         if (nbyte > DATA_XFER_LIMIT)
    601                 nbyte = DATA_XFER_LIMIT;
    602        
    603         async_exch_t *exch = vfs_exchange_begin();
    604        
    605         req = async_send_3(exch, VFS_IN_WRITE, file, LOWER32(pos),
    606             UPPER32(pos), &answer);
    607         rc = async_data_write_start(exch, (void *) buf, nbyte);
    608        
    609         vfs_exchange_end(exch);
    610        
    611         if (rc == EOK)
    612                 async_wait_for(req, &rc);
    613         else
    614                 async_forget(req);
    615 
    616         if (rc != EOK)
    617                 return rc;
    618        
    619         *nwritten = (ssize_t) IPC_GET_ARG1(answer);
    620         return EOK;
     667        return ret;
    621668}
    622669
     
    655702}
    656703
    657 /** Write data
    658  *
    659  * This function fails if it cannot write exactly @a len bytes to the file.
    660  *
    661  * @param file          File handle to write to
    662  * @param[inout] pos    Position to write to, updated by the actual bytes
    663  *                      written
    664  * @param buf           Data, @a nbytes bytes long
    665  * @param nbytes        Number of bytes to write
    666  *
    667  * @return              On success, non-negative number of bytes written
    668  * @return              On failure, a negative error code
    669  */
    670 ssize_t vfs_write(int file, aoff64_t *pos, const void *buf, size_t nbyte)
    671 {
    672         ssize_t cnt = 0;
    673         ssize_t nwritten = 0;
    674         const uint8_t *bp = (uint8_t *) buf;
    675         int rc;
    676 
    677         do {
    678                 bp += cnt;
    679                 nwritten += cnt;
    680                 *pos += cnt;
    681                 rc = vfs_write_short(file, *pos, bp, nbyte - nwritten, &cnt);
    682         } while (rc == EOK && ((ssize_t )nbyte - nwritten - cnt) > 0);
    683 
     704/** Read bytes from a file
     705 *
     706 * Read up to @a nbyte bytes from file. The actual number of bytes read
     707 * may be lower, but greater than zero if there are any bytes available.
     708 * If there are no bytes available for reading, then the function will
     709 * return success with zero bytes read.
     710 *
     711 * @param file          File handle to read from
     712 * @param[in] pos       Position to read from
     713 * @param buf           Buffer to read from
     714 * @param nbyte         Maximum number of bytes to read
     715 * @param[out] nread    Actual number of bytes read (0 or more)
     716 *
     717 * @return              EOK on success or a negative error code
     718 */
     719int vfs_read_short(int file, aoff64_t pos, void *buf, size_t nbyte,
     720    ssize_t *nread)
     721{
     722        sysarg_t rc;
     723        ipc_call_t answer;
     724        aid_t req;
     725       
     726        if (nbyte > DATA_XFER_LIMIT)
     727                nbyte = DATA_XFER_LIMIT;
     728       
     729        async_exch_t *exch = vfs_exchange_begin();
     730       
     731        req = async_send_3(exch, VFS_IN_READ, file, LOWER32(pos),
     732            UPPER32(pos), &answer);
     733        rc = async_data_read_start(exch, (void *) buf, nbyte);
     734
     735        vfs_exchange_end(exch);
     736       
     737        if (rc == EOK)
     738                async_wait_for(req, &rc);
     739        else
     740                async_forget(req);
     741       
    684742        if (rc != EOK)
    685743                return rc;
    686 
    687         *pos += cnt;
    688         return nbyte;
    689 }
    690 
    691 /** Synchronize file
    692  *
    693  * @param file  File handle to synchronize
     744       
     745        *nread = (ssize_t) IPC_GET_ARG1(answer);
     746        return EOK;
     747}
     748
     749/** Rename a file or directory
     750 *
     751 * There is no file-handle-based variant to disallow attempts to introduce loops
     752 * and breakage in the directory tree when relinking eg. a node under its own
     753 * descendant.  The path-based variant is not susceptible because the VFS can
     754 * prevent this lexically by comparing the paths.
     755 *
     756 * @param old   Old path
     757 * @param new   New path
    694758 *
    695759 * @return      EOK on success or a negative error code
    696760 */
    697 int vfs_sync(int file)
    698 {
    699         async_exch_t *exch = vfs_exchange_begin();
    700         int rc = async_req_1_0(exch, VFS_IN_SYNC, file);
    701         vfs_exchange_end(exch);
    702        
     761int vfs_rename_path(const char *old, const char *new)
     762{
     763        sysarg_t rc;
     764        sysarg_t rc_orig;
     765        aid_t req;
     766       
     767        size_t olda_size;
     768        char *olda = vfs_absolutize(old, &olda_size);
     769        if (olda == NULL)
     770                return ENOMEM;
     771
     772        size_t newa_size;
     773        char *newa = vfs_absolutize(new, &newa_size);
     774        if (newa == NULL) {
     775                free(olda);
     776                return ENOMEM;
     777        }
     778       
     779        async_exch_t *exch = vfs_exchange_begin();
     780        int root = vfs_root();
     781        if (root < 0) {
     782                free(olda);
     783                free(newa);
     784                return ENOENT;
     785        }
     786       
     787        req = async_send_1(exch, VFS_IN_RENAME, root, NULL);
     788        rc = async_data_write_start(exch, olda, olda_size);
     789        if (rc != EOK) {
     790                vfs_exchange_end(exch);
     791                free(olda);
     792                free(newa);
     793                vfs_put(root);
     794                async_wait_for(req, &rc_orig);
     795                if (rc_orig != EOK)
     796                        rc = rc_orig;
     797                return rc;
     798        }
     799        rc = async_data_write_start(exch, newa, newa_size);
     800        if (rc != EOK) {
     801                vfs_exchange_end(exch);
     802                free(olda);
     803                free(newa);
     804                vfs_put(root);
     805                async_wait_for(req, &rc_orig);
     806                if (rc_orig != EOK)
     807                        rc = rc_orig;
     808                return rc;
     809        }
     810        vfs_exchange_end(exch);
     811        free(olda);
     812        free(newa);
     813        vfs_put(root);
     814        async_wait_for(req, &rc);
     815
    703816        return rc;
    704817}
     
    721834       
    722835        return rc;
     836}
     837
     838/** Return a new file handle representing the local root
     839 *
     840 * @return      A clone of the local root file handle or a negative error code
     841 */
     842int vfs_root(void)
     843{
     844        fibril_mutex_lock(&root_mutex);
     845        int r;
     846        if (root_fd < 0)
     847                r = ENOENT;
     848        else
     849                r = vfs_clone(root_fd, -1, true);
     850        fibril_mutex_unlock(&root_mutex);
     851        return r;
     852}
     853
     854/** Set a new local root
     855 *
     856 * Note that it is still possible to have file handles for other roots and pass
     857 * them to the API functions. Functions like vfs_root() and vfs_lookup() will
     858 * however consider the file set by this function to be the root.
     859 *
     860 * @param nroot The new local root file handle
     861 */
     862void vfs_root_set(int nroot)
     863{
     864        fibril_mutex_lock(&root_mutex);
     865        if (root_fd >= 0)
     866                vfs_put(root_fd);
     867        root_fd = vfs_clone(nroot, -1, true);
     868        fibril_mutex_unlock(&root_mutex);
    723869}
    724870
     
    777923}
    778924
    779 static int get_parent_and_child(const char *path, char **child)
    780 {
    781         size_t size;
    782         char *apath = vfs_absolutize(path, &size);
    783         if (!apath)
    784                 return ENOMEM;
    785 
    786         char *slash = str_rchr(apath, L'/');
    787         int parent;
    788         if (slash == apath) {
    789                 parent = vfs_root();
    790                 *child = apath;
    791         } else {
    792                 *slash = '\0';
    793                 parent = vfs_lookup(apath, WALK_DIRECTORY);
    794                 if (parent < 0) {
    795                         free(apath);
    796                         return parent;
    797                 }
    798                 *slash = '/';
    799                 *child = str_dup(slash);
    800                 free(apath);
    801                 if (!*child) {
    802                         vfs_put(parent);
    803                         return ENOMEM;
    804                 }
    805         }
    806 
    807         return parent;
    808 }
    809 
    810 /** Link a file or directory
    811  *
    812  * Create a new name and an empty file or an empty directory in a parent
    813  * directory. If child with the same name already exists, the function returns
    814  * a failure, the existing file remains untouched and no file system object
    815  * is created.
    816  *
    817  * @param parent        File handle of the parent directory node
    818  * @param child         New name to be linked
    819  * @param kind          Kind of the object to be created: KIND_FILE or
    820  *                      KIND_DIRECTORY
     925/** Get filesystem statistics
     926 *
     927 * @param file          File located on the queried file system
     928 * @param[out] st       Buffer for storing information
     929 *
    821930 * @return              EOK on success or a negative error code
    822931 */
    823 int vfs_link(int parent, const char *child, vfs_file_kind_t kind)
    824 {
    825         int flags = (kind == KIND_DIRECTORY) ? WALK_DIRECTORY : WALK_REGULAR;
    826         int file = vfs_walk(parent, child, WALK_MUST_CREATE | flags);
    827 
     932int vfs_statfs(int file, struct statfs *st)
     933{
     934        sysarg_t rc, ret;
     935        aid_t req;
     936
     937        async_exch_t *exch = vfs_exchange_begin();
     938
     939        req = async_send_1(exch, VFS_IN_STATFS, file, NULL);
     940        rc = async_data_read_start(exch, (void *) st, sizeof(*st));
     941
     942        vfs_exchange_end(exch);
     943        async_wait_for(req, &ret);
     944
     945        rc = (ret != EOK ? ret : rc);
     946
     947        return rc;
     948}
     949
     950/** Get filesystem statistics
     951 *
     952 * @param file          Path pointing to the queried file system
     953 * @param[out] st       Buffer for storing information
     954 *
     955 * @return              EOK on success or a negative error code
     956 */
     957int vfs_statfs_path(const char *path, struct statfs *st)
     958{
     959        int file = vfs_lookup(path, 0);
    828960        if (file < 0)
    829961                return file;
     962       
     963        int rc = vfs_statfs(file, st);
    830964
    831965        vfs_put(file);
    832966
    833         return EOK;
    834 }
    835 
    836 /** Link a file or directory
    837  *
    838  * Create a new name and an empty file or an empty directory at given path.
    839  * If a link with the same name already exists, the function returns
    840  * a failure, the existing file remains untouched and no file system object
    841  * is created.
    842  *
    843  * @param path          New path to be linked
    844  * @param kind          Kind of the object to be created: KIND_FILE or
    845  *                      KIND_DIRECTORY
    846  * @return              EOK on success or a negative error code
    847  */
    848 int vfs_link_path(const char *path, vfs_file_kind_t kind)
    849 {
    850         char *child;
    851         int parent = get_parent_and_child(path, &child);
    852         if (parent < 0)
    853                 return parent;
    854 
    855         int rc = vfs_link(parent, child, kind);
    856 
    857         free(child);
    858         vfs_put(parent);
    859         return rc;
    860 }       
     967        return rc;
     968}
     969
     970/** Synchronize file
     971 *
     972 * @param file  File handle to synchronize
     973 *
     974 * @return      EOK on success or a negative error code
     975 */
     976int vfs_sync(int file)
     977{
     978        async_exch_t *exch = vfs_exchange_begin();
     979        int rc = async_req_1_0(exch, VFS_IN_SYNC, file);
     980        vfs_exchange_end(exch);
     981       
     982        return rc;
     983}
    861984
    862985/** Unlink a file or directory
     
    9231046}
    9241047
    925 /** Rename a file or directory
    926  *
    927  * There is no file-handle-based variant to disallow attempts to introduce loops
    928  * and breakage in the directory tree when relinking eg. a node under its own
    929  * descendant.  The path-based variant is not susceptible because the VFS can
    930  * prevent this lexically by comparing the paths.
    931  *
    932  * @param old   Old path
    933  * @param new   New path
     1048/** Unmount a file system
     1049 *
     1050 * @param mp    File handle representing the mount-point
    9341051 *
    9351052 * @return      EOK on success or a negative error code
    9361053 */
    937 int vfs_rename_path(const char *old, const char *new)
    938 {
    939         sysarg_t rc;
     1054int vfs_unmount(int mp)
     1055{
     1056        async_exch_t *exch = vfs_exchange_begin();
     1057        int rc = async_req_1_0(exch, VFS_IN_UNMOUNT, mp);
     1058        vfs_exchange_end(exch);
     1059        return rc;
     1060}
     1061
     1062/** Unmount a file system
     1063 *
     1064 * @param mpp   Mount-point path
     1065 *
     1066 * @return      EOK on success or a negative error code
     1067 */
     1068int vfs_unmount_path(const char *mpp)
     1069{
     1070        int mp = vfs_lookup(mpp, WALK_MOUNT_POINT | WALK_DIRECTORY);
     1071        if (mp < 0)
     1072                return mp;
     1073       
     1074        int rc = vfs_unmount(mp);
     1075        vfs_put(mp);
     1076        return rc;
     1077}
     1078
     1079/** Walk a path starting in a parent node
     1080 *
     1081 * @param parent        File handle of the parent node where the walk starts
     1082 * @param path          Parent-relative path to be walked
     1083 * @param flags         Flags influencing the walk
     1084 *
     1085 * @retrun              File handle representing the result on success or
     1086 *                      a negative error code on error
     1087 */
     1088int vfs_walk(int parent, const char *path, int flags)
     1089{
     1090        async_exch_t *exch = vfs_exchange_begin();
     1091       
     1092        ipc_call_t answer;
     1093        aid_t req = async_send_2(exch, VFS_IN_WALK, parent, flags, &answer);
     1094        sysarg_t rc = async_data_write_start(exch, path, str_size(path));
     1095        vfs_exchange_end(exch);
     1096               
    9401097        sysarg_t rc_orig;
    941         aid_t req;
    942        
    943         size_t olda_size;
    944         char *olda = vfs_absolutize(old, &olda_size);
    945         if (olda == NULL)
    946                 return ENOMEM;
    947 
    948         size_t newa_size;
    949         char *newa = vfs_absolutize(new, &newa_size);
    950         if (newa == NULL) {
    951                 free(olda);
    952                 return ENOMEM;
    953         }
    954        
    955         async_exch_t *exch = vfs_exchange_begin();
    956         int root = vfs_root();
    957         if (root < 0) {
    958                 free(olda);
    959                 free(newa);
    960                 return ENOENT;
    961         }
    962        
    963         req = async_send_1(exch, VFS_IN_RENAME, root, NULL);
    964         rc = async_data_write_start(exch, olda, olda_size);
    965         if (rc != EOK) {
    966                 vfs_exchange_end(exch);
    967                 free(olda);
    968                 free(newa);
    969                 vfs_put(root);
    970                 async_wait_for(req, &rc_orig);
    971                 if (rc_orig != EOK)
    972                         rc = rc_orig;
    973                 return rc;
    974         }
    975         rc = async_data_write_start(exch, newa, newa_size);
    976         if (rc != EOK) {
    977                 vfs_exchange_end(exch);
    978                 free(olda);
    979                 free(newa);
    980                 vfs_put(root);
    981                 async_wait_for(req, &rc_orig);
    982                 if (rc_orig != EOK)
    983                         rc = rc_orig;
    984                 return rc;
    985         }
    986         vfs_exchange_end(exch);
    987         free(olda);
    988         free(newa);
    989         vfs_put(root);
    990         async_wait_for(req, &rc);
    991 
    992         return rc;
    993 }
    994 
    995 /** Change working directory
    996  *
    997  * @param path  Path of the new working directory
    998  *
    999  * @return      EOK on success or a negative error code
    1000  */
    1001 int vfs_cwd_set(const char *path)
    1002 {
    1003         size_t abs_size;
    1004         char *abs = vfs_absolutize(path, &abs_size);
    1005         if (!abs)
    1006                 return ENOMEM;
    1007        
    1008         int fd = vfs_lookup(abs, WALK_DIRECTORY);
    1009         if (fd < 0) {
    1010                 free(abs);
    1011                 return fd;
    1012         }
    1013        
    1014         fibril_mutex_lock(&cwd_mutex);
    1015        
    1016         if (cwd_fd >= 0)
    1017                 vfs_put(cwd_fd);
    1018        
    1019         if (cwd_path)
    1020                 free(cwd_path);
    1021        
    1022         cwd_fd = fd;
    1023         cwd_path = abs;
    1024         cwd_size = abs_size;
    1025        
    1026         fibril_mutex_unlock(&cwd_mutex);
    1027         return EOK;
    1028 }
    1029 
    1030 /** Get current working directory path
    1031  *
    1032  * @param[out] buf      Buffer
    1033  * @param size          Size of @a buf
    1034  *
    1035  * @return              EOK on success or a non-negative error code
    1036  */
    1037 int vfs_cwd_get(char *buf, size_t size)
    1038 {
    1039         fibril_mutex_lock(&cwd_mutex);
    1040        
    1041         if ((cwd_size == 0) || (size < cwd_size + 1)) {
    1042                 fibril_mutex_unlock(&cwd_mutex);
    1043                 return ERANGE;
    1044         }
    1045        
    1046         str_cpy(buf, size, cwd_path);
    1047         fibril_mutex_unlock(&cwd_mutex);
    1048        
    1049         return EOK;
    1050 }
    1051 
    1052 /** Open session to service represented by a special file
    1053  *
    1054  * Given that the file referred to by @a file represents a service,
    1055  * open a session to that service.
    1056  *
    1057  * @param file  File handle representing a service
    1058  * @param iface Interface to connect to (XXX Should be automatic)
    1059  *
    1060  * @return      Session pointer on success.
    1061  * @return      @c NULL or error.
    1062  */
    1063 async_sess_t *vfs_fd_session(int file, iface_t iface)
    1064 {
    1065         struct stat stat;
    1066         int rc = vfs_stat(file, &stat);
    1067         if (rc != 0)
    1068                 return NULL;
    1069        
    1070         if (stat.service == 0)
    1071                 return NULL;
    1072        
    1073         return loc_service_connect(stat.service, iface, 0);
    1074 }
    1075 
    1076 /** Get filesystem statistics
    1077  *
    1078  * @param file          File located on the queried file system
    1079  * @param[out] st       Buffer for storing information
    1080  *
    1081  * @return              EOK on success or a negative error code
    1082  */
    1083 int vfs_statfs(int file, struct statfs *st)
    1084 {
    1085         sysarg_t rc, ret;
    1086         aid_t req;
    1087 
    1088         async_exch_t *exch = vfs_exchange_begin();
    1089 
    1090         req = async_send_1(exch, VFS_IN_STATFS, file, NULL);
    1091         rc = async_data_read_start(exch, (void *) st, sizeof(*st));
    1092 
    1093         vfs_exchange_end(exch);
    1094         async_wait_for(req, &ret);
    1095 
    1096         rc = (ret != EOK ? ret : rc);
    1097 
    1098         return rc;
    1099 }
    1100 
    1101 /** Get filesystem statistics
    1102  *
    1103  * @param file          Path pointing to the queried file system
    1104  * @param[out] st       Buffer for storing information
    1105  *
    1106  * @return              EOK on success or a negative error code
    1107  */
    1108 int vfs_statfs_path(const char *path, struct statfs *st)
    1109 {
    1110         int file = vfs_lookup(path, 0);
    1111         if (file < 0)
    1112                 return file;
    1113        
    1114         int rc = vfs_statfs(file, st);
    1115 
    1116         vfs_put(file);
    1117 
    1118         return rc;
    1119 }
    1120 
    1121 /** Pass a file handle to another VFS client
    1122  *
    1123  * @param vfs_exch      Donor's VFS exchange
    1124  * @param file          Donor's file handle to pass
    1125  * @param exch          Exchange to the acceptor
    1126  *
    1127  * @return              EOK on success or a negative error code
    1128  */
    1129 int vfs_pass_handle(async_exch_t *vfs_exch, int file, async_exch_t *exch)
    1130 {
    1131         return async_state_change_start(exch, VFS_PASS_HANDLE, (sysarg_t) file,
    1132             0, vfs_exch);
    1133 }
    1134 
    1135 /** Receive a file handle from another VFS client
    1136  *
    1137  * @param high   If true, the received file handle will be allocated from high
    1138  *               indices
    1139  *
    1140  * @return       EOK on success or a negative error code
    1141  */
    1142 int vfs_receive_handle(bool high)
    1143 {
    1144         ipc_callid_t callid;
    1145         if (!async_state_change_receive(&callid, NULL, NULL, NULL)) {
    1146                 async_answer_0(callid, EINVAL);
    1147                 return EINVAL;
    1148         }
    1149 
    1150         async_exch_t *vfs_exch = vfs_exchange_begin();
    1151 
    1152         async_state_change_finalize(callid, vfs_exch);
    1153 
    1154         sysarg_t ret;
    1155         sysarg_t rc = async_req_1_1(vfs_exch, VFS_IN_WAIT_HANDLE, high, &ret);
    1156 
    1157         async_exchange_end(vfs_exch);
     1098        async_wait_for(req, &rc_orig);
     1099
     1100        if (rc_orig != EOK)
     1101                return (int) rc_orig;
     1102               
     1103        if (rc != EOK)
     1104                return (int) rc;
     1105       
     1106        return (int) IPC_GET_ARG1(answer);
     1107}
     1108
     1109/** Write data
     1110 *
     1111 * This function fails if it cannot write exactly @a len bytes to the file.
     1112 *
     1113 * @param file          File handle to write to
     1114 * @param[inout] pos    Position to write to, updated by the actual bytes
     1115 *                      written
     1116 * @param buf           Data, @a nbytes bytes long
     1117 * @param nbytes        Number of bytes to write
     1118 *
     1119 * @return              On success, non-negative number of bytes written
     1120 * @return              On failure, a negative error code
     1121 */
     1122ssize_t vfs_write(int file, aoff64_t *pos, const void *buf, size_t nbyte)
     1123{
     1124        ssize_t cnt = 0;
     1125        ssize_t nwritten = 0;
     1126        const uint8_t *bp = (uint8_t *) buf;
     1127        int rc;
     1128
     1129        do {
     1130                bp += cnt;
     1131                nwritten += cnt;
     1132                *pos += cnt;
     1133                rc = vfs_write_short(file, *pos, bp, nbyte - nwritten, &cnt);
     1134        } while (rc == EOK && ((ssize_t )nbyte - nwritten - cnt) > 0);
    11581135
    11591136        if (rc != EOK)
    11601137                return rc;
    1161         return ret;
    1162 }
    1163 
    1164 /** Clone a file handle
    1165  *
    1166  * The caller can choose whether to clone an existing file handle into another
    1167  * already existing file handle (in which case it is first closed) or to a new
    1168  * file handle allocated either from low or high indices.
    1169  *
    1170  * @param file_from     Source file handle
    1171  * @param file_to       Destination file handle or -1
    1172  * @param high          If file_to is -1, high controls whether the new file
    1173  *                      handle will be allocated from high indices
    1174  *
    1175  * @return              New file handle on success or a negative error code
    1176  */
    1177 int vfs_clone(int file_from, int file_to, bool high)
    1178 {
    1179         async_exch_t *vfs_exch = vfs_exchange_begin();
    1180         int rc = async_req_3_0(vfs_exch, VFS_IN_CLONE, (sysarg_t) file_from,
    1181             (sysarg_t) file_to, (sysarg_t) high);
    1182         vfs_exchange_end(vfs_exch);
    1183         return rc;
     1138
     1139        *pos += cnt;
     1140        return nbyte;
     1141}
     1142
     1143/** Write bytes to a file
     1144 *
     1145 * Write up to @a nbyte bytes from file. The actual number of bytes written
     1146 * may be lower, but greater than zero.
     1147 *
     1148 * @param file          File handle to write to
     1149 * @param[in] pos       Position to write to
     1150 * @param buf           Buffer to write to
     1151 * @param nbyte         Maximum number of bytes to write
     1152 * @param[out] nread    Actual number of bytes written (0 or more)
     1153 *
     1154 * @return              EOK on success or a negative error code
     1155 */
     1156int vfs_write_short(int file, aoff64_t pos, const void *buf, size_t nbyte,
     1157    ssize_t *nwritten)
     1158{
     1159        sysarg_t rc;
     1160        ipc_call_t answer;
     1161        aid_t req;
     1162       
     1163        if (nbyte > DATA_XFER_LIMIT)
     1164                nbyte = DATA_XFER_LIMIT;
     1165       
     1166        async_exch_t *exch = vfs_exchange_begin();
     1167       
     1168        req = async_send_3(exch, VFS_IN_WRITE, file, LOWER32(pos),
     1169            UPPER32(pos), &answer);
     1170        rc = async_data_write_start(exch, (void *) buf, nbyte);
     1171       
     1172        vfs_exchange_end(exch);
     1173       
     1174        if (rc == EOK)
     1175                async_wait_for(req, &rc);
     1176        else
     1177                async_forget(req);
     1178
     1179        if (rc != EOK)
     1180                return rc;
     1181       
     1182        *nwritten = (ssize_t) IPC_GET_ARG1(answer);
     1183        return EOK;
    11841184}
    11851185
  • uspace/lib/c/include/vfs/vfs.h

    rca7506f r3ba431a  
    7373};
    7474
    75 extern char *vfs_absolutize(const char *, size_t *);
    76 extern int vfs_cwd_set(const char *path);
    77 extern int vfs_cwd_get(char *path, size_t);
    78 
    7975extern int vfs_fhandle(FILE *, int *);
    8076
     77extern char *vfs_absolutize(const char *, size_t *);
     78extern int vfs_clone(int, int, bool);
     79extern int vfs_cwd_get(char *path, size_t);
     80extern int vfs_cwd_set(const char *path);
    8181extern async_exch_t *vfs_exchange_begin(void);
    8282extern void vfs_exchange_end(async_exch_t *);
    83 
    84 extern int vfs_pass_handle(async_exch_t *, int, async_exch_t *);
    85 extern int vfs_receive_handle(bool);
    86 
    87 extern int vfs_clone(int, int, bool);
    8883extern int vfs_link(int, const char *, vfs_file_kind_t);
    8984extern int vfs_link_path(const char *, vfs_file_kind_t);
     
    9590    unsigned, int *);
    9691extern int vfs_open(int, int);
     92extern int vfs_pass_handle(async_exch_t *, int, async_exch_t *);
    9793extern int vfs_put(int);
     94extern ssize_t vfs_read(int, aoff64_t *, void *, size_t);
    9895extern int vfs_read_short(int, aoff64_t, void *, size_t, ssize_t *);
    99 extern ssize_t vfs_read(int, aoff64_t *, void *, size_t);
     96extern int vfs_receive_handle(bool);
    10097extern int vfs_rename_path(const char *, const char *);
    10198extern int vfs_resize(int, aoff64_t);
     
    112109extern int vfs_unmount_path(const char *);
    113110extern int vfs_walk(int, const char *, int);
     111extern ssize_t vfs_write(int, aoff64_t *, const void *, size_t);
    114112extern int vfs_write_short(int, aoff64_t, const void *, size_t, ssize_t *);
    115 extern ssize_t vfs_write(int, aoff64_t *, const void *, size_t);
    116113
    117114#endif
Note: See TracChangeset for help on using the changeset viewer.