├── inherit-review-settings-ok ├── src ├── update_engine │ ├── marshal.list │ ├── http_fetcher_unittest.h │ ├── update_attempter_mock.cc │ ├── bzip.h │ ├── dbus_constants.h │ ├── action_processor_mock.h │ ├── file_writer_mock.h │ ├── http_fetcher.cc │ ├── action_mock.h │ ├── update_attempter_mock.h │ ├── certificate_checker_mock.h │ ├── mock_system_state.cc │ ├── system_state.cc │ ├── simple_key_value_store.h │ ├── topological_sort.h │ ├── prefs_mock.h │ ├── terminator.cc │ ├── update_engine.xml │ ├── testrunner.cc │ ├── bzip_extent_writer.h │ ├── topological_sort.cc │ ├── file_writer.cc │ ├── tarjan.h │ ├── mock_payload_state.h │ ├── simple_key_value_store.cc │ ├── action_pipe_unittest.cc │ ├── extent_mapper.h │ ├── file_writer_unittest.cc │ ├── ext2_metadata.h │ ├── kernel_verifier_action.h │ ├── terminator.h │ ├── kernel_copier_action.h │ ├── simple_key_value_store_unittest.cc │ ├── mock_file_writer.h │ ├── system_state.h │ ├── delta_metadata.h │ ├── action_unittest.cc │ ├── prefs.h │ ├── postinstall_runner_action.h │ ├── real_system_state.h │ ├── extent_writer.cc │ ├── delta_metadata.cc │ ├── full_update_generator.h │ ├── extent_mapper.cc │ ├── omaha_response.h │ ├── http_common.h │ ├── mock_system_state.h │ ├── terminator_unittest.cc │ ├── cycle_breaker.h │ ├── graph_utils.h │ ├── delta_performer_unittest.cc │ ├── tarjan.cc │ ├── bzip_extent_writer.cc │ ├── install_plan.cc │ ├── pcr_policy_post_action.h │ ├── kernel_copier_action.cc │ ├── graph_types.h │ ├── extent_ranges.h │ ├── kernel_verifier_action.cc │ ├── http_common.cc │ ├── action_processor.cc │ ├── dbus_service.h │ ├── install_plan.h │ ├── topological_sort_unittest.cc │ ├── prefs_interface.h │ ├── tarjan_unittest.cc │ ├── extent_mapper_unittest.cc │ ├── payload_state_interface.h │ ├── file_writer.h │ ├── omaha_response_handler_action.h │ ├── action_pipe.h │ ├── postinstall_runner_action.cc │ ├── subprocess.h │ ├── zip_unittest.cc │ ├── dbus_service.cc │ └── bzip.cc ├── files │ ├── file_enumerator.cc │ ├── file_path_constants.cc │ ├── scoped_file.h │ ├── scoped_file.cc │ ├── scoped_file_unittest.cc │ ├── eintr_wrapper.h │ ├── scoped_temp_dir.cc │ ├── scoped_temp_dir.h │ ├── file_util.cc │ └── scoped_temp_dir_unittest.cc ├── strings │ ├── string_printf.cc │ ├── string_printf.h │ ├── string_split.h │ ├── string_printf_unittest.cc │ ├── string_number_conversions.h │ ├── string_split.cc │ └── string_number_conversions.cc └── macros.h ├── autogen.sh ├── NOTICE ├── README.md ├── systemd ├── update-engine-stub.service ├── update-engine-stub.timer ├── update-engine.service └── update_engine_stub ├── WATCHLISTS ├── coreos-setgoodroot ├── run_unittests_as_user ├── run_unittests_as_root ├── .gitignore ├── com.coreos.update1.conf ├── sample_omaha_v3_response.xml ├── DCO ├── LICENSE ├── unittest_key.pem ├── unittest_key2.pem ├── local_coverage_rate ├── code-of-conduct.md └── Jenkinsfile /inherit-review-settings-ok: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/update_engine/marshal.list: -------------------------------------------------------------------------------- 1 | VOID:INT64,DOUBLE,STRING,STRING,INT64 2 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -ex 3 | autoreconf --force --install --symlink 4 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | CoreOS Project 2 | Copyright 2018 CoreOS, Inc 3 | 4 | This product includes software developed at CoreOS, Inc. 5 | (http://www.coreos.com/). 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # update_engine 2 | 3 | update daemon for CoreOS 4 | 5 | ## Bugs 6 | 7 | Please use the [CoreOS issue tracker][bugs] to report all bugs, issues, and feature requests. 8 | 9 | [bugs]: https://github.com/coreos/bugs/issues/new?labels=component/update-engine 10 | -------------------------------------------------------------------------------- /systemd/update-engine-stub.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Update Engine Stub 3 | ConditionVirtualization=!container 4 | ConditionPathExists=/usr/.noupdate 5 | 6 | [Service] 7 | Type=oneshot 8 | ExecStart=/usr/sbin/update_engine_stub 9 | 10 | [Install] 11 | WantedBy=multi-user.target 12 | -------------------------------------------------------------------------------- /systemd/update-engine-stub.timer: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Update Engine Stub Timer 3 | ConditionVirtualization=!container 4 | ConditionPathExists=/usr/.noupdate 5 | 6 | [Timer] 7 | OnBootSec=7minutes 8 | OnActiveSec=41minutes 9 | Unit=update-engine-stub.service 10 | 11 | [Install] 12 | WantedBy=multi-user.target 13 | -------------------------------------------------------------------------------- /WATCHLISTS: -------------------------------------------------------------------------------- 1 | # See http://dev.chromium.org/developers/contributing-code/watchlists for 2 | # a description of this file's format. 3 | # Please keep these keys in alphabetical order. 4 | 5 | { 6 | 'WATCHLIST_DEFINITIONS': { 7 | 'all': { 8 | 'filepath': '.', 9 | }, 10 | }, 11 | 'WATCHLISTS': { 12 | 'all': ['adlr@chromium.org', 'petkov@chromium.org'] 13 | }, 14 | } 15 | -------------------------------------------------------------------------------- /systemd/update-engine.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Update Engine 3 | ConditionVirtualization=!container 4 | ConditionPathExists=!/usr/.noupdate 5 | 6 | [Service] 7 | Type=dbus 8 | BusName=com.coreos.update1 9 | ExecStart=/usr/sbin/update_engine -foreground -logtostderr 10 | BlockIOWeight=100 11 | Restart=always 12 | RestartSec=30 13 | 14 | [Install] 15 | WantedBy=multi-user.target 16 | -------------------------------------------------------------------------------- /coreos-setgoodroot: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) 2014 The CoreOS Authors. 3 | # Use of this source code is governed by a BSD-style license that can be 4 | # found in the LICENSE file. 5 | 6 | set -e 7 | 8 | # Look up the currently mounted usr partition. 9 | dev=$(rootdev -s /usr) 10 | 11 | # Repair partition table if required (e.g. the backup GPT may be out of sync) 12 | cgpt repair "${dev}" 13 | 14 | # Mark /usr as successfully booted (success=1, tries=0) and highest priority. 15 | cgpt add -S1 -T0 "${dev}" 16 | cgpt prioritize "${dev}" 17 | -------------------------------------------------------------------------------- /src/update_engine/http_fetcher_unittest.h: -------------------------------------------------------------------------------- 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 3 | // found in the LICENSE file. 4 | 5 | // Definition of unit testing constants, to be shared by different testing 6 | // related modules. 7 | 8 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_HTTP_FETCHER_TEST_H__ 9 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_HTTP_FETCHER_TEST_H__ 10 | 11 | namespace { 12 | 13 | const int kServerPort = 8088; 14 | 15 | } // namespace 16 | 17 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_HTTP_FETCHER_TEST_H__ 18 | -------------------------------------------------------------------------------- /src/update_engine/update_attempter_mock.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 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 | 5 | #include "update_engine/update_attempter_mock.h" 6 | 7 | #include "update_engine/mock_system_state.h" 8 | 9 | namespace chromeos_update_engine { 10 | 11 | UpdateAttempterMock::UpdateAttempterMock(MockSystemState* mock_system_state, 12 | MockDbusGlib* dbus) 13 | : UpdateAttempter(mock_system_state, dbus) {} 14 | 15 | } // namespace chromeos_update_engine 16 | -------------------------------------------------------------------------------- /src/files/file_enumerator.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 The Chromium 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 | 5 | #include "files/file_enumerator.h" 6 | 7 | namespace files { 8 | 9 | FileEnumerator::FileInfo::~FileInfo() { 10 | } 11 | 12 | bool FileEnumerator::ShouldSkip(const FilePath& path) { 13 | FilePath::StringType basename = path.BaseName().value(); 14 | return basename == FILE_PATH_LITERAL(".") || 15 | (basename == FILE_PATH_LITERAL("..") && 16 | !(INCLUDE_DOT_DOT & file_type_)); 17 | } 18 | 19 | } // namespace files 20 | -------------------------------------------------------------------------------- /src/files/file_path_constants.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Chromium 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 | 5 | #include "files/file_path.h" 6 | 7 | #include "macros.h" 8 | 9 | namespace files { 10 | 11 | const FilePath::CharType FilePath::kSeparators[] = FILE_PATH_LITERAL("/"); 12 | 13 | const size_t FilePath::kSeparatorsLength = arraysize(kSeparators); 14 | 15 | const FilePath::CharType FilePath::kCurrentDirectory[] = FILE_PATH_LITERAL("."); 16 | const FilePath::CharType FilePath::kParentDirectory[] = FILE_PATH_LITERAL(".."); 17 | 18 | } // namespace files 19 | -------------------------------------------------------------------------------- /run_unittests_as_user: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if ! [[ -f unittest_key.pub.pem || -f unittest_key2.pub.pem ]]; then 4 | echo "ERROR: tests much run in the build output directory" >&2 5 | exit 99 6 | fi 7 | 8 | # If running in an out-of-tree build grab the private test keys 9 | if ! [[ -f unittest_key.pem && -f unittest_key2.pem ]]; then 10 | srcdir="$(dirname "$0")" 11 | cp "${srcdir}/unittest_key.pem" "${srcdir}/unittest_key2.pem" ./ 12 | if [[ $? -ne 0 ]]; then 13 | echo "ERROR: failed to copy private test keys to build directory" >&2 14 | exit 99 15 | fi 16 | fi 17 | 18 | ./update_engine_unittests --gtest_filter='-*.RunAsRoot*' 19 | -------------------------------------------------------------------------------- /src/update_engine/bzip.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 The Chromium 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 | 5 | #include 6 | #include 7 | 8 | namespace chromeos_update_engine { 9 | 10 | // Bzip2 compresses or decompresses str/in to out. 11 | bool BzipDecompress(const std::vector& in, std::vector* out); 12 | bool BzipCompress(const std::vector& in, std::vector* out); 13 | bool BzipCompressString(const std::string& str, std::vector* out); 14 | bool BzipDecompressString(const std::string& str, std::vector* out); 15 | 16 | } // namespace chromeos_update_engine 17 | -------------------------------------------------------------------------------- /src/update_engine/dbus_constants.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 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 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_DBUS_CONSTANTS_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_DBUS_CONSTANTS_H__ 7 | 8 | namespace chromeos_update_engine { 9 | 10 | static const char* const kUpdateEngineServiceName = "com.coreos.update1"; 11 | static const char* const kUpdateEngineServicePath = 12 | "/com/coreos/update1"; 13 | static const char* const kUpdateEngineServiceInterface = 14 | "com.coreos.update1.Manager"; 15 | } // namespace chromeos_update_engine 16 | 17 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_DBUS_CONSTANTS_H__ 18 | -------------------------------------------------------------------------------- /src/update_engine/action_processor_mock.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 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 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_ACTION_PROCESSOR_MOCK_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_ACTION_PROCESSOR_MOCK_H__ 7 | 8 | #include 9 | 10 | #include "update_engine/action.h" 11 | 12 | namespace chromeos_update_engine { 13 | 14 | class ActionProcessorMock : public ActionProcessor { 15 | public: 16 | MOCK_METHOD0(StartProcessing, void()); 17 | MOCK_METHOD1(EnqueueAction, void(AbstractAction* action)); 18 | }; 19 | 20 | } // namespace chromeos_update_engine 21 | 22 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_ACTION_PROCESSOR_MOCK_H__ 23 | -------------------------------------------------------------------------------- /src/update_engine/file_writer_mock.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 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 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_FILE_WRITER_MOCK_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_FILE_WRITER_MOCK_H__ 7 | 8 | #include "gmock/gmock.h" 9 | #include "update_engine/file_writer.h" 10 | 11 | namespace chromeos_update_engine { 12 | 13 | class FileWriterMock : public FileWriter { 14 | public: 15 | MOCK_METHOD3(Open, int(const char* path, int flags, mode_t mode)); 16 | MOCK_METHOD2(Write, ssize_t(const void* bytes, size_t count)); 17 | MOCK_METHOD0(Close, int()); 18 | }; 19 | 20 | } // namespace chromeos_update_engine 21 | 22 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_FILE_WRITER_MOCK_H__ 23 | -------------------------------------------------------------------------------- /src/update_engine/http_fetcher.cc: -------------------------------------------------------------------------------- 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 3 | // found in the LICENSE file. 4 | 5 | #include "update_engine/http_fetcher.h" 6 | 7 | namespace chromeos_update_engine { 8 | 9 | void HttpFetcher::SetPostData(const void* data, size_t size, 10 | HttpContentType type) { 11 | post_data_set_ = true; 12 | post_data_.clear(); 13 | const char *char_data = reinterpret_cast(data); 14 | post_data_.insert(post_data_.end(), char_data, char_data + size); 15 | post_content_type_ = type; 16 | } 17 | 18 | void HttpFetcher::SetPostData(const void* data, size_t size) { 19 | SetPostData(data, size, kHttpContentTypeUnspecified); 20 | } 21 | 22 | } // namespace chromeos_update_engine 23 | -------------------------------------------------------------------------------- /run_unittests_as_root: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | sudo= 4 | if [[ "$(id -u)" -ne 0 ]]; then 5 | if sudo -n true; then 6 | sudo=sudo 7 | else 8 | echo "ERROR: tests require root access" >&2 9 | exit 77 10 | fi 11 | fi 12 | 13 | if ! [[ -f unittest_key.pub.pem || -f unittest_key2.pub.pem ]]; then 14 | echo "ERROR: tests much run in the build output directory" >&2 15 | exit 99 16 | fi 17 | 18 | # If running in an out-of-tree build grab the private test keys 19 | if ! [[ -f unittest_key.pem && -f unittest_key2.pem ]]; then 20 | srcdir="$(dirname "$0")" 21 | cp "${srcdir}/unittest_key.pem" "${srcdir}/unittest_key2.pem" ./ 22 | if [[ $? -ne 0 ]]; then 23 | echo "ERROR: failed to copy private test keys to build directory" >&2 24 | exit 99 25 | fi 26 | fi 27 | 28 | $sudo ./update_engine_unittests --gtest_filter='*.RunAsRoot*' 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # 2 | # NOTE! Please use 'git ls-files -i --exclude-standard' 3 | # command after changing this file, to see if there are 4 | # any tracked files which get ignored after the change. 5 | # 6 | 7 | # Standard excludes 8 | *~ 9 | *.a 10 | *.o 11 | 12 | # Build/test generated files 13 | *.gcda 14 | *.gcno 15 | .deps/ 16 | .dirstamp 17 | /*.pub.pem 18 | /Makefile 19 | /Makefile.in 20 | /aclocal.m4 21 | /app.info 22 | /autom4te.cache/ 23 | /build-aux/ 24 | /config.log 25 | /config.status 26 | /configure 27 | /delta_generator 28 | /html/ 29 | /src/update_engine/marshal.glibmarshal.c 30 | /src/update_engine/marshal.glibmarshal.h 31 | /src/update_engine/update_engine.dbusclient.h 32 | /src/update_engine/update_engine.dbusserver.h 33 | /src/update_engine/update_metadata.pb.cc 34 | /src/update_engine/update_metadata.pb.h 35 | /test_http_server 36 | /update_engine 37 | /update_engine_client 38 | /update_engine_unittests 39 | -------------------------------------------------------------------------------- /src/update_engine/action_mock.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 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 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_ACTION_MOCK_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_ACTION_MOCK_H__ 7 | 8 | #include 9 | 10 | #include "update_engine/action.h" 11 | 12 | namespace chromeos_update_engine { 13 | 14 | class ActionMock; 15 | 16 | template<> 17 | class ActionTraits { 18 | public: 19 | typedef NoneType OutputObjectType; 20 | typedef NoneType InputObjectType; 21 | }; 22 | 23 | class ActionMock : public Action { 24 | public: 25 | MOCK_METHOD0(PerformAction, void()); 26 | MOCK_CONST_METHOD0(Type, std::string()); 27 | }; 28 | 29 | } // namespace chromeos_update_engine 30 | 31 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_ACTION_MOCK_H__ 32 | -------------------------------------------------------------------------------- /src/update_engine/update_attempter_mock.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 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 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_UPDATE_ATTEMPTER_MOCK_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_UPDATE_ATTEMPTER_MOCK_H__ 7 | 8 | #include 9 | 10 | #include "update_engine/mock_dbus_interface.h" 11 | #include "update_engine/update_attempter.h" 12 | 13 | namespace chromeos_update_engine { 14 | 15 | class MockSystemState; 16 | 17 | class UpdateAttempterMock : public UpdateAttempter { 18 | public: 19 | explicit UpdateAttempterMock(MockSystemState* mock_system_state, 20 | MockDbusGlib* dbus); 21 | 22 | MOCK_METHOD1(Update, void(bool interactive)); 23 | }; 24 | 25 | } // namespace chromeos_update_engine 26 | 27 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_UPDATE_ATTEMPTER_MOCK_H__ 28 | -------------------------------------------------------------------------------- /src/update_engine/certificate_checker_mock.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011 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 | 5 | #ifndef CHROMEOS_UPDATE_ENGINE_CERTIFICATE_CHECKER_MOCK_H_ 6 | #define CHROMEOS_UPDATE_ENGINE_CERTIFICATE_CHECKER_MOCK_H_ 7 | 8 | #include 9 | #include 10 | 11 | #include "update_engine/certificate_checker.h" 12 | 13 | namespace chromeos_update_engine { 14 | 15 | class OpenSSLWrapperMock : public OpenSSLWrapper { 16 | public: 17 | MOCK_CONST_METHOD4(GetCertificateDigest, 18 | bool(X509_STORE_CTX* x509_ctx, 19 | int* out_depth, 20 | unsigned int* out_digest_length, 21 | unsigned char* out_digest)); 22 | }; 23 | 24 | } // namespace chromeos_update_engine 25 | 26 | #endif // CHROMEOS_UPDATE_ENGINE_CERTIFICATE_CHECKER_MOCK_H_ 27 | -------------------------------------------------------------------------------- /src/update_engine/mock_system_state.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 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 | 5 | #include "update_engine/mock_system_state.h" 6 | #include "update_engine/update_attempter_mock.h" 7 | 8 | namespace chromeos_update_engine { 9 | 10 | // Mock the SystemStateInterface so that we could lie that 11 | // OOBE is completed even when there's no such marker file, etc. 12 | MockSystemState::MockSystemState() 13 | : default_request_params_(this), 14 | prefs_(&mock_prefs_) { 15 | request_params_ = &default_request_params_; 16 | mock_payload_state_.Initialize(&mock_prefs_); 17 | mock_update_attempter_.reset( 18 | new testing::NiceMock(this, &dbus_)); 19 | } 20 | 21 | UpdateAttempter* MockSystemState::update_attempter() { 22 | return mock_update_attempter_.get(); 23 | } 24 | 25 | } // namespeace chromeos_update_engine 26 | 27 | -------------------------------------------------------------------------------- /src/update_engine/system_state.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 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 | 5 | #include "files/file_path.h" 6 | #include "update_engine/real_system_state.h" 7 | 8 | namespace chromeos_update_engine { 9 | 10 | static const char kPrefsDirectory[] = "/var/lib/update_engine/prefs"; 11 | 12 | RealSystemState::RealSystemState() 13 | : request_params_(this) {} 14 | 15 | bool RealSystemState::Initialize() { 16 | if (!prefs_.Init(files::FilePath(kPrefsDirectory))) { 17 | LOG(ERROR) << "Failed to initialize preferences."; 18 | return false; 19 | } 20 | 21 | if (!payload_state_.Initialize(&prefs_)) 22 | return false; 23 | 24 | // Create the update attempter. 25 | update_attempter_.reset(new UpdateAttempter(this, &dbus_)); 26 | 27 | // All is well. Initialization successful. 28 | return true; 29 | } 30 | 31 | } // namespace chromeos_update_engine 32 | -------------------------------------------------------------------------------- /src/strings/string_printf.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Chromium 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 | 5 | #include "strings/string_printf.h" 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | namespace strings { 13 | 14 | std::string StringPrintf(const char* format, ...) { 15 | va_list ap; 16 | va_start(ap, format); 17 | std::string result; 18 | StringAppendV(&result, format, ap); 19 | va_end(ap); 20 | return result; 21 | } 22 | 23 | std::string StringPrintV(const char* format, va_list ap) { 24 | std::string result; 25 | StringAppendV(&result, format, ap); 26 | return result; 27 | } 28 | 29 | void StringAppendV(std::string* dst, const char* format, va_list ap) { 30 | char *buf; 31 | int len = vasprintf(&buf, format, ap); 32 | PCHECK(len >= 0) << "vsnprintf failured"; 33 | dst->append(buf, len); 34 | free(buf); 35 | return; 36 | } 37 | 38 | } // namespace strings 39 | -------------------------------------------------------------------------------- /src/update_engine/simple_key_value_store.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 The Chromium 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 | 5 | // These functions can parse a blob of data that's formatted as a simple 6 | // key value store. Each key/value pair is stored on its own line and 7 | // separated by the first '=' on the line. 8 | 9 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_SIMPLE_KEY_VALUE_STORE_H__ 10 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_SIMPLE_KEY_VALUE_STORE_H__ 11 | 12 | #include 13 | #include 14 | 15 | namespace chromeos_update_engine { 16 | namespace simple_key_value_store { 17 | 18 | // Parses a string. 19 | std::map ParseString(const std::string& str); 20 | 21 | std::string AssembleString(const std::map& data); 22 | 23 | } // namespace simple_key_value_store 24 | } // namespace chromeos_update_engine 25 | 26 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_SIMPLE_KEY_VALUE_STORE_H__ 27 | -------------------------------------------------------------------------------- /src/update_engine/topological_sort.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 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 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_TOPOLOGICAL_SORT_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_TOPOLOGICAL_SORT_H__ 7 | 8 | 9 | #include 10 | #include "update_engine/graph_types.h" 11 | 12 | namespace chromeos_update_engine { 13 | 14 | // Performs a topological sort on the directed graph 'graph' and stores 15 | // the nodes, in order visited, in 'out'. 16 | // For example, this graph: 17 | // A ---> C ----. 18 | // \ v 19 | // `--> B --> D 20 | // Might result in this in 'out': 21 | // out[0] = D 22 | // out[1] = B 23 | // out[2] = C 24 | // out[3] = A 25 | // Note: results are undefined if there is a cycle in the graph. 26 | void TopologicalSort(const Graph& graph, std::vector* out); 27 | 28 | } // namespace chromeos_update_engine 29 | 30 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_TOPOLOGICAL_SORT_H__ 31 | -------------------------------------------------------------------------------- /src/strings/string_printf.h: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Chromium 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 | 5 | #ifndef STRINGS_STRING_PRINTF_H_ 6 | #define STRINGS_STRING_PRINTF_H_ 7 | 8 | #include // va_list 9 | 10 | #include 11 | 12 | namespace strings { 13 | 14 | // Return a C++ string given printf-like input. 15 | [[gnu::warn_unused_result]] 16 | [[gnu::format(printf, 1, 2)]] 17 | std::string StringPrintf(const char* format, ...); 18 | 19 | // Return a C++ string given vprintf-like input. 20 | [[gnu::warn_unused_result]] 21 | [[gnu::format(printf, 1, 0)]] 22 | std::string StringPrintV(const char* format, va_list ap); 23 | 24 | // Lower-level routine that takes a va_list and appends to a specified 25 | // string. All other routines are just convenience wrappers around it. 26 | [[gnu::format(printf, 2, 0)]] 27 | void StringAppendV(std::string* dst, const char* format, va_list ap); 28 | 29 | } // namespace strings 30 | 31 | #endif // STRINGS_STRING_PRINTF_H_ 32 | -------------------------------------------------------------------------------- /src/files/scoped_file.h: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Chromium 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 | 5 | #ifndef FILES_SCOPED_FILE_H_ 6 | #define FILES_SCOPED_FILE_H_ 7 | 8 | #include 9 | 10 | #include 11 | 12 | #include "macros.h" 13 | 14 | namespace files { 15 | 16 | namespace internal { 17 | 18 | // Functor for |ScopedFILE| (below). 19 | struct ScopedFILECloser { 20 | void operator()(FILE* x) const; 21 | }; 22 | 23 | } // namespace internal 24 | 25 | // Automatically closes |FILE*|s. 26 | typedef std::unique_ptr ScopedFILE; 27 | 28 | // Automatically closes a file descriptor. 29 | class ScopedFD { 30 | public: 31 | explicit ScopedFD(int fd) : fd_(fd) {} 32 | ~ScopedFD(); 33 | 34 | int get() const { return fd_; } 35 | bool is_valid() const { return fd_ >= 0; } 36 | 37 | private: 38 | int fd_; 39 | DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedFD); 40 | }; 41 | 42 | } // namespace files 43 | 44 | #endif // FILES_SCOPED_FILE_H_ 45 | -------------------------------------------------------------------------------- /src/update_engine/prefs_mock.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 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 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_PREFS_MOCK_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_PREFS_MOCK_H__ 7 | 8 | #include "gmock/gmock.h" 9 | #include "update_engine/prefs_interface.h" 10 | 11 | namespace chromeos_update_engine { 12 | 13 | class PrefsMock : public PrefsInterface { 14 | public: 15 | MOCK_METHOD2(GetString, bool(const std::string& key, std::string* value)); 16 | MOCK_METHOD2(SetString, bool(const std::string& key, 17 | const std::string& value)); 18 | MOCK_METHOD2(GetInt64, bool(const std::string& key, int64_t* value)); 19 | MOCK_METHOD2(SetInt64, bool(const std::string& key, const int64_t value)); 20 | 21 | MOCK_METHOD1(Exists, bool(const std::string& key)); 22 | MOCK_METHOD1(Delete, bool(const std::string& key)); 23 | }; 24 | 25 | } // namespace chromeos_update_engine 26 | 27 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_PREFS_MOCK_H__ 28 | -------------------------------------------------------------------------------- /src/files/scoped_file.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Chromium 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 | 5 | #include "files/scoped_file.h" 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include "files/eintr_wrapper.h" 12 | 13 | namespace files { 14 | 15 | namespace internal { 16 | 17 | // The eintr wrappers check for -1 while the stdio API defines EOF as the 18 | // return value for errors. It *should* be -1 but lets just make sure. 19 | static_assert(EOF == -1, "fclose's error value is not -1"); 20 | 21 | void ScopedFILECloser::operator()(FILE* x) const { 22 | if (x == nullptr) 23 | return; 24 | 25 | int fd = fileno(x); 26 | if (IGNORE_EINTR(fclose(x)) == EOF) 27 | PLOG(ERROR) << "Error while closing file descriptor " << fd; 28 | } 29 | 30 | } // namespace internal 31 | 32 | ScopedFD::~ScopedFD() { 33 | if (fd_ < 0) 34 | return; 35 | 36 | if (IGNORE_EINTR(close(fd_)) == -1) 37 | PLOG(ERROR) << "Error while closing file descriptor " << fd_; 38 | } 39 | 40 | } // namespace files 41 | -------------------------------------------------------------------------------- /src/update_engine/terminator.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 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 | 5 | #include "update_engine/terminator.h" 6 | 7 | #include 8 | 9 | namespace chromeos_update_engine { 10 | 11 | volatile sig_atomic_t Terminator::exit_status_ = 1; // default exit status 12 | volatile sig_atomic_t Terminator::exit_blocked_ = 0; 13 | volatile sig_atomic_t Terminator::exit_requested_ = 0; 14 | 15 | void Terminator::Init() { 16 | exit_blocked_ = 0; 17 | exit_requested_ = 0; 18 | signal(SIGTERM, HandleSignal); 19 | } 20 | 21 | void Terminator::Init(int exit_status) { 22 | exit_status_ = exit_status; 23 | Init(); 24 | } 25 | 26 | void Terminator::Exit() { 27 | exit(exit_status_); 28 | } 29 | 30 | void Terminator::HandleSignal(int signum) { 31 | if (exit_blocked_ == 0) { 32 | Exit(); 33 | } 34 | exit_requested_ = 1; 35 | } 36 | 37 | ScopedTerminatorExitUnblocker::~ScopedTerminatorExitUnblocker() { 38 | Terminator::set_exit_blocked(false); 39 | if (Terminator::exit_requested()) { 40 | Terminator::Exit(); 41 | } 42 | } 43 | 44 | } // namespace chromeos_update_engine 45 | -------------------------------------------------------------------------------- /src/update_engine/update_engine.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /com.coreos.update1.conf: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 12 | 13 | 15 | 16 | 19 | 22 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/update_engine/testrunner.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 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 | 5 | // based on pam_google_testrunner.cc 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "update_engine/subprocess.h" 12 | #include "update_engine/terminator.h" 13 | 14 | int main(int argc, char **argv) { 15 | // Disable glog's default behavior of logging to files. 16 | FLAGS_logtostderr = true; 17 | google::InitGoogleLogging(argv[0]); 18 | 19 | dbus_threads_init_default(); 20 | // TODO(garnold) temporarily cause the unittest binary to exit with status 21 | // code 2 upon catching a SIGTERM. This will help diagnose why the unittest 22 | // binary is perceived as failing by the buildbot. We should revert it to use 23 | // the default exit status of 1. Corresponding reverts are necessary in 24 | // terminator_unittest.cc. 25 | chromeos_update_engine::Terminator::Init(2); 26 | chromeos_update_engine::Subprocess::Init(); 27 | LOG(INFO) << "initializing gtest"; 28 | ::testing::InitGoogleTest(&argc, argv); 29 | LOG(INFO) << "running unit tests"; 30 | int test_result = RUN_ALL_TESTS(); 31 | LOG(INFO) << "unittest return value: " << test_result; 32 | return test_result; 33 | } 34 | -------------------------------------------------------------------------------- /src/update_engine/bzip_extent_writer.h: -------------------------------------------------------------------------------- 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 3 | // found in the LICENSE file. 4 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_BZIP_EXTENT_WRITER_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_BZIP_EXTENT_WRITER_H__ 7 | 8 | #include 9 | #include 10 | #include "update_engine/extent_writer.h" 11 | #include "update_engine/utils.h" 12 | 13 | // BzipExtentWriter is a concrete ExtentWriter subclass that bzip-decompresses 14 | // what it's given in Write. It passes the decompressed data to an underlying 15 | // ExtentWriter. 16 | 17 | namespace chromeos_update_engine { 18 | 19 | class BzipExtentWriter : public ExtentWriter { 20 | public: 21 | BzipExtentWriter(ExtentWriter* next) : next_(next) { 22 | memset(&stream_, 0, sizeof(stream_)); 23 | } 24 | ~BzipExtentWriter() {} 25 | 26 | bool Init(int fd, const std::vector& extents, uint32_t block_size); 27 | bool Write(const void* bytes, size_t count); 28 | bool EndImpl(); 29 | 30 | private: 31 | ExtentWriter* const next_; // The underlying ExtentWriter. 32 | bz_stream stream_; // the libbz2 stream 33 | std::vector input_buffer_; 34 | }; 35 | 36 | } // namespace chromeos_update_engine 37 | 38 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_BZIP_EXTENT_WRITER_H__ 39 | -------------------------------------------------------------------------------- /src/strings/string_split.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The Chromium 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 | 5 | #ifndef STRINGS_STRING_SPLIT_H_ 6 | #define STRINGS_STRING_SPLIT_H_ 7 | 8 | #include 9 | #include 10 | 11 | namespace strings { 12 | 13 | // Splits |str| into a vector of strings delimited by |delim|. If several 14 | // instances of |delim| are contiguous, or if |str| begins with or ends 15 | // with |delim|, then an empty string is inserted. 16 | // 17 | // Every substring is trimmed of any leading or trailing white space. 18 | std::vector SplitAndTrim(const std::string& str, char delim); 19 | std::vector SplitAndTrim(const std::string& str, 20 | const std::string& delim); 21 | 22 | // The same as SplitAndTrim, but don't trim white space. 23 | std::vector SplitDontTrim(const std::string& str, char delim); 24 | 25 | // Splits the string along ASCII whitespace. 26 | // Each contiguous block of non-whitespace characters is added to result. 27 | std::vector SplitWords(const std::string& str); 28 | 29 | // Trims any ASCII whitespace from either end of the input string. 30 | std::string TrimWhitespace(const std::string& input); 31 | 32 | } // namespace strings 33 | 34 | #endif // STRINGS_STRING_SPLIT_H_ 35 | -------------------------------------------------------------------------------- /src/update_engine/topological_sort.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 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 | 5 | #include "update_engine/topological_sort.h" 6 | #include 7 | #include 8 | #include 9 | 10 | using std::set; 11 | using std::vector; 12 | 13 | namespace chromeos_update_engine { 14 | 15 | namespace { 16 | void TopologicalSortVisit(const Graph& graph, 17 | set* visited_nodes, 18 | vector* nodes, 19 | Vertex::Index node) { 20 | if (visited_nodes->find(node) != visited_nodes->end()) 21 | return; 22 | 23 | visited_nodes->insert(node); 24 | // Visit all children. 25 | for (Vertex::EdgeMap::const_iterator it = graph[node].out_edges.begin(); 26 | it != graph[node].out_edges.end(); ++it) { 27 | TopologicalSortVisit(graph, visited_nodes, nodes, it->first); 28 | } 29 | // Visit this node. 30 | nodes->push_back(node); 31 | } 32 | } // namespace {} 33 | 34 | void TopologicalSort(const Graph& graph, vector* out) { 35 | set visited_nodes; 36 | 37 | for (Vertex::Index i = 0; i < graph.size(); i++) { 38 | TopologicalSortVisit(graph, &visited_nodes, out, i); 39 | } 40 | } 41 | 42 | } // namespace chromeos_update_engine 43 | -------------------------------------------------------------------------------- /src/update_engine/file_writer.cc: -------------------------------------------------------------------------------- 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 3 | // found in the LICENSE file. 4 | 5 | #include "update_engine/file_writer.h" 6 | #include 7 | 8 | namespace chromeos_update_engine { 9 | 10 | int DirectFileWriter::Open() { 11 | CHECK_EQ(fd_, -1); 12 | fd_ = open(path_.c_str(), flags_, mode_); 13 | if (fd_ < 0) { 14 | PLOG(ERROR) << "Unable to open file " << path_; 15 | return -errno; 16 | } 17 | return 0; 18 | } 19 | 20 | bool DirectFileWriter::Write(const void* bytes, size_t count) { 21 | CHECK_GE(fd_, 0); 22 | const char* char_bytes = reinterpret_cast(bytes); 23 | 24 | size_t bytes_written = 0; 25 | while (bytes_written < count) { 26 | ssize_t rc = write(fd_, char_bytes + bytes_written, 27 | count - bytes_written); 28 | if (rc < 0) 29 | return false; 30 | bytes_written += rc; 31 | } 32 | CHECK_EQ(bytes_written, count); 33 | return bytes_written == count; 34 | } 35 | 36 | int DirectFileWriter::Close() { 37 | CHECK_GE(fd_, 0); 38 | int rc = close(fd_); 39 | 40 | // This can be any negative number that's not -1. This way, this FileWriter 41 | // won't be used again for another file. 42 | fd_ = -2; 43 | 44 | if (rc < 0) 45 | return -errno; 46 | return rc; 47 | } 48 | 49 | } // namespace chromeos_update_engine 50 | -------------------------------------------------------------------------------- /src/update_engine/tarjan.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 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 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_TARJAN_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_TARJAN_H__ 7 | 8 | // This is an implemenation of Tarjan's algorithm which finds all 9 | // Strongly Connected Components in a graph. 10 | 11 | // Note: a true Tarjan algorithm would find all strongly connected components 12 | // in the graph. This implementation will only find the strongly connected 13 | // component containing the vertex passed in. 14 | 15 | #include 16 | #include "update_engine/graph_types.h" 17 | 18 | namespace chromeos_update_engine { 19 | 20 | class TarjanAlgorithm { 21 | public: 22 | TarjanAlgorithm() : index_(0), required_vertex_(0) {} 23 | 24 | // 'out' is set to the result if there is one, otherwise it's untouched. 25 | void Execute(Vertex::Index vertex, 26 | Graph* graph, 27 | std::vector* out); 28 | private: 29 | void Tarjan(Vertex::Index vertex, Graph* graph); 30 | 31 | Vertex::Index index_; 32 | Vertex::Index required_vertex_; 33 | std::vector stack_; 34 | std::vector > components_; 35 | }; 36 | 37 | } // namespace chromeos_update_engine 38 | 39 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_TARJAN_H__ 40 | -------------------------------------------------------------------------------- /src/update_engine/mock_payload_state.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 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 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_MOCK_PAYLOAD_STATE_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_MOCK_PAYLOAD_STATE_H__ 7 | 8 | #include "gmock/gmock.h" 9 | #include "update_engine/omaha_request_action.h" 10 | #include "update_engine/payload_state_interface.h" 11 | 12 | namespace chromeos_update_engine { 13 | 14 | class MockPayloadState: public PayloadStateInterface { 15 | public: 16 | bool Initialize(PrefsInterface* prefs) { 17 | return true; 18 | } 19 | 20 | // Significant methods. 21 | MOCK_METHOD1(SetResponse, void(const OmahaResponse& response)); 22 | MOCK_METHOD0(DownloadComplete, void()); 23 | MOCK_METHOD1(DownloadProgress, void(size_t count)); 24 | MOCK_METHOD1(UpdateFailed, void(ActionExitCode error)); 25 | MOCK_METHOD0(ShouldBackoffDownload, bool()); 26 | 27 | // Getters. 28 | MOCK_METHOD0(GetResponseSignature, std::string()); 29 | MOCK_METHOD0(GetPayloadAttemptNumber, uint32_t()); 30 | MOCK_METHOD0(GetUrlIndex, uint32_t()); 31 | MOCK_METHOD0(GetUrlFailureCount, uint32_t()); 32 | MOCK_METHOD0(GetBackoffExpiryTime, std::chrono::system_clock::time_point()); 33 | }; 34 | 35 | } // namespace chromeos_update_engine 36 | 37 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_MOCK_PAYLOAD_STATE_H__ 38 | -------------------------------------------------------------------------------- /sample_omaha_v3_response.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/update_engine/simple_key_value_store.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 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 | 5 | #include "update_engine/simple_key_value_store.h" 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "strings/string_split.h" 12 | 13 | using std::map; 14 | using std::string; 15 | using std::vector; 16 | 17 | namespace chromeos_update_engine { 18 | namespace simple_key_value_store { 19 | 20 | // Parses a string. 21 | map ParseString(const string& str) { 22 | // Split along '\n', then along '=' 23 | std::map ret; 24 | vector lines = strings::SplitDontTrim(str, '\n'); 25 | for (vector::const_iterator it = lines.begin(); 26 | it != lines.end(); ++it) { 27 | string::size_type pos = it->find('='); 28 | if (pos == string::npos) 29 | continue; 30 | ret[it->substr(0, pos)] = it->substr(pos + 1); 31 | } 32 | return ret; 33 | } 34 | 35 | string AssembleString(const std::map& data) { 36 | string ret; 37 | for (std::map::const_iterator it = data.begin(); 38 | it != data.end(); ++it) { 39 | ret += it->first; 40 | ret += "="; 41 | ret += it->second; 42 | ret += "\n"; 43 | } 44 | return ret; 45 | } 46 | 47 | } // namespace simple_key_value_store 48 | } // namespace chromeos_update_engine 49 | -------------------------------------------------------------------------------- /src/update_engine/action_pipe_unittest.cc: -------------------------------------------------------------------------------- 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 3 | // found in the LICENSE file. 4 | 5 | #include 6 | #include 7 | #include "update_engine/action.h" 8 | #include "update_engine/action_pipe.h" 9 | 10 | using std::string; 11 | 12 | namespace chromeos_update_engine { 13 | 14 | using chromeos_update_engine::ActionPipe; 15 | 16 | class ActionPipeTestAction; 17 | 18 | template<> 19 | class ActionTraits { 20 | public: 21 | typedef string OutputObjectType; 22 | typedef string InputObjectType; 23 | }; 24 | 25 | // This is a simple Action class for testing. 26 | struct ActionPipeTestAction : public Action { 27 | typedef string InputObjectType; 28 | typedef string OutputObjectType; 29 | ActionPipe* in_pipe() { return in_pipe_.get(); } 30 | ActionPipe* out_pipe() { return out_pipe_.get(); } 31 | void PerformAction() {} 32 | string Type() const { return "ActionPipeTestAction"; } 33 | }; 34 | 35 | class ActionPipeTest : public ::testing::Test { }; 36 | 37 | // This test creates two simple Actions and sends a message via an ActionPipe 38 | // from one to the other. 39 | TEST(ActionPipeTest, SimpleTest) { 40 | ActionPipeTestAction a, b; 41 | BondActions(&a, &b); 42 | a.out_pipe()->set_contents("foo"); 43 | EXPECT_EQ("foo", b.in_pipe()->contents()); 44 | } 45 | 46 | } // namespace chromeos_update_engine 47 | -------------------------------------------------------------------------------- /src/update_engine/extent_mapper.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 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 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_EXTENT_MAPPER_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_EXTENT_MAPPER_H__ 7 | 8 | #include 9 | #include 10 | 11 | #include "update_engine/update_metadata.pb.h" 12 | 13 | namespace chromeos_update_engine { 14 | 15 | namespace extent_mapper { 16 | 17 | // Uses the FIBMAP ioctl to get all blocks used by a file and return them 18 | // as extents. Blocks are relative to the start of the filesystem. If 19 | // there is a sparse "hole" in the file, the blocks for that will be 20 | // represented by an extent whose start block is kSpareseHole. 21 | // The resulting extents are stored in 'out'. Keep in mind that while 22 | // the blocksize of a filesystem is often 4096 bytes, that is not always 23 | // the case, so one should consult GetFilesystemBlockSize(), too. 24 | // Returns true on success. 25 | bool ExtentsForFileFibmap(const std::string& path, std::vector* out); 26 | 27 | // Puts the blocksize of the filesystem, as used by the FIBMAP ioctl, into 28 | // out_blocksize by using the FIGETBSZ ioctl. Returns true on success. 29 | bool GetFilesystemBlockSize(const std::string& path, uint32_t* out_blocksize); 30 | 31 | } // namespace extent_mapper 32 | 33 | } // namespace chromeos_update_engine 34 | 35 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_EXTENT_MAPPER_H__ 36 | -------------------------------------------------------------------------------- /DCO: -------------------------------------------------------------------------------- 1 | Developer Certificate of Origin 2 | Version 1.1 3 | 4 | Copyright (C) 2004, 2006 The Linux Foundation and its contributors. 5 | 660 York Street, Suite 102, 6 | San Francisco, CA 94110 USA 7 | 8 | Everyone is permitted to copy and distribute verbatim copies of this 9 | license document, but changing it is not allowed. 10 | 11 | 12 | Developer's Certificate of Origin 1.1 13 | 14 | By making a contribution to this project, I certify that: 15 | 16 | (a) The contribution was created in whole or in part by me and I 17 | have the right to submit it under the open source license 18 | indicated in the file; or 19 | 20 | (b) The contribution is based upon previous work that, to the best 21 | of my knowledge, is covered under an appropriate open source 22 | license and I have the right under that license to submit that 23 | work with modifications, whether created in whole or in part 24 | by me, under the same open source license (unless I am 25 | permitted to submit under a different license), as indicated 26 | in the file; or 27 | 28 | (c) The contribution was provided directly to me by some other 29 | person who certified (a), (b) or (c) and I have not modified 30 | it. 31 | 32 | (d) I understand and agree that this project and the contribution 33 | are public and that a record of the contribution (including all 34 | personal information I submit with it, including my sign-off) is 35 | maintained indefinitely and may be redistributed consistent with 36 | this project or the open source license(s) involved. 37 | -------------------------------------------------------------------------------- /src/update_engine/file_writer_unittest.cc: -------------------------------------------------------------------------------- 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 3 | // found in the LICENSE file. 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "update_engine/file_writer.h" 12 | #include "update_engine/test_utils.h" 13 | #include "update_engine/utils.h" 14 | 15 | using std::string; 16 | using std::vector; 17 | 18 | namespace chromeos_update_engine { 19 | 20 | class FileWriterTest : public ::testing::Test { }; 21 | 22 | TEST(FileWriterTest, SimpleTest) { 23 | ScopedTempFile temp_file; 24 | DirectFileWriter file_writer(temp_file.GetPath()); 25 | EXPECT_EQ(0, file_writer.Open()); 26 | EXPECT_TRUE(file_writer.Write("test", 4)); 27 | vector actual_data; 28 | EXPECT_TRUE(utils::ReadFile(temp_file.GetPath(), &actual_data)); 29 | 30 | EXPECT_FALSE(memcmp("test", &actual_data[0], actual_data.size())); 31 | EXPECT_EQ(0, file_writer.Close()); 32 | } 33 | 34 | TEST(FileWriterTest, ErrorTest) { 35 | DirectFileWriter file_writer("/tmp/ENOENT/FileWriterTest"); 36 | EXPECT_EQ(-ENOENT, file_writer.Open()); 37 | } 38 | 39 | TEST(FileWriterTest, WriteErrorTest) { 40 | ScopedTempFile temp_file; 41 | DirectFileWriter file_writer(temp_file.GetPath(), O_CREAT | O_RDONLY, 0644); 42 | EXPECT_EQ(0, file_writer.Open()); 43 | EXPECT_FALSE(file_writer.Write("x", 1)); 44 | EXPECT_EQ(0, file_writer.Close()); 45 | } 46 | 47 | 48 | } // namespace chromeos_update_engine 49 | -------------------------------------------------------------------------------- /src/update_engine/ext2_metadata.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 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 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_EXT2_METADATA_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_EXT2_METADATA_H__ 7 | 8 | #include "update_engine/delta_diff_generator.h" 9 | #include "update_engine/graph_types.h" 10 | 11 | namespace chromeos_update_engine { 12 | 13 | class Ext2Metadata { 14 | public: 15 | // Reads metadata from old image and new image and determines 16 | // the smallest way to encode the metadata for the diff. 17 | // If there's no change in the metadata, it creates a MOVE 18 | // operation. If there is a change, the smallest of REPLACE, REPLACE_BZ, 19 | // or BSDIFF wins. It writes the diff to data_fd and updates data_file_size 20 | // accordingly. It also adds the required operation to the graph and adds the 21 | // metadata extents to blocks. 22 | // Returns true on success. 23 | static bool DeltaReadMetadata(Graph* graph, 24 | std::vector* blocks, 25 | const std::string& old_image, 26 | const std::string& new_image, 27 | int data_fd, 28 | off_t* data_file_size); 29 | 30 | private: 31 | // This should never be constructed. 32 | DISALLOW_IMPLICIT_CONSTRUCTORS(Ext2Metadata); 33 | }; 34 | 35 | }; // namespace chromeos_update_engine 36 | 37 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_EXT2_METADATA_H__ 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 2 | // 3 | // Redistribution and use in source and binary forms, with or without 4 | // modification, are permitted provided that the following conditions are 5 | // met: 6 | // 7 | // * Redistributions of source code must retain the above copyright 8 | // notice, this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above 10 | // copyright notice, this list of conditions and the following disclaimer 11 | // in the documentation and/or other materials provided with the 12 | // distribution. 13 | // * Neither the name of Google Inc. nor the names of its 14 | // contributors may be used to endorse or promote products derived from 15 | // this software without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /src/update_engine/kernel_verifier_action.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 The CoreOS 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 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_KERNEL_VERIFIER_ACTION_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_KERNEL_VERIFIER_ACTION_H__ 7 | 8 | #include 9 | 10 | #include "update_engine/action.h" 11 | #include "update_engine/install_plan.h" 12 | 13 | namespace chromeos_update_engine { 14 | 15 | class KernelVerifierAction; 16 | 17 | template<> 18 | class ActionTraits { 19 | public: 20 | // Takes the install plan as input 21 | typedef InstallPlan InputObjectType; 22 | // Passes the install plan as output 23 | typedef InstallPlan OutputObjectType; 24 | }; 25 | 26 | class KernelVerifierAction : public Action { 27 | public: 28 | KernelVerifierAction() {} 29 | 30 | typedef ActionTraits::InputObjectType 31 | InputObjectType; 32 | typedef ActionTraits::OutputObjectType 33 | OutputObjectType; 34 | void PerformAction(); 35 | void TerminateProcessing() {} 36 | 37 | // Debugging/logging 38 | static std::string StaticType() { return "KernelVerifierAction"; } 39 | std::string Type() const { return StaticType(); } 40 | 41 | private: 42 | // The install plan we're passed in via the input pipe. 43 | InstallPlan install_plan_; 44 | 45 | DISALLOW_COPY_AND_ASSIGN(KernelVerifierAction); 46 | }; 47 | 48 | } // namespace chromeos_update_engine 49 | 50 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_KERNEL_VERIFIER_ACTION_H__ 51 | -------------------------------------------------------------------------------- /src/files/scoped_file_unittest.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The Chromium 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 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #include "files/scoped_file.h" 13 | 14 | namespace files { 15 | 16 | TEST(ScopedFile, ScopedFDDoesClose) { 17 | int fds[2]; 18 | char c = 0; 19 | ASSERT_EQ(0, pipe(fds)); 20 | const int write_end = fds[1]; 21 | ScopedFD read_end_closer(fds[0]); 22 | { 23 | ScopedFD write_end_closer(fds[1]); 24 | } 25 | // This is the only thread. This file descriptor should no longer be valid. 26 | int ret = close(write_end); 27 | EXPECT_EQ(-1, ret); 28 | EXPECT_EQ(EBADF, errno); 29 | // Make sure read(2) won't block. 30 | ASSERT_EQ(0, fcntl(fds[0], F_SETFL, O_NONBLOCK)); 31 | // Reading the pipe should EOF. 32 | EXPECT_EQ(0, read(fds[0], &c, 1)); 33 | } 34 | 35 | TEST(ScopedFile, ScopedFILEDoesClose) { 36 | int fds[2]; 37 | char c = 0; 38 | ASSERT_EQ(0, pipe(fds)); 39 | const int write_end = fds[1]; 40 | ScopedFD read_end_closer(fds[0]); 41 | { 42 | FILE* f = fdopen(fds[1], "w"); 43 | ScopedFILE write_end_closer(f); 44 | } 45 | // This is the only thread. This file descriptor should no longer be valid. 46 | int ret = close(write_end); 47 | EXPECT_EQ(-1, ret); 48 | EXPECT_EQ(EBADF, errno); 49 | // Make sure read(2) won't block. 50 | ASSERT_EQ(0, fcntl(fds[0], F_SETFL, O_NONBLOCK)); 51 | // Reading the pipe should EOF. 52 | EXPECT_EQ(0, read(fds[0], &c, 1)); 53 | } 54 | 55 | } // namespace files 56 | -------------------------------------------------------------------------------- /unittest_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpAIBAAKCAQEAx6hqS+Hbc7jN82ek+OBkHJNvlWXktyS2XCuQtGtnHjEV7Ou5 3 | hHNF96s5wEn8RDtrdLocm0a+SqXXf7KycFRTZxLdDbqWAMUlPXOaPI+PZLWkB7/K 4 | V7Cdj6vPGbeq7elu+aT/budhzTvq2stYrrAlcr/21tOVDPiWtfCdykh7FCXi6FaY 5 | HoNy5A6EKQLfLBuJoU/QoCufldmwlFaFDKl+Koos6R1QYJfCNZfgocrW1PIh+8t1 6 | JIvw6Izo8+fTme7nev7Ol2YZiMWJpRYKx8MgxW2UgTXlRpmQN56pc9LUsnVA8FND 7 | BN57+gMJj+XmdDmbtMpOsyXfSNEgnuwMPcEcmwIDAQABAoIBABPkwgKhlH4pUcwI 8 | 7bUmlpMKVbnrFyjwbYMtjBOOCA5IEckzi56Y5cXRt8VjGdGqogBVcvg9ykQh1iER 9 | KxpqLI0+oev2RW/6NMW0uQ+DtmPwfVGQWJb4MBraoZ4MYOmnsrkJKbJhN6t9Zt86 10 | F7IANxsB6ZRqLJXIRywFt5MqOak+GAnQJ8C8eSQg70NhbEhSOrD8wrD6tfvgIqta 11 | XxhtlQWUAILIWetnWrJsalMqnreGn7vhc7+iihhMtXh1xNBMTA+gzpov/Cx21iH5 12 | DM9ppSA6HHDXrMhauryypIRrhjOUWRyDws/kIHgIW4TCbULOlxqsputQeTmdf0ti 13 | 7lpwqAECgYEA7nNKkct3Vs51Ugk4GUPC4NOyYRPNc9UQAfHViB9gSDRacCo9Ax9J 14 | 83hJGqDXlNGzELOnhzMn8jQMyF13eWzOsMozK6Fj3uW7DBvelg5bfgsZDUUO5WUF 15 | 6BYbOheVqf12rIHR9BKBmCfLEKyxbKmw5bnB0uNo7IuBPBNuhPbvkgECgYEA1lo5 16 | XHWJpQnVl+JzXLHpXBK2nfnFAOtvzlTW+7gteeU12X2HcFASrzp7C1ULVV+i1Kcz 17 | tDFIA5yiFjEqmSJ/TsO8aqAhL5BXJjylCepQK7XkEOGCR8eQjlt7E4DulAsQbfpt 18 | k30HVVlIOFqLCWKSW8M3dy/Plodq/Gyq26rntpsCgYAzsNyGdIQfVkxKh2MY3v6c 19 | /Gdb8g4EwThiI4m1o4+ct3SvggiN57eBRx8Z3ao+QaM+yKNVhLpxH+VxfgmLUhIQ 20 | cxTarXbX+BcvTc9X2i7tSPyaStEq21aHdFtcoYY5Po/+X3ojHevoDyBPMhCYTMTj 21 | V/xzegbh2HAglNnNizZuAQKBgQCyOxEpBP5vgS7d/MgJklFEYrb/wjgBnMI5oSek 22 | 5C7EBUdyUUM1qw7uLsUy1gL3eO7uvRxrvvJvNmU76KPP8vRCLNTVH9KYNv+P5qsg 23 | BHmm7rX1J11pi9Fx3TUIMZOu+0gs+ib0lOhtGjDH0tl680BZFohfDR0hv/XAcCbd 24 | Qk0q8wKBgQCGbURFFW/5RZUA77MmpY6jsEMw2gJmVtjO5IWZg9VPvLQQPgCr4Ho/ 25 | bS2LIsT6pS+hrLOoz5KI0YueRS0jQYI+WkRqNf5wYNjxPql9632FiDLHO+Xv8PBe 26 | kHrPHy0GGT1igXScY4eemw4ZC1OSdZfkVn6Ui/JvBHrydJ2LrutMWQ== 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /unittest_key2.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpAIBAAKCAQEAqdM7gnd43cWfQzyrt16QDHE+T0yxg18OZO+9sc8jWpjC1zFt 3 | oMFokESiu9TLUp+KUC274f+DxIgAfSCO6U5DJFRPXUzve1vaXYfqljUBxc+JYcGd 4 | d6PCUl4Ap9f02DhkrGnf/rkHOCEhFNpm53dovZ9A6Q5KBfcg1HeQ088opVceQGtU 5 | mL+bONq5tLvNFLUU0Ru0Am4ADJ8Xmw4rpvqvmXJaFmVuf/Gx7+TOnaJvZTeOO9AJ 6 | K6q6V8E7+ZZiMIc5F4EOs5AX/lZfNO3RVgG2O7Dhzza+nOzJ3ZJGK5R4WwZduhn9 7 | QRYogYPB0c62878qXpf2Bn3NpUPi8Cf/RLMMmQIDAQABAoIBACyLUWKpP7S770hN 8 | k6TnUtVQps1aCn2w4y+qipEnCdjrlL+pIV43HNwqhJzL9gDYBAl/1XYz9TYJjkdD 9 | 0Ph1JLtUufR5B5/NufsqeWeow6xFAX34sPr+oyvDqFxeEsTcFdv7cVt44OHiHrE/ 10 | kBpKgdiq+vWmX9gsuBnCuuQzxC+Juo6nupwZXcpa/ow9lC4QsgKqcjaUGrXXy2t9 11 | Er+9aSl8NdTjK76BXQsDgNkDyJZwNN14xrdS8eFsS4twskaOEYI4hEM0g62NOjgd 12 | Po8Ap/MnPpGSGcAd3d3Fq8KgT1lpyMKedLFU+k0H+/Y4RBl7grz1XXvSTzGi3Qy6 13 | 38F4eVkCgYEA4mo4iiXSfrov9QffsVM17O0t9hUsOJHnUsEScxWLDm4IzaObyTtv 14 | tWW33iQSeFu4Wsol0nzjqWo3BaqiRidRUd42yZ07LJvfUDxUX9xPaUPFRs25iwhZ 15 | 6tKAVqGk7/CFrN+R44sIwbsSvbExMAyW6gnj93EWUmMWWYp02hLbN0sCgYEAwAQI 16 | awVoc56OCtRpfYtlAPD/VOP1mbNzRmVl/UyZ4XYmz6f/hEz63Bk5PhYSZftlmK/r 17 | nj4qnl7HZ8jrJgZn2e97rPNpk7KDVU1+csCgLWZBTOXl/o9tOTyjh9LoRAjKtBB7 18 | x6CkWyiyd94xIq5VbnXhvL3a4d4o6OxMWdG5aSsCgYEAo44z1afIzP7WkdzkPIZt 19 | l/8linR1A1BymBccqsHPN9dIyLP9X3puEc2u6uuH5CXtoLgSZmENXF577L38h0zz 20 | s34gebf4/RqEUMOj97OAMfxgz+rgs4yO19DEINCYAzPufJjsHEFdTAVFXn5Xl+wg 21 | QGRwp1ir1Uv64yffjYC9ls0CgYEAjvIxpiKniPNvwUYypmDgt5uyKetvCpaaabzQ 22 | +YpOQJep+wuRYFfCpZotkDf0SHGoR8wnd23GYpIilvPvgyZfp9HuW2n2nhrWROnl 23 | Cd63IDUwxeOcni7+XA71mwb7HLMC3Jws2geQc8DPZAdIww3P0eT2QYGBcobmI8jO 24 | akuEYXMCgYAm79Kb/r+3Hew5oAS1Whw70DskVlOutSgNsDPfW9MtDcnETBcGep7A 25 | 1jCL5jjdUYRonimVMFjh1K+UFzV/DQHkgNzjxz9Inbh02y67vL2X836dS9esOcbx 26 | uZhf+8rL+GnSNqYDqCEuP7qCIloDhguJq9NKyTB4yc59qIkY2zPAzQ== 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /src/files/eintr_wrapper.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The Chromium 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 | 5 | // This provides a wrapper around system calls which may be interrupted by a 6 | // signal and return EINTR. See man 7 signal. 7 | // To prevent long-lasting loops (which would likely be a bug, such as a signal 8 | // that should be masked) to go unnoticed, there is a limit after which the 9 | // caller will nonetheless see an EINTR in Debug builds. 10 | // 11 | // Don't wrap close calls in HANDLE_EINTR. Use IGNORE_EINTR if the return 12 | // value of close is significant. See http://crbug.com/269623. 13 | 14 | #ifndef FILES_EINTR_WRAPPER_H_ 15 | #define FILES_EINTR_WRAPPER_H_ 16 | 17 | #include 18 | 19 | #if defined(NDEBUG) 20 | 21 | #define HANDLE_EINTR(x) ({ \ 22 | decltype(x) eintr_wrapper_result; \ 23 | do { \ 24 | eintr_wrapper_result = (x); \ 25 | } while (eintr_wrapper_result == -1 && errno == EINTR); \ 26 | eintr_wrapper_result; \ 27 | }) 28 | 29 | #else 30 | 31 | #define HANDLE_EINTR(x) ({ \ 32 | int eintr_wrapper_counter = 0; \ 33 | decltype(x) eintr_wrapper_result; \ 34 | do { \ 35 | eintr_wrapper_result = (x); \ 36 | } while (eintr_wrapper_result == -1 && errno == EINTR && \ 37 | eintr_wrapper_counter++ < 100); \ 38 | eintr_wrapper_result; \ 39 | }) 40 | 41 | #endif // NDEBUG 42 | 43 | #define IGNORE_EINTR(x) ({ \ 44 | decltype(x) eintr_wrapper_result; \ 45 | do { \ 46 | eintr_wrapper_result = (x); \ 47 | if (eintr_wrapper_result == -1 && errno == EINTR) { \ 48 | eintr_wrapper_result = 0; \ 49 | } \ 50 | } while (0); \ 51 | eintr_wrapper_result; \ 52 | }) 53 | 54 | #endif // FILES_EINTR_WRAPPER_H_ 55 | -------------------------------------------------------------------------------- /src/update_engine/terminator.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 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 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_TERMINATOR_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_TERMINATOR_H__ 7 | 8 | #include 9 | 10 | #include // for FRIEND_TEST 11 | 12 | namespace chromeos_update_engine { 13 | 14 | // A class allowing graceful delayed exit. 15 | class Terminator { 16 | public: 17 | // Initializes the terminator and sets up signal handlers. 18 | static void Init(); 19 | static void Init(int exit_status); 20 | 21 | // Terminates the current process. 22 | static void Exit(); 23 | 24 | // Set to true if the terminator should block termination requests in an 25 | // attempt to block exiting. 26 | static void set_exit_blocked(bool block) { exit_blocked_ = block ? 1 : 0; } 27 | static bool exit_blocked() { return exit_blocked_ != 0; } 28 | 29 | // Returns true if the system is trying to terminate the process, false 30 | // otherwise. Returns true only if exit was blocked when the termination 31 | // request arrived. 32 | static bool exit_requested() { return exit_requested_ != 0; } 33 | 34 | private: 35 | FRIEND_TEST(TerminatorTest, HandleSignalTest); 36 | FRIEND_TEST(TerminatorDeathTest, ScopedTerminatorExitUnblockerExitTest); 37 | 38 | // The signal handler. 39 | static void HandleSignal(int signum); 40 | 41 | static volatile sig_atomic_t exit_status_; 42 | static volatile sig_atomic_t exit_blocked_; 43 | static volatile sig_atomic_t exit_requested_; 44 | }; 45 | 46 | class ScopedTerminatorExitUnblocker { 47 | public: 48 | ~ScopedTerminatorExitUnblocker(); 49 | }; 50 | 51 | } // namespace chromeos_update_engine 52 | 53 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_TERMINATOR_H__ 54 | -------------------------------------------------------------------------------- /src/update_engine/kernel_copier_action.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 The CoreOS 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 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_KERNEL_COPIER_ACTION_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_KERNEL_COPIER_ACTION_H__ 7 | 8 | #include 9 | 10 | #include "update_engine/action.h" 11 | #include "update_engine/install_plan.h" 12 | 13 | namespace chromeos_update_engine { 14 | 15 | class KernelCopierAction; 16 | 17 | template<> 18 | class ActionTraits { 19 | public: 20 | // Takes the install plan as input 21 | typedef InstallPlan InputObjectType; 22 | // Passes the install plan as output 23 | typedef InstallPlan OutputObjectType; 24 | }; 25 | 26 | class KernelCopierAction : public Action { 27 | public: 28 | KernelCopierAction() {} 29 | 30 | typedef ActionTraits::InputObjectType 31 | InputObjectType; 32 | typedef ActionTraits::OutputObjectType 33 | OutputObjectType; 34 | void PerformAction(); 35 | void TerminateProcessing() {} 36 | 37 | // Used for testing, so we can copy from somewhere other than root 38 | void set_copy_source(const std::string& path) { copy_source_ = path; } 39 | 40 | // Debugging/logging 41 | static std::string StaticType() { return "KernelCopierAction"; } 42 | std::string Type() const { return StaticType(); } 43 | 44 | private: 45 | // The path to copy from. If empty (the default) it is auto-detected. 46 | std::string copy_source_; 47 | 48 | // The install plan we're passed in via the input pipe. 49 | InstallPlan install_plan_; 50 | 51 | DISALLOW_COPY_AND_ASSIGN(KernelCopierAction); 52 | }; 53 | 54 | } // namespace chromeos_update_engine 55 | 56 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_KERNEL_COPIER_ACTION_H__ 57 | -------------------------------------------------------------------------------- /src/update_engine/simple_key_value_store_unittest.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 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 | 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include "macros.h" 11 | #include "update_engine/simple_key_value_store.h" 12 | 13 | using std::map; 14 | using std::string; 15 | 16 | namespace chromeos_update_engine { 17 | 18 | class SimpleKeyValueStoreTest : public ::testing::Test {}; 19 | 20 | TEST(SimpleKeyValueStoreTest, SimpleTest) { 21 | string blob = "A=B\nC=\n=\nFOO=BAR=BAZ\nBAR=BAX\nMISSING=NEWLINE"; 22 | map parts = simple_key_value_store::ParseString(blob); 23 | string combined = simple_key_value_store::AssembleString(parts); 24 | map combined_parts = 25 | simple_key_value_store::ParseString(combined); 26 | map* maps[] = { &parts, &combined_parts }; 27 | for (size_t i = 0; i < arraysize(maps); i++) { 28 | map* test_map = maps[i]; 29 | EXPECT_EQ(6, test_map->size()) << "i = " << i; 30 | EXPECT_EQ("B", (*test_map)["A"]) << "i = " << i; 31 | EXPECT_EQ("", (*test_map)["C"]) << "i = " << i; 32 | EXPECT_EQ("", (*test_map)[""]) << "i = " << i; 33 | EXPECT_EQ("BAR=BAZ", (*test_map)["FOO"]) << "i = " << i; 34 | EXPECT_EQ("BAX", (*test_map)["BAR"]) << "i = " << i; 35 | EXPECT_EQ("NEWLINE", (*test_map)["MISSING"]) << "i = " << i; 36 | } 37 | } 38 | 39 | TEST(SimpleKeyValueStoreTest, EmptyTest) { 40 | map empty_map = simple_key_value_store::ParseString(""); 41 | EXPECT_TRUE(empty_map.empty()); 42 | string str = simple_key_value_store::AssembleString(empty_map); 43 | if (!str.empty()) { 44 | EXPECT_EQ("\n", str); // Optionally may end in newline 45 | } 46 | } 47 | 48 | } // namespace chromeos_update_engine 49 | -------------------------------------------------------------------------------- /src/update_engine/mock_file_writer.h: -------------------------------------------------------------------------------- 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 3 | // found in the LICENSE file. 4 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_MOCK_FILE_WRITER_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_MOCK_FILE_WRITER_H__ 7 | 8 | #include "macros.h" 9 | #include "update_engine/file_writer.h" 10 | 11 | // MockFileWriter is an implementation of FileWriter. It will succeed 12 | // calls to Open(), Close(), but not do any work. All calls to Write() 13 | // will append the passed data to an internal vector. 14 | 15 | namespace chromeos_update_engine { 16 | 17 | class MockFileWriter : public FileWriter { 18 | public: 19 | MockFileWriter() : was_opened_(false), was_closed_(false) {} 20 | 21 | virtual int Open(const char* path, int flags, mode_t mode) { 22 | CHECK(!was_opened_); 23 | CHECK(!was_closed_); 24 | was_opened_ = true; 25 | return 0; 26 | } 27 | 28 | virtual ssize_t Write(const void* bytes, size_t count) { 29 | CHECK(was_opened_); 30 | CHECK(!was_closed_); 31 | const char* char_bytes = reinterpret_cast(bytes); 32 | bytes_.insert(bytes_.end(), char_bytes, char_bytes + count); 33 | return count; 34 | } 35 | 36 | virtual int Close() { 37 | CHECK(was_opened_); 38 | CHECK(!was_closed_); 39 | was_closed_ = true; 40 | return 0; 41 | } 42 | 43 | const std::vector& bytes() { 44 | return bytes_; 45 | } 46 | private: 47 | // The internal store of all bytes that have been written 48 | std::vector bytes_; 49 | 50 | // These are just to ensure FileWriter methods are called properly. 51 | bool was_opened_; 52 | bool was_closed_; 53 | 54 | DISALLOW_COPY_AND_ASSIGN(MockFileWriter); 55 | }; 56 | 57 | } // namespace chromeos_update_engine 58 | 59 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_MOCK_FILE_WRITER_H__ 60 | -------------------------------------------------------------------------------- /src/update_engine/system_state.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 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 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_SYSTEM_STATE_H_ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_SYSTEM_STATE_H_ 7 | 8 | #include "update_engine/omaha_request_params.h" 9 | 10 | namespace chromeos_update_engine { 11 | 12 | // SystemState is the root class within the update engine. So we should avoid 13 | // any circular references in header file inclusion. Hence forward-declaring 14 | // the required classes. 15 | class PrefsInterface; 16 | class PayloadStateInterface; 17 | class GpioHandler; 18 | class UpdateAttempter; 19 | 20 | // An interface to global system context, including platform resources, 21 | // the current state of the system, high-level objects whose lifetime is same 22 | // as main, system interfaces, etc. 23 | // Carved out separately so it can be mocked for unit tests. 24 | // Currently it has only one method, but we should start migrating other 25 | // methods to use this as and when needed to unit test them. 26 | // TODO (jaysri): Consider renaming this to something like GlobalContext. 27 | class SystemState { 28 | public: 29 | // Destructs this object. 30 | virtual ~SystemState() {} 31 | 32 | // Gets the interface object for persisted store. 33 | virtual PrefsInterface* prefs() = 0; 34 | 35 | // Gets the interface for the payload state object. 36 | virtual PayloadStateInterface* payload_state() = 0; 37 | 38 | // Returns a pointer to the update attempter object. 39 | virtual UpdateAttempter* update_attempter() = 0; 40 | 41 | // Returns a pointer to the object that stores the parameters that are 42 | // common to all Omaha requests. 43 | virtual OmahaRequestParams* request_params() = 0; 44 | }; 45 | 46 | } // namespace chromeos_update_engine 47 | 48 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_SYSTEM_STATE_H_ 49 | -------------------------------------------------------------------------------- /src/update_engine/delta_metadata.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 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 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_DELTA_METADATA_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_DELTA_METADATA_H__ 7 | 8 | #include 9 | 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | namespace chromeos_update_engine { 16 | 17 | // Update payload header field values and sizes. 18 | // See update_metadata.proto for details. 19 | extern const char kDeltaMagic[]; 20 | const uint64_t kDeltaVersion = 1; 21 | 22 | const uint64_t kDeltaMagicSize = 4; 23 | const uint64_t kDeltaVersionSize = sizeof(uint64_t); 24 | const uint64_t kDeltaManifestSizeSize = sizeof(uint64_t); 25 | 26 | const uint64_t kDeltaVersionOffset = kDeltaMagicSize; 27 | const uint64_t kDeltaManifestSizeOffset = kDeltaVersionOffset + kDeltaVersionSize; 28 | const uint64_t kDeltaManifestOffset = kDeltaManifestSizeOffset + kDeltaManifestSizeSize; 29 | 30 | class DeltaMetadata { 31 | public: 32 | // Attempts to parse the update metadata starting from the beginning of 33 | // |payload| into |manifest|. On success, sets |metadata_size| to the total 34 | // metadata bytes (including the delta magic and metadata size fields), and 35 | // returns kActionCodeSuccess. Returns kActionCodeDownloadIncomplete if more 36 | // data is needed to parse the complete metadata. Returns 37 | // kActionCodeDownloadManifestParseError if the metadata can't be parsed. 38 | static ActionExitCode ParsePayload( 39 | const std::vector& payload, 40 | DeltaArchiveManifest* manifest, 41 | uint64_t* metadata_size); 42 | 43 | private: 44 | DISALLOW_IMPLICIT_CONSTRUCTORS(DeltaMetadata); 45 | }; 46 | 47 | }; // namespace chromeos_update_engine 48 | 49 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_DELTA_METADATA_H__ 50 | -------------------------------------------------------------------------------- /src/strings/string_printf_unittest.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Chromium 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 | 5 | #include "strings/string_printf.h" 6 | 7 | #include 8 | #include 9 | 10 | namespace strings { 11 | 12 | namespace { 13 | 14 | // A helper for the StringAppendV test that follows. 15 | // 16 | // Just forwards its args to StringAppendV. 17 | static void StringAppendVTestHelper(std::string* out, const char* format, ...) { 18 | va_list ap; 19 | va_start(ap, format); 20 | StringAppendV(out, format, ap); 21 | va_end(ap); 22 | } 23 | 24 | } // namespace 25 | 26 | TEST(StringPrintfTest, StringPrintfEmpty) { 27 | EXPECT_EQ("", StringPrintf("%s", "")); 28 | } 29 | 30 | TEST(StringPrintfTest, StringPrintfMisc) { 31 | EXPECT_EQ("123hello w", StringPrintf("%3d%2s %1c", 123, "hello", 'w')); 32 | } 33 | 34 | TEST(StringPrintfTest, StringAppendVEmptyString) { 35 | std::string value("Hello"); 36 | StringAppendVTestHelper(&value, "%s", ""); 37 | EXPECT_EQ("Hello", value); 38 | } 39 | 40 | TEST(StringPrintfTest, StringAppendVString) { 41 | std::string value("Hello"); 42 | StringAppendVTestHelper(&value, " %s", "World"); 43 | EXPECT_EQ("Hello World", value); 44 | } 45 | 46 | TEST(StringPrintfTest, StringAppendVInt) { 47 | std::string value("Hello"); 48 | StringAppendVTestHelper(&value, " %d", 123); 49 | EXPECT_EQ("Hello 123", value); 50 | } 51 | 52 | TEST(StringPrintfTest, StringAppendV) { 53 | std::string out; 54 | StringAppendVTestHelper(&out, "%d foo %s", 1, "bar"); 55 | EXPECT_EQ("1 foo bar", out); 56 | } 57 | 58 | // Test that StringPrintf and StringAppendV do not change errno. 59 | TEST(StringPrintfTest, StringPrintfErrno) { 60 | errno = 1; 61 | EXPECT_EQ("", StringPrintf("%s", "")); 62 | EXPECT_EQ(1, errno); 63 | std::string out; 64 | StringAppendVTestHelper(&out, "%d foo %s", 1, "bar"); 65 | EXPECT_EQ(1, errno); 66 | } 67 | 68 | } // namespace strings 69 | -------------------------------------------------------------------------------- /src/update_engine/action_unittest.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 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 | 5 | #include 6 | #include 7 | #include "update_engine/action.h" 8 | #include "update_engine/action_processor.h" 9 | 10 | using std::string; 11 | 12 | namespace chromeos_update_engine { 13 | 14 | using chromeos_update_engine::ActionPipe; 15 | 16 | class ActionTestAction; 17 | 18 | template<> 19 | class ActionTraits { 20 | public: 21 | typedef string OutputObjectType; 22 | typedef string InputObjectType; 23 | }; 24 | 25 | // This is a simple Action class for testing. 26 | struct ActionTestAction : public Action { 27 | typedef string InputObjectType; 28 | typedef string OutputObjectType; 29 | ActionPipe* in_pipe() { return in_pipe_.get(); } 30 | ActionPipe* out_pipe() { return out_pipe_.get(); } 31 | ActionProcessor* processor() { return processor_; } 32 | void PerformAction() {} 33 | void CompleteAction() { 34 | ASSERT_TRUE(processor()); 35 | processor()->ActionComplete(this, kActionCodeSuccess); 36 | } 37 | string Type() const { return "ActionTestAction"; } 38 | }; 39 | 40 | class ActionTest : public ::testing::Test { }; 41 | 42 | // This test creates two simple Actions and sends a message via an ActionPipe 43 | // from one to the other. 44 | TEST(ActionTest, SimpleTest) { 45 | ActionTestAction action; 46 | 47 | EXPECT_FALSE(action.in_pipe()); 48 | EXPECT_FALSE(action.out_pipe()); 49 | EXPECT_FALSE(action.processor()); 50 | EXPECT_FALSE(action.IsRunning()); 51 | 52 | ActionProcessor action_processor; 53 | action_processor.EnqueueAction(&action); 54 | EXPECT_EQ(&action_processor, action.processor()); 55 | 56 | action_processor.StartProcessing(); 57 | EXPECT_TRUE(action.IsRunning()); 58 | action.CompleteAction(); 59 | EXPECT_FALSE(action.IsRunning()); 60 | } 61 | 62 | } // namespace chromeos_update_engine 63 | -------------------------------------------------------------------------------- /src/update_engine/prefs.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 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 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_PREFS_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_PREFS_H__ 7 | 8 | #include // for FRIEND_TEST 9 | 10 | #include "files/file_path.h" 11 | #include "macros.h" 12 | #include "update_engine/prefs_interface.h" 13 | 14 | namespace chromeos_update_engine { 15 | 16 | // Implements a preference store by storing the value associated with 17 | // a key in a separate file named after the key under a preference 18 | // store directory. 19 | 20 | class Prefs : public PrefsInterface { 21 | public: 22 | Prefs() {} 23 | 24 | // Initializes the store by associating this object with |prefs_dir| 25 | // as the preference store directory. Returns true on success, false 26 | // otherwise. 27 | bool Init(const files::FilePath& prefs_dir); 28 | 29 | // PrefsInterface methods. 30 | bool GetString(const std::string& key, std::string* value); 31 | bool SetString(const std::string& key, const std::string& value); 32 | bool GetInt64(const std::string& key, int64_t* value); 33 | bool SetInt64(const std::string& key, const int64_t value); 34 | 35 | bool Exists(const std::string& key); 36 | bool Delete(const std::string& key); 37 | 38 | private: 39 | FRIEND_TEST(PrefsTest, GetFileNameForKey); 40 | FRIEND_TEST(PrefsTest, GetFileNameForKeyBadCharacter); 41 | FRIEND_TEST(PrefsTest, GetFileNameForKeyEmpty); 42 | 43 | // Sets |filename| to the full path to the file containing the data 44 | // associated with |key|. Returns true on success, false otherwise. 45 | bool GetFileNameForKey(const std::string& key, files::FilePath* filename); 46 | 47 | // Preference store directory. 48 | files::FilePath prefs_dir_; 49 | 50 | DISALLOW_COPY_AND_ASSIGN(Prefs); 51 | }; 52 | 53 | } // namespace chromeos_update_engine 54 | 55 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_PREFS_H__ 56 | -------------------------------------------------------------------------------- /src/update_engine/postinstall_runner_action.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 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 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_POSTINSTALL_RUNNER_ACTION_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_POSTINSTALL_RUNNER_ACTION_H__ 7 | 8 | #include 9 | 10 | #include "update_engine/action.h" 11 | #include "update_engine/install_plan.h" 12 | 13 | // The Postinstall Runner Action is responsible for running the postinstall 14 | // script of a successfully downloaded update. 15 | 16 | namespace chromeos_update_engine { 17 | 18 | class PostinstallRunnerAction; 19 | class NoneType; 20 | 21 | template<> 22 | class ActionTraits { 23 | public: 24 | // Takes the device path as input 25 | typedef InstallPlan InputObjectType; 26 | // Passes the device path as output 27 | typedef InstallPlan OutputObjectType; 28 | }; 29 | 30 | class PostinstallRunnerAction : public Action { 31 | public: 32 | PostinstallRunnerAction() {} 33 | typedef ActionTraits::InputObjectType 34 | InputObjectType; 35 | typedef ActionTraits::OutputObjectType 36 | OutputObjectType; 37 | void PerformAction(); 38 | 39 | // Note that there's no support for terminating this action currently. 40 | void TerminateProcessing() { CHECK(false); } 41 | 42 | // Debugging/logging 43 | static std::string StaticType() { return "PostinstallRunnerAction"; } 44 | std::string Type() const { return StaticType(); } 45 | 46 | private: 47 | // Subprocess::Exec callback. 48 | void CompletePostinstall(int return_code); 49 | static void StaticCompletePostinstall(int return_code, 50 | const std::string& output, 51 | void* p); 52 | 53 | std::string temp_rootfs_dir_; 54 | 55 | DISALLOW_COPY_AND_ASSIGN(PostinstallRunnerAction); 56 | }; 57 | 58 | } // namespace chromeos_update_engine 59 | 60 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_POSTINSTALL_RUNNER_ACTION_H__ 61 | -------------------------------------------------------------------------------- /systemd/update_engine_stub: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) 2013 The CoreOS Authors. All rights reserved. 3 | # Use of this source code is governed by a BSD-style license that can be 4 | # found in the LICENSE file. 5 | 6 | # This is a simple check-in update_engine for PXE. Since the real update_engine 7 | # can't run on rootless machines run this instead for now. This will be replaced 8 | # by a new Go application that does kexec in place. 9 | 10 | set -e -o pipefail 11 | 12 | source /usr/share/coreos/release 13 | source /usr/share/coreos/update.conf 14 | if [[ -e /etc/coreos/update.conf ]]; then 15 | source /etc/coreos/update.conf 16 | fi 17 | 18 | for f in /usr/share/oem/oem-release /etc/oem-release; do 19 | if [[ -e $f ]]; then 20 | # Pull in OEM information too, but prefixing variables with OEM_ 21 | eval "$(sed -e 's/^/OEM_/' $f)" 22 | fi 23 | done 24 | 25 | BOOT_ID=$( 49 | 50 | 51 | 52 | 53 | 54 | " 55 | 56 | echo Request: "${BODY}" 57 | 58 | curl -H "Content-Type: text/xml" -d "${BODY}" "${SERVER}" 59 | -------------------------------------------------------------------------------- /src/files/scoped_temp_dir.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011 The Chromium 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 | 5 | #include "files/scoped_temp_dir.h" 6 | 7 | #include 8 | 9 | #include "files/file_util.h" 10 | 11 | namespace files { 12 | 13 | ScopedTempDir::ScopedTempDir() { 14 | } 15 | 16 | ScopedTempDir::~ScopedTempDir() { 17 | if (!path_.empty() && !Delete()) 18 | DLOG(WARNING) << "Could not delete temp dir in dtor."; 19 | } 20 | 21 | bool ScopedTempDir::CreateUniqueTempDir() { 22 | if (!path_.empty()) 23 | return false; 24 | 25 | // This "scoped_dir" prefix is only used on Windows and serves as a template 26 | // for the unique name. 27 | if (!CreateNewTempDirectory(FILE_PATH_LITERAL("scoped_dir"), &path_)) 28 | return false; 29 | 30 | return true; 31 | } 32 | 33 | bool ScopedTempDir::CreateUniqueTempDirUnderPath(const FilePath& base_path) { 34 | if (!path_.empty()) 35 | return false; 36 | 37 | // If |base_path| does not exist, create it. 38 | if (!CreateDirectory(base_path)) 39 | return false; 40 | 41 | // Create a new, uniquely named directory under |base_path|. 42 | if (!CreateTemporaryDirInDir(base_path, 43 | FILE_PATH_LITERAL("scoped_dir_"), 44 | &path_)) 45 | return false; 46 | 47 | return true; 48 | } 49 | 50 | bool ScopedTempDir::Set(const FilePath& path) { 51 | if (!path_.empty()) 52 | return false; 53 | 54 | if (!DirectoryExists(path) && !CreateDirectory(path)) 55 | return false; 56 | 57 | path_ = path; 58 | return true; 59 | } 60 | 61 | bool ScopedTempDir::Delete() { 62 | if (path_.empty()) 63 | return false; 64 | 65 | bool ret = DeleteFile(path_, true); 66 | if (ret) { 67 | // We only clear the path if deleted the directory. 68 | path_.clear(); 69 | } 70 | 71 | return ret; 72 | } 73 | 74 | FilePath ScopedTempDir::Take() { 75 | FilePath ret = path_; 76 | path_ = FilePath(); 77 | return ret; 78 | } 79 | 80 | bool ScopedTempDir::IsValid() const { 81 | return !path_.empty() && DirectoryExists(path_); 82 | } 83 | 84 | } // namespace files 85 | -------------------------------------------------------------------------------- /src/update_engine/real_system_state.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 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 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_REAL_SYSTEM_STATE_H_ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_REAL_SYSTEM_STATE_H_ 7 | 8 | #include 9 | 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | namespace chromeos_update_engine { 17 | 18 | // A real implementation of the SystemStateInterface which is 19 | // used by the actual product code. 20 | class RealSystemState : public SystemState { 21 | public: 22 | // Constructors and destructors. 23 | RealSystemState(); 24 | virtual ~RealSystemState() {} 25 | 26 | virtual inline PrefsInterface* prefs() { 27 | return &prefs_; 28 | } 29 | 30 | virtual inline PayloadStateInterface* payload_state() { 31 | return &payload_state_; 32 | } 33 | 34 | virtual inline UpdateAttempter* update_attempter() { 35 | return update_attempter_.get(); 36 | } 37 | 38 | // Returns a pointer to the object that stores the parameters that are 39 | // common to all Omaha requests. 40 | virtual inline OmahaRequestParams* request_params() { 41 | return &request_params_; 42 | } 43 | 44 | // Initializes this concrete object. Other methods should be invoked only 45 | // if the object has been initialized successfully. 46 | bool Initialize(); 47 | 48 | private: 49 | // Interface for persisted store. 50 | Prefs prefs_; 51 | 52 | // All state pertaining to payload state such as 53 | // response, URL, backoff states. 54 | PayloadState payload_state_; 55 | 56 | // The dbus object used to initialize the update attempter. 57 | ConcreteDbusGlib dbus_; 58 | 59 | // Pointer to the update attempter object. 60 | std::unique_ptr update_attempter_; 61 | 62 | // Common parameters for all Omaha requests. 63 | OmahaRequestParams request_params_; 64 | }; 65 | 66 | } // namespace chromeos_update_engine 67 | 68 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_REAL_SYSTEM_STATE_H_ 69 | -------------------------------------------------------------------------------- /src/update_engine/extent_writer.cc: -------------------------------------------------------------------------------- 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 3 | // found in the LICENSE file. 4 | 5 | #include "update_engine/extent_writer.h" 6 | #include 7 | #include 8 | #include 9 | #include "update_engine/graph_types.h" 10 | #include "update_engine/utils.h" 11 | 12 | using std::min; 13 | 14 | namespace chromeos_update_engine { 15 | 16 | bool DirectExtentWriter::Write(const void* bytes, size_t count) { 17 | if (count == 0) 18 | return true; 19 | const char* c_bytes = reinterpret_cast(bytes); 20 | size_t bytes_written = 0; 21 | while (count - bytes_written > 0) { 22 | TEST_AND_RETURN_FALSE(next_extent_index_ < extents_.size()); 23 | uint64_t bytes_remaining_next_extent = 24 | extents_[next_extent_index_].num_blocks() * block_size_ - 25 | extent_bytes_written_; 26 | CHECK_NE(bytes_remaining_next_extent, static_cast(0)); 27 | size_t bytes_to_write = 28 | static_cast(min(static_cast(count - bytes_written), 29 | bytes_remaining_next_extent)); 30 | TEST_AND_RETURN_FALSE(bytes_to_write > 0); 31 | 32 | if (extents_[next_extent_index_].start_block() != kSparseHole) { 33 | const off64_t offset = 34 | extents_[next_extent_index_].start_block() * block_size_ + 35 | extent_bytes_written_; 36 | TEST_AND_RETURN_FALSE_ERRNO(lseek64(fd_, offset, SEEK_SET) != 37 | static_cast(-1)); 38 | TEST_AND_RETURN_FALSE( 39 | utils::WriteAll(fd_, c_bytes + bytes_written, bytes_to_write)); 40 | } 41 | bytes_written += bytes_to_write; 42 | extent_bytes_written_ += bytes_to_write; 43 | if (bytes_remaining_next_extent == bytes_to_write) { 44 | // We filled this extent 45 | CHECK_EQ(extent_bytes_written_, 46 | extents_[next_extent_index_].num_blocks() * block_size_); 47 | // move to next extent 48 | extent_bytes_written_ = 0; 49 | next_extent_index_++; 50 | } 51 | } 52 | return true; 53 | } 54 | 55 | } // namespace chromeos_update_engine 56 | -------------------------------------------------------------------------------- /local_coverage_rate: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright (c) 2009 The Chromium OS Authors. All rights reserved. 4 | # Use of this source code is governed by a BSD-style license that can be 5 | # found in the LICENSE file. 6 | 7 | # Calculates the test-coverage percentage for non-test files in the 8 | # update_engine directory. Requires a file 'app.info' to contain the 9 | # results of running the unittests while collecting coverage data. 10 | 11 | cat app.info | awk -F '[,:]' ' 12 | 13 | BEGIN { OFS = ":"; } 14 | 15 | /^SF:/{ FILEN = $2; } 16 | 17 | /^end_of_record$/{ FILEN = ""; } 18 | 19 | /^DA:/{ print FILEN, $2, $3; } 20 | 21 | ' | sort | awk -F : ' 22 | BEGIN { 23 | OFS = ":"; 24 | FILEN = ""; 25 | LINE = ""; 26 | HITS = 0; 27 | } 28 | { 29 | NEWFILEN = $1; 30 | NEWLINE = $2; 31 | if ((NEWFILEN == FILEN) && (NEWLINE == LINE)) { 32 | HITS += $3 33 | } else { 34 | if (FILEN != "") { 35 | print FILEN, LINE, HITS; 36 | } 37 | FILEN = NEWFILEN; 38 | LINE = NEWLINE; 39 | HITS = $3; 40 | } 41 | } 42 | ' | grep '^.*\/trunk\/src\/platform\/update_engine\/' | \ 43 | fgrep -v '_unittest.cc:' | \ 44 | fgrep -v '/test_utils.' | \ 45 | fgrep -v '/test_http_server.cc' | \ 46 | fgrep -v '/testrunner.cc' | \ 47 | fgrep -v '/mock' | \ 48 | fgrep -v '.pb.cc' | \ 49 | awk -F : ' 50 | 51 | function printfile() { 52 | if (FNAME != "") 53 | printf "%-40s %4d / %4d: %5.1f%%\n", FNAME, FILE_GOOD_LINES, 54 | (FILE_BAD_LINES + FILE_GOOD_LINES), 55 | (FILE_GOOD_LINES * 100) / (FILE_BAD_LINES + FILE_GOOD_LINES); 56 | } 57 | 58 | BEGIN { 59 | FNAME = ""; 60 | FILE_BAD_LINES = 0; 61 | FILE_GOOD_LINES = 0; 62 | } 63 | { 64 | // calc filename 65 | ARR_SIZE = split($1, PARTS, "/"); 66 | NEWFNAME = PARTS[ARR_SIZE]; 67 | if (NEWFNAME != FNAME) { 68 | printfile(); 69 | FILE_BAD_LINES = 0; 70 | FILE_GOOD_LINES = 0; 71 | FNAME = NEWFNAME; 72 | } 73 | if ($3 == "0") { 74 | BAD_LINES += 1; 75 | FILE_BAD_LINES += 1; 76 | } else { 77 | GOOD_LINES += 1; 78 | FILE_GOOD_LINES += 1; 79 | } 80 | } 81 | 82 | END { 83 | printfile(); 84 | print "---\nSummary: tested " GOOD_LINES " / " (BAD_LINES + GOOD_LINES); 85 | printf( 86 | "Test coverage: %.1f%%\n", 87 | ((GOOD_LINES * 100) / (BAD_LINES + GOOD_LINES))); 88 | } 89 | ' 90 | -------------------------------------------------------------------------------- /src/update_engine/delta_metadata.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 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 | 5 | #include "update_engine/delta_metadata.h" 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | namespace chromeos_update_engine { 13 | 14 | const char kDeltaMagic[] = "CrAU"; 15 | static_assert(kDeltaMagicSize == sizeof(kDeltaMagic) - 1, "invalid size"); 16 | 17 | ActionExitCode DeltaMetadata::ParsePayload( 18 | const std::vector& payload, 19 | DeltaArchiveManifest* manifest, 20 | uint64_t* metadata_size) { 21 | 22 | if (payload.size() < kDeltaManifestOffset) { 23 | // Don't have enough bytes to even know the manifest size. 24 | return kActionCodeDownloadIncomplete; 25 | } 26 | 27 | // Validate the magic string. 28 | if (memcmp(payload.data(), kDeltaMagic, strlen(kDeltaMagic)) != 0) { 29 | LOG(ERROR) << "Bad payload format -- invalid delta magic."; 30 | return kActionCodeDownloadInvalidMetadataMagicString; 31 | } 32 | 33 | // TODO(jaysri): Compare the version number and skip unknown manifest 34 | // versions. We don't check the version at all today. 35 | 36 | // Next, parse the manifest size. 37 | uint64_t manifest_size; 38 | static_assert(sizeof(manifest_size) == kDeltaManifestSizeSize, 39 | "manifest_size size mismatch"); 40 | memcpy(&manifest_size, 41 | &payload[kDeltaManifestSizeOffset], 42 | kDeltaManifestSizeSize); 43 | manifest_size = be64toh(manifest_size); // switch big endian to host 44 | 45 | // We should wait for the full metadata to be read in before we can parse it. 46 | *metadata_size = kDeltaManifestOffset + manifest_size; 47 | if (payload.size() < *metadata_size) { 48 | return kActionCodeDownloadIncomplete; 49 | } 50 | 51 | // The metadata in |payload| is deemed valid. So, it's now safe to 52 | // parse the protobuf. 53 | if (!manifest->ParseFromArray(&payload[kDeltaManifestOffset], manifest_size)) { 54 | LOG(ERROR) << "Unable to parse manifest in update file."; 55 | return kActionCodeDownloadManifestParseError; 56 | } 57 | return kActionCodeSuccess; 58 | } 59 | 60 | }; // namespace chromeos_update_engine 61 | -------------------------------------------------------------------------------- /src/update_engine/full_update_generator.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 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 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_FULL_UPDATE_GENERATOR_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_FULL_UPDATE_GENERATOR_H__ 7 | 8 | #include 9 | 10 | #include "update_engine/graph_types.h" 11 | 12 | namespace chromeos_update_engine { 13 | 14 | class FullUpdateGenerator { 15 | public: 16 | FullUpdateGenerator(int fd, off_t chunk_size, off_t block_size); 17 | 18 | // Reads a new rootfs (|new_image|), creating a full update of chunk_size 19 | // chunks. Populates |graph| and |final_order| with data about the update 20 | // operations, and writes relevant data to |fd|, updating |data_file_size| as 21 | // it does. Only the first |image_size| bytes are read from |new_image| 22 | // assuming that this is the actual file system. 23 | bool Partition(const std::string& new_image, 24 | off_t image_size, 25 | Graph* graph, 26 | std::vector* final_order); 27 | 28 | // Reads a new file or device found at |path| and adds it to the update 29 | // payload. Populates |ops| with the corresponding operations which must 30 | // be added to the manifest. The optional parameter |size| may be used to 31 | // limit the amount of data read from |path|. 32 | bool Add(const std::string& path, 33 | std::vector* ops); 34 | bool Add(const std::string& path, off_t size, 35 | std::vector* ops); 36 | 37 | // Returns the size of the generated update payload. 38 | off_t Size() { return data_file_size_; } 39 | 40 | private: 41 | // Destination update payload to write to. 42 | int fd_; 43 | 44 | // Chunk size is the amount of data to give to each InstallOperation. 45 | off_t chunk_size_; 46 | // Basic unit use for data sizes/lengths in the manifest. 47 | off_t block_size_; 48 | 49 | // Amount of data written so far. 50 | off_t data_file_size_; 51 | 52 | DISALLOW_IMPLICIT_CONSTRUCTORS(FullUpdateGenerator); 53 | }; 54 | 55 | } // namespace chromeos_update_engine 56 | 57 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_FULL_UPDATE_GENERATOR_H__ 58 | -------------------------------------------------------------------------------- /src/files/scoped_temp_dir.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011 The Chromium 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 | 5 | #ifndef FILES_SCOPED_TEMP_DIR_H_ 6 | #define FILES_SCOPED_TEMP_DIR_H_ 7 | 8 | // An object representing a temporary / scratch directory that should be cleaned 9 | // up (recursively) when this object goes out of scope. Note that since 10 | // deletion occurs during the destructor, no further error handling is possible 11 | // if the directory fails to be deleted. As a result, deletion is not 12 | // guaranteed by this class. 13 | // 14 | // Multiple calls to the methods which establish a temporary directory 15 | // (CreateUniqueTempDir, CreateUniqueTempDirUnderPath, and Set) must have 16 | // intervening calls to Delete or Take, or the calls will fail. 17 | 18 | #include "files/file_path.h" 19 | #include "macros.h" 20 | 21 | namespace files { 22 | 23 | class ScopedTempDir { 24 | public: 25 | // No directory is owned/created initially. 26 | ScopedTempDir(); 27 | 28 | // Recursively delete path. 29 | ~ScopedTempDir(); 30 | 31 | // Creates a unique directory in TempPath, and takes ownership of it. 32 | // See file_util::CreateNewTemporaryDirectory. 33 | [[gnu::warn_unused_result]] bool CreateUniqueTempDir(); 34 | 35 | // Creates a unique directory under a given path, and takes ownership of it. 36 | [[gnu::warn_unused_result]] bool CreateUniqueTempDirUnderPath(const FilePath& path); 37 | 38 | // Takes ownership of directory at |path|, creating it if necessary. 39 | // Don't call multiple times unless Take() has been called first. 40 | [[gnu::warn_unused_result]] bool Set(const FilePath& path); 41 | 42 | // Deletes the temporary directory wrapped by this object. 43 | [[gnu::warn_unused_result]] bool Delete(); 44 | 45 | // Caller takes ownership of the temporary directory so it won't be destroyed 46 | // when this object goes out of scope. 47 | FilePath Take(); 48 | 49 | const FilePath& path() const { return path_; } 50 | 51 | // Returns true if path_ is non-empty and exists. 52 | bool IsValid() const; 53 | 54 | private: 55 | FilePath path_; 56 | 57 | DISALLOW_COPY_AND_ASSIGN(ScopedTempDir); 58 | }; 59 | 60 | } // namespace files 61 | 62 | #endif // FILES_SCOPED_TEMP_DIR_H_ 63 | -------------------------------------------------------------------------------- /src/update_engine/extent_mapper.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 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 | 5 | #include "update_engine/extent_mapper.h" 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | 19 | #include "files/scoped_file.h" 20 | #include "update_engine/graph_types.h" 21 | #include "update_engine/graph_utils.h" 22 | #include "update_engine/utils.h" 23 | 24 | using std::string; 25 | using std::vector; 26 | 27 | namespace chromeos_update_engine { 28 | 29 | namespace extent_mapper { 30 | 31 | namespace { 32 | const int kBlockSize = 4096; 33 | } 34 | 35 | bool ExtentsForFileFibmap(const std::string& path, std::vector* out) { 36 | CHECK(out); 37 | struct stat stbuf; 38 | int rc = stat(path.c_str(), &stbuf); 39 | TEST_AND_RETURN_FALSE_ERRNO(rc == 0); 40 | TEST_AND_RETURN_FALSE(S_ISREG(stbuf.st_mode)); 41 | 42 | int fd = open(path.c_str(), O_RDONLY, 0); 43 | TEST_AND_RETURN_FALSE_ERRNO(fd >= 0); 44 | files::ScopedFD fd_closer(fd); 45 | 46 | // Get file size in blocks 47 | rc = fstat(fd, &stbuf); 48 | if (rc < 0) { 49 | perror("fstat"); 50 | return false; 51 | } 52 | const int block_count = (stbuf.st_size + kBlockSize - 1) / kBlockSize; 53 | Extent current; 54 | current.set_start_block(0); 55 | current.set_num_blocks(0); 56 | 57 | for (int i = 0; i < block_count; i++) { 58 | unsigned int block32 = i; 59 | rc = ioctl(fd, FIBMAP, &block32); 60 | TEST_AND_RETURN_FALSE_ERRNO(rc == 0); 61 | 62 | const uint64_t block = (block32 == 0 ? kSparseHole : block32); 63 | 64 | graph_utils::AppendBlockToExtents(out, block); 65 | } 66 | return true; 67 | } 68 | 69 | bool GetFilesystemBlockSize(const std::string& path, uint32_t* out_blocksize) { 70 | int fd = open(path.c_str(), O_RDONLY, 0); 71 | TEST_AND_RETURN_FALSE_ERRNO(fd >= 0); 72 | files::ScopedFD fd_closer(fd); 73 | int rc = ioctl(fd, FIGETBSZ, out_blocksize); 74 | TEST_AND_RETURN_FALSE_ERRNO(rc != -1); 75 | return true; 76 | } 77 | 78 | } // namespace extent_mapper 79 | 80 | } // namespace chromeos_update_engine 81 | -------------------------------------------------------------------------------- /src/update_engine/omaha_response.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 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 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_OMAHA_RESPONSE_H 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_OMAHA_RESPONSE_H 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | namespace chromeos_update_engine { 16 | 17 | // This struct encapsulates the data Omaha's response for the request. 18 | // The strings in this struct are not XML escaped. 19 | struct OmahaResponse { 20 | OmahaResponse() 21 | : update_exists(false), 22 | poll_interval(0), 23 | size(0), 24 | max_failure_count_per_url(0), 25 | needs_admin(false), 26 | prompt(false), 27 | is_delta_payload(false), 28 | disable_payload_backoff(false) {} 29 | 30 | // True iff there is an update to be downloaded. 31 | bool update_exists; 32 | 33 | // If non-zero, server-dictated poll interval in seconds. 34 | int poll_interval; 35 | 36 | // These are only valid if update_exists is true: 37 | std::string display_version; 38 | 39 | // The ordered list of URLs in the Omaha response. Each item is a complete 40 | // URL (i.e. in terms of Omaha XML, each value is a urlBase + packageName) 41 | std::vector payload_urls; 42 | 43 | std::string more_info_url; 44 | std::string hash; 45 | std::string deadline; 46 | off_t size; 47 | // The number of URL-related failures to tolerate before moving on to the 48 | // next URL in the current pass. This is a configurable value from the 49 | // Omaha Response attribute, if ever we need to fine tune the behavior. 50 | uint32_t max_failure_count_per_url; 51 | bool needs_admin; 52 | bool prompt; 53 | 54 | // True if the payload described in this response is a delta payload. 55 | // False if it's a full payload. 56 | bool is_delta_payload; 57 | 58 | // True if the Omaha rule instructs us to disable the backoff logic 59 | // on the client altogether. False otherwise. 60 | bool disable_payload_backoff; 61 | }; 62 | static_assert(sizeof(off_t) == 8, "off_t not 64 bit"); 63 | 64 | } // namespace chromeos_update_engine 65 | 66 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_OMAHA_RESPONSE_H 67 | -------------------------------------------------------------------------------- /src/update_engine/http_common.h: -------------------------------------------------------------------------------- 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 3 | // found in the LICENSE file. 4 | 5 | // This file contains general definitions used in implementing, testing and 6 | // emulating communication over HTTP. 7 | 8 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_HTTP_COMMON_H__ 9 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_HTTP_COMMON_H__ 10 | 11 | #include 12 | 13 | // Enumeration type for HTTP response codes. 14 | enum HttpResponseCode { 15 | kHttpResponseUndefined = 0, 16 | kHttpResponseOk = 200, 17 | kHttpResponseCreated = 201, 18 | kHttpResponseAccepted = 202, 19 | kHttpResponseNonAuthInfo = 203, 20 | kHttpResponseNoContent = 204, 21 | kHttpResponseResetContent = 205, 22 | kHttpResponsePartialContent = 206, 23 | kHttpResponseMultipleChoices = 300, 24 | kHttpResponseMovedPermanently = 301, 25 | kHttpResponseFound = 302, 26 | kHttpResponseSeeOther = 303, 27 | kHttpResponseNotModified = 304, 28 | kHttpResponseUseProxy = 305, 29 | kHttpResponseTempRedirect = 307, 30 | kHttpResponseBadRequest = 400, 31 | kHttpResponseUnauth = 401, 32 | kHttpResponseForbidden = 403, 33 | kHttpResponseNotFound = 404, 34 | kHttpResponseRequestTimeout = 408, 35 | kHttpResponseReqRangeNotSat = 416, 36 | kHttpResponseInternalServerError = 500, 37 | kHttpResponseNotImplemented = 501, 38 | kHttpResponseServiceUnavailable = 503, 39 | kHttpResponseVersionNotSupported = 505, 40 | }; 41 | 42 | // Returns a standard HTTP status line string for a given response code. 43 | const char *GetHttpResponseDescription(HttpResponseCode code); 44 | 45 | // Converts a string beginning with an HTTP error code into numerical value. 46 | HttpResponseCode StringToHttpResponseCode(const char *s); 47 | 48 | 49 | // Enumeration type for HTTP Content-Type. 50 | enum HttpContentType { 51 | kHttpContentTypeUnspecified = 0, 52 | kHttpContentTypeTextXml, 53 | kHttpContentTypeOctetStream, 54 | }; 55 | 56 | // Returns a standard HTTP Content-Type string. 57 | const char *GetHttpContentTypeString(HttpContentType type); 58 | 59 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_HTTP_COMMON_H__ 60 | -------------------------------------------------------------------------------- /src/update_engine/mock_system_state.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 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 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_MOCK_SYSTEM_STATE_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_MOCK_SYSTEM_STATE_H__ 7 | 8 | #include 9 | 10 | #include 11 | 12 | #include "update_engine/mock_dbus_interface.h" 13 | #include "update_engine/mock_payload_state.h" 14 | #include "update_engine/prefs_mock.h" 15 | #include "update_engine/system_state.h" 16 | #include "update_engine/update_attempter_mock.h" 17 | 18 | namespace chromeos_update_engine { 19 | 20 | // Mock the SystemStateInterface so that we could lie that 21 | // OOBE is completed even when there's no such marker file, etc. 22 | class MockSystemState : public SystemState { 23 | public: 24 | MockSystemState(); 25 | 26 | virtual ~MockSystemState() {} 27 | 28 | inline virtual PrefsInterface* prefs() { 29 | return prefs_; 30 | } 31 | 32 | inline virtual PayloadStateInterface* payload_state() { 33 | return &mock_payload_state_; 34 | } 35 | 36 | virtual UpdateAttempter* update_attempter(); 37 | 38 | inline virtual OmahaRequestParams* request_params() { 39 | return request_params_; 40 | } 41 | 42 | inline void set_prefs(PrefsInterface* prefs) { 43 | prefs_ = prefs; 44 | } 45 | 46 | inline testing::NiceMock *mock_prefs() { 47 | return &mock_prefs_; 48 | } 49 | 50 | inline MockPayloadState* mock_payload_state() { 51 | return &mock_payload_state_; 52 | } 53 | 54 | inline void set_request_params(OmahaRequestParams* params) { 55 | request_params_ = params; 56 | } 57 | 58 | private: 59 | // These are Mock objects or objects we own. 60 | testing::NiceMock mock_prefs_; 61 | testing::NiceMock mock_payload_state_; 62 | std::unique_ptr> mock_update_attempter_; 63 | MockDbusGlib dbus_; 64 | 65 | // These are the other object we own. 66 | OmahaRequestParams default_request_params_; 67 | 68 | // These are pointers to objects which caller can override. 69 | PrefsInterface* prefs_; 70 | OmahaRequestParams* request_params_; 71 | }; 72 | 73 | } // namespeace chromeos_update_engine 74 | 75 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_MOCK_SYSTEM_STATE_H__ 76 | -------------------------------------------------------------------------------- /src/update_engine/terminator_unittest.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 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 | 5 | #include 6 | #include 7 | 8 | #include "update_engine/terminator.h" 9 | 10 | using std::string; 11 | using testing::ExitedWithCode; 12 | 13 | namespace chromeos_update_engine { 14 | 15 | class TerminatorTest : public ::testing::Test { 16 | protected: 17 | virtual void SetUp() { 18 | Terminator::Init(); 19 | ASSERT_FALSE(Terminator::exit_blocked()); 20 | ASSERT_FALSE(Terminator::exit_requested()); 21 | } 22 | virtual void TearDown() { 23 | // Makes sure subsequent non-Terminator tests don't get accidentally 24 | // terminated. 25 | Terminator::Init(); 26 | } 27 | }; 28 | 29 | typedef TerminatorTest TerminatorDeathTest; 30 | 31 | namespace { 32 | void UnblockExitThroughUnblocker() { 33 | ScopedTerminatorExitUnblocker unblocker = ScopedTerminatorExitUnblocker(); 34 | } 35 | 36 | void RaiseSIGTERM() { 37 | ASSERT_EXIT(raise(SIGTERM), ExitedWithCode(2), ""); 38 | } 39 | } // namespace {} 40 | 41 | TEST_F(TerminatorTest, HandleSignalTest) { 42 | Terminator::set_exit_blocked(true); 43 | Terminator::HandleSignal(SIGTERM); 44 | ASSERT_TRUE(Terminator::exit_requested()); 45 | } 46 | 47 | TEST_F(TerminatorTest, ScopedTerminatorExitUnblockerTest) { 48 | Terminator::set_exit_blocked(true); 49 | ASSERT_TRUE(Terminator::exit_blocked()); 50 | ASSERT_FALSE(Terminator::exit_requested()); 51 | UnblockExitThroughUnblocker(); 52 | ASSERT_FALSE(Terminator::exit_blocked()); 53 | ASSERT_FALSE(Terminator::exit_requested()); 54 | } 55 | 56 | TEST_F(TerminatorDeathTest, ExitTest) { 57 | ASSERT_EXIT(Terminator::Exit(), ExitedWithCode(2), ""); 58 | Terminator::set_exit_blocked(true); 59 | ASSERT_EXIT(Terminator::Exit(), ExitedWithCode(2), ""); 60 | } 61 | 62 | TEST_F(TerminatorDeathTest, RaiseSignalTest) { 63 | RaiseSIGTERM(); 64 | Terminator::set_exit_blocked(true); 65 | EXPECT_FATAL_FAILURE(RaiseSIGTERM(), ""); 66 | } 67 | 68 | TEST_F(TerminatorDeathTest, ScopedTerminatorExitUnblockerExitTest) { 69 | Terminator::set_exit_blocked(true); 70 | Terminator::exit_requested_ = 1; 71 | ASSERT_EXIT(UnblockExitThroughUnblocker(), ExitedWithCode(2), ""); 72 | } 73 | 74 | } // namespace chromeos_update_engine 75 | -------------------------------------------------------------------------------- /src/update_engine/cycle_breaker.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 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 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_CYCLE_BREAKER_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_CYCLE_BREAKER_H__ 7 | 8 | // This is a modified implementation of Donald B. Johnson's algorithm for 9 | // finding all elementary cycles (a.k.a. circuits) in a directed graph. 10 | // See the paper "Finding All the Elementary Circuits of a Directed Graph" 11 | // at http://dutta.csc.ncsu.edu/csc791_spring07/wrap/circuits_johnson.pdf 12 | // for reference. 13 | 14 | // Note: this version of the algorithm not only finds cycles, but breaks them. 15 | // It uses a simple greedy algorithm for cutting: when a cycle is discovered, 16 | // the edge with the least weight is cut. Longer term we may wish to do 17 | // something more intelligent, since the goal is (ideally) to minimize the 18 | // sum of the weights of all cut cycles. In practice, it's intractable 19 | // to consider all cycles before cutting any; there are simply too many. 20 | // In a sample graph representative of a typical workload, I found over 21 | // 5 * 10^15 cycles. 22 | 23 | #include 24 | #include 25 | #include "update_engine/graph_types.h" 26 | 27 | namespace chromeos_update_engine { 28 | 29 | class CycleBreaker { 30 | public: 31 | CycleBreaker() : skipped_ops_(0) {} 32 | // out_cut_edges is replaced with the cut edges. 33 | void BreakCycles(const Graph& graph, std::set* out_cut_edges); 34 | 35 | size_t skipped_ops() const { return skipped_ops_; } 36 | 37 | private: 38 | void HandleCircuit(); 39 | void Unblock(Vertex::Index u); 40 | bool Circuit(Vertex::Index vertex, Vertex::Index depth); 41 | bool StackContainsCutEdge() const; 42 | 43 | std::vector blocked_; // "blocked" in the paper 44 | Vertex::Index current_vertex_; // "s" in the paper 45 | std::vector stack_; // the stack variable in the paper 46 | Graph subgraph_; // "A_K" in the paper 47 | Graph blocked_graph_; // "B" in the paper 48 | 49 | std::set cut_edges_; 50 | 51 | // Number of operations skipped b/c we know they don't have any 52 | // incoming edges. 53 | size_t skipped_ops_; 54 | }; 55 | 56 | } // namespace chromeos_update_engine 57 | 58 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_CYCLE_BREAKER_H__ 59 | -------------------------------------------------------------------------------- /src/update_engine/graph_utils.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 The Chromium 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 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_GRAPH_UTILS_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_GRAPH_UTILS_H__ 7 | 8 | #include 9 | 10 | #include "update_engine/graph_types.h" 11 | #include "update_engine/update_metadata.pb.h" 12 | 13 | // A few utility functions for graphs 14 | 15 | namespace chromeos_update_engine { 16 | 17 | namespace graph_utils { 18 | 19 | // Returns the number of blocks represented by all extents in the edge. 20 | uint64_t EdgeWeight(const Graph& graph, const Edge& edge); 21 | 22 | // These add a read-before dependency from graph[src] -> graph[dst]. If the dep 23 | // already exists, the block/s is/are added to the existing edge. 24 | void AddReadBeforeDep(Vertex* src, 25 | Vertex::Index dst, 26 | uint64_t block); 27 | void AddReadBeforeDepExtents(Vertex* src, 28 | Vertex::Index dst, 29 | const std::vector& extents); 30 | 31 | void DropWriteBeforeDeps(Vertex::EdgeMap* edge_map); 32 | 33 | // For each node N in graph, drop all edges N->|index|. 34 | void DropIncomingEdgesTo(Graph* graph, Vertex::Index index); 35 | 36 | // block must either be the next block in the last extent or a block 37 | // in the next extent. This function will not handle inserting block 38 | // into an arbitrary place in the extents. 39 | void AppendBlockToExtents(std::vector* extents, uint64_t block); 40 | 41 | // Get/SetElement are intentionally overloaded so that templated functions 42 | // can accept either type of collection of Extents. 43 | Extent GetElement(const std::vector& collection, size_t index); 44 | Extent GetElement( 45 | const google::protobuf::RepeatedPtrField& collection, 46 | size_t index); 47 | 48 | template 49 | uint64_t BlocksInExtents(const T& collection) { 50 | uint64_t ret = 0; 51 | for (size_t i = 0; i < static_cast(collection.size()); ++i) { 52 | ret += GetElement(collection, i).num_blocks(); 53 | } 54 | return ret; 55 | } 56 | 57 | void DumpGraph(const Graph& graph); 58 | 59 | } // namespace graph_utils 60 | 61 | } // namespace chromeos_update_engine 62 | 63 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_GRAPH_UTILS_H__ 64 | -------------------------------------------------------------------------------- /src/update_engine/delta_performer_unittest.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 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 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #include "update_engine/delta_performer.h" 13 | #include "update_engine/extent_ranges.h" 14 | #include "update_engine/graph_types.h" 15 | #include "update_engine/update_metadata.pb.h" 16 | 17 | namespace chromeos_update_engine { 18 | 19 | using std::string; 20 | 21 | TEST(DeltaPerformerTest, ExtentsToByteStringTest) { 22 | uint64_t test[] = {1, 1, 4, 2, kSparseHole, 1, 0, 1}; 23 | static_assert(arraysize(test) % 2 == 0, "array size uneven"); 24 | const uint64_t block_size = 4096; 25 | const uint64_t file_length = 5 * block_size - 13; 26 | 27 | google::protobuf::RepeatedPtrField extents; 28 | for (size_t i = 0; i < arraysize(test); i += 2) { 29 | Extent* extent = extents.Add(); 30 | extent->set_start_block(test[i]); 31 | extent->set_num_blocks(test[i + 1]); 32 | } 33 | 34 | string expected_output = "4096:4096,16384:8192,-1:4096,0:4083"; 35 | string actual_output; 36 | EXPECT_TRUE(DeltaPerformer::ExtentsToBsdiffPositionsString(extents, 37 | block_size, 38 | file_length, 39 | &actual_output)); 40 | EXPECT_EQ(expected_output, actual_output); 41 | } 42 | 43 | TEST(DeltaPerformerTest, IsIdempotentOperationTest) { 44 | InstallOperation op; 45 | EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op)); 46 | *(op.add_dst_extents()) = ExtentForRange(0, 5); 47 | EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op)); 48 | *(op.add_src_extents()) = ExtentForRange(4, 1); 49 | EXPECT_FALSE(DeltaPerformer::IsIdempotentOperation(op)); 50 | op.clear_src_extents(); 51 | *(op.add_src_extents()) = ExtentForRange(5, 3); 52 | EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op)); 53 | *(op.add_dst_extents()) = ExtentForRange(20, 6); 54 | EXPECT_TRUE(DeltaPerformer::IsIdempotentOperation(op)); 55 | *(op.add_src_extents()) = ExtentForRange(19, 2); 56 | EXPECT_FALSE(DeltaPerformer::IsIdempotentOperation(op)); 57 | } 58 | 59 | } // namespace chromeos_update_engine 60 | -------------------------------------------------------------------------------- /src/update_engine/tarjan.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 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 | 5 | #include 6 | #include 7 | #include 8 | #include "update_engine/tarjan.h" 9 | #include "update_engine/utils.h" 10 | 11 | using std::min; 12 | using std::vector; 13 | 14 | namespace chromeos_update_engine { 15 | 16 | namespace { 17 | const vector::size_type kInvalidIndex = -1; 18 | } 19 | 20 | void TarjanAlgorithm::Execute(Vertex::Index vertex, 21 | Graph* graph, 22 | vector* out) { 23 | stack_.clear(); 24 | components_.clear(); 25 | index_ = 0; 26 | for (Graph::iterator it = graph->begin(); it != graph->end(); ++it) 27 | it->index = it->lowlink = kInvalidIndex; 28 | required_vertex_ = vertex; 29 | 30 | Tarjan(vertex, graph); 31 | if (!components_.empty()) 32 | out->swap(components_[0]); 33 | } 34 | 35 | void TarjanAlgorithm::Tarjan(Vertex::Index vertex, Graph* graph) { 36 | CHECK_EQ((*graph)[vertex].index, kInvalidIndex); 37 | (*graph)[vertex].index = index_; 38 | (*graph)[vertex].lowlink = index_; 39 | index_++; 40 | stack_.push_back(vertex); 41 | for (Vertex::EdgeMap::iterator it = (*graph)[vertex].out_edges.begin(); 42 | it != (*graph)[vertex].out_edges.end(); ++it) { 43 | Vertex::Index vertex_next = it->first; 44 | if ((*graph)[vertex_next].index == kInvalidIndex) { 45 | Tarjan(vertex_next, graph); 46 | (*graph)[vertex].lowlink = min((*graph)[vertex].lowlink, 47 | (*graph)[vertex_next].lowlink); 48 | } else if (utils::VectorContainsValue(stack_, vertex_next)) { 49 | (*graph)[vertex].lowlink = min((*graph)[vertex].lowlink, 50 | (*graph)[vertex_next].index); 51 | } 52 | } 53 | if ((*graph)[vertex].lowlink == (*graph)[vertex].index) { 54 | vector component; 55 | Vertex::Index other_vertex; 56 | do { 57 | other_vertex = stack_.back(); 58 | stack_.pop_back(); 59 | component.push_back(other_vertex); 60 | } while (other_vertex != vertex && !stack_.empty()); 61 | 62 | if (utils::VectorContainsValue(component, required_vertex_)) { 63 | components_.resize(components_.size() + 1); 64 | component.swap(components_.back()); 65 | } 66 | } 67 | } 68 | 69 | } // namespace chromeos_update_engine 70 | 71 | -------------------------------------------------------------------------------- /src/update_engine/bzip_extent_writer.cc: -------------------------------------------------------------------------------- 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 3 | // found in the LICENSE file. 4 | 5 | #include "update_engine/bzip_extent_writer.h" 6 | 7 | using std::vector; 8 | 9 | namespace chromeos_update_engine { 10 | 11 | namespace { 12 | const vector::size_type kOutputBufferLength = 1024 * 1024; 13 | } 14 | 15 | bool BzipExtentWriter::Init(int fd, 16 | const vector& extents, 17 | uint32_t block_size) { 18 | // Init bzip2 stream 19 | int rc = BZ2_bzDecompressInit(&stream_, 20 | 0, // verbosity. (0 == silent) 21 | 0 // 0 = faster algo, more memory 22 | ); 23 | TEST_AND_RETURN_FALSE(rc == BZ_OK); 24 | 25 | return next_->Init(fd, extents, block_size); 26 | } 27 | 28 | bool BzipExtentWriter::Write(const void* bytes, size_t count) { 29 | vector output_buffer(kOutputBufferLength); 30 | 31 | const char* c_bytes = reinterpret_cast(bytes); 32 | 33 | input_buffer_.insert(input_buffer_.end(), c_bytes, c_bytes + count); 34 | 35 | stream_.next_in = &input_buffer_[0]; 36 | stream_.avail_in = input_buffer_.size(); 37 | 38 | for (;;) { 39 | stream_.next_out = &output_buffer[0]; 40 | stream_.avail_out = output_buffer.size(); 41 | 42 | int rc = BZ2_bzDecompress(&stream_); 43 | TEST_AND_RETURN_FALSE(rc == BZ_OK || rc == BZ_STREAM_END); 44 | 45 | if (stream_.avail_out == output_buffer.size()) 46 | break; // got no new bytes 47 | 48 | TEST_AND_RETURN_FALSE( 49 | next_->Write(&output_buffer[0], 50 | output_buffer.size() - stream_.avail_out)); 51 | 52 | if (rc == BZ_STREAM_END) 53 | CHECK_EQ(stream_.avail_in, static_cast(0)); 54 | if (stream_.avail_in == 0) 55 | break; // no more input to process 56 | } 57 | 58 | // store unconsumed data in input_buffer_. 59 | 60 | vector new_input_buffer(input_buffer_.end() - stream_.avail_in, 61 | input_buffer_.end()); 62 | new_input_buffer.swap(input_buffer_); 63 | 64 | return true; 65 | } 66 | 67 | bool BzipExtentWriter::EndImpl() { 68 | TEST_AND_RETURN_FALSE(input_buffer_.empty()); 69 | TEST_AND_RETURN_FALSE(BZ2_bzDecompressEnd(&stream_) == BZ_OK); 70 | return next_->End(); 71 | } 72 | 73 | } // namespace chromeos_update_engine 74 | -------------------------------------------------------------------------------- /src/update_engine/install_plan.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 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 | 5 | #include "update_engine/install_plan.h" 6 | 7 | #include 8 | 9 | #include "update_engine/utils.h" 10 | 11 | using std::string; 12 | 13 | namespace chromeos_update_engine { 14 | 15 | InstallPlan::InstallPlan(bool is_resume, 16 | const string& url, 17 | uint64_t payload_size, 18 | const string& payload_hash, 19 | const string& partition_path) 20 | : is_resume(is_resume), 21 | download_url(url), 22 | payload_size(payload_size), 23 | payload_hash(payload_hash), 24 | partition_path(partition_path), 25 | new_partition_size(0), 26 | new_kernel_size(0), 27 | new_pcr_policy_size(0) {} 28 | 29 | InstallPlan::InstallPlan() : is_resume(false), 30 | payload_size(0), 31 | new_partition_size(0), 32 | new_kernel_size(0), 33 | new_pcr_policy_size(0) {} 34 | 35 | 36 | bool InstallPlan::operator==(const InstallPlan& that) const { 37 | return ((is_resume == that.is_resume) && 38 | (download_url == that.download_url) && 39 | (payload_size == that.payload_size) && 40 | (payload_hash == that.payload_hash) && 41 | (partition_path == that.partition_path) && 42 | (kernel_path == that.kernel_path) && 43 | (pcr_policy_path == that.pcr_policy_path) && 44 | (old_partition_path == that.old_partition_path) && 45 | (old_kernel_path == that.old_kernel_path)); 46 | } 47 | 48 | bool InstallPlan::operator!=(const InstallPlan& that) const { 49 | return !((*this) == that); 50 | } 51 | 52 | void InstallPlan::Dump() const { 53 | LOG(INFO) << "InstallPlan: " 54 | << (is_resume ? ", resume" : ", new_update") 55 | << ", url: " << download_url 56 | << ", payload size: " << payload_size 57 | << ", payload hash: " << payload_hash 58 | << ", partition_path: " << partition_path 59 | << ", kernel_path: " << kernel_path 60 | << ", pcr_policy_path: " << pcr_policy_path 61 | << ", old_partition_path: " << old_partition_path 62 | << ", old_kernel_path: " << old_kernel_path; 63 | } 64 | 65 | } // namespace chromeos_update_engine 66 | 67 | -------------------------------------------------------------------------------- /src/update_engine/pcr_policy_post_action.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 The CoreOS 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 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_PCR_POLICY_POST_ACTION_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_PCR_POLICY_POST_ACTION_H__ 7 | 8 | #include 9 | #include 10 | 11 | #include "update_engine/action.h" 12 | #include "update_engine/http_fetcher.h" 13 | #include "update_engine/install_plan.h" 14 | #include "update_engine/system_state.h" 15 | 16 | namespace chromeos_update_engine { 17 | 18 | class PCRPolicyPostAction; 19 | 20 | template<> 21 | class ActionTraits { 22 | public: 23 | // Takes the install plan as input 24 | typedef InstallPlan InputObjectType; 25 | // Passes the install plan as output 26 | typedef InstallPlan OutputObjectType; 27 | }; 28 | 29 | class PCRPolicyPostAction : public Action, 30 | public HttpFetcherDelegate { 31 | public: 32 | // URL to POST PCR data to is found in system_state. 33 | // Takes ownership of the passed in HttpFetcher. Useful for testing. 34 | PCRPolicyPostAction(SystemState* system_state, HttpFetcher* http_fetcher) 35 | : system_state_(system_state), 36 | http_fetcher_(http_fetcher) {} 37 | virtual ~PCRPolicyPostAction() {} 38 | 39 | typedef ActionTraits::InputObjectType 40 | InputObjectType; 41 | typedef ActionTraits::OutputObjectType 42 | OutputObjectType; 43 | void PerformAction(); 44 | void TerminateProcessing(); 45 | 46 | // Delegate methods (see http_fetcher.h) 47 | virtual void ReceivedBytes(HttpFetcher *fetcher, 48 | const char* bytes, int length); 49 | 50 | virtual void TransferComplete(HttpFetcher *fetcher, bool successful); 51 | 52 | // Debugging/logging 53 | static std::string StaticType() { return "PCRPolicyPostAction"; } 54 | std::string Type() const { return StaticType(); } 55 | 56 | private: 57 | // Global system context. 58 | SystemState* system_state_; 59 | 60 | // Pointer to our HttpFetcher. 61 | std::unique_ptr http_fetcher_; 62 | 63 | // Stores the HTTP response. 64 | std::string response_buffer_; 65 | 66 | // The install plan we're passed in via the input pipe. 67 | InstallPlan install_plan_; 68 | 69 | DISALLOW_COPY_AND_ASSIGN(PCRPolicyPostAction); 70 | }; 71 | 72 | } // namespace chromeos_update_engine 73 | 74 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_PCR_POLICY_POST_ACTION_H__ 75 | -------------------------------------------------------------------------------- /src/update_engine/kernel_copier_action.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 The CoreOS 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 | 5 | #include "update_engine/kernel_copier_action.h" 6 | 7 | #include 8 | 9 | #include "files/file_util.h" 10 | #include "update_engine/utils.h" 11 | #include "update_engine/omaha_hash_calculator.h" 12 | 13 | using std::string; 14 | 15 | namespace chromeos_update_engine { 16 | 17 | void KernelCopierAction::PerformAction() { 18 | // Will tell the ActionProcessor we've failed if we return. 19 | ScopedActionCompleter abort_action_completer(processor_, this); 20 | 21 | if (!HasInputObject()) { 22 | LOG(ERROR) << "KernelCopierAction missing input object."; 23 | return; 24 | } 25 | install_plan_ = GetInputObject(); 26 | if (install_plan_.is_resume || install_plan_.kernel_path.empty()) { 27 | // Resuming download or no kernel to install, no copy needed. 28 | if (HasOutputPipe()) 29 | SetOutputObject(install_plan_); 30 | abort_action_completer.set_code(kActionCodeSuccess); 31 | return; 32 | } 33 | 34 | // Full updates can still apply if the old kernel is missing for some 35 | // reason. Just issue a warning and move on. The payload processor will 36 | // reject delta updates with a hash mismatch if this happens. 37 | const string source = install_plan_.old_kernel_path; 38 | if (!utils::FileExists(source.c_str())) { 39 | LOG(WARNING) << "Missing source kernel " << source; 40 | if (HasOutputPipe()) 41 | SetOutputObject(install_plan_); 42 | abort_action_completer.set_code(kActionCodeSuccess); 43 | return; 44 | } 45 | 46 | off_t length = utils::FileSize(source); 47 | if (length < 0) { 48 | LOG(ERROR) << "Failed to determine size of source kernel " << source; 49 | return; 50 | } 51 | 52 | if (length != OmahaHashCalculator::RawHashOfFile( 53 | source, length, &install_plan_.old_kernel_hash)) { 54 | LOG(ERROR) << "Failed to compute hash of source kernel " << source; 55 | return; 56 | } 57 | 58 | if (!files::CopyFile(files::FilePath(source), 59 | files::FilePath(install_plan_.kernel_path))) { 60 | LOG(ERROR) << "Failed to copy kernel from " << source << " to " 61 | << install_plan_.kernel_path; 62 | return; 63 | } 64 | 65 | // Success! Pass along the new install_plan to the next action. 66 | if (HasOutputPipe()) 67 | SetOutputObject(install_plan_); 68 | abort_action_completer.set_code(kActionCodeSuccess); 69 | return; 70 | } 71 | 72 | } // namespace chromeos_update_engine 73 | -------------------------------------------------------------------------------- /src/strings/string_number_conversions.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The Chromium 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 | 5 | #ifndef STRINGS_STRING_NUMBER_CONVERSIONS_H_ 6 | #define STRINGS_STRING_NUMBER_CONVERSIONS_H_ 7 | 8 | #include 9 | 10 | #include 11 | 12 | // ---------------------------------------------------------------------------- 13 | // IMPORTANT MESSAGE FROM YOUR SPONSOR 14 | // 15 | // Please do not add "convenience" functions for converting strings to integers 16 | // that return the value and ignore success/failure. That encourages people to 17 | // write code that doesn't properly handle the error conditions. 18 | // ---------------------------------------------------------------------------- 19 | 20 | namespace strings { 21 | 22 | // String -> number conversions ------------------------------------------------ 23 | 24 | // Perform a best-effort conversion of the input string to a numeric type, 25 | // setting |*output| to the result of the conversion. Returns true for 26 | // "perfect" conversions; returns false in the following cases: 27 | // - Overflow. |*output| will be set to the maximum value supported 28 | // by the data type. 29 | // - Underflow. |*output| will be set to the minimum value supported 30 | // by the data type. 31 | // - Trailing characters in the string after parsing the number. |*output| 32 | // will be set to the value of the number that was parsed. 33 | // - Leading whitespace in the string before parsing the number. |*output| will 34 | // be set to the value of the number that was parsed. 35 | // - No characters parseable as a number at the beginning of the string. 36 | // |*output| will be set to 0. 37 | // - Empty string. |*output| will be set to 0. 38 | bool StringToInt(const std::string& input, int* output); 39 | bool StringToUint(const std::string& input, unsigned* output); 40 | bool StringToInt64(const std::string& input, int64_t* output); 41 | 42 | // Hex encoding ---------------------------------------------------------------- 43 | 44 | // Returns a hex string representation of a binary buffer. The returned hex 45 | // string will be in upper case. This function does not check if |size| is 46 | // within reasonable limits since it's written with trusted data in mind. If 47 | // you suspect that the data you want to format might be large, the absolute 48 | // max size for |size| should be is 49 | // std::numeric_limits::max() / 2 50 | std::string HexEncode(const void* bytes, size_t size); 51 | 52 | } // namespace strings 53 | 54 | #endif // STRINGS_STRING_NUMBER_CONVERSIONS_H_ 55 | -------------------------------------------------------------------------------- /src/macros.h: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Chromium 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 | 5 | // This file contains macros and macro-like constructs (e.g., templates) that 6 | // are commonly used throughout Chromium source. (It may also contain things 7 | // that are closely related to things that are commonly used that belong in this 8 | // file.) 9 | 10 | #ifndef MACROS_H_ 11 | #define MACROS_H_ 12 | 13 | #include // For size_t. 14 | #include // For memcpy. 15 | 16 | // Put this in the declarations for a class to be uncopyable. 17 | #define DISALLOW_COPY(TypeName) \ 18 | TypeName(const TypeName&) = delete 19 | 20 | // Put this in the declarations for a class to be unassignable. 21 | #define DISALLOW_ASSIGN(TypeName) \ 22 | void operator=(const TypeName&) = delete 23 | 24 | // A macro to disallow the copy constructor and operator= functions 25 | // This should be used in the private: declarations for a class 26 | #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ 27 | TypeName(const TypeName&); \ 28 | void operator=(const TypeName&) 29 | 30 | // An older, deprecated, politically incorrect name for the above. 31 | // NOTE: The usage of this macro was banned from our code base, but some 32 | // third_party libraries are yet using it. 33 | // TODO(tfarina): Figure out how to fix the usage of this macro in the 34 | // third_party libraries and get rid of it. 35 | #define DISALLOW_EVIL_CONSTRUCTORS(TypeName) DISALLOW_COPY_AND_ASSIGN(TypeName) 36 | 37 | // A macro to disallow all the implicit constructors, namely the 38 | // default constructor, copy constructor and operator= functions. 39 | // 40 | // This should be used in the private: declarations for a class 41 | // that wants to prevent anyone from instantiating it. This is 42 | // especially useful for classes containing only static methods. 43 | #define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ 44 | TypeName() = delete; \ 45 | DISALLOW_COPY_AND_ASSIGN(TypeName) 46 | 47 | // The arraysize(arr) macro returns the # of elements in an array arr. 48 | // The expression is a compile-time constant, and therefore can be 49 | // used in defining new arrays, for example. If you use arraysize on 50 | // a pointer by mistake, you will get a compile-time error. 51 | 52 | // This template function declaration is used in defining arraysize. 53 | // Note that the function doesn't need an implementation, as we only 54 | // use its type. 55 | template char (&ArraySizeHelper(T (&array)[N]))[N]; 56 | #define arraysize(array) (sizeof(ArraySizeHelper(array))) 57 | 58 | #endif // MACROS_H_ 59 | -------------------------------------------------------------------------------- /src/update_engine/graph_types.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 The Chromium 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 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_GRAPH_TYPES_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_GRAPH_TYPES_H__ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "macros.h" 16 | #include "update_engine/update_metadata.pb.h" 17 | 18 | // A few classes that help in generating delta images use these types 19 | // for the graph work. 20 | 21 | namespace chromeos_update_engine { 22 | 23 | bool operator==(const Extent& a, const Extent& b); 24 | 25 | struct EdgeProperties { 26 | // Read-before extents. I.e., blocks in |extents| must be read by the 27 | // node pointed to before the pointing node runs (presumably b/c it 28 | // overwrites these blocks). 29 | std::vector extents; 30 | 31 | // Write before extents. I.e., blocks in |write_extents| must be written 32 | // by the node pointed to before the pointing node runs (presumably 33 | // b/c it reads the data written by the other node). 34 | std::vector write_extents; 35 | 36 | bool operator==(const EdgeProperties& that) const { 37 | return extents == that.extents && write_extents == that.write_extents; 38 | } 39 | }; 40 | 41 | struct Vertex { 42 | Vertex() : valid(true), index(-1), lowlink(-1) {} 43 | bool valid; 44 | 45 | typedef std::map::size_type, EdgeProperties> EdgeMap; 46 | EdgeMap out_edges; 47 | 48 | // We sometimes wish to consider a subgraph of a graph. A subgraph would have 49 | // a subset of the vertices from the graph and a subset of the edges. 50 | // When considering this vertex within a subgraph, subgraph_edges stores 51 | // the out-edges. 52 | typedef std::set::size_type> SubgraphEdgeMap; 53 | SubgraphEdgeMap subgraph_edges; 54 | 55 | // For Tarjan's algorithm: 56 | std::vector::size_type index; 57 | std::vector::size_type lowlink; 58 | 59 | // Other Vertex properties: 60 | InstallOperation op; 61 | std::string file_name; 62 | 63 | typedef std::vector::size_type Index; 64 | static const Vertex::Index kInvalidIndex = -1; 65 | }; 66 | 67 | typedef std::vector Graph; 68 | 69 | typedef std::pair Edge; 70 | 71 | const uint64_t kSparseHole = std::numeric_limits::max(); 72 | const uint64_t kTempBlockStart = 1ULL << 60; 73 | static_assert(kTempBlockStart != 0, "kTempBlockStart invalid"); 74 | 75 | } // namespace chromeos_update_engine 76 | 77 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_GRAPH_TYPES_H__ 78 | -------------------------------------------------------------------------------- /src/update_engine/extent_ranges.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 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 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_EXTENT_RANGES_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_EXTENT_RANGES_H__ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include "update_engine/delta_diff_generator.h" 13 | #include "update_engine/graph_types.h" 14 | #include "update_engine/update_metadata.pb.h" 15 | 16 | // An ExtentRanges object represents an unordered collection of extents (and 17 | // therefore blocks). Such an object may be modified by adding or subtracting 18 | // blocks (think: set addition or set subtraction). Note that ExtentRanges 19 | // ignores sparse hole extents mostly to avoid confusion between extending a 20 | // sparse hole range vs. set addition but also to ensure that the delta 21 | // generator doesn't use sparse holes as scratch space. 22 | 23 | namespace chromeos_update_engine { 24 | 25 | struct ExtentLess { 26 | bool operator()(const Extent& x, const Extent& y) const { 27 | return x.start_block() < y.start_block(); 28 | } 29 | }; 30 | 31 | Extent ExtentForRange(uint64_t start_block, uint64_t num_blocks); 32 | 33 | class ExtentRanges { 34 | public: 35 | typedef std::set ExtentSet; 36 | 37 | ExtentRanges() : blocks_(0) {} 38 | void AddBlock(uint64_t block); 39 | void SubtractBlock(uint64_t block); 40 | void AddExtent(Extent extent); 41 | void SubtractExtent(const Extent& extent); 42 | void AddExtents(const std::vector& extents); 43 | void SubtractExtents(const std::vector& extents); 44 | void AddRepeatedExtents( 45 | const ::google::protobuf::RepeatedPtrField &exts); 46 | void SubtractRepeatedExtents( 47 | const ::google::protobuf::RepeatedPtrField &exts); 48 | void AddRanges(const ExtentRanges& ranges); 49 | void SubtractRanges(const ExtentRanges& ranges); 50 | 51 | static bool ExtentsOverlapOrTouch(const Extent& a, const Extent& b); 52 | static bool ExtentsOverlap(const Extent& a, const Extent& b); 53 | 54 | // Dumps contents to the log file. Useful for debugging. 55 | void Dump() const; 56 | 57 | uint64_t blocks() const { return blocks_; } 58 | const ExtentSet& extent_set() const { return extent_set_; } 59 | 60 | // Returns an ordered vector of extents for |count| blocks, 61 | // using extents in extent_set_. The returned extents are not 62 | // removed from extent_set_. |count| must be less than or equal to 63 | // the number of blocks in this extent set. 64 | std::vector GetExtentsForBlockCount(uint64_t count) const; 65 | 66 | private: 67 | ExtentSet extent_set_; 68 | uint64_t blocks_; 69 | }; 70 | 71 | } // namespace chromeos_update_engine 72 | 73 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_EXTENT_RANGES_H__ 74 | -------------------------------------------------------------------------------- /src/update_engine/kernel_verifier_action.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 The CoreOS 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 | 5 | #include "update_engine/kernel_verifier_action.h" 6 | 7 | #include 8 | 9 | #include "update_engine/utils.h" 10 | #include "update_engine/omaha_hash_calculator.h" 11 | 12 | using std::string; 13 | 14 | namespace chromeos_update_engine { 15 | 16 | void KernelVerifierAction::PerformAction() { 17 | // Will tell the ActionProcessor we've failed if we return. 18 | ScopedActionCompleter abort_action_completer(processor_, this); 19 | abort_action_completer.set_code(kActionCodeNewKernelVerificationError); 20 | 21 | if (!HasInputObject()) { 22 | LOG(ERROR) << "KernelVerifierAction missing input object."; 23 | return; 24 | } 25 | install_plan_ = GetInputObject(); 26 | 27 | // If unset then a new kernel was never installed. 28 | if (install_plan_.new_kernel_size == 0 && 29 | install_plan_.new_kernel_hash.empty()) { 30 | if (HasOutputPipe()) 31 | SetOutputObject(install_plan_); 32 | abort_action_completer.set_code(kActionCodeSuccess); 33 | return; 34 | } 35 | 36 | off_t length = utils::FileSize(install_plan_.kernel_path); 37 | if (length < 0) { 38 | LOG(ERROR) << "Failed to determine size of kernel " 39 | << install_plan_.kernel_path; 40 | return; 41 | } 42 | 43 | if (static_cast(length) != install_plan_.new_kernel_size) { 44 | LOG(ERROR) << "Kernel verification failure: " 45 | << install_plan_.kernel_path << " is " 46 | << length << " bytes. Expected " 47 | << install_plan_.new_kernel_size; 48 | return; 49 | } 50 | 51 | OmahaHashCalculator hasher; 52 | if (length != hasher.UpdateFile(install_plan_.kernel_path, length) || 53 | !hasher.Finalize()) { 54 | LOG(ERROR) << "Failed to compute hash of kernel " 55 | << install_plan_.kernel_path; 56 | return; 57 | } 58 | 59 | if (hasher.raw_hash() != install_plan_.new_kernel_hash) { 60 | string expected_hash; 61 | if (!OmahaHashCalculator::Base64Encode( 62 | install_plan_.new_kernel_hash.data(), 63 | install_plan_.new_kernel_hash.size(), 64 | &expected_hash)) { 65 | expected_hash = ""; 66 | } 67 | LOG(ERROR) << "Kernel verification failure: " 68 | << install_plan_.kernel_path 69 | << "\nBad hash: " << hasher.hash() 70 | << "\nExpected: " << expected_hash; 71 | return; 72 | } 73 | 74 | LOG(INFO) << "Kernel size: " << length; 75 | LOG(INFO) << "Kernel hash: " << hasher.hash(); 76 | 77 | // Success! Pass along the new install_plan to the next action. 78 | if (HasOutputPipe()) 79 | SetOutputObject(install_plan_); 80 | abort_action_completer.set_code(kActionCodeSuccess); 81 | return; 82 | } 83 | 84 | } // namespace chromeos_update_engine 85 | -------------------------------------------------------------------------------- /src/files/file_util.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The Chromium 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 | 5 | #include "files/file_util.h" 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | #include "files/file_enumerator.h" 17 | #include "files/file_path.h" 18 | 19 | namespace files { 20 | 21 | bool Move(const FilePath& from_path, const FilePath& to_path) { 22 | if (from_path.ReferencesParent() || to_path.ReferencesParent()) 23 | return false; 24 | return internal::MoveUnsafe(from_path, to_path); 25 | } 26 | 27 | bool ReadFileToString(const FilePath& path, 28 | std::string* contents, 29 | size_t max_size) { 30 | if (contents) 31 | contents->clear(); 32 | if (path.ReferencesParent()) 33 | return false; 34 | FILE* file = OpenFile(path, "rb"); 35 | if (!file) { 36 | return false; 37 | } 38 | 39 | const size_t kBufferSize = 1 << 16; 40 | std::unique_ptr buf(new char[kBufferSize]); 41 | size_t len; 42 | size_t size = 0; 43 | bool read_status = true; 44 | 45 | // Many files supplied in |path| have incorrect size (proc files etc). 46 | // Hence, the file is read sequentially as opposed to a one-shot read. 47 | while ((len = fread(buf.get(), 1, kBufferSize, file)) > 0) { 48 | if (contents) 49 | contents->append(buf.get(), std::min(len, max_size - size)); 50 | 51 | if ((max_size - size) < len) { 52 | read_status = false; 53 | break; 54 | } 55 | 56 | size += len; 57 | } 58 | read_status = read_status && !ferror(file); 59 | CloseFile(file); 60 | 61 | return read_status; 62 | } 63 | 64 | bool ReadFileToString(const FilePath& path, std::string* contents) { 65 | return ReadFileToString(path, contents, std::numeric_limits::max()); 66 | } 67 | 68 | bool IsDirectoryEmpty(const FilePath& dir_path) { 69 | FileEnumerator files(dir_path, false, 70 | FileEnumerator::FILES | FileEnumerator::DIRECTORIES); 71 | if (files.Next().empty()) 72 | return true; 73 | return false; 74 | } 75 | 76 | FILE* CreateAndOpenTemporaryFile(FilePath* path) { 77 | FilePath directory; 78 | if (!GetTempDir(&directory)) 79 | return NULL; 80 | 81 | return CreateAndOpenTemporaryFileInDir(directory, path); 82 | } 83 | 84 | bool CloseFile(FILE* file) { 85 | if (file == NULL) 86 | return true; 87 | return fclose(file) == 0; 88 | } 89 | 90 | bool TruncateFile(FILE* file) { 91 | if (file == NULL) 92 | return false; 93 | long current_offset = ftell(file); 94 | if (current_offset == -1) 95 | return false; 96 | int fd = fileno(file); 97 | if (ftruncate(fd, current_offset) != 0) 98 | return false; 99 | return true; 100 | } 101 | 102 | } // namespace files 103 | -------------------------------------------------------------------------------- /src/update_engine/http_common.cc: -------------------------------------------------------------------------------- 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 3 | // found in the LICENSE file. 4 | 5 | // Implementation of common HTTP related functions. 6 | 7 | #include "macros.h" 8 | #include "update_engine/http_common.h" 9 | 10 | 11 | const char *GetHttpResponseDescription(HttpResponseCode code) { 12 | static const struct { 13 | HttpResponseCode code; 14 | const char* description; 15 | } http_response_table[] = { 16 | { kHttpResponseOk, "OK" }, 17 | { kHttpResponseCreated, "Created" }, 18 | { kHttpResponseAccepted, "Accepted" }, 19 | { kHttpResponseNonAuthInfo, "Non-Authoritative Information" }, 20 | { kHttpResponseNoContent, "No Content" }, 21 | { kHttpResponseResetContent, "Reset Content" }, 22 | { kHttpResponsePartialContent, "Partial Content" }, 23 | { kHttpResponseMultipleChoices, "Multiple Choices" }, 24 | { kHttpResponseMovedPermanently, "Moved Permanently" }, 25 | { kHttpResponseFound, "Found" }, 26 | { kHttpResponseSeeOther, "See Other" }, 27 | { kHttpResponseNotModified, "Not Modified" }, 28 | { kHttpResponseUseProxy, "Use Proxy" }, 29 | { kHttpResponseTempRedirect, "Temporary Redirect" }, 30 | { kHttpResponseBadRequest, "Bad Request" }, 31 | { kHttpResponseUnauth, "Unauthorized" }, 32 | { kHttpResponseForbidden, "Forbidden" }, 33 | { kHttpResponseNotFound, "Not Found" }, 34 | { kHttpResponseRequestTimeout, "Request Timeout" }, 35 | { kHttpResponseInternalServerError, "Internal Server Error" }, 36 | { kHttpResponseNotImplemented, "Not Implemented" }, 37 | { kHttpResponseServiceUnavailable, "Service Unavailable" }, 38 | { kHttpResponseVersionNotSupported, "HTTP Version Not Supported" }, 39 | }; 40 | 41 | bool is_found = false; 42 | size_t i; 43 | for (i = 0; i < arraysize(http_response_table); i++) 44 | if ((is_found = (http_response_table[i].code == code))) 45 | break; 46 | 47 | return (is_found ? http_response_table[i].description : "(unsupported)"); 48 | } 49 | 50 | HttpResponseCode StringToHttpResponseCode(const char *s) { 51 | return static_cast(strtoul(s, NULL, 10)); 52 | } 53 | 54 | 55 | const char *GetHttpContentTypeString(HttpContentType type) { 56 | static const struct { 57 | HttpContentType type; 58 | const char* str; 59 | } http_content_type_table[] = { 60 | { kHttpContentTypeTextXml, "text/xml" }, 61 | { kHttpContentTypeOctetStream, "application/octet-stream" }, 62 | }; 63 | 64 | bool is_found = false; 65 | size_t i; 66 | for (i = 0; i < arraysize(http_content_type_table); i++) 67 | if ((is_found = (http_content_type_table[i].type == type))) 68 | break; 69 | 70 | return (is_found ? http_content_type_table[i].str : NULL); 71 | } 72 | -------------------------------------------------------------------------------- /src/update_engine/action_processor.cc: -------------------------------------------------------------------------------- 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 3 | // found in the LICENSE file. 4 | 5 | #include "update_engine/action_processor.h" 6 | #include 7 | #include 8 | #include "update_engine/action.h" 9 | 10 | using std::string; 11 | 12 | namespace chromeos_update_engine { 13 | 14 | ActionProcessor::ActionProcessor() 15 | : current_action_(NULL), delegate_(NULL) {} 16 | 17 | ActionProcessor::~ActionProcessor() { 18 | if (IsRunning()) { 19 | StopProcessing(); 20 | } 21 | for (std::deque::iterator it = actions_.begin(); 22 | it != actions_.end(); ++it) { 23 | (*it)->SetProcessor(NULL); 24 | } 25 | } 26 | 27 | void ActionProcessor::EnqueueAction(AbstractAction* action) { 28 | actions_.push_back(action); 29 | action->SetProcessor(this); 30 | } 31 | 32 | void ActionProcessor::StartProcessing() { 33 | CHECK(!IsRunning()); 34 | if (!actions_.empty()) { 35 | current_action_ = actions_.front(); 36 | LOG(INFO) << "ActionProcessor::StartProcessing: " 37 | << current_action_->Type(); 38 | actions_.pop_front(); 39 | current_action_->PerformAction(); 40 | } 41 | } 42 | 43 | void ActionProcessor::StopProcessing() { 44 | CHECK(IsRunning()); 45 | CHECK(current_action_); 46 | current_action_->TerminateProcessing(); 47 | CHECK(current_action_); 48 | current_action_->SetProcessor(NULL); 49 | LOG(INFO) << "ActionProcessor::StopProcessing: aborted " 50 | << current_action_->Type(); 51 | current_action_ = NULL; 52 | if (delegate_) 53 | delegate_->ProcessingStopped(this); 54 | } 55 | 56 | void ActionProcessor::ActionComplete(AbstractAction* actionptr, 57 | ActionExitCode code) { 58 | CHECK_EQ(actionptr, current_action_); 59 | if (delegate_) 60 | delegate_->ActionCompleted(this, actionptr, code); 61 | string old_type = current_action_->Type(); 62 | current_action_->SetProcessor(NULL); 63 | current_action_ = NULL; 64 | if (actions_.empty()) { 65 | LOG(INFO) << "ActionProcessor::ActionComplete: finished last action of" 66 | " type " << old_type; 67 | } else if (code != kActionCodeSuccess) { 68 | LOG(INFO) << "ActionProcessor::ActionComplete: " << old_type 69 | << " action failed. Aborting processing."; 70 | actions_.clear(); 71 | } 72 | if (actions_.empty()) { 73 | LOG(INFO) << "ActionProcessor::ActionComplete: finished last action of" 74 | " type " << old_type; 75 | if (delegate_) { 76 | delegate_->ProcessingDone(this, code); 77 | } 78 | return; 79 | } 80 | current_action_ = actions_.front(); 81 | actions_.pop_front(); 82 | LOG(INFO) << "ActionProcessor::ActionComplete: finished " << old_type 83 | << ", starting " << current_action_->Type(); 84 | current_action_->PerformAction(); 85 | } 86 | 87 | } // namespace chromeos_update_engine 88 | -------------------------------------------------------------------------------- /src/update_engine/dbus_service.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 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 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_DBUS_SERVICE_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_DBUS_SERVICE_H__ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "update_engine/update_attempter.h" 15 | 16 | // Type macros: 17 | #define UPDATE_ENGINE_TYPE_SERVICE (update_engine_service_get_type()) 18 | #define UPDATE_ENGINE_SERVICE(obj) \ 19 | (G_TYPE_CHECK_INSTANCE_CAST((obj), UPDATE_ENGINE_TYPE_SERVICE, \ 20 | UpdateEngineService)) 21 | #define UPDATE_ENGINE_IS_SERVICE(obj) \ 22 | (G_TYPE_CHECK_INSTANCE_TYPE((obj), UPDATE_ENGINE_TYPE_SERVICE)) 23 | #define UPDATE_ENGINE_SERVICE_CLASS(klass) \ 24 | (G_TYPE_CHECK_CLASS_CAST((klass), UPDATE_ENGINE_TYPE_SERVICE, \ 25 | UpdateEngineService)) 26 | #define UPDATE_ENGINE_IS_SERVICE_CLASS(klass) \ 27 | (G_TYPE_CHECK_CLASS_TYPE((klass), UPDATE_ENGINE_TYPE_SERVICE)) 28 | #define UPDATE_ENGINE_SERVICE_GET_CLASS(obj) \ 29 | (G_TYPE_INSTANCE_GET_CLASS((obj), UPDATE_ENGINE_TYPE_SERVICE, \ 30 | UpdateEngineService)) 31 | 32 | G_BEGIN_DECLS 33 | 34 | struct UpdateEngineService { 35 | GObject parent_instance; 36 | 37 | chromeos_update_engine::SystemState* system_state_; 38 | }; 39 | 40 | struct UpdateEngineServiceClass { 41 | GObjectClass parent_class; 42 | }; 43 | 44 | UpdateEngineService* update_engine_service_new(void); 45 | GType update_engine_service_get_type(void); 46 | 47 | // Methods 48 | 49 | gboolean update_engine_service_attempt_update(UpdateEngineService* self, 50 | GError **error); 51 | 52 | gboolean update_engine_service_reset_status(UpdateEngineService* self, 53 | GError **error); 54 | 55 | gboolean update_engine_service_get_status(UpdateEngineService* self, 56 | int64_t* last_checked_time, 57 | double* progress, 58 | gchar** current_operation, 59 | gchar** new_version, 60 | int64_t* new_size, 61 | GError **error); 62 | 63 | gboolean update_engine_service_emit_status_update( 64 | UpdateEngineService* self, 65 | gint64 last_checked_time, 66 | gdouble progress, 67 | const gchar* current_operation, 68 | const gchar* new_version, 69 | gint64 new_size); 70 | 71 | G_END_DECLS 72 | 73 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_DBUS_SERVICE_H__ 74 | -------------------------------------------------------------------------------- /src/update_engine/install_plan.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011 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 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_INSTALL_PLAN_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_INSTALL_PLAN_H__ 7 | 8 | #include 9 | #include 10 | 11 | // InstallPlan is a simple struct that contains relevant info for many 12 | // parts of the update system about the install that should happen. 13 | namespace chromeos_update_engine { 14 | 15 | struct InstallPlan { 16 | InstallPlan(bool is_resume, 17 | const std::string& url, 18 | uint64_t payload_size, 19 | const std::string& payload_hash, 20 | const std::string& partition_path); 21 | 22 | // Default constructor: Initialize all members which don't have a class 23 | // initializer. 24 | InstallPlan(); 25 | 26 | bool operator==(const InstallPlan& that) const; 27 | bool operator!=(const InstallPlan& that) const; 28 | 29 | void Dump() const; 30 | 31 | bool is_resume; 32 | std::string download_url; // url to download from 33 | 34 | uint64_t payload_size; // size of the payload 35 | std::string payload_hash; // SHA256 hash of the payload 36 | std::string partition_path; // path to main partition device 37 | std::string kernel_path; // path to kernel image 38 | std::string pcr_policy_path; // path to pcr policy zip file 39 | 40 | // Location to copy currently running system from. 41 | std::string old_partition_path; 42 | std::string old_kernel_path; 43 | 44 | // For verifying system state prior to applying the update. The partition 45 | // hash is computed by FilesystemCopierAction(verify_hash=false) and 46 | // later validated by PayloadProcessor once it receives the manifest. 47 | std::vector old_partition_hash; 48 | std::vector old_kernel_hash; 49 | 50 | // For verifying the update applied successfully. Values filled in by 51 | // PayloadProcessor once the update payload has been verified. 52 | // FilesystemCopierAction(verify_hashes=true) computes and verifies the 53 | // partition size and hash. 54 | uint64_t new_partition_size; 55 | std::vector new_partition_hash; 56 | uint64_t new_kernel_size; 57 | std::vector new_kernel_hash; 58 | uint64_t new_pcr_policy_size; 59 | std::vector new_pcr_policy_hash; 60 | 61 | // Optional version of the update being applied. 62 | std::string display_version; 63 | 64 | // Optional arguments to pass to the post install script. Used to inform 65 | // the script about optional update procedures that ran. For example 66 | // "KERNEL=kernel_path" indicates that update_engine installed the kernel 67 | // so the post install script should not do so. 68 | std::vector postinst_args; 69 | }; 70 | 71 | } // namespace chromeos_update_engine 72 | 73 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_INSTALL_PLAN_H__ 74 | -------------------------------------------------------------------------------- /src/update_engine/topological_sort_unittest.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 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 | 5 | #include 6 | #include 7 | #include 8 | #include "update_engine/graph_types.h" 9 | #include "update_engine/topological_sort.h" 10 | 11 | using std::make_pair; 12 | using std::vector; 13 | 14 | namespace chromeos_update_engine { 15 | 16 | class TopologicalSortTest : public ::testing::Test {}; 17 | 18 | namespace { 19 | // Returns true if the value is found in vect. If found, the index is stored 20 | // in out_index if out_index is not null. 21 | template 22 | bool IndexOf(const vector& vect, 23 | const T& value, 24 | typename vector::size_type* out_index) { 25 | for (typename vector::size_type i = 0; i < vect.size(); i++) { 26 | if (vect[i] == value) { 27 | if (out_index) { 28 | *out_index = i; 29 | } 30 | return true; 31 | } 32 | } 33 | return false; 34 | } 35 | } // namespace {} 36 | 37 | TEST(TopologicalSortTest, SimpleTest) { 38 | int counter = 0; 39 | const Vertex::Index n_a = counter++; 40 | const Vertex::Index n_b = counter++; 41 | const Vertex::Index n_c = counter++; 42 | const Vertex::Index n_d = counter++; 43 | const Vertex::Index n_e = counter++; 44 | const Vertex::Index n_f = counter++; 45 | const Vertex::Index n_g = counter++; 46 | const Vertex::Index n_h = counter++; 47 | const Vertex::Index n_i = counter++; 48 | const Vertex::Index n_j = counter++; 49 | const Graph::size_type kNodeCount = counter++; 50 | 51 | Graph graph(kNodeCount); 52 | 53 | graph[n_i].out_edges.insert(make_pair(n_j, EdgeProperties())); 54 | graph[n_i].out_edges.insert(make_pair(n_c, EdgeProperties())); 55 | graph[n_i].out_edges.insert(make_pair(n_e, EdgeProperties())); 56 | graph[n_i].out_edges.insert(make_pair(n_h, EdgeProperties())); 57 | graph[n_c].out_edges.insert(make_pair(n_b, EdgeProperties())); 58 | graph[n_b].out_edges.insert(make_pair(n_a, EdgeProperties())); 59 | graph[n_e].out_edges.insert(make_pair(n_d, EdgeProperties())); 60 | graph[n_e].out_edges.insert(make_pair(n_g, EdgeProperties())); 61 | graph[n_g].out_edges.insert(make_pair(n_d, EdgeProperties())); 62 | graph[n_g].out_edges.insert(make_pair(n_f, EdgeProperties())); 63 | graph[n_d].out_edges.insert(make_pair(n_a, EdgeProperties())); 64 | 65 | vector sorted; 66 | TopologicalSort(graph, &sorted); 67 | 68 | for (Vertex::Index i = 0; i < graph.size(); i++) { 69 | vector::size_type src_index = 0; 70 | EXPECT_TRUE(IndexOf(sorted, i, &src_index)); 71 | for (Vertex::EdgeMap::const_iterator it = graph[i].out_edges.begin(); 72 | it != graph[i].out_edges.end(); ++it) { 73 | vector::size_type dst_index = 0; 74 | EXPECT_TRUE(IndexOf(sorted, it->first, &dst_index)); 75 | EXPECT_LT(dst_index, src_index); 76 | } 77 | } 78 | } 79 | 80 | } // namespace chromeos_update_engine 81 | -------------------------------------------------------------------------------- /src/update_engine/prefs_interface.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011 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 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_PREFS_INTERFACE_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_PREFS_INTERFACE_H__ 7 | 8 | #include 9 | 10 | namespace chromeos_update_engine { 11 | 12 | extern const char kPrefsCertificateReportToSendDownload[]; 13 | extern const char kPrefsCertificateReportToSendUpdate[]; 14 | extern const char kPrefsDeltaUpdateFailures[]; 15 | extern const char kPrefsManifestMetadataSize[]; 16 | extern const char kPrefsPreviousVersion[]; 17 | extern const char kPrefsResumedUpdateFailures[]; 18 | extern const char kPrefsUpdateCheckResponseHash[]; 19 | extern const char kPrefsUpdateServerCertificate[]; 20 | extern const char kPrefsUpdateStateNextDataOffset[]; 21 | extern const char kPrefsUpdateStateNextOperation[]; 22 | extern const char kPrefsUpdateStateSHA256Context[]; 23 | extern const char kPrefsUpdateStateSignatureBlob[]; 24 | extern const char kPrefsUpdateStateSignedSHA256Context[]; 25 | extern const char kPrefsPayloadAttemptNumber[]; 26 | extern const char kPrefsCurrentResponseSignature[]; 27 | extern const char kPrefsCurrentUrlIndex[]; 28 | extern const char kPrefsCurrentUrlFailureCount[]; 29 | extern const char kPrefsBackoffExpiryTime[]; 30 | extern const char kPrefsAlephVersion[]; 31 | 32 | // The prefs interface allows access to a persistent preferences 33 | // store. The two reasons for providing this as an interface are 34 | // testing as well as easier switching to a new implementation in the 35 | // future, if necessary. 36 | 37 | class PrefsInterface { 38 | public: 39 | // Gets a string |value| associated with |key|. Returns true on 40 | // success, false on failure (including when the |key| is not 41 | // present in the store). 42 | virtual bool GetString(const std::string& key, std::string* value) = 0; 43 | 44 | // Associates |key| with a string |value|. Returns true on success, 45 | // false otherwise. 46 | virtual bool SetString(const std::string& key, const std::string& value) = 0; 47 | 48 | // Gets an int64 |value| associated with |key|. Returns true on 49 | // success, false on failure (including when the |key| is not 50 | // present in the store). 51 | virtual bool GetInt64(const std::string& key, int64_t* value) = 0; 52 | 53 | // Associates |key| with an int64 |value|. Returns true on success, 54 | // false otherwise. 55 | virtual bool SetInt64(const std::string& key, const int64_t value) = 0; 56 | 57 | // Returns true if the setting exists (i.e. a file with the given key 58 | // exists in the prefs directory) 59 | virtual bool Exists(const std::string& key) = 0; 60 | 61 | // Returns true if successfully deleted the file corresponding to 62 | // this key. Calling with non-existent keys does nothing. 63 | virtual bool Delete(const std::string& key) = 0; 64 | 65 | virtual ~PrefsInterface() {} 66 | }; 67 | 68 | } // namespace chromeos_update_engine 69 | 70 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_PREFS_INTERFACE_H__ 71 | -------------------------------------------------------------------------------- /src/update_engine/tarjan_unittest.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 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 | 5 | #include 6 | #include 7 | #include 8 | #include "update_engine/graph_types.h" 9 | #include "update_engine/tarjan.h" 10 | #include "update_engine/utils.h" 11 | 12 | using std::make_pair; 13 | using std::pair; 14 | using std::set; 15 | using std::string; 16 | using std::vector; 17 | 18 | namespace chromeos_update_engine { 19 | 20 | class TarjanAlgorithmTest : public ::testing::Test {}; 21 | 22 | TEST(TarjanAlgorithmTest, SimpleTest) { 23 | const Vertex::Index n_a = 0; 24 | const Vertex::Index n_b = 1; 25 | const Vertex::Index n_c = 2; 26 | const Vertex::Index n_d = 3; 27 | const Vertex::Index n_e = 4; 28 | const Vertex::Index n_f = 5; 29 | const Vertex::Index n_g = 6; 30 | const Vertex::Index n_h = 7; 31 | const Graph::size_type kNodeCount = 8; 32 | 33 | Graph graph(kNodeCount); 34 | 35 | graph[n_a].out_edges.insert(make_pair(n_e, EdgeProperties())); 36 | graph[n_a].out_edges.insert(make_pair(n_f, EdgeProperties())); 37 | graph[n_b].out_edges.insert(make_pair(n_a, EdgeProperties())); 38 | graph[n_c].out_edges.insert(make_pair(n_d, EdgeProperties())); 39 | graph[n_d].out_edges.insert(make_pair(n_e, EdgeProperties())); 40 | graph[n_d].out_edges.insert(make_pair(n_f, EdgeProperties())); 41 | graph[n_e].out_edges.insert(make_pair(n_b, EdgeProperties())); 42 | graph[n_e].out_edges.insert(make_pair(n_c, EdgeProperties())); 43 | graph[n_e].out_edges.insert(make_pair(n_f, EdgeProperties())); 44 | graph[n_f].out_edges.insert(make_pair(n_g, EdgeProperties())); 45 | graph[n_g].out_edges.insert(make_pair(n_h, EdgeProperties())); 46 | graph[n_h].out_edges.insert(make_pair(n_g, EdgeProperties())); 47 | 48 | TarjanAlgorithm tarjan; 49 | 50 | for (Vertex::Index i = n_a; i <= n_e; i++) { 51 | vector vertex_indexes; 52 | tarjan.Execute(i, &graph, &vertex_indexes); 53 | 54 | EXPECT_EQ(5, vertex_indexes.size()); 55 | EXPECT_TRUE(utils::VectorContainsValue(vertex_indexes, n_a)); 56 | EXPECT_TRUE(utils::VectorContainsValue(vertex_indexes, n_b)); 57 | EXPECT_TRUE(utils::VectorContainsValue(vertex_indexes, n_c)); 58 | EXPECT_TRUE(utils::VectorContainsValue(vertex_indexes, n_d)); 59 | EXPECT_TRUE(utils::VectorContainsValue(vertex_indexes, n_e)); 60 | } 61 | 62 | { 63 | vector vertex_indexes; 64 | tarjan.Execute(n_f, &graph, &vertex_indexes); 65 | 66 | EXPECT_EQ(1, vertex_indexes.size()); 67 | EXPECT_TRUE(utils::VectorContainsValue(vertex_indexes, n_f)); 68 | } 69 | 70 | for (Vertex::Index i = n_g; i <= n_h; i++) { 71 | vector vertex_indexes; 72 | tarjan.Execute(i, &graph, &vertex_indexes); 73 | 74 | EXPECT_EQ(2, vertex_indexes.size()); 75 | EXPECT_TRUE(utils::VectorContainsValue(vertex_indexes, n_g)); 76 | EXPECT_TRUE(utils::VectorContainsValue(vertex_indexes, n_h)); 77 | } 78 | } 79 | 80 | } // namespace chromeos_update_engine 81 | -------------------------------------------------------------------------------- /src/strings/string_split.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The Chromium 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 | 5 | #include "strings/string_split.h" 6 | 7 | #include 8 | #include 9 | 10 | namespace strings { 11 | 12 | namespace { 13 | 14 | const std::string kWhitespaceASCII = { 15 | 0x09, // CHARACTER TABULATION 16 | 0x0A, // LINE FEED (LF) 17 | 0x0B, // LINE TABULATION 18 | 0x0C, // FORM FEED (FF) 19 | 0x0D, // CARRIAGE RETURN (CR) 20 | 0x20, // SPACE 21 | }; 22 | 23 | std::vector Split(const std::string& str, 24 | const std::string& delim, 25 | bool trim_whitespace) { 26 | std::vector r; 27 | size_t begin_index = 0; 28 | while (true) { 29 | size_t end_index = str.find(delim, begin_index); 30 | if (end_index == std::string::npos) { 31 | std::string tmp = str.substr(begin_index); 32 | if (trim_whitespace) 33 | tmp = TrimWhitespace(tmp); 34 | // Avoid converting an empty or all-whitespace source string into a vector 35 | // of one empty string. 36 | if (!r.empty() || !tmp.empty()) 37 | r.push_back(std::move(tmp)); 38 | return r; 39 | } 40 | std::string tmp = str.substr(begin_index, end_index - begin_index); 41 | if (trim_whitespace) 42 | tmp = TrimWhitespace(tmp); 43 | r.push_back(std::move(tmp)); 44 | begin_index = end_index + delim.size(); 45 | } 46 | } 47 | 48 | std::string Trim(const std::string& input, const std::string& trim_chars) { 49 | size_t first_good_char = input.find_first_not_of(trim_chars); 50 | size_t last_good_char = input.find_last_not_of(trim_chars); 51 | 52 | if (first_good_char == std::string::npos) 53 | first_good_char = input.length(); 54 | 55 | return input.substr(first_good_char, last_good_char - first_good_char + 1); 56 | } 57 | 58 | } // namespace 59 | 60 | std::vector SplitWords(const std::string& str) { 61 | std::vector result; 62 | 63 | for (auto it = str.begin(); it != str.end();) { 64 | auto first = std::find_if(it, str.end(), [](char c) { 65 | return kWhitespaceASCII.find(c) == std::string::npos; 66 | }); 67 | auto last = std::find_if(first, str.end(), [](char c) { 68 | return kWhitespaceASCII.find(c) != std::string::npos; 69 | }); 70 | if (first != last) 71 | result.push_back(std::string(first, last)); 72 | 73 | it = last; 74 | } 75 | 76 | return result; 77 | } 78 | 79 | std::vector SplitAndTrim(const std::string& str, 80 | const std::string &delim) { 81 | return Split(str, delim, true); 82 | } 83 | 84 | std::vector SplitAndTrim(const std::string& str, char delim) { 85 | return Split(str, std::string{delim}, true); 86 | } 87 | 88 | std::vector SplitDontTrim(const std::string& str, char delim) { 89 | return Split(str, std::string{delim}, false); 90 | } 91 | 92 | std::string TrimWhitespace(const std::string& input) { 93 | return Trim(input, kWhitespaceASCII); 94 | } 95 | 96 | } // namespace strings 97 | -------------------------------------------------------------------------------- /code-of-conduct.md: -------------------------------------------------------------------------------- 1 | ## CoreOS Community Code of Conduct 2 | 3 | ### Contributor Code of Conduct 4 | 5 | As contributors and maintainers of this project, and in the interest of 6 | fostering an open and welcoming community, we pledge to respect all people who 7 | contribute through reporting issues, posting feature requests, updating 8 | documentation, submitting pull requests or patches, and other activities. 9 | 10 | We are committed to making participation in this project a harassment-free 11 | experience for everyone, regardless of level of experience, gender, gender 12 | identity and expression, sexual orientation, disability, personal appearance, 13 | body size, race, ethnicity, age, religion, or nationality. 14 | 15 | Examples of unacceptable behavior by participants include: 16 | 17 | * The use of sexualized language or imagery 18 | * Personal attacks 19 | * Trolling or insulting/derogatory comments 20 | * Public or private harassment 21 | * Publishing others' private information, such as physical or electronic addresses, without explicit permission 22 | * Other unethical or unprofessional conduct. 23 | 24 | Project maintainers have the right and responsibility to remove, edit, or 25 | reject comments, commits, code, wiki edits, issues, and other contributions 26 | that are not aligned to this Code of Conduct. By adopting this Code of Conduct, 27 | project maintainers commit themselves to fairly and consistently applying these 28 | principles to every aspect of managing this project. Project maintainers who do 29 | not follow or enforce the Code of Conduct may be permanently removed from the 30 | project team. 31 | 32 | This code of conduct applies both within project spaces and in public spaces 33 | when an individual is representing the project or its community. 34 | 35 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 36 | reported by contacting a project maintainer, Brandon Philips 37 | , and/or Rithu John . 38 | 39 | This Code of Conduct is adapted from the Contributor Covenant 40 | (http://contributor-covenant.org), version 1.2.0, available at 41 | http://contributor-covenant.org/version/1/2/0/ 42 | 43 | ### CoreOS Events Code of Conduct 44 | 45 | CoreOS events are working conferences intended for professional networking and 46 | collaboration in the CoreOS community. Attendees are expected to behave 47 | according to professional standards and in accordance with their employer’s 48 | policies on appropriate workplace behavior. 49 | 50 | While at CoreOS events or related social networking opportunities, attendees 51 | should not engage in discriminatory or offensive speech or actions including 52 | but not limited to gender, sexuality, race, age, disability, or religion. 53 | Speakers should be especially aware of these concerns. 54 | 55 | CoreOS does not condone any statements by speakers contrary to these standards. 56 | CoreOS reserves the right to deny entrance and/or eject from an event (without 57 | refund) any individual found to be engaging in discriminatory or offensive 58 | speech or actions. 59 | 60 | Please bring any concerns to the immediate attention of designated on-site 61 | staff, Brandon Philips , and/or Rithu John . 62 | -------------------------------------------------------------------------------- /src/files/scoped_temp_dir_unittest.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011 The Chromium 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 | 5 | #include 6 | 7 | #include 8 | 9 | #include "files/file_util.h" 10 | #include "files/scoped_temp_dir.h" 11 | 12 | namespace files { 13 | 14 | TEST(ScopedTempDir, FullPath) { 15 | FilePath test_path; 16 | CreateNewTempDirectory(FILE_PATH_LITERAL("scoped_temp_dir"), &test_path); 17 | 18 | // Against an existing dir, it should get destroyed when leaving scope. 19 | EXPECT_TRUE(DirectoryExists(test_path)); 20 | { 21 | ScopedTempDir dir; 22 | EXPECT_TRUE(dir.Set(test_path)); 23 | EXPECT_TRUE(dir.IsValid()); 24 | } 25 | EXPECT_FALSE(DirectoryExists(test_path)); 26 | 27 | { 28 | ScopedTempDir dir; 29 | EXPECT_TRUE(dir.Set(test_path)); 30 | // Now the dir doesn't exist, so ensure that it gets created. 31 | EXPECT_TRUE(DirectoryExists(test_path)); 32 | // When we call Release(), it shouldn't get destroyed when leaving scope. 33 | FilePath path = dir.Take(); 34 | EXPECT_EQ(path.value(), test_path.value()); 35 | EXPECT_FALSE(dir.IsValid()); 36 | } 37 | EXPECT_TRUE(DirectoryExists(test_path)); 38 | 39 | // Clean up. 40 | { 41 | ScopedTempDir dir; 42 | EXPECT_TRUE(dir.Set(test_path)); 43 | } 44 | EXPECT_FALSE(DirectoryExists(test_path)); 45 | } 46 | 47 | TEST(ScopedTempDir, TempDir) { 48 | // In this case, just verify that a directory was created and that it's a 49 | // child of TempDir. 50 | FilePath test_path; 51 | { 52 | ScopedTempDir dir; 53 | EXPECT_TRUE(dir.CreateUniqueTempDir()); 54 | test_path = dir.path(); 55 | EXPECT_TRUE(DirectoryExists(test_path)); 56 | FilePath tmp_dir; 57 | EXPECT_TRUE(GetTempDir(&tmp_dir)); 58 | EXPECT_TRUE(test_path.value().find(tmp_dir.value()) != std::string::npos); 59 | } 60 | EXPECT_FALSE(DirectoryExists(test_path)); 61 | } 62 | 63 | TEST(ScopedTempDir, UniqueTempDirUnderPath) { 64 | // Create a path which will contain a unique temp path. 65 | FilePath base_path; 66 | ASSERT_TRUE(CreateNewTempDirectory(FILE_PATH_LITERAL("base_dir"), 67 | &base_path)); 68 | 69 | FilePath test_path; 70 | { 71 | ScopedTempDir dir; 72 | EXPECT_TRUE(dir.CreateUniqueTempDirUnderPath(base_path)); 73 | test_path = dir.path(); 74 | EXPECT_TRUE(DirectoryExists(test_path)); 75 | EXPECT_TRUE(base_path.IsParent(test_path)); 76 | EXPECT_TRUE(test_path.value().find(base_path.value()) != std::string::npos); 77 | } 78 | EXPECT_FALSE(DirectoryExists(test_path)); 79 | DeleteFile(base_path, true); 80 | } 81 | 82 | TEST(ScopedTempDir, MultipleInvocations) { 83 | ScopedTempDir dir; 84 | EXPECT_TRUE(dir.CreateUniqueTempDir()); 85 | EXPECT_FALSE(dir.CreateUniqueTempDir()); 86 | EXPECT_TRUE(dir.Delete()); 87 | EXPECT_TRUE(dir.CreateUniqueTempDir()); 88 | EXPECT_FALSE(dir.CreateUniqueTempDir()); 89 | ScopedTempDir other_dir; 90 | EXPECT_TRUE(other_dir.Set(dir.Take())); 91 | EXPECT_TRUE(dir.CreateUniqueTempDir()); 92 | EXPECT_FALSE(dir.CreateUniqueTempDir()); 93 | EXPECT_FALSE(other_dir.CreateUniqueTempDir()); 94 | } 95 | 96 | } // namespace files 97 | -------------------------------------------------------------------------------- /Jenkinsfile: -------------------------------------------------------------------------------- 1 | #!groovy 2 | 3 | properties([ 4 | buildDiscarder(logRotator(daysToKeepStr: '30', numToKeepStr: '50')), 5 | pipelineTriggers([pollSCM('H/20 * * * *')]) 6 | ]) 7 | 8 | node('amd64 && coreos && sudo') { 9 | stage('Prepare') { 10 | sh 'sudo rm -fr coreos_developer_container.bin source wd' 11 | 12 | dir('source') { 13 | checkout scm 14 | } 15 | 16 | sh '''#!/bin/bash -ex 17 | version_url="https://alpha.release.core-os.net/amd64-usr/current" 18 | container_url="$version_url/coreos_developer_container.bin.bz2" 19 | 20 | # Download and verify the developer container image. 21 | gpg2 --recv-keys 04127D0BFABEC8871FFB2CCE50E0885593D2DCB4 || : 22 | curl --fail --location "$container_url" | 23 | tee >(bzip2 --decompress > coreos_developer_container.bin) | 24 | gpg2 --verify <(curl --location --silent "$container_url.sig") - 25 | 26 | # Define the Jenkins user in the container, and install build dependencies. 27 | sudo mount -o offset=2097152,x-mount.mkdir coreos_developer_container.bin wd 28 | trap 'sudo umount -d wd' EXIT 29 | sudo cp /etc/resolv.conf wd/etc/ 30 | sudo chroot wd /bin/bash -ex << EOF 31 | mount -t devtmpfs devtmpfs /dev 32 | mount -t proc proc /proc 33 | mount -t sysfs sysfs /sys 34 | trap 'umount /dev /proc /sys' EXIT 35 | echo $(getent passwd $(id -u)) >> /etc/passwd 36 | echo $(getent group $(id -g)) >> /etc/group 37 | usermod -aG sudo $USER 38 | cat << EOG > /etc/pam.d/sudo 39 | account optional pam_permit.so 40 | auth optional pam_permit.so 41 | password optional pam_permit.so 42 | session optional pam_permit.so 43 | EOG 44 | emerge-gitclone 45 | emerge -j4 -v dev-cpp/gmock dev-util/pkgconfig sys-devel/autoconf 46 | mkdir /usr/src 47 | EOF 48 | sudo mv source wd/usr/src/update_engine 49 | ''' 50 | } 51 | 52 | stage('Build') { 53 | sh '''#!/bin/bash -ex 54 | sudo mount -o offset=2097152 coreos_developer_container.bin wd 55 | trap 'sudo umount -d wd' EXIT 56 | sudo chroot --userspec=$(id -u):$(id -g) wd /bin/bash -ex << 'EOF' 57 | sudo mount -t devtmpfs devtmpfs /dev 58 | sudo mount -t proc proc /proc 59 | sudo mount -t sysfs sysfs /sys 60 | trap 'sudo umount /dev /proc /sys' EXIT 61 | cd /usr/src/update_engine 62 | ./autogen.sh 63 | ./configure --enable-debug 64 | make -j4 all 65 | EOF 66 | ''' 67 | } 68 | 69 | stage('Test') { 70 | def rc = sh returnStatus: true, script: '''#!/bin/bash -ex 71 | sudo mount -o offset=2097152 coreos_developer_container.bin wd 72 | trap 'sudo umount -d wd' EXIT 73 | sudo chroot --userspec=$(id -u):$(id -g) wd /bin/bash -ex << 'EOF' 74 | sudo mount -t devtmpfs devtmpfs /dev 75 | sudo mount -t proc proc /proc 76 | sudo mount -t sysfs sysfs /sys 77 | trap 'sudo umount /dev /proc /sys' EXIT 78 | cd /usr/src/update_engine 79 | make -j4 \ 80 | update_engine_unittests \ 81 | test_http_server \ 82 | unittest_key.pub.pem \ 83 | unittest_key2.pub.pem 84 | GTEST_OUTPUT="xml:$PWD/user.xml" ./run_unittests_as_user 85 | sudo GTEST_OUTPUT="xml:$PWD/root.xml" ./run_unittests_as_root 86 | EOF 87 | sudo mv wd/usr/src/update_engine source 88 | ''' 89 | 90 | archiveArtifacts 'source/root.xml,source/user.xml' 91 | 92 | junit 'source/root.xml,source/user.xml' 93 | 94 | currentBuild.result = rc == 0 ? 'SUCCESS' : 'FAILURE' 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/update_engine/extent_mapper_unittest.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 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 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | #include "macros.h" 16 | #include "update_engine/extent_mapper.h" 17 | #include "update_engine/graph_types.h" 18 | #include "update_engine/utils.h" 19 | 20 | using std::set; 21 | using std::string; 22 | using std::vector; 23 | 24 | namespace chromeos_update_engine { 25 | 26 | class ExtentMapperTest : public ::testing::Test {}; 27 | 28 | TEST(ExtentMapperTest, RunAsRootSimpleTest) { 29 | // It's hard to have a concrete test for extent mapping without including 30 | // a specific filesystem image. 31 | // In lieu of this, we do a weak test: make sure the extents of the unittest 32 | // executable are consistent and they match with the size of the file. 33 | const string kFilename = "/proc/self/exe"; 34 | 35 | uint32_t block_size = 0; 36 | EXPECT_TRUE(extent_mapper::GetFilesystemBlockSize(kFilename, &block_size)); 37 | EXPECT_GT(block_size, 0); 38 | 39 | vector extents; 40 | 41 | ASSERT_TRUE(extent_mapper::ExtentsForFileFibmap(kFilename, &extents)); 42 | 43 | EXPECT_FALSE(extents.empty()); 44 | set blocks; 45 | 46 | for (vector::const_iterator it = extents.begin(); 47 | it != extents.end(); ++it) { 48 | for (uint64_t block = it->start_block(); 49 | block < it->start_block() + it->num_blocks(); 50 | block++) { 51 | EXPECT_FALSE(blocks.count(block)); 52 | blocks.insert(block); 53 | } 54 | } 55 | 56 | struct stat stbuf; 57 | EXPECT_EQ(0, stat(kFilename.c_str(), &stbuf)); 58 | EXPECT_EQ(blocks.size(), (stbuf.st_size + block_size - 1)/block_size); 59 | } 60 | 61 | TEST(ExtentMapperTest, RunAsRootSparseFileTest) { 62 | // Create sparse file with one real block, then two sparse ones, then a real 63 | // block at the end. 64 | const char tmp_name_template[] = 65 | "/tmp/ExtentMapperTest.RunAsRootSparseFileTest.XXXXXX"; 66 | char buf[sizeof(tmp_name_template)]; 67 | strncpy(buf, tmp_name_template, sizeof(buf)); 68 | static_assert(sizeof(buf) > 8, "buf size incorrect"); 69 | ASSERT_EQ('\0', buf[sizeof(buf) - 1]); 70 | 71 | int fd = mkstemp(buf); 72 | ASSERT_GE(fd, 0); 73 | 74 | uint32_t block_size = 0; 75 | EXPECT_TRUE(extent_mapper::GetFilesystemBlockSize(buf, &block_size)); 76 | EXPECT_GT(block_size, 0); 77 | 78 | EXPECT_EQ(1, pwrite(fd, "x", 1, 0)); 79 | EXPECT_EQ(1, pwrite(fd, "x", 1, 3 * block_size)); 80 | close(fd); 81 | 82 | vector extents; 83 | EXPECT_TRUE(extent_mapper::ExtentsForFileFibmap(buf, &extents)); 84 | unlink(buf); 85 | EXPECT_EQ(3, extents.size()); 86 | EXPECT_EQ(1, extents[0].num_blocks()); 87 | EXPECT_EQ(2, extents[1].num_blocks()); 88 | EXPECT_EQ(1, extents[2].num_blocks()); 89 | EXPECT_NE(kSparseHole, extents[0].start_block()); 90 | EXPECT_EQ(kSparseHole, extents[1].start_block()); 91 | EXPECT_NE(kSparseHole, extents[2].start_block()); 92 | EXPECT_NE(extents[2].start_block(), extents[0].start_block()); 93 | } 94 | 95 | } // namespace chromeos_update_engine 96 | -------------------------------------------------------------------------------- /src/update_engine/payload_state_interface.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 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 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_PAYLOAD_STATE_INTERFACE_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_PAYLOAD_STATE_INTERFACE_H__ 7 | 8 | #include 9 | #include 10 | 11 | #include "update_engine/action_processor.h" 12 | #include "update_engine/omaha_response.h" 13 | 14 | namespace chromeos_update_engine { 15 | 16 | // Describes the methods that need to be implemented by the PayloadState class. 17 | // This interface has been carved out to support mocking of the PayloadState 18 | // object. 19 | class PayloadStateInterface { 20 | public: 21 | // Sets the internal payload state based on the given Omaha response. This 22 | // response could be the same or different from the one for which we've stored 23 | // the internal state. If it's different, then this method resets all the 24 | // internal state corresponding to the old response. Since the Omaha response 25 | // has a lot of fields that are not related to payload state, it uses only 26 | // a subset of the fields in the Omaha response to compare equality. 27 | virtual void SetResponse(const OmahaResponse& response) = 0; 28 | 29 | // This method should be called whenever we have completed downloading all 30 | // the bytes of a payload and have verified that its size and hash match the 31 | // expected values. We use this notificaiton to increment the payload attempt 32 | // number so that the throttle the next attempt to download the same payload 33 | // (in case there's an error in subsequent steps such as post-install) 34 | // appropriately. 35 | virtual void DownloadComplete() = 0; 36 | 37 | // This method should be called whenever we receive new bytes from the 38 | // network for the current payload. We use this notification to reset the 39 | // failure count for a given URL since receipt of some bytes means we are 40 | // able to make forward progress with the current URL. 41 | virtual void DownloadProgress(size_t count) = 0; 42 | 43 | // This method should be called whenever an update attempt fails with the 44 | // given error code. We use this notification to update the payload state 45 | // depending on the type of the error that happened. 46 | virtual void UpdateFailed(ActionExitCode error) = 0; 47 | 48 | // Returns true if we should backoff the current download attempt. 49 | // False otherwise. 50 | virtual bool ShouldBackoffDownload() = 0; 51 | 52 | // Returns the currently stored response "signature". The signature is a 53 | // subset of fields that are of interest to the PayloadState behavior. 54 | virtual std::string GetResponseSignature() = 0; 55 | 56 | // Returns the payload attempt number. 57 | virtual uint32_t GetPayloadAttemptNumber() = 0; 58 | 59 | // Returns the current URL index. 60 | virtual uint32_t GetUrlIndex() = 0; 61 | 62 | // Returns the current URL's failure count. 63 | virtual uint32_t GetUrlFailureCount() = 0; 64 | 65 | // Returns the expiry time for the current backoff period. 66 | virtual std::chrono::system_clock::time_point GetBackoffExpiryTime() = 0; 67 | }; 68 | 69 | } // namespace chromeos_update_engine 70 | 71 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_PAYLOAD_STATE_INTERFACE_H__ 72 | -------------------------------------------------------------------------------- /src/strings/string_number_conversions.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 | // Copyright (c) 2015 The CoreOS Authors. 3 | // Use of this source code is governed by a BSD-style license that can be 4 | // found in the LICENSE file. 5 | 6 | #include "strings/string_number_conversions.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace strings { 14 | 15 | bool StringToInt(const std::string& input, int *output) { 16 | const char *start = input.c_str(); 17 | char *end; 18 | long o; 19 | 20 | errno = 0; 21 | o = strtol(start, &end, 10); 22 | // Check bounds for when long is 64 bits 23 | if (o < INT_MIN) { 24 | *output = INT_MIN; 25 | return false; 26 | } 27 | else if (o > INT_MAX) { 28 | *output = INT_MAX; 29 | return false; 30 | } 31 | else 32 | *output = o; 33 | 34 | if (errno) 35 | return false; 36 | 37 | // Check length instead of *end != '\0' in case input contains extra nulls. 38 | size_t l = end - start; 39 | if (l != input.length()) 40 | return false; 41 | 42 | // Do not tolerate extra leading chars like strtol does. 43 | if (!isdigit(*start) && *start != '-') 44 | return false; 45 | 46 | return true; 47 | } 48 | 49 | bool StringToUint(const std::string& input, unsigned int *output) { 50 | const char *start = input.c_str(); 51 | 52 | // strtoul accepts negative numbers as valid, we do not. 53 | for (size_t i = 0; i < input.length(); i++) { 54 | if (isspace(start[i])) 55 | continue; 56 | else if (start[i] == '-') { 57 | *output = 0; 58 | return false; 59 | } 60 | else 61 | break; 62 | } 63 | 64 | errno = 0; 65 | char *end; 66 | unsigned long o = strtoul(start, &end, 10); 67 | // Check bounds for when long is 64 bits 68 | if (o > UINT_MAX) { 69 | *output = UINT_MAX; 70 | return false; 71 | } 72 | else 73 | *output = o; 74 | 75 | if (errno) 76 | return false; 77 | 78 | // Check length instead of *end != '\0' in case input contains extra nulls. 79 | size_t l = end - start; 80 | if (l != input.length()) 81 | return false; 82 | 83 | // Do not tolerate extra leading chars like strtol does. 84 | if (!isdigit(*start)) 85 | return false; 86 | 87 | return true; 88 | } 89 | 90 | bool StringToInt64(const std::string& input, int64_t* output) { 91 | const char *start = input.c_str(); 92 | char *end; 93 | 94 | errno = 0; 95 | *output = strtoll(start, &end, 10); 96 | if (errno) 97 | return false; 98 | 99 | // Check length instead of *end != '\0' in case input contains extra nulls. 100 | size_t l = end - start; 101 | if (l != input.length()) 102 | return false; 103 | 104 | // Do not tolerate extra leading chars like strtol does. 105 | if (!isdigit(*start) && *start != '-') 106 | return false; 107 | 108 | return true; 109 | } 110 | 111 | std::string HexEncode(const void* bytes, size_t size) { 112 | static const char kHexChars[] = "0123456789ABCDEF"; 113 | 114 | // Each input byte creates two output hex characters. 115 | std::string ret(size * 2, '\0'); 116 | 117 | for (size_t i = 0; i < size; ++i) { 118 | char b = reinterpret_cast(bytes)[i]; 119 | ret[(i * 2)] = kHexChars[(b >> 4) & 0xf]; 120 | ret[(i * 2) + 1] = kHexChars[b & 0xf]; 121 | } 122 | return ret; 123 | } 124 | 125 | } // namespace base 126 | -------------------------------------------------------------------------------- /src/update_engine/file_writer.h: -------------------------------------------------------------------------------- 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 3 | // found in the LICENSE file. 4 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_FILE_WRITER_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_FILE_WRITER_H__ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "update_engine/action_processor.h" 14 | #include "update_engine/utils.h" 15 | 16 | // FileWriter is a class that is used to (synchronously, for now) write to 17 | // a file. This file is a thin wrapper around open/write/close system calls, 18 | // but provides and interface that can be customized by subclasses that wish 19 | // to filter the data. 20 | 21 | namespace chromeos_update_engine { 22 | 23 | class FileWriter { 24 | public: 25 | FileWriter() {} 26 | virtual ~FileWriter() {} 27 | 28 | // Wrapper around open. Returns 0 on success or -errno on error. 29 | virtual int Open() = 0; 30 | 31 | // Wrapper around write. Returns true if all requested bytes 32 | // were written, or false on any error, reguardless of progress. 33 | virtual bool Write(const void* bytes, size_t count) = 0; 34 | 35 | // Same as the Write method above but returns a detailed |error| code 36 | // in addition if the returned value is false. By default this method 37 | // returns kActionExitDownloadWriteError as the error code, but subclasses 38 | // can override if they wish to return more specific error codes. 39 | virtual bool Write(const void* bytes, 40 | size_t count, 41 | ActionExitCode* error) { 42 | *error = kActionCodeDownloadWriteError; 43 | return Write(bytes, count); 44 | } 45 | 46 | // Wrapper around close. Returns 0 on success or -errno on error. 47 | virtual int Close() = 0; 48 | 49 | private: 50 | DISALLOW_COPY_AND_ASSIGN(FileWriter); 51 | }; 52 | 53 | // Direct file writer is probably the simplest FileWriter implementation. 54 | // It calls the system calls directly. 55 | 56 | class DirectFileWriter : public FileWriter { 57 | public: 58 | DirectFileWriter( 59 | const std::string path, 60 | int flags = O_TRUNC | O_WRONLY | O_CREAT | O_LARGEFILE, 61 | mode_t mode = 0644) 62 | : path_(path), 63 | flags_(flags), 64 | mode_(mode), 65 | fd_(-1) {} 66 | DirectFileWriter() = delete; 67 | virtual ~DirectFileWriter() {} 68 | 69 | virtual int Open(); 70 | virtual bool Write(const void* bytes, size_t count); 71 | virtual int Close(); 72 | 73 | int fd() const { return fd_; } 74 | 75 | private: 76 | const std::string path_; 77 | const int flags_; 78 | const mode_t mode_; 79 | int fd_; 80 | 81 | DISALLOW_COPY_AND_ASSIGN(DirectFileWriter); 82 | }; 83 | 84 | class ScopedFileWriterCloser { 85 | public: 86 | explicit ScopedFileWriterCloser(FileWriter* writer) : writer_(writer) {} 87 | ~ScopedFileWriterCloser() { 88 | int err = writer_->Close(); 89 | if (err) 90 | LOG(ERROR) << "FileWriter::Close failed: " 91 | << utils::ErrnoNumberAsString(-err); 92 | } 93 | private: 94 | FileWriter* writer_; 95 | 96 | DISALLOW_COPY_AND_ASSIGN(ScopedFileWriterCloser); 97 | }; 98 | 99 | } // namespace chromeos_update_engine 100 | 101 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_FILE_WRITER_H__ 102 | -------------------------------------------------------------------------------- /src/update_engine/omaha_response_handler_action.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011 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 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_OMAHA_RESPONSE_HANDLER_ACTION_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_OMAHA_RESPONSE_HANDLER_ACTION_H__ 7 | 8 | #include 9 | 10 | #include // for FRIEND_TEST 11 | 12 | #include "update_engine/action.h" 13 | #include "update_engine/install_plan.h" 14 | #include "update_engine/omaha_request_action.h" 15 | #include "update_engine/system_state.h" 16 | 17 | // This class reads in an Omaha response and converts what it sees into 18 | // an install plan which is passed out. 19 | 20 | namespace chromeos_update_engine { 21 | 22 | class OmahaResponseHandlerAction; 23 | 24 | template<> 25 | class ActionTraits { 26 | public: 27 | typedef OmahaResponse InputObjectType; 28 | typedef InstallPlan OutputObjectType; 29 | }; 30 | 31 | class OmahaResponseHandlerAction : public Action { 32 | public: 33 | static const char kDeadlineFile[]; 34 | 35 | OmahaResponseHandlerAction(SystemState* system_state); 36 | typedef ActionTraits::InputObjectType 37 | InputObjectType; 38 | typedef ActionTraits::OutputObjectType 39 | OutputObjectType; 40 | void PerformAction(); 41 | 42 | // This is a synchronous action, and thus TerminateProcessing() should 43 | // never be called 44 | void TerminateProcessing() { CHECK(false); } 45 | 46 | // For unit-testing 47 | void set_boot_device(const std::string& boot_device) { 48 | install_plan_.old_partition_path = boot_device; 49 | } 50 | 51 | bool GotNoUpdateResponse() const { return got_no_update_response_; } 52 | const InstallPlan& install_plan() const { return install_plan_; } 53 | 54 | // Debugging/logging 55 | static std::string StaticType() { return "OmahaResponseHandlerAction"; } 56 | std::string Type() const { return StaticType(); } 57 | void set_key_path(const std::string& path) { key_path_ = path; } 58 | 59 | private: 60 | FRIEND_TEST(UpdateAttempterTest, CreatePendingErrorEventResumedTest); 61 | 62 | // Assumes you want to install on the "other" device, where the other 63 | // device is what you get if you swap 3 for 4 or vice versa for the 64 | // number at the end of the boot device. E.g., /dev/sda4 -> /dev/sda3 65 | static bool GetInstallDev(const std::string& boot_dev, 66 | std::string* install_dev); 67 | 68 | // Selects the kernel path associated with the given partition path. 69 | // E.g., /dev/sda4 -> /boot/coreos/vmlinuz-a 70 | static bool GetKernelPath(const std::string& part_path, 71 | std::string* kernel_path); 72 | 73 | // Select the pcr policy path associated with the given partition. 74 | static bool GetPCRPolicyPath(const std::string& part_path, 75 | std::string* policy_path); 76 | 77 | // Global system context. 78 | SystemState* system_state_; 79 | 80 | // The install plan, if we have an update. 81 | InstallPlan install_plan_; 82 | 83 | // True only if we got a response and the response said no updates 84 | bool got_no_update_response_; 85 | 86 | // Public key path to use for payload verification. 87 | std::string key_path_; 88 | 89 | DISALLOW_COPY_AND_ASSIGN(OmahaResponseHandlerAction); 90 | }; 91 | 92 | } // namespace chromeos_update_engine 93 | 94 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_OMAHA_RESPONSE_HANDLER_ACTION_H__ 95 | -------------------------------------------------------------------------------- /src/update_engine/action_pipe.h: -------------------------------------------------------------------------------- 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 3 | // found in the LICENSE file. 4 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_PIPE_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_PIPE_H__ 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | #include "macros.h" 19 | 20 | // The structure of these classes (Action, ActionPipe, ActionProcessor, etc.) 21 | // is based on the KSAction* classes from the Google Update Engine code at 22 | // http://code.google.com/p/update-engine/ . The author of this file sends 23 | // a big thanks to that team for their high quality design, implementation, 24 | // and documentation. 25 | 26 | // This class serves as a temporary holding area for an object passed out 27 | // from one Action and into another Action. It's templated so that it may 28 | // contain any type of object that an Action outputs/inputs. Actions 29 | // cannot be bonded (i.e., connected with a pipe) if their output/input 30 | // object types differ (a compiler error will result). 31 | // 32 | // An ActionPipe is generally created with the Bond() method and owned by 33 | // the two Action objects. a shared_ptr is used so that when the last Action 34 | // pointing to an ActionPipe dies, the ActionPipe dies, too. 35 | 36 | namespace chromeos_update_engine { 37 | 38 | // Used by Actions an InputObjectType or OutputObjectType to specify that 39 | // for that type, no object is taken/given. 40 | class NoneType {}; 41 | 42 | template 43 | class Action; 44 | 45 | template 46 | class ActionPipe { 47 | public: 48 | virtual ~ActionPipe() {} 49 | 50 | // This should be called by an Action on its input pipe. 51 | // Returns a reference to the stored object. 52 | const ObjectType& contents() const { return contents_; } 53 | 54 | // This should be called by an Action on its output pipe. 55 | // Stores a copy of the passed object in this pipe. 56 | void set_contents(const ObjectType& contents) { contents_ = contents; } 57 | 58 | // Bonds two Actions together with a new ActionPipe. The ActionPipe is 59 | // jointly owned by the two Actions and will be automatically destroyed 60 | // when the last Action is destroyed. 61 | template 62 | static void Bond(FromAction* from, ToAction* to) { 63 | std::shared_ptr > pipe( 64 | new ActionPipe); 65 | from->set_out_pipe(pipe); 66 | 67 | to->set_in_pipe(pipe); // If you get an error on this line, then 68 | // it most likely means that the From object's OutputObjectType is 69 | // different from the To object's InputObjectType. 70 | } 71 | 72 | private: 73 | ObjectType contents_; 74 | 75 | // The ctor is private. This is because this class should construct itself 76 | // via the static Bond() method. 77 | ActionPipe() {} 78 | DISALLOW_COPY_AND_ASSIGN(ActionPipe); 79 | }; 80 | 81 | // Utility function 82 | template 83 | void BondActions(FromAction* from, ToAction* to) { 84 | static_assert(std::is_same::value, 86 | "OutputObjectType doesn't match InputObjectType"); 87 | ActionPipe::Bond(from, to); 88 | } 89 | 90 | } // namespace chromeos_update_engine 91 | 92 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_PIPE_H__ 93 | -------------------------------------------------------------------------------- /src/update_engine/postinstall_runner_action.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011 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 | 5 | #include "update_engine/postinstall_runner_action.h" 6 | #include 7 | #include 8 | #include 9 | #include "update_engine/subprocess.h" 10 | #include "update_engine/utils.h" 11 | 12 | namespace chromeos_update_engine { 13 | 14 | using std::string; 15 | using std::vector; 16 | 17 | namespace { 18 | const char kPostinstallScript[] = "/postinst"; 19 | } 20 | 21 | void PostinstallRunnerAction::PerformAction() { 22 | CHECK(HasInputObject()); 23 | const InstallPlan install_plan = GetInputObject(); 24 | const string install_device = install_plan.partition_path; 25 | ScopedActionCompleter completer(processor_, this); 26 | 27 | // Make mountpoint. 28 | TEST_AND_RETURN(utils::MakeTempDirectory("/tmp/au_postint_mount.XXXXXX", 29 | &temp_rootfs_dir_)); 30 | ScopedDirRemover temp_dir_remover(temp_rootfs_dir_); 31 | 32 | unsigned long mountflags = MS_RDONLY; 33 | int rc = mount(install_device.c_str(), 34 | temp_rootfs_dir_.c_str(), 35 | "ext2", 36 | mountflags, 37 | NULL); 38 | if (rc < 0) { 39 | LOG(INFO) << "Failed to mount install part as ext2. Trying ext3."; 40 | rc = mount(install_device.c_str(), 41 | temp_rootfs_dir_.c_str(), 42 | "ext3", 43 | mountflags, 44 | NULL); 45 | } 46 | if (rc < 0) { 47 | LOG(ERROR) << "Unable to mount destination device " << install_device 48 | << " onto " << temp_rootfs_dir_; 49 | return; 50 | } 51 | 52 | temp_dir_remover.set_should_remove(false); 53 | completer.set_should_complete(false); 54 | 55 | // Runs the postinstall script asynchronously to free up the main loop while 56 | // it's running. 57 | vector command; 58 | command.push_back(temp_rootfs_dir_ + kPostinstallScript); 59 | command.push_back(install_device); 60 | command.insert(command.end(), 61 | install_plan.postinst_args.begin(), 62 | install_plan.postinst_args.end()); 63 | 64 | if (!Subprocess::Get().Exec(command, StaticCompletePostinstall, this)) { 65 | CompletePostinstall(1); 66 | } 67 | } 68 | 69 | void PostinstallRunnerAction::CompletePostinstall(int return_code) { 70 | ScopedActionCompleter completer(processor_, this); 71 | ScopedTempUnmounter temp_unmounter(temp_rootfs_dir_); 72 | if (return_code != 0) { 73 | LOG(ERROR) << "Postinst command failed with code: " << return_code; 74 | if (return_code == 3) { 75 | // This special return code means that we tried to update firmware, 76 | // but couldn't because we booted from FW B, and we need to reboot 77 | // to get back to FW A. 78 | completer.set_code(kActionCodePostinstallBootedFromFirmwareB); 79 | } 80 | return; 81 | } 82 | 83 | LOG(INFO) << "Postinst command succeeded"; 84 | CHECK(HasInputObject()); 85 | const InstallPlan install_plan = GetInputObject(); 86 | 87 | if (HasOutputPipe()) 88 | SetOutputObject(install_plan); 89 | 90 | completer.set_code(kActionCodeSuccess); 91 | } 92 | 93 | void PostinstallRunnerAction::StaticCompletePostinstall(int return_code, 94 | const string& output, 95 | void* p) { 96 | reinterpret_cast(p)->CompletePostinstall( 97 | return_code); 98 | } 99 | 100 | } // namespace chromeos_update_engine 101 | -------------------------------------------------------------------------------- /src/update_engine/subprocess.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011 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 | 5 | #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_SUBPROCESS_H__ 6 | #define CHROMEOS_PLATFORM_UPDATE_ENGINE_SUBPROCESS_H__ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | #include "macros.h" 17 | 18 | // The Subprocess class is a singleton. It's used to spawn off a subprocess 19 | // and get notified when the subprocess exits. The result of Exec() can 20 | // be saved and used to cancel the callback request. If you know you won't 21 | // call CancelExec(), you may safely lose the return value from Exec(). 22 | 23 | namespace chromeos_update_engine { 24 | 25 | class Subprocess { 26 | public: 27 | typedef void(*ExecCallback)(int return_code, 28 | const std::string& output, 29 | void *p); 30 | 31 | static void Init() { 32 | CHECK(!subprocess_singleton_); 33 | subprocess_singleton_ = new Subprocess; 34 | } 35 | 36 | // Returns a tag > 0 on success. 37 | uint32_t Exec(const std::vector& cmd, 38 | ExecCallback callback, 39 | void* p); 40 | 41 | // Used to cancel the callback. The process will still run to completion. 42 | void CancelExec(uint32_t tag); 43 | 44 | // Executes a command synchronously. Returns true on success. If |stdout| is 45 | // non-null, the process output is stored in it, otherwise the output is 46 | // logged. Note that stderr is redirected to stdout. 47 | static bool SynchronousExecFlags(const std::vector& cmd, 48 | GSpawnFlags flags, 49 | int* return_code, 50 | std::string* stdout); 51 | static bool SynchronousExec(const std::vector& cmd, 52 | int* return_code, 53 | std::string* stdout); 54 | 55 | // Gets the one instance 56 | static Subprocess& Get() { 57 | return *subprocess_singleton_; 58 | } 59 | 60 | // Returns true iff there is at least one subprocess we're waiting on. 61 | bool SubprocessInFlight(); 62 | 63 | private: 64 | struct SubprocessRecord { 65 | SubprocessRecord() 66 | : tag(0), 67 | callback(NULL), 68 | callback_data(NULL), 69 | gioout(NULL), 70 | gioout_tag(0) {} 71 | uint32_t tag; 72 | ExecCallback callback; 73 | void* callback_data; 74 | GIOChannel* gioout; 75 | guint gioout_tag; 76 | std::string stdout; 77 | }; 78 | 79 | Subprocess() {} 80 | 81 | // Callback for when any subprocess terminates. This calls the user 82 | // requested callback. 83 | static void GChildExitedCallback(GPid pid, gint status, gpointer data); 84 | 85 | // Callback which runs in the child before exec to redirect stderr onto 86 | // stdout. 87 | static void GRedirectStderrToStdout(gpointer user_data); 88 | 89 | // Callback which runs whenever there is input available on the subprocess 90 | // stdout pipe. 91 | static gboolean GStdoutWatchCallback(GIOChannel* source, 92 | GIOCondition condition, 93 | gpointer data); 94 | 95 | // The global instance. 96 | static Subprocess* subprocess_singleton_; 97 | 98 | // A map from the asynchronous subprocess tag (see Exec) to the subprocess 99 | // record structure for all active asynchronous subprocesses. 100 | std::map > subprocess_records_; 101 | 102 | DISALLOW_COPY_AND_ASSIGN(Subprocess); 103 | }; 104 | 105 | } // namespace chromeos_update_engine 106 | 107 | #endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_SUBPROCESS_H__ 108 | -------------------------------------------------------------------------------- /src/update_engine/zip_unittest.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011 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 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #include "update_engine/bzip.h" 14 | #include "update_engine/test_utils.h" 15 | #include "update_engine/utils.h" 16 | 17 | using std::string; 18 | using std::vector; 19 | 20 | namespace chromeos_update_engine { 21 | 22 | template 23 | class ZipTest : public ::testing::Test { 24 | public: 25 | bool ZipDecompress(const std::vector& in, 26 | std::vector* out) const = 0; 27 | bool ZipCompress(const std::vector& in, 28 | std::vector* out) const = 0; 29 | bool ZipCompressString(const std::string& str, 30 | std::vector* out) const = 0; 31 | bool ZipDecompressString(const std::string& str, 32 | std::vector* out) const = 0; 33 | }; 34 | 35 | class BzipTest {}; 36 | 37 | template <> 38 | class ZipTest : public ::testing::Test { 39 | public: 40 | bool ZipDecompress(const std::vector& in, 41 | std::vector* out) const { 42 | return BzipDecompress(in, out); 43 | } 44 | bool ZipCompress(const std::vector& in, 45 | std::vector* out) const { 46 | return BzipCompress(in, out); 47 | } 48 | bool ZipCompressString(const std::string& str, 49 | std::vector* out) const { 50 | return BzipCompressString(str, out); 51 | } 52 | bool ZipDecompressString(const std::string& str, 53 | std::vector* out) const { 54 | return BzipDecompressString(str, out); 55 | } 56 | }; 57 | 58 | typedef ::testing::Types ZipTestTypes; 59 | TYPED_TEST_CASE(ZipTest, ZipTestTypes); 60 | 61 | 62 | 63 | TYPED_TEST(ZipTest, SimpleTest) { 64 | string in("this should compress well xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 65 | "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 66 | "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 67 | "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 68 | "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 69 | "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); 70 | vector out; 71 | EXPECT_TRUE(this->ZipCompressString(in, &out)); 72 | EXPECT_LT(out.size(), in.size()); 73 | EXPECT_GT(out.size(), 0); 74 | vector decompressed; 75 | EXPECT_TRUE(this->ZipDecompress(out, &decompressed)); 76 | EXPECT_EQ(in.size(), decompressed.size()); 77 | EXPECT_TRUE(!memcmp(in.data(), &decompressed[0], in.size())); 78 | } 79 | 80 | TYPED_TEST(ZipTest, PoorCompressionTest) { 81 | string in(reinterpret_cast(kRandomString), 82 | sizeof(kRandomString)); 83 | vector out; 84 | EXPECT_TRUE(this->ZipCompressString(in, &out)); 85 | EXPECT_GT(out.size(), in.size()); 86 | string out_string(&out[0], out.size()); 87 | vector decompressed; 88 | EXPECT_TRUE(this->ZipDecompressString(out_string, &decompressed)); 89 | EXPECT_EQ(in.size(), decompressed.size()); 90 | EXPECT_TRUE(!memcmp(in.data(), &decompressed[0], in.size())); 91 | } 92 | 93 | TYPED_TEST(ZipTest, MalformedZipTest) { 94 | string in(reinterpret_cast(kRandomString), 95 | sizeof(kRandomString)); 96 | vector out; 97 | EXPECT_FALSE(this->ZipDecompressString(in, &out)); 98 | } 99 | 100 | TYPED_TEST(ZipTest, EmptyInputsTest) { 101 | string in; 102 | vector out; 103 | EXPECT_TRUE(this->ZipDecompressString(in, &out)); 104 | EXPECT_EQ(0, out.size()); 105 | 106 | EXPECT_TRUE(this->ZipCompressString(in, &out)); 107 | EXPECT_EQ(0, out.size()); 108 | } 109 | 110 | } // namespace chromeos_update_engine 111 | -------------------------------------------------------------------------------- /src/update_engine/dbus_service.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 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 | 5 | #include "update_engine/dbus_service.h" 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include "update_engine/marshal.glibmarshal.h" 12 | #include "update_engine/omaha_request_params.h" 13 | #include "update_engine/utils.h" 14 | 15 | using std::string; 16 | 17 | G_DEFINE_TYPE(UpdateEngineService, update_engine_service, G_TYPE_OBJECT) 18 | 19 | static void update_engine_service_finalize(GObject* object) { 20 | G_OBJECT_CLASS(update_engine_service_parent_class)->finalize(object); 21 | } 22 | 23 | static guint status_update_signal = 0; 24 | 25 | static void update_engine_service_class_init(UpdateEngineServiceClass* klass) { 26 | GObjectClass *object_class; 27 | object_class = G_OBJECT_CLASS(klass); 28 | object_class->finalize = update_engine_service_finalize; 29 | 30 | status_update_signal = g_signal_new( 31 | "status_update", 32 | G_OBJECT_CLASS_TYPE(klass), 33 | G_SIGNAL_RUN_LAST, 34 | 0, // 0 == no class method associated 35 | NULL, // Accumulator 36 | NULL, // Accumulator data 37 | update_engine_VOID__INT64_DOUBLE_STRING_STRING_INT64, 38 | G_TYPE_NONE, // Return type 39 | 5, // param count: 40 | G_TYPE_INT64, 41 | G_TYPE_DOUBLE, 42 | G_TYPE_STRING, 43 | G_TYPE_STRING, 44 | G_TYPE_INT64); 45 | } 46 | 47 | static void update_engine_service_init(UpdateEngineService* object) { 48 | } 49 | 50 | UpdateEngineService* update_engine_service_new(void) { 51 | return reinterpret_cast( 52 | g_object_new(UPDATE_ENGINE_TYPE_SERVICE, NULL)); 53 | } 54 | 55 | gboolean update_engine_service_attempt_update(UpdateEngineService* self, 56 | GError **error) { 57 | LOG(INFO) << "Attempting interactive update"; 58 | self->system_state_->update_attempter()->CheckForUpdate(true); 59 | return TRUE; 60 | } 61 | 62 | gboolean update_engine_service_reset_status(UpdateEngineService* self, 63 | GError **error) { 64 | *error = NULL; 65 | return self->system_state_->update_attempter()->ResetStatus(); 66 | } 67 | 68 | 69 | gboolean update_engine_service_get_status(UpdateEngineService* self, 70 | int64_t* last_checked_time, 71 | double* progress, 72 | gchar** current_operation, 73 | gchar** new_version, 74 | int64_t* new_size, 75 | GError **error) { 76 | string current_op; 77 | string new_version_str; 78 | 79 | CHECK(self->system_state_->update_attempter()->GetStatus(last_checked_time, 80 | progress, 81 | ¤t_op, 82 | &new_version_str, 83 | new_size)); 84 | 85 | *current_operation = g_strdup(current_op.c_str()); 86 | *new_version = g_strdup(new_version_str.c_str()); 87 | if (!(*current_operation && *new_version)) { 88 | *error = NULL; 89 | return FALSE; 90 | } 91 | return TRUE; 92 | } 93 | 94 | gboolean update_engine_service_emit_status_update( 95 | UpdateEngineService* self, 96 | gint64 last_checked_time, 97 | gdouble progress, 98 | const gchar* current_operation, 99 | const gchar* new_version, 100 | gint64 new_size) { 101 | g_signal_emit(self, 102 | status_update_signal, 103 | 0, 104 | last_checked_time, 105 | progress, 106 | current_operation, 107 | new_version, 108 | new_size); 109 | return TRUE; 110 | } 111 | -------------------------------------------------------------------------------- /src/update_engine/bzip.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 The Chromium 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 | 5 | #include "update_engine/bzip.h" 6 | #include 7 | #include 8 | #include 9 | #include "update_engine/utils.h" 10 | 11 | using std::max; 12 | using std::string; 13 | using std::vector; 14 | 15 | namespace chromeos_update_engine { 16 | 17 | namespace { 18 | 19 | // BzipData compresses or decompresses the input to the output. 20 | // Returns true on success. 21 | // Use one of BzipBuffToBuff*ompress as the template parameter to BzipData(). 22 | int BzipBuffToBuffDecompress(char* out, 23 | uint32_t* out_length, 24 | const char* in, 25 | uint32_t in_length) { 26 | return BZ2_bzBuffToBuffDecompress(out, 27 | out_length, 28 | const_cast(in), 29 | in_length, 30 | 0, // Silent verbosity 31 | 0); // Normal algorithm 32 | } 33 | 34 | int BzipBuffToBuffCompress(char* out, 35 | uint32_t* out_length, 36 | const char* in, 37 | uint32_t in_length) { 38 | return BZ2_bzBuffToBuffCompress(out, 39 | out_length, 40 | const_cast(in), 41 | in_length, 42 | 9, // Best compression 43 | 0, // Silent verbosity 44 | 0); // Default work factor 45 | } 46 | 47 | template 51 | bool BzipData(const char* const in, 52 | const int32_t in_size, 53 | vector* const out) { 54 | TEST_AND_RETURN_FALSE(out); 55 | out->clear(); 56 | if (in_size == 0) { 57 | return true; 58 | } 59 | // Try increasing buffer size until it works 60 | size_t buf_size = in_size; 61 | out->resize(buf_size); 62 | 63 | for (;;) { 64 | uint32_t data_size = buf_size; 65 | int rc = F(&(*out)[0], &data_size, in, in_size); 66 | TEST_AND_RETURN_FALSE(rc == BZ_OUTBUFF_FULL || rc == BZ_OK); 67 | if (rc == BZ_OK) { 68 | // we're done! 69 | out->resize(data_size); 70 | return true; 71 | } 72 | 73 | // Data didn't fit; double the buffer size. 74 | buf_size *= 2; 75 | out->resize(buf_size); 76 | } 77 | } 78 | 79 | } // namespace {} 80 | 81 | bool BzipDecompress(const std::vector& in, std::vector* out) { 82 | return BzipData(&in[0], 83 | static_cast(in.size()), 84 | out); 85 | } 86 | 87 | bool BzipCompress(const std::vector& in, std::vector* out) { 88 | return BzipData(&in[0], in.size(), out); 89 | } 90 | 91 | namespace { 92 | template* const out)> 95 | bool BzipString(const std::string& str, 96 | std::vector* out) { 97 | TEST_AND_RETURN_FALSE(out); 98 | vector temp; 99 | TEST_AND_RETURN_FALSE(F(str.data(), 100 | str.size(), 101 | &temp)); 102 | out->clear(); 103 | out->insert(out->end(), temp.begin(), temp.end()); 104 | return true; 105 | } 106 | } // namespace {} 107 | 108 | bool BzipCompressString(const std::string& str, 109 | std::vector* out) { 110 | return BzipString >(str, out); 111 | } 112 | 113 | bool BzipDecompressString(const std::string& str, 114 | std::vector* out) { 115 | return BzipString >(str, out); 116 | } 117 | 118 | } // namespace chromeos_update_engine 119 | --------------------------------------------------------------------------------