refactor fuse sideloading code

Split the adb-specific portions (fetching a block from the adb host
and closing the connections) out from the rest of the FUSE filesystem
code, so that we can reuse the fuse stuff for installing off sdcards
as well.

Change-Id: I0ba385fd35999c5f5cad27842bc82024a264dd14
This commit is contained in:
Doug Zongker 2014-07-10 07:31:46 -07:00
parent 93950229cf
commit 18a78e0a16
9 changed files with 152 additions and 43 deletions

View file

@ -15,6 +15,18 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := fuse_sideload.c
LOCAL_CFLAGS := -O2 -g -DADB_HOST=0 -Wall -Wno-unused-parameter
LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE
LOCAL_MODULE := libfusesideload
LOCAL_STATIC_LIBRARIES := libcutils libc libmincrypt
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
@ -49,6 +61,7 @@ LOCAL_STATIC_LIBRARIES := \
libmtdutils \
libmincrypt \
libminadbd \
libfusesideload \
libminui \
libpng \
libfs_mgr \

View file

@ -31,7 +31,8 @@
#include "common.h"
#include "adb_install.h"
extern "C" {
#include "minadbd/adb.h"
#include "minadbd/fuse_adb_provider.h"
#include "fuse_sideload.h"
}
static RecoveryUI* ui = NULL;
@ -89,7 +90,7 @@ apply_from_adb(RecoveryUI* ui_, int* wipe_cache, const char* install_file) {
_exit(-1);
}
// ADB_SIDELOAD_HOST_PATHNAME will start to exist once the host
// FUSE_SIDELOAD_HOST_PATHNAME will start to exist once the host
// connects and starts serving a package. Poll for its
// appearance. (Note that inotify doesn't work with FUSE.)
int result;
@ -103,7 +104,7 @@ apply_from_adb(RecoveryUI* ui_, int* wipe_cache, const char* install_file) {
break;
}
if (stat(ADB_SIDELOAD_HOST_PATHNAME, &st) != 0) {
if (stat(FUSE_SIDELOAD_HOST_PATHNAME, &st) != 0) {
if (errno == ENOENT && i < ADB_INSTALL_TIMEOUT-1) {
sleep(1);
continue;
@ -114,14 +115,14 @@ apply_from_adb(RecoveryUI* ui_, int* wipe_cache, const char* install_file) {
break;
}
}
result = install_package(ADB_SIDELOAD_HOST_PATHNAME, wipe_cache, install_file, false);
result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, wipe_cache, install_file, false);
break;
}
if (!waited) {
// Calling stat() on this magic filename signals the minadbd
// subprocess to shut down.
stat(ADB_SIDELOAD_HOST_EXIT_PATHNAME, &st);
stat(FUSE_SIDELOAD_HOST_EXIT_PATHNAME, &st);
// TODO(dougz): there should be a way to cancel waiting for a
// package (by pushing some button combo on the device). For now

View file

@ -60,9 +60,8 @@
#include <sys/uio.h>
#include <unistd.h>
#include "transport.h"
#include "adb.h"
#include "mincrypt/sha256.h"
#include "fuse_sideload.h"
#define PACKAGE_FILE_ID (FUSE_ROOT_ID+1)
#define EXIT_FLAG_ID (FUSE_ROOT_ID+2)
@ -72,7 +71,9 @@
struct fuse_data {
int ffd; // file descriptor for the fuse socket
int sfd; // file descriptor for the adb channel
struct provider_vtab* vtab;
void* cookie;
uint64_t file_size; // bytes
@ -170,13 +171,13 @@ static int handle_lookup(void* data, struct fuse_data* fd,
out.entry_valid = 10;
out.attr_valid = 10;
if (strncmp(ADB_SIDELOAD_HOST_FILENAME, data,
sizeof(ADB_SIDELOAD_HOST_FILENAME)) == 0) {
if (strncmp(FUSE_SIDELOAD_HOST_FILENAME, data,
sizeof(FUSE_SIDELOAD_HOST_FILENAME)) == 0) {
out.nodeid = PACKAGE_FILE_ID;
out.generation = PACKAGE_FILE_ID;
fill_attr(&(out.attr), fd, PACKAGE_FILE_ID, fd->file_size, S_IFREG | 0444);
} else if (strncmp(ADB_SIDELOAD_HOST_EXIT_FLAG, data,
sizeof(ADB_SIDELOAD_HOST_EXIT_FLAG)) == 0) {
} else if (strncmp(FUSE_SIDELOAD_HOST_EXIT_FLAG, data,
sizeof(FUSE_SIDELOAD_HOST_EXIT_FLAG)) == 0) {
out.nodeid = EXIT_FLAG_ID;
out.generation = EXIT_FLAG_ID;
fill_attr(&(out.attr), fd, EXIT_FLAG_ID, 0, S_IFREG | 0);
@ -231,17 +232,8 @@ static int fetch_block(struct fuse_data* fd, uint32_t block) {
memset(fd->block_data + fetch_size, 0, fd->block_size - fetch_size);
}
char buf[10];
snprintf(buf, sizeof(buf), "%08u", block);
if (writex(fd->sfd, buf, 8) < 0) {
fprintf(stderr, "failed to write to adb host: %s\n", strerror(errno));
return -EIO;
}
if (readx(fd->sfd, fd->block_data, fetch_size) < 0) {
fprintf(stderr, "failed to read from adb host: %s\n", strerror(errno));
return -EIO;
}
int result = fd->vtab->read_block(fd->cookie, block, fd->block_data, fetch_size);
if (result < 0) return result;
fd->curr_block = block;
@ -346,13 +338,14 @@ static int handle_read(void* data, struct fuse_data* fd, const struct fuse_in_he
return NO_STATUS;
}
int run_fuse(int sfd, uint64_t file_size, uint32_t block_size)
int run_fuse_sideload(struct provider_vtab* vtab, void* cookie,
uint64_t file_size, uint32_t block_size)
{
int result;
// If something's already mounted on our mountpoint, try to remove
// it. (Mostly in case of a previous abnormal exit.)
umount2(ADB_SIDELOAD_HOST_MOUNTPOINT, MNT_FORCE);
umount2(FUSE_SIDELOAD_HOST_MOUNTPOINT, MNT_FORCE);
if (block_size < 1024) {
fprintf(stderr, "block size (%u) is too small\n", block_size);
@ -365,7 +358,8 @@ int run_fuse(int sfd, uint64_t file_size, uint32_t block_size)
struct fuse_data fd;
memset(&fd, 0, sizeof(fd));
fd.sfd = sfd;
fd.vtab = vtab;
fd.cookie = cookie;
fd.file_size = file_size;
fd.block_size = block_size;
fd.file_blocks = (file_size == 0) ? 0 : (((file_size-1) / block_size) + 1);
@ -414,7 +408,7 @@ int run_fuse(int sfd, uint64_t file_size, uint32_t block_size)
"allow_other,rootmode=040000"),
fd.ffd, fd.uid, fd.gid, block_size);
result = mount("/dev/fuse", ADB_SIDELOAD_HOST_MOUNTPOINT,
result = mount("/dev/fuse", FUSE_SIDELOAD_HOST_MOUNTPOINT,
"fuse", MS_NOSUID | MS_NODEV | MS_RDONLY | MS_NOEXEC, opts);
if (result < 0) {
perror("mount");
@ -493,8 +487,9 @@ int run_fuse(int sfd, uint64_t file_size, uint32_t block_size)
}
done:
writex(sfd, "DONEDONE", 8);
result = umount2(ADB_SIDELOAD_HOST_MOUNTPOINT, MNT_DETACH);
fd.vtab->close(fd.cookie);
result = umount2(FUSE_SIDELOAD_HOST_MOUNTPOINT, MNT_DETACH);
if (result < 0) {
printf("fuse_sideload umount failed: %s\n", strerror(errno));
}

38
fuse_sideload.h Normal file
View file

@ -0,0 +1,38 @@
/*
* Copyright (C) 2014 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.
*/
#ifndef __FUSE_SIDELOAD_H
#define __FUSE_SIDELOAD_H
// define the filenames created by the sideload FUSE filesystem
#define FUSE_SIDELOAD_HOST_MOUNTPOINT "/sideload"
#define FUSE_SIDELOAD_HOST_FILENAME "package.zip"
#define FUSE_SIDELOAD_HOST_PATHNAME (FUSE_SIDELOAD_HOST_MOUNTPOINT "/" FUSE_SIDELOAD_HOST_FILENAME)
#define FUSE_SIDELOAD_HOST_EXIT_FLAG "exit"
#define FUSE_SIDELOAD_HOST_EXIT_PATHNAME (FUSE_SIDELOAD_HOST_MOUNTPOINT "/" FUSE_SIDELOAD_HOST_EXIT_FLAG)
struct provider_vtab {
// read a block
int (*read_block)(void* cookie, uint32_t block, uint8_t* buffer, uint32_t fetch_size);
// close down
void (*close)(void* cookie);
};
int run_fuse_sideload(struct provider_vtab* vtab, void* cookie,
uint64_t file_size, uint32_t block_size);
#endif

View file

@ -13,7 +13,7 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
adb.c \
fdevent.c \
fuse_sideload.c \
fuse_adb_provider.c \
transport.c \
transport_usb.c \
sockets.c \
@ -23,8 +23,10 @@ LOCAL_SRC_FILES := \
LOCAL_CFLAGS := -O2 -g -DADB_HOST=0 -Wall -Wno-unused-parameter
LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE
LOCAL_C_INCLUDES += bootable/recovery
LOCAL_MODULE := libminadbd
LOCAL_STATIC_LIBRARIES := libcutils libc libmincrypt
LOCAL_STATIC_LIBRARIES := libfusesideload libcutils libc
include $(BUILD_STATIC_LIBRARY)

View file

@ -421,11 +421,4 @@ extern int SHELL_EXIT_NOTIFY_FD;
int sendfailmsg(int fd, const char *reason);
int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s);
// define the filenames created by the sideload-host FUSE filesystem
#define ADB_SIDELOAD_HOST_MOUNTPOINT "/sideload"
#define ADB_SIDELOAD_HOST_FILENAME "package.zip"
#define ADB_SIDELOAD_HOST_PATHNAME (ADB_SIDELOAD_HOST_MOUNTPOINT "/" ADB_SIDELOAD_HOST_FILENAME)
#define ADB_SIDELOAD_HOST_EXIT_FLAG "exit"
#define ADB_SIDELOAD_HOST_EXIT_PATHNAME (ADB_SIDELOAD_HOST_MOUNTPOINT "/" ADB_SIDELOAD_HOST_EXIT_FLAG)
#endif

View file

@ -0,0 +1,67 @@
/*
* Copyright (C) 2014 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 <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include "adb.h"
#include "fuse_sideload.h"
struct adb_data {
int sfd; // file descriptor for the adb channel
uint64_t file_size;
uint32_t block_size;
};
static int read_block_adb(void* cookie, uint32_t block, uint8_t* buffer, uint32_t fetch_size) {
struct adb_data* ad = (struct adb_data*)cookie;
char buf[10];
snprintf(buf, sizeof(buf), "%08u", block);
if (writex(ad->sfd, buf, 8) < 0) {
fprintf(stderr, "failed to write to adb host: %s\n", strerror(errno));
return -EIO;
}
if (readx(ad->sfd, buffer, fetch_size) < 0) {
fprintf(stderr, "failed to read from adb host: %s\n", strerror(errno));
return -EIO;
}
return 0;
}
static void close_adb(void* cookie) {
struct adb_data* ad = (struct adb_data*)cookie;
writex(ad->sfd, "DONEDONE", 8);
}
int run_adb_fuse(int sfd, uint64_t file_size, uint32_t block_size) {
struct adb_data ad;
struct provider_vtab vtab;
ad.sfd = sfd;
ad.file_size = file_size;
ad.block_size = block_size;
vtab.read_block = read_block_adb;
vtab.close = close_adb;
return run_fuse_sideload(&vtab, &ad, file_size, block_size);
}

View file

@ -14,9 +14,9 @@
* limitations under the License.
*/
#ifndef __FUSE_SIDELOAD_H
#define __FUSE_SIDELOAD_H
#ifndef __FUSE_ADB_PROVIDER_H
#define __FUSE_ADB_PROVIDER_H
int run_fuse(int sfd, uint64_t file_size, uint32_t block_size);
int run_adb_fuse(int sfd, uint64_t file_size, uint32_t block_size);
#endif

View file

@ -22,7 +22,7 @@
#include "sysdeps.h"
#include "fdevent.h"
#include "fuse_sideload.h"
#include "fuse_adb_provider.h"
#define TRACE_TAG TRACE_SERVICES
#include "adb.h"
@ -54,7 +54,7 @@ static void sideload_host_service(int sfd, void* cookie)
printf("sideload-host file size %llu block size %lu\n", file_size, block_size);
int result = run_fuse(sfd, file_size, block_size);
int result = run_adb_fuse(sfd, file_size, block_size);
printf("sideload_host finished\n");
sleep(1);