OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "net/disk_cache/simple/simple_index_file.h" |
| 6 |
| 7 #include "base/file_util.h" |
| 8 #include "base/hash.h" |
| 9 #include "base/logging.h" |
| 10 #include "base/pickle.h" |
| 11 #include "net/disk_cache/simple/simple_entry_format.h" |
| 12 #include "net/disk_cache/simple/simple_index.h" |
| 13 #include "net/disk_cache/simple/simple_util.h" |
| 14 #include "third_party/zlib/zlib.h" |
| 15 |
| 16 |
| 17 namespace { |
| 18 |
| 19 const uint64 kMaxEntiresInIndex = 100000000; |
| 20 |
| 21 uint32 CalculatePickleCRC(const Pickle& pickle) { |
| 22 return crc32(crc32(0, Z_NULL, 0), |
| 23 reinterpret_cast<const Bytef*>(pickle.payload()), |
| 24 pickle.payload_size()); |
| 25 } |
| 26 |
| 27 } // namespace |
| 28 |
| 29 namespace disk_cache { |
| 30 |
| 31 SimpleIndexFile::IndexMetadata::IndexMetadata() : |
| 32 magic_number_(kSimpleIndexMagicNumber), |
| 33 version_(kSimpleVersion), |
| 34 number_of_entries_(0), |
| 35 cache_size_(0) {} |
| 36 |
| 37 SimpleIndexFile::IndexMetadata::IndexMetadata( |
| 38 uint64 number_of_entries, uint64 cache_size) : |
| 39 magic_number_(kSimpleIndexMagicNumber), |
| 40 version_(kSimpleVersion), |
| 41 number_of_entries_(number_of_entries), |
| 42 cache_size_(cache_size) {} |
| 43 |
| 44 void SimpleIndexFile::IndexMetadata::Serialize(Pickle* pickle) const { |
| 45 DCHECK(pickle); |
| 46 pickle->WriteUInt64(magic_number_); |
| 47 pickle->WriteUInt32(version_); |
| 48 pickle->WriteUInt64(number_of_entries_); |
| 49 pickle->WriteUInt64(cache_size_); |
| 50 } |
| 51 |
| 52 bool SimpleIndexFile::IndexMetadata::Deserialize(PickleIterator* it) { |
| 53 DCHECK(it); |
| 54 return it->ReadUInt64(&magic_number_) && |
| 55 it->ReadUInt32(&version_) && |
| 56 it->ReadUInt64(&number_of_entries_)&& |
| 57 it->ReadUInt64(&cache_size_); |
| 58 } |
| 59 |
| 60 bool SimpleIndexFile::IndexMetadata::CheckIndexMetadata() { |
| 61 return number_of_entries_ <= kMaxEntiresInIndex && |
| 62 magic_number_ == disk_cache::kSimpleIndexMagicNumber && |
| 63 version_ == disk_cache::kSimpleVersion; |
| 64 } |
| 65 |
| 66 // static |
| 67 scoped_ptr<SimpleIndex::EntrySet> SimpleIndexFile::LoadFromDisk( |
| 68 const base::FilePath& index_filename) { |
| 69 std::string contents; |
| 70 if(!file_util::ReadFileToString(index_filename, &contents)) { |
| 71 LOG(WARNING) << "Could not read Simple Index file."; |
| 72 return scoped_ptr<SimpleIndex::EntrySet>(NULL); |
| 73 } |
| 74 |
| 75 return SimpleIndexFile::Deserialize(contents.data(), contents.size()); |
| 76 } |
| 77 |
| 78 // static |
| 79 scoped_ptr<SimpleIndex::EntrySet> SimpleIndexFile::Deserialize(const char* data, |
| 80 int data_len) { |
| 81 DCHECK(data); |
| 82 Pickle pickle(data, data_len); |
| 83 if (!pickle.data()) { |
| 84 LOG(WARNING) << "Corrupt Simple Index File."; |
| 85 return scoped_ptr<SimpleIndex::EntrySet>(NULL); |
| 86 } |
| 87 |
| 88 PickleIterator pickle_it(pickle); |
| 89 |
| 90 SimpleIndexFile::PickleHeader* header_p = |
| 91 pickle.headerT<SimpleIndexFile::PickleHeader>(); |
| 92 const uint32 crc_read = header_p->crc; |
| 93 const uint32 crc_calculated = CalculatePickleCRC(pickle); |
| 94 |
| 95 if (crc_read != crc_calculated) { |
| 96 LOG(WARNING) << "Invalid CRC in Simple Index file."; |
| 97 return scoped_ptr<SimpleIndex::EntrySet>(NULL); |
| 98 } |
| 99 |
| 100 SimpleIndexFile::IndexMetadata index_metadata; |
| 101 if (!index_metadata.Deserialize(&pickle_it)) { |
| 102 LOG(ERROR) << "Invalid index_metadata on Simple Cache Index."; |
| 103 return scoped_ptr<SimpleIndex::EntrySet>(NULL); |
| 104 } |
| 105 |
| 106 if (!index_metadata.CheckIndexMetadata()) { |
| 107 LOG(ERROR) << "Invalid index_metadata on Simple Cache Index."; |
| 108 return scoped_ptr<SimpleIndex::EntrySet>(NULL); |
| 109 } |
| 110 |
| 111 scoped_ptr<SimpleIndex::EntrySet> index_file_entries( |
| 112 new SimpleIndex::EntrySet()); |
| 113 while (index_file_entries->size() < index_metadata.GetNumberOfEntries()) { |
| 114 EntryMetadata entry_metadata; |
| 115 if (!entry_metadata.Deserialize(&pickle_it)) { |
| 116 LOG(WARNING) << "Invalid EntryMetadata in Simple Index file."; |
| 117 return scoped_ptr<SimpleIndex::EntrySet>(NULL); |
| 118 } |
| 119 SimpleIndex::InsertInEntrySet(entry_metadata, index_file_entries.get()); |
| 120 } |
| 121 |
| 122 return index_file_entries.Pass(); |
| 123 } |
| 124 |
| 125 // static |
| 126 scoped_ptr<Pickle> SimpleIndexFile::Serialize( |
| 127 const SimpleIndexFile::IndexMetadata& index_metadata, |
| 128 const SimpleIndex::EntrySet& entries) { |
| 129 scoped_ptr<Pickle> pickle(new Pickle(sizeof(SimpleIndexFile::PickleHeader))); |
| 130 |
| 131 index_metadata.Serialize(pickle.get()); |
| 132 for (SimpleIndex::EntrySet::const_iterator it = entries.begin(); |
| 133 it != entries.end(); ++it) { |
| 134 it->second.Serialize(pickle.get()); |
| 135 } |
| 136 SimpleIndexFile::PickleHeader* header_p = |
| 137 pickle->headerT<SimpleIndexFile::PickleHeader>(); |
| 138 header_p->crc = CalculatePickleCRC(*pickle); |
| 139 return pickle.Pass(); |
| 140 } |
| 141 |
| 142 // static |
| 143 void SimpleIndexFile::WriteToDisk(const base::FilePath& index_filename, |
| 144 const Pickle& pickle) { |
| 145 const base::FilePath temp_filename = |
| 146 index_filename.DirName().AppendASCII("index_temp"); |
| 147 int bytes_written = file_util::WriteFile( |
| 148 temp_filename, |
| 149 reinterpret_cast<const char*>(pickle.data()), |
| 150 pickle.size()); |
| 151 DCHECK_EQ(bytes_written, implicit_cast<int>(pickle.size())); |
| 152 if (bytes_written != static_cast<int>(pickle.size())) { |
| 153 // TODO(felipeg): Add better error handling. |
| 154 LOG(ERROR) << "Could not write Simple Cache index to temporary file: " |
| 155 << temp_filename.value(); |
| 156 file_util::Delete(temp_filename, /* recursive = */ false); |
| 157 return; |
| 158 } |
| 159 // Swap temp and index_file. |
| 160 bool result = file_util::ReplaceFile(temp_filename, index_filename); |
| 161 DCHECK(result); |
| 162 } |
| 163 |
| 164 } // namespace disk_cache |
OLD | NEW |