Android源码阅读——toolbox可执行文件

在研究属性服务setprop和getprop时,发现这两个可执行文件链接的是toolbox,由此分析下toolbox源码
bp文件定义
/system/core/toolbox/Android.bp

cc_defaults {
    name: "toolbox_binary_defaults",
    defaults: ["toolbox_defaults"],
    #包含的源文件
    srcs: [
        "toolbox.c",
        "getevent.c",
        "getprop.cpp",
        "modprobe.cpp",
        "setprop.cpp",
        "start.cpp",
    ],
    generated_headers: [
        "toolbox_input_labels",
    ],
    shared_libs: [
        "libbase",
    ],
    static_libs: [
        "libmodprobe",
        "libpropertyinfoparser",
    ],

	#创建的符号链接,这些都会链接向toolbox
    symlinks: [
        "getevent",
        "getprop",
        "modprobe",
        "setprop",
        "start",
        "stop",
    ],
}

#编译成可执行文件toolbox
cc_binary {
    name: "toolbox",
    defaults: ["toolbox_binary_defaults"],
    recovery_available: true,
}

toolbox包含6个源文件,创建了6个符号链接。
当使用上面的这些命令的时候,就会调用到toolbox中的main函数
/system/core/toolbox/toolbox.c

static struct {
    const char* name;
    int (*func)(int, char**);
} tools[] = {
#define TOOL(name) { #name, name##_main },
#include "tools.h"
#undef TOOL
    { 0, 0 },
};
int main(int argc, char** argv) {
    // Let's assume that none of this code handles broken pipes. At least ls,
    // ps, and top were broken (though I'd previously added this fix locally
    // to top). We exit rather than use SIG_IGN because tools like top will
    // just keep on writing to nowhere forever if we don't stop them.
    signal(SIGPIPE, SIGPIPE_handler);

    char* cmd = strrchr(argv[0], '/');
    char* name = cmd ? (cmd + 1) : argv[0];

    for (size_t i = 0; tools[i].name; i++) {
        if (!strcmp(tools[i].name, name)) {
            return tools[i].func(argc, argv);
        }
    }

    printf("%s: no such tool\n", argv[0]);
    return 127;
}

main函数就是遍历tools这个数组,这个数组存入的就是各个命令名及命令名加上_main对应的函数。
TOOL是一个宏定义,用于拼接命令名_mian,构造对应的处理函数。
然后通过tools.h头文件导入对应关系
/system/core/toolbox/tools.h

TOOL(getevent)
TOOL(getprop)
TOOL(modprobe)
TOOL(setprop)
TOOL(start)
TOOL(stop)
TOOL(toolbox)

以setprop为例,当使用setprop时,会走到toolbox中的main函数,根据tools这个数组,获得对应的函数并执行,setprop对应的函数为setprop_main函数。
/system/core/toolbox/setprop.cpp

extern "C" int setprop_main(int argc, char** argv) {
    if (argc != 3) {
        std::cout << "usage: setprop NAME VALUE\n"
                     "\n"
                     "Sets an Android system property."
                  << std::endl;
        return EXIT_FAILURE;
    }

    auto name = std::string{argv[1]};
    auto value = std::string{argv[2]};

    // SetProperty() doesn't tell us why it failed, and actually can't recognize most failures, so
    // we duplicate some of init's checks here to help the user.

    if (name.front() == '.' || name.back() == '.') {
        std::cerr << "Property names must not start or end with a '.'" << std::endl;
        return EXIT_FAILURE;
    }

    if (name.find("..") != std::string::npos) {
        std::cerr << "'..' is not allowed in a property name" << std::endl;
        return EXIT_FAILURE;
    }

    for (const auto& c : name) {
        if (!isalnum(c) && !strchr(":@_.-", c)) {
            std::cerr << "Invalid character '" << c << "' in name '" << name << "'" << std::endl;
            return EXIT_FAILURE;
        }
    }

    if (value.size() >= PROP_VALUE_MAX && !StartsWith(value, "ro.")) {
        std::cerr << "Value '" << value << "' is too long, " << value.size()
                  << " bytes vs a max of " << PROP_VALUE_MAX << std::endl;
        return EXIT_FAILURE;
    }

    if (mbstowcs(nullptr, value.data(), 0) == static_cast<std::size_t>(-1)) {
        std::cerr << "Value '" << value << "' is not a UTF8 encoded string" << std::endl;
        return EXIT_FAILURE;
    }

    if (!SetProperty(name, value)) {
        std::cerr << "Failed to set property '" << name << "' to '" << value
                  << "'.\nSee dmesg for error reason." << std::endl;
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

判断合法性,调用SetProperty设置属性

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值