Commit 252600a1 authored by huangs's avatar huangs Committed by Commit Bot

[Zucchini] Add file read/write functions in zucchini_commands.c; add Zucchini-crc32.

More details:
- Injecting std::cout and std::cerr into Main*() functions.
- Add MainParams to simplify interfaces of Main*() functions.
- Add skeletal file reads and dummy file write to Zucchini-gen and
  Zucchini-apply.

Bug: 729154
Change-Id: I35d11e99b1863e77dee084635589022a6862d6e8
Reviewed-on: https://chromium-review.googlesource.com/592053
Commit-Queue: Samuel Huang <huangs@chromium.org>
Reviewed-by: default avatarGreg Thompson <grt@chromium.org>
Cr-Commit-Position: refs/heads/master@{#490807}
parent 6a19f321
......@@ -7,6 +7,7 @@
#include <stddef.h>
#include <memory>
#include <ostream>
#include <vector>
#include "base/command_line.h"
......@@ -50,8 +51,9 @@ struct Command {
/******** List of Zucchini commands ********/
constexpr Command kCommands[] = {
{"gen", "-gen <old_file> <new_file> <patch_file>", 3, MainGen},
{"apply", "-apply <old_file> <patch_file> <new_file>", 3, MainApply},
{"gen", "-gen <old_file> <new_file> <patch_file>", 3, &MainGen},
{"apply", "-apply <old_file> <patch_file> <new_file>", 3, &MainApply},
{"crc32", "-crc32 <file>", 1, &MainCrc32},
};
/******** ScopedResourceUsageTracker ********/
......@@ -128,10 +130,10 @@ bool CheckAndGetFilePathParams(const base::CommandLine& command_line,
}
// Prints main Zucchini usage text.
void PrintUsage(std::ostream& out) {
out << "Usage:" << std::endl;
void PrintUsage(std::ostream& err) {
err << "Usage:" << std::endl;
for (const Command& command : kCommands)
out << " zucchini " << command.usage << std::endl;
err << " zucchini " << command.usage << std::endl;
}
} // namespace
......@@ -139,7 +141,8 @@ void PrintUsage(std::ostream& out) {
/******** Exported Functions ********/
zucchini::status::Code RunZucchiniCommand(const base::CommandLine& command_line,
std::ostream& out) {
std::ostream& out,
std::ostream& err) {
// Look for a command with name that matches input.
const Command* command_use = nullptr;
for (const Command& command : kCommands) {
......@@ -154,24 +157,24 @@ zucchini::status::Code RunZucchiniCommand(const base::CommandLine& command_line,
// Expect exactly 1 matching command. If 0 or >= 2, print usage and quit.
if (!command_use) {
out << "Must have exactly one of:" << std::endl;
out << " [";
err << "Must have exactly one of:" << std::endl;
err << " [";
zucchini::PrefixSep sep(", ");
for (const Command& command : kCommands)
out << sep << "-" << command.name;
out << "]" << std::endl;
PrintUsage(out);
err << sep << "-" << command.name;
err << "]" << std::endl;
PrintUsage(err);
return zucchini::status::kStatusInvalidParam;
}
// Try to parse filename arguments. On failure, print usage and quit.
std::vector<base::FilePath> paths;
if (!CheckAndGetFilePathParams(command_line, command_use->num_args, &paths)) {
out << command_use->usage << std::endl;
PrintUsage(out);
err << command_use->usage << std::endl;
PrintUsage(err);
return zucchini::status::kStatusInvalidParam;
}
ScopedResourceUsageTracker resource_usage_tracker;
return command_use->command_function(command_line, paths);
return command_use->command_function({command_line, paths, out, err});
}
......@@ -5,7 +5,7 @@
#ifndef CHROME_INSTALLER_ZUCCHINI_MAIN_UTILS_H_
#define CHROME_INSTALLER_ZUCCHINI_MAIN_UTILS_H_
#include <ostream>
#include <iosfwd>
#include "base/files/file_path.h"
#include "chrome/installer/zucchini/zucchini.h"
......@@ -26,9 +26,10 @@ class CommandLine;
// 3. Add a new entry into |kCommands| in main_utils.cc.
// Searches |command_line| for Zucchini commands. If a unique command is found,
// runs it and logs resource usage. Otherwise prints help message to |out|.
// Returns Zucchini status code for error handling.
// runs it (passes |out| and |err|), and logs resource usage. Otherwise prints
// help message to |err|. Returns Zucchini status code for error handling.
zucchini::status::Code RunZucchiniCommand(const base::CommandLine& command_line,
std::ostream& out);
std::ostream& out,
std::ostream& err);
#endif // CHROME_INSTALLER_ZUCCHINI_MAIN_UTILS_H_
......@@ -16,6 +16,8 @@ namespace status {
enum Code {
kStatusSuccess = 0,
kStatusInvalidParam = 1,
kStatusFileReadError = 2,
kStatusFileWriteError = 3,
};
} // namespace status
......
......@@ -4,24 +4,119 @@
#include "chrome/installer/zucchini/zucchini_commands.h"
#include <iostream>
#include <ostream>
#include "base/command_line.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/files/memory_mapped_file.h"
#include "base/logging.h"
#include "base/macros.h"
#include "chrome/installer/zucchini/buffer_view.h"
#include "chrome/installer/zucchini/crc32.h"
#include "chrome/installer/zucchini/io_utils.h"
namespace {
// TODO(huangs): File I/O utilities.
/******** MappedFileReader ********/
// A file reader wrapper.
class MappedFileReader {
public:
explicit MappedFileReader(const base::FilePath& file_name) {
is_ok_ = buffer_.Initialize(file_name);
if (!is_ok_) // This is also triggered if |file_name| is an empty file.
LOG(ERROR) << "Can't read file: " << file_name.value();
}
bool is_ok() const { return is_ok_; }
const uint8_t* data() const { return buffer_.data(); }
size_t length() const { return buffer_.length(); }
zucchini::ConstBufferView region() const { return {data(), length()}; }
private:
bool is_ok_;
base::MemoryMappedFile buffer_;
DISALLOW_COPY_AND_ASSIGN(MappedFileReader);
};
/******** MappedFileWriter ********/
// A file writer wrapper.
class MappedFileWriter {
public:
MappedFileWriter(const base::FilePath& file_name, size_t length) {
using base::File;
CHECK_LE(length, static_cast<uint64_t>(INT64_MAX));
is_ok_ = buffer_.Initialize(
File(file_name,
File::FLAG_CREATE_ALWAYS | File::FLAG_READ | File::FLAG_WRITE),
{0, static_cast<int64_t>(length)},
base::MemoryMappedFile::READ_WRITE_EXTEND);
if (!is_ok_)
LOG(ERROR) << "Can't create file: " << file_name.value();
}
bool is_ok() const { return is_ok_; }
uint8_t* data() { return buffer_.data(); }
size_t length() const { return buffer_.length(); }
zucchini::MutableBufferView region() { return {data(), length()}; }
private:
bool is_ok_;
base::MemoryMappedFile buffer_;
DISALLOW_COPY_AND_ASSIGN(MappedFileWriter);
};
} // namespace
zucchini::status::Code MainGen(const base::CommandLine& command_line,
const std::vector<base::FilePath>& fnames) {
CHECK_EQ(3U, fnames.size());
zucchini::status::Code MainGen(MainParams params) {
CHECK_EQ(3U, params.file_paths.size());
MappedFileReader old_image(params.file_paths[0]);
if (!old_image.is_ok())
return zucchini::status::kStatusFileReadError;
MappedFileReader new_image(params.file_paths[1]);
if (!new_image.is_ok())
return zucchini::status::kStatusFileReadError;
// TODO(etiennep): Implement.
// Dummy output as placeholder.
MappedFileWriter patch(params.file_paths[2], 256);
if (!patch.is_ok())
return zucchini::status::kStatusFileWriteError;
return zucchini::status::kStatusSuccess;
}
zucchini::status::Code MainApply(const base::CommandLine& command_line,
const std::vector<base::FilePath>& fnames) {
CHECK_EQ(3U, fnames.size());
zucchini::status::Code MainApply(MainParams params) {
CHECK_EQ(3U, params.file_paths.size());
MappedFileReader old_image(params.file_paths[0]);
if (!old_image.is_ok())
return zucchini::status::kStatusFileReadError;
MappedFileReader patch(params.file_paths[1]);
if (!patch.is_ok())
return zucchini::status::kStatusFileReadError;
// TODO(etiennep): Implement.
// Dummy output as placeholder.
MappedFileWriter new_image(params.file_paths[2], 256);
if (!new_image.is_ok())
return zucchini::status::kStatusFileWriteError;
return zucchini::status::kStatusSuccess;
}
zucchini::status::Code MainCrc32(MainParams params) {
CHECK_EQ(1U, params.file_paths.size());
MappedFileReader image(params.file_paths[0]);
if (!image.is_ok())
return zucchini::status::kStatusFileReadError;
uint32_t crc =
zucchini::CalculateCrc32(image.data(), image.data() + image.length());
params.out << "CRC32: " << zucchini::AsHex<8>(crc) << std::endl;
return zucchini::status::kStatusSuccess;
}
......@@ -5,6 +5,7 @@
#ifndef CHROME_INSTALLER_ZUCCHINI_ZUCCHINI_COMMANDS_H_
#define CHROME_INSTALLER_ZUCCHINI_ZUCCHINI_COMMANDS_H_
#include <iosfwd>
#include <vector>
#include "base/files/file_path.h"
......@@ -18,17 +19,24 @@ class CommandLine;
} // namespace base
// Aggregated parameter for Main*() functions, to simplify interface.
struct MainParams {
const base::CommandLine& command_line;
const std::vector<base::FilePath>& file_paths;
std::ostream& out;
std::ostream& err;
};
// Signature of a Zucchini Command Function.
using CommandFunction =
zucchini::status::Code (*)(const base::CommandLine&,
const std::vector<base::FilePath>&);
using CommandFunction = zucchini::status::Code (*)(MainParams);
// Command Function: Patch generation.
zucchini::status::Code MainGen(const base::CommandLine& command_line,
const std::vector<base::FilePath>& fnames);
zucchini::status::Code MainGen(MainParams params);
// Command Function: Patch application.
zucchini::status::Code MainApply(const base::CommandLine& command_line,
const std::vector<base::FilePath>& fnames);
zucchini::status::Code MainApply(MainParams params);
// Command Function: Compute CRC-32 of a file.
zucchini::status::Code MainCrc32(MainParams params);
#endif // CHROME_INSTALLER_ZUCCHINI_ZUCCHINI_COMMANDS_H_
......@@ -44,5 +44,6 @@ int main(int argc, const char* argv[]) {
*base::CommandLine::ForCurrentProcess();
InitLogging();
InitErrorHandling(command_line);
return static_cast<int>(RunZucchiniCommand(command_line, std::cerr));
return static_cast<int>(
RunZucchiniCommand(command_line, std::cout, std::cerr));
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment