15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/database/vfs_backend.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/sqlite/sqlite3.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)namespace storage { 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kFileTypeMask = 0x00007F00; 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VfsBackend::OpenTypeIsReadWrite(int desired_flags) { 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (desired_flags & SQLITE_OPEN_READWRITE) != 0; 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VfsBackend::OpenFileFlagsAreConsistent(int desired_flags) { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int file_type = desired_flags & kFileTypeMask; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool is_exclusive = (desired_flags & SQLITE_OPEN_EXCLUSIVE) != 0; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool is_delete = (desired_flags & SQLITE_OPEN_DELETEONCLOSE) != 0; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool is_create = (desired_flags & SQLITE_OPEN_CREATE) != 0; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool is_read_only = (desired_flags & SQLITE_OPEN_READONLY) != 0; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool is_read_write = (desired_flags & SQLITE_OPEN_READWRITE) != 0; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // All files should be opened either read-write or read-only, but not both. 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_read_only == is_read_write) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If a new file is created, it must also be writable. 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_create && !is_read_write) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we're accessing an existing file, we cannot give exclusive access, and 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we can't delete it. 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Normally, we'd also check that 'is_delete' is false for a main DB, main 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // journal or master journal file; however, when in incognito mode, we use 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the SQLITE_OPEN_DELETEONCLOSE flag when opening those files too and keep 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // an open handle to them for as long as the incognito profile is around. 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((is_exclusive || is_delete) && !is_create) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure we're opening the DB directory or that a file type is set. 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (file_type == SQLITE_OPEN_MAIN_DB) || 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (file_type == SQLITE_OPEN_TEMP_DB) || 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (file_type == SQLITE_OPEN_MAIN_JOURNAL) || 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (file_type == SQLITE_OPEN_TEMP_JOURNAL) || 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (file_type == SQLITE_OPEN_SUBJOURNAL) || 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (file_type == SQLITE_OPEN_MASTER_JOURNAL) || 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (file_type == SQLITE_OPEN_TRANSIENT_DB); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 58effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbase::File VfsBackend::OpenFile(const base::FilePath& file_path, 59effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch int desired_flags) { 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!file_path.empty()); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verify the flags for consistency and create the database 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // directory if it doesn't exist. 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!OpenFileFlagsAreConsistent(desired_flags) || 65effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch !base::CreateDirectory(file_path.DirName())) { 66effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return base::File(); 67effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int flags = 0; 70effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch flags |= base::File::FLAG_READ; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (desired_flags & SQLITE_OPEN_READWRITE) 72effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch flags |= base::File::FLAG_WRITE; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 74effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!(desired_flags & SQLITE_OPEN_MAIN_DB)) 75effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch flags |= base::File::FLAG_EXCLUSIVE_READ | base::File::FLAG_EXCLUSIVE_WRITE; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) flags |= ((desired_flags & SQLITE_OPEN_CREATE) ? 78effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::File::FLAG_OPEN_ALWAYS : base::File::FLAG_OPEN); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 80effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (desired_flags & SQLITE_OPEN_EXCLUSIVE) 81effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch flags |= base::File::FLAG_EXCLUSIVE_READ | base::File::FLAG_EXCLUSIVE_WRITE; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (desired_flags & SQLITE_OPEN_DELETEONCLOSE) { 84effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch flags |= base::File::FLAG_TEMPORARY | base::File::FLAG_HIDDEN | 85effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::File::FLAG_DELETE_ON_CLOSE; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This flag will allow us to delete the file later on from the browser 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // process. 90effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch flags |= base::File::FLAG_SHARE_DELETE; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Try to open/create the DB file. 93effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return base::File(file_path, flags); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 97effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbase::File VfsBackend::OpenTempFileInDirectory(const base::FilePath& dir_path, 98effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch int desired_flags) { 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We should be able to delete temp files when they're closed 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and create them as needed 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(desired_flags & SQLITE_OPEN_DELETEONCLOSE) || 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !(desired_flags & SQLITE_OPEN_CREATE)) { 103effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return base::File(); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get a unique temp file name in the database directory. 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath temp_file_path; 108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!base::CreateTemporaryFileInDir(dir_path, &temp_file_path)) 109effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return base::File(); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 111effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return OpenFile(temp_file_path, desired_flags); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int VfsBackend::DeleteFile(const base::FilePath& file_path, bool sync_dir) { 1167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!base::PathExists(file_path)) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_OK; 1187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!base::DeleteFile(file_path, false)) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SQLITE_IOERR_DELETE; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int error_code = SQLITE_OK; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sync_dir) { 124effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::File dir(file_path.DirName(), base::File::FLAG_READ); 125effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (dir.IsValid()) { 126effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!dir.Flush()) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_code = SQLITE_IOERR_DIR_FSYNC; 128effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } else { 129effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch error_code = SQLITE_CANTOPEN; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return error_code; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)uint32 VfsBackend::GetFileAttributes(const base::FilePath& file_path) { 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 attributes = ::GetFileAttributes(file_path.value().c_str()); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 attributes = 0; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!access(file_path.value().c_str(), R_OK)) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attributes |= static_cast<uint32>(R_OK); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!access(file_path.value().c_str(), W_OK)) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attributes |= static_cast<uint32>(W_OK); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!attributes) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attributes = -1; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return attributes; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int64 VfsBackend::GetFileSize(const base::FilePath& file_path) { 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 size = 0; 155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return (base::GetFileSize(file_path, &size) ? size : 0); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} // namespace storage 159