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.
5 #include "webkit/database/vfs_backend.h"
7 #include "base/file_path.h"
8 #include "base/file_util.h"
9 #include "base/logging.h"
10 #include "third_party/sqlite/sqlite3.h"
12 namespace webkit_database
{
14 static const int kFileTypeMask
= 0x00007F00;
17 bool VfsBackend::OpenTypeIsReadWrite(int desired_flags
) {
18 return (desired_flags
& SQLITE_OPEN_READWRITE
) != 0;
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;
30 // All files should be opened either read-write or read-only, but not both.
31 if (is_read_only
== is_read_write
)
34 // If a new file is created, it must also be writable.
35 if (is_create
&& !is_read_write
)
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
)
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
);
58 void VfsBackend::OpenFile(const FilePath
& file_path
,
60 base::PlatformFile
* file_handle
) {
61 DCHECK(!file_path
.empty());
63 // Verify the flags for consistency and create the database
64 // directory if it doesn't exist.
65 if (!OpenFileFlagsAreConsistent(desired_flags
) ||
66 !file_util::CreateDirectory(file_path
.DirName()))
70 flags
|= base::PLATFORM_FILE_READ
;
71 if (desired_flags
& SQLITE_OPEN_READWRITE
)
72 flags
|= base::PLATFORM_FILE_WRITE
;
74 if (!(desired_flags
& SQLITE_OPEN_MAIN_DB
)) {
75 flags
|= base::PLATFORM_FILE_EXCLUSIVE_READ
|
76 base::PLATFORM_FILE_EXCLUSIVE_WRITE
;
79 flags
|= ((desired_flags
& SQLITE_OPEN_CREATE
) ?
80 base::PLATFORM_FILE_OPEN_ALWAYS
: base::PLATFORM_FILE_OPEN
);
82 if (desired_flags
& SQLITE_OPEN_EXCLUSIVE
) {
83 flags
|= base::PLATFORM_FILE_EXCLUSIVE_READ
|
84 base::PLATFORM_FILE_EXCLUSIVE_WRITE
;
87 if (desired_flags
& SQLITE_OPEN_DELETEONCLOSE
) {
88 flags
|= base::PLATFORM_FILE_TEMPORARY
| base::PLATFORM_FILE_HIDDEN
|
89 base::PLATFORM_FILE_DELETE_ON_CLOSE
;
92 // This flag will allow us to delete the file later on from the browser
94 flags
|= base::PLATFORM_FILE_SHARE_DELETE
;
96 // Try to open/create the DB file.
98 base::CreatePlatformFile(file_path
, flags
, NULL
, NULL
);
102 void VfsBackend::OpenTempFileInDirectory(
103 const FilePath
& dir_path
,
105 base::PlatformFile
* file_handle
) {
106 // We should be able to delete temp files when they're closed
107 // and create them as needed
108 if (!(desired_flags
& SQLITE_OPEN_DELETEONCLOSE
) ||
109 !(desired_flags
& SQLITE_OPEN_CREATE
)) {
113 // Get a unique temp file name in the database directory.
114 FilePath temp_file_path
;
115 if (!file_util::CreateTemporaryFileInDir(dir_path
, &temp_file_path
))
118 OpenFile(temp_file_path
, desired_flags
, file_handle
);
122 int VfsBackend::DeleteFile(const FilePath
& file_path
, bool sync_dir
) {
123 if (!file_util::PathExists(file_path
))
125 if (!file_util::Delete(file_path
, false))
126 return SQLITE_IOERR_DELETE
;
128 int error_code
= SQLITE_OK
;
129 #if defined(OS_POSIX)
131 base::PlatformFile dir_fd
= base::CreatePlatformFile(
132 file_path
.DirName(), base::PLATFORM_FILE_READ
, NULL
, NULL
);
133 if (dir_fd
== base::kInvalidPlatformFileValue
) {
134 error_code
= SQLITE_CANTOPEN
;
137 error_code
= SQLITE_IOERR_DIR_FSYNC
;
138 base::ClosePlatformFile(dir_fd
);
146 uint32
VfsBackend::GetFileAttributes(const FilePath
& file_path
) {
148 uint32 attributes
= ::GetFileAttributes(file_path
.value().c_str());
149 #elif defined(OS_POSIX)
150 uint32 attributes
= 0;
151 if (!access(file_path
.value().c_str(), R_OK
))
152 attributes
|= static_cast<uint32
>(R_OK
);
153 if (!access(file_path
.value().c_str(), W_OK
))
154 attributes
|= static_cast<uint32
>(W_OK
);
162 int64
VfsBackend::GetFileSize(const FilePath
& file_path
) {
164 return (file_util::GetFileSize(file_path
, &size
) ? size
: 0);
167 } // namespace webkit_database