source: mainline/uspace/srv/fs/ext2fs/ext2fs_ops.c@ 0e26444

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

Fix includes in ext2fs_ops

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