source: mainline/uspace/srv/fs/ext2fs/ext2fs_ops.c@ 84226f0

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

ext2fs: Check for dot filenames in the other place too

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