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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since b8dbe2f was 4636a60, checked in by Jiri Zarevucky <zarevucky.jiri@…>, 12 years ago

Handle mounts at the server side, instead of in the endpoints.

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