Skip to content

Commit

Permalink
Merge "Create a FuseDataProvider base class"
Browse files Browse the repository at this point in the history
  • Loading branch information
Tianjie Xu authored and Gerrit Code Review committed Mar 19, 2019
2 parents 98beb64 + ea2912f commit eeea86f
Show file tree
Hide file tree
Showing 16 changed files with 250 additions and 136 deletions.
2 changes: 1 addition & 1 deletion Android.bp
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ cc_library_static {
srcs: [
"adb_install.cpp",
"fsck_unshare_blocks.cpp",
"fuse_sdcard_provider.cpp",
"fuse_sdcard_install.cpp",
"install.cpp",
"recovery.cpp",
"roots.cpp",
Expand Down
45 changes: 45 additions & 0 deletions fuse_sdcard_install.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* 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_sdcard_install.h"

#include <sys/mount.h>
#include <unistd.h>

#include <functional>

#include "fuse_provider.h"
#include "fuse_sideload.h"

bool start_sdcard_fuse(const char* path) {
FuseFileDataProvider file_data_reader(path, 65536);

if (!file_data_reader) {
return false;
}

provider_vtab vtab;
vtab.read_block = std::bind(&FuseFileDataProvider::ReadBlockAlignedData, &file_data_reader,
std::placeholders::_2, std::placeholders::_3, std::placeholders::_1);
vtab.close = [&file_data_reader]() { file_data_reader.Close(); };

// The installation process expects to find the sdcard unmounted. Unmount it with MNT_DETACH so
// that our open file continues to work but new references see it as unmounted.
umount2("/sdcard", MNT_DETACH);

return run_fuse_sideload(vtab, file_data_reader.file_size(),
file_data_reader.fuse_block_size()) == 0;
}
7 changes: 2 additions & 5 deletions fuse_sdcard_provider.h → fuse_sdcard_install.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014 The Android Open Source Project
* 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.
Expand All @@ -14,9 +14,6 @@
* limitations under the License.
*/

#ifndef __FUSE_SDCARD_PROVIDER_H
#define __FUSE_SDCARD_PROVIDER_H
#pragma once

bool start_sdcard_fuse(const char* path);

#endif
83 changes: 0 additions & 83 deletions fuse_sdcard_provider.cpp

This file was deleted.

7 changes: 5 additions & 2 deletions fuse_sideload/Android.bp
Original file line number Diff line number Diff line change
Expand Up @@ -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",
],

Expand Down
71 changes: 71 additions & 0 deletions fuse_sideload/fuse_provider.cpp
Original file line number Diff line number Diff line change
@@ -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();
}
5 changes: 3 additions & 2 deletions fuse_sideload/fuse_sideload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
73 changes: 73 additions & 0 deletions fuse_sideload/include/fuse_provider.h
Original file line number Diff line number Diff line change
@@ -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;
};
2 changes: 1 addition & 1 deletion fuse_sideload/include/fuse_sideload.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions minadbd/Android.bp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ cc_test {

static_libs: [
"libminadbd_services",
"libfusesideload",
"libadbd",
],

Expand Down
30 changes: 16 additions & 14 deletions minadbd/fuse_adb_provider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,30 +27,32 @@
#include "adb_io.h"
#include "fuse_sideload.h"

int read_block_adb(const adb_data& ad, uint32_t block, uint8_t* buffer, uint32_t fetch_size) {
if (!WriteFdFmt(ad.sfd, "%08u", block)) {
bool FuseAdbDataProvider::ReadBlockAlignedData(uint8_t* buffer, uint32_t fetch_size,
uint32_t start_block) const {
if (!WriteFdFmt(fd_, "%08u", start_block)) {
fprintf(stderr, "failed to write to adb host: %s\n", strerror(errno));
return -EIO;
return false;
}

if (!ReadFdExactly(ad.sfd, buffer, fetch_size)) {
if (!ReadFdExactly(fd_, buffer, fetch_size)) {
fprintf(stderr, "failed to read from adb host: %s\n", strerror(errno));
return -EIO;
return false;
}

return 0;
return true;
}

int run_adb_fuse(int sfd, uint64_t file_size, uint32_t block_size) {
adb_data ad;
ad.sfd = sfd;
ad.file_size = file_size;
ad.block_size = block_size;
void FuseAdbDataProvider::Close() {
WriteFdExactly(fd_, "DONEDONE");
}

int run_adb_fuse(android::base::unique_fd&& sfd, uint64_t file_size, uint32_t block_size) {
FuseAdbDataProvider adb_data_reader(std::move(sfd), file_size, block_size);

provider_vtab vtab;
vtab.read_block = std::bind(read_block_adb, ad, std::placeholders::_1, std::placeholders::_2,
std::placeholders::_3);
vtab.close = [&ad]() { WriteFdExactly(ad.sfd, "DONEDONE"); };
vtab.read_block = std::bind(&FuseAdbDataProvider::ReadBlockAlignedData, &adb_data_reader,
std::placeholders::_2, std::placeholders::_3, std::placeholders::_1);
vtab.close = [&adb_data_reader]() { adb_data_reader.Close(); };

return run_fuse_sideload(vtab, file_size, block_size);
}
Loading

0 comments on commit eeea86f

Please sign in to comment.