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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since ade06b4 was 57b4f46, checked in by Jakub Jermar <jakub@…>, 17 years ago

cstyle

  • Property mode set to 100644
File size: 11.8 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 */
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>
[72bde81]41#include <sys/stat.h>
[923c39e]42#include <stdio.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>
[82405266]51#include <ipc/devmap.h>
[2f02aa17]52#include "../../srv/vfs/vfs.h"
53
54int vfs_phone = -1;
[5fec355]55futex_t vfs_phone_futex = FUTEX_INITIALIZER;
56
57futex_t cwd_futex = FUTEX_INITIALIZER;
58DIR *cwd_dir = NULL;
59char *cwd_path = NULL;
60size_t cwd_len = 0;
61
[923c39e]62static char *absolutize(const char *path, size_t *retlen)
[5fec355]63{
64 char *ncwd_path;
65
66 futex_down(&cwd_futex);
67 size_t len = strlen(path);
68 if (*path != '/') {
69 if (!cwd_path) {
70 futex_up(&cwd_futex);
71 return NULL;
72 }
73 ncwd_path = malloc(len + cwd_len + 1);
74 if (!ncwd_path) {
75 futex_up(&cwd_futex);
76 return NULL;
77 }
78 strcpy(ncwd_path, cwd_path);
79 ncwd_path[cwd_len] = '/';
80 ncwd_path[cwd_len + 1] = '\0';
81 } else {
82 ncwd_path = malloc(len + 1);
83 if (!ncwd_path) {
84 futex_up(&cwd_futex);
85 return NULL;
86 }
87 ncwd_path[0] = '\0';
88 }
89 strcat(ncwd_path, path);
[923c39e]90 if (!canonify(ncwd_path, retlen)) {
91 futex_up(&cwd_futex);
92 free(ncwd_path);
93 return NULL;
94 }
[5fec355]95 futex_up(&cwd_futex);
96 return ncwd_path;
97}
[2f02aa17]98
99static int vfs_connect(void)
100{
101 if (vfs_phone < 0)
102 vfs_phone = ipc_connect_me_to(PHONE_NS, SERVICE_VFS, 0, 0);
103 return vfs_phone;
104}
105
[82405266]106static int device_get_handle(char *name, dev_handle_t *handle)
107{
[57b4f46]108 int phone = ipc_connect_me_to(PHONE_NS, SERVICE_DEVMAP, DEVMAP_CLIENT,
109 0);
[82405266]110 if (phone < 0)
111 return phone;
112
113 ipc_call_t answer;
114 aid_t req = async_send_2(phone, DEVMAP_DEVICE_GET_HANDLE, 0, 0,
115 &answer);
116
117 ipcarg_t retval = ipc_data_write_start(phone, name, strlen(name) + 1);
118
119 if (retval != EOK) {
120 async_wait_for(req, NULL);
121 ipc_hangup(phone);
122 return retval;
123 }
124
125 async_wait_for(req, &retval);
126
127 if (handle != NULL)
128 *handle = -1;
129
130 if (retval == EOK) {
131 if (handle != NULL)
132 *handle = (dev_handle_t) IPC_GET_ARG1(answer);
133 }
134
135 ipc_hangup(phone);
136 return retval;
137}
138
[2f02aa17]139int mount(const char *fs_name, const char *mp, const char *dev)
140{
141 int res;
142 ipcarg_t rc;
143 aid_t req;
[82405266]144 dev_handle_t dev_handle;
145
146 res = device_get_handle(dev, &dev_handle);
147 if (res != EOK)
148 return res;
149
[923c39e]150 size_t mpa_len;
151 char *mpa = absolutize(mp, &mpa_len);
[5fec355]152 if (!mpa)
153 return ENOMEM;
154
[2f02aa17]155 futex_down(&vfs_phone_futex);
156 async_serialize_start();
157 if (vfs_phone < 0) {
158 res = vfs_connect();
159 if (res < 0) {
160 async_serialize_end();
161 futex_up(&vfs_phone_futex);
[5fec355]162 free(mpa);
[2f02aa17]163 return res;
164 }
165 }
166 req = async_send_1(vfs_phone, VFS_MOUNT, dev_handle, NULL);
[215e375]167 rc = ipc_data_write_start(vfs_phone, (void *)fs_name, strlen(fs_name));
[2f02aa17]168 if (rc != EOK) {
169 async_wait_for(req, NULL);
170 async_serialize_end();
171 futex_up(&vfs_phone_futex);
[5fec355]172 free(mpa);
[2f02aa17]173 return (int) rc;
174 }
[923c39e]175 rc = ipc_data_write_start(vfs_phone, (void *)mpa, mpa_len);
[2f02aa17]176 if (rc != EOK) {
177 async_wait_for(req, NULL);
178 async_serialize_end();
179 futex_up(&vfs_phone_futex);
[5fec355]180 free(mpa);
[2f02aa17]181 return (int) rc;
182 }
183 async_wait_for(req, &rc);
184 async_serialize_end();
185 futex_up(&vfs_phone_futex);
[5fec355]186 free(mpa);
[2f02aa17]187 return (int) rc;
188}
189
[ae78b530]190static int _open(const char *path, int lflag, int oflag, ...)
[2f02aa17]191{
192 int res;
193 ipcarg_t rc;
194 ipc_call_t answer;
195 aid_t req;
196
[923c39e]197 size_t pa_len;
198 char *pa = absolutize(path, &pa_len);
[5fec355]199 if (!pa)
200 return ENOMEM;
201
[2f02aa17]202 futex_down(&vfs_phone_futex);
203 async_serialize_start();
204 if (vfs_phone < 0) {
205 res = vfs_connect();
206 if (res < 0) {
207 async_serialize_end();
208 futex_up(&vfs_phone_futex);
[5fec355]209 free(pa);
[2f02aa17]210 return res;
211 }
212 }
[ae78b530]213 req = async_send_3(vfs_phone, VFS_OPEN, lflag, oflag, 0, &answer);
[923c39e]214 rc = ipc_data_write_start(vfs_phone, pa, pa_len);
[2f02aa17]215 if (rc != EOK) {
216 async_wait_for(req, NULL);
217 async_serialize_end();
218 futex_up(&vfs_phone_futex);
[5fec355]219 free(pa);
[2f02aa17]220 return (int) rc;
221 }
222 async_wait_for(req, &rc);
223 async_serialize_end();
224 futex_up(&vfs_phone_futex);
[5fec355]225 free(pa);
[412a31e]226
[57b4f46]227 if (rc != EOK)
228 return (int) rc;
[2f02aa17]229 return (int) IPC_GET_ARG1(answer);
230}
231
[ae78b530]232int open(const char *path, int oflag, ...)
233{
234 return _open(path, L_FILE, oflag);
235}
236
[72bde81]237int close(int fildes)
238{
[e704503]239 int res;
240 ipcarg_t rc;
241
242 futex_down(&vfs_phone_futex);
243 async_serialize_start();
244 if (vfs_phone < 0) {
245 res = vfs_connect();
246 if (res < 0) {
247 async_serialize_end();
248 futex_up(&vfs_phone_futex);
249 return res;
250 }
251 }
252
253 rc = async_req_1_0(vfs_phone, VFS_CLOSE, fildes);
254
255 async_serialize_end();
256 futex_up(&vfs_phone_futex);
257
258 return (int)rc;
[72bde81]259}
260
[2f02aa17]261ssize_t read(int fildes, void *buf, size_t nbyte)
262{
263 int res;
264 ipcarg_t rc;
265 ipc_call_t answer;
266 aid_t req;
267
268 futex_down(&vfs_phone_futex);
269 async_serialize_start();
270 if (vfs_phone < 0) {
271 res = vfs_connect();
272 if (res < 0) {
273 async_serialize_end();
274 futex_up(&vfs_phone_futex);
275 return res;
276 }
277 }
[449c246]278 req = async_send_1(vfs_phone, VFS_READ, fildes, &answer);
[07e01e6]279 rc = ipc_data_read_start(vfs_phone, (void *)buf, nbyte);
280 if (rc != EOK) {
[2f02aa17]281 async_wait_for(req, NULL);
282 async_serialize_end();
283 futex_up(&vfs_phone_futex);
284 return (ssize_t) rc;
285 }
286 async_wait_for(req, &rc);
287 async_serialize_end();
288 futex_up(&vfs_phone_futex);
[f7017572]289 if (rc == EOK)
290 return (ssize_t) IPC_GET_ARG1(answer);
291 else
292 return -1;
[2f02aa17]293}
294
[449c246]295ssize_t write(int fildes, const void *buf, size_t nbyte)
296{
297 int res;
298 ipcarg_t rc;
299 ipc_call_t answer;
300 aid_t req;
301
302 futex_down(&vfs_phone_futex);
303 async_serialize_start();
304 if (vfs_phone < 0) {
305 res = vfs_connect();
306 if (res < 0) {
307 async_serialize_end();
308 futex_up(&vfs_phone_futex);
309 return res;
310 }
311 }
312 req = async_send_1(vfs_phone, VFS_WRITE, fildes, &answer);
[07e01e6]313 rc = ipc_data_write_start(vfs_phone, (void *)buf, nbyte);
314 if (rc != EOK) {
[449c246]315 async_wait_for(req, NULL);
316 async_serialize_end();
317 futex_up(&vfs_phone_futex);
318 return (ssize_t) rc;
319 }
320 async_wait_for(req, &rc);
321 async_serialize_end();
322 futex_up(&vfs_phone_futex);
[f7017572]323 if (rc == EOK)
324 return (ssize_t) IPC_GET_ARG1(answer);
325 else
326 return -1;
[449c246]327}
[222e57c]328
329off_t lseek(int fildes, off_t offset, int whence)
330{
331 int res;
332 ipcarg_t rc;
333
334 futex_down(&vfs_phone_futex);
335 async_serialize_start();
336 if (vfs_phone < 0) {
337 res = vfs_connect();
338 if (res < 0) {
339 async_serialize_end();
340 futex_up(&vfs_phone_futex);
341 return res;
342 }
343 }
344
345 off_t newoffs;
346 rc = async_req_3_1(vfs_phone, VFS_SEEK, fildes, offset, whence,
[72bde81]347 (ipcarg_t)&newoffs);
[222e57c]348
349 async_serialize_end();
350 futex_up(&vfs_phone_futex);
351
352 if (rc != EOK)
353 return (off_t) -1;
354
355 return newoffs;
356}
357
[0ee4322]358int ftruncate(int fildes, off_t length)
359{
360 int res;
361 ipcarg_t rc;
362
363 futex_down(&vfs_phone_futex);
364 async_serialize_start();
365 if (vfs_phone < 0) {
366 res = vfs_connect();
367 if (res < 0) {
368 async_serialize_end();
369 futex_up(&vfs_phone_futex);
370 return res;
371 }
372 }
373 rc = async_req_2_0(vfs_phone, VFS_TRUNCATE, fildes, length);
374 async_serialize_end();
375 futex_up(&vfs_phone_futex);
376 return (int) rc;
377}
378
[d0dc74ae]379DIR *opendir(const char *dirname)
380{
381 DIR *dirp = malloc(sizeof(DIR));
382 if (!dirp)
383 return NULL;
[ae78b530]384 dirp->fd = _open(dirname, L_DIRECTORY, 0);
[5973fd0]385 if (dirp->fd < 0) {
[d0dc74ae]386 free(dirp);
387 return NULL;
388 }
389 return dirp;
390}
391
392struct dirent *readdir(DIR *dirp)
393{
[5973fd0]394 ssize_t len = read(dirp->fd, &dirp->res.d_name[0], NAME_MAX + 1);
395 if (len <= 0)
396 return NULL;
397 return &dirp->res;
[d0dc74ae]398}
399
400void rewinddir(DIR *dirp)
401{
[5973fd0]402 (void) lseek(dirp->fd, 0, SEEK_SET);
[d0dc74ae]403}
404
405int closedir(DIR *dirp)
406{
407 (void) close(dirp->fd);
408 free(dirp);
409 return 0;
410}
411
[72bde81]412int mkdir(const char *path, mode_t mode)
[d0dc74ae]413{
[72bde81]414 int res;
415 ipcarg_t rc;
416 aid_t req;
417
[923c39e]418 size_t pa_len;
419 char *pa = absolutize(path, &pa_len);
[5fec355]420 if (!pa)
421 return ENOMEM;
422
[72bde81]423 futex_down(&vfs_phone_futex);
424 async_serialize_start();
425 if (vfs_phone < 0) {
426 res = vfs_connect();
427 if (res < 0) {
428 async_serialize_end();
429 futex_up(&vfs_phone_futex);
[5fec355]430 free(pa);
[72bde81]431 return res;
432 }
433 }
[f15cf1a6]434 req = async_send_1(vfs_phone, VFS_MKDIR, mode, NULL);
[923c39e]435 rc = ipc_data_write_start(vfs_phone, pa, pa_len);
[72bde81]436 if (rc != EOK) {
437 async_wait_for(req, NULL);
438 async_serialize_end();
439 futex_up(&vfs_phone_futex);
[5fec355]440 free(pa);
[72bde81]441 return (int) rc;
442 }
443 async_wait_for(req, &rc);
444 async_serialize_end();
445 futex_up(&vfs_phone_futex);
[5fec355]446 free(pa);
[d5d9c53]447 return rc;
[d0dc74ae]448}
449
[f15cf1a6]450static int _unlink(const char *path, int lflag)
451{
452 int res;
453 ipcarg_t rc;
454 aid_t req;
455
[923c39e]456 size_t pa_len;
457 char *pa = absolutize(path, &pa_len);
[5fec355]458 if (!pa)
459 return ENOMEM;
[923c39e]460
[f15cf1a6]461 futex_down(&vfs_phone_futex);
462 async_serialize_start();
463 if (vfs_phone < 0) {
464 res = vfs_connect();
465 if (res < 0) {
466 async_serialize_end();
467 futex_up(&vfs_phone_futex);
[5fec355]468 free(pa);
[f15cf1a6]469 return res;
470 }
471 }
472 req = async_send_0(vfs_phone, VFS_UNLINK, NULL);
[923c39e]473 rc = ipc_data_write_start(vfs_phone, pa, pa_len);
[f15cf1a6]474 if (rc != EOK) {
475 async_wait_for(req, NULL);
476 async_serialize_end();
477 futex_up(&vfs_phone_futex);
[5fec355]478 free(pa);
[f15cf1a6]479 return (int) rc;
480 }
481 async_wait_for(req, &rc);
482 async_serialize_end();
483 futex_up(&vfs_phone_futex);
[5fec355]484 free(pa);
[d5d9c53]485 return rc;
[f15cf1a6]486}
487
488int unlink(const char *path)
489{
490 return _unlink(path, L_NONE);
491}
492
493int rmdir(const char *path)
494{
495 return _unlink(path, L_DIRECTORY);
496}
497
[a8e9ab8d]498int rename(const char *old, const char *new)
499{
500 int res;
501 ipcarg_t rc;
502 aid_t req;
503
[923c39e]504 size_t olda_len;
505 char *olda = absolutize(old, &olda_len);
[a8e9ab8d]506 if (!olda)
507 return ENOMEM;
[923c39e]508
509 size_t newa_len;
510 char *newa = absolutize(new, &newa_len);
[a8e9ab8d]511 if (!newa) {
512 free(olda);
513 return ENOMEM;
514 }
515
516 futex_down(&vfs_phone_futex);
517 async_serialize_start();
518 if (vfs_phone < 0) {
519 res = vfs_connect();
520 if (res < 0) {
521 async_serialize_end();
522 futex_up(&vfs_phone_futex);
523 free(olda);
524 free(newa);
525 return res;
526 }
527 }
528 req = async_send_0(vfs_phone, VFS_RENAME, NULL);
[923c39e]529 rc = ipc_data_write_start(vfs_phone, olda, olda_len);
[a8e9ab8d]530 if (rc != EOK) {
531 async_wait_for(req, NULL);
532 async_serialize_end();
533 futex_up(&vfs_phone_futex);
534 free(olda);
535 free(newa);
536 return (int) rc;
537 }
[923c39e]538 rc = ipc_data_write_start(vfs_phone, newa, newa_len);
[a8e9ab8d]539 if (rc != EOK) {
540 async_wait_for(req, NULL);
541 async_serialize_end();
542 futex_up(&vfs_phone_futex);
543 free(olda);
544 free(newa);
545 return (int) rc;
546 }
547 async_wait_for(req, &rc);
548 async_serialize_end();
549 futex_up(&vfs_phone_futex);
550 free(olda);
551 free(newa);
552 return rc;
553}
554
[5fec355]555int chdir(const char *path)
556{
[923c39e]557 size_t pa_len;
558 char *pa = absolutize(path, &pa_len);
[5fec355]559 if (!pa)
560 return ENOMEM;
561
[923c39e]562 DIR *d = opendir(pa);
[5fec355]563 if (!d) {
564 free(pa);
565 return ENOENT;
566 }
567
568 futex_down(&cwd_futex);
569 if (cwd_dir) {
570 closedir(cwd_dir);
571 cwd_dir = NULL;
572 free(cwd_path);
573 cwd_path = NULL;
574 cwd_len = 0;
575 }
576 cwd_dir = d;
[923c39e]577 cwd_path = pa;
578 cwd_len = pa_len;
[5fec355]579 futex_up(&cwd_futex);
580}
581
582char *getcwd(char *buf, size_t size)
583{
584 if (!size)
585 return NULL;
586 futex_down(&cwd_futex);
587 if (size < cwd_len + 1) {
588 futex_up(&cwd_futex);
589 return NULL;
590 }
591 strcpy(buf, cwd_path);
592 futex_up(&cwd_futex);
593 return buf;
594}
595
[2f02aa17]596/** @}
597 */
Note: See TracBrowser for help on using the repository browser.