source: mainline/uspace/lib/c/generic/vfs/vfs.c@ 903bac0a

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 903bac0a was 42a619b, checked in by Jakub Jermar <jakub@…>, 14 years ago

Merge from lp:~jakub/helenos/camp2011.

  • Property mode set to 100644
File size: 16.4 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>
[72bde81]45#include <sys/types.h>
[2f02aa17]46#include <ipc/services.h>
[79ae36dd]47#include <ns.h>
[2f02aa17]48#include <async.h>
[a28ab12]49#include <fibril_synch.h>
[2f02aa17]50#include <errno.h>
[a28ab12]51#include <assert.h>
[19f857a]52#include <str.h>
[15f3c3f]53#include <loc.h>
[2595dab]54#include <ipc/vfs.h>
[15f3c3f]55#include <ipc/loc.h>
[2f02aa17]56
[79ae36dd]57static FIBRIL_MUTEX_INITIALIZE(vfs_mutex);
58static async_sess_t *vfs_sess = NULL;
[a28ab12]59
60static FIBRIL_MUTEX_INITIALIZE(cwd_mutex);
[5fec355]61
[2b88074b]62static int cwd_fd = -1;
63static char *cwd_path = NULL;
64static size_t cwd_size = 0;
[5fec355]65
[79ae36dd]66/** Start an async exchange on the VFS session.
67 *
68 * @return New exchange.
69 *
70 */
[866e627]71async_exch_t *vfs_exchange_begin(void)
[79ae36dd]72{
73 fibril_mutex_lock(&vfs_mutex);
74
75 while (vfs_sess == NULL)
76 vfs_sess = service_connect_blocking(EXCHANGE_PARALLEL, SERVICE_VFS,
77 0, 0);
78
79 fibril_mutex_unlock(&vfs_mutex);
80
81 return async_exchange_begin(vfs_sess);
82}
83
84/** Finish an async exchange on the VFS session.
85 *
86 * @param exch Exchange to be finished.
87 *
88 */
[866e627]89void vfs_exchange_end(async_exch_t *exch)
[79ae36dd]90{
91 async_exchange_end(exch);
92}
93
[17b2aac]94char *absolutize(const char *path, size_t *retlen)
[5fec355]95{
96 char *ncwd_path;
[34a74ab]97 char *ncwd_path_nc;
[5fec355]98
[a28ab12]99 fibril_mutex_lock(&cwd_mutex);
[9eb3623]100 size_t size = str_size(path);
[5fec355]101 if (*path != '/') {
102 if (!cwd_path) {
[a28ab12]103 fibril_mutex_unlock(&cwd_mutex);
[5fec355]104 return NULL;
105 }
[79ae36dd]106 ncwd_path_nc = malloc(cwd_size + 1 + size + 1);
[34a74ab]107 if (!ncwd_path_nc) {
[a28ab12]108 fibril_mutex_unlock(&cwd_mutex);
[5fec355]109 return NULL;
110 }
[79ae36dd]111 str_cpy(ncwd_path_nc, cwd_size + 1 + size + 1, cwd_path);
[9eb3623]112 ncwd_path_nc[cwd_size] = '/';
113 ncwd_path_nc[cwd_size + 1] = '\0';
[5fec355]114 } else {
[79ae36dd]115 ncwd_path_nc = malloc(size + 1);
[34a74ab]116 if (!ncwd_path_nc) {
[a28ab12]117 fibril_mutex_unlock(&cwd_mutex);
[5fec355]118 return NULL;
119 }
[34a74ab]120 ncwd_path_nc[0] = '\0';
[5fec355]121 }
[79ae36dd]122 str_append(ncwd_path_nc, cwd_size + 1 + size + 1, path);
[34a74ab]123 ncwd_path = canonify(ncwd_path_nc, retlen);
124 if (!ncwd_path) {
[a28ab12]125 fibril_mutex_unlock(&cwd_mutex);
[34a74ab]126 free(ncwd_path_nc);
127 return NULL;
128 }
129 /*
130 * We need to clone ncwd_path because canonify() works in-place and thus
131 * the address in ncwd_path need not be the same as ncwd_path_nc, even
132 * though they both point into the same dynamically allocated buffer.
133 */
[095003a8]134 ncwd_path = str_dup(ncwd_path);
[34a74ab]135 free(ncwd_path_nc);
136 if (!ncwd_path) {
[a28ab12]137 fibril_mutex_unlock(&cwd_mutex);
[923c39e]138 return NULL;
139 }
[a28ab12]140 fibril_mutex_unlock(&cwd_mutex);
[5fec355]141 return ncwd_path;
142}
[2f02aa17]143
[15f3c3f]144int mount(const char *fs_name, const char *mp, const char *fqsn,
[1090b8c]145 const char *opts, unsigned int flags)
[2f02aa17]146{
[210e50a]147 int null_id = -1;
[15f3c3f]148 char null[LOC_NAME_MAXLEN];
[210e50a]149
[15f3c3f]150 if (str_cmp(fqsn, "") == 0) {
[210e50a]151 /* No device specified, create a fresh
152 null/%d device instead */
[15f3c3f]153 null_id = loc_null_create();
[210e50a]154
155 if (null_id == -1)
156 return ENOMEM;
157
[15f3c3f]158 snprintf(null, LOC_NAME_MAXLEN, "null/%d", null_id);
159 fqsn = null;
[210e50a]160 }
[82405266]161
[15f3c3f]162 service_id_t service_id;
163 int res = loc_service_get_id(fqsn, &service_id, flags);
[210e50a]164 if (res != EOK) {
165 if (null_id != -1)
[15f3c3f]166 loc_null_destroy(null_id);
[210e50a]167
[82405266]168 return res;
[210e50a]169 }
[82405266]170
[9eb3623]171 size_t mpa_size;
172 char *mpa = absolutize(mp, &mpa_size);
[210e50a]173 if (!mpa) {
174 if (null_id != -1)
[15f3c3f]175 loc_null_destroy(null_id);
[210e50a]176
[5fec355]177 return ENOMEM;
[210e50a]178 }
[19b28b0]179
[79ae36dd]180 async_exch_t *exch = vfs_exchange_begin();
[a28ab12]181
[96b02eb9]182 sysarg_t rc_orig;
[15f3c3f]183 aid_t req = async_send_2(exch, VFS_IN_MOUNT, service_id, flags, NULL);
[79ae36dd]184 sysarg_t rc = async_data_write_start(exch, (void *) mpa, mpa_size);
[12fc042]185 if (rc != EOK) {
[79ae36dd]186 vfs_exchange_end(exch);
[12fc042]187 free(mpa);
[a28ab12]188 async_wait_for(req, &rc_orig);
[210e50a]189
190 if (null_id != -1)
[15f3c3f]191 loc_null_destroy(null_id);
[210e50a]192
[3734106]193 if (rc_orig == EOK)
194 return (int) rc;
195 else
196 return (int) rc_orig;
[12fc042]197 }
[19b28b0]198
[79ae36dd]199 rc = async_data_write_start(exch, (void *) opts, str_size(opts));
[594303b]200 if (rc != EOK) {
[79ae36dd]201 vfs_exchange_end(exch);
[594303b]202 free(mpa);
[a28ab12]203 async_wait_for(req, &rc_orig);
[210e50a]204
205 if (null_id != -1)
[15f3c3f]206 loc_null_destroy(null_id);
[210e50a]207
[3734106]208 if (rc_orig == EOK)
209 return (int) rc;
210 else
211 return (int) rc_orig;
[594303b]212 }
[210e50a]213
[79ae36dd]214 rc = async_data_write_start(exch, (void *) fs_name, str_size(fs_name));
[2f02aa17]215 if (rc != EOK) {
[79ae36dd]216 vfs_exchange_end(exch);
[5fec355]217 free(mpa);
[a28ab12]218 async_wait_for(req, &rc_orig);
[210e50a]219
220 if (null_id != -1)
[15f3c3f]221 loc_null_destroy(null_id);
[210e50a]222
[3734106]223 if (rc_orig == EOK)
224 return (int) rc;
225 else
226 return (int) rc_orig;
[2f02aa17]227 }
[210e50a]228
[c08c355]229 /* Ask VFS whether it likes fs_name. */
[79ae36dd]230 rc = async_req_0_0(exch, VFS_IN_PING);
[c08c355]231 if (rc != EOK) {
[79ae36dd]232 vfs_exchange_end(exch);
[c08c355]233 free(mpa);
[a28ab12]234 async_wait_for(req, &rc_orig);
[210e50a]235
236 if (null_id != -1)
[15f3c3f]237 loc_null_destroy(null_id);
[210e50a]238
[3734106]239 if (rc_orig == EOK)
240 return (int) rc;
241 else
242 return (int) rc_orig;
[c08c355]243 }
[19b28b0]244
[79ae36dd]245 vfs_exchange_end(exch);
[5fec355]246 free(mpa);
[a28ab12]247 async_wait_for(req, &rc);
[19b28b0]248
[210e50a]249 if ((rc != EOK) && (null_id != -1))
[15f3c3f]250 loc_null_destroy(null_id);
[210e50a]251
[2f02aa17]252 return (int) rc;
253}
254
[21f32ee1]255int unmount(const char *mp)
256{
[96b02eb9]257 sysarg_t rc;
258 sysarg_t rc_orig;
[b9067dfa]259 aid_t req;
260 size_t mpa_size;
261 char *mpa;
262
263 mpa = absolutize(mp, &mpa_size);
264 if (!mpa)
265 return ENOMEM;
266
[79ae36dd]267 async_exch_t *exch = vfs_exchange_begin();
[b9067dfa]268
[79ae36dd]269 req = async_send_0(exch, VFS_IN_UNMOUNT, NULL);
270 rc = async_data_write_start(exch, (void *) mpa, mpa_size);
[b9067dfa]271 if (rc != EOK) {
[79ae36dd]272 vfs_exchange_end(exch);
[b9067dfa]273 free(mpa);
[a28ab12]274 async_wait_for(req, &rc_orig);
[b9067dfa]275 if (rc_orig == EOK)
276 return (int) rc;
277 else
278 return (int) rc_orig;
279 }
280
281
[79ae36dd]282 vfs_exchange_end(exch);
[b9067dfa]283 free(mpa);
[a28ab12]284 async_wait_for(req, &rc);
[b9067dfa]285
286 return (int) rc;
[21f32ee1]287}
288
[2b88074b]289static int open_internal(const char *abs, size_t abs_size, int lflag, int oflag)
[2f02aa17]290{
[79ae36dd]291 async_exch_t *exch = vfs_exchange_begin();
[19b28b0]292
[2b88074b]293 ipc_call_t answer;
[79ae36dd]294 aid_t req = async_send_3(exch, VFS_IN_OPEN, lflag, oflag, 0, &answer);
295 sysarg_t rc = async_data_write_start(exch, abs, abs_size);
[2b88074b]296
[2f02aa17]297 if (rc != EOK) {
[79ae36dd]298 vfs_exchange_end(exch);
[a28ab12]299
[96b02eb9]300 sysarg_t rc_orig;
[3734106]301 async_wait_for(req, &rc_orig);
[2b88074b]302
[3734106]303 if (rc_orig == EOK)
304 return (int) rc;
305 else
306 return (int) rc_orig;
[2f02aa17]307 }
[2b88074b]308
[79ae36dd]309 vfs_exchange_end(exch);
[2f02aa17]310 async_wait_for(req, &rc);
[2595dab]311
[57b4f46]312 if (rc != EOK)
313 return (int) rc;
[2595dab]314
[2f02aa17]315 return (int) IPC_GET_ARG1(answer);
316}
317
[ae78b530]318int open(const char *path, int oflag, ...)
319{
[2b88074b]320 size_t abs_size;
321 char *abs = absolutize(path, &abs_size);
322 if (!abs)
323 return ENOMEM;
324
325 int ret = open_internal(abs, abs_size, L_FILE, oflag);
326 free(abs);
327
328 return ret;
[ae78b530]329}
330
[72bde81]331int close(int fildes)
332{
[96b02eb9]333 sysarg_t rc;
[19b28b0]334
[79ae36dd]335 async_exch_t *exch = vfs_exchange_begin();
336 rc = async_req_1_0(exch, VFS_IN_CLOSE, fildes);
337 vfs_exchange_end(exch);
[19b28b0]338
[79ae36dd]339 return (int) rc;
[72bde81]340}
341
[2f02aa17]342ssize_t read(int fildes, void *buf, size_t nbyte)
343{
[96b02eb9]344 sysarg_t rc;
[2f02aa17]345 ipc_call_t answer;
346 aid_t req;
[19b28b0]347
[79ae36dd]348 async_exch_t *exch = vfs_exchange_begin();
349
350 req = async_send_1(exch, VFS_IN_READ, fildes, &answer);
351 rc = async_data_read_start(exch, (void *)buf, nbyte);
[07e01e6]352 if (rc != EOK) {
[79ae36dd]353 vfs_exchange_end(exch);
[a28ab12]354
[96b02eb9]355 sysarg_t rc_orig;
[3734106]356 async_wait_for(req, &rc_orig);
[a28ab12]357
[3734106]358 if (rc_orig == EOK)
359 return (ssize_t) rc;
360 else
361 return (ssize_t) rc_orig;
[2f02aa17]362 }
[79ae36dd]363 vfs_exchange_end(exch);
[2f02aa17]364 async_wait_for(req, &rc);
[f7017572]365 if (rc == EOK)
366 return (ssize_t) IPC_GET_ARG1(answer);
367 else
[25becee8]368 return rc;
[2f02aa17]369}
370
[449c246]371ssize_t write(int fildes, const void *buf, size_t nbyte)
372{
[96b02eb9]373 sysarg_t rc;
[449c246]374 ipc_call_t answer;
375 aid_t req;
[19b28b0]376
[79ae36dd]377 async_exch_t *exch = vfs_exchange_begin();
378
379 req = async_send_1(exch, VFS_IN_WRITE, fildes, &answer);
380 rc = async_data_write_start(exch, (void *)buf, nbyte);
[07e01e6]381 if (rc != EOK) {
[79ae36dd]382 vfs_exchange_end(exch);
[a28ab12]383
[96b02eb9]384 sysarg_t rc_orig;
[3734106]385 async_wait_for(req, &rc_orig);
[a28ab12]386
[3734106]387 if (rc_orig == EOK)
388 return (ssize_t) rc;
389 else
390 return (ssize_t) rc_orig;
[449c246]391 }
[79ae36dd]392 vfs_exchange_end(exch);
[449c246]393 async_wait_for(req, &rc);
[f7017572]394 if (rc == EOK)
395 return (ssize_t) IPC_GET_ARG1(answer);
396 else
397 return -1;
[449c246]398}
[222e57c]399
[8fd04ba9]400/** Read entire buffer.
401 *
402 * In face of short reads this function continues reading until either
403 * the entire buffer is read or no more data is available (at end of file).
404 *
405 * @param fildes File descriptor
406 * @param buf Buffer, @a nbytes bytes long
407 * @param nbytes Number of bytes to read
408 *
409 * @return On success, positive number of bytes read.
410 * On failure, negative error code from read().
411 */
412ssize_t read_all(int fildes, void *buf, size_t nbyte)
413{
414 ssize_t cnt = 0;
415 size_t nread = 0;
416 uint8_t *bp = (uint8_t *) buf;
417
418 do {
419 bp += cnt;
420 nread += cnt;
421 cnt = read(fildes, bp, nbyte - nread);
422 } while (cnt > 0 && (nbyte - nread - cnt) > 0);
423
424 if (cnt < 0)
425 return cnt;
426
427 return nread + cnt;
428}
429
430/** Write entire buffer.
431 *
432 * This function fails if it cannot write exactly @a len bytes to the file.
433 *
434 * @param fildes File descriptor
435 * @param buf Data, @a nbytes bytes long
436 * @param nbytes Number of bytes to write
437 *
438 * @return EOK on error, return value from write() if writing
439 * failed.
440 */
441ssize_t write_all(int fildes, const void *buf, size_t nbyte)
442{
443 ssize_t cnt = 0;
444 ssize_t nwritten = 0;
445 const uint8_t *bp = (uint8_t *) buf;
446
447 do {
448 bp += cnt;
449 nwritten += cnt;
450 cnt = write(fildes, bp, nbyte - nwritten);
451 } while (cnt > 0 && ((ssize_t )nbyte - nwritten - cnt) > 0);
452
453 if (cnt < 0)
454 return cnt;
455
456 if ((ssize_t)nbyte - nwritten - cnt > 0)
457 return EIO;
458
459 return nbyte;
460}
461
[2595dab]462int fsync(int fildes)
463{
[79ae36dd]464 async_exch_t *exch = vfs_exchange_begin();
465 sysarg_t rc = async_req_1_0(exch, VFS_IN_SYNC, fildes);
466 vfs_exchange_end(exch);
[2595dab]467
468 return (int) rc;
469}
470
[ed903174]471off64_t lseek(int fildes, off64_t offset, int whence)
[222e57c]472{
[79ae36dd]473 async_exch_t *exch = vfs_exchange_begin();
[19b28b0]474
[96b02eb9]475 sysarg_t newoff_lo;
476 sysarg_t newoff_hi;
[79ae36dd]477 sysarg_t rc = async_req_4_2(exch, VFS_IN_SEEK, fildes,
[ed903174]478 LOWER32(offset), UPPER32(offset), whence,
479 &newoff_lo, &newoff_hi);
480
[79ae36dd]481 vfs_exchange_end(exch);
[ed903174]482
[222e57c]483 if (rc != EOK)
[ed903174]484 return (off64_t) -1;
[222e57c]485
[ed903174]486 return (off64_t) MERGE_LOUP32(newoff_lo, newoff_hi);
[222e57c]487}
488
[ed903174]489int ftruncate(int fildes, aoff64_t length)
[0ee4322]490{
[96b02eb9]491 sysarg_t rc;
[0ee4322]492
[79ae36dd]493 async_exch_t *exch = vfs_exchange_begin();
494 rc = async_req_3_0(exch, VFS_IN_TRUNCATE, fildes,
[ed903174]495 LOWER32(length), UPPER32(length));
[79ae36dd]496 vfs_exchange_end(exch);
[ed903174]497
[0ee4322]498 return (int) rc;
499}
500
[852b801]501int fstat(int fildes, struct stat *stat)
502{
[96b02eb9]503 sysarg_t rc;
[852b801]504 aid_t req;
505
[79ae36dd]506 async_exch_t *exch = vfs_exchange_begin();
507
508 req = async_send_1(exch, VFS_IN_FSTAT, fildes, NULL);
509 rc = async_data_read_start(exch, (void *) stat, sizeof(struct stat));
[852b801]510 if (rc != EOK) {
[79ae36dd]511 vfs_exchange_end(exch);
[a28ab12]512
[96b02eb9]513 sysarg_t rc_orig;
[3734106]514 async_wait_for(req, &rc_orig);
[a28ab12]515
[3734106]516 if (rc_orig == EOK)
517 return (ssize_t) rc;
518 else
519 return (ssize_t) rc_orig;
[852b801]520 }
[79ae36dd]521 vfs_exchange_end(exch);
[852b801]522 async_wait_for(req, &rc);
523
524 return rc;
525}
526
[415c7e0d]527int stat(const char *path, struct stat *stat)
528{
[96b02eb9]529 sysarg_t rc;
530 sysarg_t rc_orig;
[415c7e0d]531 aid_t req;
532
533 size_t pa_size;
534 char *pa = absolutize(path, &pa_size);
535 if (!pa)
536 return ENOMEM;
537
[79ae36dd]538 async_exch_t *exch = vfs_exchange_begin();
[415c7e0d]539
[79ae36dd]540 req = async_send_0(exch, VFS_IN_STAT, NULL);
541 rc = async_data_write_start(exch, pa, pa_size);
[415c7e0d]542 if (rc != EOK) {
[79ae36dd]543 vfs_exchange_end(exch);
[415c7e0d]544 free(pa);
[a28ab12]545 async_wait_for(req, &rc_orig);
[3734106]546 if (rc_orig == EOK)
547 return (int) rc;
548 else
549 return (int) rc_orig;
[415c7e0d]550 }
[79ae36dd]551 rc = async_data_read_start(exch, stat, sizeof(struct stat));
[415c7e0d]552 if (rc != EOK) {
[79ae36dd]553 vfs_exchange_end(exch);
[415c7e0d]554 free(pa);
[a28ab12]555 async_wait_for(req, &rc_orig);
[3734106]556 if (rc_orig == EOK)
557 return (int) rc;
558 else
559 return (int) rc_orig;
[415c7e0d]560 }
[79ae36dd]561 vfs_exchange_end(exch);
[415c7e0d]562 free(pa);
[a28ab12]563 async_wait_for(req, &rc);
[415c7e0d]564 return rc;
565}
566
[d0dc74ae]567DIR *opendir(const char *dirname)
568{
569 DIR *dirp = malloc(sizeof(DIR));
570 if (!dirp)
571 return NULL;
[2b88074b]572
573 size_t abs_size;
574 char *abs = absolutize(dirname, &abs_size);
575 if (!abs) {
576 free(dirp);
[ed903174]577 return NULL;
[2b88074b]578 }
579
580 int ret = open_internal(abs, abs_size, L_DIRECTORY, 0);
581 free(abs);
582
583 if (ret < 0) {
[d0dc74ae]584 free(dirp);
585 return NULL;
586 }
[2b88074b]587
588 dirp->fd = ret;
[d0dc74ae]589 return dirp;
590}
591
592struct dirent *readdir(DIR *dirp)
593{
[5973fd0]594 ssize_t len = read(dirp->fd, &dirp->res.d_name[0], NAME_MAX + 1);
595 if (len <= 0)
596 return NULL;
597 return &dirp->res;
[d0dc74ae]598}
599
600void rewinddir(DIR *dirp)
601{
[5973fd0]602 (void) lseek(dirp->fd, 0, SEEK_SET);
[d0dc74ae]603}
604
605int closedir(DIR *dirp)
606{
607 (void) close(dirp->fd);
608 free(dirp);
609 return 0;
610}
611
[72bde81]612int mkdir(const char *path, mode_t mode)
[d0dc74ae]613{
[96b02eb9]614 sysarg_t rc;
[72bde81]615 aid_t req;
616
[9eb3623]617 size_t pa_size;
618 char *pa = absolutize(path, &pa_size);
[5fec355]619 if (!pa)
620 return ENOMEM;
[19b28b0]621
[79ae36dd]622 async_exch_t *exch = vfs_exchange_begin();
[19b28b0]623
[79ae36dd]624 req = async_send_1(exch, VFS_IN_MKDIR, mode, NULL);
625 rc = async_data_write_start(exch, pa, pa_size);
[72bde81]626 if (rc != EOK) {
[79ae36dd]627 vfs_exchange_end(exch);
[a28ab12]628 free(pa);
629
[96b02eb9]630 sysarg_t rc_orig;
[3734106]631 async_wait_for(req, &rc_orig);
[a28ab12]632
[3734106]633 if (rc_orig == EOK)
634 return (int) rc;
635 else
636 return (int) rc_orig;
[72bde81]637 }
[79ae36dd]638 vfs_exchange_end(exch);
[5fec355]639 free(pa);
[a28ab12]640 async_wait_for(req, &rc);
[2595dab]641 return rc;
[d0dc74ae]642}
643
[f15cf1a6]644static int _unlink(const char *path, int lflag)
645{
[96b02eb9]646 sysarg_t rc;
[f15cf1a6]647 aid_t req;
648
[9eb3623]649 size_t pa_size;
650 char *pa = absolutize(path, &pa_size);
[5fec355]651 if (!pa)
652 return ENOMEM;
[19b28b0]653
[79ae36dd]654 async_exch_t *exch = vfs_exchange_begin();
655
656 req = async_send_0(exch, VFS_IN_UNLINK, NULL);
657 rc = async_data_write_start(exch, pa, pa_size);
[f15cf1a6]658 if (rc != EOK) {
[79ae36dd]659 vfs_exchange_end(exch);
[a28ab12]660 free(pa);
[3734106]661
[a28ab12]662 sysarg_t rc_orig;
[3734106]663 async_wait_for(req, &rc_orig);
[a28ab12]664
[3734106]665 if (rc_orig == EOK)
666 return (int) rc;
667 else
668 return (int) rc_orig;
[f15cf1a6]669 }
[79ae36dd]670 vfs_exchange_end(exch);
[5fec355]671 free(pa);
[a28ab12]672 async_wait_for(req, &rc);
[2595dab]673 return rc;
[f15cf1a6]674}
675
676int unlink(const char *path)
677{
678 return _unlink(path, L_NONE);
679}
680
681int rmdir(const char *path)
682{
683 return _unlink(path, L_DIRECTORY);
684}
685
[a8e9ab8d]686int rename(const char *old, const char *new)
687{
[96b02eb9]688 sysarg_t rc;
689 sysarg_t rc_orig;
[a8e9ab8d]690 aid_t req;
691
[9eb3623]692 size_t olda_size;
693 char *olda = absolutize(old, &olda_size);
[a8e9ab8d]694 if (!olda)
695 return ENOMEM;
[923c39e]696
[9eb3623]697 size_t newa_size;
698 char *newa = absolutize(new, &newa_size);
[a8e9ab8d]699 if (!newa) {
700 free(olda);
701 return ENOMEM;
702 }
[19b28b0]703
[79ae36dd]704 async_exch_t *exch = vfs_exchange_begin();
705
706 req = async_send_0(exch, VFS_IN_RENAME, NULL);
707 rc = async_data_write_start(exch, olda, olda_size);
[a8e9ab8d]708 if (rc != EOK) {
[79ae36dd]709 vfs_exchange_end(exch);
[a8e9ab8d]710 free(olda);
711 free(newa);
[a28ab12]712 async_wait_for(req, &rc_orig);
[3734106]713 if (rc_orig == EOK)
714 return (int) rc;
715 else
716 return (int) rc_orig;
[a8e9ab8d]717 }
[79ae36dd]718 rc = async_data_write_start(exch, newa, newa_size);
[a8e9ab8d]719 if (rc != EOK) {
[79ae36dd]720 vfs_exchange_end(exch);
[a8e9ab8d]721 free(olda);
722 free(newa);
[a28ab12]723 async_wait_for(req, &rc_orig);
[3734106]724 if (rc_orig == EOK)
725 return (int) rc;
726 else
727 return (int) rc_orig;
[a8e9ab8d]728 }
[79ae36dd]729 vfs_exchange_end(exch);
[a8e9ab8d]730 free(olda);
731 free(newa);
[a28ab12]732 async_wait_for(req, &rc);
[a8e9ab8d]733 return rc;
734}
735
[5fec355]736int chdir(const char *path)
737{
[2b88074b]738 size_t abs_size;
739 char *abs = absolutize(path, &abs_size);
740 if (!abs)
[5fec355]741 return ENOMEM;
[2b88074b]742
743 int fd = open_internal(abs, abs_size, L_DIRECTORY, O_DESC);
744
745 if (fd < 0) {
746 free(abs);
[5fec355]747 return ENOENT;
748 }
[2b88074b]749
[a28ab12]750 fibril_mutex_lock(&cwd_mutex);
[2b88074b]751
752 if (cwd_fd >= 0)
753 close(cwd_fd);
754
755
756 if (cwd_path)
757 free(cwd_path);
758
759 cwd_fd = fd;
760 cwd_path = abs;
761 cwd_size = abs_size;
762
[a28ab12]763 fibril_mutex_unlock(&cwd_mutex);
[0dd0f71f]764 return EOK;
[5fec355]765}
766
767char *getcwd(char *buf, size_t size)
768{
[2b88074b]769 if (size == 0)
[5fec355]770 return NULL;
[2b88074b]771
[a28ab12]772 fibril_mutex_lock(&cwd_mutex);
[2b88074b]773
774 if ((cwd_size == 0) || (size < cwd_size + 1)) {
[a28ab12]775 fibril_mutex_unlock(&cwd_mutex);
[5fec355]776 return NULL;
777 }
[2b88074b]778
[6eb2e96]779 str_cpy(buf, size, cwd_path);
[a28ab12]780 fibril_mutex_unlock(&cwd_mutex);
[2b88074b]781
[5fec355]782 return buf;
783}
784
[79ae36dd]785async_sess_t *fd_session(exch_mgmt_t mgmt, int fildes)
[852b801]786{
787 struct stat stat;
[8caaea7]788 int rc = fstat(fildes, &stat);
[79ae36dd]789 if (rc != 0) {
790 errno = rc;
791 return NULL;
792 }
[8caaea7]793
[15f3c3f]794 if (!stat.service) {
[79ae36dd]795 errno = ENOENT;
796 return NULL;
797 }
[852b801]798
[15f3c3f]799 return loc_service_connect(mgmt, stat.service, 0);
[852b801]800}
801
[2b88074b]802int dup2(int oldfd, int newfd)
[852b801]803{
[79ae36dd]804 async_exch_t *exch = vfs_exchange_begin();
[852b801]805
[96b02eb9]806 sysarg_t ret;
[79ae36dd]807 sysarg_t rc = async_req_2_1(exch, VFS_IN_DUP, oldfd, newfd, &ret);
[852b801]808
[79ae36dd]809 vfs_exchange_end(exch);
[2b88074b]810
811 if (rc == EOK)
812 return (int) ret;
813
814 return (int) rc;
[852b801]815}
816
[27b76ca]817int fd_wait(void)
[2b88074b]818{
[79ae36dd]819 async_exch_t *exch = vfs_exchange_begin();
[2b88074b]820
[96b02eb9]821 sysarg_t ret;
[27b76ca]822 sysarg_t rc = async_req_0_1(exch, VFS_IN_WAIT_HANDLE, &ret);
[2b88074b]823
[79ae36dd]824 vfs_exchange_end(exch);
[2b88074b]825
826 if (rc == EOK)
827 return (int) ret;
828
829 return (int) rc;
830}
831
[2f02aa17]832/** @}
833 */
Note: See TracBrowser for help on using the repository browser.