Rev 3625 | Rev 3629 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3625 | Rev 3628 | ||
---|---|---|---|
Line 341... | Line 341... | ||
341 | return EOK; |
341 | return EOK; |
342 | } |
342 | } |
343 | 343 | ||
344 | int fat_link(void *prnt, void *chld, const char *name) |
344 | int fat_link(void *prnt, void *chld, const char *name) |
345 | { |
345 | { |
- | 346 | fat_node_t *parentp = (fat_node_t *)prnt; |
|
- | 347 | fat_node_t *childp = (fat_node_t *)chld; |
|
- | 348 | fat_dentry_t *d; |
|
- | 349 | fat_bs_t *bs; |
|
- | 350 | block_t *b; |
|
- | 351 | int i, j; |
|
- | 352 | uint16_t bps; |
|
- | 353 | unsigned dps; |
|
- | 354 | unsigned blocks; |
|
- | 355 | ||
- | 356 | futex_down(&childp->lock); |
|
- | 357 | if (childp->lnkcnt == 1) { |
|
- | 358 | /* |
|
346 | return ENOTSUP; /* not supported at the moment */ |
359 | * On FAT, we don't support multiple hard links. |
- | 360 | */ |
|
- | 361 | futex_up(&childp->lock); |
|
- | 362 | return EMLINK; |
|
- | 363 | } |
|
- | 364 | assert(childp->lnkcnt == 0); |
|
- | 365 | futex_up(&childp->lock); |
|
- | 366 | ||
- | 367 | if (!fat_dentry_name_verify(name)) { |
|
- | 368 | /* |
|
- | 369 | * Attempt to create unsupported name. |
|
- | 370 | */ |
|
- | 371 | return ENOTSUP; |
|
- | 372 | } |
|
- | 373 | ||
- | 374 | /* |
|
- | 375 | * Get us an unused parent node's dentry or grow the parent and allocate |
|
- | 376 | * a new one. |
|
- | 377 | */ |
|
- | 378 | ||
- | 379 | futex_down(&parentp->idx->lock); |
|
- | 380 | bs = block_bb_get(parentp->idx->dev_handle); |
|
- | 381 | bps = uint16_t_le2host(bs->bps); |
|
- | 382 | dps = bps / sizeof(fat_dentry_t); |
|
- | 383 | ||
- | 384 | blocks = parentp->size / bps; |
|
- | 385 | ||
- | 386 | for (i = 0; i < blocks; i++) { |
|
- | 387 | b = fat_block_get(bs, parentp, i, BLOCK_FLAGS_NONE); |
|
- | 388 | for (j = 0; j < dps; j++) { |
|
- | 389 | d = ((fat_dentry_t *)b->data) + j; |
|
- | 390 | switch (fat_classify_dentry(d)) { |
|
- | 391 | case FAT_DENTRY_SKIP: |
|
- | 392 | case FAT_DENTRY_VALID: |
|
- | 393 | /* skipping used and meta entries */ |
|
- | 394 | continue; |
|
- | 395 | case FAT_DENTRY_FREE: |
|
- | 396 | case FAT_DENTRY_LAST: |
|
- | 397 | /* found an empty slot */ |
|
- | 398 | goto hit; |
|
- | 399 | } |
|
- | 400 | } |
|
- | 401 | block_put(b); |
|
- | 402 | } |
|
- | 403 | ||
- | 404 | /* |
|
- | 405 | * We need to grow the parent in order to create a new unused dentry. |
|
- | 406 | */ |
|
- | 407 | futex_up(&parentp->idx->lock); |
|
- | 408 | return ENOTSUP; /* XXX */ |
|
- | 409 | ||
- | 410 | hit: |
|
- | 411 | /* |
|
- | 412 | * At this point we only establish the link between the parent and the |
|
- | 413 | * child. The dentry, except of the name and the extension, will remain |
|
- | 414 | * uninitialized until the the corresponding node is synced. Thus the |
|
- | 415 | * valid dentry data is kept in the child node structure. |
|
- | 416 | */ |
|
- | 417 | memset(d, 0, sizeof(fat_dentry_t)); |
|
- | 418 | fat_dentry_name_set(d, name); |
|
- | 419 | b->dirty = true; /* need to sync block */ |
|
- | 420 | block_put(b); |
|
- | 421 | futex_up(&parentp->idx->lock); |
|
- | 422 | ||
- | 423 | futex_down(&childp->idx->lock); |
|
- | 424 | childp->idx->pfc = parentp->firstc; |
|
- | 425 | childp->idx->pdi = i * dps + j; |
|
- | 426 | futex_up(&childp->idx->lock); |
|
- | 427 | ||
- | 428 | futex_down(&childp->lock); |
|
- | 429 | childp->lnkcnt = 1; |
|
- | 430 | childp->dirty = true; /* need to sync node */ |
|
- | 431 | futex_up(&childp->lock); |
|
- | 432 | ||
- | 433 | /* |
|
- | 434 | * Hash in the index structure into the position hash. |
|
- | 435 | */ |
|
- | 436 | fat_idx_hashin(childp->idx); |
|
- | 437 | ||
- | 438 | return EOK; |
|
347 | } |
439 | } |
348 | 440 | ||
349 | int fat_unlink(void *prnt, void *chld) |
441 | int fat_unlink(void *prnt, void *chld) |
350 | { |
442 | { |
351 | return ENOTSUP; /* not supported at the moment */ |
443 | return ENOTSUP; /* not supported at the moment */ |
Line 372... | Line 464... | ||
372 | b = fat_block_get(bs, parentp, i, BLOCK_FLAGS_NONE); |
464 | b = fat_block_get(bs, parentp, i, BLOCK_FLAGS_NONE); |
373 | for (j = 0; j < dps; j++) { |
465 | for (j = 0; j < dps; j++) { |
374 | d = ((fat_dentry_t *)b->data) + j; |
466 | d = ((fat_dentry_t *)b->data) + j; |
375 | switch (fat_classify_dentry(d)) { |
467 | switch (fat_classify_dentry(d)) { |
376 | case FAT_DENTRY_SKIP: |
468 | case FAT_DENTRY_SKIP: |
- | 469 | case FAT_DENTRY_FREE: |
|
377 | continue; |
470 | continue; |
378 | case FAT_DENTRY_LAST: |
471 | case FAT_DENTRY_LAST: |
379 | block_put(b); |
472 | block_put(b); |
380 | futex_up(&parentp->idx->lock); |
473 | futex_up(&parentp->idx->lock); |
381 | return NULL; |
474 | return NULL; |
382 | default: |
475 | default: |
383 | case FAT_DENTRY_VALID: |
476 | case FAT_DENTRY_VALID: |
384 | dentry_name_canonify(d, name); |
477 | fat_dentry_name_get(d, name); |
385 | break; |
478 | break; |
386 | } |
479 | } |
387 | if (stricmp(name, component) == 0) { |
480 | if (stricmp(name, component) == 0) { |
388 | /* hit */ |
481 | /* hit */ |
389 | void *node; |
482 | void *node; |
Line 462... | Line 555... | ||
462 | b = fat_block_get(bs, nodep, i, BLOCK_FLAGS_NONE); |
555 | b = fat_block_get(bs, nodep, i, BLOCK_FLAGS_NONE); |
463 | for (j = 0; j < dps; j++) { |
556 | for (j = 0; j < dps; j++) { |
464 | d = ((fat_dentry_t *)b->data) + j; |
557 | d = ((fat_dentry_t *)b->data) + j; |
465 | switch (fat_classify_dentry(d)) { |
558 | switch (fat_classify_dentry(d)) { |
466 | case FAT_DENTRY_SKIP: |
559 | case FAT_DENTRY_SKIP: |
- | 560 | case FAT_DENTRY_FREE: |
|
467 | continue; |
561 | continue; |
468 | case FAT_DENTRY_LAST: |
562 | case FAT_DENTRY_LAST: |
469 | block_put(b); |
563 | block_put(b); |
470 | futex_up(&nodep->idx->lock); |
564 | futex_up(&nodep->idx->lock); |
471 | return false; |
565 | return false; |
Line 696... | Line 790... | ||
696 | o < bps / sizeof(fat_dentry_t); |
790 | o < bps / sizeof(fat_dentry_t); |
697 | o++, pos++) { |
791 | o++, pos++) { |
698 | d = ((fat_dentry_t *)b->data) + o; |
792 | d = ((fat_dentry_t *)b->data) + o; |
699 | switch (fat_classify_dentry(d)) { |
793 | switch (fat_classify_dentry(d)) { |
700 | case FAT_DENTRY_SKIP: |
794 | case FAT_DENTRY_SKIP: |
- | 795 | case FAT_DENTRY_FREE: |
|
701 | continue; |
796 | continue; |
702 | case FAT_DENTRY_LAST: |
797 | case FAT_DENTRY_LAST: |
703 | block_put(b); |
798 | block_put(b); |
704 | goto miss; |
799 | goto miss; |
705 | default: |
800 | default: |
706 | case FAT_DENTRY_VALID: |
801 | case FAT_DENTRY_VALID: |
707 | dentry_name_canonify(d, name); |
802 | fat_dentry_name_get(d, name); |
708 | block_put(b); |
803 | block_put(b); |
709 | goto hit; |
804 | goto hit; |
710 | } |
805 | } |
711 | } |
806 | } |
712 | block_put(b); |
807 | block_put(b); |