file_sync_client.c

来自「Android 一些工具」· C语言 代码 · 共 1,023 行 · 第 1/2 页

C
1,023
字号
    if(id == ID_FAIL) {        len = ltohl(msg.data.size);        if(len > 256) len = 256;        if(readx(fd, buffer, len)) {            return -1;        }        buffer[len] = 0;    } else {        memcpy(buffer, &id, 4);        buffer[4] = 0;//        strcpy(buffer,"unknown reason");    }    fprintf(stderr,"failed to copy '%s' to '%s': %s\n", rpath, lpath, buffer);    return 0;}/* --- */static void do_sync_ls_cb(unsigned mode, unsigned size, unsigned time,                          const char *name, void *cookie){    printf("%08x %08x %08x %s\n", mode, size, time, name);}int do_sync_ls(const char *path){    int fd = adb_connect("sync:");    if(fd < 0) {        fprintf(stderr,"error: %s\n", adb_error());        return 1;    }    if(sync_ls(fd, path, do_sync_ls_cb, 0)) {        return 1;    } else {        sync_quit(fd);        return 0;    }}typedef struct copyinfo copyinfo;struct copyinfo{    copyinfo *next;    const char *src;    const char *dst;    unsigned int time;    unsigned int mode;    unsigned int size;    int flag;    //char data[0];};copyinfo *mkcopyinfo(const char *spath, const char *dpath,                     const char *name, int isdir){    int slen = strlen(spath);    int dlen = strlen(dpath);    int nlen = strlen(name);    int ssize = slen + nlen + 2;    int dsize = dlen + nlen + 2;    copyinfo *ci = malloc(sizeof(copyinfo) + ssize + dsize);    if(ci == 0) {        fprintf(stderr,"out of memory\n");        abort();    }    ci->next = 0;    ci->time = 0;    ci->mode = 0;    ci->size = 0;    ci->flag = 0;    ci->src = (const char*)(ci + 1);    ci->dst = ci->src + ssize;    snprintf((char*) ci->src, ssize, isdir ? "%s%s/" : "%s%s", spath, name);    snprintf((char*) ci->dst, dsize, isdir ? "%s%s/" : "%s%s", dpath, name);//    fprintf(stderr,"mkcopyinfo('%s','%s')\n", ci->src, ci->dst);    return ci;}static int local_build_list(copyinfo **filelist,                            const char *lpath, const char *rpath){    DIR *d;    struct dirent *de;    struct stat st;    copyinfo *dirlist = 0;    copyinfo *ci, *next;//    fprintf(stderr,"local_build_list('%s','%s')\n", lpath, rpath);    d = opendir(lpath);    if(d == 0) {        fprintf(stderr,"cannot open '%s': %s\n", lpath, strerror(errno));        return -1;    }    while((de = readdir(d))) {        char stat_path[PATH_MAX];        char *name = de->d_name;        if(name[0] == '.') {            if(name[1] == 0) continue;            if((name[1] == '.') && (name[2] == 0)) continue;        }        /*         * We could use d_type if HAVE_DIRENT_D_TYPE is defined, but reiserfs         * always returns DT_UNKNOWN, so we just use stat() for all cases.         */        if (strlen(lpath) + strlen(de->d_name) + 1 > sizeof(stat_path))            continue;        strcpy(stat_path, lpath);        strcat(stat_path, de->d_name);        stat(stat_path, &st);        if (S_ISDIR(st.st_mode)) {            ci = mkcopyinfo(lpath, rpath, name, 1);            ci->next = dirlist;            dirlist = ci;        } else {            ci = mkcopyinfo(lpath, rpath, name, 0);            if(lstat(ci->src, &st)) {            	closedir(d);                fprintf(stderr,"cannot stat '%s': %s\n", ci->src, strerror(errno));                return -1;            }            if(!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) {                fprintf(stderr, "skipping special file '%s'\n", ci->src);                free(ci);            } else {                ci->time = st.st_mtime;                ci->mode = st.st_mode;		ci->size = st.st_size;                ci->next = *filelist;                *filelist = ci;            }        }    }    closedir(d);    for(ci = dirlist; ci != 0; ci = next) {        next = ci->next;        local_build_list(filelist, ci->src, ci->dst);        free(ci);    }    return 0;}static int copy_local_dir_remote(int fd, const char *lpath, const char *rpath, int checktimestamps){    copyinfo *filelist = 0;    copyinfo *ci, *next;    int pushed = 0;    int skipped = 0;    if((lpath[0] == 0) || (rpath[0] == 0)) return -1;    if(lpath[strlen(lpath) - 1] != '/') {        int  tmplen = strlen(lpath)+2;        char *tmp = malloc(tmplen);        if(tmp == 0) return -1;        snprintf(tmp, tmplen, "%s/",lpath);        lpath = tmp;    }    if(rpath[strlen(rpath) - 1] != '/') {        int tmplen = strlen(rpath)+2;        char *tmp = malloc(tmplen);        if(tmp == 0) return -1;        snprintf(tmp, tmplen, "%s/",rpath);        rpath = tmp;    }    if(local_build_list(&filelist, lpath, rpath)) {        return -1;    }    if(checktimestamps){        for(ci = filelist; ci != 0; ci = ci->next) {            if(sync_start_readtime(fd, ci->dst)) {                return 1;            }        }        for(ci = filelist; ci != 0; ci = ci->next) {            unsigned int timestamp, mode, size;            if(sync_finish_readtime(fd, &timestamp, &mode, &size))                return 1;	    if(size == ci->size) {                /* for links, we cannot update the atime/mtime */                if((S_ISREG(ci->mode & mode) && timestamp == ci->time) ||		   (S_ISLNK(ci->mode & mode) && timestamp >= ci->time))                    ci->flag = 1;	    }        }    }    for(ci = filelist; ci != 0; ci = next) {        next = ci->next;        if(ci->flag == 0) {            fprintf(stderr,"push: %s -> %s\n", ci->src, ci->dst);            if(sync_send(fd, ci->src, ci->dst, ci->time, ci->mode, 0 /* no verify APK */)){                return 1;            }            pushed++;        } else {            skipped++;        }        free(ci);    }    fprintf(stderr,"%d file%s pushed. %d file%s skipped.\n",            pushed, (pushed == 1) ? "" : "s",            skipped, (skipped == 1) ? "" : "s");    return 0;}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)) {            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;}typedef struct {    copyinfo **filelist;    copyinfo **dirlist;    const char *rpath;    const char *lpath;} sync_ls_build_list_cb_args;voidsync_ls_build_list_cb(unsigned mode, unsigned size, unsigned time,                      const char *name, void *cookie){    sync_ls_build_list_cb_args *args = (sync_ls_build_list_cb_args *)cookie;    copyinfo *ci;    if (S_ISDIR(mode)) {        copyinfo **dirlist = args->dirlist;        /* Don't try recursing down "." or ".." */        if (name[0] == '.') {            if (name[1] == '\0') return;            if ((name[1] == '.') && (name[2] == '\0')) return;        }        ci = mkcopyinfo(args->rpath, args->lpath, name, 1);        ci->next = *dirlist;        *dirlist = ci;    } else if (S_ISREG(mode) || S_ISLNK(mode)) {        copyinfo **filelist = args->filelist;        ci = mkcopyinfo(args->rpath, args->lpath, name, 0);        ci->time = time;        ci->mode = mode;        ci->size = size;        ci->next = *filelist;        *filelist = ci;    } else {        fprintf(stderr, "skipping special file '%s'\n", name);    }}static int remote_build_list(int syncfd, copyinfo **filelist,                             const char *rpath, const char *lpath){    copyinfo *dirlist = NULL;    sync_ls_build_list_cb_args args;    args.filelist = filelist;    args.dirlist = &dirlist;    args.rpath = rpath;    args.lpath = lpath;    /* Put the files/dirs in rpath on the lists. */    if (sync_ls(syncfd, rpath, sync_ls_build_list_cb, (void *)&args)) {        return 1;    }    /* Recurse into each directory we found. */    while (dirlist != NULL) {        copyinfo *next = dirlist->next;        if (remote_build_list(syncfd, filelist, dirlist->src, dirlist->dst)) {            return 1;        }        free(dirlist);        dirlist = next;    }    return 0;}static int copy_remote_dir_local(int fd, const char *rpath, const char *lpath,                                 int checktimestamps){    copyinfo *filelist = 0;    copyinfo *ci, *next;    int pulled = 0;    int skipped = 0;    /* Make sure that both directory paths end in a slash. */    if (rpath[0] == 0 || lpath[0] == 0) return -1;    if (rpath[strlen(rpath) - 1] != '/') {        int  tmplen = strlen(rpath) + 2;        char *tmp = malloc(tmplen);        if (tmp == 0) return -1;        snprintf(tmp, tmplen, "%s/", rpath);        rpath = tmp;    }    if (lpath[strlen(lpath) - 1] != '/') {        int  tmplen = strlen(lpath) + 2;        char *tmp = malloc(tmplen);        if (tmp == 0) return -1;        snprintf(tmp, tmplen, "%s/", lpath);        lpath = tmp;    }    fprintf(stderr, "pull: building file list...\n");    /* Recursively build the list of files to copy. */    if (remote_build_list(fd, &filelist, rpath, lpath)) {        return -1;    }#if 0    if (checktimestamps) {        for (ci = filelist; ci != 0; ci = ci->next) {            if (sync_start_readtime(fd, ci->dst)) {                return 1;            }        }        for (ci = filelist; ci != 0; ci = ci->next) {            unsigned int timestamp, mode, size;            if (sync_finish_readtime(fd, &timestamp, &mode, &size))                return 1;	    if (size == ci->size) {                /* for links, we cannot update the atime/mtime */                if ((S_ISREG(ci->mode & mode) && timestamp == ci->time) ||		   (S_ISLNK(ci->mode & mode) && timestamp >= ci->time))                    ci->flag = 1;	    }        }    }#endif    for (ci = filelist; ci != 0; ci = next) {        next = ci->next;        if (ci->flag == 0) {            fprintf(stderr, "pull: %s -> %s\n", ci->src, ci->dst);            if (sync_recv(fd, ci->src, ci->dst)) {                return 1;            }            pulled++;        } else {            skipped++;        }        free(ci);    }    fprintf(stderr, "%d file%s pulled. %d file%s skipped.\n",            pulled, (pulled == 1) ? "" : "s",            skipped, (skipped == 1) ? "" : "s");    return 0;}int do_sync_pull(const char *rpath, const char *lpath){    unsigned mode;    struct stat st;    int fd;    fd = adb_connect("sync:");    if(fd < 0) {        fprintf(stderr,"error: %s\n", adb_error());        return 1;    }    if(sync_readmode(fd, rpath, &mode)) {        return 1;    }    if(mode == 0) {        fprintf(stderr,"remote object '%s' does not exist\n", rpath);        return 1;    }    if(S_ISREG(mode) || S_ISCHR(mode) || S_ISBLK(mode)) {        if(stat(lpath, &st) == 0) {            if(S_ISDIR(st.st_mode)) {                    /* if we're copying a remote file to a local directory,                    ** we *really* want to copy to localdir + "/" + remotefilename                    */                const char *name = adb_dirstop(rpath);                if(name == 0) {                    name = rpath;                } else {                    name++;                }                int  tmplen = strlen(name) + strlen(lpath) + 2;                char *tmp = malloc(tmplen);                if(tmp == 0) return 1;                snprintf(tmp, tmplen, "%s/%s", lpath, name);                lpath = tmp;            }        }        BEGIN();        if(sync_recv(fd, rpath, lpath)) {            return 1;        } else {            END();            sync_quit(fd);            return 0;        }    } else if(S_ISDIR(mode)) {        BEGIN();        if (copy_remote_dir_local(fd, rpath, lpath, 0)) {            return 1;        } else {            END();            sync_quit(fd);            return 0;        }    } else {        fprintf(stderr,"remote object '%s' not a file or directory\n", rpath);        return 1;    }}int do_sync_sync(const char *lpath, const char *rpath){    fprintf(stderr,"syncing %s...\n",rpath);    int fd = adb_connect("sync:");    if(fd < 0) {        fprintf(stderr,"error: %s\n", adb_error());        return 1;    }    BEGIN();    if(copy_local_dir_remote(fd, lpath, rpath, 1)){        return 1;    } else {        END();        sync_quit(fd);        return 0;    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?