Rev 3325 | Rev 3352 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3325 | Rev 3335 | ||
---|---|---|---|
Line 762... | Line 762... | ||
762 | fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); |
762 | fs_index_t index = (fs_index_t)IPC_GET_ARG2(*request); |
763 | off_t pos = (off_t)IPC_GET_ARG3(*request); |
763 | off_t pos = (off_t)IPC_GET_ARG3(*request); |
764 | fat_node_t *nodep = (fat_node_t *)fat_node_get(dev_handle, index); |
764 | fat_node_t *nodep = (fat_node_t *)fat_node_get(dev_handle, index); |
765 | uint16_t bps = fat_bps_get(dev_handle); |
765 | uint16_t bps = fat_bps_get(dev_handle); |
766 | size_t bytes; |
766 | size_t bytes; |
- | 767 | block_t *b; |
|
767 | 768 | ||
768 | if (!nodep) { |
769 | if (!nodep) { |
769 | ipc_answer_0(rid, ENOENT); |
770 | ipc_answer_0(rid, ENOENT); |
770 | return; |
771 | return; |
771 | } |
772 | } |
Line 778... | Line 779... | ||
778 | ipc_answer_0(rid, EINVAL); |
779 | ipc_answer_0(rid, EINVAL); |
779 | return; |
780 | return; |
780 | } |
781 | } |
781 | 782 | ||
782 | if (nodep->type == FAT_FILE) { |
783 | if (nodep->type == FAT_FILE) { |
783 | block_t *b; |
784 | /* |
- | 785 | * Our strategy for regular file reads is to read one block at |
|
- | 786 | * most and make use of the possibility to return less data than |
|
- | 787 | * requested. This keeps the code very simple. |
|
784 | 788 | */ |
|
785 | bytes = min(len, bps - pos % bps); |
789 | bytes = min(len, bps - pos % bps); |
786 | b = fat_block_get(nodep, pos / bps); |
790 | b = fat_block_get(nodep, pos / bps); |
787 | (void) ipc_data_read_finalize(callid, b->data + pos % bps, |
791 | (void) ipc_data_read_finalize(callid, b->data + pos % bps, |
788 | bytes); |
792 | bytes); |
789 | block_put(b); |
793 | block_put(b); |
790 | } else { |
794 | } else { |
- | 795 | unsigned bnum; |
|
- | 796 | off_t spos = pos; |
|
- | 797 | char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1]; |
|
- | 798 | fat_dentry_t *d; |
|
- | 799 | ||
791 | assert(nodep->type == FAT_DIRECTORY); |
800 | assert(nodep->type == FAT_DIRECTORY); |
- | 801 | assert(nodep->size % bps == 0); |
|
- | 802 | assert(bps % sizeof(fat_dentry_t) == 0); |
|
- | 803 | ||
- | 804 | /* |
|
- | 805 | * Our strategy for readdir() is to use the position pointer as |
|
- | 806 | * an index into the array of all dentries. On entry, it points |
|
- | 807 | * to the first unread dentry. If we skip any dentries, we bump |
|
- | 808 | * the position pointer accordingly. |
|
792 | /* TODO */ |
809 | */ |
- | 810 | bnum = (pos * sizeof(fat_dentry_t)) / bps; |
|
- | 811 | while (bnum < nodep->size / bps) { |
|
- | 812 | off_t o; |
|
- | 813 | ||
- | 814 | b = fat_block_get(nodep, bnum); |
|
- | 815 | for (o = pos % (bps / sizeof(fat_dentry_t)); |
|
- | 816 | o < bps / sizeof(fat_dentry_t); |
|
- | 817 | o++, pos++) { |
|
- | 818 | d = ((fat_dentry_t *)b->data) + o; |
|
- | 819 | switch (fat_classify_dentry(d)) { |
|
- | 820 | case FAT_DENTRY_SKIP: |
|
- | 821 | continue; |
|
- | 822 | case FAT_DENTRY_LAST: |
|
- | 823 | block_put(b); |
|
- | 824 | goto miss; |
|
- | 825 | default: |
|
- | 826 | case FAT_DENTRY_VALID: |
|
- | 827 | dentry_name_canonify(d, name); |
|
- | 828 | block_put(b); |
|
- | 829 | goto hit; |
|
- | 830 | } |
|
- | 831 | } |
|
- | 832 | block_put(b); |
|
- | 833 | bnum++; |
|
- | 834 | } |
|
- | 835 | miss: |
|
793 | fat_node_put(nodep); |
836 | fat_node_put(nodep); |
794 | ipc_answer_0(callid, ENOTSUP); |
837 | ipc_answer_0(callid, ENOENT); |
795 | ipc_answer_0(rid, ENOTSUP); |
838 | ipc_answer_1(rid, ENOENT, 0); |
796 | return; |
839 | return; |
- | 840 | hit: |
|
- | 841 | (void) ipc_data_read_finalize(callid, name, strlen(name) + 1); |
|
- | 842 | bytes = (pos - spos) + 1; |
|
797 | } |
843 | } |
798 | 844 | ||
799 | fat_node_put(nodep); |
845 | fat_node_put(nodep); |
800 | ipc_answer_1(rid, EOK, (ipcarg_t)bytes); |
846 | ipc_answer_1(rid, EOK, (ipcarg_t)bytes); |
801 | } |
847 | } |