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