source: mainline/uspace/lib/libc/generic/vfs/vfs.c@ a405563

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a405563 was a405563, checked in by Jiri Svoboda <jirik.svoboda@…>, 16 years ago

Fix some warnings.

  • Property mode set to 100644
File size: 13.2 KB
RevLine 
[2f02aa17]1/*
[222e57c]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/vfs.h>
36#include <vfs/canonify.h>
[d0dc74ae]37#include <stdlib.h>
[449c246]38#include <unistd.h>
[d0dc74ae]39#include <dirent.h>
[449c246]40#include <fcntl.h>
[923c39e]41#include <stdio.h>
[852b801]42#include <sys/stat.h>
[72bde81]43#include <sys/types.h>
[2f02aa17]44#include <ipc/ipc.h>
45#include <ipc/services.h>
46#include <async.h>
47#include <atomic.h>
48#include <futex.h>
49#include <errno.h>
50#include <string.h>
[1090b8c]51#include <devmap.h>
[2595dab]52#include <ipc/vfs.h>
53#include <ipc/devmap.h>
[2f02aa17]54
[2595dab]55static int vfs_phone = -1;
56static futex_t vfs_phone_futex = FUTEX_INITIALIZER;
57static futex_t cwd_futex = FUTEX_INITIALIZER;
[5fec355]58
59DIR *cwd_dir = NULL;
60char *cwd_path = NULL;
[9eb3623]61size_t cwd_size = 0;
[5fec355]62
[17b2aac]63char *absolutize(const char *path, size_t *retlen)
[5fec355]64{
65 char *ncwd_path;
[34a74ab]66 char *ncwd_path_nc;
[5fec355]67
68 futex_down(&cwd_futex);
[9eb3623]69 size_t size = str_size(path);
[5fec355]70 if (*path != '/') {
71 if (!cwd_path) {
72 futex_up(&cwd_futex);
73 return NULL;
74 }
[9eb3623]75 ncwd_path_nc = malloc(cwd_size + 1 + size + 1);
[34a74ab]76 if (!ncwd_path_nc) {
[5fec355]77 futex_up(&cwd_futex);
78 return NULL;
79 }
[6eb2e96]80 str_cpy(ncwd_path_nc, cwd_size + 1 + size + 1, cwd_path);
[9eb3623]81 ncwd_path_nc[cwd_size] = '/';
82 ncwd_path_nc[cwd_size + 1] = '\0';
[5fec355]83 } else {
[9eb3623]84 ncwd_path_nc = malloc(size + 1);
[34a74ab]85 if (!ncwd_path_nc) {
[5fec355]86 futex_up(&cwd_futex);
87 return NULL;
88 }
[34a74ab]89 ncwd_path_nc[0] = '\0';
[5fec355]90 }
[4482bc7]91 str_append(ncwd_path_nc, cwd_size + 1 + size + 1, path);
[34a74ab]92 ncwd_path = canonify(ncwd_path_nc, retlen);
93 if (!ncwd_path) {
94 futex_up(&cwd_futex);
95 free(ncwd_path_nc);
96 return NULL;
97 }
98 /*
99 * We need to clone ncwd_path because canonify() works in-place and thus
100 * the address in ncwd_path need not be the same as ncwd_path_nc, even
101 * though they both point into the same dynamically allocated buffer.
102 */
[095003a8]103 ncwd_path = str_dup(ncwd_path);
[34a74ab]104 free(ncwd_path_nc);
105 if (!ncwd_path) {
[923c39e]106 futex_up(&cwd_futex);
107 return NULL;
108 }
[5fec355]109 futex_up(&cwd_futex);
110 return ncwd_path;
111}
[2f02aa17]112
[19b28b0]113static void vfs_connect(void)
[2f02aa17]114{
[19b28b0]115 while (vfs_phone < 0)
116 vfs_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VFS, 0, 0);
[2f02aa17]117}
118
[19b28b0]119int mount(const char *fs_name, const char *mp, const char *dev,
[1090b8c]120 const char *opts, unsigned int flags)
[2f02aa17]121{
122 int res;
123 ipcarg_t rc;
124 aid_t req;
[82405266]125 dev_handle_t dev_handle;
126
[1090b8c]127 res = devmap_device_get_handle(dev, &dev_handle, flags);
[82405266]128 if (res != EOK)
129 return res;
130
[9eb3623]131 size_t mpa_size;
132 char *mpa = absolutize(mp, &mpa_size);
[5fec355]133 if (!mpa)
134 return ENOMEM;
[19b28b0]135
[2f02aa17]136 futex_down(&vfs_phone_futex);
137 async_serialize_start();
[19b28b0]138 vfs_connect();
139
[4198f9c3]140 req = async_send_2(vfs_phone, VFS_IN_MOUNT, dev_handle, flags, NULL);
[9eb3623]141 rc = ipc_data_write_start(vfs_phone, (void *) mpa, mpa_size);
[12fc042]142 if (rc != EOK) {
143 async_wait_for(req, NULL);
144 async_serialize_end();
145 futex_up(&vfs_phone_futex);
146 free(mpa);
147 return (int) rc;
148 }
[19b28b0]149
[594303b]150 rc = ipc_data_write_start(vfs_phone, (void *) opts, str_size(opts));
151 if (rc != EOK) {
152 async_wait_for(req, NULL);
153 async_serialize_end();
154 futex_up(&vfs_phone_futex);
155 free(mpa);
156 return (int) rc;
157 }
158
[9eb3623]159 rc = ipc_data_write_start(vfs_phone, (void *) fs_name, str_size(fs_name));
[2f02aa17]160 if (rc != EOK) {
161 async_wait_for(req, NULL);
162 async_serialize_end();
163 futex_up(&vfs_phone_futex);
[5fec355]164 free(mpa);
[2f02aa17]165 return (int) rc;
166 }
[c08c355]167
168 /* Ask VFS whether it likes fs_name. */
169 rc = async_req_0_0(vfs_phone, IPC_M_PING);
170 if (rc != EOK) {
171 async_wait_for(req, NULL);
172 async_serialize_end();
173 futex_up(&vfs_phone_futex);
174 free(mpa);
175 return (int) rc;
176 }
[19b28b0]177
[2f02aa17]178 async_wait_for(req, &rc);
179 async_serialize_end();
180 futex_up(&vfs_phone_futex);
[5fec355]181 free(mpa);
[19b28b0]182
[2f02aa17]183 return (int) rc;
184}
185
[ae78b530]186static int _open(const char *path, int lflag, int oflag, ...)
[2f02aa17]187{
188 ipcarg_t rc;
189 ipc_call_t answer;
190 aid_t req;
191
[9eb3623]192 size_t pa_size;
193 char *pa = absolutize(path, &pa_size);
[5fec355]194 if (!pa)
195 return ENOMEM;
196
[2f02aa17]197 futex_down(&vfs_phone_futex);
198 async_serialize_start();
[19b28b0]199 vfs_connect();
200
[4198f9c3]201 req = async_send_3(vfs_phone, VFS_IN_OPEN, lflag, oflag, 0, &answer);
[9eb3623]202 rc = ipc_data_write_start(vfs_phone, pa, pa_size);
[2f02aa17]203 if (rc != EOK) {
204 async_wait_for(req, NULL);
205 async_serialize_end();
206 futex_up(&vfs_phone_futex);
[5fec355]207 free(pa);
[2f02aa17]208 return (int) rc;
209 }
210 async_wait_for(req, &rc);
211 async_serialize_end();
212 futex_up(&vfs_phone_futex);
[5fec355]213 free(pa);
[2595dab]214
[57b4f46]215 if (rc != EOK)
216 return (int) rc;
[2595dab]217
[2f02aa17]218 return (int) IPC_GET_ARG1(answer);
219}
220
[ae78b530]221int open(const char *path, int oflag, ...)
222{
223 return _open(path, L_FILE, oflag);
224}
225
[99272a3]226int open_node(fdi_node_t *node, int oflag)
[2595dab]227{
228 futex_down(&vfs_phone_futex);
229 async_serialize_start();
230 vfs_connect();
231
232 ipc_call_t answer;
[4198f9c3]233 aid_t req = async_send_4(vfs_phone, VFS_IN_OPEN_NODE, node->fs_handle,
[2595dab]234 node->dev_handle, node->index, oflag, &answer);
235
236 ipcarg_t rc;
237 async_wait_for(req, &rc);
238 async_serialize_end();
239 futex_up(&vfs_phone_futex);
240
241 if (rc != EOK)
242 return (int) rc;
243
244 return (int) IPC_GET_ARG1(answer);
245}
246
[72bde81]247int close(int fildes)
248{
[e704503]249 ipcarg_t rc;
[19b28b0]250
[e704503]251 futex_down(&vfs_phone_futex);
252 async_serialize_start();
[19b28b0]253 vfs_connect();
254
[4198f9c3]255 rc = async_req_1_0(vfs_phone, VFS_IN_CLOSE, fildes);
[19b28b0]256
[e704503]257 async_serialize_end();
258 futex_up(&vfs_phone_futex);
259
260 return (int)rc;
[72bde81]261}
262
[2f02aa17]263ssize_t read(int fildes, void *buf, size_t nbyte)
264{
265 ipcarg_t rc;
266 ipc_call_t answer;
267 aid_t req;
268
269 futex_down(&vfs_phone_futex);
270 async_serialize_start();
[19b28b0]271 vfs_connect();
272
[4198f9c3]273 req = async_send_1(vfs_phone, VFS_IN_READ, fildes, &answer);
[07e01e6]274 rc = ipc_data_read_start(vfs_phone, (void *)buf, nbyte);
275 if (rc != EOK) {
[2f02aa17]276 async_wait_for(req, NULL);
277 async_serialize_end();
278 futex_up(&vfs_phone_futex);
279 return (ssize_t) rc;
280 }
281 async_wait_for(req, &rc);
282 async_serialize_end();
283 futex_up(&vfs_phone_futex);
[f7017572]284 if (rc == EOK)
285 return (ssize_t) IPC_GET_ARG1(answer);
286 else
[25becee8]287 return rc;
[2f02aa17]288}
289
[449c246]290ssize_t write(int fildes, const void *buf, size_t nbyte)
291{
292 ipcarg_t rc;
293 ipc_call_t answer;
294 aid_t req;
295
296 futex_down(&vfs_phone_futex);
297 async_serialize_start();
[19b28b0]298 vfs_connect();
299
[4198f9c3]300 req = async_send_1(vfs_phone, VFS_IN_WRITE, fildes, &answer);
[07e01e6]301 rc = ipc_data_write_start(vfs_phone, (void *)buf, nbyte);
302 if (rc != EOK) {
[449c246]303 async_wait_for(req, NULL);
304 async_serialize_end();
305 futex_up(&vfs_phone_futex);
306 return (ssize_t) rc;
307 }
308 async_wait_for(req, &rc);
309 async_serialize_end();
310 futex_up(&vfs_phone_futex);
[f7017572]311 if (rc == EOK)
312 return (ssize_t) IPC_GET_ARG1(answer);
313 else
314 return -1;
[449c246]315}
[222e57c]316
[2595dab]317int fsync(int fildes)
318{
319 futex_down(&vfs_phone_futex);
320 async_serialize_start();
321 vfs_connect();
322
[4198f9c3]323 ipcarg_t rc = async_req_1_0(vfs_phone, VFS_IN_SYNC, fildes);
[2595dab]324
325 async_serialize_end();
326 futex_up(&vfs_phone_futex);
327
328 return (int) rc;
329}
330
[222e57c]331off_t lseek(int fildes, off_t offset, int whence)
332{
333 ipcarg_t rc;
334
335 futex_down(&vfs_phone_futex);
336 async_serialize_start();
[19b28b0]337 vfs_connect();
338
[c61d34b]339 ipcarg_t newoffs;
[4198f9c3]340 rc = async_req_3_1(vfs_phone, VFS_IN_SEEK, fildes, offset, whence,
[c61d34b]341 &newoffs);
[222e57c]342
343 async_serialize_end();
344 futex_up(&vfs_phone_futex);
345
346 if (rc != EOK)
347 return (off_t) -1;
348
[c61d34b]349 return (off_t) newoffs;
[222e57c]350}
351
[0ee4322]352int ftruncate(int fildes, off_t length)
353{
354 ipcarg_t rc;
355
356 futex_down(&vfs_phone_futex);
357 async_serialize_start();
[19b28b0]358 vfs_connect();
359
[4198f9c3]360 rc = async_req_2_0(vfs_phone, VFS_IN_TRUNCATE, fildes, length);
[0ee4322]361 async_serialize_end();
362 futex_up(&vfs_phone_futex);
363 return (int) rc;
364}
365
[852b801]366int fstat(int fildes, struct stat *stat)
367{
368 ipcarg_t rc;
369 aid_t req;
370
371 futex_down(&vfs_phone_futex);
372 async_serialize_start();
373 vfs_connect();
374
375 req = async_send_1(vfs_phone, VFS_IN_FSTAT, fildes, NULL);
376 rc = ipc_data_read_start(vfs_phone, (void *)stat, sizeof(struct stat));
377 if (rc != EOK) {
378 async_wait_for(req, NULL);
379 async_serialize_end();
380 futex_up(&vfs_phone_futex);
381 return (ssize_t) rc;
382 }
383 async_wait_for(req, &rc);
384 async_serialize_end();
385 futex_up(&vfs_phone_futex);
386
387 return rc;
388}
389
[415c7e0d]390int stat(const char *path, struct stat *stat)
391{
392 ipcarg_t rc;
393 aid_t req;
394
395 size_t pa_size;
396 char *pa = absolutize(path, &pa_size);
397 if (!pa)
398 return ENOMEM;
399
400 futex_down(&vfs_phone_futex);
401 async_serialize_start();
402 vfs_connect();
403
404 req = async_send_0(vfs_phone, VFS_IN_STAT, NULL);
405 rc = ipc_data_write_start(vfs_phone, pa, pa_size);
406 if (rc != EOK) {
407 async_wait_for(req, NULL);
408 async_serialize_end();
409 futex_up(&vfs_phone_futex);
410 free(pa);
411 return (int) rc;
412 }
413 rc = ipc_data_read_start(vfs_phone, stat, sizeof(struct stat));
414 if (rc != EOK) {
415 async_wait_for(req, NULL);
416 async_serialize_end();
417 futex_up(&vfs_phone_futex);
418 free(pa);
419 return (int) rc;
420 }
421 async_wait_for(req, &rc);
422 async_serialize_end();
423 futex_up(&vfs_phone_futex);
424 free(pa);
425 return rc;
426}
427
[d0dc74ae]428DIR *opendir(const char *dirname)
429{
430 DIR *dirp = malloc(sizeof(DIR));
431 if (!dirp)
432 return NULL;
[ae78b530]433 dirp->fd = _open(dirname, L_DIRECTORY, 0);
[5973fd0]434 if (dirp->fd < 0) {
[d0dc74ae]435 free(dirp);
436 return NULL;
437 }
438 return dirp;
439}
440
441struct dirent *readdir(DIR *dirp)
442{
[5973fd0]443 ssize_t len = read(dirp->fd, &dirp->res.d_name[0], NAME_MAX + 1);
444 if (len <= 0)
445 return NULL;
446 return &dirp->res;
[d0dc74ae]447}
448
449void rewinddir(DIR *dirp)
450{
[5973fd0]451 (void) lseek(dirp->fd, 0, SEEK_SET);
[d0dc74ae]452}
453
454int closedir(DIR *dirp)
455{
456 (void) close(dirp->fd);
457 free(dirp);
458 return 0;
459}
460
[72bde81]461int mkdir(const char *path, mode_t mode)
[d0dc74ae]462{
[72bde81]463 ipcarg_t rc;
464 aid_t req;
465
[9eb3623]466 size_t pa_size;
467 char *pa = absolutize(path, &pa_size);
[5fec355]468 if (!pa)
469 return ENOMEM;
[19b28b0]470
[72bde81]471 futex_down(&vfs_phone_futex);
472 async_serialize_start();
[19b28b0]473 vfs_connect();
474
[4198f9c3]475 req = async_send_1(vfs_phone, VFS_IN_MKDIR, mode, NULL);
[9eb3623]476 rc = ipc_data_write_start(vfs_phone, pa, pa_size);
[72bde81]477 if (rc != EOK) {
478 async_wait_for(req, NULL);
479 async_serialize_end();
480 futex_up(&vfs_phone_futex);
[5fec355]481 free(pa);
[72bde81]482 return (int) rc;
483 }
484 async_wait_for(req, &rc);
485 async_serialize_end();
486 futex_up(&vfs_phone_futex);
[5fec355]487 free(pa);
[2595dab]488 return rc;
[d0dc74ae]489}
490
[f15cf1a6]491static int _unlink(const char *path, int lflag)
492{
493 ipcarg_t rc;
494 aid_t req;
495
[9eb3623]496 size_t pa_size;
497 char *pa = absolutize(path, &pa_size);
[5fec355]498 if (!pa)
499 return ENOMEM;
[923c39e]500
[f15cf1a6]501 futex_down(&vfs_phone_futex);
502 async_serialize_start();
[19b28b0]503 vfs_connect();
504
[4198f9c3]505 req = async_send_0(vfs_phone, VFS_IN_UNLINK, NULL);
[9eb3623]506 rc = ipc_data_write_start(vfs_phone, pa, pa_size);
[f15cf1a6]507 if (rc != EOK) {
508 async_wait_for(req, NULL);
509 async_serialize_end();
510 futex_up(&vfs_phone_futex);
[5fec355]511 free(pa);
[f15cf1a6]512 return (int) rc;
513 }
514 async_wait_for(req, &rc);
515 async_serialize_end();
516 futex_up(&vfs_phone_futex);
[5fec355]517 free(pa);
[2595dab]518 return rc;
[f15cf1a6]519}
520
521int unlink(const char *path)
522{
523 return _unlink(path, L_NONE);
524}
525
526int rmdir(const char *path)
527{
528 return _unlink(path, L_DIRECTORY);
529}
530
[a8e9ab8d]531int rename(const char *old, const char *new)
532{
533 ipcarg_t rc;
534 aid_t req;
535
[9eb3623]536 size_t olda_size;
537 char *olda = absolutize(old, &olda_size);
[a8e9ab8d]538 if (!olda)
539 return ENOMEM;
[923c39e]540
[9eb3623]541 size_t newa_size;
542 char *newa = absolutize(new, &newa_size);
[a8e9ab8d]543 if (!newa) {
544 free(olda);
545 return ENOMEM;
546 }
547
548 futex_down(&vfs_phone_futex);
549 async_serialize_start();
[19b28b0]550 vfs_connect();
551
[4198f9c3]552 req = async_send_0(vfs_phone, VFS_IN_RENAME, NULL);
[9eb3623]553 rc = ipc_data_write_start(vfs_phone, olda, olda_size);
[a8e9ab8d]554 if (rc != EOK) {
555 async_wait_for(req, NULL);
556 async_serialize_end();
557 futex_up(&vfs_phone_futex);
558 free(olda);
559 free(newa);
560 return (int) rc;
561 }
[9eb3623]562 rc = ipc_data_write_start(vfs_phone, newa, newa_size);
[a8e9ab8d]563 if (rc != EOK) {
564 async_wait_for(req, NULL);
565 async_serialize_end();
566 futex_up(&vfs_phone_futex);
567 free(olda);
568 free(newa);
569 return (int) rc;
570 }
571 async_wait_for(req, &rc);
572 async_serialize_end();
573 futex_up(&vfs_phone_futex);
574 free(olda);
575 free(newa);
576 return rc;
577}
578
[5fec355]579int chdir(const char *path)
580{
[9eb3623]581 size_t pa_size;
582 char *pa = absolutize(path, &pa_size);
[5fec355]583 if (!pa)
584 return ENOMEM;
585
[923c39e]586 DIR *d = opendir(pa);
[5fec355]587 if (!d) {
588 free(pa);
589 return ENOENT;
590 }
591
592 futex_down(&cwd_futex);
593 if (cwd_dir) {
594 closedir(cwd_dir);
595 cwd_dir = NULL;
596 free(cwd_path);
597 cwd_path = NULL;
[9eb3623]598 cwd_size = 0;
[5fec355]599 }
600 cwd_dir = d;
[923c39e]601 cwd_path = pa;
[9eb3623]602 cwd_size = pa_size;
[5fec355]603 futex_up(&cwd_futex);
[0dd0f71f]604 return EOK;
[5fec355]605}
606
607char *getcwd(char *buf, size_t size)
608{
609 if (!size)
610 return NULL;
611 futex_down(&cwd_futex);
[9eb3623]612 if (size < cwd_size + 1) {
[5fec355]613 futex_up(&cwd_futex);
614 return NULL;
615 }
[6eb2e96]616 str_cpy(buf, size, cwd_path);
[5fec355]617 futex_up(&cwd_futex);
618 return buf;
619}
620
[852b801]621int fd_phone(int fildes)
622{
623 struct stat stat;
624 int rc;
625
626 rc = fstat(fildes, &stat);
627
628 if (!stat.devfs_stat.device)
629 return -1;
630
631 return devmap_device_connect(stat.devfs_stat.device, 0);
632}
633
634int fd_node(int fildes, fdi_node_t *node)
635{
636 struct stat stat;
637 int rc;
638
639 rc = fstat(fildes, &stat);
640
641 if (rc == EOK) {
642 node->fs_handle = stat.fs_handle;
643 node->dev_handle = stat.dev_handle;
644 node->index = stat.index;
645 }
646
647 return rc;
648}
649
[2f02aa17]650/** @}
651 */
Note: See TracBrowser for help on using the repository browser.