• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 
18 #include <optional>
19 #include <string>
20 
21 #include <android-base/file.h>
22 #include <android-base/logging.h>
23 #include <android-base/unique_fd.h>
24 #include <fstab/fstab.h>
25 #include <liblp/liblp.h>
26 
27 // Logical partitions are only mapped to a block device as needed, and
28 // immediately unmapped when no longer needed. In order to enforce this we
29 // require accessing partitions through a Handle abstraction, which may perform
30 // additional operations after closing its file descriptor.
31 class PartitionHandle {
32   public:
PartitionHandle()33     PartitionHandle() {}
PartitionHandle(const std::string & path)34     explicit PartitionHandle(const std::string& path) : path_(path) {}
PartitionHandle(const std::string & path,std::function<void ()> && closer)35     PartitionHandle(const std::string& path, std::function<void()>&& closer)
36         : path_(path), closer_(std::move(closer)) {}
37     PartitionHandle(PartitionHandle&& other) = default;
38     PartitionHandle& operator=(PartitionHandle&& other) = default;
~PartitionHandle()39     ~PartitionHandle() {
40         if (closer_) {
41             // Make sure the device is closed first.
42             fd_ = {};
43             closer_();
44         }
45     }
path()46     const std::string& path() const { return path_; }
fd()47     int fd() const { return fd_.get(); }
Open(int flags)48     bool Open(int flags) {
49         flags |= (O_EXCL | O_CLOEXEC | O_BINARY);
50 
51         // Attempts to open a second device can fail with EBUSY if the device is already open.
52         // Explicitly close any previously opened devices as unique_fd won't close them until
53         // after the attempt to open.
54         fd_.reset();
55 
56         fd_ = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path_.c_str(), flags)));
57         if (fd_ < 0) {
58             PLOG(ERROR) << "Failed to open block device: " << path_;
59             return false;
60         }
61         flags_ = flags;
62 
63         return true;
64     }
Reset(int flags)65     bool Reset(int flags) {
66         if (fd_.ok() && (flags | O_EXCL | O_CLOEXEC | O_BINARY) == flags_) {
67             return true;
68         }
69 
70         off_t offset = fd_.ok() ? lseek(fd_.get(), 0, SEEK_CUR) : 0;
71         if (offset < 0) {
72             PLOG(ERROR) << "Failed lseek on block device: " << path_;
73             return false;
74         }
75 
76         sync();
77 
78         if (Open(flags) == false) {
79             return false;
80         }
81 
82         if (lseek(fd_.get(), offset, SEEK_SET) != offset) {
83             PLOG(ERROR) << "Failed lseek on block device: " << path_;
84             return false;
85         }
86 
87         return true;
88     }
89   private:
90     std::string path_;
91     android::base::unique_fd fd_;
92     int flags_;
93     std::function<void()> closer_;
94 };
95 
96 class AutoMountMetadata {
97   public:
98     AutoMountMetadata();
99     ~AutoMountMetadata();
100     explicit operator bool() const { return mounted_; }
101 
102   private:
103     android::fs_mgr::Fstab fstab_;
104     bool mounted_ = false;
105     bool should_unmount_ = false;
106 };
107 
108 class FastbootDevice;
109 
110 // On normal devices, the super partition is always named "super". On retrofit
111 // devices, the name must be derived from the partition name or current slot.
112 // This helper assists in choosing the correct super for a given partition
113 // name.
114 std::string GetSuperSlotSuffix(FastbootDevice* device, const std::string& partition_name);
115 
116 std::optional<std::string> FindPhysicalPartition(const std::string& name);
117 bool LogicalPartitionExists(FastbootDevice* device, const std::string& name,
118                             bool* is_zero_length = nullptr);
119 
120 // Partition is O_WRONLY by default, caller should pass O_RDONLY for reading.
121 // Caller may pass additional flags if needed. (O_EXCL | O_CLOEXEC | O_BINARY)
122 // will be logically ORed internally.
123 bool OpenPartition(FastbootDevice* device, const std::string& name, PartitionHandle* handle,
124                    int flags = O_WRONLY);
125 
126 bool GetSlotNumber(const std::string& slot, int32_t* number);
127 std::vector<std::string> ListPartitions(FastbootDevice* device);
128 bool GetDeviceLockStatus();
129 
130 // Update all copies of metadata.
131 bool UpdateAllPartitionMetadata(FastbootDevice* device, const std::string& super_name,
132                                 const android::fs_mgr::LpMetadata& metadata);
133