Home | History | Annotate | Download | only in fileapi
      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 
     53 void ShowMessageAndExit(const std::string& msg) {
     54   fprintf(stderr, "%s\n", msg.c_str());
     55   exit(EXIT_FAILURE);
     56 }
     57 
     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 
     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);
     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 
    134 static void DumpOrigin(const base::FilePath& file_system_dir,
    135                        const std::string& origin_name) {
    136   SandboxOriginDatabase origin_db(file_system_dir);
    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 
    150 static void DumpFileSystem(const base::FilePath& file_system_dir) {
    151   SandboxOriginDatabase origin_db(file_system_dir);
    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 
    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