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 + -
显示快捷键?