blob: 833f806edd1baa32105248768c1a9ad6ed4639ba [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;
34 output_path_ = install_plan.download_path;
35 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();
adlr@google.comc98a7ed2009-12-04 18:54:03 +000042 output_path_ = install_plan.install_path;
rspangler@google.com49fdf182009-10-10 00:57:34 +000043 } else {
44 writer_ = direct_file_writer_.get();
45 }
rspangler@google.com49fdf182009-10-10 00:57:34 +000046 int rc = writer_->Open(output_path_.c_str(),
47 O_TRUNC | O_WRONLY | O_CREAT | O_LARGEFILE, 0644);
48 if (rc < 0) {
49 LOG(ERROR) << "Unable to open output file " << output_path_;
50 // report error to processor
51 processor_->ActionComplete(this, false);
52 return;
53 }
54 http_fetcher_->BeginTransfer(url_);
55}
56
57void DownloadAction::TerminateProcessing() {
58 CHECK(writer_);
59 CHECK_EQ(writer_->Close(), 0);
60 writer_ = NULL;
61 http_fetcher_->TerminateTransfer();
62}
63
64void DownloadAction::ReceivedBytes(HttpFetcher *fetcher,
65 const char* bytes,
66 int length) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +000067 int rc = writer_->Write(bytes, length);
68 TEST_AND_RETURN(rc >= 0);
rspangler@google.com49fdf182009-10-10 00:57:34 +000069 omaha_hash_calculator_.Update(bytes, length);
70}
71
72void DownloadAction::TransferComplete(HttpFetcher *fetcher, bool successful) {
73 if (writer_) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +000074 CHECK_EQ(writer_->Close(), 0) << errno;
rspangler@google.com49fdf182009-10-10 00:57:34 +000075 writer_ = NULL;
76 }
77 if (successful) {
78 // Make sure hash is correct
79 omaha_hash_calculator_.Finalize();
80 if (omaha_hash_calculator_.hash() != hash_) {
adlr@google.comc98a7ed2009-12-04 18:54:03 +000081 LOG(ERROR) << "Download of " << url_ << " failed. Expect hash "
82 << hash_ << " but got hash " << omaha_hash_calculator_.hash();
rspangler@google.com49fdf182009-10-10 00:57:34 +000083 successful = false;
84 }
85 }
86
87 // Write the path to the output pipe if we're successful
88 if (successful && HasOutputPipe())
adlr@google.comc98a7ed2009-12-04 18:54:03 +000089 SetOutputObject(GetInputObject());
rspangler@google.com49fdf182009-10-10 00:57:34 +000090 processor_->ActionComplete(this, successful);
91}
92
93}; // namespace {}