summaryrefslogtreecommitdiffstats
path: root/storage/browser/fileapi/sandbox_directory_database.h
blob: 4899f933c44761eec3c99bb225f450d439bef7bc (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
// Copyright (c) 2012 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.

#ifndef STORAGE_BROWSER_FILEAPI_SANDBOX_DIRECTORY_DATABASE_H_
#define STORAGE_BROWSER_FILEAPI_SANDBOX_DIRECTORY_DATABASE_H_

#include <stdint.h>

#include <string>
#include <vector>

#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
#include "storage/browser/storage_browser_export.h"

namespace content {
class SandboxDirectoryDatabaseTest;
}

namespace tracked_objects {
class Location;
}

namespace leveldb {
class DB;
class Env;
class Status;
class WriteBatch;
}

namespace storage {

// This class WILL NOT protect you against producing directory loops, giving an
// empty directory a backing data file, giving two files the same backing file,
// or pointing to a nonexistent backing file.  It does no file IO other than
// that involved with talking to its underlying database.  It does not create or
// in any way touch real files; it only creates path entries in its database.

// TODO(ericu): Safe mode, which does more checks such as the above on debug
// builds.
// TODO(ericu): Add a method that will give a unique filename for a data file.
class STORAGE_EXPORT SandboxDirectoryDatabase {
 public:
  typedef int64_t FileId;

  struct STORAGE_EXPORT FileInfo {
    FileInfo();
    ~FileInfo();

    bool is_directory() const {
      return data_path.empty();
    }

    FileId parent_id;
    base::FilePath data_path;
    base::FilePath::StringType name;
    // This modification time is valid only for directories, not files, as
    // FileWriter will get the files out of sync.
    // For files, look at the modification time of the underlying data_path.
    base::Time modification_time;
  };

  SandboxDirectoryDatabase(
      const base::FilePath& filesystem_data_directory,
      leveldb::Env* env_override);
  ~SandboxDirectoryDatabase();

  bool GetChildWithName(
      FileId parent_id,
      const base::FilePath::StringType& name,
      FileId* child_id);
  bool GetFileWithPath(const base::FilePath& path, FileId* file_id);
  // ListChildren will succeed, returning 0 children, if parent_id doesn't
  // exist.
  bool ListChildren(FileId parent_id, std::vector<FileId>* children);
  bool GetFileInfo(FileId file_id, FileInfo* info);
  base::File::Error AddFileInfo(const FileInfo& info, FileId* file_id);
  bool RemoveFileInfo(FileId file_id);
  // This does a full update of the FileInfo, and is what you'd use for moves
  // and renames.  If you just want to update the modification_time, use
  // UpdateModificationTime.
  bool UpdateFileInfo(FileId file_id, const FileInfo& info);
  bool UpdateModificationTime(
      FileId file_id, const base::Time& modification_time);
  // This is used for an overwriting move of a file [not a directory] on top of
  // another file [also not a directory]; we need to alter two files' info in a
  // single transaction to avoid weird backing file references in the event of a
  // partial failure.
  bool OverwritingMoveFile(FileId src_file_id, FileId dest_file_id);

  // This produces the series 0, 1, 2..., starting at 0 when the underlying
  // filesystem is first created, and maintaining state across
  // creation/destruction of SandboxDirectoryDatabase objects.
  bool GetNextInteger(int64_t* next);

  bool IsDirectory(FileId file_id);

  // Returns true if the database looks consistent with local filesystem.
  bool IsFileSystemConsistent();

  // Completely deletes contents of the database.
  bool DestroyDatabase();

 private:
  enum RecoveryOption {
    DELETE_ON_CORRUPTION,
    REPAIR_ON_CORRUPTION,
    FAIL_ON_CORRUPTION,
  };

  friend class content::SandboxDirectoryDatabaseTest;
  friend class ObfuscatedFileUtil;

  bool Init(RecoveryOption recovery_option);
  bool RepairDatabase(const std::string& db_path);
  void ReportInitStatus(const leveldb::Status& status);
  bool StoreDefaultValues();
  bool GetLastFileId(FileId* file_id);
  bool AddFileInfoHelper(
      const FileInfo& info, FileId file_id, leveldb::WriteBatch* batch);
  bool RemoveFileInfoHelper(FileId file_id, leveldb::WriteBatch* batch);
  // Close the database. Before this, all iterators associated with the database
  // must be deleted.
  void HandleError(const tracked_objects::Location& from_here,
                   const leveldb::Status& status);

  const base::FilePath filesystem_data_directory_;
  leveldb::Env* env_override_;
  scoped_ptr<leveldb::DB> db_;
  base::Time last_reported_time_;
  DISALLOW_COPY_AND_ASSIGN(SandboxDirectoryDatabase);
};

}  // namespace storage

#endif  // STORAGE_BROWSER_FILEAPI_SANDBOX_DIRECTORY_DATABASE_H_