Amin Hassani | a69f32e | 2020-03-30 15:20:42 -0700 | [diff] [blame] | 1 | // Copyright 2020 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 DLCSERVICE_DLC_H_ |
| 6 | #define DLCSERVICE_DLC_H_ |
| 7 | |
Amin Hassani | 8664998 | 2020-03-31 16:03:37 -0700 | [diff] [blame] | 8 | #include <map> |
Amin Hassani | 40c0f11 | 2020-04-15 09:55:00 -0700 | [diff] [blame] | 9 | #include <memory> |
Amin Hassani | 8664998 | 2020-03-31 16:03:37 -0700 | [diff] [blame] | 10 | #include <set> |
Amin Hassani | a69f32e | 2020-03-30 15:20:42 -0700 | [diff] [blame] | 11 | #include <string> |
Andrew | f67a781 | 2020-05-07 10:48:00 -0700 | [diff] [blame] | 12 | #include <utility> |
Jae Hoon Kim | 9a27d15 | 2020-04-10 12:50:14 -0700 | [diff] [blame] | 13 | #include <vector> |
Amin Hassani | a69f32e | 2020-03-30 15:20:42 -0700 | [diff] [blame] | 14 | |
| 15 | #include <base/files/file_path.h> |
Amin Hassani | 8664998 | 2020-03-31 16:03:37 -0700 | [diff] [blame] | 16 | #include <brillo/errors/error.h> |
Amin Hassani | a69f32e | 2020-03-30 15:20:42 -0700 | [diff] [blame] | 17 | #include <dbus/dlcservice/dbus-constants.h> |
| 18 | #include <dlcservice/proto_bindings/dlcservice.pb.h> |
Amin Hassani | aa38c79 | 2020-04-06 15:52:44 -0700 | [diff] [blame] | 19 | #include <gtest/gtest_prod.h> // for FRIEND_TEST |
Amin Hassani | a69f32e | 2020-03-30 15:20:42 -0700 | [diff] [blame] | 20 | #include <libimageloader/manifest.h> |
| 21 | #include <chromeos/dbus/service_constants.h> |
| 22 | |
Amin Hassani | 8664998 | 2020-03-31 16:03:37 -0700 | [diff] [blame] | 23 | #include "dlcservice/boot/boot_slot.h" |
Amin Hassani | 40c0f11 | 2020-04-15 09:55:00 -0700 | [diff] [blame] | 24 | #include "dlcservice/ref_count.h" |
Amin Hassani | a69f32e | 2020-03-30 15:20:42 -0700 | [diff] [blame] | 25 | |
Amin Hassani | a69f32e | 2020-03-30 15:20:42 -0700 | [diff] [blame] | 26 | namespace dlcservice { |
| 27 | |
Amin Hassani | 8664998 | 2020-03-31 16:03:37 -0700 | [diff] [blame] | 28 | // |DlcId| is the ID of the DLC. |
| 29 | using DlcId = std::string; |
| 30 | |
Amin Hassani | a69f32e | 2020-03-30 15:20:42 -0700 | [diff] [blame] | 31 | class DlcBase { |
| 32 | public: |
Vyshu Khota | 32388f9 | 2020-11-10 09:13:29 -0800 | [diff] [blame] | 33 | explicit DlcBase(DlcId id) : id_(std::move(id)) {} |
Amin Hassani | a69f32e | 2020-03-30 15:20:42 -0700 | [diff] [blame] | 34 | virtual ~DlcBase() = default; |
| 35 | |
Jae Hoon Kim | 0c2b6cd | 2020-04-30 13:23:16 -0700 | [diff] [blame] | 36 | // Returns the list of directories related to a DLC for deletion. |
| 37 | static std::vector<base::FilePath> GetPathsToDelete(const DlcId& id); |
| 38 | |
Amin Hassani | a69f32e | 2020-03-30 15:20:42 -0700 | [diff] [blame] | 39 | // Initializes the DLC. This should be called right after creating the DLC |
| 40 | // object. |
| 41 | bool Initialize(); |
| 42 | |
Jae Hoon Kim | e567b9e | 2020-04-08 14:43:59 -0700 | [diff] [blame] | 43 | // Returns the ID of the DLC. |
Amin Hassani | 4ca7e1c | 2020-04-29 13:01:33 -0700 | [diff] [blame] | 44 | const DlcId& GetId() const; |
Jae Hoon Kim | e567b9e | 2020-04-08 14:43:59 -0700 | [diff] [blame] | 45 | |
Amin Hassani | d5fc8b2 | 2020-04-29 12:44:52 -0700 | [diff] [blame] | 46 | // Returns the human readable name of the DLC. |
| 47 | const std::string& GetName() const; |
| 48 | |
| 49 | // Returns the description of the DLC. |
| 50 | const std::string& GetDescription() const; |
| 51 | |
Amin Hassani | a69f32e | 2020-03-30 15:20:42 -0700 | [diff] [blame] | 52 | // Returns the current state of the DLC. |
| 53 | DlcState GetState() const; |
| 54 | |
| 55 | // Returns the root directory inside a mounted DLC module. |
| 56 | base::FilePath GetRoot() const; |
| 57 | |
| 58 | // Returns true if the DLC is currently being installed. |
| 59 | bool IsInstalling() const; |
| 60 | |
| 61 | // Returns true if the DLC is already installed and mounted. |
| 62 | bool IsInstalled() const; |
| 63 | |
Amin Hassani | f27aac0 | 2020-04-23 21:56:26 -0700 | [diff] [blame] | 64 | // Returns true if the DLC is marked verified. |
| 65 | bool IsVerified() const; |
Jae Hoon Kim | 0d057fb | 2020-04-13 17:44:38 -0700 | [diff] [blame] | 66 | |
Amin Hassani | d5fc8b2 | 2020-04-29 12:44:52 -0700 | [diff] [blame] | 67 | // Returns true if the DLC has any content on disk that is taking space. This |
| 68 | // means mainly if it has images on disk. |
| 69 | bool HasContent() const; |
| 70 | |
| 71 | // Returns the amount of disk space this DLC is using right now. |
| 72 | uint64_t GetUsedBytesOnDisk() const; |
| 73 | |
Jae Hoon Kim | 0d4ff62 | 2020-05-14 14:47:40 -0700 | [diff] [blame] | 74 | // Returns true if the DLC has a boolean true for 'preload-allowed' |
Amin Hassani | a69f32e | 2020-03-30 15:20:42 -0700 | [diff] [blame] | 75 | // attribute in the manifest for the given |id| and |package|. |
| 76 | bool IsPreloadAllowed() const; |
| 77 | |
Amin Hassani | 9a3f20c | 2020-05-25 16:38:33 -0700 | [diff] [blame] | 78 | // Creates the DLC image based on the fields from the manifest if the DLC is |
| 79 | // not installed. If the DLC image exists or is installed already, some |
| 80 | // verifications are passed to validate that the DLC is mounted. |
Amin Hassani | a69f32e | 2020-03-30 15:20:42 -0700 | [diff] [blame] | 81 | // Initializes the installation like creating the necessary files, etc. |
Amin Hassani | 9a3f20c | 2020-05-25 16:38:33 -0700 | [diff] [blame] | 82 | bool Install(brillo::ErrorPtr* err); |
Amin Hassani | a69f32e | 2020-03-30 15:20:42 -0700 | [diff] [blame] | 83 | |
| 84 | // This is called after the update_engine finishes the installation of a |
| 85 | // DLC. This marks the DLC as installed and mounts the DLC image. |
Andrew | 0a534ed | 2020-05-06 09:59:17 -0700 | [diff] [blame] | 86 | bool FinishInstall(bool installed_by_ue, brillo::ErrorPtr* err); |
Amin Hassani | a69f32e | 2020-03-30 15:20:42 -0700 | [diff] [blame] | 87 | |
| 88 | // Cancels the ongoing installation of this DLC. The state will be set to |
| 89 | // uninstalled after this call if successful. |
Andrew | bcc4bd8 | 2020-06-11 14:23:55 -0700 | [diff] [blame] | 90 | // The |err_in| argument is the error that causes the install to be cancelled. |
| 91 | bool CancelInstall(const brillo::ErrorPtr& err_in, brillo::ErrorPtr* err); |
Amin Hassani | a69f32e | 2020-03-30 15:20:42 -0700 | [diff] [blame] | 92 | |
Amin Hassani | 40c0f11 | 2020-04-15 09:55:00 -0700 | [diff] [blame] | 93 | // Uninstalls the DLC. |
| 94 | bool Uninstall(brillo::ErrorPtr* err); |
| 95 | |
Amin Hassani | a69f32e | 2020-03-30 15:20:42 -0700 | [diff] [blame] | 96 | // Deletes all files associated with the DLC. |
Amin Hassani | 40c0f11 | 2020-04-15 09:55:00 -0700 | [diff] [blame] | 97 | bool Purge(brillo::ErrorPtr* err); |
| 98 | |
| 99 | // Returns true if the DLC has to be removed/purged. |
| 100 | bool ShouldPurge(); |
Amin Hassani | a69f32e | 2020-03-30 15:20:42 -0700 | [diff] [blame] | 101 | |
Amin Hassani | f27aac0 | 2020-04-23 21:56:26 -0700 | [diff] [blame] | 102 | // Is called when the DLC image is finally installed on the disk and is |
| 103 | // verified. |
Amin Hassani | 4ca7e1c | 2020-04-29 13:01:33 -0700 | [diff] [blame] | 104 | bool InstallCompleted(brillo::ErrorPtr* err); |
Jae Hoon Kim | 9a27d15 | 2020-04-10 12:50:14 -0700 | [diff] [blame] | 105 | |
Amin Hassani | f27aac0 | 2020-04-23 21:56:26 -0700 | [diff] [blame] | 106 | // Is called when the inactive DLC image is updated and verified. |
Amin Hassani | 78a5ec8 | 2020-05-19 09:47:49 -0700 | [diff] [blame] | 107 | bool UpdateCompleted(brillo::ErrorPtr* err); |
Amin Hassani | f27aac0 | 2020-04-23 21:56:26 -0700 | [diff] [blame] | 108 | |
Amin Hassani | 4856777 | 2020-05-20 16:21:11 -0700 | [diff] [blame] | 109 | // Makes the DLC ready to be updated (creates and resizes the inactive |
| 110 | // image). Returns false if anything goes wrong. |
| 111 | bool MakeReadyForUpdate() const; |
Amin Hassani | 78a5ec8 | 2020-05-19 09:47:49 -0700 | [diff] [blame] | 112 | |
| 113 | // Changes the install progress on this DLC. Only changes if the |progress| is |
| 114 | // greater than the current progress value. |
| 115 | void ChangeProgress(double progress); |
Jae Hoon Kim | 9a27d15 | 2020-04-10 12:50:14 -0700 | [diff] [blame] | 116 | |
Amin Hassani | a69f32e | 2020-03-30 15:20:42 -0700 | [diff] [blame] | 117 | private: |
Amin Hassani | aa38c79 | 2020-04-06 15:52:44 -0700 | [diff] [blame] | 118 | friend class DBusServiceTest; |
| 119 | FRIEND_TEST(DBusServiceTest, GetInstalled); |
Amin Hassani | d5fc8b2 | 2020-04-29 12:44:52 -0700 | [diff] [blame] | 120 | FRIEND_TEST(DlcBaseTest, GetUsedBytesOnDisk); |
Amin Hassani | 78a5ec8 | 2020-05-19 09:47:49 -0700 | [diff] [blame] | 121 | FRIEND_TEST(DlcBaseTest, DefaultState); |
| 122 | FRIEND_TEST(DlcBaseTest, ChangeStateNotInstalled); |
| 123 | FRIEND_TEST(DlcBaseTest, ChangeStateInstalling); |
| 124 | FRIEND_TEST(DlcBaseTest, ChangeStateInstalled); |
| 125 | FRIEND_TEST(DlcBaseTest, ChangeProgress); |
Amin Hassani | 4856777 | 2020-05-20 16:21:11 -0700 | [diff] [blame] | 126 | FRIEND_TEST(DlcBaseTest, MakeReadyForUpdate); |
Amin Hassani | 28ed900 | 2020-05-28 12:37:01 -0700 | [diff] [blame] | 127 | FRIEND_TEST(DlcBaseTest, MarkUnverified); |
Amin Hassani | 6b7a9aa | 2020-05-29 14:23:47 -0700 | [diff] [blame] | 128 | FRIEND_TEST(DlcBaseTest, MarkVerified); |
Amin Hassani | 28ed900 | 2020-05-28 12:37:01 -0700 | [diff] [blame] | 129 | FRIEND_TEST(DlcBaseTest, PreloadCopyShouldMarkUnverified); |
| 130 | FRIEND_TEST(DlcBaseTest, PreloadCopyFailOnInvalidFileSize); |
Jae Hoon Kim | 13e6151 | 2020-06-26 16:36:10 -0700 | [diff] [blame] | 131 | FRIEND_TEST(DlcBaseTest, InstallingCorruptPreloadedImageCleansUp); |
Jae Hoon Kim | f49b6d7 | 2020-06-15 11:29:24 -0700 | [diff] [blame] | 132 | FRIEND_TEST(DlcBaseTest, PreloadingSkippedOnAlreadyVerifiedDlc); |
Jae Hoon Kim | f9b2c9d | 2020-07-22 12:09:13 -0700 | [diff] [blame] | 133 | FRIEND_TEST(DlcBaseTest, UnmountClearsMountPoint); |
Amin Hassani | aa38c79 | 2020-04-06 15:52:44 -0700 | [diff] [blame] | 134 | |
Amin Hassani | a69f32e | 2020-03-30 15:20:42 -0700 | [diff] [blame] | 135 | // Returns the path to the DLC image given the slot number. |
Amin Hassani | 4ca7e1c | 2020-04-29 13:01:33 -0700 | [diff] [blame] | 136 | base::FilePath GetImagePath(BootSlot::Slot slot) const; |
Amin Hassani | a69f32e | 2020-03-30 15:20:42 -0700 | [diff] [blame] | 137 | |
Amin Hassani | c0867b6 | 2020-04-16 09:44:34 -0700 | [diff] [blame] | 138 | // Creates the DLC directories and files if they don't exist. This function |
| 139 | // should be used as fall-through. We should call this even if we presumably |
| 140 | // know the files are already there. This allows us to create any new DLC |
| 141 | // files that didn't exist on a previous version of the DLC. |
| 142 | bool CreateDlc(brillo::ErrorPtr* err); |
Amin Hassani | a69f32e | 2020-03-30 15:20:42 -0700 | [diff] [blame] | 143 | |
Amin Hassani | 6b7a9aa | 2020-05-29 14:23:47 -0700 | [diff] [blame] | 144 | // Mark the current active DLC image as verified. |
| 145 | bool MarkVerified(); |
| 146 | |
Amin Hassani | 28ed900 | 2020-05-28 12:37:01 -0700 | [diff] [blame] | 147 | // Mark the current active DLC image as unverified. |
Amin Hassani | 6b7a9aa | 2020-05-29 14:23:47 -0700 | [diff] [blame] | 148 | bool MarkUnverified(); |
Amin Hassani | 28ed900 | 2020-05-28 12:37:01 -0700 | [diff] [blame] | 149 | |
Jae Hoon Kim | 8ab2649 | 2020-05-07 13:49:36 -0700 | [diff] [blame] | 150 | // Returns true if the DLC image in the current active slot matches the hash |
| 151 | // of that in the rootfs manifest for the DLC. |
| 152 | bool Verify(); |
| 153 | |
Amin Hassani | a69f32e | 2020-03-30 15:20:42 -0700 | [diff] [blame] | 154 | // Helper used to load in (copy + cleanup) preloadable files for the DLC. |
Jae Hoon Kim | 0d4ff62 | 2020-05-14 14:47:40 -0700 | [diff] [blame] | 155 | bool PreloadedCopier(brillo::ErrorPtr* err); |
Amin Hassani | a69f32e | 2020-03-30 15:20:42 -0700 | [diff] [blame] | 156 | |
| 157 | // Mounts the DLC image. |
Amin Hassani | 4ca7e1c | 2020-04-29 13:01:33 -0700 | [diff] [blame] | 158 | bool Mount(brillo::ErrorPtr* err); |
Amin Hassani | a69f32e | 2020-03-30 15:20:42 -0700 | [diff] [blame] | 159 | |
| 160 | // Unmounts the DLC image. |
Amin Hassani | 4ca7e1c | 2020-04-29 13:01:33 -0700 | [diff] [blame] | 161 | bool Unmount(brillo::ErrorPtr* err); |
Amin Hassani | a69f32e | 2020-03-30 15:20:42 -0700 | [diff] [blame] | 162 | |
Amin Hassani | a69f32e | 2020-03-30 15:20:42 -0700 | [diff] [blame] | 163 | // Returns true if the active DLC image is present. |
| 164 | bool IsActiveImagePresent() const; |
| 165 | |
| 166 | // Deletes all directories related to this DLC. |
Amin Hassani | 4ca7e1c | 2020-04-29 13:01:33 -0700 | [diff] [blame] | 167 | bool DeleteInternal(brillo::ErrorPtr* err); |
Amin Hassani | a69f32e | 2020-03-30 15:20:42 -0700 | [diff] [blame] | 168 | |
Amin Hassani | 78a5ec8 | 2020-05-19 09:47:49 -0700 | [diff] [blame] | 169 | // Changes the state of the current DLC. It also notifies the state change |
| 170 | // reporter that a state change has been made. |
| 171 | void ChangeState(DlcState::State state); |
| 172 | |
Amin Hassani | 40c0f11 | 2020-04-15 09:55:00 -0700 | [diff] [blame] | 173 | // Sets the DLC as being active or not based on |active| value. |
| 174 | void SetActiveValue(bool active); |
| 175 | |
Amin Hassani | a69f32e | 2020-03-30 15:20:42 -0700 | [diff] [blame] | 176 | DlcId id_; |
| 177 | std::string package_; |
| 178 | |
| 179 | DlcState state_; |
| 180 | |
| 181 | base::FilePath mount_point_; |
| 182 | |
| 183 | imageloader::Manifest manifest_; |
| 184 | |
| 185 | // The directories on the stateful partition where the DLC image will reside. |
| 186 | base::FilePath content_id_path_; |
| 187 | base::FilePath content_package_path_; |
Amin Hassani | fe63fc2 | 2020-04-07 11:34:34 -0700 | [diff] [blame] | 188 | base::FilePath prefs_path_; |
Jae Hoon Kim | dcadbd4 | 2020-06-25 09:21:03 -0700 | [diff] [blame] | 189 | base::FilePath prefs_package_path_; |
Jae Hoon Kim | 0d4ff62 | 2020-05-14 14:47:40 -0700 | [diff] [blame] | 190 | base::FilePath preloaded_image_path_; |
Amin Hassani | a69f32e | 2020-03-30 15:20:42 -0700 | [diff] [blame] | 191 | |
Amin Hassani | 40c0f11 | 2020-04-15 09:55:00 -0700 | [diff] [blame] | 192 | // The object that keeps track of ref counts. NOTE: Do NOT access this object |
| 193 | // directly. Use |GetRefCount()| instead. |
| 194 | std::unique_ptr<RefCountInterface> ref_count_; |
| 195 | |
Amin Hassani | 6b010bf | 2020-06-04 17:26:58 -0700 | [diff] [blame] | 196 | DlcBase(const DlcBase&) = delete; |
| 197 | DlcBase& operator=(const DlcBase&) = delete; |
Amin Hassani | a69f32e | 2020-03-30 15:20:42 -0700 | [diff] [blame] | 198 | }; |
| 199 | |
Amin Hassani | 8664998 | 2020-03-31 16:03:37 -0700 | [diff] [blame] | 200 | using DlcMap = std::map<DlcId, DlcBase>; |
Amin Hassani | 9ca846f | 2020-04-17 12:41:01 -0700 | [diff] [blame] | 201 | using DlcIdList = std::vector<DlcId>; |
Amin Hassani | 8664998 | 2020-03-31 16:03:37 -0700 | [diff] [blame] | 202 | |
Amin Hassani | a69f32e | 2020-03-30 15:20:42 -0700 | [diff] [blame] | 203 | } // namespace dlcservice |
| 204 | |
| 205 | #endif // DLCSERVICE_DLC_H_ |