~vojtech-horky/helenos/helenos-qemu

« back to all changes in this revision

Viewing changes to uspace/lib/libc/generic/vfs/vfs.c

  • Committer: Martin Decky
  • Date: 2009-08-04 11:19:19 UTC
  • Revision ID: martin@uranus.dsrg.hide.ms.mff.cuni.cz-20090804111919-evyclddlr3v5lhmp
Initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 <stdio.h>
 
42
#include <sys/stat.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 <devmap.h>
 
52
#include <ipc/vfs.h>
 
53
#include <ipc/devmap.h>
 
54
 
 
55
static int vfs_phone = -1;
 
56
static futex_t vfs_phone_futex = FUTEX_INITIALIZER;
 
57
static futex_t cwd_futex = FUTEX_INITIALIZER;
 
58
 
 
59
DIR *cwd_dir = NULL;
 
60
char *cwd_path = NULL;
 
61
size_t cwd_size = 0;
 
62
 
 
63
char *absolutize(const char *path, size_t *retlen)
 
64
{
 
65
        char *ncwd_path;
 
66
        char *ncwd_path_nc;
 
67
 
 
68
        futex_down(&cwd_futex);
 
69
        size_t size = str_size(path);
 
70
        if (*path != '/') {
 
71
                if (!cwd_path) {
 
72
                        futex_up(&cwd_futex);
 
73
                        return NULL;
 
74
                }
 
75
                ncwd_path_nc = malloc(cwd_size + 1 + size + 1);
 
76
                if (!ncwd_path_nc) {
 
77
                        futex_up(&cwd_futex);
 
78
                        return NULL;
 
79
                }
 
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';
 
83
        } else {
 
84
                ncwd_path_nc = malloc(size + 1);
 
85
                if (!ncwd_path_nc) {
 
86
                        futex_up(&cwd_futex);
 
87
                        return NULL;
 
88
                }
 
89
                ncwd_path_nc[0] = '\0';
 
90
        }
 
91
        str_append(ncwd_path_nc, cwd_size + 1 + size + 1, path);
 
92
        ncwd_path = canonify(ncwd_path_nc, retlen);
 
93
        if (!ncwd_path) {
 
94
                futex_up(&cwd_futex);
 
95
                free(ncwd_path_nc);
 
96
                return NULL;
 
97
        }
 
98
        /*
 
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.
 
102
         */
 
103
        ncwd_path = str_dup(ncwd_path);
 
104
        free(ncwd_path_nc);
 
105
        if (!ncwd_path) {
 
106
                futex_up(&cwd_futex);
 
107
                return NULL;
 
108
        }
 
109
        futex_up(&cwd_futex);
 
110
        return ncwd_path;
 
111
}
 
112
 
 
113
static void vfs_connect(void)
 
114
{
 
115
        while (vfs_phone < 0)
 
116
                vfs_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VFS, 0, 0);
 
117
}
 
118
 
 
119
int mount(const char *fs_name, const char *mp, const char *dev,
 
120
    const char *opts, unsigned int flags)
 
121
{
 
122
        int res;
 
123
        ipcarg_t rc;
 
124
        aid_t req;
 
125
        dev_handle_t dev_handle;
 
126
        
 
127
        res = devmap_device_get_handle(dev, &dev_handle, flags);
 
128
        if (res != EOK)
 
129
                return res;
 
130
        
 
131
        size_t mpa_size;
 
132
        char *mpa = absolutize(mp, &mpa_size);
 
133
        if (!mpa)
 
134
                return ENOMEM;
 
135
        
 
136
        futex_down(&vfs_phone_futex);
 
137
        async_serialize_start();
 
138
        vfs_connect();
 
139
        
 
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);
 
142
        if (rc != EOK) {
 
143
                async_wait_for(req, NULL);
 
144
                async_serialize_end();
 
145
                futex_up(&vfs_phone_futex);
 
146
                free(mpa);
 
147
                return (int) rc;
 
148
        }
 
149
        
 
150
        rc = ipc_data_write_start(vfs_phone, (void *) opts, str_size(opts));
 
151
        if (rc != EOK) {
 
152
                async_wait_for(req, NULL);
 
153
                async_serialize_end();
 
154
                futex_up(&vfs_phone_futex);
 
155
                free(mpa);
 
156
                return (int) rc;
 
157
        }
 
158
 
 
159
        rc = ipc_data_write_start(vfs_phone, (void *) fs_name, str_size(fs_name));
 
160
        if (rc != EOK) {
 
161
                async_wait_for(req, NULL);
 
162
                async_serialize_end();
 
163
                futex_up(&vfs_phone_futex);
 
164
                free(mpa);
 
165
                return (int) rc;
 
166
        }
 
167
 
 
168
        /* Ask VFS whether it likes fs_name. */
 
169
        rc = async_req_0_0(vfs_phone, IPC_M_PING);
 
170
        if (rc != EOK) {
 
171
                async_wait_for(req, NULL);
 
172
                async_serialize_end();
 
173
                futex_up(&vfs_phone_futex);
 
174
                free(mpa);
 
175
                return (int) rc;
 
176
        }
 
177
        
 
178
        async_wait_for(req, &rc);
 
179
        async_serialize_end();
 
180
        futex_up(&vfs_phone_futex);
 
181
        free(mpa);
 
182
        
 
183
        return (int) rc;
 
184
}
 
185
 
 
186
static int _open(const char *path, int lflag, int oflag, ...)
 
187
{
 
188
        ipcarg_t rc;
 
189
        ipc_call_t answer;
 
190
        aid_t req;
 
191
        
 
192
        size_t pa_size;
 
193
        char *pa = absolutize(path, &pa_size);
 
194
        if (!pa)
 
195
                return ENOMEM;
 
196
        
 
197
        futex_down(&vfs_phone_futex);
 
198
        async_serialize_start();
 
199
        vfs_connect();
 
200
        
 
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);
 
203
        if (rc != EOK) {
 
204
                async_wait_for(req, NULL);
 
205
                async_serialize_end();
 
206
                futex_up(&vfs_phone_futex);
 
207
                free(pa);
 
208
                return (int) rc;
 
209
        }
 
210
        async_wait_for(req, &rc);
 
211
        async_serialize_end();
 
212
        futex_up(&vfs_phone_futex);
 
213
        free(pa);
 
214
        
 
215
        if (rc != EOK)
 
216
            return (int) rc;
 
217
        
 
218
        return (int) IPC_GET_ARG1(answer);
 
219
}
 
220
 
 
221
int open(const char *path, int oflag, ...)
 
222
{
 
223
        return _open(path, L_FILE, oflag);
 
224
}
 
225
 
 
226
int open_node(fdi_node_t *node, int oflag)
 
227
{
 
228
        futex_down(&vfs_phone_futex);
 
229
        async_serialize_start();
 
230
        vfs_connect();
 
231
        
 
232
        ipc_call_t answer;
 
233
        aid_t req = async_send_4(vfs_phone, VFS_IN_OPEN_NODE, node->fs_handle,
 
234
            node->dev_handle, node->index, oflag, &answer);
 
235
        
 
236
        ipcarg_t rc;
 
237
        async_wait_for(req, &rc);
 
238
        async_serialize_end();
 
239
        futex_up(&vfs_phone_futex);
 
240
        
 
241
        if (rc != EOK)
 
242
            return (int) rc;
 
243
        
 
244
        return (int) IPC_GET_ARG1(answer);
 
245
}
 
246
 
 
247
int close(int fildes)
 
248
{
 
249
        ipcarg_t rc;
 
250
        
 
251
        futex_down(&vfs_phone_futex);
 
252
        async_serialize_start();
 
253
        vfs_connect();
 
254
        
 
255
        rc = async_req_1_0(vfs_phone, VFS_IN_CLOSE, fildes);
 
256
        
 
257
        async_serialize_end();
 
258
        futex_up(&vfs_phone_futex);
 
259
        
 
260
        return (int)rc;
 
261
}
 
262
 
 
263
ssize_t read(int fildes, void *buf, size_t nbyte) 
 
264
{
 
265
        ipcarg_t rc;
 
266
        ipc_call_t answer;
 
267
        aid_t req;
 
268
 
 
269
        futex_down(&vfs_phone_futex);
 
270
        async_serialize_start();
 
271
        vfs_connect();
 
272
        
 
273
        req = async_send_1(vfs_phone, VFS_IN_READ, fildes, &answer);
 
274
        rc = ipc_data_read_start(vfs_phone, (void *)buf, nbyte);
 
275
        if (rc != EOK) {
 
276
                async_wait_for(req, NULL);
 
277
                async_serialize_end();
 
278
                futex_up(&vfs_phone_futex);
 
279
                return (ssize_t) rc;
 
280
        }
 
281
        async_wait_for(req, &rc);
 
282
        async_serialize_end();
 
283
        futex_up(&vfs_phone_futex);
 
284
        if (rc == EOK)
 
285
                return (ssize_t) IPC_GET_ARG1(answer);
 
286
        else
 
287
                return rc;
 
288
}
 
289
 
 
290
ssize_t write(int fildes, const void *buf, size_t nbyte) 
 
291
{
 
292
        ipcarg_t rc;
 
293
        ipc_call_t answer;
 
294
        aid_t req;
 
295
 
 
296
        futex_down(&vfs_phone_futex);
 
297
        async_serialize_start();
 
298
        vfs_connect();
 
299
        
 
300
        req = async_send_1(vfs_phone, VFS_IN_WRITE, fildes, &answer);
 
301
        rc = ipc_data_write_start(vfs_phone, (void *)buf, nbyte);
 
302
        if (rc != EOK) {
 
303
                async_wait_for(req, NULL);
 
304
                async_serialize_end();
 
305
                futex_up(&vfs_phone_futex);
 
306
                return (ssize_t) rc;
 
307
        }
 
308
        async_wait_for(req, &rc);
 
309
        async_serialize_end();
 
310
        futex_up(&vfs_phone_futex);
 
311
        if (rc == EOK)
 
312
                return (ssize_t) IPC_GET_ARG1(answer);
 
313
        else
 
314
                return -1;
 
315
}
 
316
 
 
317
int fsync(int fildes)
 
318
{
 
319
        futex_down(&vfs_phone_futex);
 
320
        async_serialize_start();
 
321
        vfs_connect();
 
322
        
 
323
        ipcarg_t rc = async_req_1_0(vfs_phone, VFS_IN_SYNC, fildes);
 
324
        
 
325
        async_serialize_end();
 
326
        futex_up(&vfs_phone_futex);
 
327
        
 
328
        return (int) rc;
 
329
}
 
330
 
 
331
off_t lseek(int fildes, off_t offset, int whence)
 
332
{
 
333
        ipcarg_t rc;
 
334
 
 
335
        futex_down(&vfs_phone_futex);
 
336
        async_serialize_start();
 
337
        vfs_connect();
 
338
        
 
339
        ipcarg_t newoffs;
 
340
        rc = async_req_3_1(vfs_phone, VFS_IN_SEEK, fildes, offset, whence,
 
341
            &newoffs);
 
342
 
 
343
        async_serialize_end();
 
344
        futex_up(&vfs_phone_futex);
 
345
 
 
346
        if (rc != EOK)
 
347
                return (off_t) -1;
 
348
        
 
349
        return (off_t) newoffs;
 
350
}
 
351
 
 
352
int ftruncate(int fildes, off_t length)
 
353
{
 
354
        ipcarg_t rc;
 
355
        
 
356
        futex_down(&vfs_phone_futex);
 
357
        async_serialize_start();
 
358
        vfs_connect();
 
359
        
 
360
        rc = async_req_2_0(vfs_phone, VFS_IN_TRUNCATE, fildes, length);
 
361
        async_serialize_end();
 
362
        futex_up(&vfs_phone_futex);
 
363
        return (int) rc;
 
364
}
 
365
 
 
366
int fstat(int fildes, struct stat *stat)
 
367
{
 
368
        ipcarg_t rc;
 
369
        aid_t req;
 
370
 
 
371
        futex_down(&vfs_phone_futex);
 
372
        async_serialize_start();
 
373
        vfs_connect();
 
374
        
 
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));
 
377
        if (rc != EOK) {
 
378
                async_wait_for(req, NULL);
 
379
                async_serialize_end();
 
380
                futex_up(&vfs_phone_futex);
 
381
                return (ssize_t) rc;
 
382
        }
 
383
        async_wait_for(req, &rc);
 
384
        async_serialize_end();
 
385
        futex_up(&vfs_phone_futex);
 
386
 
 
387
        return rc;
 
388
}
 
389
 
 
390
int stat(const char *path, struct stat *stat)
 
391
{
 
392
        ipcarg_t rc;
 
393
        aid_t req;
 
394
        
 
395
        size_t pa_size;
 
396
        char *pa = absolutize(path, &pa_size);
 
397
        if (!pa)
 
398
                return ENOMEM;
 
399
        
 
400
        futex_down(&vfs_phone_futex);
 
401
        async_serialize_start();
 
402
        vfs_connect();
 
403
        
 
404
        req = async_send_0(vfs_phone, VFS_IN_STAT, NULL);
 
405
        rc = ipc_data_write_start(vfs_phone, pa, pa_size);
 
406
        if (rc != EOK) {
 
407
                async_wait_for(req, NULL);
 
408
                async_serialize_end();
 
409
                futex_up(&vfs_phone_futex);
 
410
                free(pa);
 
411
                return (int) rc;
 
412
        }
 
413
        rc = ipc_data_read_start(vfs_phone, stat, sizeof(struct stat));
 
414
        if (rc != EOK) {
 
415
                async_wait_for(req, NULL);
 
416
                async_serialize_end();
 
417
                futex_up(&vfs_phone_futex);
 
418
                free(pa);
 
419
                return (int) rc;
 
420
        }
 
421
        async_wait_for(req, &rc);
 
422
        async_serialize_end();
 
423
        futex_up(&vfs_phone_futex);
 
424
        free(pa);
 
425
        return rc;
 
426
}
 
427
 
 
428
DIR *opendir(const char *dirname)
 
429
{
 
430
        DIR *dirp = malloc(sizeof(DIR));
 
431
        if (!dirp)
 
432
                return NULL;
 
433
        dirp->fd = _open(dirname, L_DIRECTORY, 0);
 
434
        if (dirp->fd < 0) {
 
435
                free(dirp);
 
436
                return NULL;
 
437
        }
 
438
        return dirp;
 
439
}
 
440
 
 
441
struct dirent *readdir(DIR *dirp)
 
442
{
 
443
        ssize_t len = read(dirp->fd, &dirp->res.d_name[0], NAME_MAX + 1);
 
444
        if (len <= 0)
 
445
                return NULL;
 
446
        return &dirp->res;
 
447
}
 
448
 
 
449
void rewinddir(DIR *dirp)
 
450
{
 
451
        (void) lseek(dirp->fd, 0, SEEK_SET);
 
452
}
 
453
 
 
454
int closedir(DIR *dirp)
 
455
{
 
456
        (void) close(dirp->fd);
 
457
        free(dirp);
 
458
        return 0;
 
459
}
 
460
 
 
461
int mkdir(const char *path, mode_t mode)
 
462
{
 
463
        ipcarg_t rc;
 
464
        aid_t req;
 
465
        
 
466
        size_t pa_size;
 
467
        char *pa = absolutize(path, &pa_size);
 
468
        if (!pa)
 
469
                return ENOMEM;
 
470
        
 
471
        futex_down(&vfs_phone_futex);
 
472
        async_serialize_start();
 
473
        vfs_connect();
 
474
        
 
475
        req = async_send_1(vfs_phone, VFS_IN_MKDIR, mode, NULL);
 
476
        rc = ipc_data_write_start(vfs_phone, pa, pa_size);
 
477
        if (rc != EOK) {
 
478
                async_wait_for(req, NULL);
 
479
                async_serialize_end();
 
480
                futex_up(&vfs_phone_futex);
 
481
                free(pa);
 
482
                return (int) rc;
 
483
        }
 
484
        async_wait_for(req, &rc);
 
485
        async_serialize_end();
 
486
        futex_up(&vfs_phone_futex);
 
487
        free(pa);
 
488
        return rc;
 
489
}
 
490
 
 
491
static int _unlink(const char *path, int lflag)
 
492
{
 
493
        ipcarg_t rc;
 
494
        aid_t req;
 
495
        
 
496
        size_t pa_size;
 
497
        char *pa = absolutize(path, &pa_size);
 
498
        if (!pa)
 
499
                return ENOMEM;
 
500
 
 
501
        futex_down(&vfs_phone_futex);
 
502
        async_serialize_start();
 
503
        vfs_connect();
 
504
        
 
505
        req = async_send_0(vfs_phone, VFS_IN_UNLINK, NULL);
 
506
        rc = ipc_data_write_start(vfs_phone, pa, pa_size);
 
507
        if (rc != EOK) {
 
508
                async_wait_for(req, NULL);
 
509
                async_serialize_end();
 
510
                futex_up(&vfs_phone_futex);
 
511
                free(pa);
 
512
                return (int) rc;
 
513
        }
 
514
        async_wait_for(req, &rc);
 
515
        async_serialize_end();
 
516
        futex_up(&vfs_phone_futex);
 
517
        free(pa);
 
518
        return rc;
 
519
}
 
520
 
 
521
int unlink(const char *path)
 
522
{
 
523
        return _unlink(path, L_NONE);
 
524
}
 
525
 
 
526
int rmdir(const char *path)
 
527
{
 
528
        return _unlink(path, L_DIRECTORY);
 
529
}
 
530
 
 
531
int rename(const char *old, const char *new)
 
532
{
 
533
        ipcarg_t rc;
 
534
        aid_t req;
 
535
        
 
536
        size_t olda_size;
 
537
        char *olda = absolutize(old, &olda_size);
 
538
        if (!olda)
 
539
                return ENOMEM;
 
540
 
 
541
        size_t newa_size;
 
542
        char *newa = absolutize(new, &newa_size);
 
543
        if (!newa) {
 
544
                free(olda);
 
545
                return ENOMEM;
 
546
        }
 
547
 
 
548
        futex_down(&vfs_phone_futex);
 
549
        async_serialize_start();
 
550
        vfs_connect();
 
551
        
 
552
        req = async_send_0(vfs_phone, VFS_IN_RENAME, NULL);
 
553
        rc = ipc_data_write_start(vfs_phone, olda, olda_size);
 
554
        if (rc != EOK) {
 
555
                async_wait_for(req, NULL);
 
556
                async_serialize_end();
 
557
                futex_up(&vfs_phone_futex);
 
558
                free(olda);
 
559
                free(newa);
 
560
                return (int) rc;
 
561
        }
 
562
        rc = ipc_data_write_start(vfs_phone, newa, newa_size);
 
563
        if (rc != EOK) {
 
564
                async_wait_for(req, NULL);
 
565
                async_serialize_end();
 
566
                futex_up(&vfs_phone_futex);
 
567
                free(olda);
 
568
                free(newa);
 
569
                return (int) rc;
 
570
        }
 
571
        async_wait_for(req, &rc);
 
572
        async_serialize_end();
 
573
        futex_up(&vfs_phone_futex);
 
574
        free(olda);
 
575
        free(newa);
 
576
        return rc;
 
577
}
 
578
 
 
579
int chdir(const char *path)
 
580
{
 
581
        size_t pa_size;
 
582
        char *pa = absolutize(path, &pa_size);
 
583
        if (!pa)
 
584
                return ENOMEM;
 
585
 
 
586
        DIR *d = opendir(pa);
 
587
        if (!d) {
 
588
                free(pa);
 
589
                return ENOENT;
 
590
        }
 
591
 
 
592
        futex_down(&cwd_futex);
 
593
        if (cwd_dir) {
 
594
                closedir(cwd_dir);
 
595
                cwd_dir = NULL;
 
596
                free(cwd_path); 
 
597
                cwd_path = NULL;
 
598
                cwd_size = 0;
 
599
        }
 
600
        cwd_dir = d;
 
601
        cwd_path = pa;
 
602
        cwd_size = pa_size;
 
603
        futex_up(&cwd_futex);
 
604
        return EOK;
 
605
}
 
606
 
 
607
char *getcwd(char *buf, size_t size)
 
608
{
 
609
        if (!size)
 
610
                return NULL;
 
611
        futex_down(&cwd_futex);
 
612
        if (size < cwd_size + 1) {
 
613
                futex_up(&cwd_futex);
 
614
                return NULL;
 
615
        }
 
616
        str_cpy(buf, size, cwd_path);
 
617
        futex_up(&cwd_futex);
 
618
        return buf;
 
619
}
 
620
 
 
621
int fd_phone(int fildes)
 
622
{
 
623
        struct stat stat;
 
624
        int rc;
 
625
 
 
626
        rc = fstat(fildes, &stat);
 
627
 
 
628
        if (!stat.devfs_stat.device)
 
629
                return -1;
 
630
        
 
631
        return devmap_device_connect(stat.devfs_stat.device, 0);
 
632
}
 
633
 
 
634
int fd_node(int fildes, fdi_node_t *node)
 
635
{
 
636
        struct stat stat;
 
637
        int rc;
 
638
 
 
639
        rc = fstat(fildes, &stat);
 
640
        
 
641
        if (rc == EOK) {
 
642
                node->fs_handle = stat.fs_handle;
 
643
                node->dev_handle = stat.dev_handle;
 
644
                node->index = stat.index;
 
645
        }
 
646
        
 
647
        return rc;
 
648
}
 
649
 
 
650
/** @}
 
651
 */