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 19namespace { 20 21// Size of the uint64 hash_key number in Hex format in a string. 22const size_t kEntryHashKeyAsHexStringSize = 2 * sizeof(uint64); 23 24// TODO(clamy, gavinp): this should go in base 25bool 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 47namespace disk_cache { 48 49namespace simple_util { 50 51std::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 57std::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 64bool 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 72uint64 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 82std::string GetFilenameFromEntryHashAndFileIndex(uint64 entry_hash, 83 int file_index) { 84 return base::StringPrintf("%016" PRIx64 "_%1d", entry_hash, file_index); 85} 86 87std::string GetSparseFilenameFromEntryHash(uint64 entry_hash) { 88 return base::StringPrintf("%016" PRIx64 "_s", entry_hash); 89} 90 91std::string GetFilenameFromKeyAndFileIndex(const std::string& key, 92 int file_index) { 93 return GetEntryHashKeyAsHexString(key) + 94 base::StringPrintf("_%1d", file_index); 95} 96 97int32 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 104int64 GetFileSizeFromKeyAndDataSize(const std::string& key, int32 data_size) { 105 return data_size + key.size() + sizeof(SimpleFileHeader) + 106 sizeof(SimpleFileEOF); 107} 108 109int GetFileIndexFromStreamIndex(int stream_index) { 110 return (stream_index == 2) ? 1 : 0; 111} 112 113// TODO(clamy, gavinp): this should go in base 114bool 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