Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / storage / browser / database / vfs_backend.cc
blob2cd0246daecdfa7853cb605f2400301b093171ba
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 "storage/browser/database/vfs_backend.h"
7 #include "base/files/file_path.h"
8 #include "base/files/file_util.h"
9 #include "base/logging.h"
10 #include "third_party/sqlite/sqlite3.h"
12 namespace storage {
14 static const int kFileTypeMask = 0x00007F00;
16 // static
17 bool VfsBackend::OpenTypeIsReadWrite(int desired_flags) {
18 return (desired_flags & SQLITE_OPEN_READWRITE) != 0;
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;
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;
34 // If a new file is created, it must also be writable.
35 if (is_create && !is_read_write)
36 return false;
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;
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);
57 // static
58 base::File VfsBackend::OpenFile(const base::FilePath& file_path,
59 int desired_flags) {
60 DCHECK(!file_path.empty());
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();
69 int flags = 0;
70 flags |= base::File::FLAG_READ;
71 if (desired_flags & SQLITE_OPEN_READWRITE)
72 flags |= base::File::FLAG_WRITE;
74 if (!(desired_flags & SQLITE_OPEN_MAIN_DB))
75 flags |= base::File::FLAG_EXCLUSIVE_READ | base::File::FLAG_EXCLUSIVE_WRITE;
77 flags |= ((desired_flags & SQLITE_OPEN_CREATE) ?
78 base::File::FLAG_OPEN_ALWAYS : base::File::FLAG_OPEN);
80 if (desired_flags & SQLITE_OPEN_EXCLUSIVE)
81 flags |= base::File::FLAG_EXCLUSIVE_READ | base::File::FLAG_EXCLUSIVE_WRITE;
83 if (desired_flags & SQLITE_OPEN_DELETEONCLOSE) {
84 flags |= base::File::FLAG_TEMPORARY | base::File::FLAG_HIDDEN |
85 base::File::FLAG_DELETE_ON_CLOSE;
88 // This flag will allow us to delete the file later on from the browser
89 // process.
90 flags |= base::File::FLAG_SHARE_DELETE;
92 // Try to open/create the DB file.
93 return base::File(file_path, flags);
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();
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();
111 return OpenFile(temp_file_path, desired_flags);
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;
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;
132 #endif
133 return error_code;
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;
152 // static
153 int64 VfsBackend::GetFileSize(const base::FilePath& file_path) {
154 int64 size = 0;
155 return (base::GetFileSize(file_path, &size) ? size : 0);
158 // static
159 bool VfsBackend::SetFileSize(const base::FilePath& file_path, int64 size) {
160 int flags = 0;
161 flags |= base::File::FLAG_READ;
162 flags |= base::File::FLAG_WRITE;
163 flags |= base::File::FLAG_OPEN;
164 base::File file = base::File(file_path, flags);
165 if (!file.IsValid())
166 return false;
167 return file.SetLength(size);
170 } // namespace storage