summaryrefslogtreecommitdiffstats
path: root/webkit/database/vfs_backend.cc
blob: a73035d7cb4d1b5d515e5e69e1d3d69160974dbb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "webkit/database/vfs_backend.h"

#include "base/file_path.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "third_party/sqlite/sqlite3.h"

namespace webkit_database {

static const int kFileTypeMask = 0x00007F00;

// static
bool VfsBackend::OpenTypeIsReadWrite(int desired_flags) {
  return (desired_flags & SQLITE_OPEN_READWRITE) != 0;
}

// static
bool VfsBackend::OpenFileFlagsAreConsistent(int desired_flags) {
  const int file_type = desired_flags & kFileTypeMask;
  const bool is_exclusive = (desired_flags & SQLITE_OPEN_EXCLUSIVE) != 0;
  const bool is_delete = (desired_flags & SQLITE_OPEN_DELETEONCLOSE) != 0;
  const bool is_create = (desired_flags & SQLITE_OPEN_CREATE) != 0;
  const bool is_read_only = (desired_flags & SQLITE_OPEN_READONLY) != 0;
  const bool is_read_write = (desired_flags & SQLITE_OPEN_READWRITE) != 0;

  // All files should be opened either read-write or read-only, but not both.
  if (is_read_only == is_read_write)
    return false;

  // If a new file is created, it must also be writable.
  if (is_create && !is_read_write)
    return false;

  // If we're accessing an existing file, we cannot give exclusive access, and
  // we can't delete it.
  // Normally, we'd also check that 'is_delete' is false for a main DB, main
  // journal or master journal file; however, when in incognito mode, we use
  // the SQLITE_OPEN_DELETEONCLOSE flag when opening those files too and keep
  // an open handle to them for as long as the incognito profile is around.
  if ((is_exclusive || is_delete) && !is_create)
    return false;

  // Make sure we're opening the DB directory or that a file type is set.
  return (file_type == SQLITE_OPEN_MAIN_DB) ||
         (file_type == SQLITE_OPEN_TEMP_DB) ||
         (file_type == SQLITE_OPEN_MAIN_JOURNAL) ||
         (file_type == SQLITE_OPEN_TEMP_JOURNAL) ||
         (file_type == SQLITE_OPEN_SUBJOURNAL) ||
         (file_type == SQLITE_OPEN_MASTER_JOURNAL) ||
         (file_type == SQLITE_OPEN_TRANSIENT_DB);
}

// static
void VfsBackend::OpenFile(const FilePath& file_path,
                          int desired_flags,
                          base::PlatformFile* file_handle) {
  DCHECK(!file_path.empty());

  // Verify the flags for consistency and create the database
  // directory if it doesn't exist.
  if (!OpenFileFlagsAreConsistent(desired_flags) ||
      !file_util::CreateDirectory(file_path.DirName()))
    return;

  int flags = 0;
  flags |= base::PLATFORM_FILE_READ;
  if (desired_flags & SQLITE_OPEN_READWRITE)
    flags |= base::PLATFORM_FILE_WRITE;

  if (!(desired_flags & SQLITE_OPEN_MAIN_DB)) {
    flags |= base::PLATFORM_FILE_EXCLUSIVE_READ |
             base::PLATFORM_FILE_EXCLUSIVE_WRITE;
  }

  flags |= ((desired_flags & SQLITE_OPEN_CREATE) ?
      base::PLATFORM_FILE_OPEN_ALWAYS : base::PLATFORM_FILE_OPEN);

  if (desired_flags & SQLITE_OPEN_EXCLUSIVE) {
    flags |= base::PLATFORM_FILE_EXCLUSIVE_READ |
             base::PLATFORM_FILE_EXCLUSIVE_WRITE;
  }

  if (desired_flags & SQLITE_OPEN_DELETEONCLOSE) {
    flags |= base::PLATFORM_FILE_TEMPORARY | base::PLATFORM_FILE_HIDDEN |
             base::PLATFORM_FILE_DELETE_ON_CLOSE;
  }

  // This flag will allow us to delete the file later on from the browser
  // process.
  flags |= base::PLATFORM_FILE_SHARE_DELETE;

  // Try to open/create the DB file.
  *file_handle =
      base::CreatePlatformFile(file_path, flags, NULL, NULL);
}

// static
void VfsBackend::OpenTempFileInDirectory(
    const FilePath& dir_path,
    int desired_flags,
    base::PlatformFile* file_handle) {
  // We should be able to delete temp files when they're closed
  // and create them as needed
  if (!(desired_flags & SQLITE_OPEN_DELETEONCLOSE) ||
      !(desired_flags & SQLITE_OPEN_CREATE)) {
    return;
  }

  // Get a unique temp file name in the database directory.
  FilePath temp_file_path;
  if (!file_util::CreateTemporaryFileInDir(dir_path, &temp_file_path))
    return;

  OpenFile(temp_file_path, desired_flags, file_handle);
}

// static
int VfsBackend::DeleteFile(const FilePath& file_path, bool sync_dir) {
  if (!file_util::PathExists(file_path))
    return SQLITE_OK;
  if (!file_util::Delete(file_path, false))
    return SQLITE_IOERR_DELETE;

  int error_code = SQLITE_OK;
#if defined(OS_POSIX)
  if (sync_dir) {
    base::PlatformFile dir_fd = base::CreatePlatformFile(
        file_path.DirName(), base::PLATFORM_FILE_READ, NULL, NULL);
    if (dir_fd == base::kInvalidPlatformFileValue) {
      error_code = SQLITE_CANTOPEN;
    } else {
      if (fsync(dir_fd))
        error_code = SQLITE_IOERR_DIR_FSYNC;
      base::ClosePlatformFile(dir_fd);
    }
  }
#endif
  return error_code;
}

// static
uint32 VfsBackend::GetFileAttributes(const FilePath& file_path) {
#if defined(OS_WIN)
  uint32 attributes = ::GetFileAttributes(file_path.value().c_str());
#elif defined(OS_POSIX)
  uint32 attributes = 0;
  if (!access(file_path.value().c_str(), R_OK))
    attributes |= static_cast<uint32>(R_OK);
  if (!access(file_path.value().c_str(), W_OK))
    attributes |= static_cast<uint32>(W_OK);
  if (!attributes)
    attributes = -1;
#endif
  return attributes;
}

// static
int64 VfsBackend::GetFileSize(const FilePath& file_path) {
  int64 size = 0;
  return (file_util::GetFileSize(file_path, &size) ? size : 0);
}

} // namespace webkit_database