1 // Copyright (c) 2013 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.
5 // A tool to dump HTML5 filesystem from CUI.
9 // ./out/Release/dump_file_system [options] <filesystem dir> [origin]...
11 // If no origin is specified, this dumps all origins in the profile dir.
12 // For Chrome App, which has a separate storage directory, specify "primary"
13 // as the origin name.
17 // -t : dumps temporary files instead of persistent.
18 // -s : dumps syncable files instead of persistent.
19 // -l : more information will be displayed.
21 // The format of -l option is:
23 // === ORIGIN origin_name origin_dir ===
24 // file_name file_id file_size file_content_path
27 // where file_name has a trailing slash, file_size is the number of
28 // children, and file_content_path is empty if the file is a directory.
39 #include "base/files/file_path.h"
40 #include "base/files/file_util.h"
41 #include "base/format_macros.h"
42 #include "base/strings/stringprintf.h"
43 #include "storage/browser/fileapi/obfuscated_file_util.h"
44 #include "storage/browser/fileapi/sandbox_directory_database.h"
45 #include "storage/browser/fileapi/sandbox_file_system_backend.h"
46 #include "storage/browser/fileapi/sandbox_origin_database.h"
47 #include "storage/browser/fileapi/sandbox_prioritized_origin_database.h"
48 #include "storage/common/fileapi/file_system_types.h"
49 #include "storage/common/fileapi/file_system_util.h"
54 const base::FilePath::CharType
* g_opt_fs_type
= FILE_PATH_LITERAL("p");
56 void ShowMessageAndExit(const std::string
& msg
) {
57 fprintf(stderr
, "%s\n", msg
.c_str());
61 void ShowUsageAndExit(const std::string
& arg0
) {
64 " [-l] [-t] [-s] <filesystem dir> [origin]...");
71 static void DumpDirectoryTree(const std::string
& origin_name
,
72 base::FilePath origin_dir
) {
73 origin_dir
= origin_dir
.Append(g_opt_fs_type
);
75 printf("=== ORIGIN %s %s ===\n",
76 origin_name
.c_str(), FilePathToString(origin_dir
).c_str());
78 if (!base::DirectoryExists(origin_dir
))
81 SandboxDirectoryDatabase
directory_db(origin_dir
, NULL
);
82 SandboxDirectoryDatabase::FileId root_id
;
83 if (!directory_db
.GetFileWithPath(StringToFilePath("/"), &root_id
))
86 std::stack
<std::pair
<SandboxDirectoryDatabase::FileId
,
88 paths
.push(std::make_pair(root_id
, ""));
89 while (!paths
.empty()) {
90 SandboxDirectoryDatabase::FileId id
= paths
.top().first
;
91 const std::string dirname
= paths
.top().second
;
94 SandboxDirectoryDatabase::FileInfo info
;
95 if (!directory_db
.GetFileInfo(id
, &info
)) {
96 ShowMessageAndExit(base::StringPrintf("GetFileInfo failed for %"PRId64
,
100 const std::string name
=
101 dirname
+ "/" + FilePathToString(base::FilePath(info
.name
));
102 std::vector
<SandboxDirectoryDatabase::FileId
> children
;
103 if (info
.is_directory()) {
104 if (!directory_db
.ListChildren(id
, &children
)) {
105 ShowMessageAndExit(base::StringPrintf(
106 "ListChildren failed for %s (%"PRId64
")",
107 info
.name
.c_str(), id
));
110 for (size_t j
= children
.size(); j
; j
--)
111 paths
.push(make_pair(children
[j
-1], name
));
114 // +1 for the leading extra slash.
115 const char* display_name
= name
.c_str() + 1;
116 const char* directory_suffix
= info
.is_directory() ? "/" : "";
119 if (info
.is_directory()) {
120 size
= static_cast<int64
>(children
.size());
122 base::GetFileSize(origin_dir
.Append(info
.data_path
), &size
);
124 // TODO(hamaji): Modification time?
125 printf("%s%s %"PRId64
" %"PRId64
" %s\n",
130 FilePathToString(info
.data_path
).c_str());
132 printf("%s%s\n", display_name
, directory_suffix
);
137 static base::FilePath
GetOriginDir(const base::FilePath
& file_system_dir
,
138 const std::string
& origin_name
) {
139 if (base::PathExists(file_system_dir
.Append(
140 SandboxPrioritizedOriginDatabase::kPrimaryOriginFile
))) {
141 return base::FilePath(
142 SandboxPrioritizedOriginDatabase::kPrimaryDirectory
);
145 SandboxOriginDatabase
origin_db(file_system_dir
, NULL
);
146 base::FilePath origin_dir
;
147 if (!origin_db
.HasOriginPath(origin_name
)) {
148 ShowMessageAndExit("Origin " + origin_name
+ " is not in " +
149 FilePathToString(file_system_dir
));
152 if (!origin_db
.GetPathForOrigin(origin_name
, &origin_dir
)) {
153 ShowMessageAndExit("Failed to get path of origin " + origin_name
+
154 " in " + FilePathToString(file_system_dir
));
160 static void DumpOrigin(const base::FilePath
& file_system_dir
,
161 const std::string
& origin_name
) {
162 base::FilePath origin_dir
= GetOriginDir(file_system_dir
, origin_name
);
163 DumpDirectoryTree(origin_name
, file_system_dir
.Append(origin_dir
));
166 static void DumpFileSystem(const base::FilePath
& file_system_dir
) {
167 SandboxOriginDatabase
origin_db(file_system_dir
, NULL
);
168 std::vector
<SandboxOriginDatabase::OriginRecord
> origins
;
169 origin_db
.ListAllOrigins(&origins
);
170 for (size_t i
= 0; i
< origins
.size(); i
++) {
171 const SandboxOriginDatabase::OriginRecord
& origin
= origins
[i
];
172 DumpDirectoryTree(origin
.origin
, file_system_dir
.Append(origin
.path
));
177 } // namespace storage
179 int main(int argc
, char* argv
[]) {
180 const char* arg0
= argv
[0];
183 ShowUsageAndExit(arg0
);
185 if (std::string(argv
[1]) == "-l") {
189 } else if (std::string(argv
[1]) == "-t") {
190 g_opt_fs_type
= FILE_PATH_LITERAL("t");
193 } else if (std::string(argv
[1]) == "-s") {
194 g_opt_fs_type
= FILE_PATH_LITERAL("s");
203 ShowUsageAndExit(arg0
);
205 const base::FilePath file_system_dir
= storage::StringToFilePath(argv
[1]);
206 if (!base::DirectoryExists(file_system_dir
)) {
207 ShowMessageAndExit(storage::FilePathToString(file_system_dir
) +
208 " is not a filesystem directory");
212 storage::DumpFileSystem(file_system_dir
);
214 for (int i
= 2; i
< argc
; i
++) {
215 storage::DumpOrigin(file_system_dir
, argv
[i
]);