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..24c3aac4a62a50177573e4fc81b4c7bd0bced3d8 |
--- /dev/null |
+++ b/webkit/fileapi/dump_file_system.cc |
@@ -0,0 +1,224 @@ |
+// 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 [options] <profile dir> [origin]... |
+// |
+// If no origin is specified, this dumps all origins in the profile dir. |
+// |
+// Available options: |
+// |
+// -t : dumps temporary files instead of persistent. |
+// -s : dumps syncable files instead of persistent. |
+// -u user : uses the specified user name instead of "Default". |
+// -l : 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 <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/format_macros.h" |
+#include "base/stringprintf.h" |
+#include "webkit/fileapi/file_system_directory_database.h" |
+#include "webkit/fileapi/file_system_origin_database.h" |
+#include "webkit/fileapi/file_system_types.h" |
+#include "webkit/fileapi/file_system_util.h" |
+#include "webkit/fileapi/obfuscated_file_util.h" |
+#include "webkit/fileapi/sandbox_mount_point_provider.h" |
+ |
+namespace { |
+ |
+bool g_opt_long; |
+fileapi::FileSystemType g_opt_fs_type = fileapi::kFileSystemTypePersistent; |
+ |
+void ShowMessageAndExit(const std::string& msg) { |
+ fprintf(stderr, "%s\n", msg.c_str()); |
+ exit(EXIT_FAILURE); |
+} |
+ |
+void ShowUsageAndExit(const std::string& arg0) { |
+ ShowMessageAndExit("Usage: " + arg0 + |
+ " [-l] [-t] [-s] [-u user] <profile dir> [origin]..."); |
+} |
+ |
+} // namespace |
+ |
+namespace fileapi { |
+ |
+static void DumpDirectoryTree(const std::string& origin_name, |
+ base::FilePath origin_dir) { |
+ origin_dir = origin_dir.Append( |
+ ObfuscatedFileUtil::GetDirectoryNameForType(g_opt_fs_type)); |
+ |
+ printf("=== ORIGIN %s %s ===\n", |
+ origin_name.c_str(), FilePathToString(origin_dir).c_str()); |
+ |
+ if (!file_util::DirectoryExists(origin_dir)) { |
+ ShowMessageAndExit(FilePathToString(origin_dir) + |
+ " is not a filesystem origin directory"); |
+ } |
+ |
+ FileSystemDirectoryDatabase directory_db(origin_dir); |
+ FileSystemDirectoryDatabase::FileId root_id; |
+ if (!directory_db.GetFileWithPath(StringToFilePath("/"), &root_id)) { |
+ ShowMessageAndExit(FilePathToString(origin_dir) + |
+ " 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 + "/" + FilePathToString(base::FilePath(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, |
+ FilePathToString(info.data_path).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 " + |
+ FilePathToString(file_system_dir)); |
+ } |
+ |
+ if (!origin_db.GetPathForOrigin(origin_name, &origin_dir)) { |
+ ShowMessageAndExit("Failed to get path of origin " + origin_name + |
+ " in " + FilePathToString(file_system_dir)); |
+ } |
+ 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]; |
+ std::string username = "Default"; |
+ while (true) { |
+ if (argc < 2) |
+ ShowUsageAndExit(arg0); |
+ |
+ if (std::string(argv[1]) == "-l") { |
+ g_opt_long = true; |
+ argc--; |
+ argv++; |
+ } else if (std::string(argv[1]) == "-t") { |
+ g_opt_fs_type = fileapi::kFileSystemTypeTemporary; |
+ argc--; |
+ argv++; |
+ } else if (std::string(argv[1]) == "-s") { |
+ g_opt_fs_type = fileapi::kFileSystemTypeSyncable; |
+ argc--; |
+ argv++; |
+ } else if (std::string(argv[1]) == "-u") { |
+ if (argc < 3) |
+ ShowUsageAndExit(arg0); |
+ username = argv[2]; |
+ argc -= 2; |
+ argv += 2; |
+ } else { |
+ break; |
+ } |
+ } |
+ |
+ if (argc < 2) |
+ ShowUsageAndExit(arg0); |
+ |
+ const base::FilePath profile_dir(fileapi::StringToFilePath(argv[1])); |
+ if (!file_util::DirectoryExists(profile_dir)) { |
+ ShowMessageAndExit(fileapi::FilePathToString(profile_dir) + |
+ " is not a directory"); |
+ } |
+ |
+ const base::FilePath file_system_dir( |
+ profile_dir.Append(fileapi::StringToFilePath(username)).Append( |
+ base::FilePath( |
+ fileapi::SandboxMountPointProvider::kFileSystemDirectory))); |
+ if (!file_util::DirectoryExists(file_system_dir)) { |
+ ShowMessageAndExit(fileapi::FilePathToString(file_system_dir) + |
+ " 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; |
+} |