OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "storage/browser/fileapi/sandbox_directory_database.h" | 5 #include "storage/browser/fileapi/sandbox_directory_database.h" |
6 | 6 |
7 #include <math.h> | 7 #include <math.h> |
8 #include <algorithm> | 8 #include <algorithm> |
9 #include <set> | 9 #include <set> |
10 #include <stack> | 10 #include <stack> |
11 | 11 |
12 #include "base/files/file_enumerator.h" | 12 #include "base/files/file_enumerator.h" |
13 #include "base/files/file_util.h" | 13 #include "base/files/file_util.h" |
14 #include "base/location.h" | 14 #include "base/location.h" |
15 #include "base/metrics/histogram.h" | 15 #include "base/metrics/histogram.h" |
16 #include "base/pickle.h" | 16 #include "base/pickle.h" |
17 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
18 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
19 #include "storage/browser/fileapi/file_system_usage_cache.h" | 19 #include "storage/browser/fileapi/file_system_usage_cache.h" |
20 #include "storage/common/fileapi/file_system_util.h" | 20 #include "storage/common/fileapi/file_system_util.h" |
21 #include "third_party/leveldatabase/env_chromium.h" | 21 #include "third_party/leveldatabase/env_chromium.h" |
22 #include "third_party/leveldatabase/src/include/leveldb/db.h" | 22 #include "third_party/leveldatabase/src/include/leveldb/db.h" |
23 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h" | 23 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h" |
24 | 24 |
25 namespace { | 25 namespace { |
26 | 26 |
27 bool PickleFromFileInfo(const storage::SandboxDirectoryDatabase::FileInfo& info, | 27 bool PickleFromFileInfo(const storage::SandboxDirectoryDatabase::FileInfo& info, |
28 Pickle* pickle) { | 28 base::Pickle* pickle) { |
29 DCHECK(pickle); | 29 DCHECK(pickle); |
30 std::string data_path; | 30 std::string data_path; |
31 // Round off here to match the behavior of the filesystem on real files. | 31 // Round off here to match the behavior of the filesystem on real files. |
32 base::Time time = | 32 base::Time time = |
33 base::Time::FromDoubleT(floor(info.modification_time.ToDoubleT())); | 33 base::Time::FromDoubleT(floor(info.modification_time.ToDoubleT())); |
34 std::string name; | 34 std::string name; |
35 | 35 |
36 data_path = storage::FilePathToString(info.data_path); | 36 data_path = storage::FilePathToString(info.data_path); |
37 name = storage::FilePathToString(base::FilePath(info.name)); | 37 name = storage::FilePathToString(base::FilePath(info.name)); |
38 | 38 |
39 if (pickle->WriteInt64(info.parent_id) && | 39 if (pickle->WriteInt64(info.parent_id) && |
40 pickle->WriteString(data_path) && | 40 pickle->WriteString(data_path) && |
41 pickle->WriteString(name) && | 41 pickle->WriteString(name) && |
42 pickle->WriteInt64(time.ToInternalValue())) | 42 pickle->WriteInt64(time.ToInternalValue())) |
43 return true; | 43 return true; |
44 | 44 |
45 NOTREACHED(); | 45 NOTREACHED(); |
46 return false; | 46 return false; |
47 } | 47 } |
48 | 48 |
49 bool FileInfoFromPickle(const Pickle& pickle, | 49 bool FileInfoFromPickle(const base::Pickle& pickle, |
50 storage::SandboxDirectoryDatabase::FileInfo* info) { | 50 storage::SandboxDirectoryDatabase::FileInfo* info) { |
51 PickleIterator iter(pickle); | 51 base::PickleIterator iter(pickle); |
52 std::string data_path; | 52 std::string data_path; |
53 std::string name; | 53 std::string name; |
54 int64 internal_time; | 54 int64 internal_time; |
55 | 55 |
56 if (iter.ReadInt64(&info->parent_id) && | 56 if (iter.ReadInt64(&info->parent_id) && |
57 iter.ReadString(&data_path) && | 57 iter.ReadString(&data_path) && |
58 iter.ReadString(&name) && | 58 iter.ReadString(&name) && |
59 iter.ReadInt64(&internal_time)) { | 59 iter.ReadInt64(&internal_time)) { |
60 info->data_path = storage::StringToFilePath(data_path); | 60 info->data_path = storage::StringToFilePath(data_path); |
61 info->name = storage::StringToFilePath(name).value(); | 61 info->name = storage::StringToFilePath(name).value(); |
62 info->modification_time = base::Time::FromInternalValue(internal_time); | 62 info->modification_time = base::Time::FromInternalValue(internal_time); |
63 return true; | 63 return true; |
64 } | 64 } |
65 LOG(ERROR) << "Pickle could not be digested!"; | 65 LOG(ERROR) << "base::Pickle could not be digested!"; |
66 return false; | 66 return false; |
67 } | 67 } |
68 | 68 |
69 const base::FilePath::CharType kDirectoryDatabaseName[] = | 69 const base::FilePath::CharType kDirectoryDatabaseName[] = |
70 FILE_PATH_LITERAL("Paths"); | 70 FILE_PATH_LITERAL("Paths"); |
71 const char kChildLookupPrefix[] = "CHILD_OF:"; | 71 const char kChildLookupPrefix[] = "CHILD_OF:"; |
72 const char kChildLookupSeparator[] = ":"; | 72 const char kChildLookupSeparator[] = ":"; |
73 const char kLastFileIdKey[] = "LAST_FILE_ID"; | 73 const char kLastFileIdKey[] = "LAST_FILE_ID"; |
74 const char kLastIntegerKey[] = "LAST_INTEGER"; | 74 const char kLastIntegerKey[] = "LAST_INTEGER"; |
75 const int64 kMinimumReportIntervalHours = 1; | 75 const int64 kMinimumReportIntervalHours = 1; |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 // key: "LAST_INTEGER" | 217 // key: "LAST_INTEGER" |
218 // value: "<last_integer>" | 218 // value: "<last_integer>" |
219 if (last_integer_ >= 0 || | 219 if (last_integer_ >= 0 || |
220 !base::StringToInt64(itr->value().ToString(), &last_integer_)) | 220 !base::StringToInt64(itr->value().ToString(), &last_integer_)) |
221 return false; | 221 return false; |
222 } else { | 222 } else { |
223 // key: "<entry_id>" | 223 // key: "<entry_id>" |
224 // value: "<pickled FileInfo>" | 224 // value: "<pickled FileInfo>" |
225 FileInfo file_info; | 225 FileInfo file_info; |
226 if (!FileInfoFromPickle( | 226 if (!FileInfoFromPickle( |
227 Pickle(itr->value().data(), itr->value().size()), &file_info)) | 227 base::Pickle(itr->value().data(), itr->value().size()), |
| 228 &file_info)) |
228 return false; | 229 return false; |
229 | 230 |
230 FileId file_id = -1; | 231 FileId file_id = -1; |
231 if (!base::StringToInt64(key, &file_id) || file_id < 0) | 232 if (!base::StringToInt64(key, &file_id) || file_id < 0) |
232 return false; | 233 return false; |
233 | 234 |
234 if (max_file_id < file_id) | 235 if (max_file_id < file_id) |
235 max_file_id = file_id; | 236 max_file_id = file_id; |
236 if (!file_ids.insert(file_id).second) | 237 if (!file_ids.insert(file_id).second) |
237 return false; | 238 return false; |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
491 bool SandboxDirectoryDatabase::GetFileInfo(FileId file_id, FileInfo* info) { | 492 bool SandboxDirectoryDatabase::GetFileInfo(FileId file_id, FileInfo* info) { |
492 if (!Init(REPAIR_ON_CORRUPTION)) | 493 if (!Init(REPAIR_ON_CORRUPTION)) |
493 return false; | 494 return false; |
494 DCHECK(info); | 495 DCHECK(info); |
495 std::string file_key = GetFileLookupKey(file_id); | 496 std::string file_key = GetFileLookupKey(file_id); |
496 std::string file_data_string; | 497 std::string file_data_string; |
497 leveldb::Status status = | 498 leveldb::Status status = |
498 db_->Get(leveldb::ReadOptions(), file_key, &file_data_string); | 499 db_->Get(leveldb::ReadOptions(), file_key, &file_data_string); |
499 if (status.ok()) { | 500 if (status.ok()) { |
500 bool success = FileInfoFromPickle( | 501 bool success = FileInfoFromPickle( |
501 Pickle(file_data_string.data(), file_data_string.length()), info); | 502 base::Pickle(file_data_string.data(), file_data_string.length()), info); |
502 if (!success) | 503 if (!success) |
503 return false; | 504 return false; |
504 if (!VerifyDataPath(info->data_path)) { | 505 if (!VerifyDataPath(info->data_path)) { |
505 LOG(ERROR) << "Resolved data path is invalid: " | 506 LOG(ERROR) << "Resolved data path is invalid: " |
506 << info->data_path.value(); | 507 << info->data_path.value(); |
507 return false; | 508 return false; |
508 } | 509 } |
509 return true; | 510 return true; |
510 } | 511 } |
511 // Special-case the root, for databases that haven't been initialized yet. | 512 // Special-case the root, for databases that haven't been initialized yet. |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
614 } | 615 } |
615 return true; | 616 return true; |
616 } | 617 } |
617 | 618 |
618 bool SandboxDirectoryDatabase::UpdateModificationTime( | 619 bool SandboxDirectoryDatabase::UpdateModificationTime( |
619 FileId file_id, const base::Time& modification_time) { | 620 FileId file_id, const base::Time& modification_time) { |
620 FileInfo info; | 621 FileInfo info; |
621 if (!GetFileInfo(file_id, &info)) | 622 if (!GetFileInfo(file_id, &info)) |
622 return false; | 623 return false; |
623 info.modification_time = modification_time; | 624 info.modification_time = modification_time; |
624 Pickle pickle; | 625 base::Pickle pickle; |
625 if (!PickleFromFileInfo(info, &pickle)) | 626 if (!PickleFromFileInfo(info, &pickle)) |
626 return false; | 627 return false; |
627 leveldb::Status status = db_->Put( | 628 leveldb::Status status = db_->Put( |
628 leveldb::WriteOptions(), | 629 leveldb::WriteOptions(), |
629 GetFileLookupKey(file_id), | 630 GetFileLookupKey(file_id), |
630 leveldb::Slice(reinterpret_cast<const char *>(pickle.data()), | 631 leveldb::Slice(reinterpret_cast<const char *>(pickle.data()), |
631 pickle.size())); | 632 pickle.size())); |
632 if (!status.ok()) { | 633 if (!status.ok()) { |
633 HandleError(FROM_HERE, status); | 634 HandleError(FROM_HERE, status); |
634 return false; | 635 return false; |
(...skipping 11 matching lines...) Expand all Loading... |
646 if (!GetFileInfo(dest_file_id, &dest_file_info)) | 647 if (!GetFileInfo(dest_file_id, &dest_file_info)) |
647 return false; | 648 return false; |
648 if (src_file_info.is_directory() || dest_file_info.is_directory()) | 649 if (src_file_info.is_directory() || dest_file_info.is_directory()) |
649 return false; | 650 return false; |
650 leveldb::WriteBatch batch; | 651 leveldb::WriteBatch batch; |
651 // This is the only field that really gets moved over; if you add fields to | 652 // This is the only field that really gets moved over; if you add fields to |
652 // FileInfo, e.g. ctime, they might need to be copied here. | 653 // FileInfo, e.g. ctime, they might need to be copied here. |
653 dest_file_info.data_path = src_file_info.data_path; | 654 dest_file_info.data_path = src_file_info.data_path; |
654 if (!RemoveFileInfoHelper(src_file_id, &batch)) | 655 if (!RemoveFileInfoHelper(src_file_id, &batch)) |
655 return false; | 656 return false; |
656 Pickle pickle; | 657 base::Pickle pickle; |
657 if (!PickleFromFileInfo(dest_file_info, &pickle)) | 658 if (!PickleFromFileInfo(dest_file_info, &pickle)) |
658 return false; | 659 return false; |
659 batch.Put( | 660 batch.Put( |
660 GetFileLookupKey(dest_file_id), | 661 GetFileLookupKey(dest_file_id), |
661 leveldb::Slice(reinterpret_cast<const char *>(pickle.data()), | 662 leveldb::Slice(reinterpret_cast<const char *>(pickle.data()), |
662 pickle.size())); | 663 pickle.size())); |
663 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch); | 664 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch); |
664 if (!status.ok()) { | 665 if (!status.ok()) { |
665 HandleError(FROM_HERE, status); | 666 HandleError(FROM_HERE, status); |
666 return false; | 667 return false; |
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
892 } | 893 } |
893 std::string id_string = GetFileLookupKey(file_id); | 894 std::string id_string = GetFileLookupKey(file_id); |
894 if (!file_id) { | 895 if (!file_id) { |
895 // The root directory doesn't need to be looked up by path from its parent. | 896 // The root directory doesn't need to be looked up by path from its parent. |
896 DCHECK(!info.parent_id); | 897 DCHECK(!info.parent_id); |
897 DCHECK(info.data_path.empty()); | 898 DCHECK(info.data_path.empty()); |
898 } else { | 899 } else { |
899 std::string child_key = GetChildLookupKey(info.parent_id, info.name); | 900 std::string child_key = GetChildLookupKey(info.parent_id, info.name); |
900 batch->Put(child_key, id_string); | 901 batch->Put(child_key, id_string); |
901 } | 902 } |
902 Pickle pickle; | 903 base::Pickle pickle; |
903 if (!PickleFromFileInfo(info, &pickle)) | 904 if (!PickleFromFileInfo(info, &pickle)) |
904 return false; | 905 return false; |
905 batch->Put( | 906 batch->Put( |
906 id_string, | 907 id_string, |
907 leveldb::Slice(reinterpret_cast<const char *>(pickle.data()), | 908 leveldb::Slice(reinterpret_cast<const char *>(pickle.data()), |
908 pickle.size())); | 909 pickle.size())); |
909 return true; | 910 return true; |
910 } | 911 } |
911 | 912 |
912 // This does very few safety checks! | 913 // This does very few safety checks! |
(...skipping 20 matching lines...) Expand all Loading... |
933 | 934 |
934 void SandboxDirectoryDatabase::HandleError( | 935 void SandboxDirectoryDatabase::HandleError( |
935 const tracked_objects::Location& from_here, | 936 const tracked_objects::Location& from_here, |
936 const leveldb::Status& status) { | 937 const leveldb::Status& status) { |
937 LOG(ERROR) << "SandboxDirectoryDatabase failed at: " | 938 LOG(ERROR) << "SandboxDirectoryDatabase failed at: " |
938 << from_here.ToString() << " with error: " << status.ToString(); | 939 << from_here.ToString() << " with error: " << status.ToString(); |
939 db_.reset(); | 940 db_.reset(); |
940 } | 941 } |
941 | 942 |
942 } // namespace storage | 943 } // namespace storage |
OLD | NEW |