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
Line 
1/*
2 * Copyright (c) 2008 Jakub Jermar
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 */
34
35#include <vfs/canonify.h>
36#include <vfs/vfs.h>
37#include <vfs/vfs_sess.h>
38#include <macros.h>
39#include <stdlib.h>
40#include <unistd.h>
41#include <dirent.h>
42#include <fcntl.h>
43#include <stdio.h>
44#include <sys/stat.h>
45#include <sys/types.h>
46#include <ipc/services.h>
47#include <ns.h>
48#include <async.h>
49#include <fibril_synch.h>
50#include <errno.h>
51#include <assert.h>
52#include <str.h>
53#include <loc.h>
54#include <ipc/vfs.h>
55#include <ipc/loc.h>
56
57static FIBRIL_MUTEX_INITIALIZE(vfs_mutex);
58static async_sess_t *vfs_sess = NULL;
59
60static FIBRIL_MUTEX_INITIALIZE(cwd_mutex);
61
62static int cwd_fd = -1;
63static char *cwd_path = NULL;
64static size_t cwd_size = 0;
65
66/** Start an async exchange on the VFS session.
67 *
68 * @return New exchange.
69 *
70 */
71async_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 */
89void vfs_exchange_end(async_exch_t *exch)
90{
91 async_exchange_end(exch);
92}
93
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);
100 sysarg_t rc = async_data_write_start(exch, path, str_size(path));
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
126char *absolutize(const char *path, size_t *retlen)
127{
128 char *ncwd_path;
129 char *ncwd_path_nc;
130
131 fibril_mutex_lock(&cwd_mutex);
132 size_t size = str_size(path);
133 if (*path != '/') {
134 if (!cwd_path) {
135 fibril_mutex_unlock(&cwd_mutex);
136 return NULL;
137 }
138 ncwd_path_nc = malloc(cwd_size + 1 + size + 1);
139 if (!ncwd_path_nc) {
140 fibril_mutex_unlock(&cwd_mutex);
141 return NULL;
142 }
143 str_cpy(ncwd_path_nc, cwd_size + 1 + size + 1, cwd_path);
144 ncwd_path_nc[cwd_size] = '/';
145 ncwd_path_nc[cwd_size + 1] = '\0';
146 } else {
147 ncwd_path_nc = malloc(size + 1);
148 if (!ncwd_path_nc) {
149 fibril_mutex_unlock(&cwd_mutex);
150 return NULL;
151 }
152 ncwd_path_nc[0] = '\0';
153 }
154 str_append(ncwd_path_nc, cwd_size + 1 + size + 1, path);
155 ncwd_path = canonify(ncwd_path_nc, retlen);
156 if (!ncwd_path) {
157 fibril_mutex_unlock(&cwd_mutex);
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 */
166 ncwd_path = str_dup(ncwd_path);
167 free(ncwd_path_nc);
168 if (!ncwd_path) {
169 fibril_mutex_unlock(&cwd_mutex);
170 return NULL;
171 }
172 fibril_mutex_unlock(&cwd_mutex);
173 return ncwd_path;
174}
175
176int mount(const char *fs_name, const char *mp, const char *fqsn,
177 const char *opts, unsigned int flags, unsigned int instance)
178{
179 int null_id = -1;
180 char null[LOC_NAME_MAXLEN];
181
182 if (str_cmp(fqsn, "") == 0) {
183 /* No device specified, create a fresh
184 null/%d device instead */
185 null_id = loc_null_create();
186
187 if (null_id == -1)
188 return ENOMEM;
189
190 snprintf(null, LOC_NAME_MAXLEN, "null/%d", null_id);
191 fqsn = null;
192 }
193
194 service_id_t service_id;
195 int res = loc_service_get_id(fqsn, &service_id, flags);
196 if (res != EOK) {
197 if (null_id != -1)
198 loc_null_destroy(null_id);
199
200 return res;
201 }
202
203 size_t mpa_size;
204 char *mpa = absolutize(mp, &mpa_size);
205 if (!mpa) {
206 if (null_id != -1)
207 loc_null_destroy(null_id);
208
209 return ENOMEM;
210 }
211
212 async_exch_t *exch = vfs_exchange_begin();
213
214 sysarg_t rc_orig;
215 aid_t req = async_send_3(exch, VFS_IN_MOUNT, service_id, flags,
216 instance, NULL);
217 sysarg_t rc = async_data_write_start(exch, (void *) mpa, mpa_size);
218 if (rc != EOK) {
219 vfs_exchange_end(exch);
220 free(mpa);
221 async_wait_for(req, &rc_orig);
222
223 if (null_id != -1)
224 loc_null_destroy(null_id);
225
226 if (rc_orig == EOK)
227 return (int) rc;
228 else
229 return (int) rc_orig;
230 }
231
232 rc = async_data_write_start(exch, (void *) opts, str_size(opts));
233 if (rc != EOK) {
234 vfs_exchange_end(exch);
235 free(mpa);
236 async_wait_for(req, &rc_orig);
237
238 if (null_id != -1)
239 loc_null_destroy(null_id);
240
241 if (rc_orig == EOK)
242 return (int) rc;
243 else
244 return (int) rc_orig;
245 }
246
247 rc = async_data_write_start(exch, (void *) fs_name, str_size(fs_name));
248 if (rc != EOK) {
249 vfs_exchange_end(exch);
250 free(mpa);
251 async_wait_for(req, &rc_orig);
252
253 if (null_id != -1)
254 loc_null_destroy(null_id);
255
256 if (rc_orig == EOK)
257 return (int) rc;
258 else
259 return (int) rc_orig;
260 }
261
262 vfs_exchange_end(exch);
263 free(mpa);
264 async_wait_for(req, &rc);
265
266 if ((rc != EOK) && (null_id != -1))
267 loc_null_destroy(null_id);
268
269 return (int) rc;
270}
271
272int unmount(const char *mp)
273{
274 sysarg_t rc;
275 sysarg_t rc_orig;
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
284 async_exch_t *exch = vfs_exchange_begin();
285
286 req = async_send_0(exch, VFS_IN_UNMOUNT, NULL);
287 rc = async_data_write_start(exch, (void *) mpa, mpa_size);
288 if (rc != EOK) {
289 vfs_exchange_end(exch);
290 free(mpa);
291 async_wait_for(req, &rc_orig);
292 if (rc_orig == EOK)
293 return (int) rc;
294 else
295 return (int) rc_orig;
296 }
297
298
299 vfs_exchange_end(exch);
300 free(mpa);
301 async_wait_for(req, &rc);
302
303 return (int) rc;
304}
305
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
319int open(const char *path, int oflag, ...)
320{
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
328 size_t abs_size;
329 char *abs = absolutize(path, &abs_size);
330 if (!abs) {
331 return ENOMEM;
332 }
333
334 int ret = _vfs_walk(-1, abs, walk_flags(oflag) | WALK_REGULAR);
335 if (ret < 0) {
336 return ret;
337 }
338
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 }
351
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
360 return ret;
361}
362
363int close(int fildes)
364{
365 sysarg_t rc;
366
367 async_exch_t *exch = vfs_exchange_begin();
368 rc = async_req_1_0(exch, VFS_IN_CLOSE, fildes);
369 vfs_exchange_end(exch);
370
371 return (int) rc;
372}
373
374// TODO: Versioning for read.
375
376ssize_t read(int fildes, void *buf, size_t nbyte)
377{
378 sysarg_t rc;
379 ipc_call_t answer;
380 aid_t req;
381
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);
386 if (rc != EOK) {
387 vfs_exchange_end(exch);
388
389 sysarg_t rc_orig;
390 async_wait_for(req, &rc_orig);
391
392 if (rc_orig == EOK)
393 return (ssize_t) rc;
394 else
395 return (ssize_t) rc_orig;
396 }
397 vfs_exchange_end(exch);
398 async_wait_for(req, &rc);
399 if (rc == EOK)
400 return (ssize_t) IPC_GET_ARG1(answer);
401 else
402 return rc;
403}
404
405ssize_t write(int fildes, const void *buf, size_t nbyte)
406{
407 sysarg_t rc;
408 ipc_call_t answer;
409 aid_t req;
410
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);
415 if (rc != EOK) {
416 vfs_exchange_end(exch);
417
418 sysarg_t rc_orig;
419 async_wait_for(req, &rc_orig);
420
421 if (rc_orig == EOK)
422 return (ssize_t) rc;
423 else
424 return (ssize_t) rc_orig;
425 }
426 vfs_exchange_end(exch);
427 async_wait_for(req, &rc);
428 if (rc == EOK)
429 return (ssize_t) IPC_GET_ARG1(answer);
430 else
431 return -1;
432}
433
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
496int fsync(int fildes)
497{
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);
501
502 return (int) rc;
503}
504
505off64_t lseek(int fildes, off64_t offset, int whence)
506{
507 async_exch_t *exch = vfs_exchange_begin();
508
509 sysarg_t newoff_lo;
510 sysarg_t newoff_hi;
511 sysarg_t rc = async_req_4_2(exch, VFS_IN_SEEK, fildes,
512 LOWER32(offset), UPPER32(offset), whence,
513 &newoff_lo, &newoff_hi);
514
515 vfs_exchange_end(exch);
516
517 if (rc != EOK)
518 return (off64_t) -1;
519
520 return (off64_t) MERGE_LOUP32(newoff_lo, newoff_hi);
521}
522
523int ftruncate(int fildes, aoff64_t length)
524{
525 sysarg_t rc;
526
527 async_exch_t *exch = vfs_exchange_begin();
528 rc = async_req_3_0(exch, VFS_IN_TRUNCATE, fildes,
529 LOWER32(length), UPPER32(length));
530 vfs_exchange_end(exch);
531
532 return (int) rc;
533}
534
535int fstat(int fildes, struct stat *stat)
536{
537 sysarg_t rc;
538 aid_t req;
539
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));
544 if (rc != EOK) {
545 vfs_exchange_end(exch);
546
547 sysarg_t rc_orig;
548 async_wait_for(req, &rc_orig);
549
550 if (rc_orig == EOK)
551 return (ssize_t) rc;
552 else
553 return (ssize_t) rc_orig;
554 }
555 vfs_exchange_end(exch);
556 async_wait_for(req, &rc);
557
558 return rc;
559}
560
561int stat(const char *path, struct stat *stat)
562{
563 size_t pa_size;
564 char *pa = absolutize(path, &pa_size);
565 if (!pa) {
566 return ENOMEM;
567 }
568
569 int fd = _vfs_walk(-1, pa, 0);
570 if (fd < 0) {
571 return fd;
572 }
573
574 int rc = fstat(fd, stat);
575 close(fd);
576 return rc;
577}
578
579DIR *opendir(const char *dirname)
580{
581 DIR *dirp = malloc(sizeof(DIR));
582 if (!dirp) {
583 errno = ENOMEM;
584 return NULL;
585 }
586
587 size_t abs_size;
588 char *abs = absolutize(dirname, &abs_size);
589 if (!abs) {
590 free(dirp);
591 errno = ENOMEM;
592 return NULL;
593 }
594
595 int ret = _vfs_walk(-1, abs, WALK_DIRECTORY);
596 free(abs);
597
598 if (ret < 0) {
599 free(dirp);
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;
609 return NULL;
610 }
611
612 dirp->fd = ret;
613 return dirp;
614}
615
616struct dirent *readdir(DIR *dirp)
617{
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;
622}
623
624void rewinddir(DIR *dirp)
625{
626 (void) lseek(dirp->fd, 0, SEEK_SET);
627}
628
629int closedir(DIR *dirp)
630{
631 (void) close(dirp->fd);
632 free(dirp);
633 return 0;
634}
635
636int mkdir(const char *path, mode_t mode)
637{
638 size_t pa_size;
639 char *pa = absolutize(path, &pa_size);
640 if (!pa) {
641 return ENOMEM;
642 }
643
644 int ret = _vfs_walk(-1, pa, WALK_MUST_CREATE | WALK_DIRECTORY);
645 if (ret < 0) {
646 return ret;
647 }
648
649 close(ret);
650 return EOK;
651}
652
653static int _vfs_unlink2(int parent, const char *path, int expect, int wflag)
654{
655 sysarg_t rc;
656 aid_t req;
657
658 async_exch_t *exch = vfs_exchange_begin();
659
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
663 vfs_exchange_end(exch);
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 }
671 return rc;
672}
673
674int unlink(const char *path)
675{
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);
683}
684
685int rmdir(const char *path)
686{
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);
694}
695
696int rename(const char *old, const char *new)
697{
698 sysarg_t rc;
699 sysarg_t rc_orig;
700 aid_t req;
701
702 size_t olda_size;
703 char *olda = absolutize(old, &olda_size);
704 if (!olda)
705 return ENOMEM;
706
707 size_t newa_size;
708 char *newa = absolutize(new, &newa_size);
709 if (!newa) {
710 free(olda);
711 return ENOMEM;
712 }
713
714 async_exch_t *exch = vfs_exchange_begin();
715
716 req = async_send_1(exch, VFS_IN_RENAME, -1, NULL);
717 rc = async_data_write_start(exch, olda, olda_size);
718 if (rc != EOK) {
719 vfs_exchange_end(exch);
720 free(olda);
721 free(newa);
722 async_wait_for(req, &rc_orig);
723 if (rc_orig == EOK)
724 return (int) rc;
725 else
726 return (int) rc_orig;
727 }
728 rc = async_data_write_start(exch, newa, newa_size);
729 if (rc != EOK) {
730 vfs_exchange_end(exch);
731 free(olda);
732 free(newa);
733 async_wait_for(req, &rc_orig);
734 if (rc_orig == EOK)
735 return (int) rc;
736 else
737 return (int) rc_orig;
738 }
739 vfs_exchange_end(exch);
740 free(olda);
741 free(newa);
742 async_wait_for(req, &rc);
743 return rc;
744}
745
746int chdir(const char *path)
747{
748 size_t abs_size;
749 char *abs = absolutize(path, &abs_size);
750 if (!abs)
751 return ENOMEM;
752
753 int fd = _vfs_walk(-1, abs, WALK_DIRECTORY);
754 if (fd < 0) {
755 free(abs);
756 return ENOENT;
757 }
758
759 fibril_mutex_lock(&cwd_mutex);
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
772 fibril_mutex_unlock(&cwd_mutex);
773 return EOK;
774}
775
776char *getcwd(char *buf, size_t size)
777{
778 if (size == 0)
779 return NULL;
780
781 fibril_mutex_lock(&cwd_mutex);
782
783 if ((cwd_size == 0) || (size < cwd_size + 1)) {
784 fibril_mutex_unlock(&cwd_mutex);
785 return NULL;
786 }
787
788 str_cpy(buf, size, cwd_path);
789 fibril_mutex_unlock(&cwd_mutex);
790
791 return buf;
792}
793
794async_sess_t *fd_session(exch_mgmt_t mgmt, int fildes)
795{
796 struct stat stat;
797 int rc = fstat(fildes, &stat);
798 if (rc != 0) {
799 errno = rc;
800 return NULL;
801 }
802
803 if (!stat.service) {
804 errno = ENOENT;
805 return NULL;
806 }
807
808 return loc_service_connect(mgmt, stat.service, 0);
809}
810
811int dup2(int oldfd, int newfd)
812{
813 async_exch_t *exch = vfs_exchange_begin();
814
815 sysarg_t ret;
816 sysarg_t rc = async_req_2_1(exch, VFS_IN_DUP, oldfd, newfd, &ret);
817
818 vfs_exchange_end(exch);
819
820 if (rc == EOK)
821 return (int) ret;
822
823 return (int) rc;
824}
825
826int fd_wait(void)
827{
828 async_exch_t *exch = vfs_exchange_begin();
829
830 sysarg_t ret;
831 sysarg_t rc = async_req_0_1(exch, VFS_IN_WAIT_HANDLE, &ret);
832
833 vfs_exchange_end(exch);
834
835 if (rc == EOK)
836 return (int) ret;
837
838 return (int) rc;
839}
840
841int get_mtab_list(list_t *mtab_list)
842{
843 sysarg_t rc;
844 aid_t req;
845 size_t i;
846 sysarg_t num_mounted_fs;
847
848 async_exch_t *exch = vfs_exchange_begin();
849
850 req = async_send_0(exch, VFS_IN_MTAB_GET, NULL);
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
860 mtab_ent = malloc(sizeof(mtab_ent_t));
861 if (!mtab_ent) {
862 rc = ENOMEM;
863 goto exit;
864 }
865
866 memset(mtab_ent, 0, sizeof(mtab_ent_t));
867
868 rc = async_data_read_start(exch, (void *) mtab_ent->mp,
869 MAX_PATH_LEN);
870 if (rc != EOK)
871 goto exit;
872
873 rc = async_data_read_start(exch, (void *) mtab_ent->opts,
874 MAX_MNTOPTS_LEN);
875 if (rc != EOK)
876 goto exit;
877
878 rc = async_data_read_start(exch, (void *) mtab_ent->fs_name,
879 FS_NAME_MAXLEN);
880 if (rc != EOK)
881 goto exit;
882
883 sysarg_t p[2];
884
885 rc = async_req_0_2(exch, VFS_IN_PING, &p[0], &p[1]);
886 if (rc != EOK)
887 goto exit;
888
889 mtab_ent->instance = p[0];
890 mtab_ent->service_id = p[1];
891
892 link_initialize(&mtab_ent->link);
893 list_append(&mtab_ent->link, mtab_list);
894 }
895
896exit:
897 async_wait_for(req, &rc);
898 vfs_exchange_end(exch);
899 return rc;
900}
901
902/** @}
903 */
Note: See TracBrowser for help on using the repository browser.