blob: 1cec31e052f279870468e5003c8f9cb9c5a5cfbc [file] [log] [blame]
// Copyright (c) 2010 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.
#include "update_engine/set_bootable_flag_action.h"
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <string>
#include <vector>
#include "update_engine/subprocess.h"
#include "update_engine/utils.h"
using std::string;
using std::vector;
namespace chromeos_update_engine {
namespace {
const char* const kGpt = "/usr/bin/gpt";
const ssize_t kPmbrLength = 512;
}
void SetBootableFlagAction::PerformAction() {
ScopedActionCompleter completer(processor_, this);
TEST_AND_RETURN(HasInputObject());
const InstallPlan install_plan = GetInputObject();
TEST_AND_RETURN(!install_plan.install_path.empty());
const string partition = install_plan.install_path;
string root_device = utils::RootDevice(partition);
string partition_number = utils::PartitionNumber(partition);
utils::BootLoader boot_loader;
TEST_AND_RETURN(utils::GetBootloader(&boot_loader));
// For now, only support Syslinux bootloader
TEST_AND_RETURN(boot_loader == utils::BootLoader_SYSLINUX);
string temp_file;
TEST_AND_RETURN(utils::MakeTempFile("/tmp/pmbr_copy.XXXXXX",
&temp_file,
NULL));
ScopedPathUnlinker temp_file_unlinker(temp_file);
// Copy existing PMBR to temp file
vector<char> buf(kPmbrLength);
{
int fd = open(root_device.c_str(), O_RDONLY);
TEST_AND_RETURN(fd >= 0);
ScopedFdCloser fd_closer(&fd);
ssize_t bytes_read;
TEST_AND_RETURN(utils::PReadAll(fd, &buf[0], buf.size(), 0, &bytes_read));
}
TEST_AND_RETURN(utils::WriteFile(temp_file.c_str(), &buf[0], buf.size()));
// Call gpt tool to do the work
vector<string> command;
command.push_back(kGpt);
command.push_back("-S");
command.push_back("boot");
command.push_back("-i");
command.push_back(partition_number);
command.push_back("-b");
command.push_back(temp_file);
command.push_back(root_device);
int rc = 0;
Subprocess::SynchronousExec(command, &rc);
TEST_AND_RETURN(rc == 0);
completer.set_code(kActionCodeSuccess);
if (HasOutputPipe())
SetOutputObject(GetInputObject());
}
} // namespace chromeos_update_engine