2
* Copyright (c) 2008 Jakub Jermar
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
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.
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.
36
#include <vfs/canonify.h>
43
#include <sys/types.h>
45
#include <ipc/services.h>
53
#include <ipc/devmap.h>
55
static int vfs_phone = -1;
56
static futex_t vfs_phone_futex = FUTEX_INITIALIZER;
57
static futex_t cwd_futex = FUTEX_INITIALIZER;
60
char *cwd_path = NULL;
63
char *absolutize(const char *path, size_t *retlen)
68
futex_down(&cwd_futex);
69
size_t size = str_size(path);
75
ncwd_path_nc = malloc(cwd_size + 1 + size + 1);
80
str_cpy(ncwd_path_nc, cwd_size + 1 + size + 1, cwd_path);
81
ncwd_path_nc[cwd_size] = '/';
82
ncwd_path_nc[cwd_size + 1] = '\0';
84
ncwd_path_nc = malloc(size + 1);
89
ncwd_path_nc[0] = '\0';
91
str_append(ncwd_path_nc, cwd_size + 1 + size + 1, path);
92
ncwd_path = canonify(ncwd_path_nc, retlen);
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.
103
ncwd_path = str_dup(ncwd_path);
106
futex_up(&cwd_futex);
109
futex_up(&cwd_futex);
113
static void vfs_connect(void)
115
while (vfs_phone < 0)
116
vfs_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VFS, 0, 0);
119
int mount(const char *fs_name, const char *mp, const char *dev,
120
const char *opts, unsigned int flags)
125
dev_handle_t dev_handle;
127
res = devmap_device_get_handle(dev, &dev_handle, flags);
132
char *mpa = absolutize(mp, &mpa_size);
136
futex_down(&vfs_phone_futex);
137
async_serialize_start();
140
req = async_send_2(vfs_phone, VFS_IN_MOUNT, dev_handle, flags, NULL);
141
rc = ipc_data_write_start(vfs_phone, (void *) mpa, mpa_size);
143
async_wait_for(req, NULL);
144
async_serialize_end();
145
futex_up(&vfs_phone_futex);
150
rc = ipc_data_write_start(vfs_phone, (void *) opts, str_size(opts));
152
async_wait_for(req, NULL);
153
async_serialize_end();
154
futex_up(&vfs_phone_futex);
159
rc = ipc_data_write_start(vfs_phone, (void *) fs_name, str_size(fs_name));
161
async_wait_for(req, NULL);
162
async_serialize_end();
163
futex_up(&vfs_phone_futex);
168
/* Ask VFS whether it likes fs_name. */
169
rc = async_req_0_0(vfs_phone, IPC_M_PING);
171
async_wait_for(req, NULL);
172
async_serialize_end();
173
futex_up(&vfs_phone_futex);
178
async_wait_for(req, &rc);
179
async_serialize_end();
180
futex_up(&vfs_phone_futex);
186
static int _open(const char *path, int lflag, int oflag, ...)
193
char *pa = absolutize(path, &pa_size);
197
futex_down(&vfs_phone_futex);
198
async_serialize_start();
201
req = async_send_3(vfs_phone, VFS_IN_OPEN, lflag, oflag, 0, &answer);
202
rc = ipc_data_write_start(vfs_phone, pa, pa_size);
204
async_wait_for(req, NULL);
205
async_serialize_end();
206
futex_up(&vfs_phone_futex);
210
async_wait_for(req, &rc);
211
async_serialize_end();
212
futex_up(&vfs_phone_futex);
218
return (int) IPC_GET_ARG1(answer);
221
int open(const char *path, int oflag, ...)
223
return _open(path, L_FILE, oflag);
226
int open_node(fdi_node_t *node, int oflag)
228
futex_down(&vfs_phone_futex);
229
async_serialize_start();
233
aid_t req = async_send_4(vfs_phone, VFS_IN_OPEN_NODE, node->fs_handle,
234
node->dev_handle, node->index, oflag, &answer);
237
async_wait_for(req, &rc);
238
async_serialize_end();
239
futex_up(&vfs_phone_futex);
244
return (int) IPC_GET_ARG1(answer);
247
int close(int fildes)
251
futex_down(&vfs_phone_futex);
252
async_serialize_start();
255
rc = async_req_1_0(vfs_phone, VFS_IN_CLOSE, fildes);
257
async_serialize_end();
258
futex_up(&vfs_phone_futex);
263
ssize_t read(int fildes, void *buf, size_t nbyte)
269
futex_down(&vfs_phone_futex);
270
async_serialize_start();
273
req = async_send_1(vfs_phone, VFS_IN_READ, fildes, &answer);
274
rc = ipc_data_read_start(vfs_phone, (void *)buf, nbyte);
276
async_wait_for(req, NULL);
277
async_serialize_end();
278
futex_up(&vfs_phone_futex);
281
async_wait_for(req, &rc);
282
async_serialize_end();
283
futex_up(&vfs_phone_futex);
285
return (ssize_t) IPC_GET_ARG1(answer);
290
ssize_t write(int fildes, const void *buf, size_t nbyte)
296
futex_down(&vfs_phone_futex);
297
async_serialize_start();
300
req = async_send_1(vfs_phone, VFS_IN_WRITE, fildes, &answer);
301
rc = ipc_data_write_start(vfs_phone, (void *)buf, nbyte);
303
async_wait_for(req, NULL);
304
async_serialize_end();
305
futex_up(&vfs_phone_futex);
308
async_wait_for(req, &rc);
309
async_serialize_end();
310
futex_up(&vfs_phone_futex);
312
return (ssize_t) IPC_GET_ARG1(answer);
317
int fsync(int fildes)
319
futex_down(&vfs_phone_futex);
320
async_serialize_start();
323
ipcarg_t rc = async_req_1_0(vfs_phone, VFS_IN_SYNC, fildes);
325
async_serialize_end();
326
futex_up(&vfs_phone_futex);
331
off_t lseek(int fildes, off_t offset, int whence)
335
futex_down(&vfs_phone_futex);
336
async_serialize_start();
340
rc = async_req_3_1(vfs_phone, VFS_IN_SEEK, fildes, offset, whence,
343
async_serialize_end();
344
futex_up(&vfs_phone_futex);
349
return (off_t) newoffs;
352
int ftruncate(int fildes, off_t length)
356
futex_down(&vfs_phone_futex);
357
async_serialize_start();
360
rc = async_req_2_0(vfs_phone, VFS_IN_TRUNCATE, fildes, length);
361
async_serialize_end();
362
futex_up(&vfs_phone_futex);
366
int fstat(int fildes, struct stat *stat)
371
futex_down(&vfs_phone_futex);
372
async_serialize_start();
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));
378
async_wait_for(req, NULL);
379
async_serialize_end();
380
futex_up(&vfs_phone_futex);
383
async_wait_for(req, &rc);
384
async_serialize_end();
385
futex_up(&vfs_phone_futex);
390
int stat(const char *path, struct stat *stat)
396
char *pa = absolutize(path, &pa_size);
400
futex_down(&vfs_phone_futex);
401
async_serialize_start();
404
req = async_send_0(vfs_phone, VFS_IN_STAT, NULL);
405
rc = ipc_data_write_start(vfs_phone, pa, pa_size);
407
async_wait_for(req, NULL);
408
async_serialize_end();
409
futex_up(&vfs_phone_futex);
413
rc = ipc_data_read_start(vfs_phone, stat, sizeof(struct stat));
415
async_wait_for(req, NULL);
416
async_serialize_end();
417
futex_up(&vfs_phone_futex);
421
async_wait_for(req, &rc);
422
async_serialize_end();
423
futex_up(&vfs_phone_futex);
428
DIR *opendir(const char *dirname)
430
DIR *dirp = malloc(sizeof(DIR));
433
dirp->fd = _open(dirname, L_DIRECTORY, 0);
441
struct dirent *readdir(DIR *dirp)
443
ssize_t len = read(dirp->fd, &dirp->res.d_name[0], NAME_MAX + 1);
449
void rewinddir(DIR *dirp)
451
(void) lseek(dirp->fd, 0, SEEK_SET);
454
int closedir(DIR *dirp)
456
(void) close(dirp->fd);
461
int mkdir(const char *path, mode_t mode)
467
char *pa = absolutize(path, &pa_size);
471
futex_down(&vfs_phone_futex);
472
async_serialize_start();
475
req = async_send_1(vfs_phone, VFS_IN_MKDIR, mode, NULL);
476
rc = ipc_data_write_start(vfs_phone, pa, pa_size);
478
async_wait_for(req, NULL);
479
async_serialize_end();
480
futex_up(&vfs_phone_futex);
484
async_wait_for(req, &rc);
485
async_serialize_end();
486
futex_up(&vfs_phone_futex);
491
static int _unlink(const char *path, int lflag)
497
char *pa = absolutize(path, &pa_size);
501
futex_down(&vfs_phone_futex);
502
async_serialize_start();
505
req = async_send_0(vfs_phone, VFS_IN_UNLINK, NULL);
506
rc = ipc_data_write_start(vfs_phone, pa, pa_size);
508
async_wait_for(req, NULL);
509
async_serialize_end();
510
futex_up(&vfs_phone_futex);
514
async_wait_for(req, &rc);
515
async_serialize_end();
516
futex_up(&vfs_phone_futex);
521
int unlink(const char *path)
523
return _unlink(path, L_NONE);
526
int rmdir(const char *path)
528
return _unlink(path, L_DIRECTORY);
531
int rename(const char *old, const char *new)
537
char *olda = absolutize(old, &olda_size);
542
char *newa = absolutize(new, &newa_size);
548
futex_down(&vfs_phone_futex);
549
async_serialize_start();
552
req = async_send_0(vfs_phone, VFS_IN_RENAME, NULL);
553
rc = ipc_data_write_start(vfs_phone, olda, olda_size);
555
async_wait_for(req, NULL);
556
async_serialize_end();
557
futex_up(&vfs_phone_futex);
562
rc = ipc_data_write_start(vfs_phone, newa, newa_size);
564
async_wait_for(req, NULL);
565
async_serialize_end();
566
futex_up(&vfs_phone_futex);
571
async_wait_for(req, &rc);
572
async_serialize_end();
573
futex_up(&vfs_phone_futex);
579
int chdir(const char *path)
582
char *pa = absolutize(path, &pa_size);
586
DIR *d = opendir(pa);
592
futex_down(&cwd_futex);
603
futex_up(&cwd_futex);
607
char *getcwd(char *buf, size_t size)
611
futex_down(&cwd_futex);
612
if (size < cwd_size + 1) {
613
futex_up(&cwd_futex);
616
str_cpy(buf, size, cwd_path);
617
futex_up(&cwd_futex);
621
int fd_phone(int fildes)
626
rc = fstat(fildes, &stat);
628
if (!stat.devfs_stat.device)
631
return devmap_device_connect(stat.devfs_stat.device, 0);
634
int fd_node(int fildes, fdi_node_t *node)
639
rc = fstat(fildes, &stat);
642
node->fs_handle = stat.fs_handle;
643
node->dev_handle = stat.dev_handle;
644
node->index = stat.index;