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:
parent
93950229cf
commit
18a78e0a16
9 changed files with 152 additions and 43 deletions
13
Android.mk
13
Android.mk
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
38
fuse_sideload.h
Normal 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
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
67
minadbd/fuse_adb_provider.c
Normal file
67
minadbd/fuse_adb_provider.c
Normal 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);
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue