Home | History | Annotate | Download | only in dump_cache
      1 // Copyright (c) 2012 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 // This command-line program dumps the contents of a set of cache files, either
      6 // to stdout or to another set of cache files.
      7 
      8 #include <stdio.h>
      9 #include <string>
     10 
     11 #include "base/at_exit.h"
     12 #include "base/command_line.h"
     13 #include "base/strings/string16.h"
     14 #include "base/strings/string_util.h"
     15 #include "base/strings/stringprintf.h"
     16 #include "net/disk_cache/disk_format.h"
     17 #include "net/tools/dump_cache/dump_files.h"
     18 #include "net/tools/dump_cache/simple_cache_dumper.h"
     19 
     20 #if defined(OS_WIN)
     21 #include "base/process/launch.h"
     22 #include "base/win/scoped_handle.h"
     23 #include "net/tools/dump_cache/upgrade_win.h"
     24 #endif
     25 
     26 enum Errors {
     27   GENERIC = -1,
     28   ALL_GOOD = 0,
     29   INVALID_ARGUMENT = 1,
     30   FILE_ACCESS_ERROR,
     31   UNKNOWN_VERSION,
     32   TOOL_NOT_FOUND,
     33 };
     34 
     35 #if defined(OS_WIN)
     36 const char kUpgradeHelp[] =
     37     "\nIn order to use the upgrade function, a version of this tool that\n"
     38     "understands the file format of the files to upgrade is needed. For\n"
     39     "instance, to upgrade files saved with file format 3.4 to version 5.2,\n"
     40     "a version of this program that was compiled with version 3.4 has to be\n"
     41     "located beside this executable, and named dump_cache_3.exe, and this\n"
     42     "executable should be compiled with version 5.2 being the current one.";
     43 #endif  // defined(OS_WIN)
     44 
     45 // Folders to read and write cache files.
     46 const char kInputPath[] = "input";
     47 const char kOutputPath[] = "output";
     48 
     49 // Dumps the file headers to stdout.
     50 const char kDumpHeaders[] = "dump-headers";
     51 
     52 // Dumps all entries to stdout.
     53 const char kDumpContents[] = "dump-contents";
     54 
     55 // Convert the cache to files.
     56 const char kDumpToFiles[] = "dump-to-files";
     57 
     58 // Upgrade an old version to the current one.
     59 const char kUpgrade[] = "upgrade";
     60 
     61 // Internal use:
     62 const char kSlave[] = "slave";
     63 #if defined(OS_WIN)
     64 const char kPipe[] = "pipe";
     65 #endif  // defined(OS_WIN)
     66 
     67 int Help() {
     68   printf("warning: input files are modified by this tool\n");
     69   printf("dump_cache --input=path1 [--output=path2]\n");
     70   printf("--dump-headers: display file headers\n");
     71   printf("--dump-contents: display all entries\n");
     72   printf("--upgrade: copy contents to the output path\n");
     73   printf("--dump-to-files: write the contents of the cache to files\n");
     74   return INVALID_ARGUMENT;
     75 }
     76 
     77 #if defined(OS_WIN)
     78 
     79 // Starts a new process, to generate the files.
     80 int LaunchSlave(CommandLine command_line,
     81                 const base::string16& pipe_number,
     82                 int version) {
     83   bool do_upgrade = command_line.HasSwitch(kUpgrade);
     84   bool do_convert_to_text = command_line.HasSwitch(kDumpToFiles);
     85 
     86   if (do_upgrade) {
     87     base::FilePath program(
     88         base::StringPrintf(L"%ls%d", L"dump_cache", version));
     89     command_line.SetProgram(program);
     90   }
     91 
     92   if (do_upgrade || do_convert_to_text)
     93     command_line.AppendSwitch(kSlave);
     94 
     95   command_line.AppendSwitchNative(kPipe, pipe_number);
     96   if (!base::LaunchProcess(command_line, base::LaunchOptions(), NULL)) {
     97     printf("Unable to launch the needed version of this tool: %ls\n",
     98            command_line.GetProgram().value().c_str());
     99     printf(kUpgradeHelp);
    100     return TOOL_NOT_FOUND;
    101   }
    102   return ALL_GOOD;
    103 }
    104 
    105 #endif
    106 
    107 // -----------------------------------------------------------------------
    108 
    109 int main(int argc, const char* argv[]) {
    110   // Setup an AtExitManager so Singleton objects will be destroyed.
    111   base::AtExitManager at_exit_manager;
    112 
    113   CommandLine::Init(argc, argv);
    114 
    115   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
    116   base::FilePath input_path = command_line.GetSwitchValuePath(kInputPath);
    117   if (input_path.empty())
    118     return Help();
    119 
    120   bool dump_to_files = command_line.HasSwitch(kDumpToFiles);
    121   bool upgrade = command_line.HasSwitch(kUpgrade);
    122 
    123   base::FilePath output_path = command_line.GetSwitchValuePath(kOutputPath);
    124   if ((dump_to_files || upgrade) && output_path.empty())
    125     return Help();
    126 
    127   int version = GetMajorVersion(input_path);
    128   if (!version)
    129     return FILE_ACCESS_ERROR;
    130 
    131   bool slave_required = upgrade;
    132   if (version != disk_cache::kCurrentVersion >> 16) {
    133     if (command_line.HasSwitch(kSlave)) {
    134       printf("Unknown version\n");
    135       return UNKNOWN_VERSION;
    136     }
    137     slave_required = true;
    138   }
    139 
    140 #if defined(OS_WIN)
    141   base::string16 pipe_number = command_line.GetSwitchValueNative(kPipe);
    142   if (command_line.HasSwitch(kSlave) && slave_required)
    143     return RunSlave(input_path, pipe_number);
    144 
    145   base::win::ScopedHandle server;
    146   if (slave_required) {
    147     server.Set(CreateServer(&pipe_number));
    148     if (!server.IsValid()) {
    149       printf("Unable to create the server pipe\n");
    150       return GENERIC;
    151     }
    152 
    153     int ret = LaunchSlave(command_line, pipe_number, version);
    154     if (ret)
    155       return ret;
    156   }
    157 
    158   if (upgrade)
    159     return UpgradeCache(output_path, server);
    160 
    161   if (slave_required) {
    162     // Wait until the slave starts dumping data before we quit. Lazy "fix" for a
    163     // console quirk.
    164     Sleep(500);
    165     return ALL_GOOD;
    166   }
    167 #else  // defined(OS_WIN)
    168   if (slave_required) {
    169     printf("Unsupported operation\n");
    170     return INVALID_ARGUMENT;
    171   }
    172 #endif
    173 
    174   if (dump_to_files) {
    175     net::SimpleCacheDumper dumper(input_path, output_path);
    176     dumper.Run();
    177     return ALL_GOOD;
    178   }
    179 
    180   if (command_line.HasSwitch(kDumpContents))
    181     return DumpContents(input_path);
    182 
    183   if (command_line.HasSwitch(kDumpHeaders))
    184     return DumpHeaders(input_path);
    185 
    186   return Help();
    187 }
    188