source: mainline/uspace/lib/c/generic/vfs/vfs.c@ 84dc30c

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 84dc30c was 38db6288, checked in by Jiri Svoboda <jiri@…>, 12 years ago

Add remove() function from C standard.

  • Property mode set to 100644
File size: 18.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>
[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
[fa24efa]344ssize_t read(int fildes, void *buf, size_t nbyte)
[2f02aa17]345{
[96b02eb9]346 sysarg_t rc;
[2f02aa17]347 ipc_call_t answer;
348 aid_t req;
[19b28b0]349
[fa24efa]350 if (nbyte > DATA_XFER_LIMIT)
351 nbyte = DATA_XFER_LIMIT;
352
[79ae36dd]353 async_exch_t *exch = vfs_exchange_begin();
354
355 req = async_send_1(exch, VFS_IN_READ, fildes, &answer);
[fa24efa]356 rc = async_data_read_start(exch, (void *) buf, nbyte);
[07e01e6]357 if (rc != EOK) {
[79ae36dd]358 vfs_exchange_end(exch);
[a28ab12]359
[96b02eb9]360 sysarg_t rc_orig;
[3734106]361 async_wait_for(req, &rc_orig);
[a28ab12]362
[3734106]363 if (rc_orig == EOK)
364 return (ssize_t) rc;
365 else
366 return (ssize_t) rc_orig;
[2f02aa17]367 }
[79ae36dd]368 vfs_exchange_end(exch);
[2f02aa17]369 async_wait_for(req, &rc);
[f7017572]370 if (rc == EOK)
371 return (ssize_t) IPC_GET_ARG1(answer);
372 else
[25becee8]373 return rc;
[2f02aa17]374}
375
[449c246]376ssize_t write(int fildes, const void *buf, size_t nbyte)
377{
[96b02eb9]378 sysarg_t rc;
[449c246]379 ipc_call_t answer;
380 aid_t req;
[19b28b0]381
[fa24efa]382 if (nbyte > DATA_XFER_LIMIT)
383 nbyte = DATA_XFER_LIMIT;
384
[79ae36dd]385 async_exch_t *exch = vfs_exchange_begin();
386
387 req = async_send_1(exch, VFS_IN_WRITE, fildes, &answer);
[fa24efa]388 rc = async_data_write_start(exch, (void *) buf, nbyte);
[07e01e6]389 if (rc != EOK) {
[79ae36dd]390 vfs_exchange_end(exch);
[a28ab12]391
[96b02eb9]392 sysarg_t rc_orig;
[3734106]393 async_wait_for(req, &rc_orig);
[a28ab12]394
[3734106]395 if (rc_orig == EOK)
396 return (ssize_t) rc;
397 else
398 return (ssize_t) rc_orig;
[449c246]399 }
[79ae36dd]400 vfs_exchange_end(exch);
[449c246]401 async_wait_for(req, &rc);
[f7017572]402 if (rc == EOK)
403 return (ssize_t) IPC_GET_ARG1(answer);
404 else
405 return -1;
[449c246]406}
[222e57c]407
[8fd04ba9]408/** Read entire buffer.
409 *
410 * In face of short reads this function continues reading until either
411 * the entire buffer is read or no more data is available (at end of file).
412 *
413 * @param fildes File descriptor
414 * @param buf Buffer, @a nbytes bytes long
415 * @param nbytes Number of bytes to read
416 *
417 * @return On success, positive number of bytes read.
418 * On failure, negative error code from read().
419 */
420ssize_t read_all(int fildes, void *buf, size_t nbyte)
421{
422 ssize_t cnt = 0;
423 size_t nread = 0;
424 uint8_t *bp = (uint8_t *) buf;
425
426 do {
427 bp += cnt;
428 nread += cnt;
429 cnt = read(fildes, bp, nbyte - nread);
430 } while (cnt > 0 && (nbyte - nread - cnt) > 0);
431
432 if (cnt < 0)
433 return cnt;
434
435 return nread + cnt;
436}
437
438/** Write entire buffer.
439 *
440 * This function fails if it cannot write exactly @a len bytes to the file.
441 *
442 * @param fildes File descriptor
443 * @param buf Data, @a nbytes bytes long
444 * @param nbytes Number of bytes to write
445 *
446 * @return EOK on error, return value from write() if writing
447 * failed.
448 */
449ssize_t write_all(int fildes, const void *buf, size_t nbyte)
450{
451 ssize_t cnt = 0;
452 ssize_t nwritten = 0;
453 const uint8_t *bp = (uint8_t *) buf;
454
455 do {
456 bp += cnt;
457 nwritten += cnt;
458 cnt = write(fildes, bp, nbyte - nwritten);
459 } while (cnt > 0 && ((ssize_t )nbyte - nwritten - cnt) > 0);
460
461 if (cnt < 0)
462 return cnt;
463
464 if ((ssize_t)nbyte - nwritten - cnt > 0)
465 return EIO;
466
467 return nbyte;
468}
469
[2595dab]470int fsync(int fildes)
471{
[79ae36dd]472 async_exch_t *exch = vfs_exchange_begin();
473 sysarg_t rc = async_req_1_0(exch, VFS_IN_SYNC, fildes);
474 vfs_exchange_end(exch);
[2595dab]475
476 return (int) rc;
477}
478
[ed903174]479off64_t lseek(int fildes, off64_t offset, int whence)
[222e57c]480{
[79ae36dd]481 async_exch_t *exch = vfs_exchange_begin();
[19b28b0]482
[96b02eb9]483 sysarg_t newoff_lo;
484 sysarg_t newoff_hi;
[79ae36dd]485 sysarg_t rc = async_req_4_2(exch, VFS_IN_SEEK, fildes,
[ed903174]486 LOWER32(offset), UPPER32(offset), whence,
487 &newoff_lo, &newoff_hi);
488
[79ae36dd]489 vfs_exchange_end(exch);
[ed903174]490
[222e57c]491 if (rc != EOK)
[ed903174]492 return (off64_t) -1;
[222e57c]493
[ed903174]494 return (off64_t) MERGE_LOUP32(newoff_lo, newoff_hi);
[222e57c]495}
496
[ed903174]497int ftruncate(int fildes, aoff64_t length)
[0ee4322]498{
[96b02eb9]499 sysarg_t rc;
[0ee4322]500
[79ae36dd]501 async_exch_t *exch = vfs_exchange_begin();
502 rc = async_req_3_0(exch, VFS_IN_TRUNCATE, fildes,
[ed903174]503 LOWER32(length), UPPER32(length));
[79ae36dd]504 vfs_exchange_end(exch);
[ed903174]505
[0ee4322]506 return (int) rc;
507}
508
[852b801]509int fstat(int fildes, struct stat *stat)
510{
[96b02eb9]511 sysarg_t rc;
[852b801]512 aid_t req;
513
[79ae36dd]514 async_exch_t *exch = vfs_exchange_begin();
515
516 req = async_send_1(exch, VFS_IN_FSTAT, fildes, NULL);
517 rc = async_data_read_start(exch, (void *) stat, sizeof(struct stat));
[852b801]518 if (rc != EOK) {
[79ae36dd]519 vfs_exchange_end(exch);
[a28ab12]520
[96b02eb9]521 sysarg_t rc_orig;
[3734106]522 async_wait_for(req, &rc_orig);
[a28ab12]523
[3734106]524 if (rc_orig == EOK)
525 return (ssize_t) rc;
526 else
527 return (ssize_t) rc_orig;
[852b801]528 }
[79ae36dd]529 vfs_exchange_end(exch);
[852b801]530 async_wait_for(req, &rc);
531
532 return rc;
533}
534
[415c7e0d]535int stat(const char *path, struct stat *stat)
536{
[96b02eb9]537 sysarg_t rc;
538 sysarg_t rc_orig;
[415c7e0d]539 aid_t req;
540
541 size_t pa_size;
542 char *pa = absolutize(path, &pa_size);
543 if (!pa)
544 return ENOMEM;
545
[79ae36dd]546 async_exch_t *exch = vfs_exchange_begin();
[415c7e0d]547
[79ae36dd]548 req = async_send_0(exch, VFS_IN_STAT, NULL);
549 rc = async_data_write_start(exch, pa, pa_size);
[415c7e0d]550 if (rc != EOK) {
[79ae36dd]551 vfs_exchange_end(exch);
[415c7e0d]552 free(pa);
[a28ab12]553 async_wait_for(req, &rc_orig);
[3734106]554 if (rc_orig == EOK)
555 return (int) rc;
556 else
557 return (int) rc_orig;
[415c7e0d]558 }
[79ae36dd]559 rc = async_data_read_start(exch, stat, sizeof(struct stat));
[415c7e0d]560 if (rc != EOK) {
[79ae36dd]561 vfs_exchange_end(exch);
[415c7e0d]562 free(pa);
[a28ab12]563 async_wait_for(req, &rc_orig);
[3734106]564 if (rc_orig == EOK)
565 return (int) rc;
566 else
567 return (int) rc_orig;
[415c7e0d]568 }
[79ae36dd]569 vfs_exchange_end(exch);
[415c7e0d]570 free(pa);
[a28ab12]571 async_wait_for(req, &rc);
[415c7e0d]572 return rc;
573}
574
[d0dc74ae]575DIR *opendir(const char *dirname)
576{
577 DIR *dirp = malloc(sizeof(DIR));
578 if (!dirp)
579 return NULL;
[2b88074b]580
581 size_t abs_size;
582 char *abs = absolutize(dirname, &abs_size);
583 if (!abs) {
584 free(dirp);
[ed903174]585 return NULL;
[2b88074b]586 }
587
588 int ret = open_internal(abs, abs_size, L_DIRECTORY, 0);
589 free(abs);
590
591 if (ret < 0) {
[d0dc74ae]592 free(dirp);
593 return NULL;
594 }
[2b88074b]595
596 dirp->fd = ret;
[d0dc74ae]597 return dirp;
598}
599
600struct dirent *readdir(DIR *dirp)
601{
[5973fd0]602 ssize_t len = read(dirp->fd, &dirp->res.d_name[0], NAME_MAX + 1);
603 if (len <= 0)
604 return NULL;
605 return &dirp->res;
[d0dc74ae]606}
607
608void rewinddir(DIR *dirp)
609{
[5973fd0]610 (void) lseek(dirp->fd, 0, SEEK_SET);
[d0dc74ae]611}
612
613int closedir(DIR *dirp)
614{
615 (void) close(dirp->fd);
616 free(dirp);
617 return 0;
618}
619
[72bde81]620int mkdir(const char *path, mode_t mode)
[d0dc74ae]621{
[96b02eb9]622 sysarg_t rc;
[72bde81]623 aid_t req;
624
[9eb3623]625 size_t pa_size;
626 char *pa = absolutize(path, &pa_size);
[5fec355]627 if (!pa)
628 return ENOMEM;
[19b28b0]629
[79ae36dd]630 async_exch_t *exch = vfs_exchange_begin();
[19b28b0]631
[79ae36dd]632 req = async_send_1(exch, VFS_IN_MKDIR, mode, NULL);
633 rc = async_data_write_start(exch, pa, pa_size);
[72bde81]634 if (rc != EOK) {
[79ae36dd]635 vfs_exchange_end(exch);
[a28ab12]636 free(pa);
637
[96b02eb9]638 sysarg_t rc_orig;
[3734106]639 async_wait_for(req, &rc_orig);
[a28ab12]640
[3734106]641 if (rc_orig == EOK)
642 return (int) rc;
643 else
644 return (int) rc_orig;
[72bde81]645 }
[79ae36dd]646 vfs_exchange_end(exch);
[5fec355]647 free(pa);
[a28ab12]648 async_wait_for(req, &rc);
[2595dab]649 return rc;
[d0dc74ae]650}
651
[f15cf1a6]652static int _unlink(const char *path, int lflag)
653{
[96b02eb9]654 sysarg_t rc;
[f15cf1a6]655 aid_t req;
656
[9eb3623]657 size_t pa_size;
658 char *pa = absolutize(path, &pa_size);
[5fec355]659 if (!pa)
660 return ENOMEM;
[19b28b0]661
[79ae36dd]662 async_exch_t *exch = vfs_exchange_begin();
663
[9ea7d90]664 req = async_send_1(exch, VFS_IN_UNLINK, lflag, NULL);
[79ae36dd]665 rc = async_data_write_start(exch, pa, pa_size);
[f15cf1a6]666 if (rc != EOK) {
[79ae36dd]667 vfs_exchange_end(exch);
[a28ab12]668 free(pa);
[3734106]669
[a28ab12]670 sysarg_t rc_orig;
[3734106]671 async_wait_for(req, &rc_orig);
[a28ab12]672
[3734106]673 if (rc_orig == EOK)
674 return (int) rc;
675 else
676 return (int) rc_orig;
[f15cf1a6]677 }
[79ae36dd]678 vfs_exchange_end(exch);
[5fec355]679 free(pa);
[a28ab12]680 async_wait_for(req, &rc);
[2595dab]681 return rc;
[f15cf1a6]682}
683
684int unlink(const char *path)
685{
686 return _unlink(path, L_NONE);
687}
688
689int rmdir(const char *path)
690{
691 return _unlink(path, L_DIRECTORY);
692}
693
[a8e9ab8d]694int rename(const char *old, const char *new)
695{
[96b02eb9]696 sysarg_t rc;
697 sysarg_t rc_orig;
[a8e9ab8d]698 aid_t req;
699
[9eb3623]700 size_t olda_size;
701 char *olda = absolutize(old, &olda_size);
[a8e9ab8d]702 if (!olda)
703 return ENOMEM;
[923c39e]704
[9eb3623]705 size_t newa_size;
706 char *newa = absolutize(new, &newa_size);
[a8e9ab8d]707 if (!newa) {
708 free(olda);
709 return ENOMEM;
710 }
[19b28b0]711
[79ae36dd]712 async_exch_t *exch = vfs_exchange_begin();
713
714 req = async_send_0(exch, VFS_IN_RENAME, NULL);
715 rc = async_data_write_start(exch, olda, olda_size);
[a8e9ab8d]716 if (rc != EOK) {
[79ae36dd]717 vfs_exchange_end(exch);
[a8e9ab8d]718 free(olda);
719 free(newa);
[a28ab12]720 async_wait_for(req, &rc_orig);
[3734106]721 if (rc_orig == EOK)
722 return (int) rc;
723 else
724 return (int) rc_orig;
[a8e9ab8d]725 }
[79ae36dd]726 rc = async_data_write_start(exch, newa, newa_size);
[a8e9ab8d]727 if (rc != EOK) {
[79ae36dd]728 vfs_exchange_end(exch);
[a8e9ab8d]729 free(olda);
730 free(newa);
[a28ab12]731 async_wait_for(req, &rc_orig);
[3734106]732 if (rc_orig == EOK)
733 return (int) rc;
734 else
735 return (int) rc_orig;
[a8e9ab8d]736 }
[79ae36dd]737 vfs_exchange_end(exch);
[a8e9ab8d]738 free(olda);
739 free(newa);
[a28ab12]740 async_wait_for(req, &rc);
[a8e9ab8d]741 return rc;
742}
743
[38db6288]744int remove(const char *path)
745{
746 return unlink(path);
747}
748
[5fec355]749int chdir(const char *path)
750{
[2b88074b]751 size_t abs_size;
752 char *abs = absolutize(path, &abs_size);
753 if (!abs)
[5fec355]754 return ENOMEM;
[2b88074b]755
756 int fd = open_internal(abs, abs_size, L_DIRECTORY, O_DESC);
757
758 if (fd < 0) {
759 free(abs);
[5fec355]760 return ENOENT;
761 }
[2b88074b]762
[a28ab12]763 fibril_mutex_lock(&cwd_mutex);
[2b88074b]764
765 if (cwd_fd >= 0)
766 close(cwd_fd);
767
768
769 if (cwd_path)
770 free(cwd_path);
771
772 cwd_fd = fd;
773 cwd_path = abs;
774 cwd_size = abs_size;
775
[a28ab12]776 fibril_mutex_unlock(&cwd_mutex);
[0dd0f71f]777 return EOK;
[5fec355]778}
779
780char *getcwd(char *buf, size_t size)
781{
[2b88074b]782 if (size == 0)
[5fec355]783 return NULL;
[2b88074b]784
[a28ab12]785 fibril_mutex_lock(&cwd_mutex);
[2b88074b]786
787 if ((cwd_size == 0) || (size < cwd_size + 1)) {
[a28ab12]788 fibril_mutex_unlock(&cwd_mutex);
[5fec355]789 return NULL;
790 }
[2b88074b]791
[6eb2e96]792 str_cpy(buf, size, cwd_path);
[a28ab12]793 fibril_mutex_unlock(&cwd_mutex);
[2b88074b]794
[5fec355]795 return buf;
796}
797
[79ae36dd]798async_sess_t *fd_session(exch_mgmt_t mgmt, int fildes)
[852b801]799{
800 struct stat stat;
[8caaea7]801 int rc = fstat(fildes, &stat);
[79ae36dd]802 if (rc != 0) {
803 errno = rc;
804 return NULL;
805 }
[8caaea7]806
[15f3c3f]807 if (!stat.service) {
[79ae36dd]808 errno = ENOENT;
809 return NULL;
810 }
[852b801]811
[15f3c3f]812 return loc_service_connect(mgmt, stat.service, 0);
[852b801]813}
814
[2b88074b]815int dup2(int oldfd, int newfd)
[852b801]816{
[79ae36dd]817 async_exch_t *exch = vfs_exchange_begin();
[852b801]818
[96b02eb9]819 sysarg_t ret;
[79ae36dd]820 sysarg_t rc = async_req_2_1(exch, VFS_IN_DUP, oldfd, newfd, &ret);
[852b801]821
[79ae36dd]822 vfs_exchange_end(exch);
[2b88074b]823
824 if (rc == EOK)
825 return (int) ret;
826
827 return (int) rc;
[852b801]828}
829
[27b76ca]830int fd_wait(void)
[2b88074b]831{
[79ae36dd]832 async_exch_t *exch = vfs_exchange_begin();
[2b88074b]833
[96b02eb9]834 sysarg_t ret;
[27b76ca]835 sysarg_t rc = async_req_0_1(exch, VFS_IN_WAIT_HANDLE, &ret);
[2b88074b]836
[79ae36dd]837 vfs_exchange_end(exch);
[2b88074b]838
839 if (rc == EOK)
840 return (int) ret;
841
842 return (int) rc;
843}
844
[10e4cd7]845int get_mtab_list(list_t *mtab_list)
846{
847 sysarg_t rc;
[4965357f]848 aid_t req;
[10e4cd7]849 size_t i;
[4965357f]850 sysarg_t num_mounted_fs;
[10e4cd7]851
852 async_exch_t *exch = vfs_exchange_begin();
853
[41e9ef7]854 req = async_send_0(exch, VFS_IN_MTAB_GET, NULL);
[10e4cd7]855
856 /* Ask VFS how many filesystems are mounted */
857 rc = async_req_0_1(exch, VFS_IN_PING, &num_mounted_fs);
858 if (rc != EOK)
859 goto exit;
860
861 for (i = 0; i < num_mounted_fs; ++i) {
862 mtab_ent_t *mtab_ent;
863
[8d6a41c]864 mtab_ent = malloc(sizeof(mtab_ent_t));
865 if (!mtab_ent) {
[10e4cd7]866 rc = ENOMEM;
867 goto exit;
868 }
869
[8d6a41c]870 memset(mtab_ent, 0, sizeof(mtab_ent_t));
[10e4cd7]871
[4965357f]872 rc = async_data_read_start(exch, (void *) mtab_ent->mp,
[10e4cd7]873 MAX_PATH_LEN);
874 if (rc != EOK)
875 goto exit;
876
[4965357f]877 rc = async_data_read_start(exch, (void *) mtab_ent->opts,
[10e4cd7]878 MAX_MNTOPTS_LEN);
879 if (rc != EOK)
880 goto exit;
881
[4965357f]882 rc = async_data_read_start(exch, (void *) mtab_ent->fs_name,
[10e4cd7]883 FS_NAME_MAXLEN);
884 if (rc != EOK)
885 goto exit;
886
[6b8e5b74]887 sysarg_t p[2];
[10e4cd7]888
[6b8e5b74]889 rc = async_req_0_2(exch, VFS_IN_PING, &p[0], &p[1]);
[f8838b8]890 if (rc != EOK)
891 goto exit;
[10e4cd7]892
[6b8e5b74]893 mtab_ent->instance = p[0];
894 mtab_ent->service_id = p[1];
[10e4cd7]895
[8d6a41c]896 link_initialize(&mtab_ent->link);
897 list_append(&mtab_ent->link, mtab_list);
[10e4cd7]898 }
899
900exit:
[4965357f]901 async_wait_for(req, &rc);
[10e4cd7]902 vfs_exchange_end(exch);
903 return rc;
904}
905
[73fbcbb]906int statfs(const char *path, struct statfs *st)
[66366470]907{
[73fbcbb]908 sysarg_t rc, rc_orig;
[9dc6083]909 aid_t req;
910 size_t pa_size;
[73fbcbb]911
[9dc6083]912 char *pa = absolutize(path, &pa_size);
913 if (!pa)
914 return ENOMEM;
[73fbcbb]915
[9dc6083]916 async_exch_t *exch = vfs_exchange_begin();
[73fbcbb]917
[9dc6083]918 req = async_send_0(exch, VFS_IN_STATFS, NULL);
919 rc = async_data_write_start(exch, pa, pa_size);
[73fbcbb]920 if (rc != EOK)
921 goto exit;
922
923 rc = async_data_read_start(exch, (void *) st, sizeof(*st));
924
925exit:
[66366470]926 vfs_exchange_end(exch);
[9dc6083]927 free(pa);
[73fbcbb]928 async_wait_for(req, &rc_orig);
929 return (int) (rc_orig != EOK ? rc_orig : rc);
[66366470]930}
931
[2f02aa17]932/** @}
933 */
Note: See TracBrowser for help on using the repository browser.