source: mainline/uspace/lib/c/generic/vfs/vfs.c@ 79ae36dd

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 79ae36dd was 79ae36dd, checked in by Martin Decky <martin@…>, 14 years ago

new async framework with integrated exchange tracking

  • strict isolation between low-level IPC and high-level async framework with integrated exchange tracking
    • each IPC connection is represented by an async_sess_t structure
    • each IPC exchange is represented by an async_exch_t structure
    • exchange management is either based on atomic messages (EXCHANGE_ATOMIC), locking (EXCHANGE_SERIALIZE) or connection cloning (EXCHANGE_CLONE)
  • async_obsolete: temporary compatibility layer to keep old async clients working (several pieces of code are currently broken, but only non-essential functionality)
  • IPC_M_PHONE_HANGUP is now method no. 0 (for elegant boolean evaluation)
  • IPC_M_DEBUG_ALL has been renamed to IPC_M_DEBUG
  • IPC_M_PING has been removed (VFS protocol now has VFS_IN_PING)
  • console routines in libc have been rewritten for better abstraction
  • additional use for libc-private header files (FILE structure opaque to the client)
  • various cstyle changes (typos, indentation, missing externs in header files, improved comments, etc.)
  • Property mode set to 100644
File size: 15.5 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>
[1090b8c]53#include <devmap.h>
[2595dab]54#include <ipc/vfs.h>
55#include <ipc/devmap.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 */
71static async_exch_t *vfs_exchange_begin(void)
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 */
89static void vfs_exchange_end(async_exch_t *exch)
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
[1313ee9]144int mount(const char *fs_name, const char *mp, const char *fqdn,
[1090b8c]145 const char *opts, unsigned int flags)
[2f02aa17]146{
[210e50a]147 int null_id = -1;
148 char null[DEVMAP_NAME_MAXLEN];
149
150 if (str_cmp(fqdn, "") == 0) {
151 /* No device specified, create a fresh
152 null/%d device instead */
153 null_id = devmap_null_create();
154
155 if (null_id == -1)
156 return ENOMEM;
157
158 snprintf(null, DEVMAP_NAME_MAXLEN, "null/%d", null_id);
159 fqdn = null;
160 }
[82405266]161
[991f645]162 devmap_handle_t devmap_handle;
163 int res = devmap_device_get_handle(fqdn, &devmap_handle, flags);
[210e50a]164 if (res != EOK) {
165 if (null_id != -1)
166 devmap_null_destroy(null_id);
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)
175 devmap_null_destroy(null_id);
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;
[79ae36dd]183 aid_t req = async_send_2(exch, VFS_IN_MOUNT, devmap_handle, flags, NULL);
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)
191 devmap_null_destroy(null_id);
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)
206 devmap_null_destroy(null_id);
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)
221 devmap_null_destroy(null_id);
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)
237 devmap_null_destroy(null_id);
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))
250 devmap_null_destroy(null_id);
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
[99272a3]331int open_node(fdi_node_t *node, int oflag)
[2595dab]332{
[79ae36dd]333 async_exch_t *exch = vfs_exchange_begin();
[2595dab]334
335 ipc_call_t answer;
[79ae36dd]336 aid_t req = async_send_4(exch, VFS_IN_OPEN_NODE, node->fs_handle,
[991f645]337 node->devmap_handle, node->index, oflag, &answer);
[2595dab]338
[79ae36dd]339 vfs_exchange_end(exch);
[a28ab12]340
[96b02eb9]341 sysarg_t rc;
[2595dab]342 async_wait_for(req, &rc);
343
344 if (rc != EOK)
[3734106]345 return (int) rc;
[2595dab]346
347 return (int) IPC_GET_ARG1(answer);
348}
349
[72bde81]350int close(int fildes)
351{
[96b02eb9]352 sysarg_t rc;
[19b28b0]353
[79ae36dd]354 async_exch_t *exch = vfs_exchange_begin();
355 rc = async_req_1_0(exch, VFS_IN_CLOSE, fildes);
356 vfs_exchange_end(exch);
[19b28b0]357
[79ae36dd]358 return (int) rc;
[72bde81]359}
360
[2f02aa17]361ssize_t read(int fildes, void *buf, size_t nbyte)
362{
[96b02eb9]363 sysarg_t rc;
[2f02aa17]364 ipc_call_t answer;
365 aid_t req;
[19b28b0]366
[79ae36dd]367 async_exch_t *exch = vfs_exchange_begin();
368
369 req = async_send_1(exch, VFS_IN_READ, fildes, &answer);
370 rc = async_data_read_start(exch, (void *)buf, nbyte);
[07e01e6]371 if (rc != EOK) {
[79ae36dd]372 vfs_exchange_end(exch);
[a28ab12]373
[96b02eb9]374 sysarg_t rc_orig;
[3734106]375 async_wait_for(req, &rc_orig);
[a28ab12]376
[3734106]377 if (rc_orig == EOK)
378 return (ssize_t) rc;
379 else
380 return (ssize_t) rc_orig;
[2f02aa17]381 }
[79ae36dd]382 vfs_exchange_end(exch);
[2f02aa17]383 async_wait_for(req, &rc);
[f7017572]384 if (rc == EOK)
385 return (ssize_t) IPC_GET_ARG1(answer);
386 else
[25becee8]387 return rc;
[2f02aa17]388}
389
[449c246]390ssize_t write(int fildes, const void *buf, size_t nbyte)
391{
[96b02eb9]392 sysarg_t rc;
[449c246]393 ipc_call_t answer;
394 aid_t req;
[19b28b0]395
[79ae36dd]396 async_exch_t *exch = vfs_exchange_begin();
397
398 req = async_send_1(exch, VFS_IN_WRITE, fildes, &answer);
399 rc = async_data_write_start(exch, (void *)buf, nbyte);
[07e01e6]400 if (rc != EOK) {
[79ae36dd]401 vfs_exchange_end(exch);
[a28ab12]402
[96b02eb9]403 sysarg_t rc_orig;
[3734106]404 async_wait_for(req, &rc_orig);
[a28ab12]405
[3734106]406 if (rc_orig == EOK)
407 return (ssize_t) rc;
408 else
409 return (ssize_t) rc_orig;
[449c246]410 }
[79ae36dd]411 vfs_exchange_end(exch);
[449c246]412 async_wait_for(req, &rc);
[f7017572]413 if (rc == EOK)
414 return (ssize_t) IPC_GET_ARG1(answer);
415 else
416 return -1;
[449c246]417}
[222e57c]418
[2595dab]419int fsync(int fildes)
420{
[79ae36dd]421 async_exch_t *exch = vfs_exchange_begin();
422 sysarg_t rc = async_req_1_0(exch, VFS_IN_SYNC, fildes);
423 vfs_exchange_end(exch);
[2595dab]424
425 return (int) rc;
426}
427
[ed903174]428off64_t lseek(int fildes, off64_t offset, int whence)
[222e57c]429{
[79ae36dd]430 async_exch_t *exch = vfs_exchange_begin();
[19b28b0]431
[96b02eb9]432 sysarg_t newoff_lo;
433 sysarg_t newoff_hi;
[79ae36dd]434 sysarg_t rc = async_req_4_2(exch, VFS_IN_SEEK, fildes,
[ed903174]435 LOWER32(offset), UPPER32(offset), whence,
436 &newoff_lo, &newoff_hi);
437
[79ae36dd]438 vfs_exchange_end(exch);
[ed903174]439
[222e57c]440 if (rc != EOK)
[ed903174]441 return (off64_t) -1;
[222e57c]442
[ed903174]443 return (off64_t) MERGE_LOUP32(newoff_lo, newoff_hi);
[222e57c]444}
445
[ed903174]446int ftruncate(int fildes, aoff64_t length)
[0ee4322]447{
[96b02eb9]448 sysarg_t rc;
[0ee4322]449
[79ae36dd]450 async_exch_t *exch = vfs_exchange_begin();
451 rc = async_req_3_0(exch, VFS_IN_TRUNCATE, fildes,
[ed903174]452 LOWER32(length), UPPER32(length));
[79ae36dd]453 vfs_exchange_end(exch);
[ed903174]454
[0ee4322]455 return (int) rc;
456}
457
[852b801]458int fstat(int fildes, struct stat *stat)
459{
[96b02eb9]460 sysarg_t rc;
[852b801]461 aid_t req;
462
[79ae36dd]463 async_exch_t *exch = vfs_exchange_begin();
464
465 req = async_send_1(exch, VFS_IN_FSTAT, fildes, NULL);
466 rc = async_data_read_start(exch, (void *) stat, sizeof(struct stat));
[852b801]467 if (rc != EOK) {
[79ae36dd]468 vfs_exchange_end(exch);
[a28ab12]469
[96b02eb9]470 sysarg_t rc_orig;
[3734106]471 async_wait_for(req, &rc_orig);
[a28ab12]472
[3734106]473 if (rc_orig == EOK)
474 return (ssize_t) rc;
475 else
476 return (ssize_t) rc_orig;
[852b801]477 }
[79ae36dd]478 vfs_exchange_end(exch);
[852b801]479 async_wait_for(req, &rc);
480
481 return rc;
482}
483
[415c7e0d]484int stat(const char *path, struct stat *stat)
485{
[96b02eb9]486 sysarg_t rc;
487 sysarg_t rc_orig;
[415c7e0d]488 aid_t req;
489
490 size_t pa_size;
491 char *pa = absolutize(path, &pa_size);
492 if (!pa)
493 return ENOMEM;
494
[79ae36dd]495 async_exch_t *exch = vfs_exchange_begin();
[415c7e0d]496
[79ae36dd]497 req = async_send_0(exch, VFS_IN_STAT, NULL);
498 rc = async_data_write_start(exch, pa, pa_size);
[415c7e0d]499 if (rc != EOK) {
[79ae36dd]500 vfs_exchange_end(exch);
[415c7e0d]501 free(pa);
[a28ab12]502 async_wait_for(req, &rc_orig);
[3734106]503 if (rc_orig == EOK)
504 return (int) rc;
505 else
506 return (int) rc_orig;
[415c7e0d]507 }
[79ae36dd]508 rc = async_data_read_start(exch, stat, sizeof(struct stat));
[415c7e0d]509 if (rc != EOK) {
[79ae36dd]510 vfs_exchange_end(exch);
[415c7e0d]511 free(pa);
[a28ab12]512 async_wait_for(req, &rc_orig);
[3734106]513 if (rc_orig == EOK)
514 return (int) rc;
515 else
516 return (int) rc_orig;
[415c7e0d]517 }
[79ae36dd]518 vfs_exchange_end(exch);
[415c7e0d]519 free(pa);
[a28ab12]520 async_wait_for(req, &rc);
[415c7e0d]521 return rc;
522}
523
[d0dc74ae]524DIR *opendir(const char *dirname)
525{
526 DIR *dirp = malloc(sizeof(DIR));
527 if (!dirp)
528 return NULL;
[2b88074b]529
530 size_t abs_size;
531 char *abs = absolutize(dirname, &abs_size);
532 if (!abs) {
533 free(dirp);
[ed903174]534 return NULL;
[2b88074b]535 }
536
537 int ret = open_internal(abs, abs_size, L_DIRECTORY, 0);
538 free(abs);
539
540 if (ret < 0) {
[d0dc74ae]541 free(dirp);
542 return NULL;
543 }
[2b88074b]544
545 dirp->fd = ret;
[d0dc74ae]546 return dirp;
547}
548
549struct dirent *readdir(DIR *dirp)
550{
[5973fd0]551 ssize_t len = read(dirp->fd, &dirp->res.d_name[0], NAME_MAX + 1);
552 if (len <= 0)
553 return NULL;
554 return &dirp->res;
[d0dc74ae]555}
556
557void rewinddir(DIR *dirp)
558{
[5973fd0]559 (void) lseek(dirp->fd, 0, SEEK_SET);
[d0dc74ae]560}
561
562int closedir(DIR *dirp)
563{
564 (void) close(dirp->fd);
565 free(dirp);
566 return 0;
567}
568
[72bde81]569int mkdir(const char *path, mode_t mode)
[d0dc74ae]570{
[96b02eb9]571 sysarg_t rc;
[72bde81]572 aid_t req;
573
[9eb3623]574 size_t pa_size;
575 char *pa = absolutize(path, &pa_size);
[5fec355]576 if (!pa)
577 return ENOMEM;
[19b28b0]578
[79ae36dd]579 async_exch_t *exch = vfs_exchange_begin();
[19b28b0]580
[79ae36dd]581 req = async_send_1(exch, VFS_IN_MKDIR, mode, NULL);
582 rc = async_data_write_start(exch, pa, pa_size);
[72bde81]583 if (rc != EOK) {
[79ae36dd]584 vfs_exchange_end(exch);
[a28ab12]585 free(pa);
586
[96b02eb9]587 sysarg_t rc_orig;
[3734106]588 async_wait_for(req, &rc_orig);
[a28ab12]589
[3734106]590 if (rc_orig == EOK)
591 return (int) rc;
592 else
593 return (int) rc_orig;
[72bde81]594 }
[79ae36dd]595 vfs_exchange_end(exch);
[5fec355]596 free(pa);
[a28ab12]597 async_wait_for(req, &rc);
[2595dab]598 return rc;
[d0dc74ae]599}
600
[f15cf1a6]601static int _unlink(const char *path, int lflag)
602{
[96b02eb9]603 sysarg_t rc;
[f15cf1a6]604 aid_t req;
605
[9eb3623]606 size_t pa_size;
607 char *pa = absolutize(path, &pa_size);
[5fec355]608 if (!pa)
609 return ENOMEM;
[19b28b0]610
[79ae36dd]611 async_exch_t *exch = vfs_exchange_begin();
612
613 req = async_send_0(exch, VFS_IN_UNLINK, NULL);
614 rc = async_data_write_start(exch, pa, pa_size);
[f15cf1a6]615 if (rc != EOK) {
[79ae36dd]616 vfs_exchange_end(exch);
[a28ab12]617 free(pa);
[3734106]618
[a28ab12]619 sysarg_t rc_orig;
[3734106]620 async_wait_for(req, &rc_orig);
[a28ab12]621
[3734106]622 if (rc_orig == EOK)
623 return (int) rc;
624 else
625 return (int) rc_orig;
[f15cf1a6]626 }
[79ae36dd]627 vfs_exchange_end(exch);
[5fec355]628 free(pa);
[a28ab12]629 async_wait_for(req, &rc);
[2595dab]630 return rc;
[f15cf1a6]631}
632
633int unlink(const char *path)
634{
635 return _unlink(path, L_NONE);
636}
637
638int rmdir(const char *path)
639{
640 return _unlink(path, L_DIRECTORY);
641}
642
[a8e9ab8d]643int rename(const char *old, const char *new)
644{
[96b02eb9]645 sysarg_t rc;
646 sysarg_t rc_orig;
[a8e9ab8d]647 aid_t req;
648
[9eb3623]649 size_t olda_size;
650 char *olda = absolutize(old, &olda_size);
[a8e9ab8d]651 if (!olda)
652 return ENOMEM;
[923c39e]653
[9eb3623]654 size_t newa_size;
655 char *newa = absolutize(new, &newa_size);
[a8e9ab8d]656 if (!newa) {
657 free(olda);
658 return ENOMEM;
659 }
[19b28b0]660
[79ae36dd]661 async_exch_t *exch = vfs_exchange_begin();
662
663 req = async_send_0(exch, VFS_IN_RENAME, NULL);
664 rc = async_data_write_start(exch, olda, olda_size);
[a8e9ab8d]665 if (rc != EOK) {
[79ae36dd]666 vfs_exchange_end(exch);
[a8e9ab8d]667 free(olda);
668 free(newa);
[a28ab12]669 async_wait_for(req, &rc_orig);
[3734106]670 if (rc_orig == EOK)
671 return (int) rc;
672 else
673 return (int) rc_orig;
[a8e9ab8d]674 }
[79ae36dd]675 rc = async_data_write_start(exch, newa, newa_size);
[a8e9ab8d]676 if (rc != EOK) {
[79ae36dd]677 vfs_exchange_end(exch);
[a8e9ab8d]678 free(olda);
679 free(newa);
[a28ab12]680 async_wait_for(req, &rc_orig);
[3734106]681 if (rc_orig == EOK)
682 return (int) rc;
683 else
684 return (int) rc_orig;
[a8e9ab8d]685 }
[79ae36dd]686 vfs_exchange_end(exch);
[a8e9ab8d]687 free(olda);
688 free(newa);
[a28ab12]689 async_wait_for(req, &rc);
[a8e9ab8d]690 return rc;
691}
692
[5fec355]693int chdir(const char *path)
694{
[2b88074b]695 size_t abs_size;
696 char *abs = absolutize(path, &abs_size);
697 if (!abs)
[5fec355]698 return ENOMEM;
[2b88074b]699
700 int fd = open_internal(abs, abs_size, L_DIRECTORY, O_DESC);
701
702 if (fd < 0) {
703 free(abs);
[5fec355]704 return ENOENT;
705 }
[2b88074b]706
[a28ab12]707 fibril_mutex_lock(&cwd_mutex);
[2b88074b]708
709 if (cwd_fd >= 0)
710 close(cwd_fd);
711
712
713 if (cwd_path)
714 free(cwd_path);
715
716 cwd_fd = fd;
717 cwd_path = abs;
718 cwd_size = abs_size;
719
[a28ab12]720 fibril_mutex_unlock(&cwd_mutex);
[0dd0f71f]721 return EOK;
[5fec355]722}
723
724char *getcwd(char *buf, size_t size)
725{
[2b88074b]726 if (size == 0)
[5fec355]727 return NULL;
[2b88074b]728
[a28ab12]729 fibril_mutex_lock(&cwd_mutex);
[2b88074b]730
731 if ((cwd_size == 0) || (size < cwd_size + 1)) {
[a28ab12]732 fibril_mutex_unlock(&cwd_mutex);
[5fec355]733 return NULL;
734 }
[2b88074b]735
[6eb2e96]736 str_cpy(buf, size, cwd_path);
[a28ab12]737 fibril_mutex_unlock(&cwd_mutex);
[2b88074b]738
[5fec355]739 return buf;
740}
741
[79ae36dd]742async_sess_t *fd_session(exch_mgmt_t mgmt, int fildes)
[852b801]743{
744 struct stat stat;
[8caaea7]745 int rc = fstat(fildes, &stat);
[79ae36dd]746 if (rc != 0) {
747 errno = rc;
748 return NULL;
749 }
[8caaea7]750
[79ae36dd]751 if (!stat.device) {
752 errno = ENOENT;
753 return NULL;
754 }
[852b801]755
[79ae36dd]756 return devmap_device_connect(mgmt, stat.device, 0);
[852b801]757}
758
759int fd_node(int fildes, fdi_node_t *node)
760{
761 struct stat stat;
[79ae36dd]762 int rc = fstat(fildes, &stat);
[852b801]763
764 if (rc == EOK) {
765 node->fs_handle = stat.fs_handle;
[991f645]766 node->devmap_handle = stat.devmap_handle;
[852b801]767 node->index = stat.index;
768 }
769
770 return rc;
771}
772
[2b88074b]773int dup2(int oldfd, int newfd)
774{
[79ae36dd]775 async_exch_t *exch = vfs_exchange_begin();
[2b88074b]776
[96b02eb9]777 sysarg_t ret;
[79ae36dd]778 sysarg_t rc = async_req_2_1(exch, VFS_IN_DUP, oldfd, newfd, &ret);
[2b88074b]779
[79ae36dd]780 vfs_exchange_end(exch);
[2b88074b]781
782 if (rc == EOK)
783 return (int) ret;
784
785 return (int) rc;
786}
787
[2f02aa17]788/** @}
789 */
Note: See TracBrowser for help on using the repository browser.