blob: 53878213c605d90a2c35256a1c18f883d3c64b20 [file] [log] [blame]
rspangler@google.com49fdf182009-10-10 00:57:34 +00001// Copyright (c) 2009 The Chromium OS 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
rspangler@google.com49fdf182009-10-10 00:57:34 +00005#include "update_engine/download_action.h"
adlr@google.comc98a7ed2009-12-04 18:54:03 +00006#include <errno.h>
7#include <algorithm>
8#include <glib.h>
9#include "update_engine/action_pipe.h"
10
11using std::min;
rspangler@google.com49fdf182009-10-10 00:57:34 +000012
13namespace chromeos_update_engine {
14
adlr@google.comc98a7ed2009-12-04 18:54:03 +000015DownloadAction::DownloadAction(HttpFetcher* http_fetcher)
Andrew de los Reyesf9185172010-05-03 11:07:05 -070016 : writer_(NULL),
rspangler@google.com49fdf182009-10-10 00:57:34 +000017 http_fetcher_(http_fetcher) {}
18
19DownloadAction::~DownloadAction() {}
20
21void DownloadAction::PerformAction() {
22 http_fetcher_->set_delegate(this);
rspangler@google.com49fdf182009-10-10 00:57:34 +000023
adlr@google.comc98a7ed2009-12-04 18:54:03 +000024 // Get the InstallPlan and read it
25 CHECK(HasInputObject());
Andrew de los Reyesf9185172010-05-03 11:07:05 -070026 install_plan_ = GetInputObject();
adlr@google.comc98a7ed2009-12-04 18:54:03 +000027
Andrew de los Reyesf9185172010-05-03 11:07:05 -070028 install_plan_.Dump();
adlr@google.comc98a7ed2009-12-04 18:54:03 +000029
Andrew de los Reyesf9185172010-05-03 11:07:05 -070030 if (writer_) {
31 LOG(INFO) << "Using writer for test.";
rspangler@google.com49fdf182009-10-10 00:57:34 +000032 } else {
Andrew de los Reyesf9185172010-05-03 11:07:05 -070033 if (install_plan_.is_full_update) {
34 kernel_file_writer_.reset(new DirectFileWriter);
35 rootfs_file_writer_.reset(new DirectFileWriter);
36 split_file_writer_.reset(new SplitFileWriter(kernel_file_writer_.get(),
37 rootfs_file_writer_.get()));
38 split_file_writer_->SetFirstOpenArgs(
39 install_plan_.kernel_install_path.c_str(),
40 O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE,
41 0644);
42 decompressing_file_writer_.reset(
43 new GzipDecompressingFileWriter(split_file_writer_.get()));
44 writer_ = decompressing_file_writer_.get();
45 } else {
46 delta_performer_.reset(new DeltaPerformer);
47 writer_ = delta_performer_.get();
48 }
rspangler@google.com49fdf182009-10-10 00:57:34 +000049 }
Andrew de los Reyesf9185172010-05-03 11:07:05 -070050 int rc = writer_->Open(install_plan_.install_path.c_str(),
51 O_TRUNC | O_WRONLY | O_CREAT | O_LARGEFILE,
52 0644);
rspangler@google.com49fdf182009-10-10 00:57:34 +000053 if (rc < 0) {
Andrew de los Reyesf9185172010-05-03 11:07:05 -070054 LOG(ERROR) << "Unable to open output file " << install_plan_.install_path;
rspangler@google.com49fdf182009-10-10 00:57:34 +000055 // report error to processor
56 processor_->ActionComplete(this, false);
57 return;
58 }
Andrew de los Reyesf9185172010-05-03 11:07:05 -070059 if (!install_plan_.is_full_update) {
60 if (!delta_performer_->OpenKernel(
61 install_plan_.kernel_install_path.c_str())) {
62 LOG(ERROR) << "Unable to open kernel file "
63 << install_plan_.kernel_install_path.c_str();
64 writer_->Close();
65 processor_->ActionComplete(this, false);
66 return;
67 }
68 }
69 http_fetcher_->BeginTransfer(install_plan_.download_url);
rspangler@google.com49fdf182009-10-10 00:57:34 +000070}
71
72void DownloadAction::TerminateProcessing() {
73 CHECK(writer_);
74 CHECK_EQ(writer_->Close(), 0);
75 writer_ = NULL;
76 http_fetcher_->TerminateTransfer();
77}
78
79void DownloadAction::ReceivedBytes(HttpFetcher *fetcher,
80 const char* bytes,
81 int length) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +000082 int rc = writer_->Write(bytes, length);
83 TEST_AND_RETURN(rc >= 0);
rspangler@google.com49fdf182009-10-10 00:57:34 +000084 omaha_hash_calculator_.Update(bytes, length);
85}
86
87void DownloadAction::TransferComplete(HttpFetcher *fetcher, bool successful) {
88 if (writer_) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +000089 CHECK_EQ(writer_->Close(), 0) << errno;
rspangler@google.com49fdf182009-10-10 00:57:34 +000090 writer_ = NULL;
91 }
92 if (successful) {
93 // Make sure hash is correct
94 omaha_hash_calculator_.Finalize();
Andrew de los Reyesf9185172010-05-03 11:07:05 -070095 if (omaha_hash_calculator_.hash() != install_plan_.download_hash) {
96 LOG(ERROR) << "Download of " << install_plan_.download_url
97 << " failed. Expect hash " << install_plan_.download_hash
98 << " but got hash " << omaha_hash_calculator_.hash();
rspangler@google.com49fdf182009-10-10 00:57:34 +000099 successful = false;
100 }
101 }
102
103 // Write the path to the output pipe if we're successful
104 if (successful && HasOutputPipe())
adlr@google.comc98a7ed2009-12-04 18:54:03 +0000105 SetOutputObject(GetInputObject());
rspangler@google.com49fdf182009-10-10 00:57:34 +0000106 processor_->ActionComplete(this, successful);
107}
108
109}; // namespace {}