source: mainline/uspace/lib/c/generic/vfs/vfs.c@ 5a324d99

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 5a324d99 was 73fbcbb, checked in by Maurizio Lombardi <m.lombardi85@…>, 12 years ago

cstyle

  • Property mode set to 100644
File size: 18.2 KB
RevLine 
[2f02aa17]1/*
[64d2b10]2 * Copyright (c) 2008 Jakub Jermar
[2f02aa17]3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libc
30 * @{
31 */
32/** @file
33 */
[19b28b0]34
[5fec355]35#include <vfs/canonify.h>
[79ae36dd]36#include <vfs/vfs.h>
37#include <vfs/vfs_sess.h>
[ed903174]38#include <macros.h>
[d0dc74ae]39#include <stdlib.h>
[449c246]40#include <unistd.h>
[d0dc74ae]41#include <dirent.h>
[449c246]42#include <fcntl.h>
[923c39e]43#include <stdio.h>
[852b801]44#include <sys/stat.h>
[9dc6083]45#include <sys/statfs.h>
[72bde81]46#include <sys/types.h>
[2f02aa17]47#include <ipc/services.h>
[79ae36dd]48#include <ns.h>
[2f02aa17]49#include <async.h>
[a28ab12]50#include <fibril_synch.h>
[2f02aa17]51#include <errno.h>
[a28ab12]52#include <assert.h>
[19f857a]53#include <str.h>
[15f3c3f]54#include <loc.h>
[2595dab]55#include <ipc/vfs.h>
[15f3c3f]56#include <ipc/loc.h>
[2f02aa17]57
[79ae36dd]58static FIBRIL_MUTEX_INITIALIZE(vfs_mutex);
59static async_sess_t *vfs_sess = NULL;
[a28ab12]60
61static FIBRIL_MUTEX_INITIALIZE(cwd_mutex);
[5fec355]62
[2b88074b]63static int cwd_fd = -1;
64static char *cwd_path = NULL;
65static size_t cwd_size = 0;
[5fec355]66
[79ae36dd]67/** Start an async exchange on the VFS session.
68 *
69 * @return New exchange.
70 *
71 */
[866e627]72async_exch_t *vfs_exchange_begin(void)
[79ae36dd]73{
74 fibril_mutex_lock(&vfs_mutex);
75
76 while (vfs_sess == NULL)
77 vfs_sess = service_connect_blocking(EXCHANGE_PARALLEL, SERVICE_VFS,
78 0, 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 */
[866e627]90void vfs_exchange_end(async_exch_t *exch)
[79ae36dd]91{
92 async_exchange_end(exch);
93}
94
[17b2aac]95char *absolutize(const char *path, size_t *retlen)
[5fec355]96{
97 char *ncwd_path;
[34a74ab]98 char *ncwd_path_nc;
[5fec355]99
[a28ab12]100 fibril_mutex_lock(&cwd_mutex);
[9eb3623]101 size_t size = str_size(path);
[5fec355]102 if (*path != '/') {
103 if (!cwd_path) {
[a28ab12]104 fibril_mutex_unlock(&cwd_mutex);
[5fec355]105 return NULL;
106 }
[79ae36dd]107 ncwd_path_nc = malloc(cwd_size + 1 + size + 1);
[34a74ab]108 if (!ncwd_path_nc) {
[a28ab12]109 fibril_mutex_unlock(&cwd_mutex);
[5fec355]110 return NULL;
111 }
[79ae36dd]112 str_cpy(ncwd_path_nc, cwd_size + 1 + size + 1, cwd_path);
[9eb3623]113 ncwd_path_nc[cwd_size] = '/';
114 ncwd_path_nc[cwd_size + 1] = '\0';
[5fec355]115 } else {
[79ae36dd]116 ncwd_path_nc = malloc(size + 1);
[34a74ab]117 if (!ncwd_path_nc) {
[a28ab12]118 fibril_mutex_unlock(&cwd_mutex);
[5fec355]119 return NULL;
120 }
[34a74ab]121 ncwd_path_nc[0] = '\0';
[5fec355]122 }
[79ae36dd]123 str_append(ncwd_path_nc, cwd_size + 1 + size + 1, path);
[34a74ab]124 ncwd_path = canonify(ncwd_path_nc, retlen);
125 if (!ncwd_path) {
[a28ab12]126 fibril_mutex_unlock(&cwd_mutex);
[34a74ab]127 free(ncwd_path_nc);
128 return NULL;
129 }
130 /*
131 * We need to clone ncwd_path because canonify() works in-place and thus
132 * the address in ncwd_path need not be the same as ncwd_path_nc, even
133 * though they both point into the same dynamically allocated buffer.
134 */
[095003a8]135 ncwd_path = str_dup(ncwd_path);
[34a74ab]136 free(ncwd_path_nc);
137 if (!ncwd_path) {
[a28ab12]138 fibril_mutex_unlock(&cwd_mutex);
[923c39e]139 return NULL;
140 }
[a28ab12]141 fibril_mutex_unlock(&cwd_mutex);
[5fec355]142 return ncwd_path;
143}
[2f02aa17]144
[15f3c3f]145int mount(const char *fs_name, const char *mp, const char *fqsn,
[4979403]146 const char *opts, unsigned int flags, unsigned int instance)
[2f02aa17]147{
[210e50a]148 int null_id = -1;
[15f3c3f]149 char null[LOC_NAME_MAXLEN];
[210e50a]150
[15f3c3f]151 if (str_cmp(fqsn, "") == 0) {
[210e50a]152 /* No device specified, create a fresh
153 null/%d device instead */
[15f3c3f]154 null_id = loc_null_create();
[210e50a]155
156 if (null_id == -1)
157 return ENOMEM;
158
[15f3c3f]159 snprintf(null, LOC_NAME_MAXLEN, "null/%d", null_id);
160 fqsn = null;
[210e50a]161 }
[82405266]162
[15f3c3f]163 service_id_t service_id;
164 int res = loc_service_get_id(fqsn, &service_id, flags);
[210e50a]165 if (res != EOK) {
166 if (null_id != -1)
[15f3c3f]167 loc_null_destroy(null_id);
[210e50a]168
[82405266]169 return res;
[210e50a]170 }
[82405266]171
[9eb3623]172 size_t mpa_size;
173 char *mpa = absolutize(mp, &mpa_size);
[210e50a]174 if (!mpa) {
175 if (null_id != -1)
[15f3c3f]176 loc_null_destroy(null_id);
[210e50a]177
[5fec355]178 return ENOMEM;
[210e50a]179 }
[19b28b0]180
[79ae36dd]181 async_exch_t *exch = vfs_exchange_begin();
[a28ab12]182
[96b02eb9]183 sysarg_t rc_orig;
[4979403]184 aid_t req = async_send_3(exch, VFS_IN_MOUNT, service_id, flags,
[286286c]185 instance, NULL);
[79ae36dd]186 sysarg_t rc = async_data_write_start(exch, (void *) mpa, mpa_size);
[12fc042]187 if (rc != EOK) {
[79ae36dd]188 vfs_exchange_end(exch);
[12fc042]189 free(mpa);
[a28ab12]190 async_wait_for(req, &rc_orig);
[210e50a]191
192 if (null_id != -1)
[15f3c3f]193 loc_null_destroy(null_id);
[210e50a]194
[3734106]195 if (rc_orig == EOK)
196 return (int) rc;
197 else
198 return (int) rc_orig;
[12fc042]199 }
[19b28b0]200
[79ae36dd]201 rc = async_data_write_start(exch, (void *) opts, str_size(opts));
[594303b]202 if (rc != EOK) {
[79ae36dd]203 vfs_exchange_end(exch);
[594303b]204 free(mpa);
[a28ab12]205 async_wait_for(req, &rc_orig);
[210e50a]206
207 if (null_id != -1)
[15f3c3f]208 loc_null_destroy(null_id);
[210e50a]209
[3734106]210 if (rc_orig == EOK)
211 return (int) rc;
212 else
213 return (int) rc_orig;
[594303b]214 }
[210e50a]215
[79ae36dd]216 rc = async_data_write_start(exch, (void *) fs_name, str_size(fs_name));
[2f02aa17]217 if (rc != EOK) {
[79ae36dd]218 vfs_exchange_end(exch);
[5fec355]219 free(mpa);
[a28ab12]220 async_wait_for(req, &rc_orig);
[210e50a]221
222 if (null_id != -1)
[15f3c3f]223 loc_null_destroy(null_id);
[210e50a]224
[3734106]225 if (rc_orig == EOK)
226 return (int) rc;
227 else
228 return (int) rc_orig;
[2f02aa17]229 }
[210e50a]230
[c08c355]231 /* Ask VFS whether it likes fs_name. */
[79ae36dd]232 rc = async_req_0_0(exch, VFS_IN_PING);
[c08c355]233 if (rc != EOK) {
[79ae36dd]234 vfs_exchange_end(exch);
[c08c355]235 free(mpa);
[a28ab12]236 async_wait_for(req, &rc_orig);
[210e50a]237
238 if (null_id != -1)
[15f3c3f]239 loc_null_destroy(null_id);
[210e50a]240
[3734106]241 if (rc_orig == EOK)
242 return (int) rc;
243 else
244 return (int) rc_orig;
[c08c355]245 }
[19b28b0]246
[79ae36dd]247 vfs_exchange_end(exch);
[5fec355]248 free(mpa);
[a28ab12]249 async_wait_for(req, &rc);
[19b28b0]250
[210e50a]251 if ((rc != EOK) && (null_id != -1))
[15f3c3f]252 loc_null_destroy(null_id);
[210e50a]253
[2f02aa17]254 return (int) rc;
255}
256
[21f32ee1]257int unmount(const char *mp)
258{
[96b02eb9]259 sysarg_t rc;
260 sysarg_t rc_orig;
[b9067dfa]261 aid_t req;
262 size_t mpa_size;
263 char *mpa;
264
265 mpa = absolutize(mp, &mpa_size);
266 if (!mpa)
267 return ENOMEM;
268
[79ae36dd]269 async_exch_t *exch = vfs_exchange_begin();
[b9067dfa]270
[79ae36dd]271 req = async_send_0(exch, VFS_IN_UNMOUNT, NULL);
272 rc = async_data_write_start(exch, (void *) mpa, mpa_size);
[b9067dfa]273 if (rc != EOK) {
[79ae36dd]274 vfs_exchange_end(exch);
[b9067dfa]275 free(mpa);
[a28ab12]276 async_wait_for(req, &rc_orig);
[b9067dfa]277 if (rc_orig == EOK)
278 return (int) rc;
279 else
280 return (int) rc_orig;
281 }
282
283
[79ae36dd]284 vfs_exchange_end(exch);
[b9067dfa]285 free(mpa);
[a28ab12]286 async_wait_for(req, &rc);
[b9067dfa]287
288 return (int) rc;
[21f32ee1]289}
290
[2b88074b]291static int open_internal(const char *abs, size_t abs_size, int lflag, int oflag)
[2f02aa17]292{
[79ae36dd]293 async_exch_t *exch = vfs_exchange_begin();
[19b28b0]294
[2b88074b]295 ipc_call_t answer;
[79ae36dd]296 aid_t req = async_send_3(exch, VFS_IN_OPEN, lflag, oflag, 0, &answer);
297 sysarg_t rc = async_data_write_start(exch, abs, abs_size);
[2b88074b]298
[2f02aa17]299 if (rc != EOK) {
[79ae36dd]300 vfs_exchange_end(exch);
[a28ab12]301
[96b02eb9]302 sysarg_t rc_orig;
[3734106]303 async_wait_for(req, &rc_orig);
[2b88074b]304
[3734106]305 if (rc_orig == EOK)
306 return (int) rc;
307 else
308 return (int) rc_orig;
[2f02aa17]309 }
[2b88074b]310
[79ae36dd]311 vfs_exchange_end(exch);
[2f02aa17]312 async_wait_for(req, &rc);
[2595dab]313
[57b4f46]314 if (rc != EOK)
315 return (int) rc;
[2595dab]316
[2f02aa17]317 return (int) IPC_GET_ARG1(answer);
318}
319
[ae78b530]320int open(const char *path, int oflag, ...)
321{
[2b88074b]322 size_t abs_size;
323 char *abs = absolutize(path, &abs_size);
324 if (!abs)
325 return ENOMEM;
326
327 int ret = open_internal(abs, abs_size, L_FILE, oflag);
328 free(abs);
329
330 return ret;
[ae78b530]331}
332
[72bde81]333int close(int fildes)
334{
[96b02eb9]335 sysarg_t rc;
[19b28b0]336
[79ae36dd]337 async_exch_t *exch = vfs_exchange_begin();
338 rc = async_req_1_0(exch, VFS_IN_CLOSE, fildes);
339 vfs_exchange_end(exch);
[19b28b0]340
[79ae36dd]341 return (int) rc;
[72bde81]342}
343
[2f02aa17]344ssize_t read(int fildes, void *buf, size_t nbyte)
345{
[96b02eb9]346 sysarg_t rc;
[2f02aa17]347 ipc_call_t answer;
348 aid_t req;
[19b28b0]349
[79ae36dd]350 async_exch_t *exch = vfs_exchange_begin();
351
352 req = async_send_1(exch, VFS_IN_READ, fildes, &answer);
353 rc = async_data_read_start(exch, (void *)buf, nbyte);
[07e01e6]354 if (rc != EOK) {
[79ae36dd]355 vfs_exchange_end(exch);
[a28ab12]356
[96b02eb9]357 sysarg_t rc_orig;
[3734106]358 async_wait_for(req, &rc_orig);
[a28ab12]359
[3734106]360 if (rc_orig == EOK)
361 return (ssize_t) rc;
362 else
363 return (ssize_t) rc_orig;
[2f02aa17]364 }
[79ae36dd]365 vfs_exchange_end(exch);
[2f02aa17]366 async_wait_for(req, &rc);
[f7017572]367 if (rc == EOK)
368 return (ssize_t) IPC_GET_ARG1(answer);
369 else
[25becee8]370 return rc;
[2f02aa17]371}
372
[449c246]373ssize_t write(int fildes, const void *buf, size_t nbyte)
374{
[96b02eb9]375 sysarg_t rc;
[449c246]376 ipc_call_t answer;
377 aid_t req;
[19b28b0]378
[79ae36dd]379 async_exch_t *exch = vfs_exchange_begin();
380
381 req = async_send_1(exch, VFS_IN_WRITE, fildes, &answer);
382 rc = async_data_write_start(exch, (void *)buf, nbyte);
[07e01e6]383 if (rc != EOK) {
[79ae36dd]384 vfs_exchange_end(exch);
[a28ab12]385
[96b02eb9]386 sysarg_t rc_orig;
[3734106]387 async_wait_for(req, &rc_orig);
[a28ab12]388
[3734106]389 if (rc_orig == EOK)
390 return (ssize_t) rc;
391 else
392 return (ssize_t) rc_orig;
[449c246]393 }
[79ae36dd]394 vfs_exchange_end(exch);
[449c246]395 async_wait_for(req, &rc);
[f7017572]396 if (rc == EOK)
397 return (ssize_t) IPC_GET_ARG1(answer);
398 else
399 return -1;
[449c246]400}
[222e57c]401
[8fd04ba9]402/** Read entire buffer.
403 *
404 * In face of short reads this function continues reading until either
405 * the entire buffer is read or no more data is available (at end of file).
406 *
407 * @param fildes File descriptor
408 * @param buf Buffer, @a nbytes bytes long
409 * @param nbytes Number of bytes to read
410 *
411 * @return On success, positive number of bytes read.
412 * On failure, negative error code from read().
413 */
414ssize_t read_all(int fildes, void *buf, size_t nbyte)
415{
416 ssize_t cnt = 0;
417 size_t nread = 0;
418 uint8_t *bp = (uint8_t *) buf;
419
420 do {
421 bp += cnt;
422 nread += cnt;
423 cnt = read(fildes, bp, nbyte - nread);
424 } while (cnt > 0 && (nbyte - nread - cnt) > 0);
425
426 if (cnt < 0)
427 return cnt;
428
429 return nread + cnt;
430}
431
432/** Write entire buffer.
433 *
434 * This function fails if it cannot write exactly @a len bytes to the file.
435 *
436 * @param fildes File descriptor
437 * @param buf Data, @a nbytes bytes long
438 * @param nbytes Number of bytes to write
439 *
440 * @return EOK on error, return value from write() if writing
441 * failed.
442 */
443ssize_t write_all(int fildes, const void *buf, size_t nbyte)
444{
445 ssize_t cnt = 0;
446 ssize_t nwritten = 0;
447 const uint8_t *bp = (uint8_t *) buf;
448
449 do {
450 bp += cnt;
451 nwritten += cnt;
452 cnt = write(fildes, bp, nbyte - nwritten);
453 } while (cnt > 0 && ((ssize_t )nbyte - nwritten - cnt) > 0);
454
455 if (cnt < 0)
456 return cnt;
457
458 if ((ssize_t)nbyte - nwritten - cnt > 0)
459 return EIO;
460
461 return nbyte;
462}
463
[2595dab]464int fsync(int fildes)
465{
[79ae36dd]466 async_exch_t *exch = vfs_exchange_begin();
467 sysarg_t rc = async_req_1_0(exch, VFS_IN_SYNC, fildes);
468 vfs_exchange_end(exch);
[2595dab]469
470 return (int) rc;
471}
472
[ed903174]473off64_t lseek(int fildes, off64_t offset, int whence)
[222e57c]474{
[79ae36dd]475 async_exch_t *exch = vfs_exchange_begin();
[19b28b0]476
[96b02eb9]477 sysarg_t newoff_lo;
478 sysarg_t newoff_hi;
[79ae36dd]479 sysarg_t rc = async_req_4_2(exch, VFS_IN_SEEK, fildes,
[ed903174]480 LOWER32(offset), UPPER32(offset), whence,
481 &newoff_lo, &newoff_hi);
482
[79ae36dd]483 vfs_exchange_end(exch);
[ed903174]484
[222e57c]485 if (rc != EOK)
[ed903174]486 return (off64_t) -1;
[222e57c]487
[ed903174]488 return (off64_t) MERGE_LOUP32(newoff_lo, newoff_hi);
[222e57c]489}
490
[ed903174]491int ftruncate(int fildes, aoff64_t length)
[0ee4322]492{
[96b02eb9]493 sysarg_t rc;
[0ee4322]494
[79ae36dd]495 async_exch_t *exch = vfs_exchange_begin();
496 rc = async_req_3_0(exch, VFS_IN_TRUNCATE, fildes,
[ed903174]497 LOWER32(length), UPPER32(length));
[79ae36dd]498 vfs_exchange_end(exch);
[ed903174]499
[0ee4322]500 return (int) rc;
501}
502
[852b801]503int fstat(int fildes, struct stat *stat)
504{
[96b02eb9]505 sysarg_t rc;
[852b801]506 aid_t req;
507
[79ae36dd]508 async_exch_t *exch = vfs_exchange_begin();
509
510 req = async_send_1(exch, VFS_IN_FSTAT, fildes, NULL);
511 rc = async_data_read_start(exch, (void *) stat, sizeof(struct stat));
[852b801]512 if (rc != EOK) {
[79ae36dd]513 vfs_exchange_end(exch);
[a28ab12]514
[96b02eb9]515 sysarg_t rc_orig;
[3734106]516 async_wait_for(req, &rc_orig);
[a28ab12]517
[3734106]518 if (rc_orig == EOK)
519 return (ssize_t) rc;
520 else
521 return (ssize_t) rc_orig;
[852b801]522 }
[79ae36dd]523 vfs_exchange_end(exch);
[852b801]524 async_wait_for(req, &rc);
525
526 return rc;
527}
528
[415c7e0d]529int stat(const char *path, struct stat *stat)
530{
[96b02eb9]531 sysarg_t rc;
532 sysarg_t rc_orig;
[415c7e0d]533 aid_t req;
534
535 size_t pa_size;
536 char *pa = absolutize(path, &pa_size);
537 if (!pa)
538 return ENOMEM;
539
[79ae36dd]540 async_exch_t *exch = vfs_exchange_begin();
[415c7e0d]541
[79ae36dd]542 req = async_send_0(exch, VFS_IN_STAT, NULL);
543 rc = async_data_write_start(exch, pa, pa_size);
[415c7e0d]544 if (rc != EOK) {
[79ae36dd]545 vfs_exchange_end(exch);
[415c7e0d]546 free(pa);
[a28ab12]547 async_wait_for(req, &rc_orig);
[3734106]548 if (rc_orig == EOK)
549 return (int) rc;
550 else
551 return (int) rc_orig;
[415c7e0d]552 }
[79ae36dd]553 rc = async_data_read_start(exch, stat, sizeof(struct stat));
[415c7e0d]554 if (rc != EOK) {
[79ae36dd]555 vfs_exchange_end(exch);
[415c7e0d]556 free(pa);
[a28ab12]557 async_wait_for(req, &rc_orig);
[3734106]558 if (rc_orig == EOK)
559 return (int) rc;
560 else
561 return (int) rc_orig;
[415c7e0d]562 }
[79ae36dd]563 vfs_exchange_end(exch);
[415c7e0d]564 free(pa);
[a28ab12]565 async_wait_for(req, &rc);
[415c7e0d]566 return rc;
567}
568
[d0dc74ae]569DIR *opendir(const char *dirname)
570{
571 DIR *dirp = malloc(sizeof(DIR));
572 if (!dirp)
573 return NULL;
[2b88074b]574
575 size_t abs_size;
576 char *abs = absolutize(dirname, &abs_size);
577 if (!abs) {
578 free(dirp);
[ed903174]579 return NULL;
[2b88074b]580 }
581
582 int ret = open_internal(abs, abs_size, L_DIRECTORY, 0);
583 free(abs);
584
585 if (ret < 0) {
[d0dc74ae]586 free(dirp);
587 return NULL;
588 }
[2b88074b]589
590 dirp->fd = ret;
[d0dc74ae]591 return dirp;
592}
593
594struct dirent *readdir(DIR *dirp)
595{
[5973fd0]596 ssize_t len = read(dirp->fd, &dirp->res.d_name[0], NAME_MAX + 1);
597 if (len <= 0)
598 return NULL;
599 return &dirp->res;
[d0dc74ae]600}
601
602void rewinddir(DIR *dirp)
603{
[5973fd0]604 (void) lseek(dirp->fd, 0, SEEK_SET);
[d0dc74ae]605}
606
607int closedir(DIR *dirp)
608{
609 (void) close(dirp->fd);
610 free(dirp);
611 return 0;
612}
613
[72bde81]614int mkdir(const char *path, mode_t mode)
[d0dc74ae]615{
[96b02eb9]616 sysarg_t rc;
[72bde81]617 aid_t req;
618
[9eb3623]619 size_t pa_size;
620 char *pa = absolutize(path, &pa_size);
[5fec355]621 if (!pa)
622 return ENOMEM;
[19b28b0]623
[79ae36dd]624 async_exch_t *exch = vfs_exchange_begin();
[19b28b0]625
[79ae36dd]626 req = async_send_1(exch, VFS_IN_MKDIR, mode, NULL);
627 rc = async_data_write_start(exch, pa, pa_size);
[72bde81]628 if (rc != EOK) {
[79ae36dd]629 vfs_exchange_end(exch);
[a28ab12]630 free(pa);
631
[96b02eb9]632 sysarg_t rc_orig;
[3734106]633 async_wait_for(req, &rc_orig);
[a28ab12]634
[3734106]635 if (rc_orig == EOK)
636 return (int) rc;
637 else
638 return (int) rc_orig;
[72bde81]639 }
[79ae36dd]640 vfs_exchange_end(exch);
[5fec355]641 free(pa);
[a28ab12]642 async_wait_for(req, &rc);
[2595dab]643 return rc;
[d0dc74ae]644}
645
[f15cf1a6]646static int _unlink(const char *path, int lflag)
647{
[96b02eb9]648 sysarg_t rc;
[f15cf1a6]649 aid_t req;
650
[9eb3623]651 size_t pa_size;
652 char *pa = absolutize(path, &pa_size);
[5fec355]653 if (!pa)
654 return ENOMEM;
[19b28b0]655
[79ae36dd]656 async_exch_t *exch = vfs_exchange_begin();
657
[9ea7d90]658 req = async_send_1(exch, VFS_IN_UNLINK, lflag, NULL);
[79ae36dd]659 rc = async_data_write_start(exch, pa, pa_size);
[f15cf1a6]660 if (rc != EOK) {
[79ae36dd]661 vfs_exchange_end(exch);
[a28ab12]662 free(pa);
[3734106]663
[a28ab12]664 sysarg_t rc_orig;
[3734106]665 async_wait_for(req, &rc_orig);
[a28ab12]666
[3734106]667 if (rc_orig == EOK)
668 return (int) rc;
669 else
670 return (int) rc_orig;
[f15cf1a6]671 }
[79ae36dd]672 vfs_exchange_end(exch);
[5fec355]673 free(pa);
[a28ab12]674 async_wait_for(req, &rc);
[2595dab]675 return rc;
[f15cf1a6]676}
677
678int unlink(const char *path)
679{
680 return _unlink(path, L_NONE);
681}
682
683int rmdir(const char *path)
684{
685 return _unlink(path, L_DIRECTORY);
686}
687
[a8e9ab8d]688int rename(const char *old, const char *new)
689{
[96b02eb9]690 sysarg_t rc;
691 sysarg_t rc_orig;
[a8e9ab8d]692 aid_t req;
693
[9eb3623]694 size_t olda_size;
695 char *olda = absolutize(old, &olda_size);
[a8e9ab8d]696 if (!olda)
697 return ENOMEM;
[923c39e]698
[9eb3623]699 size_t newa_size;
700 char *newa = absolutize(new, &newa_size);
[a8e9ab8d]701 if (!newa) {
702 free(olda);
703 return ENOMEM;
704 }
[19b28b0]705
[79ae36dd]706 async_exch_t *exch = vfs_exchange_begin();
707
708 req = async_send_0(exch, VFS_IN_RENAME, NULL);
709 rc = async_data_write_start(exch, olda, olda_size);
[a8e9ab8d]710 if (rc != EOK) {
[79ae36dd]711 vfs_exchange_end(exch);
[a8e9ab8d]712 free(olda);
713 free(newa);
[a28ab12]714 async_wait_for(req, &rc_orig);
[3734106]715 if (rc_orig == EOK)
716 return (int) rc;
717 else
718 return (int) rc_orig;
[a8e9ab8d]719 }
[79ae36dd]720 rc = async_data_write_start(exch, newa, newa_size);
[a8e9ab8d]721 if (rc != EOK) {
[79ae36dd]722 vfs_exchange_end(exch);
[a8e9ab8d]723 free(olda);
724 free(newa);
[a28ab12]725 async_wait_for(req, &rc_orig);
[3734106]726 if (rc_orig == EOK)
727 return (int) rc;
728 else
729 return (int) rc_orig;
[a8e9ab8d]730 }
[79ae36dd]731 vfs_exchange_end(exch);
[a8e9ab8d]732 free(olda);
733 free(newa);
[a28ab12]734 async_wait_for(req, &rc);
[a8e9ab8d]735 return rc;
736}
737
[5fec355]738int chdir(const char *path)
739{
[2b88074b]740 size_t abs_size;
741 char *abs = absolutize(path, &abs_size);
742 if (!abs)
[5fec355]743 return ENOMEM;
[2b88074b]744
745 int fd = open_internal(abs, abs_size, L_DIRECTORY, O_DESC);
746
747 if (fd < 0) {
748 free(abs);
[5fec355]749 return ENOENT;
750 }
[2b88074b]751
[a28ab12]752 fibril_mutex_lock(&cwd_mutex);
[2b88074b]753
754 if (cwd_fd >= 0)
755 close(cwd_fd);
756
757
758 if (cwd_path)
759 free(cwd_path);
760
761 cwd_fd = fd;
762 cwd_path = abs;
763 cwd_size = abs_size;
764
[a28ab12]765 fibril_mutex_unlock(&cwd_mutex);
[0dd0f71f]766 return EOK;
[5fec355]767}
768
769char *getcwd(char *buf, size_t size)
770{
[2b88074b]771 if (size == 0)
[5fec355]772 return NULL;
[2b88074b]773
[a28ab12]774 fibril_mutex_lock(&cwd_mutex);
[2b88074b]775
776 if ((cwd_size == 0) || (size < cwd_size + 1)) {
[a28ab12]777 fibril_mutex_unlock(&cwd_mutex);
[5fec355]778 return NULL;
779 }
[2b88074b]780
[6eb2e96]781 str_cpy(buf, size, cwd_path);
[a28ab12]782 fibril_mutex_unlock(&cwd_mutex);
[2b88074b]783
[5fec355]784 return buf;
785}
786
[79ae36dd]787async_sess_t *fd_session(exch_mgmt_t mgmt, int fildes)
[852b801]788{
789 struct stat stat;
[8caaea7]790 int rc = fstat(fildes, &stat);
[79ae36dd]791 if (rc != 0) {
792 errno = rc;
793 return NULL;
794 }
[8caaea7]795
[15f3c3f]796 if (!stat.service) {
[79ae36dd]797 errno = ENOENT;
798 return NULL;
799 }
[852b801]800
[15f3c3f]801 return loc_service_connect(mgmt, stat.service, 0);
[852b801]802}
803
[2b88074b]804int dup2(int oldfd, int newfd)
[852b801]805{
[79ae36dd]806 async_exch_t *exch = vfs_exchange_begin();
[852b801]807
[96b02eb9]808 sysarg_t ret;
[79ae36dd]809 sysarg_t rc = async_req_2_1(exch, VFS_IN_DUP, oldfd, newfd, &ret);
[852b801]810
[79ae36dd]811 vfs_exchange_end(exch);
[2b88074b]812
813 if (rc == EOK)
814 return (int) ret;
815
816 return (int) rc;
[852b801]817}
818
[27b76ca]819int fd_wait(void)
[2b88074b]820{
[79ae36dd]821 async_exch_t *exch = vfs_exchange_begin();
[2b88074b]822
[96b02eb9]823 sysarg_t ret;
[27b76ca]824 sysarg_t rc = async_req_0_1(exch, VFS_IN_WAIT_HANDLE, &ret);
[2b88074b]825
[79ae36dd]826 vfs_exchange_end(exch);
[2b88074b]827
828 if (rc == EOK)
829 return (int) ret;
830
831 return (int) rc;
832}
833
[10e4cd7]834int get_mtab_list(list_t *mtab_list)
835{
836 sysarg_t rc;
[4965357f]837 aid_t req;
[10e4cd7]838 size_t i;
[4965357f]839 sysarg_t num_mounted_fs;
[10e4cd7]840
841 async_exch_t *exch = vfs_exchange_begin();
842
[41e9ef7]843 req = async_send_0(exch, VFS_IN_MTAB_GET, NULL);
[10e4cd7]844
845 /* Ask VFS how many filesystems are mounted */
846 rc = async_req_0_1(exch, VFS_IN_PING, &num_mounted_fs);
847 if (rc != EOK)
848 goto exit;
849
850 for (i = 0; i < num_mounted_fs; ++i) {
851 mtab_ent_t *mtab_ent;
852
[8d6a41c]853 mtab_ent = malloc(sizeof(mtab_ent_t));
854 if (!mtab_ent) {
[10e4cd7]855 rc = ENOMEM;
856 goto exit;
857 }
858
[8d6a41c]859 memset(mtab_ent, 0, sizeof(mtab_ent_t));
[10e4cd7]860
[4965357f]861 rc = async_data_read_start(exch, (void *) mtab_ent->mp,
[10e4cd7]862 MAX_PATH_LEN);
863 if (rc != EOK)
864 goto exit;
865
[4965357f]866 rc = async_data_read_start(exch, (void *) mtab_ent->opts,
[10e4cd7]867 MAX_MNTOPTS_LEN);
868 if (rc != EOK)
869 goto exit;
870
[4965357f]871 rc = async_data_read_start(exch, (void *) mtab_ent->fs_name,
[10e4cd7]872 FS_NAME_MAXLEN);
873 if (rc != EOK)
874 goto exit;
875
[6b8e5b74]876 sysarg_t p[2];
[10e4cd7]877
[6b8e5b74]878 rc = async_req_0_2(exch, VFS_IN_PING, &p[0], &p[1]);
[f8838b8]879 if (rc != EOK)
880 goto exit;
[10e4cd7]881
[6b8e5b74]882 mtab_ent->instance = p[0];
883 mtab_ent->service_id = p[1];
[10e4cd7]884
[8d6a41c]885 link_initialize(&mtab_ent->link);
886 list_append(&mtab_ent->link, mtab_list);
[10e4cd7]887 }
888
889exit:
[4965357f]890 async_wait_for(req, &rc);
[10e4cd7]891 vfs_exchange_end(exch);
892 return rc;
893}
894
[73fbcbb]895int statfs(const char *path, struct statfs *st)
[66366470]896{
[73fbcbb]897 sysarg_t rc, rc_orig;
[9dc6083]898 aid_t req;
899 size_t pa_size;
[73fbcbb]900
[9dc6083]901 char *pa = absolutize(path, &pa_size);
902 if (!pa)
903 return ENOMEM;
[73fbcbb]904
[9dc6083]905 async_exch_t *exch = vfs_exchange_begin();
[73fbcbb]906
[9dc6083]907 req = async_send_0(exch, VFS_IN_STATFS, NULL);
908 rc = async_data_write_start(exch, pa, pa_size);
[73fbcbb]909 if (rc != EOK)
910 goto exit;
911
912 rc = async_data_read_start(exch, (void *) st, sizeof(*st));
913
914exit:
[66366470]915 vfs_exchange_end(exch);
[9dc6083]916 free(pa);
[73fbcbb]917 async_wait_for(req, &rc_orig);
918 return (int) (rc_orig != EOK ? rc_orig : rc);
[66366470]919}
920
[2f02aa17]921/** @}
922 */
Note: See TracBrowser for help on using the repository browser.