• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 //
5 // A tool to dump HTML5 filesystem from CUI.
6 //
7 // Usage:
8 //
9 // ./out/Release/dump_file_system [options] <filesystem dir> [origin]...
10 //
11 // If no origin is specified, this dumps all origins in the profile dir.
12 //
13 // Available options:
14 //
15 // -t : dumps temporary files instead of persistent.
16 // -s : dumps syncable files instead of persistent.
17 // -l : more information will be displayed.
18 //
19 // The format of -l option is:
20 //
21 // === ORIGIN origin_name origin_dir ===
22 // file_name file_id file_size file_content_path
23 // ...
24 //
25 // where file_name has a trailing slash, file_size is the number of
26 // children, and file_content_path is empty if the file is a directory.
27 //
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 
32 #include <stack>
33 #include <string>
34 #include <utility>
35 #include <vector>
36 
37 #include "base/file_util.h"
38 #include "base/files/file_path.h"
39 #include "base/format_macros.h"
40 #include "base/strings/stringprintf.h"
41 #include "webkit/browser/fileapi/obfuscated_file_util.h"
42 #include "webkit/browser/fileapi/sandbox_directory_database.h"
43 #include "webkit/browser/fileapi/sandbox_file_system_backend.h"
44 #include "webkit/browser/fileapi/sandbox_origin_database.h"
45 #include "webkit/common/fileapi/file_system_types.h"
46 #include "webkit/common/fileapi/file_system_util.h"
47 
48 namespace {
49 
50 bool g_opt_long;
51 const char* g_opt_fs_type = "p";
52 
ShowMessageAndExit(const std::string & msg)53 void ShowMessageAndExit(const std::string& msg) {
54   fprintf(stderr, "%s\n", msg.c_str());
55   exit(EXIT_FAILURE);
56 }
57 
ShowUsageAndExit(const std::string & arg0)58 void ShowUsageAndExit(const std::string& arg0) {
59   ShowMessageAndExit(
60       "Usage: " + arg0 +
61       " [-l] [-t] [-s] <filesystem dir> [origin]...");
62 }
63 
64 }  // namespace
65 
66 namespace fileapi {
67 
DumpDirectoryTree(const std::string & origin_name,base::FilePath origin_dir)68 static void DumpDirectoryTree(const std::string& origin_name,
69                               base::FilePath origin_dir) {
70   origin_dir = origin_dir.Append(g_opt_fs_type);
71 
72   printf("=== ORIGIN %s %s ===\n",
73          origin_name.c_str(), FilePathToString(origin_dir).c_str());
74 
75   if (!base::DirectoryExists(origin_dir))
76     return;
77 
78   SandboxDirectoryDatabase directory_db(origin_dir, NULL);
79   SandboxDirectoryDatabase::FileId root_id;
80   if (!directory_db.GetFileWithPath(StringToFilePath("/"), &root_id))
81     return;
82 
83   std::stack<std::pair<SandboxDirectoryDatabase::FileId,
84                        std::string> > paths;
85   paths.push(std::make_pair(root_id, ""));
86   while (!paths.empty()) {
87     SandboxDirectoryDatabase::FileId id = paths.top().first;
88     const std::string dirname = paths.top().second;
89     paths.pop();
90 
91     SandboxDirectoryDatabase::FileInfo info;
92     if (!directory_db.GetFileInfo(id, &info)) {
93       ShowMessageAndExit(base::StringPrintf("GetFileInfo failed for %"PRId64,
94                                             id));
95     }
96 
97     const std::string name =
98         dirname + "/" + FilePathToString(base::FilePath(info.name));
99     std::vector<SandboxDirectoryDatabase::FileId> children;
100     if (info.is_directory()) {
101       if (!directory_db.ListChildren(id, &children)) {
102         ShowMessageAndExit(base::StringPrintf(
103             "ListChildren failed for %s (%"PRId64")",
104             info.name.c_str(), id));
105       }
106 
107       for (size_t j = children.size(); j; j--)
108         paths.push(make_pair(children[j-1], name));
109     }
110 
111     // +1 for the leading extra slash.
112     const char* display_name = name.c_str() + 1;
113     const char* directory_suffix = info.is_directory() ? "/" : "";
114     if (g_opt_long) {
115       int64 size;
116       if (info.is_directory()) {
117         size = static_cast<int64>(children.size());
118       } else {
119         base::GetFileSize(origin_dir.Append(info.data_path), &size);
120       }
121       // TODO(hamaji): Modification time?
122       printf("%s%s %"PRId64" %"PRId64" %s\n",
123              display_name,
124              directory_suffix,
125              id,
126              size,
127              FilePathToString(info.data_path).c_str());
128     } else {
129       printf("%s%s\n", display_name, directory_suffix);
130     }
131   }
132 }
133 
DumpOrigin(const base::FilePath & file_system_dir,const std::string & origin_name)134 static void DumpOrigin(const base::FilePath& file_system_dir,
135                        const std::string& origin_name) {
136   SandboxOriginDatabase origin_db(file_system_dir, NULL);
137   base::FilePath origin_dir;
138   if (!origin_db.HasOriginPath(origin_name)) {
139     ShowMessageAndExit("Origin " + origin_name + " is not in " +
140                        FilePathToString(file_system_dir));
141   }
142 
143   if (!origin_db.GetPathForOrigin(origin_name, &origin_dir)) {
144     ShowMessageAndExit("Failed to get path of origin " + origin_name +
145                        " in " + FilePathToString(file_system_dir));
146   }
147   DumpDirectoryTree(origin_name, file_system_dir.Append(origin_dir));
148 }
149 
DumpFileSystem(const base::FilePath & file_system_dir)150 static void DumpFileSystem(const base::FilePath& file_system_dir) {
151   SandboxOriginDatabase origin_db(file_system_dir, NULL);
152   std::vector<SandboxOriginDatabase::OriginRecord> origins;
153   origin_db.ListAllOrigins(&origins);
154   for (size_t i = 0; i < origins.size(); i++) {
155     const SandboxOriginDatabase::OriginRecord& origin = origins[i];
156     DumpDirectoryTree(origin.origin, file_system_dir.Append(origin.path));
157     puts("");
158   }
159 }
160 
161 }  // namespace fileapi
162 
main(int argc,char * argv[])163 int main(int argc, char* argv[]) {
164   const char* arg0 = argv[0];
165   std::string username = "Default";
166   while (true) {
167     if (argc < 2)
168       ShowUsageAndExit(arg0);
169 
170     if (std::string(argv[1]) == "-l") {
171       g_opt_long = true;
172       argc--;
173       argv++;
174     } else if (std::string(argv[1]) == "-t") {
175       g_opt_fs_type = "t";
176       argc--;
177       argv++;
178     } else if (std::string(argv[1]) == "-s") {
179       g_opt_fs_type = "s";
180       argc--;
181       argv++;
182     } else {
183       break;
184     }
185   }
186 
187   if (argc < 2)
188     ShowUsageAndExit(arg0);
189 
190   const base::FilePath file_system_dir = fileapi::StringToFilePath(argv[1]);
191   if (!base::DirectoryExists(file_system_dir)) {
192     ShowMessageAndExit(fileapi::FilePathToString(file_system_dir) +
193                        " is not a filesystem directory");
194   }
195 
196   if (argc == 2) {
197     fileapi::DumpFileSystem(file_system_dir);
198   } else {
199     for (int i = 2; i < argc; i++) {
200       fileapi::DumpOrigin(file_system_dir, argv[i]);
201     }
202   }
203   return 0;
204 }
205