Index: src/platform/update_engine/install_action.cc |
diff --git a/src/platform/update_engine/install_action.cc b/src/platform/update_engine/install_action.cc |
deleted file mode 100644 |
index d144b7bbd36ae2b3acc6bba853a2a083153c3661..0000000000000000000000000000000000000000 |
--- a/src/platform/update_engine/install_action.cc |
+++ /dev/null |
@@ -1,260 +0,0 @@ |
-// Copyright (c) 2009 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/install_action.h" |
-#include <errno.h> |
-#include <string> |
-#include <vector> |
-#include <gflags/gflags.h> |
-#include "update_engine/filesystem_iterator.h" |
-#include "update_engine/gzip.h" |
-#include "update_engine/subprocess.h" |
-#include "update_engine/utils.h" |
- |
-DEFINE_string(mount_install_path, "", |
- "If set, the path to use when mounting the " |
- "destination device during install"); |
- |
-using std::string; |
-using std::vector; |
- |
-namespace chromeos_update_engine { |
- |
-namespace { |
-const string kBspatchPath = "/usr/bin/bspatch"; |
-} |
- |
-void InstallAction::PerformAction() { |
- ScopedActionCompleter completer(processor_, this); |
- // For now, do nothing other than pass what we need to to the output pipe |
- CHECK(HasInputObject()); |
- const InstallPlan install_plan = GetInputObject(); |
- if (HasOutputPipe()) |
- SetOutputObject(install_plan.install_path); |
- if (install_plan.is_full_update) { |
- // No need to perform an install |
- completer.set_success(true); |
- return; |
- } |
- // We have a delta update. |
- |
- // Open delta file |
- DeltaDiffParser parser(install_plan.download_path); |
- if (!parser.valid()) { |
- LOG(ERROR) << "Unable to open delta file"; |
- return; |
- } |
- |
- // Mount install fs |
- string mountpoint = FLAGS_mount_install_path; |
- if (mountpoint.empty()) { |
- // Set up dest_path_ |
- char *mountpoint_temp = strdup("/tmp/install_mnt.XXXXXX"); |
- CHECK(mountpoint_temp); |
- CHECK_EQ(mountpoint_temp, mkdtemp(mountpoint_temp)); |
- CHECK_NE('\0', mountpoint_temp[0]); |
- mountpoint = mountpoint_temp; |
- free(mountpoint_temp); |
- } |
- |
- TEST_AND_RETURN(utils::MountFilesystem(install_plan.install_path, |
- mountpoint)); |
- |
- // Automatically unmount the fs when this goes out of scope: |
- ScopedFilesystemUnmounter filesystem_unmounter(mountpoint); |
- |
- { |
- // Iterate through existing fs, deleting unneeded files |
- // Delete files that don't exist in the update, or exist but are |
- // hard links. |
- FilesystemIterator iter(mountpoint, |
- utils::SetWithValue<string>("/lost+found")); |
- for (; !iter.IsEnd(); iter.Increment()) { |
- if (!parser.ContainsPath(iter.GetPartialPath()) || |
- parser.GetFileAtPath(iter.GetPartialPath()).has_hardlink_path()) { |
- VLOG(1) << "install removing local path: " << iter.GetFullPath(); |
- TEST_AND_RETURN(utils::RecursiveUnlinkDir(iter.GetFullPath())); |
- } |
- } |
- TEST_AND_RETURN(!iter.IsErr()); |
- } |
- |
- // iterate through delta metadata, writing files |
- DeltaDiffParserIterator iter = parser.Begin(); |
- for (; iter != parser.End(); iter.Increment()) { |
- const DeltaArchiveManifest_File& file = iter.GetFile(); |
- VLOG(1) << "Installing file: " << iter.path(); |
- TEST_AND_RETURN(InstallFile(mountpoint, file, iter.path(), parser)); |
- } |
- |
- completer.set_success(true); |
-} |
- |
-bool InstallAction::InstallFile(const std::string& mountpoint, |
- const DeltaArchiveManifest_File& file, |
- const std::string& path, |
- const DeltaDiffParser& parser) const { |
- // See what's already there |
- struct stat existing_stbuf; |
- int result = lstat((mountpoint + path).c_str(), &existing_stbuf); |
- TEST_AND_RETURN_FALSE_ERRNO((result == 0) || (errno == ENOENT)); |
- bool exists = (result == 0); |
- // Create the proper file |
- if (file.has_hardlink_path()) { |
- TEST_AND_RETURN_FALSE(file.has_hardlink_path()); |
- TEST_AND_RETURN_FALSE_ERRNO(link( |
- (mountpoint + file.hardlink_path()).c_str(), |
- (mountpoint + path).c_str()) == 0); |
- } else if (S_ISDIR(file.mode())) { |
- if (!exists) { |
- TEST_AND_RETURN_FALSE_ERRNO( |
- (mkdir((mountpoint + path).c_str(), file.mode())) == 0); |
- } |
- } else if (S_ISLNK(file.mode())) { |
- InstallFileSymlink(mountpoint, file, path, parser, exists); |
- } else if (S_ISCHR(file.mode()) || |
- S_ISBLK(file.mode()) || |
- S_ISFIFO(file.mode()) || |
- S_ISSOCK(file.mode())) { |
- InstallFileSpecialFile(mountpoint, file, path, parser, exists); |
- } else if (S_ISREG(file.mode())) { |
- InstallFileRegularFile(mountpoint, file, path, parser, exists); |
- } else { |
- // unknown mode type |
- TEST_AND_RETURN_FALSE(false); |
- } |
- |
- // chmod/chown new file |
- TEST_AND_RETURN_FALSE(file.has_uid() && file.has_gid()); |
- TEST_AND_RETURN_FALSE_ERRNO(lchown((mountpoint + path).c_str(), |
- file.uid(), file.gid()) == 0); |
- if (!S_ISLNK(file.mode())) |
- TEST_AND_RETURN_FALSE_ERRNO(chmod((mountpoint + path).c_str(), file.mode()) |
- == 0); |
- return true; |
-} |
- |
-bool InstallAction::InstallFileRegularFile( |
- const std::string& mountpoint, |
- const DeltaArchiveManifest_File& file, |
- const std::string& path, |
- const DeltaDiffParser& parser, |
- const bool exists) const { |
- if (!file.has_data_format()) |
- return true; |
- TEST_AND_RETURN_FALSE(file.has_data_offset() && file.has_data_length()); |
- if (file.data_format() == DeltaArchiveManifest_File_DataFormat_BSDIFF) { |
- // Expand with bspatch |
- string patch_path = utils::TempFilename(mountpoint + path + ".XXXXXX"); |
- TEST_AND_RETURN_FALSE(file.has_data_length()); |
- TEST_AND_RETURN_FALSE(parser.CopyDataToFile( |
- file.data_offset(), |
- static_cast<off_t>(file.data_length()), false, |
- patch_path)); |
- string output_path = utils::TempFilename(mountpoint + path + ".XXXXXX"); |
- int rc = 1; |
- vector<string> cmd; |
- cmd.push_back(kBspatchPath); |
- cmd.push_back(mountpoint + path); |
- cmd.push_back(output_path); |
- cmd.push_back(patch_path); |
- TEST_AND_RETURN_FALSE(Subprocess::SynchronousExec(cmd, &rc)); |
- TEST_AND_RETURN_FALSE(rc == 0); |
- TEST_AND_RETURN_FALSE_ERRNO(rename(output_path.c_str(), |
- (mountpoint + path).c_str()) == 0); |
- TEST_AND_RETURN_FALSE_ERRNO(unlink(patch_path.c_str()) == 0); |
- } else { |
- // Expand full data, decompressing if necessary |
- TEST_AND_RETURN_FALSE((file.data_format() == |
- DeltaArchiveManifest_File_DataFormat_FULL) || |
- (file.data_format() == |
- DeltaArchiveManifest_File_DataFormat_FULL_GZ)); |
- if (exists) |
- TEST_AND_RETURN_FALSE_ERRNO(unlink((mountpoint + path).c_str()) == 0); |
- TEST_AND_RETURN_FALSE(file.has_data_length()); |
- const bool gzipped = file.data_format() == |
- DeltaArchiveManifest_File_DataFormat_FULL_GZ; |
- bool success = |
- parser.CopyDataToFile(file.data_offset(), file.data_length(), |
- gzipped, |
- mountpoint + path); |
- TEST_AND_RETURN_FALSE(success); |
- } |
- return true; |
-} |
- |
-// char/block devices, fifos, and sockets: |
-bool InstallAction::InstallFileSpecialFile( |
- const std::string& mountpoint, |
- const DeltaArchiveManifest_File& file, |
- const std::string& path, |
- const DeltaDiffParser& parser, |
- const bool exists) const { |
- if (exists) |
- TEST_AND_RETURN_FALSE(unlink((mountpoint + path).c_str()) == 0); |
- dev_t dev = 0; |
- if (S_ISCHR(file.mode()) || S_ISBLK(file.mode())) { |
- vector<char> dev_proto; |
- TEST_AND_RETURN_FALSE(file.has_data_format()); |
- TEST_AND_RETURN_FALSE(parser.ReadDataVector(file.data_offset(), |
- file.data_length(), |
- &dev_proto)); |
- if (file.data_format() == DeltaArchiveManifest_File_DataFormat_FULL_GZ) { |
- TEST_AND_RETURN_FALSE(file.has_data_length()); |
- { |
- vector<char> decompressed_dev_proto; |
- TEST_AND_RETURN_FALSE(GzipDecompress(dev_proto, |
- &decompressed_dev_proto)); |
- dev_proto = decompressed_dev_proto; |
- } |
- } else { |
- TEST_AND_RETURN_FALSE(file.data_format() == |
- DeltaArchiveManifest_File_DataFormat_FULL); |
- } |
- LinuxDevice linux_device; |
- utils::HexDumpVector(dev_proto); |
- TEST_AND_RETURN_FALSE(linux_device.ParseFromArray(&dev_proto[0], |
- dev_proto.size())); |
- dev = makedev(linux_device.major(), linux_device.minor()); |
- } |
- TEST_AND_RETURN_FALSE_ERRNO(mknod((mountpoint + path).c_str(), |
- file.mode(), dev) == 0); |
- return true; |
-} |
-// symlinks: |
-bool InstallAction::InstallFileSymlink(const std::string& mountpoint, |
- const DeltaArchiveManifest_File& file, |
- const std::string& path, |
- const DeltaDiffParser& parser, |
- const bool exists) const { |
- // If there's no data, we leave the symlink as is |
- if (!file.has_data_format()) |
- return true; // No changes needed |
- TEST_AND_RETURN_FALSE((file.data_format() == |
- DeltaArchiveManifest_File_DataFormat_FULL) || |
- (file.data_format() == |
- DeltaArchiveManifest_File_DataFormat_FULL_GZ)); |
- TEST_AND_RETURN_FALSE(file.has_data_offset() && file.has_data_length()); |
- // We have data, and thus use it to create a symlink. |
- // First delete any existing symlink: |
- if (exists) |
- TEST_AND_RETURN_FALSE_ERRNO(unlink((mountpoint + path).c_str()) == 0); |
- vector<char> symlink_data; |
- TEST_AND_RETURN_FALSE(parser.ReadDataVector(file.data_offset(), |
- file.data_length(), |
- &symlink_data)); |
- if (file.data_format() == DeltaArchiveManifest_File_DataFormat_FULL_GZ) { |
- vector<char> decompressed_symlink_data; |
- TEST_AND_RETURN_FALSE(GzipDecompress(symlink_data, |
- &decompressed_symlink_data)); |
- symlink_data = decompressed_symlink_data; |
- } |
- symlink_data.push_back('\0'); |
- TEST_AND_RETURN_FALSE_ERRNO(symlink(&symlink_data[0], |
- (mountpoint + path).c_str()) == 0); |
- return true; |
-} |
- |
- |
-} // namespace chromeos_update_engine |