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 webkit_database { 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 webkit_database 159