OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 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 "webkit/browser/database/vfs_backend.h" | |
6 | |
7 #include "base/file_util.h" | |
8 #include "base/files/file_path.h" | |
9 #include "base/logging.h" | |
10 #include "third_party/sqlite/sqlite3.h" | |
11 | |
12 namespace storage { | |
13 | |
14 static const int kFileTypeMask = 0x00007F00; | |
15 | |
16 // static | |
17 bool VfsBackend::OpenTypeIsReadWrite(int desired_flags) { | |
18 return (desired_flags & SQLITE_OPEN_READWRITE) != 0; | |
19 } | |
20 | |
21 // static | |
22 bool VfsBackend::OpenFileFlagsAreConsistent(int desired_flags) { | |
23 const int file_type = desired_flags & kFileTypeMask; | |
24 const bool is_exclusive = (desired_flags & SQLITE_OPEN_EXCLUSIVE) != 0; | |
25 const bool is_delete = (desired_flags & SQLITE_OPEN_DELETEONCLOSE) != 0; | |
26 const bool is_create = (desired_flags & SQLITE_OPEN_CREATE) != 0; | |
27 const bool is_read_only = (desired_flags & SQLITE_OPEN_READONLY) != 0; | |
28 const bool is_read_write = (desired_flags & SQLITE_OPEN_READWRITE) != 0; | |
29 | |
30 // All files should be opened either read-write or read-only, but not both. | |
31 if (is_read_only == is_read_write) | |
32 return false; | |
33 | |
34 // If a new file is created, it must also be writable. | |
35 if (is_create && !is_read_write) | |
36 return false; | |
37 | |
38 // If we're accessing an existing file, we cannot give exclusive access, and | |
39 // we can't delete it. | |
40 // Normally, we'd also check that 'is_delete' is false for a main DB, main | |
41 // journal or master journal file; however, when in incognito mode, we use | |
42 // the SQLITE_OPEN_DELETEONCLOSE flag when opening those files too and keep | |
43 // an open handle to them for as long as the incognito profile is around. | |
44 if ((is_exclusive || is_delete) && !is_create) | |
45 return false; | |
46 | |
47 // Make sure we're opening the DB directory or that a file type is set. | |
48 return (file_type == SQLITE_OPEN_MAIN_DB) || | |
49 (file_type == SQLITE_OPEN_TEMP_DB) || | |
50 (file_type == SQLITE_OPEN_MAIN_JOURNAL) || | |
51 (file_type == SQLITE_OPEN_TEMP_JOURNAL) || | |
52 (file_type == SQLITE_OPEN_SUBJOURNAL) || | |
53 (file_type == SQLITE_OPEN_MASTER_JOURNAL) || | |
54 (file_type == SQLITE_OPEN_TRANSIENT_DB); | |
55 } | |
56 | |
57 // static | |
58 base::File VfsBackend::OpenFile(const base::FilePath& file_path, | |
59 int desired_flags) { | |
60 DCHECK(!file_path.empty()); | |
61 | |
62 // Verify the flags for consistency and create the database | |
63 // directory if it doesn't exist. | |
64 if (!OpenFileFlagsAreConsistent(desired_flags) || | |
65 !base::CreateDirectory(file_path.DirName())) { | |
66 return base::File(); | |
67 } | |
68 | |
69 int flags = 0; | |
70 flags |= base::File::FLAG_READ; | |
71 if (desired_flags & SQLITE_OPEN_READWRITE) | |
72 flags |= base::File::FLAG_WRITE; | |
73 | |
74 if (!(desired_flags & SQLITE_OPEN_MAIN_DB)) | |
75 flags |= base::File::FLAG_EXCLUSIVE_READ | base::File::FLAG_EXCLUSIVE_WRITE; | |
76 | |
77 flags |= ((desired_flags & SQLITE_OPEN_CREATE) ? | |
78 base::File::FLAG_OPEN_ALWAYS : base::File::FLAG_OPEN); | |
79 | |
80 if (desired_flags & SQLITE_OPEN_EXCLUSIVE) | |
81 flags |= base::File::FLAG_EXCLUSIVE_READ | base::File::FLAG_EXCLUSIVE_WRITE; | |
82 | |
83 if (desired_flags & SQLITE_OPEN_DELETEONCLOSE) { | |
84 flags |= base::File::FLAG_TEMPORARY | base::File::FLAG_HIDDEN | | |
85 base::File::FLAG_DELETE_ON_CLOSE; | |
86 } | |
87 | |
88 // This flag will allow us to delete the file later on from the browser | |
89 // process. | |
90 flags |= base::File::FLAG_SHARE_DELETE; | |
91 | |
92 // Try to open/create the DB file. | |
93 return base::File(file_path, flags); | |
94 } | |
95 | |
96 // static | |
97 base::File VfsBackend::OpenTempFileInDirectory(const base::FilePath& dir_path, | |
98 int desired_flags) { | |
99 // We should be able to delete temp files when they're closed | |
100 // and create them as needed | |
101 if (!(desired_flags & SQLITE_OPEN_DELETEONCLOSE) || | |
102 !(desired_flags & SQLITE_OPEN_CREATE)) { | |
103 return base::File(); | |
104 } | |
105 | |
106 // Get a unique temp file name in the database directory. | |
107 base::FilePath temp_file_path; | |
108 if (!base::CreateTemporaryFileInDir(dir_path, &temp_file_path)) | |
109 return base::File(); | |
110 | |
111 return OpenFile(temp_file_path, desired_flags); | |
112 } | |
113 | |
114 // static | |
115 int VfsBackend::DeleteFile(const base::FilePath& file_path, bool sync_dir) { | |
116 if (!base::PathExists(file_path)) | |
117 return SQLITE_OK; | |
118 if (!base::DeleteFile(file_path, false)) | |
119 return SQLITE_IOERR_DELETE; | |
120 | |
121 int error_code = SQLITE_OK; | |
122 #if defined(OS_POSIX) | |
123 if (sync_dir) { | |
124 base::File dir(file_path.DirName(), base::File::FLAG_READ); | |
125 if (dir.IsValid()) { | |
126 if (!dir.Flush()) | |
127 error_code = SQLITE_IOERR_DIR_FSYNC; | |
128 } else { | |
129 error_code = SQLITE_CANTOPEN; | |
130 } | |
131 } | |
132 #endif | |
133 return error_code; | |
134 } | |
135 | |
136 // static | |
137 uint32 VfsBackend::GetFileAttributes(const base::FilePath& file_path) { | |
138 #if defined(OS_WIN) | |
139 uint32 attributes = ::GetFileAttributes(file_path.value().c_str()); | |
140 #elif defined(OS_POSIX) | |
141 uint32 attributes = 0; | |
142 if (!access(file_path.value().c_str(), R_OK)) | |
143 attributes |= static_cast<uint32>(R_OK); | |
144 if (!access(file_path.value().c_str(), W_OK)) | |
145 attributes |= static_cast<uint32>(W_OK); | |
146 if (!attributes) | |
147 attributes = -1; | |
148 #endif | |
149 return attributes; | |
150 } | |
151 | |
152 // static | |
153 int64 VfsBackend::GetFileSize(const base::FilePath& file_path) { | |
154 int64 size = 0; | |
155 return (base::GetFileSize(file_path, &size) ? size : 0); | |
156 } | |
157 | |
158 } // namespace storage | |
OLD | NEW |