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

Commit 43473d3a authored by Tom Cherry's avatar Tom Cherry Committed by android-build-merger
Browse files

Merge changes I9d0482d1,Ib82833be

am: b87f1c17

Change-Id: Ia031560d95ab967ea12d4c971de32308c5bb9888
parents 3447f72d b87f1c17
Loading
Loading
Loading
Loading
+104 −176
Original line number Original line Diff line number Diff line
@@ -56,9 +56,6 @@
#include "util.h"
#include "util.h"


#define SYSFS_PREFIX    "/sys"
#define SYSFS_PREFIX    "/sys"
static const char *firmware_dirs[] = { "/etc/firmware",
                                       "/vendor/firmware",
                                       "/firmware/image" };


extern struct selabel_handle *sehandle;
extern struct selabel_handle *sehandle;


@@ -79,16 +76,8 @@ struct perm_node {
    struct listnode plist;
    struct listnode plist;
};
};


struct platform_node {
    char *name;
    char *path;
    int path_len;
    struct listnode list;
};

static list_declare(sys_perms);
static list_declare(sys_perms);
static list_declare(dev_perms);
static list_declare(dev_perms);
static list_declare(platform_names);


int add_dev_perms(const char *name, const char *attr,
int add_dev_perms(const char *name, const char *attr,
                  mode_t perm, unsigned int uid, unsigned int gid,
                  mode_t perm, unsigned int uid, unsigned int gid,
@@ -153,17 +142,18 @@ static bool match_subsystem(perms_* dp, const char* pattern,
    return perm_path_matches(subsys_path.c_str(), dp);
    return perm_path_matches(subsys_path.c_str(), dp);
}
}


static void fixup_sys_perms(const char* upath, const char* subsystem) {
static void fixup_sys_perms(const std::string& upath, const std::string& subsystem) {
    // upaths omit the "/sys" that paths in this list
    // upaths omit the "/sys" that paths in this list
    // contain, so we prepend it...
    // contain, so we prepend it...
    std::string path = std::string(SYSFS_PREFIX) + upath;
    std::string path = SYSFS_PREFIX + upath;


    listnode* node;
    listnode* node;
    list_for_each(node, &sys_perms) {
    list_for_each(node, &sys_perms) {
        perms_* dp = &(node_to_item(node, perm_node, plist))->dp;
        perms_* dp = &(node_to_item(node, perm_node, plist))->dp;
        if (match_subsystem(dp, SYSFS_PREFIX "/class/%s/%s", path.c_str(), subsystem)) {
        if (match_subsystem(dp, SYSFS_PREFIX "/class/%s/%s", path.c_str(), subsystem.c_str())) {
            ; // matched
            ; // matched
        } else if (match_subsystem(dp, SYSFS_PREFIX "/bus/%s/devices/%s", path.c_str(), subsystem)) {
        } else if (match_subsystem(dp, SYSFS_PREFIX "/bus/%s/devices/%s", path.c_str(),
                                   subsystem.c_str())) {
            ; // matched
            ; // matched
        } else if (!perm_path_matches(path.c_str(), dp)) {
        } else if (!perm_path_matches(path.c_str(), dp)) {
            continue;
            continue;
@@ -209,7 +199,7 @@ static mode_t get_device_perm(const char* path, const std::vector<std::string>&
    return 0600;
    return 0600;
}
}


static void make_device(const char* path, const char* /*upath*/, int block, int major, int minor,
static void make_device(const std::string& path, int block, int major, int minor,
                        const std::vector<std::string>& links) {
                        const std::vector<std::string>& links) {
    unsigned uid;
    unsigned uid;
    unsigned gid;
    unsigned gid;
@@ -217,7 +207,7 @@ static void make_device(const char* path, const char* /*upath*/, int block, int
    dev_t dev;
    dev_t dev;
    char *secontext = NULL;
    char *secontext = NULL;


    mode = get_device_perm(path, links, &uid, &gid) | (block ? S_IFBLK : S_IFCHR);
    mode = get_device_perm(path.c_str(), links, &uid, &gid) | (block ? S_IFBLK : S_IFCHR);


    if (sehandle) {
    if (sehandle) {
        std::vector<const char*> c_links;
        std::vector<const char*> c_links;
@@ -225,7 +215,7 @@ static void make_device(const char* path, const char* /*upath*/, int block, int
            c_links.emplace_back(link.c_str());
            c_links.emplace_back(link.c_str());
        }
        }
        c_links.emplace_back(nullptr);
        c_links.emplace_back(nullptr);
        if (selabel_lookup_best_match(sehandle, &secontext, path, &c_links[0], mode)) {
        if (selabel_lookup_best_match(sehandle, &secontext, path.c_str(), &c_links[0], mode)) {
            PLOG(ERROR) << "Device '" << path << "' not created; cannot find SELinux label";
            PLOG(ERROR) << "Device '" << path << "' not created; cannot find SELinux label";
            return;
            return;
        }
        }
@@ -244,10 +234,9 @@ static void make_device(const char* path, const char* /*upath*/, int block, int
    }
    }
    /* If the node already exists update its SELinux label to handle cases when
    /* If the node already exists update its SELinux label to handle cases when
     * it was created with the wrong context during coldboot procedure. */
     * it was created with the wrong context during coldboot procedure. */
    if (mknod(path, mode, dev) && (errno == EEXIST) && secontext) {
    if (mknod(path.c_str(), mode, dev) && (errno == EEXIST) && secontext) {

        char* fcon = nullptr;
        char* fcon = nullptr;
        int rc = lgetfilecon(path, &fcon);
        int rc = lgetfilecon(path.c_str(), &fcon);
        if (rc < 0) {
        if (rc < 0) {
            PLOG(ERROR) << "Cannot get SELinux label on '" << path << "' device";
            PLOG(ERROR) << "Cannot get SELinux label on '" << path << "' device";
            goto out;
            goto out;
@@ -256,13 +245,13 @@ static void make_device(const char* path, const char* /*upath*/, int block, int
        bool different = strcmp(fcon, secontext) != 0;
        bool different = strcmp(fcon, secontext) != 0;
        freecon(fcon);
        freecon(fcon);


        if (different && lsetfilecon(path, secontext)) {
        if (different && lsetfilecon(path.c_str(), secontext)) {
            PLOG(ERROR) << "Cannot set '" << secontext << "' SELinux label on '" << path << "' device";
            PLOG(ERROR) << "Cannot set '" << secontext << "' SELinux label on '" << path << "' device";
        }
        }
    }
    }


out:
out:
    chown(path, uid, -1);
    chown(path.c_str(), uid, -1);
    if (setegid(AID_ROOT)) {
    if (setegid(AID_ROOT)) {
        PLOG(FATAL) << "setegid(AID_ROOT) failed";
        PLOG(FATAL) << "setegid(AID_ROOT) failed";
    }
    }
@@ -273,75 +262,25 @@ out:
    }
    }
}
}


void add_platform_device(const char* path) {
// TODO: Move this to be a member variable of a future devices class.
    int path_len = strlen(path);
std::vector<std::string> platform_devices;
    struct platform_node *bus;
    const char *name = path;

    if (!strncmp(path, "/devices/", 9)) {
        name += 9;
        if (!strncmp(name, "platform/", 9))
            name += 9;
    }


    LOG(VERBOSE) << "adding platform device " << name << " (" << path << ")";
// Given a path that may start with a platform device, find the length of the

// platform device prefix.  If it doesn't start with a platform device, return false
    bus = (platform_node*) calloc(1, sizeof(struct platform_node));
bool find_platform_device(const std::string& path, std::string* out_path) {
    bus->path = strdup(path);
    out_path->clear();
    bus->path_len = path_len;
    // platform_devices is searched backwards, since parents are added before their children,
    bus->name = bus->path + (name - path);
    // and we want to match as deep of a child as we can.
    list_add_tail(&platform_names, &bus->list);
    for (auto it = platform_devices.rbegin(); it != platform_devices.rend(); ++it) {
}
        auto platform_device_path_length = it->length();

        if (platform_device_path_length < path.length() &&
/*
            path[platform_device_path_length] == '/' &&
 * given a path that may start with a platform device, find the length of the
            android::base::StartsWith(path, it->c_str())) {
 * platform device prefix.  If it doesn't start with a platform device, return
            *out_path = *it;
 * 0.
            return true;
 */
static struct platform_node *find_platform_device(const char *path)
{
    int path_len = strlen(path);
    struct listnode *node;
    struct platform_node *bus;

    list_for_each_reverse(node, &platform_names) {
        bus = node_to_item(node, struct platform_node, list);
        if ((bus->path_len < path_len) &&
                (path[bus->path_len] == '/') &&
                !strncmp(path, bus->path, bus->path_len))
            return bus;
    }

    return NULL;
}

void remove_platform_device(const char* path) {
    struct listnode *node;
    struct platform_node *bus;

    list_for_each_reverse(node, &platform_names) {
        bus = node_to_item(node, struct platform_node, list);
        if (!strcmp(path, bus->path)) {
            LOG(INFO) << "removing platform device " << bus->name;
            free(bus->path);
            list_remove(node);
            free(bus);
            return;
        }
    }
        }
        }

static void destroy_platform_devices() {
    struct listnode* node;
    struct listnode* n;
    struct platform_node* bus;

    list_for_each_safe(node, n, &platform_names) {
        list_remove(node);
        bus = node_to_item(node, struct platform_node, list);
        free(bus->path);
        free(bus);
    }
    }
    return false;
}
}


/* Given a path that may start with a PCI device, populate the supplied buffer
/* Given a path that may start with a PCI device, populate the supplied buffer
@@ -398,19 +337,11 @@ static bool find_vbd_device_prefix(const std::string& path, std::string* result)
    return true;
    return true;
}
}


static void parse_event(const char *msg, struct uevent *uevent)
void parse_event(const char* msg, uevent* uevent) {
{
    uevent->partition_num = -1;
    uevent->action = "";
    uevent->path = "";
    uevent->subsystem = "";
    uevent->firmware = "";
    uevent->major = -1;
    uevent->major = -1;
    uevent->minor = -1;
    uevent->minor = -1;
    uevent->partition_name = NULL;
    // currently ignoring SEQNUM
    uevent->partition_num = -1;
    uevent->device_name = NULL;

        /* currently ignoring SEQNUM */
    while(*msg) {
    while(*msg) {
        if(!strncmp(msg, "ACTION=", 7)) {
        if(!strncmp(msg, "ACTION=", 7)) {
            msg += 7;
            msg += 7;
@@ -441,30 +372,26 @@ static void parse_event(const char *msg, struct uevent *uevent)
            uevent->device_name = msg;
            uevent->device_name = msg;
        }
        }


        /* advance to after the next \0 */
        // advance to after the next \0
        while(*msg++)
        while(*msg++)
            ;
            ;
    }
    }


    if (LOG_UEVENTS) {
    if (LOG_UEVENTS) {
        LOG(INFO) << android::base::StringPrintf("event { '%s', '%s', '%s', '%s', %d, %d }",
        LOG(INFO) << "event { '" << uevent->action << "', '" << uevent->path << "', '"
                                                 uevent->action, uevent->path, uevent->subsystem,
                  << uevent->subsystem << "', '" << uevent->firmware << "', " << uevent->major
                                                 uevent->firmware, uevent->major, uevent->minor);
                  << ", " << uevent->minor << " }";
    }
    }
}
}


std::vector<std::string> get_character_device_symlinks(uevent* uevent) {
std::vector<std::string> get_character_device_symlinks(uevent* uevent) {
    platform_node* pdev = find_platform_device(uevent->path);
    std::string parent_device;
    if (!pdev) return {};
    if (!find_platform_device(uevent->path, &parent_device)) return {};

    /* skip "/devices/platform/<driver>" */
    std::string parent = std::string(uevent->path);
    auto parent_start = parent.find('/', pdev->path_len);
    if (parent_start == std::string::npos) return {};


    parent.erase(0, parent_start);
    // skip path to the parent driver
    std::string path = uevent->path.substr(parent_device.length());


    if (!android::base::StartsWith(parent, "/usb")) return {};
    if (!android::base::StartsWith(path, "/usb")) return {};


    // skip root hub name and device. use device interface
    // skip root hub name and device. use device interface
    // skip 3 slashes, including the first / by starting the search at the 1st character, not 0th.
    // skip 3 slashes, including the first / by starting the search at the 1st character, not 0th.
@@ -472,13 +399,13 @@ std::vector<std::string> get_character_device_symlinks(uevent* uevent) {
    // e.g. "/usb/usb_device/name/tty2-1:1.0" -> "name"
    // e.g. "/usb/usb_device/name/tty2-1:1.0" -> "name"


    std::string::size_type start = 0;
    std::string::size_type start = 0;
    start = parent.find('/', start + 1);
    start = path.find('/', start + 1);
    if (start == std::string::npos) return {};
    if (start == std::string::npos) return {};


    start = parent.find('/', start + 1);
    start = path.find('/', start + 1);
    if (start == std::string::npos) return {};
    if (start == std::string::npos) return {};


    auto end = parent.find('/', start + 1);
    auto end = path.find('/', start + 1);
    if (end == std::string::npos) return {};
    if (end == std::string::npos) return {};


    start++;  // Skip the first '/'
    start++;  // Skip the first '/'
@@ -486,11 +413,10 @@ std::vector<std::string> get_character_device_symlinks(uevent* uevent) {
    auto length = end - start;
    auto length = end - start;
    if (length == 0) return {};
    if (length == 0) return {};


    auto name_string = parent.substr(start, length);
    auto name_string = path.substr(start, length);


    // TODO: remove std::string() when uevent->subsystem is an std::string
    std::vector<std::string> links;
    std::vector<std::string> links;
    links.emplace_back("/dev/usb/" + std::string(uevent->subsystem) + name_string);
    links.emplace_back("/dev/usb/" + uevent->subsystem + name_string);


    mkdir("/dev/usb", 0755);
    mkdir("/dev/usb", 0755);


@@ -516,12 +442,19 @@ void sanitize_partition_name(std::string* string) {


std::vector<std::string> get_block_device_symlinks(uevent* uevent) {
std::vector<std::string> get_block_device_symlinks(uevent* uevent) {
    std::string device;
    std::string device;
    struct platform_node* pdev;
    std::string type;
    std::string type;


    pdev = find_platform_device(uevent->path);
    if (find_platform_device(uevent->path, &device)) {
    if (pdev) {
        // Skip /devices/platform or /devices/ if present
        device = pdev->name;
        static const std::string devices_platform_prefix = "/devices/platform/";
        static const std::string devices_prefix = "/devices/";

        if (android::base::StartsWith(device, devices_platform_prefix.c_str())) {
            device = device.substr(devices_platform_prefix.length());
        } else if (android::base::StartsWith(device, devices_prefix.c_str())) {
            device = device.substr(devices_prefix.length());
        }

        type = "platform";
        type = "platform";
    } else if (find_pci_device_prefix(uevent->path, &device)) {
    } else if (find_pci_device_prefix(uevent->path, &device)) {
        type = "pci";
        type = "pci";
@@ -537,7 +470,7 @@ std::vector<std::string> get_block_device_symlinks(uevent* uevent) {


    auto link_path = "/dev/block/" + type + "/" + device;
    auto link_path = "/dev/block/" + type + "/" + device;


    if (uevent->partition_name) {
    if (!uevent->partition_name.empty()) {
        std::string partition_name_sanitized(uevent->partition_name);
        std::string partition_name_sanitized(uevent->partition_name);
        sanitize_partition_name(&partition_name_sanitized);
        sanitize_partition_name(&partition_name_sanitized);
        if (partition_name_sanitized != uevent->partition_name) {
        if (partition_name_sanitized != uevent->partition_name) {
@@ -551,57 +484,51 @@ std::vector<std::string> get_block_device_symlinks(uevent* uevent) {
        links.emplace_back(link_path + "/by-num/p" + std::to_string(uevent->partition_num));
        links.emplace_back(link_path + "/by-num/p" + std::to_string(uevent->partition_num));
    }
    }


    // TODO: remove uevent_path when uevent->path is an std::string
    auto last_slash = uevent->path.rfind('/');
    std::string uevent_path = uevent->path;
    links.emplace_back(link_path + "/" + uevent->path.substr(last_slash + 1));
    auto last_slash = uevent_path.rfind('/');
    links.emplace_back(link_path + "/" + uevent_path.substr(last_slash + 1));


    return links;
    return links;
}
}


static void make_link_init(const char* oldpath, const char* newpath) {
static void make_link_init(const std::string& oldpath, const std::string& newpath) {
  const char* slash = strrchr(newpath, '/');
    if (mkdir_recursive(dirname(newpath.c_str()), 0755)) {
  if (!slash) return;
        PLOG(ERROR) << "Failed to create directory " << dirname(newpath.c_str());

  if (mkdir_recursive(dirname(newpath), 0755)) {
    PLOG(ERROR) << "Failed to create directory " << dirname(newpath);
    }
    }


  if (symlink(oldpath, newpath) && errno != EEXIST) {
    if (symlink(oldpath.c_str(), newpath.c_str()) && errno != EEXIST) {
        PLOG(ERROR) << "Failed to symlink " << oldpath << " to " << newpath;
        PLOG(ERROR) << "Failed to symlink " << oldpath << " to " << newpath;
    }
    }
}
}


static void remove_link(const char* oldpath, const char* newpath) {
static void remove_link(const std::string& oldpath, const std::string& newpath) {
    std::string path;
    std::string path;
  if (android::base::Readlink(newpath, &path) && path == oldpath) unlink(newpath);
    if (android::base::Readlink(newpath, &path) && path == oldpath) unlink(newpath.c_str());
}
}


static void handle_device(const char* action, const char* devpath, const char* path, int block,
static void handle_device(const std::string& action, const std::string& devpath, int block,
                          int major, int minor, const std::vector<std::string>& links) {
                          int major, int minor, const std::vector<std::string>& links) {
    if(!strcmp(action, "add")) {
    if (action == "add") {
        make_device(devpath, path, block, major, minor, links);
        make_device(devpath, block, major, minor, links);
        for (const auto& link : links) {
        for (const auto& link : links) {
            make_link_init(devpath, link.c_str());
            make_link_init(devpath, link);
        }
        }
    }
    }


    if(!strcmp(action, "remove")) {
    if (action == "remove") {
        for (const auto& link : links) {
        for (const auto& link : links) {
            remove_link(devpath, link.c_str());
            remove_link(devpath, link);
        }
        }
        unlink(devpath);
        unlink(devpath.c_str());
    }
    }
}
}


static void handle_platform_device_event(struct uevent *uevent)
void handle_platform_device_event(uevent* uevent) {
{
    if (uevent->action == "add") {
    const char *path = uevent->path;
        platform_devices.emplace_back(uevent->path);

    } else if (uevent->action == "remove") {
    if (!strcmp(uevent->action, "add"))
        auto it = std::find(platform_devices.begin(), platform_devices.end(), uevent->path);
        add_platform_device(path);
        if (it != platform_devices.end()) platform_devices.erase(it);
    else if (!strcmp(uevent->action, "remove"))
    }
        remove_platform_device(path);
}
}


static void handle_block_device_event(uevent* uevent) {
static void handle_block_device_event(uevent* uevent) {
@@ -615,11 +542,11 @@ static void handle_block_device_event(uevent* uevent) {
    std::string devpath = base + name;
    std::string devpath = base + name;


    std::vector<std::string> links;
    std::vector<std::string> links;
    if (!strncmp(uevent->path, "/devices/", 9))
    if (android::base::StartsWith(uevent->path, "/devices")) {
        links = get_block_device_symlinks(uevent);
        links = get_block_device_symlinks(uevent);
    }


    handle_device(uevent->action, devpath.c_str(), uevent->path, 1, uevent->major, uevent->minor,
    handle_device(uevent->action, devpath, 1, uevent->major, uevent->minor, links);
                  links);
}
}


static void handle_generic_device_event(uevent* uevent) {
static void handle_generic_device_event(uevent* uevent) {
@@ -627,7 +554,7 @@ static void handle_generic_device_event(uevent* uevent) {
    if (uevent->major < 0 || uevent->minor < 0) return;
    if (uevent->major < 0 || uevent->minor < 0) return;


    std::string name = android::base::Basename(uevent->path);
    std::string name = android::base::Basename(uevent->path);
    ueventd_subsystem* subsystem = ueventd_subsystem_find_by_name(uevent->subsystem);
    ueventd_subsystem* subsystem = ueventd_subsystem_find_by_name(uevent->subsystem.c_str());


    std::string devpath;
    std::string devpath;


@@ -651,11 +578,10 @@ static void handle_generic_device_event(uevent* uevent) {
        // TODO: Remove std::string()
        // TODO: Remove std::string()
        devpath = std::string(subsystem->dirname) + "/" + devname;
        devpath = std::string(subsystem->dirname) + "/" + devname;
        mkdir_recursive(android::base::Dirname(devpath), 0755);
        mkdir_recursive(android::base::Dirname(devpath), 0755);
    } else if (!strncmp(uevent->subsystem, "usb", 3)) {
    } else if (android::base::StartsWith(uevent->subsystem, "usb")) {
        if (!strcmp(uevent->subsystem, "usb")) {
        if (uevent->subsystem == "usb") {
            if (uevent->device_name) {
            if (!uevent->device_name.empty()) {
                // TODO: Remove std::string
                devpath = "/dev/" + uevent->device_name;
                devpath = "/dev/" + std::string(uevent->device_name);
            } else {
            } else {
                // This imitates the file system that would be created
                // This imitates the file system that would be created
                // if we were using devfs instead.
                // if we were using devfs instead.
@@ -675,18 +601,18 @@ static void handle_generic_device_event(uevent* uevent) {


    auto links = get_character_device_symlinks(uevent);
    auto links = get_character_device_symlinks(uevent);


    handle_device(uevent->action, devpath.c_str(), uevent->path, 0, uevent->major, uevent->minor,
    handle_device(uevent->action, devpath, 0, uevent->major, uevent->minor, links);
                  links);
}
}


static void handle_device_event(struct uevent *uevent)
static void handle_device_event(struct uevent *uevent)
{
{
    if (!strcmp(uevent->action,"add") || !strcmp(uevent->action, "change") || !strcmp(uevent->action, "online"))
    if (uevent->action == "add" || uevent->action == "change" || uevent->action == "online") {
        fixup_sys_perms(uevent->path, uevent->subsystem);
        fixup_sys_perms(uevent->path, uevent->subsystem);
    }


    if (!strncmp(uevent->subsystem, "block", 5)) {
    if (uevent->subsystem == "block") {
        handle_block_device_event(uevent);
        handle_block_device_event(uevent);
    } else if (!strncmp(uevent->subsystem, "platform", 8)) {
    } else if (uevent->subsystem == "platform") {
        handle_platform_device_event(uevent);
        handle_platform_device_event(uevent);
    } else {
    } else {
        handle_generic_device_event(uevent);
        handle_generic_device_event(uevent);
@@ -719,7 +645,7 @@ static void process_firmware_event(uevent* uevent) {


    LOG(INFO) << "firmware: loading '" << uevent->firmware << "' for '" << uevent->path << "'";
    LOG(INFO) << "firmware: loading '" << uevent->firmware << "' for '" << uevent->path << "'";


    std::string root = android::base::StringPrintf("/sys%s", uevent->path);
    std::string root = "/sys" + uevent->path;
    std::string loading = root + "/loading";
    std::string loading = root + "/loading";
    std::string data = root + "/data";
    std::string data = root + "/data";


@@ -735,9 +661,12 @@ static void process_firmware_event(uevent* uevent) {
        return;
        return;
    }
    }


    static const char* firmware_dirs[] = {"/etc/firmware/", "/vendor/firmware/",
                                          "/firmware/image/"};

try_loading_again:
try_loading_again:
    for (size_t i = 0; i < arraysize(firmware_dirs); i++) {
    for (size_t i = 0; i < arraysize(firmware_dirs); i++) {
        std::string file = android::base::StringPrintf("%s/%s", firmware_dirs[i], uevent->firmware);
        std::string file = firmware_dirs[i] + uevent->firmware;
        android::base::unique_fd fw_fd(open(file.c_str(), O_RDONLY|O_CLOEXEC));
        android::base::unique_fd fw_fd(open(file.c_str(), O_RDONLY|O_CLOEXEC));
        struct stat sb;
        struct stat sb;
        if (fw_fd != -1 && fstat(fw_fd, &sb) != -1) {
        if (fw_fd != -1 && fstat(fw_fd, &sb) != -1) {
@@ -761,8 +690,7 @@ try_loading_again:
}
}


static void handle_firmware_event(uevent* uevent) {
static void handle_firmware_event(uevent* uevent) {
    if (strcmp(uevent->subsystem, "firmware")) return;
    if (uevent->subsystem != "firmware" || uevent->action != "add") return;
    if (strcmp(uevent->action, "add")) return;


    // Loading the firmware in a child means we can do that in parallel...
    // Loading the firmware in a child means we can do that in parallel...
    // (We ignore SIGCHLD rather than wait for our children.)
    // (We ignore SIGCHLD rather than wait for our children.)
@@ -796,7 +724,7 @@ static inline coldboot_action_t handle_device_fd_with(
        msg[n] = '\0';
        msg[n] = '\0';
        msg[n+1] = '\0';
        msg[n+1] = '\0';


        struct uevent uevent;
        uevent uevent;
        parse_event(msg, &uevent);
        parse_event(msg, &uevent);
        coldboot_action_t act = handle_uevent(&uevent);
        coldboot_action_t act = handle_uevent(&uevent);
        if (should_stop_coldboot(act))
        if (should_stop_coldboot(act))
@@ -940,7 +868,7 @@ void device_init(const char* path, coldboot_callback fn) {
}
}


void device_close() {
void device_close() {
    destroy_platform_devices();
    platform_devices.clear();
    device_fd.reset();
    device_fd.reset();
    selinux_status_close();
    selinux_status_close();
}
}
+9 −8
Original line number Original line Diff line number Diff line
@@ -36,12 +36,12 @@ enum coldboot_action_t {
};
};


struct uevent {
struct uevent {
    const char* action;
    std::string action;
    const char* path;
    std::string path;
    const char* subsystem;
    std::string subsystem;
    const char* firmware;
    std::string firmware;
    const char* partition_name;
    std::string partition_name;
    const char* device_name;
    std::string device_name;
    int partition_num;
    int partition_num;
    int major;
    int major;
    int minor;
    int minor;
@@ -59,10 +59,11 @@ extern int add_dev_perms(const char *name, const char *attr,
int get_device_fd();
int get_device_fd();


// Exposed for testing
// Exposed for testing
void add_platform_device(const char* path);
extern std::vector<std::string> platform_devices;
void remove_platform_device(const char* path);
bool find_platform_device(const std::string& path, std::string* out_path);
std::vector<std::string> get_character_device_symlinks(uevent* uevent);
std::vector<std::string> get_character_device_symlinks(uevent* uevent);
std::vector<std::string> get_block_device_symlinks(uevent* uevent);
std::vector<std::string> get_block_device_symlinks(uevent* uevent);
void sanitize_partition_name(std::string* string);
void sanitize_partition_name(std::string* string);
void handle_platform_device_event(uevent* uevent);


#endif /* _INIT_DEVICES_H */
#endif /* _INIT_DEVICES_H */
+53 −11
Original line number Original line Diff line number Diff line
@@ -22,12 +22,26 @@
#include <android-base/scopeguard.h>
#include <android-base/scopeguard.h>
#include <gtest/gtest.h>
#include <gtest/gtest.h>


void add_platform_device(const std::string& path) {
    uevent uevent = {
        .action = "add", .subsystem = "platform", .path = path,
    };
    handle_platform_device_event(&uevent);
}

void remove_platform_device(const std::string& path) {
    uevent uevent = {
        .action = "remove", .subsystem = "platform", .path = path,
    };
    handle_platform_device_event(&uevent);
}

template <std::vector<std::string> (*Function)(uevent*)>
template <std::vector<std::string> (*Function)(uevent*)>
void test_get_symlinks(const std::string& platform_device_name, uevent* uevent,
void test_get_symlinks(const std::string& platform_device_name, uevent* uevent,
                       const std::vector<std::string> expected_links) {
                       const std::vector<std::string> expected_links) {
    add_platform_device(platform_device_name.c_str());
    add_platform_device(platform_device_name);
    auto platform_device_remover = android::base::make_scope_guard(
    auto platform_device_remover = android::base::make_scope_guard(
        [&platform_device_name]() { remove_platform_device(platform_device_name.c_str()); });
        [&platform_device_name]() { remove_platform_device(platform_device_name); });


    std::vector<std::string> result = Function(uevent);
    std::vector<std::string> result = Function(uevent);


@@ -41,6 +55,36 @@ void test_get_symlinks(const std::string& platform_device_name, uevent* uevent,
    }
    }
}
}


TEST(devices, handle_platform_device_event) {
    platform_devices.clear();
    add_platform_device("/devices/platform/some_device_name");
    ASSERT_EQ(1U, platform_devices.size());
    remove_platform_device("/devices/platform/some_device_name");
    ASSERT_EQ(0U, platform_devices.size());
}

TEST(devices, find_platform_device) {
    platform_devices.clear();
    add_platform_device("/devices/platform/some_device_name");
    add_platform_device("/devices/platform/some_device_name/longer");
    add_platform_device("/devices/platform/other_device_name");
    EXPECT_EQ(3U, platform_devices.size());

    std::string out_path;
    EXPECT_FALSE(find_platform_device("/devices/platform/not_found", &out_path));
    EXPECT_EQ("", out_path);

    EXPECT_FALSE(
        find_platform_device("/devices/platform/some_device_name_with_same_prefix", &out_path));

    EXPECT_TRUE(
        find_platform_device("/devices/platform/some_device_name/longer/longer_child", &out_path));
    EXPECT_EQ("/devices/platform/some_device_name/longer", out_path);

    EXPECT_TRUE(find_platform_device("/devices/platform/some_device_name/other_child", &out_path));
    EXPECT_EQ("/devices/platform/some_device_name", out_path);
}

TEST(devices, get_character_device_symlinks_success) {
TEST(devices, get_character_device_symlinks_success) {
    const char* platform_device = "/devices/platform/some_device_name";
    const char* platform_device = "/devices/platform/some_device_name";
    uevent uevent = {
    uevent uevent = {
@@ -127,7 +171,7 @@ TEST(devices, get_block_device_symlinks_success_platform) {
    const char* platform_device = "/devices/soc.0/f9824900.sdhci";
    const char* platform_device = "/devices/soc.0/f9824900.sdhci";
    uevent uevent = {
    uevent uevent = {
        .path = "/devices/soc.0/f9824900.sdhci/mmc_host/mmc0/mmc0:0001/block/mmcblk0",
        .path = "/devices/soc.0/f9824900.sdhci/mmc_host/mmc0/mmc0:0001/block/mmcblk0",
        .partition_name = nullptr,
        .partition_name = "",
        .partition_num = -1,
        .partition_num = -1,
    };
    };
    std::vector<std::string> expected_result{"/dev/block/platform/soc.0/f9824900.sdhci/mmcblk0"};
    std::vector<std::string> expected_result{"/dev/block/platform/soc.0/f9824900.sdhci/mmcblk0"};
@@ -156,7 +200,7 @@ TEST(devices, get_block_device_symlinks_success_platform_with_partition_only_num
    const char* platform_device = "/devices/soc.0/f9824900.sdhci";
    const char* platform_device = "/devices/soc.0/f9824900.sdhci";
    uevent uevent = {
    uevent uevent = {
        .path = "/devices/soc.0/f9824900.sdhci/mmc_host/mmc0/mmc0:0001/block/mmcblk0p1",
        .path = "/devices/soc.0/f9824900.sdhci/mmc_host/mmc0/mmc0:0001/block/mmcblk0p1",
        .partition_name = nullptr,
        .partition_name = "",
        .partition_num = 1,
        .partition_num = 1,
    };
    };
    std::vector<std::string> expected_result{
    std::vector<std::string> expected_result{
@@ -185,9 +229,7 @@ TEST(devices, get_block_device_symlinks_success_platform_with_partition_only_nam
TEST(devices, get_block_device_symlinks_success_pci) {
TEST(devices, get_block_device_symlinks_success_pci) {
    const char* platform_device = "/devices/do/not/match";
    const char* platform_device = "/devices/do/not/match";
    uevent uevent = {
    uevent uevent = {
        .path = "/devices/pci0000:00/0000:00:1f.2/mmcblk0",
        .path = "/devices/pci0000:00/0000:00:1f.2/mmcblk0", .partition_name = "", .partition_num = -1,
        .partition_name = nullptr,
        .partition_num = -1,
    };
    };
    std::vector<std::string> expected_result{"/dev/block/pci/pci0000:00/0000:00:1f.2/mmcblk0"};
    std::vector<std::string> expected_result{"/dev/block/pci/pci0000:00/0000:00:1f.2/mmcblk0"};


@@ -197,7 +239,7 @@ TEST(devices, get_block_device_symlinks_success_pci) {
TEST(devices, get_block_device_symlinks_pci_bad_format) {
TEST(devices, get_block_device_symlinks_pci_bad_format) {
    const char* platform_device = "/devices/do/not/match";
    const char* platform_device = "/devices/do/not/match";
    uevent uevent = {
    uevent uevent = {
        .path = "/devices/pci//mmcblk0", .partition_name = nullptr, .partition_num = -1,
        .path = "/devices/pci//mmcblk0", .partition_name = "", .partition_num = -1,
    };
    };
    std::vector<std::string> expected_result{};
    std::vector<std::string> expected_result{};


@@ -207,7 +249,7 @@ TEST(devices, get_block_device_symlinks_pci_bad_format) {
TEST(devices, get_block_device_symlinks_success_vbd) {
TEST(devices, get_block_device_symlinks_success_vbd) {
    const char* platform_device = "/devices/do/not/match";
    const char* platform_device = "/devices/do/not/match";
    uevent uevent = {
    uevent uevent = {
        .path = "/devices/vbd-1234/mmcblk0", .partition_name = nullptr, .partition_num = -1,
        .path = "/devices/vbd-1234/mmcblk0", .partition_name = "", .partition_num = -1,
    };
    };
    std::vector<std::string> expected_result{"/dev/block/vbd/1234/mmcblk0"};
    std::vector<std::string> expected_result{"/dev/block/vbd/1234/mmcblk0"};


@@ -217,7 +259,7 @@ TEST(devices, get_block_device_symlinks_success_vbd) {
TEST(devices, get_block_device_symlinks_vbd_bad_format) {
TEST(devices, get_block_device_symlinks_vbd_bad_format) {
    const char* platform_device = "/devices/do/not/match";
    const char* platform_device = "/devices/do/not/match";
    uevent uevent = {
    uevent uevent = {
        .path = "/devices/vbd-/mmcblk0", .partition_name = nullptr, .partition_num = -1,
        .path = "/devices/vbd-/mmcblk0", .partition_name = "", .partition_num = -1,
    };
    };
    std::vector<std::string> expected_result{};
    std::vector<std::string> expected_result{};


@@ -228,7 +270,7 @@ TEST(devices, get_block_device_symlinks_no_matches) {
    const char* platform_device = "/devices/soc.0/f9824900.sdhci";
    const char* platform_device = "/devices/soc.0/f9824900.sdhci";
    uevent uevent = {
    uevent uevent = {
        .path = "/devices/soc.0/not_the_device/mmc_host/mmc0/mmc0:0001/block/mmcblk0p1",
        .path = "/devices/soc.0/not_the_device/mmc_host/mmc0/mmc0:0001/block/mmcblk0p1",
        .partition_name = nullptr,
        .partition_name = "",
        .partition_num = -1,
        .partition_num = -1,
    };
    };
    std::vector<std::string> expected_result;
    std::vector<std::string> expected_result;
+4 −8

File changed.

Preview size limit exceeded, changes collapsed.