blob: 6da671947a28b33c5543063f05ce1e70dda617e3 [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)
16 : size_(0),
17 should_decompress_(false),
rspangler@google.com49fdf182009-10-10 00:57:34 +000018 writer_(NULL),
19 http_fetcher_(http_fetcher) {}
20
21DownloadAction::~DownloadAction() {}
22
23void DownloadAction::PerformAction() {
24 http_fetcher_->set_delegate(this);
25 CHECK(!writer_);
26 direct_file_writer_.reset(new DirectFileWriter);
27
adlr@google.comc98a7ed2009-12-04 18:54:03 +000028 // Get the InstallPlan and read it
29 CHECK(HasInputObject());
30 InstallPlan install_plan(GetInputObject());
31
32 should_decompress_ = install_plan.is_full_update;
33 url_ = install_plan.download_url;
Andrew de los Reyes1e338b82010-01-22 14:57:27 -080034 output_path_ = install_plan.install_path;
adlr@google.comc98a7ed2009-12-04 18:54:03 +000035 hash_ = install_plan.download_hash;
36 install_plan.Dump();
37
rspangler@google.com49fdf182009-10-10 00:57:34 +000038 if (should_decompress_) {
39 decompressing_file_writer_.reset(
40 new GzipDecompressingFileWriter(direct_file_writer_.get()));
41 writer_ = decompressing_file_writer_.get();
42 } else {
43 writer_ = direct_file_writer_.get();
44 }
rspangler@google.com49fdf182009-10-10 00:57:34 +000045 int rc = writer_->Open(output_path_.c_str(),
46 O_TRUNC | O_WRONLY | O_CREAT | O_LARGEFILE, 0644);
47 if (rc < 0) {
48 LOG(ERROR) << "Unable to open output file " << output_path_;
49 // report error to processor
50 processor_->ActionComplete(this, false);
51 return;
52 }
53 http_fetcher_->BeginTransfer(url_);
54}
55
56void DownloadAction::TerminateProcessing() {
57 CHECK(writer_);
58 CHECK_EQ(writer_->Close(), 0);
59 writer_ = NULL;
60 http_fetcher_->TerminateTransfer();
61}
62
63void DownloadAction::ReceivedBytes(HttpFetcher *fetcher,
64 const char* bytes,
65 int length) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +000066 int rc = writer_->Write(bytes, length);
67 TEST_AND_RETURN(rc >= 0);
rspangler@google.com49fdf182009-10-10 00:57:34 +000068 omaha_hash_calculator_.Update(bytes, length);
69}
70
71void DownloadAction::TransferComplete(HttpFetcher *fetcher, bool successful) {
72 if (writer_) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +000073 CHECK_EQ(writer_->Close(), 0) << errno;
rspangler@google.com49fdf182009-10-10 00:57:34 +000074 writer_ = NULL;
75 }
76 if (successful) {
77 // Make sure hash is correct
78 omaha_hash_calculator_.Finalize();
79 if (omaha_hash_calculator_.hash() != hash_) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +000080 LOG(ERROR) << "Download of " << url_ << " failed. Expect hash "
81 << hash_ << " but got hash " << omaha_hash_calculator_.hash();
rspangler@google.com49fdf182009-10-10 00:57:34 +000082 successful = false;
83 }
84 }
85
86 // Write the path to the output pipe if we're successful
87 if (successful && HasOutputPipe())
adlr@google.comc98a7ed2009-12-04 18:54:03 +000088 SetOutputObject(GetInputObject());
rspangler@google.com49fdf182009-10-10 00:57:34 +000089 processor_->ActionComplete(this, successful);
90}
91
92}; // namespace {}