source: mainline/uspace/lib/c/generic/vfs/vfs.c@ 9b48c06

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 9b48c06 was 9b48c06, checked in by Ji?? Z?rev?cky <zarevucky.jiri@…>, 12 years ago

Replace all the other uses of VFS_IN_OPEN.

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