| 892 | } |
| 893 | |
| 894 | int FSCryptFDataDenc::decrypt_bl(uint64_t off, uint64_t len, uint64_t pos, const std::vector<Segment>& holes, bufferlist *bl) |
| 895 | { |
| 896 | auto data_len = bl->length(); |
| 897 | if (data_len == 0) |
| 898 | return 0; |
| 899 | |
| 900 | auto target_end = off + len; |
| 901 | |
| 902 | bufferlist newbl; |
| 903 | |
| 904 | uint64_t end = off + data_len; |
| 905 | uint64_t cur_block = fscrypt_block_from_ofs(pos); |
| 906 | uint64_t block_off = fscrypt_block_start(pos); |
| 907 | |
| 908 | uint64_t start_block_off = block_off; |
| 909 | |
| 910 | auto hiter = holes.begin(); |
| 911 | |
| 912 | while (pos < target_end) { |
| 913 | bool has_hole = false; |
| 914 | |
| 915 | /* |
| 916 | * Check to see if cur_block is part of a |
| 917 | * hole. We expect holes to ordered by offset. |
| 918 | * |
| 919 | * There is four states it can be in |
| 920 | * 1. If position is before hole offset, it cannot be part of a hole |
| 921 | * 2. If hole end is less than position, hole occurs completely before |
| 922 | * 3. If hole starts after target_end, hole occurs completely after |
| 923 | * 4. No conditionals are met, is a hole |
| 924 | */ |
| 925 | |
| 926 | while (hiter != holes.end()) { |
| 927 | uint64_t hofs = hiter->first; |
| 928 | uint64_t hlen = hiter->second; |
| 929 | uint64_t hend = hofs + hlen - 1; |
| 930 | |
| 931 | if (pos < hofs) |
| 932 | break; |
| 933 | |
| 934 | if (hend < pos) { |
| 935 | ++hiter; |
| 936 | continue; |
| 937 | } |
| 938 | |
| 939 | if (hofs >= target_end) { |
| 940 | hiter = holes.end(); |
| 941 | break; |
| 942 | } |
| 943 | |
| 944 | has_hole = true; |
| 945 | break; |
| 946 | } |
| 947 | |
| 948 | uint64_t needed_pos = (pos > off ? pos : off); |
| 949 | void *data_pos = bl->c_str() + needed_pos - start_block_off; |
| 950 | if (!has_hole && *(uint64_t *)data_pos == 0) { |
| 951 | has_hole = true; |
no test coverage detected