source: mainline/uspace/srv/fs/minixfs/mfs_ops.c@ 13ecdac9

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 13ecdac9 was 13ecdac9, checked in by Maurizio Lombardi <m.lombardi85@…>, 14 years ago

Add support to directories (mkdir now works)

  • Property mode set to 100644
File size: 20.1 KB
RevLine 
[096c8835]1/*
2 * Copyright (c) 2011 Maurizio Lombardi
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 fs
30 * @{
31 */
32
[9e3dc95]33#include <stdlib.h>
[953a823]34#include <fibril_synch.h>
[bb7e8382]35#include <align.h>
[7413683]36#include "mfs.h"
[9e3dc95]37#include "mfs_utils.h"
38
[8ceba1e]39static bool check_magic_number(uint16_t magic, bool *native,
[44c6091f]40 mfs_version_t *version, bool *longfilenames);
[44c0f5b]41static int mfs_node_core_get(fs_node_t **rfn, struct mfs_instance *inst,
[44c6091f]42 fs_index_t index);
[096c8835]43
[41202a9]44static int mfs_node_put(fs_node_t *fsnode);
45static int mfs_node_open(fs_node_t *fsnode);
46static fs_index_t mfs_index_get(fs_node_t *fsnode);
47static unsigned mfs_lnkcnt_get(fs_node_t *fsnode);
[ac28650]48static char mfs_plb_get_char(unsigned pos);
49static bool mfs_is_directory(fs_node_t *fsnode);
50static bool mfs_is_file(fs_node_t *fsnode);
51static int mfs_has_children(bool *has_children, fs_node_t *fsnode);
52static int mfs_root_get(fs_node_t **rfn, devmap_handle_t handle);
53static devmap_handle_t mfs_device_get(fs_node_t *fsnode);
54static aoff64_t mfs_size_get(fs_node_t *node);
[bd64680]55static int mfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component);
[10eb754]56static int mfs_create_node(fs_node_t **rfn, devmap_handle_t handle, int flags);
[88ccd8b8]57static int mfs_link(fs_node_t *pfn, fs_node_t *cfn, const char *name);
[ac28650]58
[668f1949]59static int mfs_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle,
[ac28650]60 fs_index_t index);
61
[41202a9]62
[953a823]63static LIST_INITIALIZE(inst_list);
64static FIBRIL_MUTEX_INITIALIZE(inst_list_mutex);
65
[e54ba607]66libfs_ops_t mfs_libfs_ops = {
[0d6ab10]67 .size_get = mfs_size_get,
[fe4ac35]68 .root_get = mfs_root_get,
[5a58ae2]69 .device_get = mfs_device_get,
[7d04324]70 .is_directory = mfs_is_directory,
[44c0f5b]71 .is_file = mfs_is_file,
[cfbcd86]72 .node_get = mfs_node_get,
[41202a9]73 .node_put = mfs_node_put,
74 .node_open = mfs_node_open,
75 .index_get = mfs_index_get,
[bd64680]76 .match = mfs_match,
[10eb754]77 .create = mfs_create_node,
[88ccd8b8]78 .link = mfs_link,
[54caa41b]79 .plb_get_char = mfs_plb_get_char,
[41202a9]80 .has_children = mfs_has_children,
81 .lnkcnt_get = mfs_lnkcnt_get
[e54ba607]82};
[3b08178]83
[096c8835]84void mfs_mounted(ipc_callid_t rid, ipc_call_t *request)
85{
86 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
[44c6091f]87 enum cache_mode cmode;
[953a823]88 struct mfs_superblock *sb;
89 struct mfs3_superblock *sb3;
90 struct mfs_sb_info *sbi;
91 struct mfs_instance *instance;
[8ceba1e]92 bool native, longnames;
[9e3dc95]93 mfs_version_t version;
[245eb02d]94 uint16_t magic;
[096c8835]95
96 /* Accept the mount options */
97 char *opts;
98 int rc = async_data_write_accept((void **) &opts, true, 0, 0, 0, NULL);
[44c6091f]99
[096c8835]100 if (rc != EOK) {
[92dd5c8]101 mfsdebug("Can't accept async data write\n");
[096c8835]102 async_answer_0(rid, rc);
103 return;
104 }
105
106 /* Check for option enabling write through. */
107 if (str_cmp(opts, "wtcache") == 0)
108 cmode = CACHE_MODE_WT;
109 else
110 cmode = CACHE_MODE_WB;
111
112 free(opts);
113
114 /* initialize libblock */
[92dd5c8]115 rc = block_init(devmap_handle, 1024);
[096c8835]116 if (rc != EOK) {
[92dd5c8]117 mfsdebug("libblock initialization failed\n");
[096c8835]118 async_answer_0(rid, rc);
119 return;
120 }
121
[953a823]122 /*Allocate space for generic MFS superblock*/
[b438804]123 sbi = malloc(sizeof(*sbi));
[953a823]124
125 if (!sbi) {
126 async_answer_0(rid, ENOMEM);
127 return;
128 }
129
130 /*Allocate space for filesystem instance*/
[b438804]131 instance = malloc(sizeof(*instance));
[953a823]132
133 if (!instance) {
134 async_answer_0(rid, ENOMEM);
135 return;
136 }
137
[b438804]138 sb = malloc(MFS_SUPERBLOCK_SIZE);
[953a823]139
140 if (!sb) {
141 async_answer_0(rid, ENOMEM);
142 return;
143 }
[92dd5c8]144
145 /* Read the superblock */
[953a823]146 rc = block_read_direct(devmap_handle, MFS_SUPERBLOCK << 1, 1, sb);
[096c8835]147 if (rc != EOK) {
148 block_fini(devmap_handle);
149 async_answer_0(rid, rc);
150 return;
151 }
152
[953a823]153 sb3 = (struct mfs3_superblock *) sb;
154
155 if (check_magic_number(sb->s_magic, &native, &version, &longnames)) {
[7a96476]156 /*This is a V1 or V2 Minix filesystem*/
[953a823]157 magic = sb->s_magic;
[245eb02d]158 goto recognized;
159 }
160
[953a823]161 if (!check_magic_number(sb3->s_magic, &native, &version, &longnames)) {
[92dd5c8]162 mfsdebug("magic number not recognized\n");
[9e3dc95]163 block_fini(devmap_handle);
164 async_answer_0(rid, ENOTSUP);
165 return;
166 }
[92dd5c8]167
[7a96476]168 /*This is a V3 Minix filesystem*/
169
[953a823]170 magic = sb3->s_magic;
[245eb02d]171
172recognized:
173
174 mfsdebug("magic number recognized = %04x\n", magic);
[953a823]175
176 /*Fill superblock info structure*/
177
178 sbi->fs_version = version;
179 sbi->long_names = longnames;
180 sbi->native = native;
181 sbi->magic = magic;
[ef76d72]182 sbi->isearch = 0;
183 sbi->zsearch = 0;
[953a823]184
185 if (version == MFS_VERSION_V3) {
186 sbi->ninodes = conv32(native, sb3->s_ninodes);
187 sbi->ibmap_blocks = conv16(native, sb3->s_ibmap_blocks);
188 sbi->zbmap_blocks = conv16(native, sb3->s_zbmap_blocks);
189 sbi->firstdatazone = conv16(native, sb3->s_first_data_zone);
190 sbi->log2_zone_size = conv16(native, sb3->s_log2_zone_size);
191 sbi->max_file_size = conv32(native, sb3->s_max_file_size);
192 sbi->nzones = conv32(native, sb3->s_nzones);
193 sbi->block_size = conv16(native, sb3->s_block_size);
[10eb754]194 sbi->ino_per_block = V3_INODES_PER_BLOCK(sbi->block_size);
[a04b62d]195 sbi->dirsize = MFS3_DIRSIZE;
[bd64680]196 sbi->max_name_len = MFS3_MAX_NAME_LEN;
[953a823]197 } else {
198 sbi->ninodes = conv16(native, sb->s_ninodes);
199 sbi->ibmap_blocks = conv16(native, sb->s_ibmap_blocks);
200 sbi->zbmap_blocks = conv16(native, sb->s_zbmap_blocks);
201 sbi->firstdatazone = conv16(native, sb->s_first_data_zone);
202 sbi->log2_zone_size = conv16(native, sb->s_log2_zone_size);
203 sbi->max_file_size = conv32(native, sb->s_max_file_size);
[3b08178]204 sbi->block_size = MFS_BLOCKSIZE;
[5a841a4]205 if (version == MFS_VERSION_V2) {
[953a823]206 sbi->nzones = conv32(native, sb->s_nzones2);
[5a841a4]207 sbi->ino_per_block = V2_INODES_PER_BLOCK;
208 } else {
209 sbi->nzones = conv16(native, sb->s_nzones);
210 sbi->ino_per_block = V1_INODES_PER_BLOCK;
211 }
[a04b62d]212 sbi->dirsize = longnames ? MFSL_DIRSIZE : MFS_DIRSIZE;
[bd64680]213 sbi->max_name_len = longnames ? MFS_L_MAX_NAME_LEN :
[44c6091f]214 MFS_MAX_NAME_LEN;
[953a823]215 }
[10eb754]216 sbi->itable_off = 2 + sbi->ibmap_blocks + sbi->zbmap_blocks;
[44c6091f]217
[953a823]218 free(sb);
219
[586f123]220 rc = block_cache_init(devmap_handle, sbi->block_size, 0, cmode);
[3b08178]221
222 if (rc != EOK) {
223 block_fini(devmap_handle);
224 async_answer_0(rid, EINVAL);
225 mfsdebug("block cache initialization failed\n");
226 return;
227 }
228
[953a823]229 /*Initialize the instance structure and add it to the list*/
230 link_initialize(&instance->link);
231 instance->handle = devmap_handle;
232 instance->sbi = sbi;
233
234 fibril_mutex_lock(&inst_list_mutex);
235 list_append(&instance->link, &inst_list);
236 fibril_mutex_unlock(&inst_list_mutex);
237
238 mfsdebug("mount successful\n");
239
240 async_answer_0(rid, EOK);
[9e3dc95]241}
242
[3b08178]243void mfs_mount(ipc_callid_t rid, ipc_call_t *request)
244{
245 libfs_mount(&mfs_libfs_ops, mfs_reg.fs_handle, rid, request);
246}
247
[e54ba607]248devmap_handle_t mfs_device_get(fs_node_t *fsnode)
249{
250 struct mfs_node *node = fsnode->data;
251 return node->instance->handle;
252}
253
[10eb754]254static int mfs_create_node(fs_node_t **rfn, devmap_handle_t handle, int flags)
255{
[88ccd8b8]256 int r;
257 struct mfs_instance *inst;
258 struct mfs_node *mnode;
259 fs_node_t *fsnode;
260 uint32_t inum;
[44c6091f]261
[10eb754]262 mfsdebug("create_node()\n");
[88ccd8b8]263
264 r = mfs_instance_get(handle, &inst);
[cfac897]265 on_error(r, return r);
[88ccd8b8]266
267 /*Alloc a new inode*/
268 r = mfs_alloc_bit(inst, &inum, BMAP_INODE);
[cfac897]269 on_error(r, return r);
[88ccd8b8]270
271 struct mfs_ino_info *ino_i;
272
273 ino_i = malloc(sizeof(*ino_i));
274 if (!ino_i) {
275 r = ENOMEM;
276 goto out_err;
277 }
278
279 mnode = malloc(sizeof(*mnode));
280 if (!mnode) {
281 r = ENOMEM;
282 goto out_err_1;
283 }
[44c6091f]284
[88ccd8b8]285 fsnode = malloc(sizeof(fs_node_t));
286 if (!fsnode) {
287 r = ENOMEM;
288 goto out_err_2;
289 }
290
[13ecdac9]291 if (flags & L_DIRECTORY)
292 ino_i->i_mode = S_IFDIR;
293 else
294 ino_i->i_mode = S_IFREG;
295
[88ccd8b8]296 ino_i->i_nlinks = 1;
297 ino_i->i_uid = 0;
298 ino_i->i_gid = 0;
299 ino_i->i_size = 0;
300 ino_i->i_atime = 0;
301 ino_i->i_mtime = 0;
302 ino_i->i_ctime = 0;
303
304 memset(ino_i->i_dzone, 0, sizeof(uint32_t) * V2_NR_DIRECT_ZONES);
305 memset(ino_i->i_izone, 0, sizeof(uint32_t) * V2_NR_INDIRECT_ZONES);
306
[58c36ac]307 mfsdebug("new node idx = %d\n", (int) inum);
308
[88ccd8b8]309 ino_i->index = inum;
310 ino_i->dirty = true;
311 mnode->ino_i = ino_i;
312 mnode->instance = inst;
313
[58c36ac]314 r = put_inode(mnode);
[cfac897]315 on_error(r, goto out_err_2);
[88ccd8b8]316
317 fs_node_initialize(fsnode);
318 fsnode->data = mnode;
319 *rfn = fsnode;
320
321 return EOK;
322
323out_err_2:
324 free(mnode);
325out_err_1:
326 free(ino_i);
327out_err:
328 return r;
[10eb754]329}
330
[bd64680]331static int mfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
332{
333 struct mfs_node *mnode = pfn->data;
334 struct mfs_ino_info *ino_i = mnode->ino_i;
335 struct mfs_dentry_info *d_info;
[488f7ed]336 int r;
[bd64680]337
[534d08e8]338 mfsdebug("mfs_match()\n");
339
[bd64680]340 if (!S_ISDIR(ino_i->i_mode))
341 return ENOTDIR;
342
343 struct mfs_sb_info *sbi = mnode->instance->sbi;
344 const size_t comp_size = str_size(component);
345
346 int i = 2;
347 while (1) {
[488f7ed]348 r = read_directory_entry(mnode, &d_info, i++);
[cfac897]349 on_error(r, return r);
[488f7ed]350
[bd64680]351 if (!d_info) {
352 /*Reached the end of the directory entry list*/
353 break;
354 }
355
356 if (!d_info->d_inum) {
357 /*This entry is not used*/
[9cd199c]358 free(d_info);
[bd64680]359 continue;
360 }
361
362 if (!bcmp(component, d_info->d_name, min(sbi->max_name_len,
363 comp_size))) {
364 /*Hit!*/
365 mfs_node_core_get(rfn, mnode->instance,
[44c6091f]366 d_info->d_inum);
[9cd199c]367 free(d_info);
[bd64680]368 goto found;
369 }
[9cd199c]370 free(d_info);
[bd64680]371 }
372 *rfn = NULL;
373found:
374 return EOK;
375}
376
[ac28650]377static aoff64_t mfs_size_get(fs_node_t *node)
[0d6ab10]378{
379 assert(node);
380
381 const struct mfs_node *mnode = node->data;
382 assert(mnode);
[155f792]383 assert(mnode->ino_i);
[0d6ab10]384
[155f792]385 return mnode->ino_i->i_size;
[0d6ab10]386}
387
388void mfs_stat(ipc_callid_t rid, ipc_call_t *request)
389{
390 libfs_stat(&mfs_libfs_ops, mfs_reg.fs_handle, rid, request);
391}
392
[ac28650]393static int mfs_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle,
[44c0f5b]394 fs_index_t index)
395{
396 int rc;
397 struct mfs_instance *instance;
398
399 rc = mfs_instance_get(devmap_handle, &instance);
[cfac897]400 on_error(rc, return rc);
[44c0f5b]401
402 return mfs_node_core_get(rfn, instance, index);
403}
404
[41202a9]405static int mfs_node_put(fs_node_t *fsnode)
406{
407 struct mfs_node *mnode = fsnode->data;
408
[ae8541d]409 put_inode(mnode);
[41202a9]410 free(mnode->ino_i);
411 free(mnode);
412
413 return EOK;
414}
415
416static int mfs_node_open(fs_node_t *fsnode)
417{
418 /*
419 * Opening a file is stateless, nothing
420 * to be done here.
421 */
422 return EOK;
423}
424
425static fs_index_t mfs_index_get(fs_node_t *fsnode)
426{
427 struct mfs_node *mnode = fsnode->data;
428
429 assert(mnode->ino_i);
430 return mnode->ino_i->index;
431}
432
433static unsigned mfs_lnkcnt_get(fs_node_t *fsnode)
434{
435 unsigned rc;
436 struct mfs_node *mnode = fsnode->data;
437
438 assert(mnode);
439 assert(mnode->ino_i);
440
441 rc = mnode->ino_i->i_nlinks;
442 return rc;
443}
444
[44c0f5b]445static int mfs_node_core_get(fs_node_t **rfn, struct mfs_instance *inst,
[44c6091f]446 fs_index_t index)
[44c0f5b]447{
448 fs_node_t *node = NULL;
449 struct mfs_node *mnode = NULL;
450 int rc;
451
[b438804]452 node = malloc(sizeof(fs_node_t));
[44c0f5b]453 if (!node) {
454 rc = ENOMEM;
455 goto out_err;
456 }
457
458 fs_node_initialize(node);
459
[b438804]460 mnode = malloc(sizeof(*mnode));
[44c0f5b]461 if (!mnode) {
462 rc = ENOMEM;
463 goto out_err;
464 }
465
[155f792]466 struct mfs_ino_info *ino_i;
467
[c922bc7]468 rc = get_inode(inst, &ino_i, index);
[cfac897]469 on_error(rc, goto out_err);
[155f792]470
[41202a9]471 ino_i->index = index;
[155f792]472 mnode->ino_i = ino_i;
473
[44c0f5b]474 mnode->instance = inst;
475 node->data = mnode;
476 *rfn = node;
477
478 return EOK;
479
480out_err:
481 if (node)
482 free(node);
483 if (mnode)
484 free(mnode);
485 return rc;
486}
487
[ac28650]488static bool mfs_is_directory(fs_node_t *fsnode)
[5a58ae2]489{
[44c0f5b]490 const struct mfs_node *node = fsnode->data;
[155f792]491 return S_ISDIR(node->ino_i->i_mode);
[5a58ae2]492}
493
[ac28650]494static bool mfs_is_file(fs_node_t *fsnode)
[7d04324]495{
496 struct mfs_node *node = fsnode->data;
[155f792]497 return S_ISREG(node->ino_i->i_mode);
[7d04324]498}
499
[ac28650]500static int mfs_root_get(fs_node_t **rfn, devmap_handle_t handle)
[fe4ac35]501{
[41202a9]502 int rc = mfs_node_get(rfn, handle, MFS_ROOT_INO);
503 return rc;
[fe4ac35]504}
505
[54caa41b]506void mfs_lookup(ipc_callid_t rid, ipc_call_t *request)
507{
508 libfs_lookup(&mfs_libfs_ops, mfs_reg.fs_handle, rid, request);
509}
510
[ac28650]511static char mfs_plb_get_char(unsigned pos)
[cfbcd86]512{
513 return mfs_reg.plb_ro[pos % PLB_SIZE];
514}
515
[88ccd8b8]516static int mfs_link(fs_node_t *pfn, fs_node_t *cfn, const char *name)
517{
[afd9c3b]518 struct mfs_node *parent = pfn->data;
519 struct mfs_node *child = cfn->data;
[48de019]520 struct mfs_sb_info *sbi = parent->instance->sbi;
521
[bb7e8382]522 mfsdebug("mfs_link() %d\n", (int) child->ino_i->index);
523
[48de019]524 if (str_size(name) > sbi->max_name_len)
525 return ENAMETOOLONG;
[afd9c3b]526
527 int r = insert_dentry(parent, name, child->ino_i->index);
[13ecdac9]528 on_error(r, goto exit_error);
529
530 if (S_ISDIR(child->ino_i->i_mode)) {
531 r = insert_dentry(child, ".", child->ino_i->index);
532 on_error(r, goto exit_error);
533 r = insert_dentry(child, "..", parent->ino_i->index);
534 }
[afd9c3b]535
[13ecdac9]536exit_error:
[afd9c3b]537 return r;
[88ccd8b8]538}
539
[ac28650]540static int mfs_has_children(bool *has_children, fs_node_t *fsnode)
[54caa41b]541{
542 struct mfs_node *mnode = fsnode->data;
[488f7ed]543 int r;
[54caa41b]544
545 *has_children = false;
546
547 if (!S_ISDIR(mnode->ino_i->i_mode))
548 goto out;
549
550 struct mfs_dentry_info *d_info;
[44c6091f]551
[ac28650]552 /* The first two dentries are always . and .. */
553 int i = 2;
554 while (1) {
[488f7ed]555 r = read_directory_entry(mnode, &d_info, i++);
[cfac897]556 on_error(r, return r);
[54caa41b]557
[7a96476]558 if (!d_info) {
559 /*Reached the end of the dentries list*/
[152610a8]560 break;
[7a96476]561 }
[54caa41b]562
563 if (d_info->d_inum) {
[7a96476]564 /*A valid entry has been found*/
[54caa41b]565 *has_children = true;
566 free(d_info);
567 break;
568 }
569
570 free(d_info);
571 }
572
[41202a9]573out:
574
[54caa41b]575 return EOK;
576}
577
[668f1949]578void
579mfs_read(ipc_callid_t rid, ipc_call_t *request)
580{
581 int rc;
582 devmap_handle_t handle = (devmap_handle_t) IPC_GET_ARG1(*request);
583 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
584 aoff64_t pos = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request),
[44c6091f]585 IPC_GET_ARG4(*request));
[668f1949]586 fs_node_t *fn;
587
[58c36ac]588 mfsdebug("mfs_read()\n");
589
[668f1949]590 rc = mfs_node_get(&fn, handle, index);
591 if (rc != EOK) {
592 async_answer_0(rid, rc);
593 return;
594 }
595 if (!fn) {
596 async_answer_0(rid, ENOENT);
597 return;
598 }
599
600 struct mfs_node *mnode;
601 struct mfs_ino_info *ino_i;
602 size_t len, bytes = 0;
603 ipc_callid_t callid;
604
605 mnode = fn->data;
606 ino_i = mnode->ino_i;
607
608 if (!async_data_read_receive(&callid, &len)) {
[230229de]609 rc = EINVAL;
610 goto out_error;
[668f1949]611 }
612
613 if (S_ISDIR(ino_i->i_mode)) {
614 aoff64_t spos = pos;
615 struct mfs_dentry_info *d_info;
616
617 while (1) {
[488f7ed]618 rc = read_directory_entry(mnode, &d_info, pos);
[cfac897]619 on_error(rc, goto out_error);
[488f7ed]620
[668f1949]621 if (!d_info) {
622 /*Reached the end of the dentries list*/
623 break;
624 }
625
626 if (d_info->d_inum) {
627 /*Dentry found!*/
628 mfsdebug("DENTRY FOUND %s!!\n", d_info->d_name);
629 goto found;
630 }
631
632 free(d_info);
633 pos++;
634 }
635
636 rc = mfs_node_put(fn);
637 async_answer_0(callid, rc != EOK ? rc : ENOENT);
638 async_answer_1(rid, rc != EOK ? rc : ENOENT, 0);
639 return;
640found:
641 async_data_read_finalize(callid, d_info->d_name,
[44c6091f]642 str_size(d_info->d_name) + 1);
[668f1949]643 bytes = ((pos - spos) + 1);
[230229de]644 } else {
645 struct mfs_sb_info *sbi = mnode->instance->sbi;
646
647 if (pos >= (size_t) ino_i->i_size) {
648 /*Trying to read beyond the end of file*/
649 bytes = 0;
650 (void) async_data_read_finalize(callid, NULL, 0);
651 goto out_success;
652 }
653
654 bytes = min(len, sbi->block_size - pos % sbi->block_size);
655 bytes = min(bytes, ino_i->i_size - pos);
656
657 uint32_t zone;
658 block_t *b;
[668f1949]659
[230229de]660 rc = read_map(&zone, mnode, pos);
[cfac897]661 on_error(rc, goto out_error);
[230229de]662
663 if (zone == 0) {
664 /*sparse file*/
665 uint8_t *buf = malloc(sbi->block_size);
666 if (!buf) {
667 rc = ENOMEM;
668 goto out_error;
669 }
[6fc5262]670 memset(buf, 0, sizeof(sbi->block_size));
[230229de]671 async_data_read_finalize(callid,
[44c6091f]672 buf + pos % sbi->block_size, bytes);
[230229de]673 free(buf);
674 goto out_success;
675 }
676
677 rc = block_get(&b, handle, zone, BLOCK_FLAGS_NONE);
[cfac897]678 on_error(rc, goto out_error);
[230229de]679
680 async_data_read_finalize(callid, b->data +
[44c6091f]681 pos % sbi->block_size, bytes);
[230229de]682
683 rc = block_put(b);
684 if (rc != EOK) {
685 mfs_node_put(fn);
686 async_answer_0(rid, rc);
687 return;
688 }
689 }
690out_success:
[668f1949]691 rc = mfs_node_put(fn);
692 async_answer_1(rid, rc, (sysarg_t)bytes);
[230229de]693 return;
[44c6091f]694out_error:
695 ;
[230229de]696 int tmp = mfs_node_put(fn);
697 async_answer_0(callid, tmp != EOK ? tmp : rc);
698 async_answer_0(rid, tmp != EOK ? tmp : rc);
[668f1949]699}
700
[bb7e8382]701void
702mfs_write(ipc_callid_t rid, ipc_call_t *request)
703{
704 mfsdebug("mfs_write()\n");
705
706 devmap_handle_t handle = (devmap_handle_t) IPC_GET_ARG1(*request);
707 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
708 aoff64_t pos = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request),
[44c6091f]709 IPC_GET_ARG4(*request));
[bb7e8382]710
711 fs_node_t *fn;
712 int r;
713 int flags = BLOCK_FLAGS_NONE;
714
715 r = mfs_node_get(&fn, handle, index);
716 if (r != EOK) {
717 async_answer_0(rid, r);
718 return;
719 }
720
721 if (!fn) {
722 async_answer_0(rid, ENOENT);
723 return;
724 }
725
726 ipc_callid_t callid;
727 size_t len;
728
729 if (!async_data_write_receive(&callid, &len)) {
730 r = EINVAL;
731 goto out_err;
732 }
733
734 struct mfs_node *mnode = fn->data;
735 struct mfs_sb_info *sbi = mnode->instance->sbi;
736 struct mfs_ino_info *ino_i = mnode->ino_i;
737 const size_t bs = sbi->block_size;
738 size_t bytes = min(len, bs - pos % bs);
739 size_t boundary = ROUND_UP(ino_i->i_size, bs);
740 uint32_t block;
741
742 if (bytes == bs)
743 flags = BLOCK_FLAGS_NOREAD;
744
745 if (pos < boundary) {
746 r = read_map(&block, mnode, pos);
747 on_error(r, goto out_err);
748
749 if (block == 0) {
750 /*Writing in a sparse block*/
751 r = mfs_alloc_bit(mnode->instance, &block, BMAP_ZONE);
752 on_error(r, goto out_err);
753 flags = BLOCK_FLAGS_NOREAD;
754 }
755 } else {
756 uint32_t dummy;
757
758 r = mfs_alloc_bit(mnode->instance, &block, BMAP_ZONE);
759 on_error(r, goto out_err);
760
761 r = write_map(mnode, pos, block, &dummy);
762 on_error(r, goto out_err);
763 }
764
765 block_t *b;
766 r = block_get(&b, handle, block, flags);
767 on_error(r, goto out_err);
768
769 async_data_write_finalize(callid, b->data + pos % bs, bytes);
770 b->dirty = true;
771
772 r = block_put(b);
773 if (r != EOK) {
774 mfs_node_put(fn);
775 async_answer_0(rid, r);
776 return;
777 }
778
779 ino_i->i_size = pos + bytes;
780 ino_i->dirty = true;
781 r = mfs_node_put(fn);
782 async_answer_2(rid, r, bytes, pos + bytes);
783 return;
784
785out_err:
786 mfs_node_put(fn);
787 async_answer_0(callid, r);
788 async_answer_0(rid, r);
789}
790
[8a49fed]791void
792mfs_truncate(ipc_callid_t rid, ipc_call_t *request)
793{
794 devmap_handle_t handle = (devmap_handle_t) IPC_GET_ARG1(*request);
795 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
796 aoff64_t size = (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request),
797 IPC_GET_ARG4(*request));
798 fs_node_t *fn;
799 int r;
800
801 mfsdebug("mfs_truncate()\n");
802
803 r = mfs_node_get(&fn, handle, index);
804 if (r != EOK) {
805 async_answer_0(rid, r);
806 return;
807 }
808
809 if (!fn) {
810 async_answer_0(rid, r);
811 return;
812 }
813
814 struct mfs_node *mnode = fn->data;
815 struct mfs_ino_info *ino_i = mnode->ino_i;
816
817 if (ino_i->i_size == size)
818 r = EOK;
819 else
820 r = inode_shrink(mnode, ino_i->i_size - size);
821
822 async_answer_0(rid, r);
823 mfs_node_put(fn);
824}
825
[44c0f5b]826int mfs_instance_get(devmap_handle_t handle, struct mfs_instance **instance)
[3b08178]827{
828 link_t *link;
829 struct mfs_instance *instance_ptr;
830
831 fibril_mutex_lock(&inst_list_mutex);
832
833 for (link = inst_list.next; link != &inst_list; link = link->next) {
[bd64680]834 instance_ptr = list_get_instance(link, struct mfs_instance,
[44c6091f]835 link);
836
[3b08178]837 if (instance_ptr->handle == handle) {
838 *instance = instance_ptr;
839 fibril_mutex_unlock(&inst_list_mutex);
840 return EOK;
841 }
842 }
843
844 mfsdebug("Instance not found\n");
845
846 fibril_mutex_unlock(&inst_list_mutex);
847 return EINVAL;
848}
849
[8ceba1e]850static bool check_magic_number(uint16_t magic, bool *native,
[44c6091f]851 mfs_version_t *version, bool *longfilenames)
[9e3dc95]852{
[cfac897]853 bool rc = true;
[8ceba1e]854 *longfilenames = false;
855
[57640e7]856 if (magic == MFS_MAGIC_V1 || magic == MFS_MAGIC_V1R) {
857 *native = magic == MFS_MAGIC_V1;
[9e3dc95]858 *version = MFS_VERSION_V1;
[8ceba1e]859 } else if (magic == MFS_MAGIC_V1L || magic == MFS_MAGIC_V1LR) {
860 *native = magic == MFS_MAGIC_V1L;
861 *version = MFS_VERSION_V1;
862 *longfilenames = true;
[57640e7]863 } else if (magic == MFS_MAGIC_V2 || magic == MFS_MAGIC_V2R) {
864 *native = magic == MFS_MAGIC_V2;
[9e3dc95]865 *version = MFS_VERSION_V2;
[8ceba1e]866 } else if (magic == MFS_MAGIC_V2L || magic == MFS_MAGIC_V2LR) {
867 *native = magic == MFS_MAGIC_V2L;
868 *version = MFS_VERSION_V2;
869 *longfilenames = true;
[57640e7]870 } else if (magic == MFS_MAGIC_V3 || magic == MFS_MAGIC_V3R) {
871 *native = magic == MFS_MAGIC_V3;
[9e3dc95]872 *version = MFS_VERSION_V3;
[cfac897]873 } else
874 rc = false;
[9e3dc95]875
[7a96476]876 return rc;
[096c8835]877}
878
[e700970]879void
880mfs_close(ipc_callid_t rid, ipc_call_t *request)
881{
882 async_answer_0(rid, EOK);
883}
884
885void
886mfs_open_node(ipc_callid_t rid, ipc_call_t *request)
887{
888 libfs_open_node(&mfs_libfs_ops, mfs_reg.fs_handle, rid, request);
889}
890
[096c8835]891/**
892 * @}
[44c6091f]893 */
[096c8835]894
Note: See TracBrowser for help on using the repository browser.