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

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

Fix missing rc check in libc _open()

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