adb 工具源码修改

adb 工具源码修改

1、修改客户端输入后的判断逻辑,使带密码的命令 可以通过命令检查

修改 system/core/adb/client/commandline.cpp

在最前面 新增一个函数 用来处理 自定义带密码的命令

//add by dk start
std::string get_command(const char* c){   
    std::string s= c;
    if(s.find("-") != std::string::npos){
    	char buf[20];
    	strcpy(buf,s.c_str());
    	char* str1= strtok(buf, " -");
    	fprintf(stderr, "adb:strock----\"%s\"\n", str1);
		return str1;
    }

    char * p=(char*)s.c_str();
    fprintf(stderr, "adb:buf****----\"%s\"\n", p);
    return s;
       
}
//add by dk end

对 adb_commandline(int argc, const char** argv) 函数内容进行修改 此函数 是对adb 命令进行校验 和处理

argv 是输入的命令和参数 数组 argv[0] 表示的是 命令字段

	//add by dk start  
	//获取处理后的命令
	fprintf(stderr, "adb:--command--\"%s\"\n", argv[0]);
    std::string str1=get_command(argv[0]);
    fprintf(stderr, "adb:get_command----\"%s\"\n", str1.c_str());
    //add by dk end
   	//add by dk
	//修改root 命令判断,用处理后的命令匹配
    else if (!strcmp(str1.c_str(), "root") || !strcmp(argv[0], "unroot")){
        return adb_root(argv[0]) ? 0 : 1;
    } 
  //修改shell 命令判断,用处理后的命令匹配
  	else if (!strcmp(str1.c_str(), "shell")) {
        return adb_shell(argc, argv);
    } 
//修改push pull  命令判断,用处理后的命令匹配
 else if (!strcmp(str1.c_str(), "push")) {
        bool copy_attrs = false;
        bool sync = false;
        bool compressed = true;
        std::vector<const char*> srcs;
        const char* dst = nullptr;

        parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, &copy_attrs, &sync, &compressed);
        if (srcs.empty() || !dst) error_exit("push requires an argument");
        //return do_sync_push(srcs, dst, sync, compressed) ? 0 : 1;
		
		//add by dakun
		std::string pass_s=argv[0];
		auto sub = pass_s+":";
		fprintf(stderr, "adb:push----\"%s\"\n", sub.c_str());
		return do_sync_push(srcs, dst, sync, compressed,sub.c_str()) ? 0 : 1;
		//add end
    } else if (!strcmp(str1.c_str(), "pull")) {
        bool copy_attrs = false;
        bool compressed = true;
        std::vector<const char*> srcs;
        const char* dst = ".";

        parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, &copy_attrs, nullptr, &compressed);
        if (srcs.empty()) error_exit("pull requires an argument");
		//return do_sync_pull(srcs, dst, copy_attrs, compressed) ? 0 : 1;
		
		//add by dakun
		std::string pass_s=argv[0];
		auto sub = pass_s+":";
        return do_sync_pull(srcs, dst, copy_attrs,compressed, sub.c_str(),nullptr) ? 0 : 1;
		//add end
    }

在命令后都会调用 adb_connect()方法去进行与服务端通信,但是 shell 和push pull 命令 会进行进一步处理。

对 shell 命令进行追踪处理

修改adb_shell(int argc, const char** argv) 方法

在方法的最后 通过调用 RemoteShell 来进一步调用 adb_connect ,发现 在进行 adb_connect 时所传递的service_string 是 ShellServiceString 方法生成的

//std::string service_string = ShellServiceString(use_shell_protocol, shell_type_arg, command);
//add by dakun
 std::string service_string = ShellServiceString(use_shell_protocol, shell_type_arg, command,sp.c_str());
  return RemoteShell(use_shell_protocol, shell_type_arg, escape_char, command.empty(),service_string);

在 ShellServiceString 方法中可以看到 service_string 方是通过StringPrintf 进行拼接 ,

在这里需要重载一个 ShellServiceString 方法将 带密码的shell 传入 拼接到一起。

//add by dakun
static std::string ShellServiceString(bool use_shell_protocol,
                                      const std::string& type_arg,
                                      const std::string& command,
									  const std::string& pass) {
    std::vector<std::string> args;
    if (use_shell_protocol) {
        args.push_back(kShellServiceArgShellProtocol);

        const char* terminal_type = getenv("TERM");
        if (terminal_type != nullptr) {
            args.push_back(std::string("TERM=") + terminal_type);
        }
    }
    if (!type_arg.empty()) {
        args.push_back(type_arg);
    }

    // Shell service string can look like: shell[,arg1,arg2,...]:[command].
    return android::base::StringPrintf("%s%s%s:%s",
									   pass.c_str(),
                                       args.empty() ? "" : ",",
                                       android::base::Join(args, ',').c_str(),
                                       command.c_str());
}

在 adb_shell(int argc, const char** argv) 中 会对argv[0] 重新赋值,所以在最开始要先获取传入的密码

//add by dakun
std::string sp=argv[0]; 
fprintf(stderr, "adb:strcat----\"%s\"\n", sp.c_str());

// Parse shell-specific command-line options.
argv[0] = "adb shell"; // So getopt(3) error messages start "adb shell".

对push 和 pull 命令进行追踪处理

push 和 pull 命令都是通过 sync 命令同步实现的

在匹配命令之后最终会调用 do_sync_push和 do_sync_pull 这两个方法来执行上传

通过追踪 发现这是在file_sync_client.cpp 中的方法

在这两个方法中能找到 SyncConnection 类 ,追踪这个类的构造可以发现 在这个构造方法中进行了

adb_connect(“sync-”, &error) ,所以想要将密码传入需要 新增一个带参数的构造用来传密码

//add by dakun 
  public:
    SyncConnection(std::string_view s) : acknowledgement_buffer_(sizeof(sync_status) + SYNC_DATA_MAX) {
        acknowledgement_buffer_.resize(0);
        max = SYNC_DATA_MAX; // TODO: decide at runtime.

        std::string error;
        if (!adb_get_feature_set(&features_, &error)) {
            Error("failed to get feature set: %s", error.c_str());
        } else {
            have_stat_v2_ = CanUseFeature(features_, kFeatureStat2);
            have_ls_v2_ = CanUseFeature(features_, kFeatureLs2);
            have_sendrecv_v2_ = CanUseFeature(features_, kFeatureSendRecv2);
            have_sendrecv_v2_brotli_ = CanUseFeature(features_, kFeatureSendRecv2Brotli);
            fd.reset(adb_connect(s, &error));
            if (fd < 0) {
                Error("connect failed: %s", error.c_str());
            }
        }
    }
//add end

同样也新增一个带密码参数的 do_sync_push 或 do_sync_pull 方法 ,在这个方法中调用 带参数的

SyncConnection(std::string_view s) 构造方法

//add by dakun
bool do_sync_push(const std::vector<const char*>& srcs, const char* dst, bool sync, bool compressed,const char* pass) {
    SyncConnection sc(pass);
    if (!sc.IsValid()) return false;

    bool success = true;
    bool dst_exists;
    bool dst_isdir;

    struct stat st;
    if (sync_stat_fallback(sc, dst, &st)) {
        dst_exists = true;
        dst_isdir = S_ISDIR(st.st_mode);
    } else {
        if (errno == ENOENT || errno == ENOPROTOOPT) {
            dst_exists = false;
            dst_isdir = false;
        } else {
            sc.Error("stat failed when trying to push to %s: %s", dst, strerror(errno));
            return false;
        }
    }

    if (!dst_isdir) {
        if (srcs.size() > 1) {
            sc.Error("target '%s' is not a directory", dst);
            return false;
        } else {
            size_t dst_len = strlen(dst);

            // A path that ends with a slash doesn't have to be a directory if
            // it doesn't exist yet.
            if (dst[dst_len - 1] == '/' && dst_exists) {
                sc.Error("failed to access '%s': Not a directory", dst);
                return false;
            }
        }
    }

    for (const char* src_path : srcs) {
        const char* dst_path = dst;
        struct stat st;
        if (stat(src_path, &st) == -1) {
            sc.Error("cannot stat '%s': %s", src_path, strerror(errno));
            success = false;
            continue;
        }

        if (S_ISDIR(st.st_mode)) {
            std::string dst_dir = dst;

            // If the destination path existed originally, the source directory
            // should be copied as a child of the destination.
            if (dst_exists) {
                if (!dst_isdir) {
                    sc.Error("target '%s' is not a directory", dst);
                    return false;
                }
                // dst is a POSIX path, so we don't want to use the sysdeps
                // helpers here.
                if (dst_dir.back() != '/') {
                    dst_dir.push_back('/');
                }
                dst_dir.append(android::base::Basename(src_path));
            }

            success &= copy_local_dir_remote(sc, src_path, dst_dir, sync, false, compressed);
            continue;
        } else if (!should_push_file(st.st_mode)) {
            sc.Warning("skipping special file '%s' (mode = 0o%o)", src_path, st.st_mode);
            continue;
        }

        std::string path_holder;
        if (dst_isdir) {
            // If we're copying a local file to a remote directory,
            // we really want to copy to remote_dir + "/" + local_filename.
            path_holder = dst_path;
            if (path_holder.back() != '/') {
                path_holder.push_back('/');
            }
            path_holder += android::base::Basename(src_path);
            dst_path = path_holder.c_str();
        }

        sc.NewTransfer();
        sc.SetExpectedTotalBytes(st.st_size);
        success &= sync_send(sc, src_path, dst_path, st.st_mtime, st.st_mode, sync, compressed);
        sc.ReportTransferRate(src_path, TransferDirection::push);
    }

    success &= sc.ReadAcknowledgements(true);
    sc.ReportOverallTransferRate(TransferDirection::push);
    return success;
}
//add end

ps:这里传的是 push 和 pull 而不是之前的sync 所以在服务端也要进行处理 ,并且需要同步修改

file_sync_client.h 文件

//add by dakun
bool do_sync_push(const std::vector<const char*>& srcs, const char* dst, bool sync, bool compressed,const char* pass);
bool do_sync_pull(const std::vector<const char*>& srcs, const char* dst, bool copy_attrs, bool compressed, const char* pass, const char* name = nullptr);
//add by end
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值