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