blob: 94cec80c8ae3720654cbad6282891db9d0137e44 [file] [log] [blame]
[email protected]a3703dd2010-02-11 17:46:131// Copyright (c) 2010 The Chromium Authors. All rights reserved.
[email protected]da34ae02009-09-22 20:41:202// 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/database/vfs_backend.h"
6
7#if defined(USE_SYSTEM_SQLITE)
8#include <sqlite3.h>
9#else
10#include "third_party/sqlite/preprocessed/sqlite3.h"
11#endif
12
13#include "base/file_path.h"
14#include "base/file_util.h"
[email protected]3c5ed2c2009-11-13 01:30:4515#include "base/logging.h"
[email protected]da34ae02009-09-22 20:41:2016
17namespace webkit_database {
18
[email protected]a3703dd2010-02-11 17:46:1319static const int kFileTypeMask = 0x00007F00;
20
21// static
[email protected]fe615f32010-06-13 09:08:4122void VfsBackend::GetFileHandleForProcess(base::ProcessHandle process_handle,
23 const base::PlatformFile& file_handle,
24 base::PlatformFile* target_handle,
25 bool close_source_handle) {
26 if (file_handle == base::kInvalidPlatformFileValue) {
27 *target_handle = base::kInvalidPlatformFileValue;
28 return;
29 }
30
31#if defined(OS_WIN)
32 // Duplicate the file handle.
33 if (!DuplicateHandle(GetCurrentProcess(), file_handle,
34 process_handle, target_handle, 0, false,
35 DUPLICATE_SAME_ACCESS |
36 (close_source_handle ? DUPLICATE_CLOSE_SOURCE : 0))) {
37 // file_handle is closed whether or not DuplicateHandle succeeds.
38 *target_handle = INVALID_HANDLE_VALUE;
39 }
40#elif defined(OS_POSIX)
41 *target_handle = file_handle;
42#endif
43}
44
45// static
[email protected]a3703dd2010-02-11 17:46:1346bool VfsBackend::FileTypeIsMainDB(int desired_flags) {
47 return (desired_flags & kFileTypeMask) == SQLITE_OPEN_MAIN_DB;
48}
49
50// static
[email protected]fe615f32010-06-13 09:08:4151bool VfsBackend::FileTypeIsJournal(int desired_flags) {
52 int file_type = desired_flags & kFileTypeMask;
53 return ((file_type == SQLITE_OPEN_MAIN_JOURNAL) ||
54 (file_type == SQLITE_OPEN_TEMP_JOURNAL) ||
55 (file_type == SQLITE_OPEN_SUBJOURNAL) ||
56 (file_type == SQLITE_OPEN_MASTER_JOURNAL));
57}
58
59// static
[email protected]a3703dd2010-02-11 17:46:1360bool VfsBackend::OpenTypeIsReadWrite(int desired_flags) {
[email protected]2f312ab2010-04-21 07:17:4161 return (desired_flags & SQLITE_OPEN_READWRITE) != 0;
[email protected]a3703dd2010-02-11 17:46:1362}
63
64// static
[email protected]3c5ed2c2009-11-13 01:30:4565bool VfsBackend::OpenFileFlagsAreConsistent(int desired_flags) {
[email protected]a3703dd2010-02-11 17:46:1366 const int file_type = desired_flags & kFileTypeMask;
[email protected]da34ae02009-09-22 20:41:2067 const bool is_exclusive = (desired_flags & SQLITE_OPEN_EXCLUSIVE) != 0;
68 const bool is_delete = (desired_flags & SQLITE_OPEN_DELETEONCLOSE) != 0;
69 const bool is_create = (desired_flags & SQLITE_OPEN_CREATE) != 0;
70 const bool is_read_only = (desired_flags & SQLITE_OPEN_READONLY) != 0;
71 const bool is_read_write = (desired_flags & SQLITE_OPEN_READWRITE) != 0;
72
[email protected]b5be3f532009-10-24 01:28:3973 // All files should be opened either read-write or read-only, but not both.
74 if (is_read_only == is_read_write)
[email protected]da34ae02009-09-22 20:41:2075 return false;
[email protected]da34ae02009-09-22 20:41:2076
[email protected]b5be3f532009-10-24 01:28:3977 // If a new file is created, it must also be writable.
78 if (is_create && !is_read_write)
[email protected]da34ae02009-09-22 20:41:2079 return false;
[email protected]da34ae02009-09-22 20:41:2080
[email protected]b5be3f532009-10-24 01:28:3981 // If we're accessing an existing file, we cannot give exclusive access, and
82 // we can't delete it.
[email protected]fe615f32010-06-13 09:08:4183 // Normally, we'd also check that 'is_delete' is false for a main DB, main
84 // journal or master journal file; however, when in incognito mode, we use
85 // the SQLITE_OPEN_DELETEONCLOSE flag when opening those files too and keep
86 // an open handle to them for as long as the incognito profile is around.
[email protected]b5be3f532009-10-24 01:28:3987 if ((is_exclusive || is_delete) && !is_create)
[email protected]da34ae02009-09-22 20:41:2088 return false;
[email protected]da34ae02009-09-22 20:41:2089
[email protected]da34ae02009-09-22 20:41:2090 // Make sure we're opening the DB directory or that a file type is set.
[email protected]b5be3f532009-10-24 01:28:3991 return (file_type == SQLITE_OPEN_MAIN_DB) ||
92 (file_type == SQLITE_OPEN_TEMP_DB) ||
93 (file_type == SQLITE_OPEN_MAIN_JOURNAL) ||
94 (file_type == SQLITE_OPEN_TEMP_JOURNAL) ||
95 (file_type == SQLITE_OPEN_SUBJOURNAL) ||
96 (file_type == SQLITE_OPEN_MASTER_JOURNAL) ||
97 (file_type == SQLITE_OPEN_TRANSIENT_DB);
[email protected]da34ae02009-09-22 20:41:2098}
99
[email protected]a3703dd2010-02-11 17:46:13100// static
[email protected]3c5ed2c2009-11-13 01:30:45101void VfsBackend::OpenFile(const FilePath& file_path,
[email protected]b5be3f532009-10-24 01:28:39102 int desired_flags,
[email protected]fe615f32010-06-13 09:08:41103 base::PlatformFile* file_handle) {
[email protected]3c5ed2c2009-11-13 01:30:45104 DCHECK(!file_path.empty());
105
[email protected]da34ae02009-09-22 20:41:20106 // Verify the flags for consistency and create the database
107 // directory if it doesn't exist.
[email protected]3c5ed2c2009-11-13 01:30:45108 if (!OpenFileFlagsAreConsistent(desired_flags) ||
109 !file_util::CreateDirectory(file_path.DirName()))
[email protected]c93efc7c52009-10-29 19:58:30110 return;
[email protected]da34ae02009-09-22 20:41:20111
[email protected]c93efc7c52009-10-29 19:58:30112 int flags = 0;
113 flags |= base::PLATFORM_FILE_READ;
114 if (desired_flags & SQLITE_OPEN_READWRITE)
115 flags |= base::PLATFORM_FILE_WRITE;
[email protected]da34ae02009-09-22 20:41:20116
[email protected]c93efc7c52009-10-29 19:58:30117 if (!(desired_flags & SQLITE_OPEN_MAIN_DB)) {
118 flags |= base::PLATFORM_FILE_EXCLUSIVE_READ |
119 base::PLATFORM_FILE_EXCLUSIVE_WRITE;
120 }
[email protected]da34ae02009-09-22 20:41:20121
[email protected]c93efc7c52009-10-29 19:58:30122 flags |= ((desired_flags & SQLITE_OPEN_CREATE) ?
123 base::PLATFORM_FILE_OPEN_ALWAYS : base::PLATFORM_FILE_OPEN);
[email protected]da34ae02009-09-22 20:41:20124
[email protected]c93efc7c52009-10-29 19:58:30125 if (desired_flags & SQLITE_OPEN_EXCLUSIVE) {
126 flags |= base::PLATFORM_FILE_EXCLUSIVE_READ |
127 base::PLATFORM_FILE_EXCLUSIVE_WRITE;
128 }
[email protected]da34ae02009-09-22 20:41:20129
[email protected]c93efc7c52009-10-29 19:58:30130 if (desired_flags & SQLITE_OPEN_DELETEONCLOSE) {
131 flags |= base::PLATFORM_FILE_TEMPORARY | base::PLATFORM_FILE_HIDDEN |
132 base::PLATFORM_FILE_DELETE_ON_CLOSE;
133 }
[email protected]da34ae02009-09-22 20:41:20134
[email protected]c93efc7c52009-10-29 19:58:30135 // Try to open/create the DB file.
[email protected]fe615f32010-06-13 09:08:41136 *file_handle =
[email protected]3c5ed2c2009-11-13 01:30:45137 base::CreatePlatformFile(file_path.ToWStringHack(), flags, NULL);
[email protected]da34ae02009-09-22 20:41:20138}
139
[email protected]a3703dd2010-02-11 17:46:13140// static
[email protected]3c5ed2c2009-11-13 01:30:45141void VfsBackend::OpenTempFileInDirectory(
142 const FilePath& dir_path,
143 int desired_flags,
[email protected]fe615f32010-06-13 09:08:41144 base::PlatformFile* file_handle) {
[email protected]3c5ed2c2009-11-13 01:30:45145 // We should be able to delete temp files when they're closed
146 // and create them as needed
147 if (!(desired_flags & SQLITE_OPEN_DELETEONCLOSE) ||
148 !(desired_flags & SQLITE_OPEN_CREATE)) {
149 return;
150 }
151
152 // Get a unique temp file name in the database directory.
153 FilePath temp_file_path;
154 if (!file_util::CreateTemporaryFileInDir(dir_path, &temp_file_path))
155 return;
156
[email protected]fe615f32010-06-13 09:08:41157 OpenFile(temp_file_path, desired_flags, file_handle);
[email protected]3c5ed2c2009-11-13 01:30:45158}
159
[email protected]a3703dd2010-02-11 17:46:13160// static
[email protected]3c5ed2c2009-11-13 01:30:45161int VfsBackend::DeleteFile(const FilePath& file_path, bool sync_dir) {
162 if (!file_util::PathExists(file_path))
[email protected]da34ae02009-09-22 20:41:20163 return SQLITE_OK;
[email protected]3c5ed2c2009-11-13 01:30:45164 if (!file_util::Delete(file_path, false))
[email protected]da34ae02009-09-22 20:41:20165 return SQLITE_IOERR_DELETE;
[email protected]da34ae02009-09-22 20:41:20166
167 int error_code = SQLITE_OK;
168#if defined(OS_POSIX)
169 if (sync_dir) {
170 base::PlatformFile dir_fd = base::CreatePlatformFile(
[email protected]3c5ed2c2009-11-13 01:30:45171 file_path.DirName().ToWStringHack(), base::PLATFORM_FILE_READ, NULL);
[email protected]da34ae02009-09-22 20:41:20172 if (dir_fd == base::kInvalidPlatformFileValue) {
173 error_code = SQLITE_CANTOPEN;
174 } else {
[email protected]b5be3f532009-10-24 01:28:39175 if (fsync(dir_fd))
[email protected]da34ae02009-09-22 20:41:20176 error_code = SQLITE_IOERR_DIR_FSYNC;
[email protected]da34ae02009-09-22 20:41:20177 base::ClosePlatformFile(dir_fd);
178 }
179 }
180#endif
181 return error_code;
182}
183
[email protected]a3703dd2010-02-11 17:46:13184// static
[email protected]3c5ed2c2009-11-13 01:30:45185uint32 VfsBackend::GetFileAttributes(const FilePath& file_path) {
[email protected]da34ae02009-09-22 20:41:20186#if defined(OS_WIN)
[email protected]3c5ed2c2009-11-13 01:30:45187 uint32 attributes = ::GetFileAttributes(file_path.value().c_str());
[email protected]da34ae02009-09-22 20:41:20188#elif defined(OS_POSIX)
189 uint32 attributes = 0;
[email protected]3c5ed2c2009-11-13 01:30:45190 if (!access(file_path.value().c_str(), R_OK))
[email protected]da34ae02009-09-22 20:41:20191 attributes |= static_cast<uint32>(R_OK);
[email protected]3c5ed2c2009-11-13 01:30:45192 if (!access(file_path.value().c_str(), W_OK))
[email protected]da34ae02009-09-22 20:41:20193 attributes |= static_cast<uint32>(W_OK);
[email protected]b5be3f532009-10-24 01:28:39194 if (!attributes)
[email protected]da34ae02009-09-22 20:41:20195 attributes = -1;
[email protected]da34ae02009-09-22 20:41:20196#endif
197 return attributes;
198}
199
[email protected]a3703dd2010-02-11 17:46:13200// static
[email protected]3c5ed2c2009-11-13 01:30:45201int64 VfsBackend::GetFileSize(const FilePath& file_path) {
[email protected]da34ae02009-09-22 20:41:20202 int64 size = 0;
[email protected]3c5ed2c2009-11-13 01:30:45203 return (file_util::GetFileSize(file_path, &size) ? size : 0);
[email protected]da34ae02009-09-22 20:41:20204}
205
[email protected]b5be3f532009-10-24 01:28:39206} // namespace webkit_database