source: mainline/uspace/lib/c/generic/vfs/vfs.c@ 3ef62df

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 3ef62df was 3ef62df, checked in by Ji?? Z?rev?cky <zarevucky.jiri@…>, 12 years ago

Reimplement open() using WALK and OPEN2.

  • Property mode set to 100644
File size: 19.4 KB
RevLine 
[2f02aa17]1/*
[64d2b10]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/canonify.h>
[79ae36dd]36#include <vfs/vfs.h>
37#include <vfs/vfs_sess.h>
[ed903174]38#include <macros.h>
[d0dc74ae]39#include <stdlib.h>
[449c246]40#include <unistd.h>
[d0dc74ae]41#include <dirent.h>
[449c246]42#include <fcntl.h>
[923c39e]43#include <stdio.h>
[852b801]44#include <sys/stat.h>
[72bde81]45#include <sys/types.h>
[2f02aa17]46#include <ipc/services.h>
[79ae36dd]47#include <ns.h>
[2f02aa17]48#include <async.h>
[a28ab12]49#include <fibril_synch.h>
[2f02aa17]50#include <errno.h>
[a28ab12]51#include <assert.h>
[19f857a]52#include <str.h>
[15f3c3f]53#include <loc.h>
[2595dab]54#include <ipc/vfs.h>
[15f3c3f]55#include <ipc/loc.h>
[2f02aa17]56
[79ae36dd]57static FIBRIL_MUTEX_INITIALIZE(vfs_mutex);
58static async_sess_t *vfs_sess = NULL;
[a28ab12]59
60static FIBRIL_MUTEX_INITIALIZE(cwd_mutex);
[5fec355]61
[2b88074b]62static int cwd_fd = -1;
63static char *cwd_path = NULL;
64static size_t cwd_size = 0;
[5fec355]65
[79ae36dd]66/** Start an async exchange on the VFS session.
67 *
68 * @return New exchange.
69 *
70 */
[866e627]71async_exch_t *vfs_exchange_begin(void)
[79ae36dd]72{
73 fibril_mutex_lock(&vfs_mutex);
74
75 while (vfs_sess == NULL)
76 vfs_sess = service_connect_blocking(EXCHANGE_PARALLEL, SERVICE_VFS,
77 0, 0);
78
79 fibril_mutex_unlock(&vfs_mutex);
80
81 return async_exchange_begin(vfs_sess);
82}
83
84/** Finish an async exchange on the VFS session.
85 *
86 * @param exch Exchange to be finished.
87 *
88 */
[866e627]89void vfs_exchange_end(async_exch_t *exch)
[79ae36dd]90{
91 async_exchange_end(exch);
92}
93
[0b18364]94int _vfs_walk(int parent, const char *path, int flags)
95{
96 async_exch_t *exch = vfs_exchange_begin();
97
98 ipc_call_t answer;
99 aid_t req = async_send_2(exch, VFS_IN_WALK, parent, flags, &answer);
[3ef62df]100 sysarg_t rc = async_data_write_start(exch, path, str_size(path));
[0b18364]101 vfs_exchange_end(exch);
102
103 sysarg_t rc_orig;
104 async_wait_for(req, &rc_orig);
105
106 if (rc_orig != EOK) {
107 return (int) rc_orig;
108 }
109
110 if (rc != EOK) {
111 return (int) rc;
112 }
113
114 return (int) IPC_GET_ARG1(answer);
115}
116
117int _vfs_open(int fildes, int mode)
118{
119 async_exch_t *exch = vfs_exchange_begin();
120 sysarg_t rc = async_req_2_0(exch, VFS_IN_OPEN2, fildes, mode);
121 vfs_exchange_end(exch);
122
123 return (int) rc;
124}
125
[17b2aac]126char *absolutize(const char *path, size_t *retlen)
[5fec355]127{
128 char *ncwd_path;
[34a74ab]129 char *ncwd_path_nc;
[5fec355]130
[a28ab12]131 fibril_mutex_lock(&cwd_mutex);
[9eb3623]132 size_t size = str_size(path);
[5fec355]133 if (*path != '/') {
134 if (!cwd_path) {
[a28ab12]135 fibril_mutex_unlock(&cwd_mutex);
[5fec355]136 return NULL;
137 }
[79ae36dd]138 ncwd_path_nc = malloc(cwd_size + 1 + size + 1);
[34a74ab]139 if (!ncwd_path_nc) {
[a28ab12]140 fibril_mutex_unlock(&cwd_mutex);
[5fec355]141 return NULL;
142 }
[79ae36dd]143 str_cpy(ncwd_path_nc, cwd_size + 1 + size + 1, cwd_path);
[9eb3623]144 ncwd_path_nc[cwd_size] = '/';
145 ncwd_path_nc[cwd_size + 1] = '\0';
[5fec355]146 } else {
[79ae36dd]147 ncwd_path_nc = malloc(size + 1);
[34a74ab]148 if (!ncwd_path_nc) {
[a28ab12]149 fibril_mutex_unlock(&cwd_mutex);
[5fec355]150 return NULL;
151 }
[34a74ab]152 ncwd_path_nc[0] = '\0';
[5fec355]153 }
[79ae36dd]154 str_append(ncwd_path_nc, cwd_size + 1 + size + 1, path);
[34a74ab]155 ncwd_path = canonify(ncwd_path_nc, retlen);
156 if (!ncwd_path) {
[a28ab12]157 fibril_mutex_unlock(&cwd_mutex);
[34a74ab]158 free(ncwd_path_nc);
159 return NULL;
160 }
161 /*
162 * We need to clone ncwd_path because canonify() works in-place and thus
163 * the address in ncwd_path need not be the same as ncwd_path_nc, even
164 * though they both point into the same dynamically allocated buffer.
165 */
[095003a8]166 ncwd_path = str_dup(ncwd_path);
[34a74ab]167 free(ncwd_path_nc);
168 if (!ncwd_path) {
[a28ab12]169 fibril_mutex_unlock(&cwd_mutex);
[923c39e]170 return NULL;
171 }
[a28ab12]172 fibril_mutex_unlock(&cwd_mutex);
[5fec355]173 return ncwd_path;
174}
[2f02aa17]175
[15f3c3f]176int mount(const char *fs_name, const char *mp, const char *fqsn,
[4979403]177 const char *opts, unsigned int flags, unsigned int instance)
[2f02aa17]178{
[210e50a]179 int null_id = -1;
[15f3c3f]180 char null[LOC_NAME_MAXLEN];
[210e50a]181
[15f3c3f]182 if (str_cmp(fqsn, "") == 0) {
[210e50a]183 /* No device specified, create a fresh
184 null/%d device instead */
[15f3c3f]185 null_id = loc_null_create();
[210e50a]186
187 if (null_id == -1)
188 return ENOMEM;
189
[15f3c3f]190 snprintf(null, LOC_NAME_MAXLEN, "null/%d", null_id);
191 fqsn = null;
[210e50a]192 }
[82405266]193
[15f3c3f]194 service_id_t service_id;
195 int res = loc_service_get_id(fqsn, &service_id, flags);
[210e50a]196 if (res != EOK) {
197 if (null_id != -1)
[15f3c3f]198 loc_null_destroy(null_id);
[210e50a]199
[82405266]200 return res;
[210e50a]201 }
[82405266]202
[9eb3623]203 size_t mpa_size;
204 char *mpa = absolutize(mp, &mpa_size);
[210e50a]205 if (!mpa) {
206 if (null_id != -1)
[15f3c3f]207 loc_null_destroy(null_id);
[210e50a]208
[5fec355]209 return ENOMEM;
[210e50a]210 }
[19b28b0]211
[79ae36dd]212 async_exch_t *exch = vfs_exchange_begin();
[a28ab12]213
[96b02eb9]214 sysarg_t rc_orig;
[4979403]215 aid_t req = async_send_3(exch, VFS_IN_MOUNT, service_id, flags,
[286286c]216 instance, NULL);
[79ae36dd]217 sysarg_t rc = async_data_write_start(exch, (void *) mpa, mpa_size);
[12fc042]218 if (rc != EOK) {
[79ae36dd]219 vfs_exchange_end(exch);
[12fc042]220 free(mpa);
[a28ab12]221 async_wait_for(req, &rc_orig);
[210e50a]222
223 if (null_id != -1)
[15f3c3f]224 loc_null_destroy(null_id);
[210e50a]225
[3734106]226 if (rc_orig == EOK)
227 return (int) rc;
228 else
229 return (int) rc_orig;
[12fc042]230 }
[19b28b0]231
[79ae36dd]232 rc = async_data_write_start(exch, (void *) opts, str_size(opts));
[594303b]233 if (rc != EOK) {
[79ae36dd]234 vfs_exchange_end(exch);
[594303b]235 free(mpa);
[a28ab12]236 async_wait_for(req, &rc_orig);
[210e50a]237
238 if (null_id != -1)
[15f3c3f]239 loc_null_destroy(null_id);
[210e50a]240
[3734106]241 if (rc_orig == EOK)
242 return (int) rc;
243 else
244 return (int) rc_orig;
[594303b]245 }
[210e50a]246
[79ae36dd]247 rc = async_data_write_start(exch, (void *) fs_name, str_size(fs_name));
[2f02aa17]248 if (rc != EOK) {
[79ae36dd]249 vfs_exchange_end(exch);
[5fec355]250 free(mpa);
[a28ab12]251 async_wait_for(req, &rc_orig);
[210e50a]252
253 if (null_id != -1)
[15f3c3f]254 loc_null_destroy(null_id);
[210e50a]255
[3734106]256 if (rc_orig == EOK)
257 return (int) rc;
258 else
259 return (int) rc_orig;
[2f02aa17]260 }
[210e50a]261
[c08c355]262 /* Ask VFS whether it likes fs_name. */
[79ae36dd]263 rc = async_req_0_0(exch, VFS_IN_PING);
[c08c355]264 if (rc != EOK) {
[79ae36dd]265 vfs_exchange_end(exch);
[c08c355]266 free(mpa);
[a28ab12]267 async_wait_for(req, &rc_orig);
[210e50a]268
269 if (null_id != -1)
[15f3c3f]270 loc_null_destroy(null_id);
[210e50a]271
[3734106]272 if (rc_orig == EOK)
273 return (int) rc;
274 else
275 return (int) rc_orig;
[c08c355]276 }
[19b28b0]277
[79ae36dd]278 vfs_exchange_end(exch);
[5fec355]279 free(mpa);
[a28ab12]280 async_wait_for(req, &rc);
[19b28b0]281
[210e50a]282 if ((rc != EOK) && (null_id != -1))
[15f3c3f]283 loc_null_destroy(null_id);
[210e50a]284
[2f02aa17]285 return (int) rc;
286}
287
[21f32ee1]288int unmount(const char *mp)
289{
[96b02eb9]290 sysarg_t rc;
291 sysarg_t rc_orig;
[b9067dfa]292 aid_t req;
293 size_t mpa_size;
294 char *mpa;
295
296 mpa = absolutize(mp, &mpa_size);
297 if (!mpa)
298 return ENOMEM;
299
[79ae36dd]300 async_exch_t *exch = vfs_exchange_begin();
[b9067dfa]301
[79ae36dd]302 req = async_send_0(exch, VFS_IN_UNMOUNT, NULL);
303 rc = async_data_write_start(exch, (void *) mpa, mpa_size);
[b9067dfa]304 if (rc != EOK) {
[79ae36dd]305 vfs_exchange_end(exch);
[b9067dfa]306 free(mpa);
[a28ab12]307 async_wait_for(req, &rc_orig);
[b9067dfa]308 if (rc_orig == EOK)
309 return (int) rc;
310 else
311 return (int) rc_orig;
312 }
313
314
[79ae36dd]315 vfs_exchange_end(exch);
[b9067dfa]316 free(mpa);
[a28ab12]317 async_wait_for(req, &rc);
[b9067dfa]318
319 return (int) rc;
[21f32ee1]320}
321
[3ef62df]322static int walk_flags(int oflags)
323{
324 int flags = 0;
325 if (oflags & O_CREAT) {
326 if (oflags & O_EXCL) {
327 flags |= WALK_MUST_CREATE;
328 } else {
329 flags |= WALK_MAY_CREATE;
330 }
331 }
332 return flags;
333}
334
[2b88074b]335static int open_internal(const char *abs, size_t abs_size, int lflag, int oflag)
[2f02aa17]336{
[9a8c188]337 // FIXME: Some applications call this incorrectly.
338 if ((oflag & (O_RDONLY|O_WRONLY|O_RDWR)) == 0) {
339 oflag |= O_RDWR;
340 }
341
342 assert((((oflag & O_RDONLY) != 0) + ((oflag & O_WRONLY) != 0) + ((oflag & O_RDWR) != 0)) == 1);
343
[79ae36dd]344 async_exch_t *exch = vfs_exchange_begin();
[19b28b0]345
[2b88074b]346 ipc_call_t answer;
[79ae36dd]347 aid_t req = async_send_3(exch, VFS_IN_OPEN, lflag, oflag, 0, &answer);
348 sysarg_t rc = async_data_write_start(exch, abs, abs_size);
[2b88074b]349
[2f02aa17]350 if (rc != EOK) {
[79ae36dd]351 vfs_exchange_end(exch);
[a28ab12]352
[96b02eb9]353 sysarg_t rc_orig;
[3734106]354 async_wait_for(req, &rc_orig);
[2b88074b]355
[3734106]356 if (rc_orig == EOK)
357 return (int) rc;
358 else
359 return (int) rc_orig;
[2f02aa17]360 }
[2b88074b]361
[79ae36dd]362 vfs_exchange_end(exch);
[2f02aa17]363 async_wait_for(req, &rc);
[2595dab]364
[57b4f46]365 if (rc != EOK)
366 return (int) rc;
[2595dab]367
[2f02aa17]368 return (int) IPC_GET_ARG1(answer);
369}
370
[ae78b530]371int open(const char *path, int oflag, ...)
372{
[3ef62df]373 // FIXME: Some applications call this incorrectly.
374 if ((oflag & (O_RDONLY|O_WRONLY|O_RDWR)) == 0) {
375 oflag |= O_RDWR;
376 }
377
378 assert((((oflag & O_RDONLY) != 0) + ((oflag & O_WRONLY) != 0) + ((oflag & O_RDWR) != 0)) == 1);
379
[2b88074b]380 size_t abs_size;
381 char *abs = absolutize(path, &abs_size);
[3ef62df]382 if (!abs) {
[2b88074b]383 return ENOMEM;
[3ef62df]384 }
385
386 int ret = _vfs_walk(-1, abs, walk_flags(oflag) | WALK_REGULAR);
387 if (ret < 0) {
388 return ret;
389 }
[2b88074b]390
[3ef62df]391 int mode =
392 ((oflag & O_RDWR) ? MODE_READ|MODE_WRITE : 0) |
393 ((oflag & O_RDONLY) ? MODE_READ : 0) |
394 ((oflag & O_WRONLY) ? MODE_WRITE : 0) |
395 ((oflag & O_APPEND) ? MODE_APPEND : 0);
396
397 int rc = _vfs_open(ret, mode);
398 if (rc < 0) {
399 // _vfs_put(ret);
400 close(ret);
401 return rc;
402 }
[2b88074b]403
[3ef62df]404 if (oflag & O_TRUNC) {
405 assert(oflag & O_WRONLY || oflag & O_RDWR);
406 assert(!(oflag & O_APPEND));
407
408 // _vfs_resize
409 (void) ftruncate(ret, 0);
410 }
411
[2b88074b]412 return ret;
[ae78b530]413}
414
[72bde81]415int close(int fildes)
416{
[96b02eb9]417 sysarg_t rc;
[19b28b0]418
[79ae36dd]419 async_exch_t *exch = vfs_exchange_begin();
420 rc = async_req_1_0(exch, VFS_IN_CLOSE, fildes);
421 vfs_exchange_end(exch);
[19b28b0]422
[79ae36dd]423 return (int) rc;
[72bde81]424}
425
[2f02aa17]426ssize_t read(int fildes, void *buf, size_t nbyte)
427{
[96b02eb9]428 sysarg_t rc;
[2f02aa17]429 ipc_call_t answer;
430 aid_t req;
[19b28b0]431
[79ae36dd]432 async_exch_t *exch = vfs_exchange_begin();
433
434 req = async_send_1(exch, VFS_IN_READ, fildes, &answer);
435 rc = async_data_read_start(exch, (void *)buf, nbyte);
[07e01e6]436 if (rc != EOK) {
[79ae36dd]437 vfs_exchange_end(exch);
[a28ab12]438
[96b02eb9]439 sysarg_t rc_orig;
[3734106]440 async_wait_for(req, &rc_orig);
[a28ab12]441
[3734106]442 if (rc_orig == EOK)
443 return (ssize_t) rc;
444 else
445 return (ssize_t) rc_orig;
[2f02aa17]446 }
[79ae36dd]447 vfs_exchange_end(exch);
[2f02aa17]448 async_wait_for(req, &rc);
[f7017572]449 if (rc == EOK)
450 return (ssize_t) IPC_GET_ARG1(answer);
451 else
[25becee8]452 return rc;
[2f02aa17]453}
454
[449c246]455ssize_t write(int fildes, const void *buf, size_t nbyte)
456{
[96b02eb9]457 sysarg_t rc;
[449c246]458 ipc_call_t answer;
459 aid_t req;
[19b28b0]460
[79ae36dd]461 async_exch_t *exch = vfs_exchange_begin();
462
463 req = async_send_1(exch, VFS_IN_WRITE, fildes, &answer);
464 rc = async_data_write_start(exch, (void *)buf, nbyte);
[07e01e6]465 if (rc != EOK) {
[79ae36dd]466 vfs_exchange_end(exch);
[a28ab12]467
[96b02eb9]468 sysarg_t rc_orig;
[3734106]469 async_wait_for(req, &rc_orig);
[a28ab12]470
[3734106]471 if (rc_orig == EOK)
472 return (ssize_t) rc;
473 else
474 return (ssize_t) rc_orig;
[449c246]475 }
[79ae36dd]476 vfs_exchange_end(exch);
[449c246]477 async_wait_for(req, &rc);
[f7017572]478 if (rc == EOK)
479 return (ssize_t) IPC_GET_ARG1(answer);
480 else
481 return -1;
[449c246]482}
[222e57c]483
[8fd04ba9]484/** Read entire buffer.
485 *
486 * In face of short reads this function continues reading until either
487 * the entire buffer is read or no more data is available (at end of file).
488 *
489 * @param fildes File descriptor
490 * @param buf Buffer, @a nbytes bytes long
491 * @param nbytes Number of bytes to read
492 *
493 * @return On success, positive number of bytes read.
494 * On failure, negative error code from read().
495 */
496ssize_t read_all(int fildes, void *buf, size_t nbyte)
497{
498 ssize_t cnt = 0;
499 size_t nread = 0;
500 uint8_t *bp = (uint8_t *) buf;
501
502 do {
503 bp += cnt;
504 nread += cnt;
505 cnt = read(fildes, bp, nbyte - nread);
506 } while (cnt > 0 && (nbyte - nread - cnt) > 0);
507
508 if (cnt < 0)
509 return cnt;
510
511 return nread + cnt;
512}
513
514/** Write entire buffer.
515 *
516 * This function fails if it cannot write exactly @a len bytes to the file.
517 *
518 * @param fildes File descriptor
519 * @param buf Data, @a nbytes bytes long
520 * @param nbytes Number of bytes to write
521 *
522 * @return EOK on error, return value from write() if writing
523 * failed.
524 */
525ssize_t write_all(int fildes, const void *buf, size_t nbyte)
526{
527 ssize_t cnt = 0;
528 ssize_t nwritten = 0;
529 const uint8_t *bp = (uint8_t *) buf;
530
531 do {
532 bp += cnt;
533 nwritten += cnt;
534 cnt = write(fildes, bp, nbyte - nwritten);
535 } while (cnt > 0 && ((ssize_t )nbyte - nwritten - cnt) > 0);
536
537 if (cnt < 0)
538 return cnt;
539
540 if ((ssize_t)nbyte - nwritten - cnt > 0)
541 return EIO;
542
543 return nbyte;
544}
545
[2595dab]546int fsync(int fildes)
547{
[79ae36dd]548 async_exch_t *exch = vfs_exchange_begin();
549 sysarg_t rc = async_req_1_0(exch, VFS_IN_SYNC, fildes);
550 vfs_exchange_end(exch);
[2595dab]551
552 return (int) rc;
553}
554
[ed903174]555off64_t lseek(int fildes, off64_t offset, int whence)
[222e57c]556{
[79ae36dd]557 async_exch_t *exch = vfs_exchange_begin();
[19b28b0]558
[96b02eb9]559 sysarg_t newoff_lo;
560 sysarg_t newoff_hi;
[79ae36dd]561 sysarg_t rc = async_req_4_2(exch, VFS_IN_SEEK, fildes,
[ed903174]562 LOWER32(offset), UPPER32(offset), whence,
563 &newoff_lo, &newoff_hi);
564
[79ae36dd]565 vfs_exchange_end(exch);
[ed903174]566
[222e57c]567 if (rc != EOK)
[ed903174]568 return (off64_t) -1;
[222e57c]569
[ed903174]570 return (off64_t) MERGE_LOUP32(newoff_lo, newoff_hi);
[222e57c]571}
572
[ed903174]573int ftruncate(int fildes, aoff64_t length)
[0ee4322]574{
[96b02eb9]575 sysarg_t rc;
[0ee4322]576
[79ae36dd]577 async_exch_t *exch = vfs_exchange_begin();
578 rc = async_req_3_0(exch, VFS_IN_TRUNCATE, fildes,
[ed903174]579 LOWER32(length), UPPER32(length));
[79ae36dd]580 vfs_exchange_end(exch);
[ed903174]581
[0ee4322]582 return (int) rc;
583}
584
[852b801]585int fstat(int fildes, struct stat *stat)
586{
[96b02eb9]587 sysarg_t rc;
[852b801]588 aid_t req;
589
[79ae36dd]590 async_exch_t *exch = vfs_exchange_begin();
591
592 req = async_send_1(exch, VFS_IN_FSTAT, fildes, NULL);
593 rc = async_data_read_start(exch, (void *) stat, sizeof(struct stat));
[852b801]594 if (rc != EOK) {
[79ae36dd]595 vfs_exchange_end(exch);
[a28ab12]596
[96b02eb9]597 sysarg_t rc_orig;
[3734106]598 async_wait_for(req, &rc_orig);
[a28ab12]599
[3734106]600 if (rc_orig == EOK)
601 return (ssize_t) rc;
602 else
603 return (ssize_t) rc_orig;
[852b801]604 }
[79ae36dd]605 vfs_exchange_end(exch);
[852b801]606 async_wait_for(req, &rc);
607
608 return rc;
609}
610
[415c7e0d]611int stat(const char *path, struct stat *stat)
612{
[96b02eb9]613 sysarg_t rc;
614 sysarg_t rc_orig;
[415c7e0d]615 aid_t req;
616
617 size_t pa_size;
618 char *pa = absolutize(path, &pa_size);
619 if (!pa)
620 return ENOMEM;
621
[79ae36dd]622 async_exch_t *exch = vfs_exchange_begin();
[415c7e0d]623
[79ae36dd]624 req = async_send_0(exch, VFS_IN_STAT, NULL);
625 rc = async_data_write_start(exch, pa, pa_size);
[415c7e0d]626 if (rc != EOK) {
[79ae36dd]627 vfs_exchange_end(exch);
[415c7e0d]628 free(pa);
[a28ab12]629 async_wait_for(req, &rc_orig);
[3734106]630 if (rc_orig == EOK)
631 return (int) rc;
632 else
633 return (int) rc_orig;
[415c7e0d]634 }
[79ae36dd]635 rc = async_data_read_start(exch, stat, sizeof(struct stat));
[415c7e0d]636 if (rc != EOK) {
[79ae36dd]637 vfs_exchange_end(exch);
[415c7e0d]638 free(pa);
[a28ab12]639 async_wait_for(req, &rc_orig);
[3734106]640 if (rc_orig == EOK)
641 return (int) rc;
642 else
643 return (int) rc_orig;
[415c7e0d]644 }
[79ae36dd]645 vfs_exchange_end(exch);
[415c7e0d]646 free(pa);
[a28ab12]647 async_wait_for(req, &rc);
[415c7e0d]648 return rc;
649}
650
[d0dc74ae]651DIR *opendir(const char *dirname)
652{
653 DIR *dirp = malloc(sizeof(DIR));
654 if (!dirp)
655 return NULL;
[2b88074b]656
657 size_t abs_size;
658 char *abs = absolutize(dirname, &abs_size);
659 if (!abs) {
660 free(dirp);
[ed903174]661 return NULL;
[2b88074b]662 }
663
664 int ret = open_internal(abs, abs_size, L_DIRECTORY, 0);
665 free(abs);
666
667 if (ret < 0) {
[d0dc74ae]668 free(dirp);
669 return NULL;
670 }
[2b88074b]671
672 dirp->fd = ret;
[d0dc74ae]673 return dirp;
674}
675
676struct dirent *readdir(DIR *dirp)
677{
[5973fd0]678 ssize_t len = read(dirp->fd, &dirp->res.d_name[0], NAME_MAX + 1);
679 if (len <= 0)
680 return NULL;
681 return &dirp->res;
[d0dc74ae]682}
683
684void rewinddir(DIR *dirp)
685{
[5973fd0]686 (void) lseek(dirp->fd, 0, SEEK_SET);
[d0dc74ae]687}
688
689int closedir(DIR *dirp)
690{
691 (void) close(dirp->fd);
692 free(dirp);
693 return 0;
694}
695
[72bde81]696int mkdir(const char *path, mode_t mode)
[d0dc74ae]697{
[96b02eb9]698 sysarg_t rc;
[72bde81]699 aid_t req;
700
[9eb3623]701 size_t pa_size;
702 char *pa = absolutize(path, &pa_size);
[5fec355]703 if (!pa)
704 return ENOMEM;
[19b28b0]705
[79ae36dd]706 async_exch_t *exch = vfs_exchange_begin();
[19b28b0]707
[79ae36dd]708 req = async_send_1(exch, VFS_IN_MKDIR, mode, NULL);
709 rc = async_data_write_start(exch, pa, pa_size);
[72bde81]710 if (rc != EOK) {
[79ae36dd]711 vfs_exchange_end(exch);
[a28ab12]712 free(pa);
713
[96b02eb9]714 sysarg_t rc_orig;
[3734106]715 async_wait_for(req, &rc_orig);
[a28ab12]716
[3734106]717 if (rc_orig == EOK)
718 return (int) rc;
719 else
720 return (int) rc_orig;
[72bde81]721 }
[79ae36dd]722 vfs_exchange_end(exch);
[5fec355]723 free(pa);
[a28ab12]724 async_wait_for(req, &rc);
[2595dab]725 return rc;
[d0dc74ae]726}
727
[f15cf1a6]728static int _unlink(const char *path, int lflag)
729{
[96b02eb9]730 sysarg_t rc;
[f15cf1a6]731 aid_t req;
732
[9eb3623]733 size_t pa_size;
734 char *pa = absolutize(path, &pa_size);
[5fec355]735 if (!pa)
736 return ENOMEM;
[19b28b0]737
[79ae36dd]738 async_exch_t *exch = vfs_exchange_begin();
739
[9ea7d90]740 req = async_send_1(exch, VFS_IN_UNLINK, lflag, NULL);
[79ae36dd]741 rc = async_data_write_start(exch, pa, pa_size);
[f15cf1a6]742 if (rc != EOK) {
[79ae36dd]743 vfs_exchange_end(exch);
[a28ab12]744 free(pa);
[3734106]745
[a28ab12]746 sysarg_t rc_orig;
[3734106]747 async_wait_for(req, &rc_orig);
[a28ab12]748
[3734106]749 if (rc_orig == EOK)
750 return (int) rc;
751 else
752 return (int) rc_orig;
[f15cf1a6]753 }
[79ae36dd]754 vfs_exchange_end(exch);
[5fec355]755 free(pa);
[a28ab12]756 async_wait_for(req, &rc);
[2595dab]757 return rc;
[f15cf1a6]758}
759
760int unlink(const char *path)
761{
762 return _unlink(path, L_NONE);
763}
764
765int rmdir(const char *path)
766{
767 return _unlink(path, L_DIRECTORY);
768}
769
[a8e9ab8d]770int rename(const char *old, const char *new)
771{
[96b02eb9]772 sysarg_t rc;
773 sysarg_t rc_orig;
[a8e9ab8d]774 aid_t req;
775
[9eb3623]776 size_t olda_size;
777 char *olda = absolutize(old, &olda_size);
[a8e9ab8d]778 if (!olda)
779 return ENOMEM;
[923c39e]780
[9eb3623]781 size_t newa_size;
782 char *newa = absolutize(new, &newa_size);
[a8e9ab8d]783 if (!newa) {
784 free(olda);
785 return ENOMEM;
786 }
[19b28b0]787
[79ae36dd]788 async_exch_t *exch = vfs_exchange_begin();
789
790 req = async_send_0(exch, VFS_IN_RENAME, NULL);
791 rc = async_data_write_start(exch, olda, olda_size);
[a8e9ab8d]792 if (rc != EOK) {
[79ae36dd]793 vfs_exchange_end(exch);
[a8e9ab8d]794 free(olda);
795 free(newa);
[a28ab12]796 async_wait_for(req, &rc_orig);
[3734106]797 if (rc_orig == EOK)
798 return (int) rc;
799 else
800 return (int) rc_orig;
[a8e9ab8d]801 }
[79ae36dd]802 rc = async_data_write_start(exch, newa, newa_size);
[a8e9ab8d]803 if (rc != EOK) {
[79ae36dd]804 vfs_exchange_end(exch);
[a8e9ab8d]805 free(olda);
806 free(newa);
[a28ab12]807 async_wait_for(req, &rc_orig);
[3734106]808 if (rc_orig == EOK)
809 return (int) rc;
810 else
811 return (int) rc_orig;
[a8e9ab8d]812 }
[79ae36dd]813 vfs_exchange_end(exch);
[a8e9ab8d]814 free(olda);
815 free(newa);
[a28ab12]816 async_wait_for(req, &rc);
[a8e9ab8d]817 return rc;
818}
819
[5fec355]820int chdir(const char *path)
821{
[2b88074b]822 size_t abs_size;
823 char *abs = absolutize(path, &abs_size);
824 if (!abs)
[5fec355]825 return ENOMEM;
[2b88074b]826
827 int fd = open_internal(abs, abs_size, L_DIRECTORY, O_DESC);
828
829 if (fd < 0) {
830 free(abs);
[5fec355]831 return ENOENT;
832 }
[2b88074b]833
[a28ab12]834 fibril_mutex_lock(&cwd_mutex);
[2b88074b]835
836 if (cwd_fd >= 0)
837 close(cwd_fd);
838
839
840 if (cwd_path)
841 free(cwd_path);
842
843 cwd_fd = fd;
844 cwd_path = abs;
845 cwd_size = abs_size;
846
[a28ab12]847 fibril_mutex_unlock(&cwd_mutex);
[0dd0f71f]848 return EOK;
[5fec355]849}
850
851char *getcwd(char *buf, size_t size)
852{
[2b88074b]853 if (size == 0)
[5fec355]854 return NULL;
[2b88074b]855
[a28ab12]856 fibril_mutex_lock(&cwd_mutex);
[2b88074b]857
858 if ((cwd_size == 0) || (size < cwd_size + 1)) {
[a28ab12]859 fibril_mutex_unlock(&cwd_mutex);
[5fec355]860 return NULL;
861 }
[2b88074b]862
[6eb2e96]863 str_cpy(buf, size, cwd_path);
[a28ab12]864 fibril_mutex_unlock(&cwd_mutex);
[2b88074b]865
[5fec355]866 return buf;
867}
868
[79ae36dd]869async_sess_t *fd_session(exch_mgmt_t mgmt, int fildes)
[852b801]870{
871 struct stat stat;
[8caaea7]872 int rc = fstat(fildes, &stat);
[79ae36dd]873 if (rc != 0) {
874 errno = rc;
875 return NULL;
876 }
[8caaea7]877
[15f3c3f]878 if (!stat.service) {
[79ae36dd]879 errno = ENOENT;
880 return NULL;
881 }
[852b801]882
[15f3c3f]883 return loc_service_connect(mgmt, stat.service, 0);
[852b801]884}
885
[2b88074b]886int dup2(int oldfd, int newfd)
[852b801]887{
[79ae36dd]888 async_exch_t *exch = vfs_exchange_begin();
[852b801]889
[96b02eb9]890 sysarg_t ret;
[79ae36dd]891 sysarg_t rc = async_req_2_1(exch, VFS_IN_DUP, oldfd, newfd, &ret);
[852b801]892
[79ae36dd]893 vfs_exchange_end(exch);
[2b88074b]894
895 if (rc == EOK)
896 return (int) ret;
897
898 return (int) rc;
[852b801]899}
900
[27b76ca]901int fd_wait(void)
[2b88074b]902{
[79ae36dd]903 async_exch_t *exch = vfs_exchange_begin();
[2b88074b]904
[96b02eb9]905 sysarg_t ret;
[27b76ca]906 sysarg_t rc = async_req_0_1(exch, VFS_IN_WAIT_HANDLE, &ret);
[2b88074b]907
[79ae36dd]908 vfs_exchange_end(exch);
[2b88074b]909
910 if (rc == EOK)
911 return (int) ret;
912
913 return (int) rc;
914}
915
[10e4cd7]916int get_mtab_list(list_t *mtab_list)
917{
918 sysarg_t rc;
[4965357f]919 aid_t req;
[10e4cd7]920 size_t i;
[4965357f]921 sysarg_t num_mounted_fs;
[10e4cd7]922
923 async_exch_t *exch = vfs_exchange_begin();
924
[41e9ef7]925 req = async_send_0(exch, VFS_IN_MTAB_GET, NULL);
[10e4cd7]926
927 /* Ask VFS how many filesystems are mounted */
928 rc = async_req_0_1(exch, VFS_IN_PING, &num_mounted_fs);
929 if (rc != EOK)
930 goto exit;
931
932 for (i = 0; i < num_mounted_fs; ++i) {
933 mtab_ent_t *mtab_ent;
934
[8d6a41c]935 mtab_ent = malloc(sizeof(mtab_ent_t));
936 if (!mtab_ent) {
[10e4cd7]937 rc = ENOMEM;
938 goto exit;
939 }
940
[8d6a41c]941 memset(mtab_ent, 0, sizeof(mtab_ent_t));
[10e4cd7]942
[4965357f]943 rc = async_data_read_start(exch, (void *) mtab_ent->mp,
[10e4cd7]944 MAX_PATH_LEN);
945 if (rc != EOK)
946 goto exit;
947
[4965357f]948 rc = async_data_read_start(exch, (void *) mtab_ent->opts,
[10e4cd7]949 MAX_MNTOPTS_LEN);
950 if (rc != EOK)
951 goto exit;
952
[4965357f]953 rc = async_data_read_start(exch, (void *) mtab_ent->fs_name,
[10e4cd7]954 FS_NAME_MAXLEN);
955 if (rc != EOK)
956 goto exit;
957
[6b8e5b74]958 sysarg_t p[2];
[10e4cd7]959
[6b8e5b74]960 rc = async_req_0_2(exch, VFS_IN_PING, &p[0], &p[1]);
[f8838b8]961 if (rc != EOK)
962 goto exit;
[10e4cd7]963
[6b8e5b74]964 mtab_ent->instance = p[0];
965 mtab_ent->service_id = p[1];
[10e4cd7]966
[8d6a41c]967 link_initialize(&mtab_ent->link);
968 list_append(&mtab_ent->link, mtab_list);
[10e4cd7]969 }
970
971exit:
[4965357f]972 async_wait_for(req, &rc);
[10e4cd7]973 vfs_exchange_end(exch);
974 return rc;
975}
976
[2f02aa17]977/** @}
978 */
Note: See TracBrowser for help on using the repository browser.