source: mainline/uspace/lib/c/generic/vfs/vfs.c@ 286286c

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

Cstyle fixes and cleanup.

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