| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/disk_cache/simple/simple_synchronous_entry.h" | 5 #include "net/disk_cache/simple/simple_synchronous_entry.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cstring> | 8 #include <cstring> |
| 9 #include <functional> | 9 #include <functional> |
| 10 #include <limits> | 10 #include <limits> |
| 11 | 11 |
| 12 #include "base/compiler_specific.h" | 12 #include "base/compiler_specific.h" |
| 13 #include "base/files/file_util.h" | 13 #include "base/files/file_util.h" |
| 14 #include "base/hash.h" | 14 #include "base/hash.h" |
| 15 #include "base/location.h" | 15 #include "base/location.h" |
| 16 #include "base/memory/ptr_util.h" |
| 16 #include "base/metrics/histogram_macros.h" | 17 #include "base/metrics/histogram_macros.h" |
| 17 #include "base/numerics/safe_conversions.h" | 18 #include "base/numerics/safe_conversions.h" |
| 18 #include "base/sha1.h" | 19 #include "base/sha1.h" |
| 19 #include "base/timer/elapsed_timer.h" | 20 #include "base/timer/elapsed_timer.h" |
| 20 #include "crypto/secure_hash.h" | 21 #include "crypto/secure_hash.h" |
| 21 #include "net/base/hash_value.h" | 22 #include "net/base/hash_value.h" |
| 22 #include "net/base/io_buffer.h" | 23 #include "net/base/io_buffer.h" |
| 23 #include "net/base/net_errors.h" | 24 #include "net/base/net_errors.h" |
| 24 #include "net/disk_cache/simple/simple_backend_version.h" | 25 #include "net/disk_cache/simple/simple_backend_version.h" |
| 25 #include "net/disk_cache/simple/simple_histogram_macros.h" | 26 #include "net/disk_cache/simple/simple_histogram_macros.h" |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 262 const base::TimeTicks& time_enqueued, | 263 const base::TimeTicks& time_enqueued, |
| 263 SimpleEntryCreationResults* out_results) { | 264 SimpleEntryCreationResults* out_results) { |
| 264 base::TimeTicks start_sync_open_entry = base::TimeTicks::Now(); | 265 base::TimeTicks start_sync_open_entry = base::TimeTicks::Now(); |
| 265 SIMPLE_CACHE_UMA(TIMES, "QueueLatency.OpenEntry", cache_type, | 266 SIMPLE_CACHE_UMA(TIMES, "QueueLatency.OpenEntry", cache_type, |
| 266 (start_sync_open_entry - time_enqueued)); | 267 (start_sync_open_entry - time_enqueued)); |
| 267 | 268 |
| 268 SimpleSynchronousEntry* sync_entry = | 269 SimpleSynchronousEntry* sync_entry = |
| 269 new SimpleSynchronousEntry(cache_type, path, key, entry_hash, had_index); | 270 new SimpleSynchronousEntry(cache_type, path, key, entry_hash, had_index); |
| 270 out_results->result = sync_entry->InitializeForOpen( | 271 out_results->result = sync_entry->InitializeForOpen( |
| 271 &out_results->entry_stat, &out_results->stream_0_data, | 272 &out_results->entry_stat, &out_results->stream_0_data, |
| 272 &out_results->stream_0_crc32); | 273 &out_results->stream_0_crc32, &out_results->stream_1_data, |
| 274 &out_results->stream_1_crc32); |
| 273 if (out_results->result != net::OK) { | 275 if (out_results->result != net::OK) { |
| 274 sync_entry->Doom(); | 276 sync_entry->Doom(); |
| 275 delete sync_entry; | 277 delete sync_entry; |
| 276 out_results->sync_entry = NULL; | 278 out_results->sync_entry = NULL; |
| 277 out_results->stream_0_data = NULL; | 279 out_results->stream_0_data = NULL; |
| 278 return; | 280 return; |
| 279 } | 281 } |
| 280 SIMPLE_CACHE_UMA(TIMES, "DiskOpenLatency", cache_type, | 282 SIMPLE_CACHE_UMA(TIMES, "DiskOpenLatency", cache_type, |
| 281 base::TimeTicks::Now() - start_sync_open_entry); | 283 base::TimeTicks::Now() - start_sync_open_entry); |
| 282 out_results->sync_entry = sync_entry; | 284 out_results->sync_entry = sync_entry; |
| (...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 685 ++it; | 687 ++it; |
| 686 } | 688 } |
| 687 | 689 |
| 688 int64_t len_from_start = len - (start - offset); | 690 int64_t len_from_start = len - (start - offset); |
| 689 *out_start = start; | 691 *out_start = start; |
| 690 *out_result = static_cast<int>(std::min(avail_so_far, len_from_start)); | 692 *out_result = static_cast<int>(std::min(avail_so_far, len_from_start)); |
| 691 } | 693 } |
| 692 | 694 |
| 693 int SimpleSynchronousEntry::CheckEOFRecord(int index, | 695 int SimpleSynchronousEntry::CheckEOFRecord(int index, |
| 694 const SimpleEntryStat& entry_stat, | 696 const SimpleEntryStat& entry_stat, |
| 695 uint32_t expected_crc32) const { | 697 uint32_t expected_crc32) { |
| 696 DCHECK(initialized_); | 698 DCHECK(initialized_); |
| 697 uint32_t crc32; | 699 SimpleFileEOF eof_record; |
| 698 bool has_crc32; | 700 int rv = GetEOFRecordData(nullptr, 0, index, entry_stat, &eof_record); |
| 699 bool has_key_sha256; | 701 |
| 700 int32_t stream_size; | |
| 701 int rv = GetEOFRecordData(index, entry_stat, &has_crc32, &has_key_sha256, | |
| 702 &crc32, &stream_size); | |
| 703 if (rv != net::OK) { | 702 if (rv != net::OK) { |
| 704 Doom(); | 703 Doom(); |
| 705 return rv; | 704 return rv; |
| 706 } | 705 } |
| 707 if (has_crc32 && crc32 != expected_crc32) { | 706 if ((eof_record.flags & SimpleFileEOF::FLAG_HAS_CRC32) && |
| 707 eof_record.data_crc32 != expected_crc32) { |
| 708 DVLOG(1) << "EOF record had bad crc."; | 708 DVLOG(1) << "EOF record had bad crc."; |
| 709 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_CRC_MISMATCH); | 709 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_CRC_MISMATCH); |
| 710 Doom(); | 710 Doom(); |
| 711 return net::ERR_CACHE_CHECKSUM_MISMATCH; | 711 return net::ERR_CACHE_CHECKSUM_MISMATCH; |
| 712 } | 712 } |
| 713 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_SUCCESS); | 713 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_SUCCESS); |
| 714 return net::OK; | 714 return net::OK; |
| 715 } | 715 } |
| 716 | 716 |
| 717 int SimpleSynchronousEntry::PreReadStreamPayload( |
| 718 char* prefetch_buf, |
| 719 int file_size, |
| 720 int stream_index, |
| 721 int extra_size, |
| 722 const SimpleEntryStat& entry_stat, |
| 723 const SimpleFileEOF& eof_record, |
| 724 scoped_refptr<net::GrowableIOBuffer>* stream_data, |
| 725 uint32_t* out_crc32) { |
| 726 int stream_size = entry_stat.data_size(stream_index); |
| 727 int read_size = stream_size + extra_size; |
| 728 *stream_data = new net::GrowableIOBuffer(); |
| 729 (*stream_data)->SetCapacity(read_size); |
| 730 int file_offset = entry_stat.GetOffsetInFile(key_.size(), 0, stream_index); |
| 731 if (!ReadFromFileOrPrefetched(prefetch_buf, file_size, file_offset, read_size, |
| 732 (*stream_data)->data())) |
| 733 return net::ERR_FAILED; |
| 734 |
| 735 // Check the CRC32. |
| 736 uint32_t expected_crc32 = |
| 737 stream_size == 0 |
| 738 ? crc32(0, Z_NULL, 0) |
| 739 : crc32(crc32(0, Z_NULL, 0), |
| 740 reinterpret_cast<const Bytef*>((*stream_data)->data()), |
| 741 stream_size); |
| 742 if ((eof_record.flags & SimpleFileEOF::FLAG_HAS_CRC32) && |
| 743 eof_record.data_crc32 != expected_crc32) { |
| 744 DVLOG(1) << "EOF record had bad crc."; |
| 745 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_CRC_MISMATCH); |
| 746 return net::ERR_CACHE_CHECKSUM_MISMATCH; |
| 747 } |
| 748 *out_crc32 = expected_crc32; |
| 749 return net::OK; |
| 750 } |
| 751 |
| 717 void SimpleSynchronousEntry::Close( | 752 void SimpleSynchronousEntry::Close( |
| 718 const SimpleEntryStat& entry_stat, | 753 const SimpleEntryStat& entry_stat, |
| 719 std::unique_ptr<std::vector<CRCRecord>> crc32s_to_write, | 754 std::unique_ptr<std::vector<CRCRecord>> crc32s_to_write, |
| 720 net::GrowableIOBuffer* stream_0_data) { | 755 net::GrowableIOBuffer* stream_0_data) { |
| 721 base::ElapsedTimer close_time; | 756 base::ElapsedTimer close_time; |
| 722 DCHECK(stream_0_data); | 757 DCHECK(stream_0_data); |
| 723 | 758 |
| 724 for (std::vector<CRCRecord>::const_iterator it = crc32s_to_write->begin(); | 759 for (std::vector<CRCRecord>::const_iterator it = crc32s_to_write->begin(); |
| 725 it != crc32s_to_write->end(); ++it) { | 760 it != crc32s_to_write->end(); ++it) { |
| 726 const int stream_index = it->index; | 761 const int stream_index = it->index; |
| (...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1089 } | 1124 } |
| 1090 } | 1125 } |
| 1091 | 1126 |
| 1092 header_and_key_check_needed_[file_index] = false; | 1127 header_and_key_check_needed_[file_index] = false; |
| 1093 return true; | 1128 return true; |
| 1094 } | 1129 } |
| 1095 | 1130 |
| 1096 int SimpleSynchronousEntry::InitializeForOpen( | 1131 int SimpleSynchronousEntry::InitializeForOpen( |
| 1097 SimpleEntryStat* out_entry_stat, | 1132 SimpleEntryStat* out_entry_stat, |
| 1098 scoped_refptr<net::GrowableIOBuffer>* stream_0_data, | 1133 scoped_refptr<net::GrowableIOBuffer>* stream_0_data, |
| 1099 uint32_t* out_stream_0_crc32) { | 1134 uint32_t* out_stream_0_crc32, |
| 1135 scoped_refptr<net::GrowableIOBuffer>* stream_1_data, |
| 1136 uint32_t* out_stream_1_crc32) { |
| 1100 DCHECK(!initialized_); | 1137 DCHECK(!initialized_); |
| 1101 if (!OpenFiles(out_entry_stat)) { | 1138 if (!OpenFiles(out_entry_stat)) { |
| 1102 DLOG(WARNING) << "Could not open platform files for entry."; | 1139 DLOG(WARNING) << "Could not open platform files for entry."; |
| 1103 return net::ERR_FAILED; | 1140 return net::ERR_FAILED; |
| 1104 } | 1141 } |
| 1105 for (int i = 0; i < kSimpleEntryFileCount; ++i) { | 1142 for (int i = 0; i < kSimpleEntryFileCount; ++i) { |
| 1106 if (empty_file_omitted_[i]) | 1143 if (empty_file_omitted_[i]) |
| 1107 continue; | 1144 continue; |
| 1108 | 1145 |
| 1109 if (key_.empty()) { | 1146 if (key_.empty()) { |
| 1110 // If |key_| is empty, we were opened via the iterator interface, without | 1147 // If |key_| is empty, we were opened via the iterator interface, without |
| 1111 // knowing what our key is. We must therefore read the header immediately | 1148 // knowing what our key is. We must therefore read the header immediately |
| 1112 // to discover it, so SimpleEntryImpl can make it available to | 1149 // to discover it, so SimpleEntryImpl can make it available to |
| 1113 // disk_cache::Entry::GetKey(). | 1150 // disk_cache::Entry::GetKey(). |
| 1114 if (!CheckHeaderAndKey(i)) | 1151 if (!CheckHeaderAndKey(i)) |
| 1115 return net::ERR_FAILED; | 1152 return net::ERR_FAILED; |
| 1116 } else { | 1153 } else { |
| 1117 // If we do know which key were are looking for, we still need to | 1154 // If we do know which key were are looking for, we still need to |
| 1118 // check that the file actually has it (rather than just being a hash | 1155 // check that the file actually has it (rather than just being a hash |
| 1119 // collision or some sort of file system accident), but that can be put | 1156 // collision or some sort of file system accident), but that can be put |
| 1120 // off until opportune time: either the read of the footer, or when we | 1157 // off until opportune time: either the read of the footer, or when we |
| 1121 // start reading in the data, depending on stream # and format revision. | 1158 // start reading in the data, depending on stream # and format revision. |
| 1122 header_and_key_check_needed_[i] = true; | 1159 header_and_key_check_needed_[i] = true; |
| 1123 } | 1160 } |
| 1124 | 1161 |
| 1125 if (i == 0) { | 1162 if (i == 0) { |
| 1126 // File size for stream 0 has been stored temporarily in data_size[1]. | 1163 // File size for stream 0 has been stored temporarily in data_size[1]. |
| 1127 int ret_value_stream_0 = | 1164 int ret_value_stream_0 = ReadAndValidateStream0( |
| 1128 ReadAndValidateStream0(out_entry_stat->data_size(1), out_entry_stat, | 1165 out_entry_stat->data_size(1), out_entry_stat, stream_0_data, |
| 1129 stream_0_data, out_stream_0_crc32); | 1166 out_stream_0_crc32, stream_1_data, out_stream_1_crc32); |
| 1130 if (ret_value_stream_0 != net::OK) | 1167 if (ret_value_stream_0 != net::OK) |
| 1131 return ret_value_stream_0; | 1168 return ret_value_stream_0; |
| 1132 } else { | 1169 } else { |
| 1133 out_entry_stat->set_data_size( | 1170 out_entry_stat->set_data_size( |
| 1134 2, | 1171 2, |
| 1135 GetDataSizeFromFileSize(key_.size(), out_entry_stat->data_size(2))); | 1172 GetDataSizeFromFileSize(key_.size(), out_entry_stat->data_size(2))); |
| 1136 if (out_entry_stat->data_size(2) < 0) { | 1173 if (out_entry_stat->data_size(2) < 0) { |
| 1137 DLOG(WARNING) << "Stream 2 file is too small."; | 1174 DLOG(WARNING) << "Stream 2 file is too small."; |
| 1138 return net::ERR_FAILED; | 1175 return net::ERR_FAILED; |
| 1139 } | 1176 } |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1214 } | 1251 } |
| 1215 RecordSyncCreateResult(CREATE_ENTRY_SUCCESS, had_index_); | 1252 RecordSyncCreateResult(CREATE_ENTRY_SUCCESS, had_index_); |
| 1216 initialized_ = true; | 1253 initialized_ = true; |
| 1217 return net::OK; | 1254 return net::OK; |
| 1218 } | 1255 } |
| 1219 | 1256 |
| 1220 int SimpleSynchronousEntry::ReadAndValidateStream0( | 1257 int SimpleSynchronousEntry::ReadAndValidateStream0( |
| 1221 int file_size, | 1258 int file_size, |
| 1222 SimpleEntryStat* out_entry_stat, | 1259 SimpleEntryStat* out_entry_stat, |
| 1223 scoped_refptr<net::GrowableIOBuffer>* stream_0_data, | 1260 scoped_refptr<net::GrowableIOBuffer>* stream_0_data, |
| 1224 uint32_t* out_stream_0_crc32) { | 1261 uint32_t* out_stream_0_crc32, |
| 1262 scoped_refptr<net::GrowableIOBuffer>* stream_1_data, |
| 1263 uint32_t* out_stream_1_crc32) { |
| 1264 // If the file is sufficiently small, we will prefetch everything -- |
| 1265 // in which case |prefetch_buf| will be non-null, and we should look at it |
| 1266 // rather than call ::Read for the bits. |
| 1267 std::unique_ptr<char[]> prefetch_buf; |
| 1268 const int kPrefetchLimit = 32 * 1024; |
| 1269 if (file_size <= kPrefetchLimit) { |
| 1270 prefetch_buf = base::MakeUnique<char[]>(file_size); |
| 1271 if (files_[0].Read(0, prefetch_buf.get(), file_size) != file_size) |
| 1272 return net::ERR_FAILED; |
| 1273 } |
| 1274 |
| 1225 // Pretend this file has a null stream zero, and contains the optional key | 1275 // Pretend this file has a null stream zero, and contains the optional key |
| 1226 // SHA256. This is good enough to read the EOF record on the file, which gives | 1276 // SHA256. This is good enough to read the EOF record on the file, which gives |
| 1227 // the actual size of stream 0. | 1277 // the actual size of stream 0. |
| 1228 int temp_data_size = GetDataSizeFromFileSize(key_.size(), file_size); | 1278 int temp_data_size = GetDataSizeFromFileSize(key_.size(), file_size); |
| 1229 out_entry_stat->set_data_size(0, 0); | 1279 out_entry_stat->set_data_size(0, 0); |
| 1230 out_entry_stat->set_data_size( | 1280 out_entry_stat->set_data_size( |
| 1231 1, temp_data_size - sizeof(net::SHA256HashValue) - sizeof(SimpleFileEOF)); | 1281 1, temp_data_size - sizeof(net::SHA256HashValue) - sizeof(SimpleFileEOF)); |
| 1232 | 1282 |
| 1233 bool has_crc32; | 1283 SimpleFileEOF stream_0_eof; |
| 1234 bool has_key_sha256; | 1284 int rv = GetEOFRecordData(prefetch_buf.get(), file_size, 0, *out_entry_stat, |
| 1235 uint32_t read_crc32; | 1285 &stream_0_eof); |
| 1236 int32_t stream_0_size; | 1286 if (rv != net::OK) |
| 1237 int ret_value_crc32 = | 1287 return rv; |
| 1238 GetEOFRecordData(0, *out_entry_stat, &has_crc32, &has_key_sha256, | 1288 |
| 1239 &read_crc32, &stream_0_size); | 1289 bool has_key_sha256 = |
| 1240 if (ret_value_crc32 != net::OK) | 1290 (stream_0_eof.flags & SimpleFileEOF::FLAG_HAS_KEY_SHA256) == |
| 1241 return ret_value_crc32; | 1291 SimpleFileEOF::FLAG_HAS_KEY_SHA256; |
| 1292 int32_t stream_0_size = stream_0_eof.stream_size; |
| 1242 | 1293 |
| 1243 // Calculate and set the real values for the two streams. | 1294 // Calculate and set the real values for the two streams. |
| 1244 int32_t total_size = out_entry_stat->data_size(1); | 1295 int32_t total_size = out_entry_stat->data_size(1); |
| 1245 if (!has_key_sha256) | 1296 if (!has_key_sha256) |
| 1246 total_size += sizeof(net::SHA256HashValue); | 1297 total_size += sizeof(net::SHA256HashValue); |
| 1298 |
| 1299 // Sanity-check: don't want to be allocating a gigantic buffer > file size |
| 1300 // just because of a header field. |
| 1247 if (stream_0_size > total_size) | 1301 if (stream_0_size > total_size) |
| 1248 return net::ERR_FAILED; | 1302 return net::ERR_FAILED; |
| 1249 out_entry_stat->set_data_size(0, stream_0_size); | 1303 out_entry_stat->set_data_size(0, stream_0_size); |
| 1250 out_entry_stat->set_data_size(1, total_size - stream_0_size); | 1304 out_entry_stat->set_data_size(1, total_size - stream_0_size); |
| 1251 | 1305 |
| 1252 // Put stream 0 data in memory. | 1306 // Put stream 0 data in memory --- plus maybe the sha256(key) footer. |
| 1253 *stream_0_data = new net::GrowableIOBuffer(); | 1307 int extra_stream_0_read = 0; |
| 1254 (*stream_0_data)->SetCapacity(stream_0_size + sizeof(net::SHA256HashValue)); | |
| 1255 int file_offset = out_entry_stat->GetOffsetInFile(key_.size(), 0, 0); | |
| 1256 int read_size = stream_0_size; | |
| 1257 if (has_key_sha256) | 1308 if (has_key_sha256) |
| 1258 read_size += sizeof(net::SHA256HashValue); | 1309 extra_stream_0_read += sizeof(net::SHA256HashValue); |
| 1259 if (files_[0].Read(file_offset, (*stream_0_data)->data(), read_size) != | 1310 rv = PreReadStreamPayload(prefetch_buf.get(), file_size, 0, |
| 1260 read_size) | 1311 extra_stream_0_read, *out_entry_stat, stream_0_eof, |
| 1261 return net::ERR_FAILED; | 1312 stream_0_data, out_stream_0_crc32); |
| 1313 if (rv != net::OK) |
| 1314 return rv; |
| 1262 | 1315 |
| 1263 // Check the CRC32. | 1316 // If prefetch buffer is available, and we have sha256(key) (so we don't need |
| 1264 uint32_t expected_crc32 = | 1317 // to look at the header), extract out stream 1 info as well. |
| 1265 stream_0_size == 0 | 1318 if (prefetch_buf && has_key_sha256) { |
| 1266 ? crc32(0, Z_NULL, 0) | 1319 SimpleFileEOF stream_1_eof; |
| 1267 : crc32(crc32(0, Z_NULL, 0), | 1320 rv = GetEOFRecordData(prefetch_buf.get(), file_size, 1, *out_entry_stat, |
| 1268 reinterpret_cast<const Bytef*>((*stream_0_data)->data()), | 1321 &stream_1_eof); |
| 1269 stream_0_size); | 1322 if (rv != net::OK) |
| 1270 if (has_crc32 && read_crc32 != expected_crc32) { | 1323 return rv; |
| 1271 DVLOG(1) << "EOF record had bad crc."; | 1324 |
| 1272 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_CRC_MISMATCH); | 1325 rv = PreReadStreamPayload(prefetch_buf.get(), file_size, 1, 0, |
| 1273 return net::ERR_FAILED; | 1326 *out_entry_stat, stream_1_eof, stream_1_data, |
| 1327 out_stream_1_crc32); |
| 1328 if (rv != net::OK) |
| 1329 return rv; |
| 1330 } else { |
| 1331 *stream_1_data = nullptr; |
| 1274 } | 1332 } |
| 1275 *out_stream_0_crc32 = expected_crc32; | |
| 1276 | 1333 |
| 1277 // If present, check the key SHA256. | 1334 // If present, check the key SHA256. |
| 1278 if (has_key_sha256) { | 1335 if (has_key_sha256) { |
| 1279 net::SHA256HashValue hash_value; | 1336 net::SHA256HashValue hash_value; |
| 1280 CalculateSHA256OfKey(key_, &hash_value); | 1337 CalculateSHA256OfKey(key_, &hash_value); |
| 1281 bool matched = | 1338 bool matched = |
| 1282 std::memcmp(&hash_value, (*stream_0_data)->data() + stream_0_size, | 1339 std::memcmp(&hash_value, (*stream_0_data)->data() + stream_0_size, |
| 1283 sizeof(hash_value)) == 0; | 1340 sizeof(hash_value)) == 0; |
| 1284 if (!matched) { | 1341 if (!matched) { |
| 1285 RecordKeySHA256Result(cache_type_, KeySHA256Result::NO_MATCH); | 1342 RecordKeySHA256Result(cache_type_, KeySHA256Result::NO_MATCH); |
| 1286 return net::ERR_FAILED; | 1343 return net::ERR_FAILED; |
| 1287 } | 1344 } |
| 1288 // Elide header check if we verified sha256(key) via footer. | 1345 // Elide header check if we verified sha256(key) via footer. |
| 1289 header_and_key_check_needed_[0] = false; | 1346 header_and_key_check_needed_[0] = false; |
| 1290 RecordKeySHA256Result(cache_type_, KeySHA256Result::MATCHED); | 1347 RecordKeySHA256Result(cache_type_, KeySHA256Result::MATCHED); |
| 1291 } else { | 1348 } else { |
| 1292 RecordKeySHA256Result(cache_type_, KeySHA256Result::NOT_PRESENT); | 1349 RecordKeySHA256Result(cache_type_, KeySHA256Result::NOT_PRESENT); |
| 1293 } | 1350 } |
| 1294 | 1351 |
| 1295 // Ensure the key is validated before completion. | 1352 // Ensure the key is validated before completion. |
| 1296 if (!has_key_sha256 && header_and_key_check_needed_[0]) | 1353 if (!has_key_sha256 && header_and_key_check_needed_[0]) |
| 1297 CheckHeaderAndKey(0); | 1354 CheckHeaderAndKey(0); |
| 1298 | 1355 |
| 1299 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_SUCCESS); | 1356 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_SUCCESS); |
| 1300 return net::OK; | 1357 return net::OK; |
| 1301 } | 1358 } |
| 1302 | 1359 |
| 1303 int SimpleSynchronousEntry::GetEOFRecordData(int index, | 1360 bool SimpleSynchronousEntry::ReadFromFileOrPrefetched(char* prefetch_buf, |
| 1361 int file_size, |
| 1362 int offset, |
| 1363 int size, |
| 1364 char* dest) { |
| 1365 if (!prefetch_buf) { |
| 1366 return files_[0].Read(offset, dest, size) == size; |
| 1367 } else { |
| 1368 if (offset < 0 || size < 0) |
| 1369 return false; |
| 1370 base::CheckedNumeric<int> end = |
| 1371 base::CheckedNumeric<int>(offset) + size - 1; |
| 1372 if (!end.IsValid()) |
| 1373 return false; |
| 1374 if (offset >= file_size || end.ValueOrDie() >= file_size) |
| 1375 return false; |
| 1376 |
| 1377 memcpy(dest, prefetch_buf + offset, size); |
| 1378 return true; |
| 1379 } |
| 1380 } |
| 1381 |
| 1382 int SimpleSynchronousEntry::GetEOFRecordData(char* prefetch_buf, |
| 1383 int file_size, |
| 1384 int stream_index, |
| 1304 const SimpleEntryStat& entry_stat, | 1385 const SimpleEntryStat& entry_stat, |
| 1305 bool* out_has_crc32, | 1386 SimpleFileEOF* eof_record) { |
| 1306 bool* out_has_key_sha256, | 1387 int file_offset = entry_stat.GetEOFOffsetInFile(key_.size(), stream_index); |
| 1307 uint32_t* out_crc32, | 1388 int file_index = GetFileIndexFromStreamIndex(stream_index); |
| 1308 int32_t* out_data_size) const { | 1389 |
| 1309 SimpleFileEOF eof_record; | 1390 // Should only have prefetch_buf when reading things in file 0. |
| 1310 int file_offset = entry_stat.GetEOFOffsetInFile(key_.size(), index); | 1391 DCHECK(file_index == 0 || !prefetch_buf); |
| 1311 int file_index = GetFileIndexFromStreamIndex(index); | 1392 bool ok; |
| 1312 File* file = const_cast<File*>(&files_[file_index]); | 1393 if (prefetch_buf) |
| 1313 if (file->Read(file_offset, reinterpret_cast<char*>(&eof_record), | 1394 ok = ReadFromFileOrPrefetched(prefetch_buf, file_size, file_offset, |
| 1314 sizeof(eof_record)) != | 1395 sizeof(SimpleFileEOF), |
| 1315 sizeof(eof_record)) { | 1396 reinterpret_cast<char*>(eof_record)); |
| 1397 else |
| 1398 // Need to support files_[1], so can't use ReadFromFileOrPrefetched |
| 1399 // in this case. |
| 1400 ok = files_[file_index].Read( |
| 1401 file_offset, reinterpret_cast<char*>(eof_record), |
| 1402 sizeof(SimpleFileEOF)) == sizeof(SimpleFileEOF); |
| 1403 |
| 1404 if (!ok) { |
| 1316 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_READ_FAILURE); | 1405 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_READ_FAILURE); |
| 1317 return net::ERR_CACHE_CHECKSUM_READ_FAILURE; | 1406 return net::ERR_CACHE_CHECKSUM_READ_FAILURE; |
| 1318 } | 1407 } |
| 1319 | 1408 |
| 1320 if (eof_record.final_magic_number != kSimpleFinalMagicNumber) { | 1409 if (eof_record->final_magic_number != kSimpleFinalMagicNumber) { |
| 1321 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_MAGIC_NUMBER_MISMATCH); | 1410 RecordCheckEOFResult(cache_type_, CHECK_EOF_RESULT_MAGIC_NUMBER_MISMATCH); |
| 1322 DVLOG(1) << "EOF record had bad magic number."; | 1411 DVLOG(1) << "EOF record had bad magic number."; |
| 1323 return net::ERR_CACHE_CHECKSUM_READ_FAILURE; | 1412 return net::ERR_CACHE_CHECKSUM_READ_FAILURE; |
| 1324 } | 1413 } |
| 1325 | 1414 |
| 1326 if (!base::IsValueInRangeForNumericType<int32_t>(eof_record.stream_size)) | 1415 if (!base::IsValueInRangeForNumericType<int32_t>(eof_record->stream_size)) |
| 1327 return net::ERR_FAILED; | 1416 return net::ERR_FAILED; |
| 1328 | 1417 SIMPLE_CACHE_UMA(BOOLEAN, "SyncCheckEOFHasCrc", cache_type_, |
| 1329 *out_has_crc32 = (eof_record.flags & SimpleFileEOF::FLAG_HAS_CRC32) == | 1418 (eof_record->flags & SimpleFileEOF::FLAG_HAS_CRC32) == |
| 1330 SimpleFileEOF::FLAG_HAS_CRC32; | 1419 SimpleFileEOF::FLAG_HAS_CRC32); |
| 1331 *out_has_key_sha256 = | |
| 1332 (eof_record.flags & SimpleFileEOF::FLAG_HAS_KEY_SHA256) == | |
| 1333 SimpleFileEOF::FLAG_HAS_KEY_SHA256; | |
| 1334 *out_crc32 = eof_record.data_crc32; | |
| 1335 *out_data_size = eof_record.stream_size; | |
| 1336 SIMPLE_CACHE_UMA(BOOLEAN, "SyncCheckEOFHasCrc", cache_type_, *out_has_crc32); | |
| 1337 return net::OK; | 1420 return net::OK; |
| 1338 } | 1421 } |
| 1339 | 1422 |
| 1340 void SimpleSynchronousEntry::Doom() const { | 1423 void SimpleSynchronousEntry::Doom() const { |
| 1341 DeleteFilesForEntryHash(path_, entry_hash_); | 1424 DeleteFilesForEntryHash(path_, entry_hash_); |
| 1342 } | 1425 } |
| 1343 | 1426 |
| 1344 // static | 1427 // static |
| 1345 bool SimpleSynchronousEntry::DeleteFileForEntryHash(const FilePath& path, | 1428 bool SimpleSynchronousEntry::DeleteFileForEntryHash(const FilePath& path, |
| 1346 const uint64_t entry_hash, | 1429 const uint64_t entry_hash, |
| (...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1651 range.offset = offset; | 1734 range.offset = offset; |
| 1652 range.length = len; | 1735 range.length = len; |
| 1653 range.data_crc32 = data_crc32; | 1736 range.data_crc32 = data_crc32; |
| 1654 range.file_offset = data_file_offset; | 1737 range.file_offset = data_file_offset; |
| 1655 sparse_ranges_.insert(std::make_pair(offset, range)); | 1738 sparse_ranges_.insert(std::make_pair(offset, range)); |
| 1656 | 1739 |
| 1657 return true; | 1740 return true; |
| 1658 } | 1741 } |
| 1659 | 1742 |
| 1660 } // namespace disk_cache | 1743 } // namespace disk_cache |
| OLD | NEW |