[Android] Android adb push是怎样被实现的?

本文详细解析了Android中adb push命令的工作原理和技术细节,包括如何通过ADB连接进行文件同步、如何处理不同类型的本地文件和远程路径等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Android adb push是怎样被实现的?

CODE: commandline.c
PATH: <ANDROID_PROJECT>/system/core/adb/commandline.c
FUNC: do_sync_push() @adb_commandline()
LINE: 1147
-
do_sync_push() body is at 
@ <ANDROID_PROJECT>/system/core/adb/file_sync_client.c
-
int do_sync_push( const char *lpath, const char *rpath, int verifyApk)
{
    struct stat st;
    unsigned mode;
    int fd;

   fd = adb_connect("sync:");

    if(fd < 0) {
        fprintf(stderr, "error: %s\n", adb_error());
        return 1;
    }

    if(stat(lpath, &st)) {
        fprintf(stderr, "cannot stat '%s': %s\n", lpath, strerror(errno));
        sync_quit(fd);
        return 1;
    }

    if(S_ISDIR(st.st_mode)) {
        BEGIN();
        if(copy_local_dir_remote(fd, lpath, rpath, 0, 0)) {
            return 1;
        } else {
            END();
            sync_quit(fd);
        }
    } else {
        if(sync_readmode(fd, rpath, &mode)) {
            return 1;
        }
        if((mode != 0) && S_ISDIR(mode)) {
                /* if we're copying a local file to a remote directory,
                ** we *really* want to copy to remotedir + "/" + localfilename
                */
            const char *name = adb_dirstop(lpath);
            if(name == 0) {
                name = lpath;
            } else {
                name++;
            }
            int  tmplen = strlen(name) + strlen(rpath) + 2;
            char *tmp = malloc(strlen(name) + strlen(rpath) + 2);
            if(tmp == 0) return 1;
            snprintf(tmp, tmplen, "%s/%s", rpath, name);
            rpath = tmp;
        }
        BEGIN();
        if(sync_send(fd, lpath, rpath, st.st_mtime , st.st_mode , verifyApk)) {
            return 1;
        } else {
            END();
            sync_quit(fd);
            return 0;
        }
    }

    return 0;
}

-
接着查看sync_send()函数的实现部分
-
@ <ANDROID_PROJECT>/system/core/adb/file_sync_client.c
L 297
-
static int sync_send (int fd, const char *lpath, const char *rpath,
                     unsigned mtime, mode_t mode, int verifyApk)
{
    syncmsg msg;
    int len, r;
    syncsendbuf *sbuf = &send_buffer;
    char* file_buffer = NULL;
    int size = 0;
    char tmp[64];

    len = strlen(rpath);
    if(len > 1024) goto fail;

    snprintf(tmp, sizeof(tmp), ",%d", mode);
    r = strlen(tmp);

    if (verifyApk) {
        int lfd;
        zipfile_t zip;
        zipentry_t entry;
        int amt;

        // if we are transferring an APK file, then sanity check to make sure
        // we have a real zip file that contains an AndroidManifest.xml
        // this requires that we read the entire file into memory.
        lfd = adb_open(lpath, O_RDONLY);
        if(lfd < 0) {
            fprintf(stderr, "cannot open '%s': %s\n", lpath, strerror(errno));
            return -1;
        }

        size = adb_lseek(lfd, 0, SEEK_END);
        if (size == -1 || -1 == adb_lseek(lfd, 0, SEEK_SET)) {
            fprintf(stderr, "error seeking in file '%s'\n" , lpath);
            adb_close(lfd);
            return 1;
        }

        file_buffer = ( char *)malloc(size);
        if (file_buffer == NULL) {
            fprintf(stderr, "could not allocate buffer for '%s'\n" ,
                    lpath);
            adb_close(lfd);
            return 1;
        }
        amt = adb_read(lfd, file_buffer, size);
        if (amt != size) {
            fprintf(stderr, "error reading from file: '%s'\n" , lpath);
            adb_close(lfd);
            free(file_buffer);
            return 1;
        }

        adb_close(lfd);

        zip = init_zipfile(file_buffer, size);
        if (zip == NULL) {
            fprintf(stderr, "file '%s' is not a valid zip file\n",
                    lpath);
            free(file_buffer);
            return 1;
        }

        entry = lookup_zipentry(zip, "AndroidManifest.xml");
        release_zipfile(zip);
        if (entry == NULL) {
            fprintf(stderr, "file '%s' does not contain AndroidManifest.xml\n" ,
                    lpath);
            free(file_buffer);
            return 1;
        }
    }

    msg.req.id = ID_SEND;
    msg.req.namelen = htoll(len + r);


    if(writex(fd, &msg.req, sizeof(msg.req)) ||
       writex(fd, rpath, len) || writex(fd, tmp, r)) {
        free(file_buffer);
        goto fail;
    }


    if (file_buffer) {
        write_data_buffer(fd, file_buffer, size, sbuf);
        free(file_buffer);
    } else if (S_ISREG(mode))
        write_data_file(fd, lpath, sbuf);
#ifdef HAVE_SYMLINKS
    else if (S_ISLNK(mode))
        write_data_link(fd, lpath, sbuf);
#endif
    else
        goto fail;

    msg.data.id = ID_DONE;
    msg.data.size = htoll(mtime);
    if(writex(fd, &msg.data, sizeof(msg.data)))
        goto fail;

    if(readx(fd, &msg.status, sizeof(msg.status)))
        return -1;

    if(msg.status.id != ID_OKAY) {
        if(msg.status.id == ID_FAIL) {
            len = ltohl(msg.status.msglen);
            if(len > 256) len = 256;
            if(readx(fd, sbuf->data , len)) {
                return -1;
            }
            sbuf-> data[len] = 0;
        } else
            strcpy(sbuf-> data, "unknown reason");

        fprintf(stderr, "failed to copy '%s' to '%s': %s\n" , lpath, rpath, sbuf->data);
        return -1;
    }

    return 0;

fail:
    fprintf(stderr,"protocol failure\n");
    adb_close(fd);
    return -1;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值