source: mainline/uspace/lib/c/generic/vfs/vfs.c@ 089385e8

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 089385e8 was 089385e8, checked in by Vojtech Horky <vojtechhorky@…>, 13 years ago

Change to previous directory with `cd -' in bdsh

  • Property mode set to 100644
File size: 18.2 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
60/* Current (working) directory. */
61static FIBRIL_MUTEX_INITIALIZE(cwd_mutex);
62static int cwd_fd = -1;
63static char *cwd_path = NULL;
64static size_t cwd_size = 0;
65
66/* Previous directory. */
67static FIBRIL_MUTEX_INITIALIZE(pwd_mutex);
68static int pwd_fd = -1;
69static char *pwd_path = NULL;
70static size_t pwd_size = 0;
71
72
73/** Start an async exchange on the VFS session.
74 *
75 * @return New exchange.
76 *
77 */
78async_exch_t *vfs_exchange_begin(void)
79{
80 fibril_mutex_lock(&vfs_mutex);
81
82 while (vfs_sess == NULL)
83 vfs_sess = service_connect_blocking(EXCHANGE_PARALLEL, SERVICE_VFS,
84 0, 0);
85
86 fibril_mutex_unlock(&vfs_mutex);
87
88 return async_exchange_begin(vfs_sess);
89}
90
91/** Finish an async exchange on the VFS session.
92 *
93 * @param exch Exchange to be finished.
94 *
95 */
96void vfs_exchange_end(async_exch_t *exch)
97{
98 async_exchange_end(exch);
99}
100
101char *absolutize(const char *path, size_t *retlen)
102{
103 char *ncwd_path;
104 char *ncwd_path_nc;
105
106 fibril_mutex_lock(&cwd_mutex);
107 size_t size = str_size(path);
108 if (*path != '/') {
109 if (!cwd_path) {
110 fibril_mutex_unlock(&cwd_mutex);
111 return NULL;
112 }
113 ncwd_path_nc = malloc(cwd_size + 1 + size + 1);
114 if (!ncwd_path_nc) {
115 fibril_mutex_unlock(&cwd_mutex);
116 return NULL;
117 }
118 str_cpy(ncwd_path_nc, cwd_size + 1 + size + 1, cwd_path);
119 ncwd_path_nc[cwd_size] = '/';
120 ncwd_path_nc[cwd_size + 1] = '\0';
121 } else {
122 ncwd_path_nc = malloc(size + 1);
123 if (!ncwd_path_nc) {
124 fibril_mutex_unlock(&cwd_mutex);
125 return NULL;
126 }
127 ncwd_path_nc[0] = '\0';
128 }
129 str_append(ncwd_path_nc, cwd_size + 1 + size + 1, path);
130 ncwd_path = canonify(ncwd_path_nc, retlen);
131 if (!ncwd_path) {
132 fibril_mutex_unlock(&cwd_mutex);
133 free(ncwd_path_nc);
134 return NULL;
135 }
136 /*
137 * We need to clone ncwd_path because canonify() works in-place and thus
138 * the address in ncwd_path need not be the same as ncwd_path_nc, even
139 * though they both point into the same dynamically allocated buffer.
140 */
141 ncwd_path = str_dup(ncwd_path);
142 free(ncwd_path_nc);
143 if (!ncwd_path) {
144 fibril_mutex_unlock(&cwd_mutex);
145 return NULL;
146 }
147 fibril_mutex_unlock(&cwd_mutex);
148 return ncwd_path;
149}
150
151int mount(const char *fs_name, const char *mp, const char *fqsn,
152 const char *opts, unsigned int flags, unsigned int instance)
153{
154 int null_id = -1;
155 char null[LOC_NAME_MAXLEN];
156
157 if (str_cmp(fqsn, "") == 0) {
158 /* No device specified, create a fresh
159 null/%d device instead */
160 null_id = loc_null_create();
161
162 if (null_id == -1)
163 return ENOMEM;
164
165 snprintf(null, LOC_NAME_MAXLEN, "null/%d", null_id);
166 fqsn = null;
167 }
168
169 service_id_t service_id;
170 int res = loc_service_get_id(fqsn, &service_id, flags);
171 if (res != EOK) {
172 if (null_id != -1)
173 loc_null_destroy(null_id);
174
175 return res;
176 }
177
178 size_t mpa_size;
179 char *mpa = absolutize(mp, &mpa_size);
180 if (!mpa) {
181 if (null_id != -1)
182 loc_null_destroy(null_id);
183
184 return ENOMEM;
185 }
186
187 async_exch_t *exch = vfs_exchange_begin();
188
189 sysarg_t rc_orig;
190 aid_t req = async_send_3(exch, VFS_IN_MOUNT, service_id, flags,
191 instance, NULL);
192 sysarg_t rc = async_data_write_start(exch, (void *) mpa, mpa_size);
193 if (rc != EOK) {
194 vfs_exchange_end(exch);
195 free(mpa);
196 async_wait_for(req, &rc_orig);
197
198 if (null_id != -1)
199 loc_null_destroy(null_id);
200
201 if (rc_orig == EOK)
202 return (int) rc;
203 else
204 return (int) rc_orig;
205 }
206
207 rc = async_data_write_start(exch, (void *) opts, str_size(opts));
208 if (rc != EOK) {
209 vfs_exchange_end(exch);
210 free(mpa);
211 async_wait_for(req, &rc_orig);
212
213 if (null_id != -1)
214 loc_null_destroy(null_id);
215
216 if (rc_orig == EOK)
217 return (int) rc;
218 else
219 return (int) rc_orig;
220 }
221
222 rc = async_data_write_start(exch, (void *) fs_name, str_size(fs_name));
223 if (rc != EOK) {
224 vfs_exchange_end(exch);
225 free(mpa);
226 async_wait_for(req, &rc_orig);
227
228 if (null_id != -1)
229 loc_null_destroy(null_id);
230
231 if (rc_orig == EOK)
232 return (int) rc;
233 else
234 return (int) rc_orig;
235 }
236
237 /* Ask VFS whether it likes fs_name. */
238 rc = async_req_0_0(exch, VFS_IN_PING);
239 if (rc != EOK) {
240 vfs_exchange_end(exch);
241 free(mpa);
242 async_wait_for(req, &rc_orig);
243
244 if (null_id != -1)
245 loc_null_destroy(null_id);
246
247 if (rc_orig == EOK)
248 return (int) rc;
249 else
250 return (int) rc_orig;
251 }
252
253 vfs_exchange_end(exch);
254 free(mpa);
255 async_wait_for(req, &rc);
256
257 if ((rc != EOK) && (null_id != -1))
258 loc_null_destroy(null_id);
259
260 return (int) rc;
261}
262
263int unmount(const char *mp)
264{
265 sysarg_t rc;
266 sysarg_t rc_orig;
267 aid_t req;
268 size_t mpa_size;
269 char *mpa;
270
271 mpa = absolutize(mp, &mpa_size);
272 if (!mpa)
273 return ENOMEM;
274
275 async_exch_t *exch = vfs_exchange_begin();
276
277 req = async_send_0(exch, VFS_IN_UNMOUNT, NULL);
278 rc = async_data_write_start(exch, (void *) mpa, mpa_size);
279 if (rc != EOK) {
280 vfs_exchange_end(exch);
281 free(mpa);
282 async_wait_for(req, &rc_orig);
283 if (rc_orig == EOK)
284 return (int) rc;
285 else
286 return (int) rc_orig;
287 }
288
289
290 vfs_exchange_end(exch);
291 free(mpa);
292 async_wait_for(req, &rc);
293
294 return (int) rc;
295}
296
297static int open_internal(const char *abs, size_t abs_size, int lflag, int oflag)
298{
299 async_exch_t *exch = vfs_exchange_begin();
300
301 ipc_call_t answer;
302 aid_t req = async_send_3(exch, VFS_IN_OPEN, lflag, oflag, 0, &answer);
303 sysarg_t rc = async_data_write_start(exch, abs, abs_size);
304
305 if (rc != EOK) {
306 vfs_exchange_end(exch);
307
308 sysarg_t rc_orig;
309 async_wait_for(req, &rc_orig);
310
311 if (rc_orig == EOK)
312 return (int) rc;
313 else
314 return (int) rc_orig;
315 }
316
317 vfs_exchange_end(exch);
318 async_wait_for(req, &rc);
319
320 if (rc != EOK)
321 return (int) rc;
322
323 return (int) IPC_GET_ARG1(answer);
324}
325
326int open(const char *path, int oflag, ...)
327{
328 size_t abs_size;
329 char *abs = absolutize(path, &abs_size);
330 if (!abs)
331 return ENOMEM;
332
333 int ret = open_internal(abs, abs_size, L_FILE, oflag);
334 free(abs);
335
336 return ret;
337}
338
339int close(int fildes)
340{
341 sysarg_t rc;
342
343 async_exch_t *exch = vfs_exchange_begin();
344 rc = async_req_1_0(exch, VFS_IN_CLOSE, fildes);
345 vfs_exchange_end(exch);
346
347 return (int) rc;
348}
349
350ssize_t read(int fildes, void *buf, size_t nbyte)
351{
352 sysarg_t rc;
353 ipc_call_t answer;
354 aid_t req;
355
356 async_exch_t *exch = vfs_exchange_begin();
357
358 req = async_send_1(exch, VFS_IN_READ, fildes, &answer);
359 rc = async_data_read_start(exch, (void *)buf, nbyte);
360 if (rc != EOK) {
361 vfs_exchange_end(exch);
362
363 sysarg_t rc_orig;
364 async_wait_for(req, &rc_orig);
365
366 if (rc_orig == EOK)
367 return (ssize_t) rc;
368 else
369 return (ssize_t) rc_orig;
370 }
371 vfs_exchange_end(exch);
372 async_wait_for(req, &rc);
373 if (rc == EOK)
374 return (ssize_t) IPC_GET_ARG1(answer);
375 else
376 return rc;
377}
378
379ssize_t write(int fildes, const void *buf, size_t nbyte)
380{
381 sysarg_t rc;
382 ipc_call_t answer;
383 aid_t req;
384
385 async_exch_t *exch = vfs_exchange_begin();
386
387 req = async_send_1(exch, VFS_IN_WRITE, fildes, &answer);
388 rc = async_data_write_start(exch, (void *)buf, nbyte);
389 if (rc != EOK) {
390 vfs_exchange_end(exch);
391
392 sysarg_t rc_orig;
393 async_wait_for(req, &rc_orig);
394
395 if (rc_orig == EOK)
396 return (ssize_t) rc;
397 else
398 return (ssize_t) rc_orig;
399 }
400 vfs_exchange_end(exch);
401 async_wait_for(req, &rc);
402 if (rc == EOK)
403 return (ssize_t) IPC_GET_ARG1(answer);
404 else
405 return -1;
406}
407
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
470int fsync(int fildes)
471{
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);
475
476 return (int) rc;
477}
478
479off64_t lseek(int fildes, off64_t offset, int whence)
480{
481 async_exch_t *exch = vfs_exchange_begin();
482
483 sysarg_t newoff_lo;
484 sysarg_t newoff_hi;
485 sysarg_t rc = async_req_4_2(exch, VFS_IN_SEEK, fildes,
486 LOWER32(offset), UPPER32(offset), whence,
487 &newoff_lo, &newoff_hi);
488
489 vfs_exchange_end(exch);
490
491 if (rc != EOK)
492 return (off64_t) -1;
493
494 return (off64_t) MERGE_LOUP32(newoff_lo, newoff_hi);
495}
496
497int ftruncate(int fildes, aoff64_t length)
498{
499 sysarg_t rc;
500
501 async_exch_t *exch = vfs_exchange_begin();
502 rc = async_req_3_0(exch, VFS_IN_TRUNCATE, fildes,
503 LOWER32(length), UPPER32(length));
504 vfs_exchange_end(exch);
505
506 return (int) rc;
507}
508
509int fstat(int fildes, struct stat *stat)
510{
511 sysarg_t rc;
512 aid_t req;
513
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));
518 if (rc != EOK) {
519 vfs_exchange_end(exch);
520
521 sysarg_t rc_orig;
522 async_wait_for(req, &rc_orig);
523
524 if (rc_orig == EOK)
525 return (ssize_t) rc;
526 else
527 return (ssize_t) rc_orig;
528 }
529 vfs_exchange_end(exch);
530 async_wait_for(req, &rc);
531
532 return rc;
533}
534
535int stat(const char *path, struct stat *stat)
536{
537 sysarg_t rc;
538 sysarg_t rc_orig;
539 aid_t req;
540
541 size_t pa_size;
542 char *pa = absolutize(path, &pa_size);
543 if (!pa)
544 return ENOMEM;
545
546 async_exch_t *exch = vfs_exchange_begin();
547
548 req = async_send_0(exch, VFS_IN_STAT, NULL);
549 rc = async_data_write_start(exch, pa, pa_size);
550 if (rc != EOK) {
551 vfs_exchange_end(exch);
552 free(pa);
553 async_wait_for(req, &rc_orig);
554 if (rc_orig == EOK)
555 return (int) rc;
556 else
557 return (int) rc_orig;
558 }
559 rc = async_data_read_start(exch, stat, sizeof(struct stat));
560 if (rc != EOK) {
561 vfs_exchange_end(exch);
562 free(pa);
563 async_wait_for(req, &rc_orig);
564 if (rc_orig == EOK)
565 return (int) rc;
566 else
567 return (int) rc_orig;
568 }
569 vfs_exchange_end(exch);
570 free(pa);
571 async_wait_for(req, &rc);
572 return rc;
573}
574
575DIR *opendir(const char *dirname)
576{
577 DIR *dirp = malloc(sizeof(DIR));
578 if (!dirp)
579 return NULL;
580
581 size_t abs_size;
582 char *abs = absolutize(dirname, &abs_size);
583 if (!abs) {
584 free(dirp);
585 return NULL;
586 }
587
588 int ret = open_internal(abs, abs_size, L_DIRECTORY, 0);
589 free(abs);
590
591 if (ret < 0) {
592 free(dirp);
593 return NULL;
594 }
595
596 dirp->fd = ret;
597 return dirp;
598}
599
600struct dirent *readdir(DIR *dirp)
601{
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;
606}
607
608void rewinddir(DIR *dirp)
609{
610 (void) lseek(dirp->fd, 0, SEEK_SET);
611}
612
613int closedir(DIR *dirp)
614{
615 (void) close(dirp->fd);
616 free(dirp);
617 return 0;
618}
619
620int mkdir(const char *path, mode_t mode)
621{
622 sysarg_t rc;
623 aid_t req;
624
625 size_t pa_size;
626 char *pa = absolutize(path, &pa_size);
627 if (!pa)
628 return ENOMEM;
629
630 async_exch_t *exch = vfs_exchange_begin();
631
632 req = async_send_1(exch, VFS_IN_MKDIR, mode, NULL);
633 rc = async_data_write_start(exch, pa, pa_size);
634 if (rc != EOK) {
635 vfs_exchange_end(exch);
636 free(pa);
637
638 sysarg_t rc_orig;
639 async_wait_for(req, &rc_orig);
640
641 if (rc_orig == EOK)
642 return (int) rc;
643 else
644 return (int) rc_orig;
645 }
646 vfs_exchange_end(exch);
647 free(pa);
648 async_wait_for(req, &rc);
649 return rc;
650}
651
652static int _unlink(const char *path, int lflag)
653{
654 sysarg_t rc;
655 aid_t req;
656
657 size_t pa_size;
658 char *pa = absolutize(path, &pa_size);
659 if (!pa)
660 return ENOMEM;
661
662 async_exch_t *exch = vfs_exchange_begin();
663
664 req = async_send_1(exch, VFS_IN_UNLINK, lflag, NULL);
665 rc = async_data_write_start(exch, pa, pa_size);
666 if (rc != EOK) {
667 vfs_exchange_end(exch);
668 free(pa);
669
670 sysarg_t rc_orig;
671 async_wait_for(req, &rc_orig);
672
673 if (rc_orig == EOK)
674 return (int) rc;
675 else
676 return (int) rc_orig;
677 }
678 vfs_exchange_end(exch);
679 free(pa);
680 async_wait_for(req, &rc);
681 return rc;
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
694int rename(const char *old, const char *new)
695{
696 sysarg_t rc;
697 sysarg_t rc_orig;
698 aid_t req;
699
700 size_t olda_size;
701 char *olda = absolutize(old, &olda_size);
702 if (!olda)
703 return ENOMEM;
704
705 size_t newa_size;
706 char *newa = absolutize(new, &newa_size);
707 if (!newa) {
708 free(olda);
709 return ENOMEM;
710 }
711
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);
716 if (rc != EOK) {
717 vfs_exchange_end(exch);
718 free(olda);
719 free(newa);
720 async_wait_for(req, &rc_orig);
721 if (rc_orig == EOK)
722 return (int) rc;
723 else
724 return (int) rc_orig;
725 }
726 rc = async_data_write_start(exch, newa, newa_size);
727 if (rc != EOK) {
728 vfs_exchange_end(exch);
729 free(olda);
730 free(newa);
731 async_wait_for(req, &rc_orig);
732 if (rc_orig == EOK)
733 return (int) rc;
734 else
735 return (int) rc_orig;
736 }
737 vfs_exchange_end(exch);
738 free(olda);
739 free(newa);
740 async_wait_for(req, &rc);
741 return rc;
742}
743
744int chdir(const char *path)
745{
746 size_t abs_size;
747 char *abs = absolutize(path, &abs_size);
748 if (!abs)
749 return ENOMEM;
750
751 int fd = open_internal(abs, abs_size, L_DIRECTORY, O_DESC);
752
753 if (fd < 0) {
754 free(abs);
755 return ENOENT;
756 }
757
758 fibril_mutex_lock(&cwd_mutex);
759
760
761 fibril_mutex_lock(&pwd_mutex);
762
763 if (pwd_fd >= 0)
764 close(pwd_fd);
765
766
767 if (pwd_path)
768 free(pwd_path);
769
770
771 pwd_fd = cwd_fd;
772 pwd_path = cwd_path;
773 pwd_size = cwd_size;
774
775 fibril_mutex_unlock(&pwd_mutex);
776
777 cwd_fd = fd;
778 cwd_path = abs;
779 cwd_size = abs_size;
780
781 fibril_mutex_unlock(&cwd_mutex);
782 return EOK;
783}
784
785char *getcwd(char *buf, size_t size)
786{
787 if (size == 0)
788 return NULL;
789
790 fibril_mutex_lock(&cwd_mutex);
791
792 if ((cwd_size == 0) || (size < cwd_size + 1)) {
793 fibril_mutex_unlock(&cwd_mutex);
794 return NULL;
795 }
796
797 str_cpy(buf, size, cwd_path);
798 fibril_mutex_unlock(&cwd_mutex);
799
800 return buf;
801}
802
803
804char *getprevwd(char *buf, size_t size)
805{
806 if (size == 0)
807 return NULL;
808
809 fibril_mutex_lock(&pwd_mutex);
810
811 if ((pwd_size == 0) || (size < pwd_size + 1)) {
812 fibril_mutex_unlock(&pwd_mutex);
813 return NULL;
814 }
815
816 str_cpy(buf, size, pwd_path);
817 fibril_mutex_unlock(&pwd_mutex);
818
819 return buf;
820}
821
822async_sess_t *fd_session(exch_mgmt_t mgmt, int fildes)
823{
824 struct stat stat;
825 int rc = fstat(fildes, &stat);
826 if (rc != 0) {
827 errno = rc;
828 return NULL;
829 }
830
831 if (!stat.service) {
832 errno = ENOENT;
833 return NULL;
834 }
835
836 return loc_service_connect(mgmt, stat.service, 0);
837}
838
839int dup2(int oldfd, int newfd)
840{
841 async_exch_t *exch = vfs_exchange_begin();
842
843 sysarg_t ret;
844 sysarg_t rc = async_req_2_1(exch, VFS_IN_DUP, oldfd, newfd, &ret);
845
846 vfs_exchange_end(exch);
847
848 if (rc == EOK)
849 return (int) ret;
850
851 return (int) rc;
852}
853
854int fd_wait(void)
855{
856 async_exch_t *exch = vfs_exchange_begin();
857
858 sysarg_t ret;
859 sysarg_t rc = async_req_0_1(exch, VFS_IN_WAIT_HANDLE, &ret);
860
861 vfs_exchange_end(exch);
862
863 if (rc == EOK)
864 return (int) ret;
865
866 return (int) rc;
867}
868
869int get_mtab_list(list_t *mtab_list)
870{
871 sysarg_t rc;
872 aid_t req;
873 size_t i;
874 sysarg_t num_mounted_fs;
875
876 async_exch_t *exch = vfs_exchange_begin();
877
878 req = async_send_0(exch, VFS_IN_MTAB_GET, NULL);
879
880 /* Ask VFS how many filesystems are mounted */
881 rc = async_req_0_1(exch, VFS_IN_PING, &num_mounted_fs);
882 if (rc != EOK)
883 goto exit;
884
885 for (i = 0; i < num_mounted_fs; ++i) {
886 mtab_ent_t *mtab_ent;
887
888 mtab_ent = malloc(sizeof(mtab_ent_t));
889 if (!mtab_ent) {
890 rc = ENOMEM;
891 goto exit;
892 }
893
894 memset(mtab_ent, 0, sizeof(mtab_ent_t));
895
896 rc = async_data_read_start(exch, (void *) mtab_ent->mp,
897 MAX_PATH_LEN);
898 if (rc != EOK)
899 goto exit;
900
901 rc = async_data_read_start(exch, (void *) mtab_ent->opts,
902 MAX_MNTOPTS_LEN);
903 if (rc != EOK)
904 goto exit;
905
906 rc = async_data_read_start(exch, (void *) mtab_ent->fs_name,
907 FS_NAME_MAXLEN);
908 if (rc != EOK)
909 goto exit;
910
911 sysarg_t p[2];
912
913 rc = async_req_0_2(exch, VFS_IN_PING, &p[0], &p[1]);
914 if (rc != EOK)
915 goto exit;
916
917 mtab_ent->instance = p[0];
918 mtab_ent->service_id = p[1];
919
920 link_initialize(&mtab_ent->link);
921 list_append(&mtab_ent->link, mtab_list);
922 }
923
924exit:
925 async_wait_for(req, &rc);
926 vfs_exchange_end(exch);
927 return rc;
928}
929
930/** @}
931 */
Note: See TracBrowser for help on using the repository browser.