Changes in uspace/srv/fs/fat/fat_ops.c [1313ee9:cca29e3c] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/fat/fat_ops.c
r1313ee9 rcca29e3c 52 52 #include <adt/list.h> 53 53 #include <assert.h> 54 #include <fibril_sync h.h>54 #include <fibril_sync.h> 55 55 #include <sys/mman.h> 56 56 #include <align.h> … … 65 65 static LIST_INITIALIZE(ffn_head); 66 66 67 /*68 * Forward declarations of FAT libfs operations.69 */70 static int fat_root_get(fs_node_t **, dev_handle_t);71 static int fat_match(fs_node_t **, fs_node_t *, const char *);72 static int fat_node_get(fs_node_t **, dev_handle_t, fs_index_t);73 static int fat_node_open(fs_node_t *);74 static int fat_node_put(fs_node_t *);75 static int fat_create_node(fs_node_t **, dev_handle_t, int);76 static int fat_destroy_node(fs_node_t *);77 static int fat_link(fs_node_t *, fs_node_t *, const char *);78 static int fat_unlink(fs_node_t *, fs_node_t *, const char *);79 static int fat_has_children(bool *, fs_node_t *);80 static fs_index_t fat_index_get(fs_node_t *);81 static size_t fat_size_get(fs_node_t *);82 static unsigned fat_lnkcnt_get(fs_node_t *);83 static char fat_plb_get_char(unsigned);84 static bool fat_is_directory(fs_node_t *);85 static bool fat_is_file(fs_node_t *node);86 static dev_handle_t fat_device_get(fs_node_t *node);87 88 /*89 * Helper functions.90 */91 67 static void fat_node_initialize(fat_node_t *node) 92 68 { … … 102 78 } 103 79 104 static intfat_node_sync(fat_node_t *node)80 static void fat_node_sync(fat_node_t *node) 105 81 { 106 82 block_t *b; … … 120 96 rc = _fat_block_get(&b, bs, node->idx->dev_handle, node->idx->pfc, 121 97 (node->idx->pdi * sizeof(fat_dentry_t)) / bps, BLOCK_FLAGS_NONE); 122 if (rc != EOK) 123 return rc; 98 assert(rc == EOK); 124 99 125 100 d = ((fat_dentry_t *)b->data) + (node->idx->pdi % dps); … … 136 111 b->dirty = true; /* need to sync block */ 137 112 rc = block_put(b); 138 return rc;139 } 140 141 static int fat_node_get_new(fat_node_t **nodepp)113 assert(rc == EOK); 114 } 115 116 static fat_node_t *fat_node_get_new(void) 142 117 { 143 118 fs_node_t *fn; 144 119 fat_node_t *nodep; 145 int rc;146 120 147 121 fibril_mutex_lock(&ffn_mutex); … … 159 133 list_remove(&nodep->ffn_link); 160 134 fibril_mutex_unlock(&ffn_mutex); 161 if (nodep->dirty) { 162 rc = fat_node_sync(nodep); 163 if (rc != EOK) { 164 idxp_tmp->nodep = NULL; 165 fibril_mutex_unlock(&nodep->lock); 166 fibril_mutex_unlock(&idxp_tmp->lock); 167 free(nodep->bp); 168 free(nodep); 169 return rc; 170 } 171 } 135 if (nodep->dirty) 136 fat_node_sync(nodep); 172 137 idxp_tmp->nodep = NULL; 173 138 fibril_mutex_unlock(&nodep->lock); … … 180 145 fn = (fs_node_t *)malloc(sizeof(fs_node_t)); 181 146 if (!fn) 182 return ENOMEM;147 return NULL; 183 148 nodep = (fat_node_t *)malloc(sizeof(fat_node_t)); 184 149 if (!nodep) { 185 150 free(fn); 186 return ENOMEM;151 return NULL; 187 152 } 188 153 } … … 192 157 nodep->bp = fn; 193 158 194 *nodepp = nodep; 195 return EOK; 159 return nodep; 196 160 } 197 161 … … 200 164 * @param idxp Locked index structure. 201 165 */ 202 static int fat_node_get_core(fat_node_t **nodepp,fat_idx_t *idxp)166 static fat_node_t *fat_node_get_core(fat_idx_t *idxp) 203 167 { 204 168 block_t *b; … … 217 181 */ 218 182 fibril_mutex_lock(&idxp->nodep->lock); 219 if (!idxp->nodep->refcnt++) { 220 fibril_mutex_lock(&ffn_mutex); 183 if (!idxp->nodep->refcnt++) 221 184 list_remove(&idxp->nodep->ffn_link); 222 fibril_mutex_unlock(&ffn_mutex);223 }224 185 fibril_mutex_unlock(&idxp->nodep->lock); 225 *nodepp = idxp->nodep; 226 return EOK; 186 return idxp->nodep; 227 187 } 228 188 … … 233 193 assert(idxp->pfc); 234 194 235 rc = fat_node_get_new(&nodep);236 if ( rc != EOK)237 return rc;195 nodep = fat_node_get_new(); 196 if (!nodep) 197 return NULL; 238 198 239 199 bs = block_bb_get(idxp->dev_handle); … … 245 205 rc = _fat_block_get(&b, bs, idxp->dev_handle, idxp->pfc, 246 206 (idxp->pdi * sizeof(fat_dentry_t)) / bps, BLOCK_FLAGS_NONE); 247 if (rc != EOK) { 248 (void) fat_node_put(FS_NODE(nodep)); 249 return rc; 250 } 207 assert(rc == EOK); 251 208 252 209 d = ((fat_dentry_t *)b->data) + (idxp->pdi % dps); … … 266 223 rc = fat_clusters_get(&clusters, bs, idxp->dev_handle, 267 224 uint16_t_le2host(d->firstc)); 268 if (rc != EOK) { 269 (void) fat_node_put(FS_NODE(nodep)); 270 return rc; 271 } 225 assert(rc == EOK); 272 226 nodep->size = bps * spc * clusters; 273 227 } else { … … 280 234 281 235 rc = block_put(b); 282 if (rc != EOK) { 283 (void) fat_node_put(FS_NODE(nodep)); 284 return rc; 285 } 236 assert(rc == EOK); 286 237 287 238 /* Link the idx structure with the node structure. */ … … 289 240 idxp->nodep = nodep; 290 241 291 *nodepp = nodep; 292 return EOK; 293 } 242 return nodep; 243 } 244 245 /* 246 * Forward declarations of FAT libfs operations. 247 */ 248 static fs_node_t *fat_node_get(dev_handle_t, fs_index_t); 249 static void fat_node_put(fs_node_t *); 250 static fs_node_t *fat_create_node(dev_handle_t, int); 251 static int fat_destroy_node(fs_node_t *); 252 static int fat_link(fs_node_t *, fs_node_t *, const char *); 253 static int fat_unlink(fs_node_t *, fs_node_t *, const char *); 254 static fs_node_t *fat_match(fs_node_t *, const char *); 255 static fs_index_t fat_index_get(fs_node_t *); 256 static size_t fat_size_get(fs_node_t *); 257 static unsigned fat_lnkcnt_get(fs_node_t *); 258 static bool fat_has_children(fs_node_t *); 259 static fs_node_t *fat_root_get(dev_handle_t); 260 static char fat_plb_get_char(unsigned); 261 static bool fat_is_directory(fs_node_t *); 262 static bool fat_is_file(fs_node_t *node); 294 263 295 264 /* … … 297 266 */ 298 267 299 int fat_root_get(fs_node_t **rfn, dev_handle_t dev_handle) 300 { 301 return fat_node_get(rfn, dev_handle, 0); 302 } 303 304 int fat_match(fs_node_t **rfn, fs_node_t *pfn, const char *component) 268 /** Instantiate a FAT in-core node. */ 269 fs_node_t *fat_node_get(dev_handle_t dev_handle, fs_index_t index) 270 { 271 fat_node_t *nodep; 272 fat_idx_t *idxp; 273 274 idxp = fat_idx_get_by_index(dev_handle, index); 275 if (!idxp) 276 return NULL; 277 /* idxp->lock held */ 278 nodep = fat_node_get_core(idxp); 279 fibril_mutex_unlock(&idxp->lock); 280 return FS_NODE(nodep); 281 } 282 283 void fat_node_put(fs_node_t *fn) 284 { 285 fat_node_t *nodep = FAT_NODE(fn); 286 bool destroy = false; 287 288 fibril_mutex_lock(&nodep->lock); 289 if (!--nodep->refcnt) { 290 if (nodep->idx) { 291 fibril_mutex_lock(&ffn_mutex); 292 list_append(&nodep->ffn_link, &ffn_head); 293 fibril_mutex_unlock(&ffn_mutex); 294 } else { 295 /* 296 * The node does not have any index structure associated 297 * with itself. This can only mean that we are releasing 298 * the node after a failed attempt to allocate the index 299 * structure for it. 300 */ 301 destroy = true; 302 } 303 } 304 fibril_mutex_unlock(&nodep->lock); 305 if (destroy) { 306 free(nodep->bp); 307 free(nodep); 308 } 309 } 310 311 fs_node_t *fat_create_node(dev_handle_t dev_handle, int flags) 312 { 313 fat_idx_t *idxp; 314 fat_node_t *nodep; 315 fat_bs_t *bs; 316 fat_cluster_t mcl, lcl; 317 uint16_t bps; 318 int rc; 319 320 bs = block_bb_get(dev_handle); 321 bps = uint16_t_le2host(bs->bps); 322 if (flags & L_DIRECTORY) { 323 /* allocate a cluster */ 324 rc = fat_alloc_clusters(bs, dev_handle, 1, &mcl, &lcl); 325 if (rc != EOK) 326 return NULL; 327 } 328 329 nodep = fat_node_get_new(); 330 if (!nodep) { 331 (void) fat_free_clusters(bs, dev_handle, mcl); 332 return NULL; 333 } 334 idxp = fat_idx_get_new(dev_handle); 335 if (!idxp) { 336 (void) fat_free_clusters(bs, dev_handle, mcl); 337 fat_node_put(FS_NODE(nodep)); 338 return NULL; 339 } 340 /* idxp->lock held */ 341 if (flags & L_DIRECTORY) { 342 /* Populate the new cluster with unused dentries. */ 343 rc = fat_zero_cluster(bs, dev_handle, mcl); 344 assert(rc == EOK); 345 nodep->type = FAT_DIRECTORY; 346 nodep->firstc = mcl; 347 nodep->size = bps * bs->spc; 348 } else { 349 nodep->type = FAT_FILE; 350 nodep->firstc = FAT_CLST_RES0; 351 nodep->size = 0; 352 } 353 nodep->lnkcnt = 0; /* not linked anywhere */ 354 nodep->refcnt = 1; 355 nodep->dirty = true; 356 357 nodep->idx = idxp; 358 idxp->nodep = nodep; 359 360 fibril_mutex_unlock(&idxp->lock); 361 return FS_NODE(nodep); 362 } 363 364 int fat_destroy_node(fs_node_t *fn) 365 { 366 fat_node_t *nodep = FAT_NODE(fn); 367 fat_bs_t *bs; 368 int rc = EOK; 369 370 /* 371 * The node is not reachable from the file system. This means that the 372 * link count should be zero and that the index structure cannot be 373 * found in the position hash. Obviously, we don't need to lock the node 374 * nor its index structure. 375 */ 376 assert(nodep->lnkcnt == 0); 377 378 /* 379 * The node may not have any children. 380 */ 381 assert(fat_has_children(fn) == false); 382 383 bs = block_bb_get(nodep->idx->dev_handle); 384 if (nodep->firstc != FAT_CLST_RES0) { 385 assert(nodep->size); 386 /* Free all clusters allocated to the node. */ 387 rc = fat_free_clusters(bs, nodep->idx->dev_handle, 388 nodep->firstc); 389 } 390 391 fat_idx_destroy(nodep->idx); 392 free(nodep->bp); 393 free(nodep); 394 return rc; 395 } 396 397 int fat_link(fs_node_t *pfn, fs_node_t *cfn, const char *name) 398 { 399 fat_node_t *parentp = FAT_NODE(pfn); 400 fat_node_t *childp = FAT_NODE(cfn); 401 fat_dentry_t *d; 402 fat_bs_t *bs; 403 block_t *b; 404 unsigned i, j; 405 uint16_t bps; 406 unsigned dps; 407 unsigned blocks; 408 fat_cluster_t mcl, lcl; 409 int rc; 410 411 fibril_mutex_lock(&childp->lock); 412 if (childp->lnkcnt == 1) { 413 /* 414 * On FAT, we don't support multiple hard links. 415 */ 416 fibril_mutex_unlock(&childp->lock); 417 return EMLINK; 418 } 419 assert(childp->lnkcnt == 0); 420 fibril_mutex_unlock(&childp->lock); 421 422 if (!fat_dentry_name_verify(name)) { 423 /* 424 * Attempt to create unsupported name. 425 */ 426 return ENOTSUP; 427 } 428 429 /* 430 * Get us an unused parent node's dentry or grow the parent and allocate 431 * a new one. 432 */ 433 434 fibril_mutex_lock(&parentp->idx->lock); 435 bs = block_bb_get(parentp->idx->dev_handle); 436 bps = uint16_t_le2host(bs->bps); 437 dps = bps / sizeof(fat_dentry_t); 438 439 blocks = parentp->size / bps; 440 441 for (i = 0; i < blocks; i++) { 442 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 443 assert(rc == EOK); 444 for (j = 0; j < dps; j++) { 445 d = ((fat_dentry_t *)b->data) + j; 446 switch (fat_classify_dentry(d)) { 447 case FAT_DENTRY_SKIP: 448 case FAT_DENTRY_VALID: 449 /* skipping used and meta entries */ 450 continue; 451 case FAT_DENTRY_FREE: 452 case FAT_DENTRY_LAST: 453 /* found an empty slot */ 454 goto hit; 455 } 456 } 457 rc = block_put(b); 458 assert(rc == EOK); 459 } 460 j = 0; 461 462 /* 463 * We need to grow the parent in order to create a new unused dentry. 464 */ 465 if (parentp->firstc == FAT_CLST_ROOT) { 466 /* Can't grow the root directory. */ 467 fibril_mutex_unlock(&parentp->idx->lock); 468 return ENOSPC; 469 } 470 rc = fat_alloc_clusters(bs, parentp->idx->dev_handle, 1, &mcl, &lcl); 471 if (rc != EOK) { 472 fibril_mutex_unlock(&parentp->idx->lock); 473 return rc; 474 } 475 rc = fat_zero_cluster(bs, parentp->idx->dev_handle, mcl); 476 assert(rc == EOK); 477 rc = fat_append_clusters(bs, parentp, mcl); 478 assert(rc == EOK); 479 parentp->size += bps * bs->spc; 480 parentp->dirty = true; /* need to sync node */ 481 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 482 assert(rc == EOK); 483 d = (fat_dentry_t *)b->data; 484 485 hit: 486 /* 487 * At this point we only establish the link between the parent and the 488 * child. The dentry, except of the name and the extension, will remain 489 * uninitialized until the corresponding node is synced. Thus the valid 490 * dentry data is kept in the child node structure. 491 */ 492 memset(d, 0, sizeof(fat_dentry_t)); 493 fat_dentry_name_set(d, name); 494 b->dirty = true; /* need to sync block */ 495 rc = block_put(b); 496 assert(rc == EOK); 497 fibril_mutex_unlock(&parentp->idx->lock); 498 499 fibril_mutex_lock(&childp->idx->lock); 500 501 /* 502 * If possible, create the Sub-directory Identifier Entry and the 503 * Sub-directory Parent Pointer Entry (i.e. "." and ".."). These entries 504 * are not mandatory according to Standard ECMA-107 and HelenOS VFS does 505 * not use them anyway, so this is rather a sign of our good will. 506 */ 507 rc = fat_block_get(&b, bs, childp, 0, BLOCK_FLAGS_NONE); 508 assert(rc == EOK); 509 d = (fat_dentry_t *)b->data; 510 if (fat_classify_dentry(d) == FAT_DENTRY_LAST || 511 str_cmp(d->name, FAT_NAME_DOT) == 0) { 512 memset(d, 0, sizeof(fat_dentry_t)); 513 str_cpy(d->name, 8, FAT_NAME_DOT); 514 str_cpy(d->ext, 3, FAT_EXT_PAD); 515 d->attr = FAT_ATTR_SUBDIR; 516 d->firstc = host2uint16_t_le(childp->firstc); 517 /* TODO: initialize also the date/time members. */ 518 } 519 d++; 520 if (fat_classify_dentry(d) == FAT_DENTRY_LAST || 521 str_cmp(d->name, FAT_NAME_DOT_DOT) == 0) { 522 memset(d, 0, sizeof(fat_dentry_t)); 523 str_cpy(d->name, 8, FAT_NAME_DOT_DOT); 524 str_cpy(d->ext, 3, FAT_EXT_PAD); 525 d->attr = FAT_ATTR_SUBDIR; 526 d->firstc = (parentp->firstc == FAT_CLST_ROOT) ? 527 host2uint16_t_le(FAT_CLST_RES0) : 528 host2uint16_t_le(parentp->firstc); 529 /* TODO: initialize also the date/time members. */ 530 } 531 b->dirty = true; /* need to sync block */ 532 rc = block_put(b); 533 assert(rc == EOK); 534 535 childp->idx->pfc = parentp->firstc; 536 childp->idx->pdi = i * dps + j; 537 fibril_mutex_unlock(&childp->idx->lock); 538 539 fibril_mutex_lock(&childp->lock); 540 childp->lnkcnt = 1; 541 childp->dirty = true; /* need to sync node */ 542 fibril_mutex_unlock(&childp->lock); 543 544 /* 545 * Hash in the index structure into the position hash. 546 */ 547 fat_idx_hashin(childp->idx); 548 549 return EOK; 550 } 551 552 int fat_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *nm) 553 { 554 fat_node_t *parentp = FAT_NODE(pfn); 555 fat_node_t *childp = FAT_NODE(cfn); 556 fat_bs_t *bs; 557 fat_dentry_t *d; 558 uint16_t bps; 559 block_t *b; 560 int rc; 561 562 if (!parentp) 563 return EBUSY; 564 565 if (fat_has_children(cfn)) 566 return ENOTEMPTY; 567 568 fibril_mutex_lock(&parentp->lock); 569 fibril_mutex_lock(&childp->lock); 570 assert(childp->lnkcnt == 1); 571 fibril_mutex_lock(&childp->idx->lock); 572 bs = block_bb_get(childp->idx->dev_handle); 573 bps = uint16_t_le2host(bs->bps); 574 575 rc = _fat_block_get(&b, bs, childp->idx->dev_handle, childp->idx->pfc, 576 (childp->idx->pdi * sizeof(fat_dentry_t)) / bps, 577 BLOCK_FLAGS_NONE); 578 assert(rc == EOK); 579 d = (fat_dentry_t *)b->data + 580 (childp->idx->pdi % (bps / sizeof(fat_dentry_t))); 581 /* mark the dentry as not-currently-used */ 582 d->name[0] = FAT_DENTRY_ERASED; 583 b->dirty = true; /* need to sync block */ 584 rc = block_put(b); 585 assert(rc == EOK); 586 587 /* remove the index structure from the position hash */ 588 fat_idx_hashout(childp->idx); 589 /* clear position information */ 590 childp->idx->pfc = FAT_CLST_RES0; 591 childp->idx->pdi = 0; 592 fibril_mutex_unlock(&childp->idx->lock); 593 childp->lnkcnt = 0; 594 childp->dirty = true; 595 fibril_mutex_unlock(&childp->lock); 596 fibril_mutex_unlock(&parentp->lock); 597 598 return EOK; 599 } 600 601 fs_node_t *fat_match(fs_node_t *pfn, const char *component) 305 602 { 306 603 fat_bs_t *bs; … … 322 619 for (i = 0; i < blocks; i++) { 323 620 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 324 if (rc != EOK) { 325 fibril_mutex_unlock(&parentp->idx->lock); 326 return rc; 327 } 621 assert(rc == EOK); 328 622 for (j = 0; j < dps; j++) { 329 623 d = ((fat_dentry_t *)b->data) + j; … … 333 627 continue; 334 628 case FAT_DENTRY_LAST: 335 /* miss */336 629 rc = block_put(b); 630 assert(rc == EOK); 337 631 fibril_mutex_unlock(&parentp->idx->lock); 338 *rfn = NULL; 339 return rc; 632 return NULL; 340 633 default: 341 634 case FAT_DENTRY_VALID: … … 362 655 */ 363 656 rc = block_put(b); 364 return (rc == EOK) ? ENOMEM : rc; 657 assert(rc == EOK); 658 return NULL; 365 659 } 366 rc = fat_node_get_core(&nodep,idx);660 nodep = fat_node_get_core(idx); 367 661 fibril_mutex_unlock(&idx->lock); 368 if (rc != EOK) {369 (void) block_put(b);370 return rc;371 }372 *rfn = FS_NODE(nodep);373 662 rc = block_put(b); 374 if (rc != EOK) 375 (void) fat_node_put(*rfn); 376 return rc; 663 assert(rc == EOK); 664 return FS_NODE(nodep); 377 665 } 378 666 } 379 667 rc = block_put(b); 380 if (rc != EOK) { 381 fibril_mutex_unlock(&parentp->idx->lock); 382 return rc; 383 } 668 assert(rc == EOK); 384 669 } 385 670 386 671 fibril_mutex_unlock(&parentp->idx->lock); 387 *rfn = NULL; 388 return EOK; 389 } 390 391 /** Instantiate a FAT in-core node. */ 392 int fat_node_get(fs_node_t **rfn, dev_handle_t dev_handle, fs_index_t index) 393 { 394 fat_node_t *nodep; 395 fat_idx_t *idxp; 396 int rc; 397 398 idxp = fat_idx_get_by_index(dev_handle, index); 399 if (!idxp) { 400 *rfn = NULL; 401 return EOK; 402 } 403 /* idxp->lock held */ 404 rc = fat_node_get_core(&nodep, idxp); 405 fibril_mutex_unlock(&idxp->lock); 406 if (rc == EOK) 407 *rfn = FS_NODE(nodep); 408 return rc; 409 } 410 411 int fat_node_open(fs_node_t *fn) 412 { 413 /* 414 * Opening a file is stateless, nothing 415 * to be done here. 416 */ 417 return EOK; 418 } 419 420 int fat_node_put(fs_node_t *fn) 421 { 422 fat_node_t *nodep = FAT_NODE(fn); 423 bool destroy = false; 424 425 fibril_mutex_lock(&nodep->lock); 426 if (!--nodep->refcnt) { 427 if (nodep->idx) { 428 fibril_mutex_lock(&ffn_mutex); 429 list_append(&nodep->ffn_link, &ffn_head); 430 fibril_mutex_unlock(&ffn_mutex); 431 } else { 432 /* 433 * The node does not have any index structure associated 434 * with itself. This can only mean that we are releasing 435 * the node after a failed attempt to allocate the index 436 * structure for it. 437 */ 438 destroy = true; 439 } 440 } 441 fibril_mutex_unlock(&nodep->lock); 442 if (destroy) { 443 free(nodep->bp); 444 free(nodep); 445 } 446 return EOK; 447 } 448 449 int fat_create_node(fs_node_t **rfn, dev_handle_t dev_handle, int flags) 450 { 451 fat_idx_t *idxp; 452 fat_node_t *nodep; 453 fat_bs_t *bs; 454 fat_cluster_t mcl, lcl; 455 uint16_t bps; 456 int rc; 457 458 bs = block_bb_get(dev_handle); 459 bps = uint16_t_le2host(bs->bps); 460 if (flags & L_DIRECTORY) { 461 /* allocate a cluster */ 462 rc = fat_alloc_clusters(bs, dev_handle, 1, &mcl, &lcl); 463 if (rc != EOK) 464 return rc; 465 /* populate the new cluster with unused dentries */ 466 rc = fat_zero_cluster(bs, dev_handle, mcl); 467 if (rc != EOK) { 468 (void) fat_free_clusters(bs, dev_handle, mcl); 469 return rc; 470 } 471 } 472 473 rc = fat_node_get_new(&nodep); 474 if (rc != EOK) { 475 (void) fat_free_clusters(bs, dev_handle, mcl); 476 return rc; 477 } 478 rc = fat_idx_get_new(&idxp, dev_handle); 479 if (rc != EOK) { 480 (void) fat_free_clusters(bs, dev_handle, mcl); 481 (void) fat_node_put(FS_NODE(nodep)); 482 return rc; 483 } 484 /* idxp->lock held */ 485 if (flags & L_DIRECTORY) { 486 nodep->type = FAT_DIRECTORY; 487 nodep->firstc = mcl; 488 nodep->size = bps * bs->spc; 489 } else { 490 nodep->type = FAT_FILE; 491 nodep->firstc = FAT_CLST_RES0; 492 nodep->size = 0; 493 } 494 nodep->lnkcnt = 0; /* not linked anywhere */ 495 nodep->refcnt = 1; 496 nodep->dirty = true; 497 498 nodep->idx = idxp; 499 idxp->nodep = nodep; 500 501 fibril_mutex_unlock(&idxp->lock); 502 *rfn = FS_NODE(nodep); 503 return EOK; 504 } 505 506 int fat_destroy_node(fs_node_t *fn) 507 { 508 fat_node_t *nodep = FAT_NODE(fn); 509 fat_bs_t *bs; 510 bool has_children; 511 int rc; 512 513 /* 514 * The node is not reachable from the file system. This means that the 515 * link count should be zero and that the index structure cannot be 516 * found in the position hash. Obviously, we don't need to lock the node 517 * nor its index structure. 518 */ 519 assert(nodep->lnkcnt == 0); 520 521 /* 522 * The node may not have any children. 523 */ 524 rc = fat_has_children(&has_children, fn); 525 if (rc != EOK) 526 return rc; 527 assert(!has_children); 528 529 bs = block_bb_get(nodep->idx->dev_handle); 530 if (nodep->firstc != FAT_CLST_RES0) { 531 assert(nodep->size); 532 /* Free all clusters allocated to the node. */ 533 rc = fat_free_clusters(bs, nodep->idx->dev_handle, 534 nodep->firstc); 535 } 536 537 fat_idx_destroy(nodep->idx); 538 free(nodep->bp); 539 free(nodep); 540 return rc; 541 } 542 543 int fat_link(fs_node_t *pfn, fs_node_t *cfn, const char *name) 544 { 545 fat_node_t *parentp = FAT_NODE(pfn); 546 fat_node_t *childp = FAT_NODE(cfn); 547 fat_dentry_t *d; 548 fat_bs_t *bs; 549 block_t *b; 550 unsigned i, j; 551 uint16_t bps; 552 unsigned dps; 553 unsigned blocks; 554 fat_cluster_t mcl, lcl; 555 int rc; 556 557 fibril_mutex_lock(&childp->lock); 558 if (childp->lnkcnt == 1) { 559 /* 560 * On FAT, we don't support multiple hard links. 561 */ 562 fibril_mutex_unlock(&childp->lock); 563 return EMLINK; 564 } 565 assert(childp->lnkcnt == 0); 566 fibril_mutex_unlock(&childp->lock); 567 568 if (!fat_dentry_name_verify(name)) { 569 /* 570 * Attempt to create unsupported name. 571 */ 572 return ENOTSUP; 573 } 574 575 /* 576 * Get us an unused parent node's dentry or grow the parent and allocate 577 * a new one. 578 */ 579 580 fibril_mutex_lock(&parentp->idx->lock); 581 bs = block_bb_get(parentp->idx->dev_handle); 582 bps = uint16_t_le2host(bs->bps); 583 dps = bps / sizeof(fat_dentry_t); 584 585 blocks = parentp->size / bps; 586 587 for (i = 0; i < blocks; i++) { 588 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 589 if (rc != EOK) { 590 fibril_mutex_unlock(&parentp->idx->lock); 591 return rc; 592 } 593 for (j = 0; j < dps; j++) { 594 d = ((fat_dentry_t *)b->data) + j; 595 switch (fat_classify_dentry(d)) { 596 case FAT_DENTRY_SKIP: 597 case FAT_DENTRY_VALID: 598 /* skipping used and meta entries */ 599 continue; 600 case FAT_DENTRY_FREE: 601 case FAT_DENTRY_LAST: 602 /* found an empty slot */ 603 goto hit; 604 } 605 } 606 rc = block_put(b); 607 if (rc != EOK) { 608 fibril_mutex_unlock(&parentp->idx->lock); 609 return rc; 610 } 611 } 612 j = 0; 613 614 /* 615 * We need to grow the parent in order to create a new unused dentry. 616 */ 617 if (parentp->firstc == FAT_CLST_ROOT) { 618 /* Can't grow the root directory. */ 619 fibril_mutex_unlock(&parentp->idx->lock); 620 return ENOSPC; 621 } 622 rc = fat_alloc_clusters(bs, parentp->idx->dev_handle, 1, &mcl, &lcl); 623 if (rc != EOK) { 624 fibril_mutex_unlock(&parentp->idx->lock); 625 return rc; 626 } 627 rc = fat_zero_cluster(bs, parentp->idx->dev_handle, mcl); 628 if (rc != EOK) { 629 (void) fat_free_clusters(bs, parentp->idx->dev_handle, mcl); 630 fibril_mutex_unlock(&parentp->idx->lock); 631 return rc; 632 } 633 rc = fat_append_clusters(bs, parentp, mcl); 634 if (rc != EOK) { 635 (void) fat_free_clusters(bs, parentp->idx->dev_handle, mcl); 636 fibril_mutex_unlock(&parentp->idx->lock); 637 return rc; 638 } 639 parentp->size += bps * bs->spc; 640 parentp->dirty = true; /* need to sync node */ 641 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE); 642 if (rc != EOK) { 643 fibril_mutex_unlock(&parentp->idx->lock); 644 return rc; 645 } 646 d = (fat_dentry_t *)b->data; 647 648 hit: 649 /* 650 * At this point we only establish the link between the parent and the 651 * child. The dentry, except of the name and the extension, will remain 652 * uninitialized until the corresponding node is synced. Thus the valid 653 * dentry data is kept in the child node structure. 654 */ 655 memset(d, 0, sizeof(fat_dentry_t)); 656 fat_dentry_name_set(d, name); 657 b->dirty = true; /* need to sync block */ 658 rc = block_put(b); 659 fibril_mutex_unlock(&parentp->idx->lock); 660 if (rc != EOK) 661 return rc; 662 663 fibril_mutex_lock(&childp->idx->lock); 664 665 /* 666 * If possible, create the Sub-directory Identifier Entry and the 667 * Sub-directory Parent Pointer Entry (i.e. "." and ".."). These entries 668 * are not mandatory according to Standard ECMA-107 and HelenOS VFS does 669 * not use them anyway, so this is rather a sign of our good will. 670 */ 671 rc = fat_block_get(&b, bs, childp, 0, BLOCK_FLAGS_NONE); 672 if (rc != EOK) { 673 /* 674 * Rather than returning an error, simply skip the creation of 675 * these two entries. 676 */ 677 goto skip_dots; 678 } 679 d = (fat_dentry_t *)b->data; 680 if (fat_classify_dentry(d) == FAT_DENTRY_LAST || 681 str_cmp(d->name, FAT_NAME_DOT) == 0) { 682 memset(d, 0, sizeof(fat_dentry_t)); 683 str_cpy(d->name, 8, FAT_NAME_DOT); 684 str_cpy(d->ext, 3, FAT_EXT_PAD); 685 d->attr = FAT_ATTR_SUBDIR; 686 d->firstc = host2uint16_t_le(childp->firstc); 687 /* TODO: initialize also the date/time members. */ 688 } 689 d++; 690 if (fat_classify_dentry(d) == FAT_DENTRY_LAST || 691 str_cmp(d->name, FAT_NAME_DOT_DOT) == 0) { 692 memset(d, 0, sizeof(fat_dentry_t)); 693 str_cpy(d->name, 8, FAT_NAME_DOT_DOT); 694 str_cpy(d->ext, 3, FAT_EXT_PAD); 695 d->attr = FAT_ATTR_SUBDIR; 696 d->firstc = (parentp->firstc == FAT_CLST_ROOT) ? 697 host2uint16_t_le(FAT_CLST_RES0) : 698 host2uint16_t_le(parentp->firstc); 699 /* TODO: initialize also the date/time members. */ 700 } 701 b->dirty = true; /* need to sync block */ 702 /* 703 * Ignore the return value as we would have fallen through on error 704 * anyway. 705 */ 706 (void) block_put(b); 707 skip_dots: 708 709 childp->idx->pfc = parentp->firstc; 710 childp->idx->pdi = i * dps + j; 711 fibril_mutex_unlock(&childp->idx->lock); 712 713 fibril_mutex_lock(&childp->lock); 714 childp->lnkcnt = 1; 715 childp->dirty = true; /* need to sync node */ 716 fibril_mutex_unlock(&childp->lock); 717 718 /* 719 * Hash in the index structure into the position hash. 720 */ 721 fat_idx_hashin(childp->idx); 722 723 return EOK; 724 } 725 726 int fat_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *nm) 727 { 728 fat_node_t *parentp = FAT_NODE(pfn); 729 fat_node_t *childp = FAT_NODE(cfn); 730 fat_bs_t *bs; 731 fat_dentry_t *d; 732 uint16_t bps; 733 block_t *b; 734 bool has_children; 735 int rc; 736 737 if (!parentp) 738 return EBUSY; 739 740 rc = fat_has_children(&has_children, cfn); 741 if (rc != EOK) 742 return rc; 743 if (has_children) 744 return ENOTEMPTY; 745 746 fibril_mutex_lock(&parentp->lock); 747 fibril_mutex_lock(&childp->lock); 748 assert(childp->lnkcnt == 1); 749 fibril_mutex_lock(&childp->idx->lock); 750 bs = block_bb_get(childp->idx->dev_handle); 751 bps = uint16_t_le2host(bs->bps); 752 753 rc = _fat_block_get(&b, bs, childp->idx->dev_handle, childp->idx->pfc, 754 (childp->idx->pdi * sizeof(fat_dentry_t)) / bps, 755 BLOCK_FLAGS_NONE); 756 if (rc != EOK) 757 goto error; 758 d = (fat_dentry_t *)b->data + 759 (childp->idx->pdi % (bps / sizeof(fat_dentry_t))); 760 /* mark the dentry as not-currently-used */ 761 d->name[0] = FAT_DENTRY_ERASED; 762 b->dirty = true; /* need to sync block */ 763 rc = block_put(b); 764 if (rc != EOK) 765 goto error; 766 767 /* remove the index structure from the position hash */ 768 fat_idx_hashout(childp->idx); 769 /* clear position information */ 770 childp->idx->pfc = FAT_CLST_RES0; 771 childp->idx->pdi = 0; 772 fibril_mutex_unlock(&childp->idx->lock); 773 childp->lnkcnt = 0; 774 childp->dirty = true; 775 fibril_mutex_unlock(&childp->lock); 776 fibril_mutex_unlock(&parentp->lock); 777 778 return EOK; 779 780 error: 781 fibril_mutex_unlock(&parentp->idx->lock); 782 fibril_mutex_unlock(&childp->lock); 783 fibril_mutex_unlock(&childp->idx->lock); 784 return rc; 785 } 786 787 int fat_has_children(bool *has_children, fs_node_t *fn) 672 return NULL; 673 } 674 675 fs_index_t fat_index_get(fs_node_t *fn) 676 { 677 return FAT_NODE(fn)->idx->index; 678 } 679 680 size_t fat_size_get(fs_node_t *fn) 681 { 682 return FAT_NODE(fn)->size; 683 } 684 685 unsigned fat_lnkcnt_get(fs_node_t *fn) 686 { 687 return FAT_NODE(fn)->lnkcnt; 688 } 689 690 bool fat_has_children(fs_node_t *fn) 788 691 { 789 692 fat_bs_t *bs; … … 796 699 int rc; 797 700 798 if (nodep->type != FAT_DIRECTORY) { 799 *has_children = false; 800 return EOK; 801 } 701 if (nodep->type != FAT_DIRECTORY) 702 return false; 802 703 803 704 fibril_mutex_lock(&nodep->idx->lock); … … 812 713 813 714 rc = fat_block_get(&b, bs, nodep, i, BLOCK_FLAGS_NONE); 814 if (rc != EOK) { 815 fibril_mutex_unlock(&nodep->idx->lock); 816 return rc; 817 } 715 assert(rc == EOK); 818 716 for (j = 0; j < dps; j++) { 819 717 d = ((fat_dentry_t *)b->data) + j; … … 824 722 case FAT_DENTRY_LAST: 825 723 rc = block_put(b); 724 assert(rc == EOK); 826 725 fibril_mutex_unlock(&nodep->idx->lock); 827 *has_children = false; 828 return rc; 726 return false; 829 727 default: 830 728 case FAT_DENTRY_VALID: 831 729 rc = block_put(b); 730 assert(rc == EOK); 832 731 fibril_mutex_unlock(&nodep->idx->lock); 833 *has_children = true; 834 return rc; 732 return true; 835 733 } 734 rc = block_put(b); 735 assert(rc == EOK); 736 fibril_mutex_unlock(&nodep->idx->lock); 737 return true; 836 738 } 837 739 rc = block_put(b); 838 if (rc != EOK) { 839 fibril_mutex_unlock(&nodep->idx->lock); 840 return rc; 841 } 740 assert(rc == EOK); 842 741 } 843 742 844 743 fibril_mutex_unlock(&nodep->idx->lock); 845 *has_children = false; 846 return EOK; 847 } 848 849 850 fs_index_t fat_index_get(fs_node_t *fn) 851 { 852 return FAT_NODE(fn)->idx->index; 853 } 854 855 size_t fat_size_get(fs_node_t *fn) 856 { 857 return FAT_NODE(fn)->size; 858 } 859 860 unsigned fat_lnkcnt_get(fs_node_t *fn) 861 { 862 return FAT_NODE(fn)->lnkcnt; 744 return false; 745 } 746 747 fs_node_t *fat_root_get(dev_handle_t dev_handle) 748 { 749 return fat_node_get(dev_handle, 0); 863 750 } 864 751 … … 876 763 { 877 764 return FAT_NODE(fn)->type == FAT_FILE; 878 }879 880 dev_handle_t fat_device_get(fs_node_t *node)881 {882 return 0;883 765 } 884 766 885 767 /** libfs operations */ 886 768 libfs_ops_t fat_libfs_ops = { 887 .root_get = fat_root_get,888 769 .match = fat_match, 889 770 .node_get = fat_node_get, 890 .node_open = fat_node_open,891 771 .node_put = fat_node_put, 892 772 .create = fat_create_node, … … 894 774 .link = fat_link, 895 775 .unlink = fat_unlink, 896 .has_children = fat_has_children,897 776 .index_get = fat_index_get, 898 777 .size_get = fat_size_get, 899 778 .lnkcnt_get = fat_lnkcnt_get, 900 .plb_get_char = fat_plb_get_char, 779 .has_children = fat_has_children, 780 .root_get = fat_root_get, 781 .plb_get_char = fat_plb_get_char, 901 782 .is_directory = fat_is_directory, 902 .is_file = fat_is_file, 903 .device_get = fat_device_get 783 .is_file = fat_is_file 904 784 }; 905 785 … … 920 800 ipc_callid_t callid; 921 801 size_t size; 922 if (! async_data_write_receive(&callid, &size)) {802 if (!ipc_data_write_receive(&callid, &size)) { 923 803 ipc_answer_0(callid, EINVAL); 924 804 ipc_answer_0(rid, EINVAL); … … 931 811 return; 932 812 } 933 ipcarg_t retval = async_data_write_finalize(callid, opts, size);813 ipcarg_t retval = ipc_data_write_finalize(callid, opts, size); 934 814 if (retval != EOK) { 935 815 ipc_answer_0(rid, retval); … … 953 833 954 834 /* prepare the boot block */ 955 rc = block_bb_read(dev_handle, BS_BLOCK );835 rc = block_bb_read(dev_handle, BS_BLOCK * BS_SIZE, BS_SIZE); 956 836 if (rc != EOK) { 957 837 block_fini(dev_handle); … … 1049 929 fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); 1050 930 off_t pos = (off_t)IPC_GET_ARG3(*request); 1051 fs_node_t *fn ;931 fs_node_t *fn = fat_node_get(dev_handle, index); 1052 932 fat_node_t *nodep; 1053 933 fat_bs_t *bs; … … 1057 937 int rc; 1058 938 1059 rc = fat_node_get(&fn, dev_handle, index);1060 if (rc != EOK) {1061 ipc_answer_0(rid, rc);1062 return;1063 }1064 939 if (!fn) { 1065 940 ipc_answer_0(rid, ENOENT); … … 1070 945 ipc_callid_t callid; 1071 946 size_t len; 1072 if (! async_data_read_receive(&callid, &len)) {947 if (!ipc_data_read_receive(&callid, &len)) { 1073 948 fat_node_put(fn); 1074 949 ipc_answer_0(callid, EINVAL); … … 1089 964 /* reading beyond the EOF */ 1090 965 bytes = 0; 1091 (void) async_data_read_finalize(callid, NULL, 0);966 (void) ipc_data_read_finalize(callid, NULL, 0); 1092 967 } else { 1093 968 bytes = min(len, bps - pos % bps); … … 1095 970 rc = fat_block_get(&b, bs, nodep, pos / bps, 1096 971 BLOCK_FLAGS_NONE); 1097 if (rc != EOK) { 1098 fat_node_put(fn); 1099 ipc_answer_0(callid, rc); 1100 ipc_answer_0(rid, rc); 1101 return; 1102 } 1103 (void) async_data_read_finalize(callid, b->data + pos % bps, 972 assert(rc == EOK); 973 (void) ipc_data_read_finalize(callid, b->data + pos % bps, 1104 974 bytes); 1105 975 rc = block_put(b); 1106 if (rc != EOK) { 1107 fat_node_put(fn); 1108 ipc_answer_0(rid, rc); 1109 return; 1110 } 976 assert(rc == EOK); 1111 977 } 1112 978 } else { … … 1132 998 rc = fat_block_get(&b, bs, nodep, bnum, 1133 999 BLOCK_FLAGS_NONE); 1134 if (rc != EOK) 1135 goto err; 1000 assert(rc == EOK); 1136 1001 for (o = pos % (bps / sizeof(fat_dentry_t)); 1137 1002 o < bps / sizeof(fat_dentry_t); … … 1144 1009 case FAT_DENTRY_LAST: 1145 1010 rc = block_put(b); 1146 if (rc != EOK) 1147 goto err; 1011 assert(rc == EOK); 1148 1012 goto miss; 1149 1013 default: 1150 1014 case FAT_DENTRY_VALID: 1151 1015 fat_dentry_name_get(d, name); 1152 rc = block_put(b); 1153 if (rc != EOK) 1154 goto err; 1016 rc == block_put(b); 1017 assert(rc == EOK); 1155 1018 goto hit; 1156 1019 } 1157 1020 } 1158 1021 rc = block_put(b); 1159 if (rc != EOK) 1160 goto err; 1022 assert(rc == EOK); 1161 1023 bnum++; 1162 1024 } 1163 1025 miss: 1164 rc = fat_node_put(fn); 1165 ipc_answer_0(callid, rc != EOK ? rc : ENOENT); 1166 ipc_answer_1(rid, rc != EOK ? rc : ENOENT, 0); 1167 return; 1168 1169 err: 1170 (void) fat_node_put(fn); 1171 ipc_answer_0(callid, rc); 1172 ipc_answer_0(rid, rc); 1173 return; 1174 1026 fat_node_put(fn); 1027 ipc_answer_0(callid, ENOENT); 1028 ipc_answer_1(rid, ENOENT, 0); 1029 return; 1175 1030 hit: 1176 (void) async_data_read_finalize(callid, name, str_size(name) + 1);1031 (void) ipc_data_read_finalize(callid, name, str_size(name) + 1); 1177 1032 bytes = (pos - spos) + 1; 1178 1033 } 1179 1034 1180 rc =fat_node_put(fn);1181 ipc_answer_1(rid, rc, (ipcarg_t)bytes);1035 fat_node_put(fn); 1036 ipc_answer_1(rid, EOK, (ipcarg_t)bytes); 1182 1037 } 1183 1038 … … 1187 1042 fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); 1188 1043 off_t pos = (off_t)IPC_GET_ARG3(*request); 1189 fs_node_t *fn ;1044 fs_node_t *fn = fat_node_get(dev_handle, index); 1190 1045 fat_node_t *nodep; 1191 1046 fat_bs_t *bs; 1192 size_t bytes , size;1047 size_t bytes; 1193 1048 block_t *b; 1194 1049 uint16_t bps; … … 1199 1054 int rc; 1200 1055 1201 rc = fat_node_get(&fn, dev_handle, index);1202 if (rc != EOK) {1203 ipc_answer_0(rid, rc);1204 return;1205 }1206 1056 if (!fn) { 1207 1057 ipc_answer_0(rid, ENOENT); … … 1212 1062 ipc_callid_t callid; 1213 1063 size_t len; 1214 if (! async_data_write_receive(&callid, &len)) {1215 (void)fat_node_put(fn);1064 if (!ipc_data_write_receive(&callid, &len)) { 1065 fat_node_put(fn); 1216 1066 ipc_answer_0(callid, EINVAL); 1217 1067 ipc_answer_0(rid, EINVAL); … … 1244 1094 */ 1245 1095 rc = fat_fill_gap(bs, nodep, FAT_CLST_RES0, pos); 1246 if (rc != EOK) { 1247 (void) fat_node_put(fn); 1248 ipc_answer_0(callid, rc); 1249 ipc_answer_0(rid, rc); 1250 return; 1251 } 1096 assert(rc == EOK); 1252 1097 rc = fat_block_get(&b, bs, nodep, pos / bps, flags); 1253 if (rc != EOK) { 1254 (void) fat_node_put(fn); 1255 ipc_answer_0(callid, rc); 1256 ipc_answer_0(rid, rc); 1257 return; 1258 } 1259 (void) async_data_write_finalize(callid, b->data + pos % bps, 1098 assert(rc == EOK); 1099 (void) ipc_data_write_finalize(callid, b->data + pos % bps, 1260 1100 bytes); 1261 1101 b->dirty = true; /* need to sync block */ 1262 1102 rc = block_put(b); 1263 if (rc != EOK) { 1264 (void) fat_node_put(fn); 1265 ipc_answer_0(rid, rc); 1266 return; 1267 } 1103 assert(rc == EOK); 1268 1104 if (pos + bytes > nodep->size) { 1269 1105 nodep->size = pos + bytes; 1270 1106 nodep->dirty = true; /* need to sync node */ 1271 1107 } 1272 size = nodep->size; 1273 rc = fat_node_put(fn); 1274 ipc_answer_2(rid, rc, bytes, nodep->size); 1108 ipc_answer_2(rid, EOK, bytes, nodep->size); 1109 fat_node_put(fn); 1275 1110 return; 1276 1111 } else { … … 1279 1114 * clusters for the node and zero them out. 1280 1115 */ 1116 int status; 1281 1117 unsigned nclsts; 1282 1118 fat_cluster_t mcl, lcl; … … 1284 1120 nclsts = (ROUND_UP(pos + bytes, bpc) - boundary) / bpc; 1285 1121 /* create an independent chain of nclsts clusters in all FATs */ 1286 rc= fat_alloc_clusters(bs, dev_handle, nclsts, &mcl, &lcl);1287 if ( rc!= EOK) {1122 status = fat_alloc_clusters(bs, dev_handle, nclsts, &mcl, &lcl); 1123 if (status != EOK) { 1288 1124 /* could not allocate a chain of nclsts clusters */ 1289 (void)fat_node_put(fn);1290 ipc_answer_0(callid, rc);1291 ipc_answer_0(rid, rc);1125 fat_node_put(fn); 1126 ipc_answer_0(callid, status); 1127 ipc_answer_0(rid, status); 1292 1128 return; 1293 1129 } 1294 1130 /* zero fill any gaps */ 1295 1131 rc = fat_fill_gap(bs, nodep, mcl, pos); 1296 if (rc != EOK) { 1297 (void) fat_free_clusters(bs, dev_handle, mcl); 1298 (void) fat_node_put(fn); 1299 ipc_answer_0(callid, rc); 1300 ipc_answer_0(rid, rc); 1301 return; 1302 } 1132 assert(rc == EOK); 1303 1133 rc = _fat_block_get(&b, bs, dev_handle, lcl, (pos / bps) % spc, 1304 1134 flags); 1305 if (rc != EOK) { 1306 (void) fat_free_clusters(bs, dev_handle, mcl); 1307 (void) fat_node_put(fn); 1308 ipc_answer_0(callid, rc); 1309 ipc_answer_0(rid, rc); 1310 return; 1311 } 1312 (void) async_data_write_finalize(callid, b->data + pos % bps, 1135 assert(rc == EOK); 1136 (void) ipc_data_write_finalize(callid, b->data + pos % bps, 1313 1137 bytes); 1314 1138 b->dirty = true; /* need to sync block */ 1315 1139 rc = block_put(b); 1316 if (rc != EOK) { 1317 (void) fat_free_clusters(bs, dev_handle, mcl); 1318 (void) fat_node_put(fn); 1319 ipc_answer_0(rid, rc); 1320 return; 1321 } 1140 assert(rc == EOK); 1322 1141 /* 1323 1142 * Append the cluster chain starting in mcl to the end of the … … 1325 1144 */ 1326 1145 rc = fat_append_clusters(bs, nodep, mcl); 1327 if (rc != EOK) { 1328 (void) fat_free_clusters(bs, dev_handle, mcl); 1329 (void) fat_node_put(fn); 1330 ipc_answer_0(rid, rc); 1331 return; 1332 } 1333 nodep->size = size = pos + bytes; 1146 assert(rc == EOK); 1147 nodep->size = pos + bytes; 1334 1148 nodep->dirty = true; /* need to sync node */ 1335 rc = fat_node_put(fn);1336 ipc_answer_2(rid, rc, bytes, size);1149 ipc_answer_2(rid, EOK, bytes, nodep->size); 1150 fat_node_put(fn); 1337 1151 return; 1338 1152 } … … 1344 1158 fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); 1345 1159 size_t size = (off_t)IPC_GET_ARG3(*request); 1346 fs_node_t *fn ;1160 fs_node_t *fn = fat_node_get(dev_handle, index); 1347 1161 fat_node_t *nodep; 1348 1162 fat_bs_t *bs; … … 1352 1166 int rc; 1353 1167 1354 rc = fat_node_get(&fn, dev_handle, index);1355 if (rc != EOK) {1356 ipc_answer_0(rid, rc);1357 return;1358 }1359 1168 if (!fn) { 1360 1169 ipc_answer_0(rid, ENOENT); … … 1420 1229 dev_handle_t dev_handle = (dev_handle_t)IPC_GET_ARG1(*request); 1421 1230 fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); 1422 fs_node_t *fn;1423 1231 int rc; 1424 1232 1425 rc = fat_node_get(&fn, dev_handle, index); 1426 if (rc != EOK) { 1427 ipc_answer_0(rid, rc); 1428 return; 1429 } 1233 fs_node_t *fn = fat_node_get(dev_handle, index); 1430 1234 if (!fn) { 1431 1235 ipc_answer_0(rid, ENOENT);
Note:
See TracChangeset
for help on using the changeset viewer.