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

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

C binding for devmap. Gets rid of duplicate code.

  • Property mode set to 100644
File size: 10.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 */
[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>
[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>
[1090b8c]51#include <devmap.h>
[d3e6935]52#include "../../../srv/vfs/vfs.h"
[2f02aa17]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;
[9eb3623]60size_t cwd_size = 0;
[5fec355]61
[17b2aac]62char *absolutize(const char *path, size_t *retlen)
[5fec355]63{
64 char *ncwd_path;
[34a74ab]65 char *ncwd_path_nc;
[5fec355]66
67 futex_down(&cwd_futex);
[9eb3623]68 size_t size = str_size(path);
[5fec355]69 if (*path != '/') {
70 if (!cwd_path) {
71 futex_up(&cwd_futex);
72 return NULL;
73 }
[9eb3623]74 ncwd_path_nc = malloc(cwd_size + 1 + size + 1);
[34a74ab]75 if (!ncwd_path_nc) {
[5fec355]76 futex_up(&cwd_futex);
77 return NULL;
78 }
[6eb2e96]79 str_cpy(ncwd_path_nc, cwd_size + 1 + size + 1, cwd_path);
[9eb3623]80 ncwd_path_nc[cwd_size] = '/';
81 ncwd_path_nc[cwd_size + 1] = '\0';
[5fec355]82 } else {
[9eb3623]83 ncwd_path_nc = malloc(size + 1);
[34a74ab]84 if (!ncwd_path_nc) {
[5fec355]85 futex_up(&cwd_futex);
86 return NULL;
87 }
[34a74ab]88 ncwd_path_nc[0] = '\0';
[5fec355]89 }
[4482bc7]90 str_append(ncwd_path_nc, cwd_size + 1 + size + 1, path);
[34a74ab]91 ncwd_path = canonify(ncwd_path_nc, retlen);
92 if (!ncwd_path) {
93 futex_up(&cwd_futex);
94 free(ncwd_path_nc);
95 return NULL;
96 }
97 /*
98 * We need to clone ncwd_path because canonify() works in-place and thus
99 * the address in ncwd_path need not be the same as ncwd_path_nc, even
100 * though they both point into the same dynamically allocated buffer.
101 */
[095003a8]102 ncwd_path = str_dup(ncwd_path);
[34a74ab]103 free(ncwd_path_nc);
104 if (!ncwd_path) {
[923c39e]105 futex_up(&cwd_futex);
106 return NULL;
107 }
[5fec355]108 futex_up(&cwd_futex);
109 return ncwd_path;
110}
[2f02aa17]111
[19b28b0]112static void vfs_connect(void)
[2f02aa17]113{
[19b28b0]114 while (vfs_phone < 0)
115 vfs_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VFS, 0, 0);
[2f02aa17]116}
117
[19b28b0]118int mount(const char *fs_name, const char *mp, const char *dev,
[1090b8c]119 const char *opts, unsigned int flags)
[2f02aa17]120{
121 int res;
122 ipcarg_t rc;
123 aid_t req;
[82405266]124 dev_handle_t dev_handle;
125
[1090b8c]126 res = devmap_device_get_handle(dev, &dev_handle, flags);
[82405266]127 if (res != EOK)
128 return res;
129
[9eb3623]130 size_t mpa_size;
131 char *mpa = absolutize(mp, &mpa_size);
[5fec355]132 if (!mpa)
133 return ENOMEM;
[19b28b0]134
[2f02aa17]135 futex_down(&vfs_phone_futex);
136 async_serialize_start();
[19b28b0]137 vfs_connect();
138
139 req = async_send_2(vfs_phone, VFS_MOUNT, dev_handle, flags, NULL);
[9eb3623]140 rc = ipc_data_write_start(vfs_phone, (void *) mpa, mpa_size);
[12fc042]141 if (rc != EOK) {
142 async_wait_for(req, NULL);
143 async_serialize_end();
144 futex_up(&vfs_phone_futex);
145 free(mpa);
146 return (int) rc;
147 }
[19b28b0]148
[594303b]149 rc = ipc_data_write_start(vfs_phone, (void *) opts, str_size(opts));
150 if (rc != EOK) {
151 async_wait_for(req, NULL);
152 async_serialize_end();
153 futex_up(&vfs_phone_futex);
154 free(mpa);
155 return (int) rc;
156 }
157
[9eb3623]158 rc = ipc_data_write_start(vfs_phone, (void *) fs_name, str_size(fs_name));
[2f02aa17]159 if (rc != EOK) {
160 async_wait_for(req, NULL);
161 async_serialize_end();
162 futex_up(&vfs_phone_futex);
[5fec355]163 free(mpa);
[2f02aa17]164 return (int) rc;
165 }
[c08c355]166
167 /* Ask VFS whether it likes fs_name. */
168 rc = async_req_0_0(vfs_phone, IPC_M_PING);
169 if (rc != EOK) {
170 async_wait_for(req, NULL);
171 async_serialize_end();
172 futex_up(&vfs_phone_futex);
173 free(mpa);
174 return (int) rc;
175 }
[19b28b0]176
[2f02aa17]177 async_wait_for(req, &rc);
178 async_serialize_end();
179 futex_up(&vfs_phone_futex);
[5fec355]180 free(mpa);
[19b28b0]181
[2f02aa17]182 return (int) rc;
183}
184
[ae78b530]185static int _open(const char *path, int lflag, int oflag, ...)
[2f02aa17]186{
187 ipcarg_t rc;
188 ipc_call_t answer;
189 aid_t req;
190
[9eb3623]191 size_t pa_size;
192 char *pa = absolutize(path, &pa_size);
[5fec355]193 if (!pa)
194 return ENOMEM;
195
[2f02aa17]196 futex_down(&vfs_phone_futex);
197 async_serialize_start();
[19b28b0]198 vfs_connect();
199
[ae78b530]200 req = async_send_3(vfs_phone, VFS_OPEN, lflag, oflag, 0, &answer);
[9eb3623]201 rc = ipc_data_write_start(vfs_phone, pa, pa_size);
[2f02aa17]202 if (rc != EOK) {
203 async_wait_for(req, NULL);
204 async_serialize_end();
205 futex_up(&vfs_phone_futex);
[5fec355]206 free(pa);
[2f02aa17]207 return (int) rc;
208 }
209 async_wait_for(req, &rc);
210 async_serialize_end();
211 futex_up(&vfs_phone_futex);
[5fec355]212 free(pa);
[412a31e]213
[57b4f46]214 if (rc != EOK)
215 return (int) rc;
[2f02aa17]216 return (int) IPC_GET_ARG1(answer);
217}
218
[ae78b530]219int open(const char *path, int oflag, ...)
220{
221 return _open(path, L_FILE, oflag);
222}
223
[72bde81]224int close(int fildes)
225{
[e704503]226 ipcarg_t rc;
[19b28b0]227
[e704503]228 futex_down(&vfs_phone_futex);
229 async_serialize_start();
[19b28b0]230 vfs_connect();
231
[e704503]232 rc = async_req_1_0(vfs_phone, VFS_CLOSE, fildes);
[19b28b0]233
[e704503]234 async_serialize_end();
235 futex_up(&vfs_phone_futex);
236
237 return (int)rc;
[72bde81]238}
239
[2f02aa17]240ssize_t read(int fildes, void *buf, size_t nbyte)
241{
242 ipcarg_t rc;
243 ipc_call_t answer;
244 aid_t req;
245
246 futex_down(&vfs_phone_futex);
247 async_serialize_start();
[19b28b0]248 vfs_connect();
249
[449c246]250 req = async_send_1(vfs_phone, VFS_READ, fildes, &answer);
[07e01e6]251 rc = ipc_data_read_start(vfs_phone, (void *)buf, nbyte);
252 if (rc != EOK) {
[2f02aa17]253 async_wait_for(req, NULL);
254 async_serialize_end();
255 futex_up(&vfs_phone_futex);
256 return (ssize_t) rc;
257 }
258 async_wait_for(req, &rc);
259 async_serialize_end();
260 futex_up(&vfs_phone_futex);
[f7017572]261 if (rc == EOK)
262 return (ssize_t) IPC_GET_ARG1(answer);
263 else
[25becee8]264 return rc;
[2f02aa17]265}
266
[449c246]267ssize_t write(int fildes, const void *buf, size_t nbyte)
268{
269 ipcarg_t rc;
270 ipc_call_t answer;
271 aid_t req;
272
273 futex_down(&vfs_phone_futex);
274 async_serialize_start();
[19b28b0]275 vfs_connect();
276
[449c246]277 req = async_send_1(vfs_phone, VFS_WRITE, fildes, &answer);
[07e01e6]278 rc = ipc_data_write_start(vfs_phone, (void *)buf, nbyte);
279 if (rc != EOK) {
[449c246]280 async_wait_for(req, NULL);
281 async_serialize_end();
282 futex_up(&vfs_phone_futex);
283 return (ssize_t) rc;
284 }
285 async_wait_for(req, &rc);
286 async_serialize_end();
287 futex_up(&vfs_phone_futex);
[f7017572]288 if (rc == EOK)
289 return (ssize_t) IPC_GET_ARG1(answer);
290 else
291 return -1;
[449c246]292}
[222e57c]293
294off_t lseek(int fildes, off_t offset, int whence)
295{
296 ipcarg_t rc;
297
298 futex_down(&vfs_phone_futex);
299 async_serialize_start();
[19b28b0]300 vfs_connect();
301
[c61d34b]302 ipcarg_t newoffs;
[222e57c]303 rc = async_req_3_1(vfs_phone, VFS_SEEK, fildes, offset, whence,
[c61d34b]304 &newoffs);
[222e57c]305
306 async_serialize_end();
307 futex_up(&vfs_phone_futex);
308
309 if (rc != EOK)
310 return (off_t) -1;
311
[c61d34b]312 return (off_t) newoffs;
[222e57c]313}
314
[0ee4322]315int ftruncate(int fildes, off_t length)
316{
317 ipcarg_t rc;
318
319 futex_down(&vfs_phone_futex);
320 async_serialize_start();
[19b28b0]321 vfs_connect();
322
[0ee4322]323 rc = async_req_2_0(vfs_phone, VFS_TRUNCATE, fildes, length);
324 async_serialize_end();
325 futex_up(&vfs_phone_futex);
326 return (int) rc;
327}
328
[d0dc74ae]329DIR *opendir(const char *dirname)
330{
331 DIR *dirp = malloc(sizeof(DIR));
332 if (!dirp)
333 return NULL;
[ae78b530]334 dirp->fd = _open(dirname, L_DIRECTORY, 0);
[5973fd0]335 if (dirp->fd < 0) {
[d0dc74ae]336 free(dirp);
337 return NULL;
338 }
339 return dirp;
340}
341
342struct dirent *readdir(DIR *dirp)
343{
[5973fd0]344 ssize_t len = read(dirp->fd, &dirp->res.d_name[0], NAME_MAX + 1);
345 if (len <= 0)
346 return NULL;
347 return &dirp->res;
[d0dc74ae]348}
349
350void rewinddir(DIR *dirp)
351{
[5973fd0]352 (void) lseek(dirp->fd, 0, SEEK_SET);
[d0dc74ae]353}
354
355int closedir(DIR *dirp)
356{
357 (void) close(dirp->fd);
358 free(dirp);
359 return 0;
360}
361
[72bde81]362int mkdir(const char *path, mode_t mode)
[d0dc74ae]363{
[72bde81]364 ipcarg_t rc;
365 aid_t req;
366
[9eb3623]367 size_t pa_size;
368 char *pa = absolutize(path, &pa_size);
[5fec355]369 if (!pa)
370 return ENOMEM;
[19b28b0]371
[72bde81]372 futex_down(&vfs_phone_futex);
373 async_serialize_start();
[19b28b0]374 vfs_connect();
375
[f15cf1a6]376 req = async_send_1(vfs_phone, VFS_MKDIR, mode, NULL);
[9eb3623]377 rc = ipc_data_write_start(vfs_phone, pa, pa_size);
[72bde81]378 if (rc != EOK) {
379 async_wait_for(req, NULL);
380 async_serialize_end();
381 futex_up(&vfs_phone_futex);
[5fec355]382 free(pa);
[72bde81]383 return (int) rc;
384 }
385 async_wait_for(req, &rc);
386 async_serialize_end();
387 futex_up(&vfs_phone_futex);
[5fec355]388 free(pa);
[d5d9c53]389 return rc;
[d0dc74ae]390}
391
[f15cf1a6]392static int _unlink(const char *path, int lflag)
393{
394 ipcarg_t rc;
395 aid_t req;
396
[9eb3623]397 size_t pa_size;
398 char *pa = absolutize(path, &pa_size);
[5fec355]399 if (!pa)
400 return ENOMEM;
[923c39e]401
[f15cf1a6]402 futex_down(&vfs_phone_futex);
403 async_serialize_start();
[19b28b0]404 vfs_connect();
405
[f15cf1a6]406 req = async_send_0(vfs_phone, VFS_UNLINK, NULL);
[9eb3623]407 rc = ipc_data_write_start(vfs_phone, pa, pa_size);
[f15cf1a6]408 if (rc != EOK) {
409 async_wait_for(req, NULL);
410 async_serialize_end();
411 futex_up(&vfs_phone_futex);
[5fec355]412 free(pa);
[f15cf1a6]413 return (int) rc;
414 }
415 async_wait_for(req, &rc);
416 async_serialize_end();
417 futex_up(&vfs_phone_futex);
[5fec355]418 free(pa);
[d5d9c53]419 return rc;
[f15cf1a6]420}
421
422int unlink(const char *path)
423{
424 return _unlink(path, L_NONE);
425}
426
427int rmdir(const char *path)
428{
429 return _unlink(path, L_DIRECTORY);
430}
431
[a8e9ab8d]432int rename(const char *old, const char *new)
433{
434 ipcarg_t rc;
435 aid_t req;
436
[9eb3623]437 size_t olda_size;
438 char *olda = absolutize(old, &olda_size);
[a8e9ab8d]439 if (!olda)
440 return ENOMEM;
[923c39e]441
[9eb3623]442 size_t newa_size;
443 char *newa = absolutize(new, &newa_size);
[a8e9ab8d]444 if (!newa) {
445 free(olda);
446 return ENOMEM;
447 }
448
449 futex_down(&vfs_phone_futex);
450 async_serialize_start();
[19b28b0]451 vfs_connect();
452
[a8e9ab8d]453 req = async_send_0(vfs_phone, VFS_RENAME, NULL);
[9eb3623]454 rc = ipc_data_write_start(vfs_phone, olda, olda_size);
[a8e9ab8d]455 if (rc != EOK) {
456 async_wait_for(req, NULL);
457 async_serialize_end();
458 futex_up(&vfs_phone_futex);
459 free(olda);
460 free(newa);
461 return (int) rc;
462 }
[9eb3623]463 rc = ipc_data_write_start(vfs_phone, newa, newa_size);
[a8e9ab8d]464 if (rc != EOK) {
465 async_wait_for(req, NULL);
466 async_serialize_end();
467 futex_up(&vfs_phone_futex);
468 free(olda);
469 free(newa);
470 return (int) rc;
471 }
472 async_wait_for(req, &rc);
473 async_serialize_end();
474 futex_up(&vfs_phone_futex);
475 free(olda);
476 free(newa);
477 return rc;
478}
479
[5fec355]480int chdir(const char *path)
481{
[9eb3623]482 size_t pa_size;
483 char *pa = absolutize(path, &pa_size);
[5fec355]484 if (!pa)
485 return ENOMEM;
486
[923c39e]487 DIR *d = opendir(pa);
[5fec355]488 if (!d) {
489 free(pa);
490 return ENOENT;
491 }
492
493 futex_down(&cwd_futex);
494 if (cwd_dir) {
495 closedir(cwd_dir);
496 cwd_dir = NULL;
497 free(cwd_path);
498 cwd_path = NULL;
[9eb3623]499 cwd_size = 0;
[5fec355]500 }
501 cwd_dir = d;
[923c39e]502 cwd_path = pa;
[9eb3623]503 cwd_size = pa_size;
[5fec355]504 futex_up(&cwd_futex);
[0dd0f71f]505 return EOK;
[5fec355]506}
507
508char *getcwd(char *buf, size_t size)
509{
510 if (!size)
511 return NULL;
512 futex_down(&cwd_futex);
[9eb3623]513 if (size < cwd_size + 1) {
[5fec355]514 futex_up(&cwd_futex);
515 return NULL;
516 }
[6eb2e96]517 str_cpy(buf, size, cwd_path);
[5fec355]518 futex_up(&cwd_futex);
519 return buf;
520}
521
[2f02aa17]522/** @}
523 */
Note: See TracBrowser for help on using the repository browser.