blob: 679ee6125807c29a608804572725e52a76b87c33 [file] [log] [blame]
Gilad Arnold6dbbd392012-07-10 16:19:11 -07001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
adlr@google.com3defe6a2009-12-04 20:57:17 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Gilad Arnoldcf175a02014-07-10 16:48:47 -07005#ifndef UPDATE_ENGINE_FILESYSTEM_COPIER_ACTION_H_
6#define UPDATE_ENGINE_FILESYSTEM_COPIER_ACTION_H_
adlr@google.com3defe6a2009-12-04 20:57:17 +00007
8#include <sys/stat.h>
9#include <sys/types.h>
Darin Petkov698d0412010-10-13 10:59:44 -070010
adlr@google.com3defe6a2009-12-04 20:57:17 +000011#include <string>
Andrew de los Reyesc7020782010-04-28 10:46:04 -070012#include <vector>
Darin Petkov698d0412010-10-13 10:59:44 -070013
Andrew de los Reyesc7020782010-04-28 10:46:04 -070014#include <gio/gio.h>
adlr@google.com3defe6a2009-12-04 20:57:17 +000015#include <glib.h>
Darin Petkov698d0412010-10-13 10:59:44 -070016#include <gtest/gtest_prod.h> // for FRIEND_TEST
17
adlr@google.com3defe6a2009-12-04 20:57:17 +000018#include "update_engine/action.h"
19#include "update_engine/install_plan.h"
Darin Petkov698d0412010-10-13 10:59:44 -070020#include "update_engine/omaha_hash_calculator.h"
adlr@google.com3defe6a2009-12-04 20:57:17 +000021
22// This action will only do real work if it's a delta update. It will
Andrew de los Reyesc7020782010-04-28 10:46:04 -070023// copy the root partition to install partition, and then terminate.
adlr@google.com3defe6a2009-12-04 20:57:17 +000024
25namespace chromeos_update_engine {
26
Alex Deymo42432912013-07-12 20:21:15 -070027class SystemState;
adlr@google.com3defe6a2009-12-04 20:57:17 +000028
Chris Sosad317e402013-06-12 13:47:09 -070029class FilesystemCopierAction : public InstallPlanAction {
adlr@google.com3defe6a2009-12-04 20:57:17 +000030 public:
Alex Deymo42432912013-07-12 20:21:15 -070031 FilesystemCopierAction(SystemState* system_state,
32 bool copying_kernel_install_path,
33 bool verify_hash);
Darin Petkovc2e4a7d2010-12-02 14:47:06 -080034
Alex Deymo610277e2014-11-11 21:18:11 -080035 void PerformAction() override;
36 void TerminateProcessing() override;
adlr@google.com3defe6a2009-12-04 20:57:17 +000037
Ben Chan2add7d72012-10-08 19:28:37 -070038 // Used for testing. Return true if Cleanup() has not yet been called due
39 // to a callback upon the completion or cancellation of the copier action.
40 // A test should wait until IsCleanupPending() returns false before
41 // terminating the glib main loop.
42 bool IsCleanupPending() const;
43
adlr@google.com3defe6a2009-12-04 20:57:17 +000044 // Used for testing, so we can copy from somewhere other than root
Darin Petkovc2e4a7d2010-12-02 14:47:06 -080045 void set_copy_source(const std::string& path) { copy_source_ = path; }
adlr@google.com3defe6a2009-12-04 20:57:17 +000046
47 // Debugging/logging
48 static std::string StaticType() { return "FilesystemCopierAction"; }
Alex Deymo610277e2014-11-11 21:18:11 -080049 std::string Type() const override { return StaticType(); }
adlr@google.com3defe6a2009-12-04 20:57:17 +000050
51 private:
Darin Petkov698d0412010-10-13 10:59:44 -070052 friend class FilesystemCopierActionTest;
53 FRIEND_TEST(FilesystemCopierActionTest, RunAsRootDetermineFilesystemSizeTest);
54
Darin Petkovc2e4a7d2010-12-02 14:47:06 -080055 // Ping-pong buffers generally cycle through the following states:
Darin Petkov3aefa862010-12-07 14:45:00 -080056 // Empty->Reading->Full->Writing->Empty. In hash verification mode the state
57 // is never set to Writing.
Darin Petkovc2e4a7d2010-12-02 14:47:06 -080058 enum BufferState {
59 kBufferStateEmpty,
60 kBufferStateReading,
61 kBufferStateFull,
62 kBufferStateWriting
63 };
Darin Petkov698d0412010-10-13 10:59:44 -070064
Darin Petkovc2e4a7d2010-12-02 14:47:06 -080065 // Callbacks from glib when the read/write operation is done.
66 void AsyncReadReadyCallback(GObject *source_object, GAsyncResult *res);
67 static void StaticAsyncReadReadyCallback(GObject *source_object,
68 GAsyncResult *res,
69 gpointer user_data);
70
71 void AsyncWriteReadyCallback(GObject *source_object, GAsyncResult *res);
72 static void StaticAsyncWriteReadyCallback(GObject *source_object,
73 GAsyncResult *res,
74 gpointer user_data);
75
76 // Based on the state of the ping-pong buffers spawns appropriate read/write
77 // actions asynchronously.
78 void SpawnAsyncActions();
79
80 // Cleans up all the variables we use for async operations and tells the
Darin Petkov3aefa862010-12-07 14:45:00 -080081 // ActionProcessor we're done w/ |code| as passed in. |cancelled_| should be
Darin Petkovc2e4a7d2010-12-02 14:47:06 -080082 // true if TerminateProcessing() was called.
David Zeuthena99981f2013-04-29 13:42:47 -070083 void Cleanup(ErrorCode code);
Darin Petkov698d0412010-10-13 10:59:44 -070084
85 // Determine, if possible, the source file system size to avoid copying the
86 // whole partition. Currently this supports only the root file system assuming
87 // it's ext3-compatible.
88 void DetermineFilesystemSize(int fd);
89
Andrew de los Reyesf9185172010-05-03 11:07:05 -070090 // If true, this action is copying to the kernel_install_path from
91 // the install plan, otherwise it's copying just to the install_path.
92 const bool copying_kernel_install_path_;
Darin Petkov698d0412010-10-13 10:59:44 -070093
Darin Petkov3aefa862010-12-07 14:45:00 -080094 // If true, this action is running in applied update hash verification mode --
95 // it computes a hash for the target install path and compares it against the
96 // expected value.
97 const bool verify_hash_;
98
Andrew de los Reyesc7020782010-04-28 10:46:04 -070099 // The path to copy from. If empty (the default), the source is from the
100 // passed in InstallPlan.
Andrew de los Reyes4fe15d02009-12-10 19:01:36 -0800101 std::string copy_source_;
adlr@google.com3defe6a2009-12-04 20:57:17 +0000102
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700103 // If non-null, these are GUnixInputStream objects for the opened
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700104 // source/destination partitions.
105 GInputStream* src_stream_;
106 GOutputStream* dst_stream_;
Darin Petkov698d0412010-10-13 10:59:44 -0700107
Darin Petkovc2e4a7d2010-12-02 14:47:06 -0800108 // Ping-pong buffers for storing data we read/write. Only one buffer is being
109 // read at a time and only one buffer is being written at a time.
110 std::vector<char> buffer_[2];
Darin Petkov698d0412010-10-13 10:59:44 -0700111
Darin Petkovc2e4a7d2010-12-02 14:47:06 -0800112 // The state of each buffer.
113 BufferState buffer_state_[2];
Darin Petkov698d0412010-10-13 10:59:44 -0700114
Darin Petkovc2e4a7d2010-12-02 14:47:06 -0800115 // Number of valid elements in |buffer_| if its state is kBufferStateFull.
116 std::vector<char>::size_type buffer_valid_size_[2];
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700117
Darin Petkovc2e4a7d2010-12-02 14:47:06 -0800118 // The cancellable objects for the in-flight async calls.
119 GCancellable* canceller_[2];
120
121 bool read_done_; // true if reached EOF on the input stream.
122 bool failed_; // true if the action has failed.
123 bool cancelled_; // true if the action has been cancelled.
Andrew de los Reyesc7020782010-04-28 10:46:04 -0700124
adlr@google.com3defe6a2009-12-04 20:57:17 +0000125 // The install plan we're passed in via the input pipe.
126 InstallPlan install_plan_;
Darin Petkov698d0412010-10-13 10:59:44 -0700127
128 // Calculates the hash of the copied data.
129 OmahaHashCalculator hasher_;
130
131 // Copies and hashes this many bytes from the head of the input stream. This
132 // field is initialized when the action is started and decremented as more
133 // bytes get copied.
134 int64_t filesystem_size_;
135
Alex Deymo42432912013-07-12 20:21:15 -0700136 // The global context for update_engine.
137 SystemState* system_state_;
138
adlr@google.com3defe6a2009-12-04 20:57:17 +0000139 DISALLOW_COPY_AND_ASSIGN(FilesystemCopierAction);
140};
141
142} // namespace chromeos_update_engine
143
Gilad Arnoldcf175a02014-07-10 16:48:47 -0700144#endif // UPDATE_ENGINE_FILESYSTEM_COPIER_ACTION_H_