Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 18a78e0a authored by Doug Zongker's avatar Doug Zongker
Browse files

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
parent 93950229
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -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 \
+6 −5
Original line number Diff line number Diff line
@@ -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
+19 −24
Original line number Diff line number Diff line
@@ -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));
    }

fuse_sideload.h

0 → 100644
+38 −0
Original line number Diff line number Diff line
/*
 * 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
+4 −2
Original line number Diff line number Diff line
@@ -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)
Loading