source: mainline/uspace/srv/fs/ext2fs/ext2fs_ops.c@ 868ef40

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 868ef40 was eef306c, checked in by Martin Sucha <sucha14@…>, 14 years ago

Check filesystem feature flags when mounting

  • Property mode set to 100644
File size: 20.4 KB
Line 
1/*
2 * Copyright (c) 2008 Jakub Jermar
3 * Copyright (c) 2011 Martin Sucha
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup fs
31 * @{
32 */
33
34/**
35 * @file ext2fs_ops.c
36 * @brief Implementation of VFS operations for the EXT2 file system server.
37 */
38
39#include "ext2fs.h"
40#include "../../vfs/vfs.h"
41#include <libfs.h>
42#include <libblock.h>
43#include <libext2.h>
44#include <ipc/services.h>
45#include <ipc/devmap.h>
46#include <macros.h>
47#include <async.h>
48#include <errno.h>
49#include <str.h>
50#include <byteorder.h>
51#include <adt/hash_table.h>
52#include <adt/list.h>
53#include <assert.h>
54#include <fibril_synch.h>
55#include <sys/mman.h>
56#include <align.h>
57#include <adt/hash_table.h>
58
59#define EXT2FS_NODE(node) ((node) ? (ext2fs_node_t *) (node)->data : NULL)
60#define EXT2FS_DBG(format, ...) {if (false) printf("ext2fs: %s: " format "\n", __FUNCTION__, ##__VA_ARGS__);}
61
62typedef struct ext2fs_instance {
63 link_t link;
64 devmap_handle_t devmap_handle;
65 ext2_filesystem_t *filesystem;
66} ext2fs_instance_t;
67
68typedef struct ext2fs_node {
69 ext2fs_instance_t *instance;
70 ext2_inode_ref_t *inode_ref;
71} ext2fs_node_t;
72
73/*
74 * Forward declarations of auxiliary functions
75 */
76static int ext2fs_instance_get(devmap_handle_t, ext2fs_instance_t **);
77static void ext2fs_read_directory(ipc_callid_t, ipc_callid_t, aoff64_t,
78 size_t, ext2fs_instance_t *, ext2_inode_ref_t *);
79static void ext2fs_read_file(ipc_callid_t, ipc_callid_t, aoff64_t,
80 size_t, ext2fs_instance_t *, ext2_inode_ref_t *);
81static bool ext2fs_is_dots(const uint8_t *, size_t);
82static int ext2fs_node_get_core(fs_node_t **, ext2fs_instance_t *, fs_index_t);
83
84/*
85 * Forward declarations of EXT2 libfs operations.
86 */
87static int ext2fs_root_get(fs_node_t **, devmap_handle_t);
88static int ext2fs_match(fs_node_t **, fs_node_t *, const char *);
89static int ext2fs_node_get(fs_node_t **, devmap_handle_t, fs_index_t);
90static int ext2fs_node_open(fs_node_t *);
91static int ext2fs_node_put(fs_node_t *);
92static int ext2fs_create_node(fs_node_t **, devmap_handle_t, int);
93static int ext2fs_destroy_node(fs_node_t *);
94static int ext2fs_link(fs_node_t *, fs_node_t *, const char *);
95static int ext2fs_unlink(fs_node_t *, fs_node_t *, const char *);
96static int ext2fs_has_children(bool *, fs_node_t *);
97static fs_index_t ext2fs_index_get(fs_node_t *);
98static aoff64_t ext2fs_size_get(fs_node_t *);
99static unsigned ext2fs_lnkcnt_get(fs_node_t *);
100static char ext2fs_plb_get_char(unsigned);
101static bool ext2fs_is_directory(fs_node_t *);
102static bool ext2fs_is_file(fs_node_t *node);
103static devmap_handle_t ext2fs_device_get(fs_node_t *node);
104
105/*
106 * Static variables
107 */
108static LIST_INITIALIZE(instance_list);
109static FIBRIL_MUTEX_INITIALIZE(instance_list_mutex);
110
111/**
112 *
113 */
114int ext2fs_global_init(void)
115{
116 return EOK;
117}
118
119int ext2fs_global_fini(void)
120{
121 return EOK;
122}
123
124
125
126/*
127 * EXT2 libfs operations.
128 */
129
130/**
131 * Find an instance of filesystem for the given devmap_handle
132 */
133int ext2fs_instance_get(devmap_handle_t devmap_handle, ext2fs_instance_t **inst)
134{
135 EXT2FS_DBG("(%u, -)", devmap_handle);
136 link_t *link;
137 ext2fs_instance_t *tmp;
138
139 fibril_mutex_lock(&instance_list_mutex);
140
141 if (list_empty(&instance_list)) {
142 EXT2FS_DBG("list empty");
143 fibril_mutex_unlock(&instance_list_mutex);
144 return EINVAL;
145 }
146
147 for (link = instance_list.next; link != &instance_list; link = link->next) {
148 tmp = list_get_instance(link, ext2fs_instance_t, link);
149
150 if (tmp->devmap_handle == devmap_handle) {
151 *inst = tmp;
152 fibril_mutex_unlock(&instance_list_mutex);
153 return EOK;
154 }
155 }
156
157 EXT2FS_DBG("not found");
158
159 fibril_mutex_unlock(&instance_list_mutex);
160 return EINVAL;
161}
162
163
164
165int ext2fs_root_get(fs_node_t **rfn, devmap_handle_t devmap_handle)
166{
167 EXT2FS_DBG("(-, %u)", devmap_handle);
168 return ext2fs_node_get(rfn, devmap_handle, EXT2_INODE_ROOT_INDEX);
169}
170
171int ext2fs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
172{
173 EXT2FS_DBG("(-,-,%s)", component);
174 ext2fs_node_t *eparent = EXT2FS_NODE(pfn);
175 ext2_filesystem_t *fs;
176 ext2_directory_iterator_t it;
177 int rc;
178 size_t name_size;
179 size_t component_size;
180 bool found = false;
181
182 fs = eparent->instance->filesystem;
183
184 if (!ext2_inode_is_type(fs->superblock, eparent->inode_ref->inode,
185 EXT2_INODE_MODE_DIRECTORY)) {
186 return ENOTDIR;
187 }
188
189 rc = ext2_directory_iterator_init(&it, fs, eparent->inode_ref);
190 if (rc != EOK) {
191 return rc;
192 }
193
194 // Find length of component in bytes
195 // TODO: check for library function call that does this
196 component_size = 0;
197 while (*(component+component_size) != 0) {
198 component_size++;
199 }
200
201 while (it.current != NULL) {
202 // ignore empty directory entries
203 if (it.current->inode != 0) {
204 name_size = ext2_directory_entry_ll_get_name_length(fs->superblock,
205 it.current);
206
207 if (name_size == component_size && bcmp(component, &it.current->name,
208 name_size) == 0) {
209 rc = ext2fs_node_get_core(rfn, eparent->instance,
210 it.current->inode);
211 if (rc != EOK) {
212 ext2_directory_iterator_fini(&it);
213 return rc;
214 }
215 found = true;
216 break;
217 }
218 }
219
220 rc = ext2_directory_iterator_next(&it);
221 if (rc != EOK) {
222 ext2_directory_iterator_fini(&it);
223 return rc;
224 }
225 }
226
227 ext2_directory_iterator_fini(&it);
228
229 if (!found) {
230 return ENOENT;
231 }
232
233 return EOK;
234}
235
236/** Instantiate a EXT2 in-core node. */
237int ext2fs_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle, fs_index_t index)
238{
239 EXT2FS_DBG("(-,%u,%u)", devmap_handle, index);
240
241 ext2fs_instance_t *inst = NULL;
242 int rc;
243
244 rc = ext2fs_instance_get(devmap_handle, &inst);
245 if (rc != EOK) {
246 return rc;
247 }
248
249 return ext2fs_node_get_core(rfn, inst, index);
250}
251
252int ext2fs_node_get_core(fs_node_t **rfn, ext2fs_instance_t *inst,
253 fs_index_t index)
254{
255 int rc;
256 fs_node_t *node = NULL;
257 ext2fs_node_t *enode = NULL;
258
259 ext2_inode_ref_t *inode_ref = NULL;
260
261 enode = malloc(sizeof(ext2fs_node_t));
262 if (enode == NULL) {
263 return ENOMEM;
264 }
265
266 node = malloc(sizeof(fs_node_t));
267 if (node == NULL) {
268 free(enode);
269 return ENOMEM;
270 }
271 fs_node_initialize(node);
272
273 rc = ext2_filesystem_get_inode_ref(inst->filesystem, index, &inode_ref);
274 if (rc != EOK) {
275 free(enode);
276 free(node);
277 return rc;
278 }
279
280 enode->inode_ref = inode_ref;
281 enode->instance = inst;
282 node->data = enode;
283 *rfn = node;
284
285 EXT2FS_DBG("inode: %u", inode_ref->index);
286
287 EXT2FS_DBG("EOK");
288
289 return EOK;
290}
291
292int ext2fs_node_open(fs_node_t *fn)
293{
294 EXT2FS_DBG("");
295 /*
296 * Opening a file is stateless, nothing
297 * to be done here.
298 */
299 return EOK;
300}
301
302int ext2fs_node_put(fs_node_t *fn)
303{
304 EXT2FS_DBG("");
305 int rc;
306 ext2fs_node_t *enode = EXT2FS_NODE(fn);
307 rc = ext2_filesystem_put_inode_ref(enode->inode_ref);
308 if (rc != EOK) {
309 EXT2FS_DBG("ext2_filesystem_put_inode_ref failed");
310 }
311 return rc;
312}
313
314int ext2fs_create_node(fs_node_t **rfn, devmap_handle_t devmap_handle, int flags)
315{
316 EXT2FS_DBG("");
317 // TODO
318 return ENOTSUP;
319}
320
321int ext2fs_destroy_node(fs_node_t *fn)
322{
323 EXT2FS_DBG("");
324 // TODO
325 return ENOTSUP;
326}
327
328int ext2fs_link(fs_node_t *pfn, fs_node_t *cfn, const char *name)
329{
330 EXT2FS_DBG("");
331 // TODO
332 return ENOTSUP;
333}
334
335int ext2fs_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
336{
337 EXT2FS_DBG("");
338 // TODO
339 return ENOTSUP;
340}
341
342int ext2fs_has_children(bool *has_children, fs_node_t *fn)
343{
344 EXT2FS_DBG("");
345 ext2fs_node_t *enode = EXT2FS_NODE(fn);
346 ext2_directory_iterator_t it;
347 ext2_filesystem_t *fs;
348 int rc;
349 bool found = false;
350 size_t name_size;
351
352 fs = enode->instance->filesystem;
353
354 if (!ext2_inode_is_type(fs->superblock, enode->inode_ref->inode,
355 EXT2_INODE_MODE_DIRECTORY)) {
356 *has_children = false;
357 EXT2FS_DBG("EOK - false");
358 return EOK;
359 }
360
361 rc = ext2_directory_iterator_init(&it, fs, enode->inode_ref);
362 if (rc != EOK) {
363 EXT2FS_DBG("error %u", rc);
364 return rc;
365 }
366
367 // Find a non-empty directory entry
368 while (it.current != NULL) {
369 if (it.current->inode != 0) {
370 name_size = ext2_directory_entry_ll_get_name_length(fs->superblock,
371 it.current);
372 if (!ext2fs_is_dots(&it.current->name, name_size)) {
373 found = true;
374 break;
375 }
376 }
377
378 rc = ext2_directory_iterator_next(&it);
379 if (rc != EOK) {
380 ext2_directory_iterator_fini(&it);
381 EXT2FS_DBG("error %u", rc);
382 return rc;
383 }
384 }
385
386 rc = ext2_directory_iterator_fini(&it);
387 if (rc != EOK) {
388 EXT2FS_DBG("error %u", rc);
389 return rc;
390 }
391
392 *has_children = found;
393 EXT2FS_DBG("EOK");
394
395 return EOK;
396}
397
398
399fs_index_t ext2fs_index_get(fs_node_t *fn)
400{
401 ext2fs_node_t *enode = EXT2FS_NODE(fn);
402 EXT2FS_DBG("%u", enode->inode_ref->index);
403 return enode->inode_ref->index;
404}
405
406aoff64_t ext2fs_size_get(fs_node_t *fn)
407{
408 ext2fs_node_t *enode = EXT2FS_NODE(fn);
409 aoff64_t size = ext2_inode_get_size(enode->instance->filesystem->superblock,
410 enode->inode_ref->inode);
411 EXT2FS_DBG("%" PRIu64, size);
412 return size;
413}
414
415unsigned ext2fs_lnkcnt_get(fs_node_t *fn)
416{
417 ext2fs_node_t *enode = EXT2FS_NODE(fn);
418 unsigned count = ext2_inode_get_usage_count(enode->inode_ref->inode);
419 EXT2FS_DBG("%u", count);
420 return count;
421}
422
423char ext2fs_plb_get_char(unsigned pos)
424{
425 return ext2fs_reg.plb_ro[pos % PLB_SIZE];
426}
427
428bool ext2fs_is_directory(fs_node_t *fn)
429{
430 ext2fs_node_t *enode = EXT2FS_NODE(fn);
431 bool is_dir = ext2_inode_is_type(enode->instance->filesystem->superblock,
432 enode->inode_ref->inode, EXT2_INODE_MODE_DIRECTORY);
433 EXT2FS_DBG("%s", is_dir ? "true" : "false");
434 EXT2FS_DBG("%u", enode->inode_ref->index);
435 return is_dir;
436}
437
438bool ext2fs_is_file(fs_node_t *fn)
439{
440 ext2fs_node_t *enode = EXT2FS_NODE(fn);
441 bool is_file = ext2_inode_is_type(enode->instance->filesystem->superblock,
442 enode->inode_ref->inode, EXT2_INODE_MODE_FILE);
443 EXT2FS_DBG("%s", is_file ? "true" : "false");
444 return is_file;
445}
446
447devmap_handle_t ext2fs_device_get(fs_node_t *fn)
448{
449 EXT2FS_DBG("");
450 ext2fs_node_t *enode = EXT2FS_NODE(fn);
451 return enode->instance->devmap_handle;
452}
453
454/** libfs operations */
455libfs_ops_t ext2fs_libfs_ops = {
456 .root_get = ext2fs_root_get,
457 .match = ext2fs_match,
458 .node_get = ext2fs_node_get,
459 .node_open = ext2fs_node_open,
460 .node_put = ext2fs_node_put,
461 .create = ext2fs_create_node,
462 .destroy = ext2fs_destroy_node,
463 .link = ext2fs_link,
464 .unlink = ext2fs_unlink,
465 .has_children = ext2fs_has_children,
466 .index_get = ext2fs_index_get,
467 .size_get = ext2fs_size_get,
468 .lnkcnt_get = ext2fs_lnkcnt_get,
469 .plb_get_char = ext2fs_plb_get_char,
470 .is_directory = ext2fs_is_directory,
471 .is_file = ext2fs_is_file,
472 .device_get = ext2fs_device_get
473};
474
475/*
476 * VFS operations.
477 */
478
479void ext2fs_mounted(ipc_callid_t rid, ipc_call_t *request)
480{
481 EXT2FS_DBG("");
482 int rc;
483 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
484 ext2_filesystem_t *fs;
485 ext2fs_instance_t *inst;
486 bool read_only;
487
488 /* Accept the mount options */
489 char *opts;
490 rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
491
492 if (rc != EOK) {
493 async_answer_0(rid, rc);
494 return;
495 }
496
497 free(opts);
498
499 /* Allocate libext2 filesystem structure */
500 fs = (ext2_filesystem_t *) malloc(sizeof(ext2_filesystem_t));
501 if (fs == NULL) {
502 async_answer_0(rid, ENOMEM);
503 return;
504 }
505
506 /* Allocate instance structure */
507 inst = (ext2fs_instance_t *) malloc(sizeof(ext2fs_instance_t));
508 if (inst == NULL) {
509 free(fs);
510 async_answer_0(rid, ENOMEM);
511 return;
512 }
513
514 /* Initialize the filesystem */
515 rc = ext2_filesystem_init(fs, devmap_handle);
516 if (rc != EOK) {
517 free(fs);
518 free(inst);
519 async_answer_0(rid, rc);
520 return;
521 }
522
523 /* Do some sanity checking */
524 rc = ext2_filesystem_check_sanity(fs);
525 if (rc != EOK) {
526 ext2_filesystem_fini(fs);
527 free(fs);
528 free(inst);
529 async_answer_0(rid, rc);
530 return;
531 }
532
533 /* Check flags */
534 rc = ext2_filesystem_check_flags(fs, &read_only);
535 if (rc != EOK) {
536 ext2_filesystem_fini(fs);
537 free(fs);
538 free(inst);
539 async_answer_0(rid, rc);
540 return;
541 }
542
543 /* Initialize instance and add to the list */
544 link_initialize(&inst->link);
545 inst->devmap_handle = devmap_handle;
546 inst->filesystem = fs;
547
548 fibril_mutex_lock(&instance_list_mutex);
549 list_append(&inst->link, &instance_list);
550 fibril_mutex_unlock(&instance_list_mutex);
551
552 async_answer_0(rid, EOK);
553}
554
555void ext2fs_mount(ipc_callid_t rid, ipc_call_t *request)
556{
557 EXT2FS_DBG("");
558 libfs_mount(&ext2fs_libfs_ops, ext2fs_reg.fs_handle, rid, request);
559}
560
561void ext2fs_unmounted(ipc_callid_t rid, ipc_call_t *request)
562{
563 EXT2FS_DBG("");
564 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
565 ext2fs_instance_t *inst;
566 int rc;
567
568 rc = ext2fs_instance_get(devmap_handle, &inst);
569
570 if (rc != EOK) {
571 async_answer_0(rid, rc);
572 return;
573 }
574
575 // TODO: check if the fs is busy
576
577 // Remove the instance from list
578 fibril_mutex_lock(&instance_list_mutex);
579 list_remove(&inst->link);
580 fibril_mutex_unlock(&instance_list_mutex);
581
582 ext2_filesystem_fini(inst->filesystem);
583
584 async_answer_0(rid, EOK);
585}
586
587void ext2fs_unmount(ipc_callid_t rid, ipc_call_t *request)
588{
589 EXT2FS_DBG("");
590 libfs_unmount(&ext2fs_libfs_ops, rid, request);
591}
592
593void ext2fs_lookup(ipc_callid_t rid, ipc_call_t *request)
594{
595 EXT2FS_DBG("");
596 libfs_lookup(&ext2fs_libfs_ops, ext2fs_reg.fs_handle, rid, request);
597}
598
599void ext2fs_read(ipc_callid_t rid, ipc_call_t *request)
600{
601 EXT2FS_DBG("");
602 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
603 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
604 aoff64_t pos =
605 (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
606
607 ext2fs_instance_t *inst;
608 ext2_inode_ref_t *inode_ref;
609 int rc;
610
611 /*
612 * Receive the read request.
613 */
614 ipc_callid_t callid;
615 size_t size;
616 if (!async_data_read_receive(&callid, &size)) {
617 async_answer_0(callid, EINVAL);
618 async_answer_0(rid, EINVAL);
619 return;
620 }
621
622 rc = ext2fs_instance_get(devmap_handle, &inst);
623 if (rc != EOK) {
624 async_answer_0(callid, rc);
625 async_answer_0(rid, rc);
626 return;
627 }
628
629 rc = ext2_filesystem_get_inode_ref(inst->filesystem, index, &inode_ref);
630 if (rc != EOK) {
631 async_answer_0(callid, rc);
632 async_answer_0(rid, rc);
633 return;
634 }
635
636 if (ext2_inode_is_type(inst->filesystem->superblock, inode_ref->inode,
637 EXT2_INODE_MODE_FILE)) {
638 ext2fs_read_file(rid, callid, pos, size, inst, inode_ref);
639 }
640 else if (ext2_inode_is_type(inst->filesystem->superblock, inode_ref->inode,
641 EXT2_INODE_MODE_DIRECTORY)) {
642 ext2fs_read_directory(rid, callid, pos, size, inst, inode_ref);
643 }
644 else {
645 // Other inode types not supported
646 async_answer_0(callid, ENOTSUP);
647 async_answer_0(rid, ENOTSUP);
648 }
649
650 ext2_filesystem_put_inode_ref(inode_ref);
651
652}
653
654/**
655 * Determine whether given directory entry name is . or ..
656 */
657bool ext2fs_is_dots(const uint8_t *name, size_t name_size) {
658 if (name_size == 1 && name[0] == '.') {
659 return true;
660 }
661
662 if (name_size == 2 && name[0] == '.' && name[1] == '.') {
663 return true;
664 }
665
666 return false;
667}
668
669void ext2fs_read_directory(ipc_callid_t rid, ipc_callid_t callid, aoff64_t pos,
670 size_t size, ext2fs_instance_t *inst, ext2_inode_ref_t *inode_ref)
671{
672 ext2_directory_iterator_t it;
673 aoff64_t cur;
674 uint8_t *buf;
675 size_t name_size;
676 int rc;
677 bool found = false;
678
679 rc = ext2_directory_iterator_init(&it, inst->filesystem, inode_ref);
680 if (rc != EOK) {
681 async_answer_0(callid, rc);
682 async_answer_0(rid, rc);
683 return;
684 }
685
686 // Find the index we want to read
687 // Note that we need to iterate and count as
688 // the underlying structure is a linked list
689 // Moreover, we want to skip . and .. entries
690 // as these are not used in HelenOS
691 cur = 0;
692 while (it.current != NULL) {
693 if (it.current->inode == 0) {
694 goto skip;
695 }
696
697 name_size = ext2_directory_entry_ll_get_name_length(
698 inst->filesystem->superblock, it.current);
699
700 // skip . and ..
701 if (ext2fs_is_dots(&it.current->name, name_size)) {
702 goto skip;
703 }
704
705 // Is this the dir entry we want to read?
706 if (cur == pos) {
707 // The on-disk entry does not contain \0 at the end
708 // end of entry name, so we copy it to new buffer
709 // and add the \0 at the end
710 buf = malloc(name_size+1);
711 if (buf == NULL) {
712 ext2_directory_iterator_fini(&it);
713 async_answer_0(callid, ENOMEM);
714 async_answer_0(rid, ENOMEM);
715 return;
716 }
717 memcpy(buf, &it.current->name, name_size);
718 *(buf+name_size) = 0;
719 found = true;
720 (void) async_data_read_finalize(callid, buf, name_size+1);
721 free(buf);
722 break;
723 }
724 cur++;
725
726skip:
727 rc = ext2_directory_iterator_next(&it);
728 if (rc != EOK) {
729 ext2_directory_iterator_fini(&it);
730 async_answer_0(callid, rc);
731 async_answer_0(rid, rc);
732 return;
733 }
734 }
735
736 rc = ext2_directory_iterator_fini(&it);
737 if (rc != EOK) {
738 async_answer_0(rid, rc);
739 return;
740 }
741
742 if (found) {
743 async_answer_1(rid, EOK, 1);
744 }
745 else {
746 async_answer_0(callid, ENOENT);
747 async_answer_0(rid, ENOENT);
748 }
749}
750
751void ext2fs_read_file(ipc_callid_t rid, ipc_callid_t callid, aoff64_t pos,
752 size_t size, ext2fs_instance_t *inst, ext2_inode_ref_t *inode_ref)
753{
754 int rc;
755 uint32_t block_size;
756 aoff64_t file_block;
757 uint64_t file_size;
758 uint32_t fs_block;
759 size_t offset_in_block;
760 size_t bytes;
761 block_t *block;
762
763 file_size = ext2_inode_get_size(inst->filesystem->superblock,
764 inode_ref->inode);
765
766 if (pos >= file_size) {
767 // Read 0 bytes successfully
768 async_data_read_finalize(callid, NULL, 0);
769 async_answer_1(rid, EOK, 0);
770 return;
771 }
772
773 // For now, we only read data from one block at a time
774 block_size = ext2_superblock_get_block_size(inst->filesystem->superblock);
775 file_block = pos / block_size;
776 offset_in_block = pos % block_size;
777 bytes = min(block_size - offset_in_block, size);
778
779 rc = ext2_filesystem_get_inode_data_block_index(inst->filesystem,
780 inode_ref->inode, file_block, &fs_block);
781 if (rc != EOK) {
782 async_answer_0(callid, rc);
783 async_answer_0(rid, rc);
784 return;
785 }
786
787 rc = block_get(&block, inst->devmap_handle, fs_block, BLOCK_FLAGS_NONE);
788 if (rc != EOK) {
789 async_answer_0(callid, rc);
790 async_answer_0(rid, rc);
791 return;
792 }
793
794 async_data_read_finalize(callid, block->data, bytes);
795
796 rc = block_put(block);
797 if (rc != EOK) {
798 async_answer_0(rid, rc);
799 return;
800 }
801
802 async_answer_1(rid, EOK, bytes);
803}
804
805void ext2fs_write(ipc_callid_t rid, ipc_call_t *request)
806{
807 EXT2FS_DBG("");
808// devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
809// fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
810// aoff64_t pos =
811// (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
812
813 // TODO
814 async_answer_0(rid, ENOTSUP);
815}
816
817void ext2fs_truncate(ipc_callid_t rid, ipc_call_t *request)
818{
819 EXT2FS_DBG("");
820// devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
821// fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
822// aoff64_t size =
823// (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
824
825 // TODO
826 async_answer_0(rid, ENOTSUP);
827}
828
829void ext2fs_close(ipc_callid_t rid, ipc_call_t *request)
830{
831 EXT2FS_DBG("");
832 async_answer_0(rid, EOK);
833}
834
835void ext2fs_destroy(ipc_callid_t rid, ipc_call_t *request)
836{
837 EXT2FS_DBG("");
838// devmap_handle_t devmap_handle = (devmap_handle_t)IPC_GET_ARG1(*request);
839// fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request);
840
841 // TODO
842 async_answer_0(rid, ENOTSUP);
843}
844
845void ext2fs_open_node(ipc_callid_t rid, ipc_call_t *request)
846{
847 EXT2FS_DBG("");
848 libfs_open_node(&ext2fs_libfs_ops, ext2fs_reg.fs_handle, rid, request);
849}
850
851void ext2fs_stat(ipc_callid_t rid, ipc_call_t *request)
852{
853 EXT2FS_DBG("");
854 libfs_stat(&ext2fs_libfs_ops, ext2fs_reg.fs_handle, rid, request);
855}
856
857void ext2fs_sync(ipc_callid_t rid, ipc_call_t *request)
858{
859 EXT2FS_DBG("");
860// devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
861// fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
862
863 // TODO
864 async_answer_0(rid, ENOTSUP);
865}
866
867/**
868 * @}
869 */
Note: See TracBrowser for help on using the repository browser.