Chromium Code Reviews| Index: webkit/fileapi/dump_file_system.cc |
| diff --git a/webkit/fileapi/dump_file_system.cc b/webkit/fileapi/dump_file_system.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..af2c6a0fb4a6014bab1113dca883f9fa5a799c64 |
| --- /dev/null |
| +++ b/webkit/fileapi/dump_file_system.cc |
| @@ -0,0 +1,198 @@ |
| +// Copyright (c) 2013 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. |
| +// |
| +// A tool to dump HTML5 filesystem from CUI. |
| +// |
| +// Usage: |
| +// |
| +// ./out/Release/dump_file_system [-l] [-t] <profile dir> [origin]... |
| +// |
| +// If no origin is specified, this dumps all origins in the profile dir. |
| +// |
| +// If -t is specified, this dumps temporary files instead of persistent. |
| +// |
| +// If -l is specified, more information will be displayed. |
| +// The format of -l option is: |
| +// |
| +// === ORIGIN origin_name origin_dir === |
| +// file_name file_id file_size file_content_path |
| +// ... |
| +// |
| +// where file_name has a trailing slash, file_size is the number of |
| +// children, and file_content_path is empty if the file is a directory. |
| +// |
| + |
| +#include <inttypes.h> |
| +#include <stdio.h> |
| +#include <stdlib.h> |
| + |
| +#include <stack> |
| +#include <string> |
| +#include <utility> |
| +#include <vector> |
| + |
| +#include "base/file_util.h" |
| +#include "base/files/file_path.h" |
| +#include "base/stringprintf.h" |
| +#include "webkit/fileapi/file_system_directory_database.h" |
| +#include "webkit/fileapi/file_system_origin_database.h" |
| + |
| +namespace { |
| + |
| +static void ShowMessageAndExit(const std::string& msg) { |
|
kinuko
2013/04/16 10:59:48
nit: no need of static?
hamaji
2013/04/16 12:25:12
Done.
|
| + fprintf(stderr, "%s\n", msg.c_str()); |
| + exit(EXIT_FAILURE); |
| +} |
| + |
| +static void ShowUsageAndExit(const std::string& arg0) { |
|
kinuko
2013/04/16 10:59:48
ditto
hamaji
2013/04/16 12:25:12
Done.
|
| + ShowMessageAndExit("Usage: " + arg0 + |
| + " [-l] [-t] <profile dir> [origin]..."); |
| +} |
| + |
| +} // anonymous namespace |
|
kinuko
2013/04/16 10:59:48
nit: '// namespace' is fine in chrome
hamaji
2013/04/16 12:25:12
Done.
|
| + |
| +namespace fileapi { |
| + |
| +static bool g_opt_long; |
| +static bool g_opt_temporary; |
|
kinuko
2013/04/16 10:59:48
can these be inside the anonymous space?
hamaji
2013/04/16 12:25:12
Done.
|
| + |
| +static void DumpDirectoryTree(const std::string& origin_name, |
| + base::FilePath origin_dir) { |
| + if (!g_opt_temporary) { |
| + origin_dir = origin_dir.Append("p"); |
| + } |
|
kinuko
2013/04/16 10:59:48
Append("t") for g_opt_temporary==true?
Can we use
hamaji
2013/04/16 12:25:12
Done.
|
| + |
| + printf("=== ORIGIN %s %s ===\n", |
| + origin_name.c_str(), origin_dir.value().c_str()); |
| + |
| + if (!file_util::DirectoryExists(origin_dir)) |
| + ShowMessageAndExit(origin_dir.value() + |
| + " is not a filesystem origin directory"); |
|
kinuko
2013/04/16 10:59:48
nit: Please put { } for multi-line body (here and
hamaji
2013/04/16 12:25:12
Done.
|
| + |
| + FileSystemDirectoryDatabase directory_db(origin_dir); |
| + if (!directory_db.IsFileSystemConsistent()) |
| + ShowMessageAndExit(origin_dir.value() + |
| + " is not a consistent file system"); |
|
kinuko
2013/04/16 10:59:48
Probably you don't need these lines, or maybe add
hamaji
2013/04/16 12:25:12
Removed.
|
| + |
| + FileSystemDirectoryDatabase::FileId root_id; |
| + if (!directory_db.GetFileWithPath(base::FilePath("/"), &root_id)) |
| + ShowMessageAndExit(origin_dir.value() + |
| + " does not have the root directory"); |
| + |
| + std::stack<std::pair<FileSystemDirectoryDatabase::FileId, |
| + std::string> > paths; |
| + paths.push(std::make_pair(root_id, "")); |
| + while (!paths.empty()) { |
| + FileSystemDirectoryDatabase::FileId id = paths.top().first; |
| + const std::string dirname = paths.top().second; |
| + paths.pop(); |
| + |
| + FileSystemDirectoryDatabase::FileInfo info; |
| + if (!directory_db.GetFileInfo(id, &info)) |
| + ShowMessageAndExit(base::StringPrintf("GetFileInfo failed for %"PRId64, |
| + id)); |
| + |
| + const std::string name = dirname + "/" + info.name; |
| + std::vector<FileSystemDirectoryDatabase::FileId> children; |
| + if (info.is_directory()) { |
| + if (!directory_db.ListChildren(id, &children)) |
| + ShowMessageAndExit(base::StringPrintf( |
| + "ListChildren failed for %s (%"PRId64")", |
| + info.name.c_str(), id)); |
| + |
| + for (size_t j = children.size(); j; j--) |
| + paths.push(make_pair(children[j-1], name)); |
| + } |
| + |
| + // +1 for the leading extra slash. |
| + const char* display_name = name.c_str() + 1; |
| + const char* directory_suffix = info.is_directory() ? "/" : ""; |
| + if (g_opt_long) { |
| + int64 size; |
| + if (info.is_directory()) { |
| + size = static_cast<int64>(children.size()); |
| + } else { |
| + file_util::GetFileSize(origin_dir.Append(info.data_path), &size); |
| + } |
| + // TODO(hamaji): Modification time? |
| + printf("%s%s %"PRId64" %"PRId64" %s\n", |
| + display_name, |
| + directory_suffix, |
| + id, |
| + size, |
| + info.data_path.value().c_str()); |
| + } else { |
| + printf("%s%s\n", display_name, directory_suffix); |
| + } |
| + } |
| +} |
| + |
| +static void DumpOrigin(const base::FilePath& file_system_dir, |
| + const std::string& origin_name) { |
| + FileSystemOriginDatabase origin_db(file_system_dir); |
| + base::FilePath origin_dir; |
| + if (!origin_db.HasOriginPath(origin_name)) |
| + ShowMessageAndExit("Origin " + origin_name + " is not in " + |
| + file_system_dir.value()); |
| + |
| + if (!origin_db.GetPathForOrigin(origin_name, &origin_dir)) |
| + ShowMessageAndExit("Failed to get path of origin " + origin_name + |
| + " in " + file_system_dir.value()); |
| + DumpDirectoryTree(origin_name, file_system_dir.Append(origin_dir)); |
| +} |
| + |
| +static void DumpFileSystem(const base::FilePath& file_system_dir) { |
| + FileSystemOriginDatabase origin_db(file_system_dir); |
| + std::vector<FileSystemOriginDatabase::OriginRecord> origins; |
| + origin_db.ListAllOrigins(&origins); |
| + for (size_t i = 0; i < origins.size(); i++) { |
| + const FileSystemOriginDatabase::OriginRecord& origin = origins[i]; |
| + DumpDirectoryTree(origin.origin, file_system_dir.Append(origin.path)); |
| + puts(""); |
| + } |
| +} |
| + |
| +} // namespace fileapi |
| + |
| +int main(int argc, char* argv[]) { |
| + const char* arg0 = argv[0]; |
| + while (true) { |
| + if (argc < 2) |
| + ShowUsageAndExit(arg0); |
| + |
| + if (std::string(argv[1]) == "-l") { |
| + fileapi::g_opt_long = true; |
| + argc--; |
| + argv++; |
| + } else if (std::string(argv[1]) == "-t") { |
| + fileapi::g_opt_temporary = true; |
| + argc--; |
| + argv++; |
| + } else { |
| + break; |
| + } |
| + } |
| + |
| + if (argc < 2) |
| + ShowUsageAndExit(arg0); |
| + |
| + const base::FilePath profile_dir(argv[1]); |
| + if (!file_util::DirectoryExists(profile_dir)) |
| + ShowMessageAndExit(profile_dir.value() + " is not a profile directory"); |
|
kinuko
2013/04/16 10:59:48
nit: "is not a directory" ?
hamaji
2013/04/16 12:25:12
Done.
|
| + |
| + const base::FilePath file_system_dir( |
| + profile_dir.Append("Default").Append("File System")); |
|
kinuko
2013/04/16 10:59:48
can you use
fileapi::SandboxMountPointProvider::kF
hamaji
2013/04/16 12:25:12
Done.
|
| + if (!file_util::DirectoryExists(file_system_dir)) |
| + ShowMessageAndExit(file_system_dir.value() + |
| + " is not a filesystem directory"); |
| + |
| + if (argc == 2) { |
| + fileapi::DumpFileSystem(file_system_dir); |
| + } else { |
| + for (int i = 2; i < argc; i++) { |
| + fileapi::DumpOrigin(file_system_dir, argv[i]); |
| + } |
| + } |
| + return 0; |
| +} |