Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 36c2679 in mainline


Ignore:
Timestamp:
2011-08-02T20:21:03Z (10 years ago)
Author:
Oleg Romanenko <romanenko.oleg@…>
Branches:
lfn, master
Children:
f6641d2
Parents:
8c18b7a
Message:

Implement exfat_read

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/fs/exfat/exfat_ops.c

    r8c18b7a r36c2679  
    947947}
    948948
     949void exfat_read(ipc_callid_t rid, ipc_call_t *request)
     950{
     951        devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request);
     952        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
     953        aoff64_t pos =
     954            (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
     955        fs_node_t *fn;
     956        exfat_node_t *nodep;
     957        exfat_bs_t *bs;
     958        size_t bytes=0;
     959        block_t *b;
     960        int rc;
     961
     962        rc = exfat_node_get(&fn, devmap_handle, index);
     963        if (rc != EOK) {
     964                async_answer_0(rid, rc);
     965                return;
     966        }
     967        if (!fn) {
     968                async_answer_0(rid, ENOENT);
     969                return;
     970        }
     971        nodep = EXFAT_NODE(fn);
     972
     973        ipc_callid_t callid;
     974        size_t len;
     975        if (!async_data_read_receive(&callid, &len)) {
     976                exfat_node_put(fn);
     977                async_answer_0(callid, EINVAL);
     978                async_answer_0(rid, EINVAL);
     979                return;
     980        }
     981
     982        bs = block_bb_get(devmap_handle);
     983
     984        if (nodep->type == EXFAT_FILE) {
     985                /*
     986                 * Our strategy for regular file reads is to read one block at
     987                 * most and make use of the possibility to return less data than
     988                 * requested. This keeps the code very simple.
     989                 */
     990                if (pos >= nodep->size) {
     991                        /* reading beyond the EOF */
     992                        bytes = 0;
     993                        (void) async_data_read_finalize(callid, NULL, 0);
     994                } else {
     995                        bytes = min(len, BPS(bs) - pos % BPS(bs));
     996                        bytes = min(bytes, nodep->size - pos);
     997                        rc = exfat_block_get(&b, bs, nodep, pos / BPS(bs),
     998                            BLOCK_FLAGS_NONE);
     999                        if (rc != EOK) {
     1000                                exfat_node_put(fn);
     1001                                async_answer_0(callid, rc);
     1002                                async_answer_0(rid, rc);
     1003                                return;
     1004                        }
     1005                        (void) async_data_read_finalize(callid,
     1006                            b->data + pos % BPS(bs), bytes);
     1007                        rc = block_put(b);
     1008                        if (rc != EOK) {
     1009                                exfat_node_put(fn);
     1010                                async_answer_0(rid, rc);
     1011                                return;
     1012                        }
     1013                }
     1014        } else {
     1015                if (nodep->type != EXFAT_DIRECTORY) {
     1016                        async_answer_0(callid, ENOTSUP);
     1017                        async_answer_0(rid, ENOTSUP);
     1018                        return;
     1019                }
     1020                       
     1021                aoff64_t spos = pos;
     1022                char name[EXFAT_FILENAME_LEN+1];
     1023                exfat_file_dentry_t df;
     1024                exfat_stream_dentry_t ds;
     1025
     1026                assert(nodep->size % BPS(bs) == 0);
     1027                assert(BPS(bs) % sizeof(exfat_dentry_t) == 0);
     1028
     1029                exfat_directory_t di;
     1030                rc = exfat_directory_open(nodep, &di);
     1031                if (rc != EOK) goto err;
     1032                rc = exfat_directory_seek(&di, pos);
     1033                if (rc != EOK) {
     1034                        (void) exfat_directory_close(&di);
     1035                        goto err;
     1036                }
     1037
     1038                rc = exfat_directory_read_file(&di, name, EXFAT_FILENAME_LEN, &df, &ds);
     1039                if (rc == EOK) goto hit;
     1040                if (rc == ENOENT) goto miss;
     1041
     1042err:
     1043                (void) exfat_node_put(fn);
     1044                async_answer_0(callid, rc);
     1045                async_answer_0(rid, rc);
     1046                return;
     1047
     1048miss:
     1049                rc = exfat_directory_close(&di);
     1050                if (rc!=EOK)
     1051                        goto err;
     1052                rc = exfat_node_put(fn);
     1053                async_answer_0(callid, rc != EOK ? rc : ENOENT);
     1054                async_answer_1(rid, rc != EOK ? rc : ENOENT, 0);
     1055                return;
     1056
     1057hit:
     1058                pos = di.pos;
     1059                rc = exfat_directory_close(&di);
     1060                if (rc!=EOK)
     1061                        goto err;
     1062                (void) async_data_read_finalize(callid, name, str_size(name) + 1);
     1063                bytes = (pos - spos)+1;
     1064        }
     1065
     1066        rc = exfat_node_put(fn);
     1067        async_answer_1(rid, rc, (sysarg_t)bytes);
     1068}
    9491069
    9501070/**
Note: See TracChangeset for help on using the changeset viewer.