blob: 6e54f1b0a7884c53fb94ee4086b09b69783f618b [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
[email protected]da34ae02009-09-22 20:41:207#include "base/file_path.h"
8#include "base/file_util.h"
[email protected]3c5ed2c2009-11-13 01:30:459#include "base/logging.h"
[email protected]e33cba42010-08-18 23:37:0310#include "third_party/sqlite/sqlite3.h"
[email protected]da34ae02009-09-22 20:41:2011
12namespace webkit_database {
13
[email protected]a3703dd2010-02-11 17:46:1314static const int kFileTypeMask = 0x00007F00;
15
16// static
[email protected]fe615f32010-06-13 09:08:4117void VfsBackend::GetFileHandleForProcess(base::ProcessHandle process_handle,
18 const base::PlatformFile& file_handle,
19 base::PlatformFile* target_handle,
20 bool close_source_handle) {
21 if (file_handle == base::kInvalidPlatformFileValue) {
22 *target_handle = base::kInvalidPlatformFileValue;
23 return;
24 }
25
26#if defined(OS_WIN)
27 // Duplicate the file handle.
28 if (!DuplicateHandle(GetCurrentProcess(), file_handle,
29 process_handle, target_handle, 0, false,
30 DUPLICATE_SAME_ACCESS |
31 (close_source_handle ? DUPLICATE_CLOSE_SOURCE : 0))) {
32 // file_handle is closed whether or not DuplicateHandle succeeds.
33 *target_handle = INVALID_HANDLE_VALUE;
34 }
35#elif defined(OS_POSIX)
36 *target_handle = file_handle;
37#endif
38}
39
40// static
[email protected]a3703dd2010-02-11 17:46:1341bool VfsBackend::FileTypeIsMainDB(int desired_flags) {
42 return (desired_flags & kFileTypeMask) == SQLITE_OPEN_MAIN_DB;
43}
44
45// static
[email protected]fe615f32010-06-13 09:08:4146bool VfsBackend::FileTypeIsJournal(int desired_flags) {
47 int file_type = desired_flags & kFileTypeMask;
48 return ((file_type == SQLITE_OPEN_MAIN_JOURNAL) ||
49 (file_type == SQLITE_OPEN_TEMP_JOURNAL) ||
50 (file_type == SQLITE_OPEN_SUBJOURNAL) ||
51 (file_type == SQLITE_OPEN_MASTER_JOURNAL));
52}
53
54// static
[email protected]a3703dd2010-02-11 17:46:1355bool VfsBackend::OpenTypeIsReadWrite(int desired_flags) {
[email protected]2f312ab2010-04-21 07:17:4156 return (desired_flags & SQLITE_OPEN_READWRITE) != 0;
[email protected]a3703dd2010-02-11 17:46:1357}
58
59// static
[email protected]3c5ed2c2009-11-13 01:30:4560bool VfsBackend::OpenFileFlagsAreConsistent(int desired_flags) {
[email protected]a3703dd2010-02-11 17:46:1361 const int file_type = desired_flags & kFileTypeMask;
[email protected]da34ae02009-09-22 20:41:2062 const bool is_exclusive = (desired_flags & SQLITE_OPEN_EXCLUSIVE) != 0;
63 const bool is_delete = (desired_flags & SQLITE_OPEN_DELETEONCLOSE) != 0;
64 const bool is_create = (desired_flags & SQLITE_OPEN_CREATE) != 0;
65 const bool is_read_only = (desired_flags & SQLITE_OPEN_READONLY) != 0;
66 const bool is_read_write = (desired_flags & SQLITE_OPEN_READWRITE) != 0;
67
[email protected]b5be3f532009-10-24 01:28:3968 // All files should be opened either read-write or read-only, but not both.
69 if (is_read_only == is_read_write)
[email protected]da34ae02009-09-22 20:41:2070 return false;
[email protected]da34ae02009-09-22 20:41:2071
[email protected]b5be3f532009-10-24 01:28:3972 // If a new file is created, it must also be writable.
73 if (is_create && !is_read_write)
[email protected]da34ae02009-09-22 20:41:2074 return false;
[email protected]da34ae02009-09-22 20:41:2075
[email protected]b5be3f532009-10-24 01:28:3976 // If we're accessing an existing file, we cannot give exclusive access, and
77 // we can't delete it.
[email protected]fe615f32010-06-13 09:08:4178 // Normally, we'd also check that 'is_delete' is false for a main DB, main
79 // journal or master journal file; however, when in incognito mode, we use
80 // the SQLITE_OPEN_DELETEONCLOSE flag when opening those files too and keep
81 // an open handle to them for as long as the incognito profile is around.
[email protected]b5be3f532009-10-24 01:28:3982 if ((is_exclusive || is_delete) && !is_create)
[email protected]da34ae02009-09-22 20:41:2083 return false;
[email protected]da34ae02009-09-22 20:41:2084
[email protected]da34ae02009-09-22 20:41:2085 // Make sure we're opening the DB directory or that a file type is set.
[email protected]b5be3f532009-10-24 01:28:3986 return (file_type == SQLITE_OPEN_MAIN_DB) ||
87 (file_type == SQLITE_OPEN_TEMP_DB) ||
88 (file_type == SQLITE_OPEN_MAIN_JOURNAL) ||
89 (file_type == SQLITE_OPEN_TEMP_JOURNAL) ||
90 (file_type == SQLITE_OPEN_SUBJOURNAL) ||
91 (file_type == SQLITE_OPEN_MASTER_JOURNAL) ||
92 (file_type == SQLITE_OPEN_TRANSIENT_DB);
[email protected]da34ae02009-09-22 20:41:2093}
94
[email protected]a3703dd2010-02-11 17:46:1395// static
[email protected]3c5ed2c2009-11-13 01:30:4596void VfsBackend::OpenFile(const FilePath& file_path,
[email protected]b5be3f532009-10-24 01:28:3997 int desired_flags,
[email protected]fe615f32010-06-13 09:08:4198 base::PlatformFile* file_handle) {
[email protected]3c5ed2c2009-11-13 01:30:4599 DCHECK(!file_path.empty());
100
[email protected]da34ae02009-09-22 20:41:20101 // Verify the flags for consistency and create the database
102 // directory if it doesn't exist.
[email protected]3c5ed2c2009-11-13 01:30:45103 if (!OpenFileFlagsAreConsistent(desired_flags) ||
104 !file_util::CreateDirectory(file_path.DirName()))
[email protected]c93efc7c52009-10-29 19:58:30105 return;
[email protected]da34ae02009-09-22 20:41:20106
[email protected]c93efc7c52009-10-29 19:58:30107 int flags = 0;
108 flags |= base::PLATFORM_FILE_READ;
109 if (desired_flags & SQLITE_OPEN_READWRITE)
110 flags |= base::PLATFORM_FILE_WRITE;
[email protected]da34ae02009-09-22 20:41:20111
[email protected]c93efc7c52009-10-29 19:58:30112 if (!(desired_flags & SQLITE_OPEN_MAIN_DB)) {
113 flags |= base::PLATFORM_FILE_EXCLUSIVE_READ |
114 base::PLATFORM_FILE_EXCLUSIVE_WRITE;
115 }
[email protected]da34ae02009-09-22 20:41:20116
[email protected]c93efc7c52009-10-29 19:58:30117 flags |= ((desired_flags & SQLITE_OPEN_CREATE) ?
118 base::PLATFORM_FILE_OPEN_ALWAYS : base::PLATFORM_FILE_OPEN);
[email protected]da34ae02009-09-22 20:41:20119
[email protected]c93efc7c52009-10-29 19:58:30120 if (desired_flags & SQLITE_OPEN_EXCLUSIVE) {
121 flags |= base::PLATFORM_FILE_EXCLUSIVE_READ |
122 base::PLATFORM_FILE_EXCLUSIVE_WRITE;
123 }
[email protected]da34ae02009-09-22 20:41:20124
[email protected]c93efc7c52009-10-29 19:58:30125 if (desired_flags & SQLITE_OPEN_DELETEONCLOSE) {
126 flags |= base::PLATFORM_FILE_TEMPORARY | base::PLATFORM_FILE_HIDDEN |
127 base::PLATFORM_FILE_DELETE_ON_CLOSE;
128 }
[email protected]da34ae02009-09-22 20:41:20129
[email protected]c93efc7c52009-10-29 19:58:30130 // Try to open/create the DB file.
[email protected]fe615f32010-06-13 09:08:41131 *file_handle =
[email protected]3c5ed2c2009-11-13 01:30:45132 base::CreatePlatformFile(file_path.ToWStringHack(), flags, NULL);
[email protected]da34ae02009-09-22 20:41:20133}
134
[email protected]a3703dd2010-02-11 17:46:13135// static
[email protected]3c5ed2c2009-11-13 01:30:45136void VfsBackend::OpenTempFileInDirectory(
137 const FilePath& dir_path,
138 int desired_flags,
[email protected]fe615f32010-06-13 09:08:41139 base::PlatformFile* file_handle) {
[email protected]3c5ed2c2009-11-13 01:30:45140 // We should be able to delete temp files when they're closed
141 // and create them as needed
142 if (!(desired_flags & SQLITE_OPEN_DELETEONCLOSE) ||
143 !(desired_flags & SQLITE_OPEN_CREATE)) {
144 return;
145 }
146
147 // Get a unique temp file name in the database directory.
148 FilePath temp_file_path;
149 if (!file_util::CreateTemporaryFileInDir(dir_path, &temp_file_path))
150 return;
151
[email protected]fe615f32010-06-13 09:08:41152 OpenFile(temp_file_path, desired_flags, file_handle);
[email protected]3c5ed2c2009-11-13 01:30:45153}
154
[email protected]a3703dd2010-02-11 17:46:13155// static
[email protected]3c5ed2c2009-11-13 01:30:45156int VfsBackend::DeleteFile(const FilePath& file_path, bool sync_dir) {
157 if (!file_util::PathExists(file_path))
[email protected]da34ae02009-09-22 20:41:20158 return SQLITE_OK;
[email protected]3c5ed2c2009-11-13 01:30:45159 if (!file_util::Delete(file_path, false))
[email protected]da34ae02009-09-22 20:41:20160 return SQLITE_IOERR_DELETE;
[email protected]da34ae02009-09-22 20:41:20161
162 int error_code = SQLITE_OK;
163#if defined(OS_POSIX)
164 if (sync_dir) {
165 base::PlatformFile dir_fd = base::CreatePlatformFile(
[email protected]3c5ed2c2009-11-13 01:30:45166 file_path.DirName().ToWStringHack(), base::PLATFORM_FILE_READ, NULL);
[email protected]da34ae02009-09-22 20:41:20167 if (dir_fd == base::kInvalidPlatformFileValue) {
168 error_code = SQLITE_CANTOPEN;
169 } else {
[email protected]b5be3f532009-10-24 01:28:39170 if (fsync(dir_fd))
[email protected]da34ae02009-09-22 20:41:20171 error_code = SQLITE_IOERR_DIR_FSYNC;
[email protected]da34ae02009-09-22 20:41:20172 base::ClosePlatformFile(dir_fd);
173 }
174 }
175#endif
176 return error_code;
177}
178
[email protected]a3703dd2010-02-11 17:46:13179// static
[email protected]3c5ed2c2009-11-13 01:30:45180uint32 VfsBackend::GetFileAttributes(const FilePath& file_path) {
[email protected]da34ae02009-09-22 20:41:20181#if defined(OS_WIN)
[email protected]3c5ed2c2009-11-13 01:30:45182 uint32 attributes = ::GetFileAttributes(file_path.value().c_str());
[email protected]da34ae02009-09-22 20:41:20183#elif defined(OS_POSIX)
184 uint32 attributes = 0;
[email protected]3c5ed2c2009-11-13 01:30:45185 if (!access(file_path.value().c_str(), R_OK))
[email protected]da34ae02009-09-22 20:41:20186 attributes |= static_cast<uint32>(R_OK);
[email protected]3c5ed2c2009-11-13 01:30:45187 if (!access(file_path.value().c_str(), W_OK))
[email protected]da34ae02009-09-22 20:41:20188 attributes |= static_cast<uint32>(W_OK);
[email protected]b5be3f532009-10-24 01:28:39189 if (!attributes)
[email protected]da34ae02009-09-22 20:41:20190 attributes = -1;
[email protected]da34ae02009-09-22 20:41:20191#endif
192 return attributes;
193}
194
[email protected]a3703dd2010-02-11 17:46:13195// static
[email protected]3c5ed2c2009-11-13 01:30:45196int64 VfsBackend::GetFileSize(const FilePath& file_path) {
[email protected]da34ae02009-09-22 20:41:20197 int64 size = 0;
[email protected]3c5ed2c2009-11-13 01:30:45198 return (file_util::GetFileSize(file_path, &size) ? size : 0);
[email protected]da34ae02009-09-22 20:41:20199}
200
[email protected]b5be3f532009-10-24 01:28:39201} // namespace webkit_database