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_util.h" 6 7 #include <limits> 8 9 #include "base/file_util.h" 10 #include "base/format_macros.h" 11 #include "base/logging.h" 12 #include "base/sha1.h" 13 #include "base/strings/string_number_conversions.h" 14 #include "base/strings/stringprintf.h" 15 #include "base/threading/thread_restrictions.h" 16 #include "base/time/time.h" 17 #include "net/disk_cache/simple/simple_entry_format.h" 18 19 namespace { 20 21 // Size of the uint64 hash_key number in Hex format in a string. 22 const size_t kEntryHashKeyAsHexStringSize = 2 * sizeof(uint64); 23 24 // TODO(clamy, gavinp): this should go in base 25 bool GetNanoSecsFromStat(const struct stat& st, 26 time_t* out_sec, 27 long* out_nsec) { 28 #if defined(OS_ANDROID) 29 *out_sec = st.st_mtime; 30 *out_nsec = st.st_mtime_nsec; 31 #elif defined(OS_LINUX) 32 *out_sec = st.st_mtim.tv_sec; 33 *out_nsec = st.st_mtim.tv_nsec; 34 #elif defined(OS_MACOSX) || defined(OS_IOS) || defined(OS_BSD) 35 *out_sec = st.st_mtimespec.tv_sec; 36 *out_nsec = st.st_mtimespec.tv_nsec; 37 #else 38 return false; 39 #endif 40 return true; 41 } 42 43 } // namespace 44 45 namespace disk_cache { 46 47 namespace simple_util { 48 49 std::string ConvertEntryHashKeyToHexString(uint64 hash_key) { 50 const std::string hash_key_str = base::StringPrintf("%016" PRIx64, hash_key); 51 DCHECK_EQ(kEntryHashKeyAsHexStringSize, hash_key_str.size()); 52 return hash_key_str; 53 } 54 55 std::string GetEntryHashKeyAsHexString(const std::string& key) { 56 std::string hash_key_str = 57 ConvertEntryHashKeyToHexString(GetEntryHashKey(key)); 58 DCHECK_EQ(kEntryHashKeyAsHexStringSize, hash_key_str.size()); 59 return hash_key_str; 60 } 61 62 bool GetEntryHashKeyFromHexString(const base::StringPiece& hash_key, 63 uint64* hash_key_out) { 64 if (hash_key.size() != kEntryHashKeyAsHexStringSize) { 65 return false; 66 } 67 return base::HexStringToUInt64(hash_key, hash_key_out); 68 } 69 70 uint64 GetEntryHashKey(const std::string& key) { 71 union { 72 unsigned char sha_hash[base::kSHA1Length]; 73 uint64 key_hash; 74 } u; 75 base::SHA1HashBytes(reinterpret_cast<const unsigned char*>(key.data()), 76 key.size(), u.sha_hash); 77 return u.key_hash; 78 } 79 80 std::string GetFilenameFromEntryHashAndFileIndex(uint64 entry_hash, 81 int file_index) { 82 return base::StringPrintf("%016" PRIx64 "_%1d", entry_hash, file_index); 83 } 84 85 std::string GetSparseFilenameFromEntryHash(uint64 entry_hash) { 86 return base::StringPrintf("%016" PRIx64 "_s", entry_hash); 87 } 88 89 std::string GetFilenameFromKeyAndFileIndex(const std::string& key, 90 int file_index) { 91 return GetEntryHashKeyAsHexString(key) + 92 base::StringPrintf("_%1d", file_index); 93 } 94 95 int32 GetDataSizeFromKeyAndFileSize(const std::string& key, int64 file_size) { 96 int64 data_size = file_size - key.size() - sizeof(SimpleFileHeader) - 97 sizeof(SimpleFileEOF); 98 DCHECK_GE(implicit_cast<int64>(std::numeric_limits<int32>::max()), data_size); 99 return data_size; 100 } 101 102 int64 GetFileSizeFromKeyAndDataSize(const std::string& key, int32 data_size) { 103 return data_size + key.size() + sizeof(SimpleFileHeader) + 104 sizeof(SimpleFileEOF); 105 } 106 107 int GetFileIndexFromStreamIndex(int stream_index) { 108 return (stream_index == 2) ? 1 : 0; 109 } 110 111 // TODO(clamy, gavinp): this should go in base 112 bool GetMTime(const base::FilePath& path, base::Time* out_mtime) { 113 DCHECK(out_mtime); 114 #if defined(OS_POSIX) 115 base::ThreadRestrictions::AssertIOAllowed(); 116 struct stat file_stat; 117 if (stat(path.value().c_str(), &file_stat) != 0) 118 return false; 119 time_t sec; 120 long nsec; 121 if (GetNanoSecsFromStat(file_stat, &sec, &nsec)) { 122 int64 usec = (nsec / base::Time::kNanosecondsPerMicrosecond); 123 *out_mtime = base::Time::FromTimeT(sec) 124 + base::TimeDelta::FromMicroseconds(usec); 125 return true; 126 } 127 #endif 128 base::PlatformFileInfo file_info; 129 if (!base::GetFileInfo(path, &file_info)) 130 return false; 131 *out_mtime = file_info.last_modified; 132 return true; 133 } 134 135 } // namespace simple_backend 136 137 } // namespace disk_cache 138