| OLD | NEW | 
|   1 // Copyright (c) 2009 The Chromium OS Authors. All rights reserved. |   1 // 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 |   2 // Use of this source code is governed by a BSD-style license that can be | 
|   3 // found in the LICENSE file. |   3 // found in the LICENSE file. | 
|   4  |   4  | 
 |   5 #include "update_engine/download_action.h" | 
 |   6 #include <errno.h> | 
 |   7 #include <algorithm> | 
|   5 #include <glib.h> |   8 #include <glib.h> | 
 |   9 #include "update_engine/action_pipe.h" | 
|   6  |  10  | 
|   7 #include "update_engine/action_pipe.h" |  11 using std::min; | 
|   8 #include "update_engine/download_action.h" |  | 
|   9  |  12  | 
|  10 namespace chromeos_update_engine { |  13 namespace chromeos_update_engine { | 
|  11  |  14  | 
|  12 DownloadAction::DownloadAction(const std::string& url, |  15 DownloadAction::DownloadAction(HttpFetcher* http_fetcher) | 
|  13                                const std::string& output_path, |  16     : size_(0), | 
|  14                                off_t size, const std::string& hash, |  17       should_decompress_(false), | 
|  15                                const bool should_decompress, |  | 
|  16                                HttpFetcher* http_fetcher) |  | 
|  17     : size_(size), |  | 
|  18       url_(url), |  | 
|  19       output_path_(output_path), |  | 
|  20       hash_(hash), |  | 
|  21       should_decompress_(should_decompress), |  | 
|  22       writer_(NULL), |  18       writer_(NULL), | 
|  23       http_fetcher_(http_fetcher) {} |  19       http_fetcher_(http_fetcher) {} | 
|  24  |  20  | 
|  25 DownloadAction::~DownloadAction() {} |  21 DownloadAction::~DownloadAction() {} | 
|  26  |  22  | 
|  27 void DownloadAction::PerformAction() { |  23 void DownloadAction::PerformAction() { | 
|  28   http_fetcher_->set_delegate(this); |  24   http_fetcher_->set_delegate(this); | 
|  29   CHECK(!writer_); |  25   CHECK(!writer_); | 
|  30   direct_file_writer_.reset(new DirectFileWriter); |  26   direct_file_writer_.reset(new DirectFileWriter); | 
|  31  |  27  | 
 |  28   // 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  | 
|  32   if (should_decompress_) { |  38   if (should_decompress_) { | 
|  33     decompressing_file_writer_.reset( |  39     decompressing_file_writer_.reset( | 
|  34         new GzipDecompressingFileWriter(direct_file_writer_.get())); |  40         new GzipDecompressingFileWriter(direct_file_writer_.get())); | 
|  35     writer_ = decompressing_file_writer_.get(); |  41     writer_ = decompressing_file_writer_.get(); | 
 |  42     output_path_ = install_plan.install_path; | 
|  36   } else { |  43   } else { | 
|  37     writer_ = direct_file_writer_.get(); |  44     writer_ = direct_file_writer_.get(); | 
|  38   } |  45   } | 
|  39  |  | 
|  40   int rc = writer_->Open(output_path_.c_str(), |  46   int rc = writer_->Open(output_path_.c_str(), | 
|  41                          O_TRUNC | O_WRONLY | O_CREAT | O_LARGEFILE, 0644); |  47                          O_TRUNC | O_WRONLY | O_CREAT | O_LARGEFILE, 0644); | 
|  42   if (rc < 0) { |  48   if (rc < 0) { | 
|  43     LOG(ERROR) << "Unable to open output file " << output_path_; |  49     LOG(ERROR) << "Unable to open output file " << output_path_; | 
|  44     // report error to processor |  50     // report error to processor | 
|  45     processor_->ActionComplete(this, false); |  51     processor_->ActionComplete(this, false); | 
|  46     return; |  52     return; | 
|  47   } |  53   } | 
|  48   http_fetcher_->BeginTransfer(url_); |  54   http_fetcher_->BeginTransfer(url_); | 
|  49 } |  55 } | 
|  50  |  56  | 
|  51 void DownloadAction::TerminateProcessing() { |  57 void DownloadAction::TerminateProcessing() { | 
|  52   CHECK(writer_); |  58   CHECK(writer_); | 
|  53   CHECK_EQ(writer_->Close(), 0); |  59   CHECK_EQ(writer_->Close(), 0); | 
|  54   writer_ = NULL; |  60   writer_ = NULL; | 
|  55   http_fetcher_->TerminateTransfer(); |  61   http_fetcher_->TerminateTransfer(); | 
|  56 } |  62 } | 
|  57  |  63  | 
|  58 void DownloadAction::ReceivedBytes(HttpFetcher *fetcher, |  64 void DownloadAction::ReceivedBytes(HttpFetcher *fetcher, | 
|  59                                    const char* bytes, |  65                                    const char* bytes, | 
|  60                                    int length) { |  66                                    int length) { | 
|  61   int bytes_written = 0; |  67   int rc = writer_->Write(bytes, length); | 
|  62   do { |  68   TEST_AND_RETURN(rc >= 0); | 
|  63     CHECK_GT(length, bytes_written); |  | 
|  64     int rc = writer_->Write(bytes + bytes_written, length - bytes_written); |  | 
|  65     // TODO(adlr): handle write error |  | 
|  66     CHECK_GE(rc, 0); |  | 
|  67     bytes_written += rc; |  | 
|  68   } while (length != bytes_written); |  | 
|  69   omaha_hash_calculator_.Update(bytes, length); |  69   omaha_hash_calculator_.Update(bytes, length); | 
|  70 } |  70 } | 
|  71  |  71  | 
|  72 void DownloadAction::TransferComplete(HttpFetcher *fetcher, bool successful) { |  72 void DownloadAction::TransferComplete(HttpFetcher *fetcher, bool successful) { | 
|  73   if (writer_) { |  73   if (writer_) { | 
|  74     CHECK_EQ(0, writer_->Close()) << errno; |  74     CHECK_EQ(writer_->Close(), 0) << errno; | 
|  75     writer_ = NULL; |  75     writer_ = NULL; | 
|  76   } |  76   } | 
|  77   if (successful) { |  77   if (successful) { | 
|  78     // Make sure hash is correct |  78     // Make sure hash is correct | 
|  79     omaha_hash_calculator_.Finalize(); |  79     omaha_hash_calculator_.Finalize(); | 
|  80     if (omaha_hash_calculator_.hash() != hash_) { |  80     if (omaha_hash_calculator_.hash() != hash_) { | 
|  81       LOG(INFO) << "Download of " << url_ << " failed. Expect hash " |  81       LOG(ERROR) << "Download of " << url_ << " failed. Expect hash " | 
|  82                 << hash_ << " but got hash " << omaha_hash_calculator_.hash(); |  82                  << hash_ << " but got hash " << omaha_hash_calculator_.hash(); | 
|  83       successful = false; |  83       successful = false; | 
|  84     } |  84     } | 
|  85   } |  85   } | 
|  86  |  86  | 
|  87   // Write the path to the output pipe if we're successful |  87   // Write the path to the output pipe if we're successful | 
|  88   if (successful && HasOutputPipe()) |  88   if (successful && HasOutputPipe()) | 
|  89     SetOutputObject(output_path_); |  89     SetOutputObject(GetInputObject()); | 
|  90   processor_->ActionComplete(this, successful); |  90   processor_->ActionComplete(this, successful); | 
|  91 } |  91 } | 
|  92  |  92  | 
|  93 };  // namespace {} |  93 };  // namespace {} | 
| OLD | NEW |