summaryrefslogtreecommitdiffstats
path: root/fuse_sideload
diff options
context:
space:
mode:
Diffstat (limited to 'fuse_sideload')
-rw-r--r--fuse_sideload/Android.bp7
-rw-r--r--fuse_sideload/fuse_provider.cpp71
-rw-r--r--fuse_sideload/fuse_sideload.cpp5
-rw-r--r--fuse_sideload/include/fuse_provider.h73
-rw-r--r--fuse_sideload/include/fuse_sideload.h2
5 files changed, 153 insertions, 5 deletions
diff --git a/fuse_sideload/Android.bp b/fuse_sideload/Android.bp
index 90c4c22c3..8548548d2 100644
--- a/fuse_sideload/Android.bp
+++ b/fuse_sideload/Android.bp
@@ -16,14 +16,17 @@ cc_library {
name: "libfusesideload",
recovery_available: true,
+ defaults: [
+ "recovery_defaults",
+ ],
+
cflags: [
"-D_XOPEN_SOURCE",
"-D_GNU_SOURCE",
- "-Wall",
- "-Werror",
],
srcs: [
+ "fuse_provider.cpp",
"fuse_sideload.cpp",
],
diff --git a/fuse_sideload/fuse_provider.cpp b/fuse_sideload/fuse_provider.cpp
new file mode 100644
index 000000000..58786f5f3
--- /dev/null
+++ b/fuse_sideload/fuse_provider.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "fuse_provider.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <functional>
+
+#include <android-base/file.h>
+
+#include "fuse_sideload.h"
+
+FuseFileDataProvider::FuseFileDataProvider(const std::string& path, uint32_t block_size) {
+ struct stat sb;
+ if (stat(path.c_str(), &sb) == -1) {
+ fprintf(stderr, "failed to stat %s: %s\n", path.c_str(), strerror(errno));
+ return;
+ }
+
+ fd_.reset(open(path.c_str(), O_RDONLY));
+ if (fd_ == -1) {
+ fprintf(stderr, "failed to open %s: %s\n", path.c_str(), strerror(errno));
+ return;
+ }
+ file_size_ = sb.st_size;
+ fuse_block_size_ = block_size;
+}
+
+bool FuseFileDataProvider::ReadBlockAlignedData(uint8_t* buffer, uint32_t fetch_size,
+ uint32_t start_block) const {
+ uint64_t offset = static_cast<uint64_t>(start_block) * fuse_block_size_;
+ if (fetch_size > file_size_ || offset > file_size_ - fetch_size) {
+ fprintf(stderr,
+ "Out of bound read, start block: %" PRIu32 ", fetch size: %" PRIu32
+ ", file size %" PRIu64 "\n",
+ start_block, fetch_size, file_size_);
+ return false;
+ }
+
+ if (!android::base::ReadFullyAtOffset(fd_, buffer, fetch_size, offset)) {
+ fprintf(stderr, "Failed to read fetch size: %" PRIu32 " bytes data at offset %" PRIu64 ": %s\n",
+ fetch_size, offset, strerror(errno));
+ return false;
+ }
+
+ return true;
+}
+
+void FuseFileDataProvider::Close() {
+ fd_.reset();
+}
diff --git a/fuse_sideload/fuse_sideload.cpp b/fuse_sideload/fuse_sideload.cpp
index 1c7e98f01..e812486f8 100644
--- a/fuse_sideload/fuse_sideload.cpp
+++ b/fuse_sideload/fuse_sideload.cpp
@@ -244,8 +244,9 @@ static int fetch_block(fuse_data* fd, uint32_t block) {
memset(fd->block_data + fetch_size, 0, fd->block_size - fetch_size);
}
- int result = fd->vtab.read_block(block, fd->block_data, fetch_size);
- if (result < 0) return result;
+ if (!fd->vtab.read_block(block, fd->block_data, fetch_size)) {
+ return -EIO;
+ }
fd->curr_block = block;
diff --git a/fuse_sideload/include/fuse_provider.h b/fuse_sideload/include/fuse_provider.h
new file mode 100644
index 000000000..672af0577
--- /dev/null
+++ b/fuse_sideload/include/fuse_provider.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+#include <string>
+
+#include <android-base/unique_fd.h>
+
+// This is the base class to read data from source and provide the data to FUSE.
+class FuseDataProvider {
+ public:
+ FuseDataProvider(android::base::unique_fd&& fd, uint64_t file_size, uint32_t block_size)
+ : fd_(std::move(fd)), file_size_(file_size), fuse_block_size_(block_size) {}
+
+ virtual ~FuseDataProvider() = default;
+
+ uint64_t file_size() const {
+ return file_size_;
+ }
+ uint32_t fuse_block_size() const {
+ return fuse_block_size_;
+ }
+
+ explicit operator bool() const {
+ return fd_ != -1;
+ }
+
+ // Reads |fetch_size| bytes data starting from |start_block|. Puts the result in |buffer|.
+ virtual bool ReadBlockAlignedData(uint8_t* buffer, uint32_t fetch_size,
+ uint32_t start_block) const = 0;
+
+ virtual void Close() = 0;
+
+ protected:
+ FuseDataProvider() = default;
+
+ // The underlying source to read data from.
+ android::base::unique_fd fd_;
+ // Size in bytes of the file to read.
+ uint64_t file_size_ = 0;
+ // Block size passed to the fuse, this is different from the block size of the block device.
+ uint32_t fuse_block_size_ = 0;
+};
+
+// This class reads data from a file.
+class FuseFileDataProvider : public FuseDataProvider {
+ public:
+ FuseFileDataProvider(android::base::unique_fd&& fd, uint64_t file_size, uint32_t block_size)
+ : FuseDataProvider(std::move(fd), file_size, block_size) {}
+
+ FuseFileDataProvider(const std::string& path, uint32_t block_size);
+
+ bool ReadBlockAlignedData(uint8_t* buffer, uint32_t fetch_size,
+ uint32_t start_block) const override;
+
+ void Close() override;
+};
diff --git a/fuse_sideload/include/fuse_sideload.h b/fuse_sideload/include/fuse_sideload.h
index 1b34cbdb0..821c7c808 100644
--- a/fuse_sideload/include/fuse_sideload.h
+++ b/fuse_sideload/include/fuse_sideload.h
@@ -28,7 +28,7 @@ static constexpr const char* FUSE_SIDELOAD_HOST_EXIT_PATHNAME = "/sideload/exit"
struct provider_vtab {
// read a block
- std::function<int(uint32_t block, uint8_t* buffer, uint32_t fetch_size)> read_block;
+ std::function<bool(uint32_t block, uint8_t* buffer, uint32_t fetch_size)> read_block;
// close down
std::function<void(void)> close;