file_sync_client.c

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

C
1,023
字号
/* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <sys/stat.h>#include <sys/time.h>#include <time.h>#include <dirent.h>#include <limits.h>#include <sys/types.h>#include <zipfile/zipfile.h>#include "sysdeps.h"#include "adb.h"#include "adb_client.h"#include "file_sync_service.h"static unsigned total_bytes;static long long start_time;static long long NOW(){    struct timeval tv;    gettimeofday(&tv, 0);    return ((long long) tv.tv_usec) +        1000000LL * ((long long) tv.tv_sec);}static void BEGIN(){    total_bytes = 0;    start_time = NOW();}static void END(){    long long t = NOW() - start_time;    if(total_bytes == 0) return;    if (t == 0)  /* prevent division by 0 :-) */		t = 1000000;    fprintf(stderr,"%lld KB/s (%d bytes in %lld.%03llds)\n",            ((((long long) total_bytes) * 1000000LL) / t) / 1024LL,            total_bytes, (t / 1000000LL), (t % 1000000LL) / 1000LL);}void sync_quit(int fd){    syncmsg msg;    msg.req.id = ID_QUIT;    msg.req.namelen = 0;    writex(fd, &msg.req, sizeof(msg.req));}typedef void (*sync_ls_cb)(unsigned mode, unsigned size, unsigned time, const char *name, void *cookie);int sync_ls(int fd, const char *path, sync_ls_cb func, void *cookie){    syncmsg msg;    char buf[257];    int len;    len = strlen(path);    if(len > 1024) goto fail;    msg.req.id = ID_LIST;    msg.req.namelen = htoll(len);    if(writex(fd, &msg.req, sizeof(msg.req)) ||       writex(fd, path, len)) {        goto fail;    }    for(;;) {        if(readx(fd, &msg.dent, sizeof(msg.dent))) break;        if(msg.dent.id == ID_DONE) return 0;        if(msg.dent.id != ID_DENT) break;        len = ltohl(msg.dent.namelen);        if(len > 256) break;        if(readx(fd, buf, len)) break;        buf[len] = 0;        func(ltohl(msg.dent.mode),             ltohl(msg.dent.size),             ltohl(msg.dent.time),             buf, cookie);    }fail:    adb_close(fd);    return -1;}typedef struct syncsendbuf syncsendbuf;struct syncsendbuf {    unsigned id;    unsigned size;    char data[SYNC_DATA_MAX];};static syncsendbuf send_buffer;int sync_readtime(int fd, const char *path, unsigned *timestamp){    syncmsg msg;    int len = strlen(path);    msg.req.id = ID_STAT;    msg.req.namelen = htoll(len);    if(writex(fd, &msg.req, sizeof(msg.req)) ||       writex(fd, path, len)) {        return -1;    }    if(readx(fd, &msg.stat, sizeof(msg.stat))) {        return -1;    }    if(msg.stat.id != ID_STAT) {        return -1;    }    *timestamp = ltohl(msg.stat.time);    return 0;}static int sync_start_readtime(int fd, const char *path){    syncmsg msg;    int len = strlen(path);    msg.req.id = ID_STAT;    msg.req.namelen = htoll(len);    if(writex(fd, &msg.req, sizeof(msg.req)) ||       writex(fd, path, len)) {        return -1;    }    return 0;}static int sync_finish_readtime(int fd, unsigned int *timestamp,				unsigned int *mode, unsigned int *size){    syncmsg msg;    if(readx(fd, &msg.stat, sizeof(msg.stat)))        return -1;    if(msg.stat.id != ID_STAT)        return -1;    *timestamp = ltohl(msg.stat.time);    *mode = ltohl(msg.stat.mode);    *size = ltohl(msg.stat.size);    return 0;}int sync_readmode(int fd, const char *path, unsigned *mode){    syncmsg msg;    int len = strlen(path);    msg.req.id = ID_STAT;    msg.req.namelen = htoll(len);    if(writex(fd, &msg.req, sizeof(msg.req)) ||       writex(fd, path, len)) {        return -1;    }    if(readx(fd, &msg.stat, sizeof(msg.stat))) {        return -1;    }    if(msg.stat.id != ID_STAT) {        return -1;    }    *mode = ltohl(msg.stat.mode);    return 0;}static int write_data_file(int fd, const char *path, syncsendbuf *sbuf){    int lfd, err = 0;    lfd = adb_open(path, O_RDONLY);    if(lfd < 0) {        fprintf(stderr,"cannot open '%s': %s\n", path, strerror(errno));        return -1;    }    sbuf->id = ID_DATA;    for(;;) {        int ret;        ret = adb_read(lfd, sbuf->data, SYNC_DATA_MAX);        if(!ret)            break;        if(ret < 0) {            if(errno == EINTR)	        continue;            fprintf(stderr,"cannot read '%s': %s\n", path, strerror(errno));            break;        }        sbuf->size = htoll(ret);        if(writex(fd, sbuf, sizeof(unsigned) * 2 + ret)){	        err = -1;            break;        }        total_bytes += ret;    }    adb_close(lfd);    return err;}static int write_data_buffer(int fd, char* file_buffer, int size, syncsendbuf *sbuf){    int err = 0;    int total = 0;    sbuf->id = ID_DATA;    while (total < size) {        int count = size - total;        if (count > SYNC_DATA_MAX) {            count = SYNC_DATA_MAX;        }        memcpy(sbuf->data, &file_buffer[total], count);        sbuf->size = htoll(count);        if(writex(fd, sbuf, sizeof(unsigned) * 2 + count)){	        err = -1;            break;        }        total += count;        total_bytes += count;    }    return err;}#ifdef HAVE_SYMLINKSstatic int write_data_link(int fd, const char *path, syncsendbuf *sbuf){    int len, ret;    len = readlink(path, sbuf->data, SYNC_DATA_MAX-1);    if(len < 0) {        fprintf(stderr, "error reading link '%s': %s\n", path, strerror(errno));	return -1;    }    sbuf->data[len] = '\0';    sbuf->size = htoll(len + 1);    sbuf->id = ID_DATA;    ret = writex(fd, sbuf, sizeof(unsigned) * 2 + len + 1);    if(ret)        return -1;    total_bytes += len + 1;    return 0;}#endifstatic 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;}static int mkdirs(char *name){    int ret;    char *x = name + 1;    for(;;) {        x = adb_dirstart(x);        if(x == 0) return 0;        *x = 0;        ret = adb_mkdir(name, 0775);        *x = OS_PATH_SEPARATOR;        if((ret < 0) && (errno != EEXIST)) {            return ret;        }        x++;    }    return 0;}int sync_recv(int fd, const char *rpath, const char *lpath){    syncmsg msg;    int len;    int lfd = -1;    char *buffer = send_buffer.data;    unsigned id;    len = strlen(rpath);    if(len > 1024) return -1;    msg.req.id = ID_RECV;    msg.req.namelen = htoll(len);    if(writex(fd, &msg.req, sizeof(msg.req)) ||       writex(fd, rpath, len)) {        return -1;    }    if(readx(fd, &msg.data, sizeof(msg.data))) {        return -1;    }    id = msg.data.id;    if((id == ID_DATA) || (id == ID_DONE)) {        adb_unlink(lpath);        mkdirs((char *)lpath);        lfd = adb_creat(lpath, 0644);        if(lfd < 0) {            fprintf(stderr,"cannot create '%s': %s\n", lpath, strerror(errno));            return -1;        }        goto handle_data;    } else {        goto remote_error;    }    for(;;) {        if(readx(fd, &msg.data, sizeof(msg.data))) {            return -1;        }        id = msg.data.id;    handle_data:        len = ltohl(msg.data.size);        if(id == ID_DONE) break;        if(id != ID_DATA) goto remote_error;        if(len > SYNC_DATA_MAX) {            fprintf(stderr,"data overrun\n");            adb_close(lfd);            return -1;        }        if(readx(fd, buffer, len)) {            adb_close(lfd);            return -1;        }        if(writex(lfd, buffer, len)) {            fprintf(stderr,"cannot write '%s': %s\n", rpath, strerror(errno));            adb_close(lfd);            return -1;        }        total_bytes += len;    }    adb_close(lfd);    return 0;remote_error:    adb_close(lfd);    adb_unlink(lpath);

⌨️ 快捷键说明

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