am 186f1dee: Merge "adb sync cleanup."

* commit '186f1dee2afc15c8941a1f78e1aa97e2ec9970ee':
  adb sync cleanup.
This commit is contained in:
Elliott Hughes 2015-08-24 20:51:42 +00:00 committed by Android Git Automerger
commit c583c5112b
14 changed files with 523 additions and 818 deletions

View File

@ -237,7 +237,7 @@ track-jdwp
Note that there is no single-shot service to retrieve the list only once.
sync:
This starts the file synchronisation service, used to implement "adb push"
This starts the file synchronization service, used to implement "adb push"
and "adb pull". Since this service is pretty complex, it will be detailed
in a companion document named SYNC.TXT

View File

@ -25,12 +25,9 @@ follows as described in SERVICES.TXT.
The following sync requests are accepted:
LIST - List the files in a folder
RECV - Retrieve a file from device
SEND - Send a file to device
RECV - Retreive a file from device
Not yet documented:
STAT - Stat a file
ULNK - Unlink (remove) a file. (Not currently supported)
For all of the sync request above the must be followed by length number of
bytes containing an utf-8 string with a remote filename.
@ -40,7 +37,7 @@ Lists files in the directory specified by the remote filename. The server will
respond with zero or more directory entries or "dents".
The directory entries will be returned in the following form
1. A four-byte sync response id beeing "DENT"
1. A four-byte sync response id "DENT"
2. A four-byte integer representing file mode.
3. A four-byte integer representing file size.
4. A four-byte integer representing last modified time.
@ -60,13 +57,13 @@ the transfer fails. Some file types will not be deleted, which allows
adb push disk_image /some_block_device
to work.
After this the actual file is sent in chunks. Each chucks has the following
After this the actual file is sent in chunks. Each chunk has the following
format.
A sync request with id "DATA" and length equal to the chunk size. After
follows chunk size number of bytes. This is repeated until the file is
transfered. Each chunk must not be larger than 64k.
transferred. Each chunk must not be larger than 64k.
When the file is tranfered a sync request "DONE" is sent, where length is set
When the file is transferred a sync request "DONE" is sent, where length is set
to the last modified time for the file. The server responds to this last
request (but not to chuck requests) with an "OKAY" sync response (length can
be ignored).
@ -77,8 +74,8 @@ Retrieves a file from device to a local file. The remote path is the path to
the file that will be returned. Just as for the SEND sync request the file
received is split up into chunks. The sync response id is "DATA" and length is
the chuck size. After follows chunk size number of bytes. This is repeated
until the file is transfered. Each chuck will not be larger than 64k.
until the file is transferred. Each chuck will not be larger than 64k.
When the file is transfered a sync resopnse "DONE" is retrieved where the
When the file is transferred a sync response "DONE" is retrieved where the
length can be ignored.

View File

@ -44,28 +44,6 @@ static const char* __adb_serial = NULL;
static int __adb_server_port = DEFAULT_ADB_PORT;
static const char* __adb_server_name = NULL;
static std::string perror_str(const char* msg) {
return android::base::StringPrintf("%s: %s", msg, strerror(errno));
}
static bool ReadProtocolString(int fd, std::string* s, std::string* error) {
char buf[5];
if (!ReadFdExactly(fd, buf, 4)) {
*error = perror_str("protocol fault (couldn't read status length)");
return false;
}
buf[4] = 0;
unsigned long len = strtoul(buf, 0, 16);
s->resize(len, '\0');
if (!ReadFdExactly(fd, &(*s)[0], len)) {
*error = perror_str("protocol fault (couldn't read status message)");
return false;
}
return true;
}
void adb_set_transport(TransportType type, const char* serial)
{
__adb_transport = type;
@ -175,7 +153,7 @@ int _adb_connect(const std::string& service, std::string* error) {
return -1;
}
if(!SendProtocolString(fd, service)) {
if (!SendProtocolString(fd, service)) {
*error = perror_str("write failure during connection");
adb_close(fd);
return -1;

View File

@ -32,7 +32,27 @@ bool SendProtocolString(int fd, const std::string& s) {
length = 0xffff;
}
return WriteFdFmt(fd, "%04x", length) && WriteFdExactly(fd, s);
// The cost of sending two strings outweighs the cost of formatting.
// "adb sync" performance is affected by this.
return WriteFdFmt(fd, "%04x%.*s", length, length, s.c_str());
}
bool ReadProtocolString(int fd, std::string* s, std::string* error) {
char buf[5];
if (!ReadFdExactly(fd, buf, 4)) {
*error = perror_str("protocol fault (couldn't read status length)");
return false;
}
buf[4] = 0;
unsigned long len = strtoul(buf, 0, 16);
s->resize(len, '\0');
if (!ReadFdExactly(fd, &(*s)[0], len)) {
*error = perror_str("protocol fault (couldn't read status message)");
return false;
}
return true;
}
bool SendOkay(int fd) {

View File

@ -30,23 +30,22 @@ bool SendFail(int fd, const std::string& reason);
// Writes a protocol-format string; a four hex digit length followed by the string data.
bool SendProtocolString(int fd, const std::string& s);
/*
* Reads exactly len bytes from fd into buf.
*
* Returns false if there is an error or if EOF was reached before len bytes
* were read. If EOF was found, errno will be set to 0.
*
* If this function fails, the contents of buf are undefined.
*/
bool ReadFdExactly(int fd, void *buf, size_t len);
// Reads a protocol-format string; a four hex digit length followed by the string data.
bool ReadProtocolString(int fd, std::string* s, std::string* error);
/*
* Writes exactly len bytes from buf to fd.
*
* Returns false if there is an error or if the fd was closed before the write
* completed. If the other end of the fd (such as in a socket, pipe, or fifo),
* is closed, errno will be set to 0.
*/
// Reads exactly len bytes from fd into buf.
//
// Returns false if there is an error or if EOF was reached before len bytes
// were read. If EOF was found, errno will be set to 0.
//
// If this function fails, the contents of buf are undefined.
bool ReadFdExactly(int fd, void* buf, size_t len);
// Writes exactly len bytes from buf to fd.
//
// Returns false if there is an error or if the fd was closed before the write
// completed. If the other end of the fd (such as in a socket, pipe, or fifo),
// is closed, errno will be set to 0.
bool WriteFdExactly(int fd, const void* buf, size_t len);
// Same as above, but for strings.

View File

@ -225,3 +225,7 @@ bool parse_host_and_port(const std::string& address,
<< " (" << *canonical_address << ")";
return true;
}
std::string perror_str(const char* msg) {
return android::base::StringPrintf("%s: %s", msg, strerror(errno));
}

View File

@ -44,4 +44,6 @@ bool parse_host_and_port(const std::string& address,
std::string* host, int* port,
std::string* error);
std::string perror_str(const char* msg);
#endif

View File

@ -381,7 +381,7 @@ static void *stdin_read_thread(void *x)
fdi = fds[1];
free(fds);
for(;;) {
while (true) {
/* fdi is really the client's stdin, so use read, not adb_read here */
D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi);
r = unix_read(fdi, buf, 1024);
@ -889,14 +889,14 @@ static std::string find_product_out_path(const std::string& hint) {
}
static void parse_push_pull_args(const char **arg, int narg, char const **path1,
char const **path2, int *show_progress,
char const **path2, bool* show_progress,
int *copy_attrs) {
*show_progress = 0;
*show_progress = false;
*copy_attrs = 0;
while (narg > 0) {
if (!strcmp(*arg, "-p")) {
*show_progress = 1;
*show_progress = true;
} else if (!strcmp(*arg, "-a")) {
*copy_attrs = 1;
} else {
@ -1331,33 +1331,25 @@ int adb_commandline(int argc, const char **argv) {
/* do_sync_*() commands */
else if (!strcmp(argv[0], "ls")) {
if (argc != 2) return usage();
return do_sync_ls(argv[1]);
return do_sync_ls(argv[1]) ? 0 : 1;
}
else if (!strcmp(argv[0], "push")) {
int show_progress = 0;
int copy_attrs = 0; // unused
bool show_progress = false;
int copy_attrs = 0;
const char* lpath = NULL, *rpath = NULL;
parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress, &copy_attrs);
if ((lpath != NULL) && (rpath != NULL)) {
return do_sync_push(lpath, rpath, show_progress);
}
return usage();
if (!lpath || !rpath || copy_attrs != 0) return usage();
return do_sync_push(lpath, rpath, show_progress) ? 0 : 1;
}
else if (!strcmp(argv[0], "pull")) {
int show_progress = 0;
bool show_progress = false;
int copy_attrs = 0;
const char* rpath = NULL, *lpath = ".";
parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress, &copy_attrs);
if (rpath != NULL) {
return do_sync_pull(rpath, lpath, show_progress, copy_attrs);
}
return usage();
if (!rpath) return usage();
return do_sync_pull(rpath, lpath, show_progress, copy_attrs) ? 0 : 1;
}
else if (!strcmp(argv[0], "install")) {
if (argc < 2) return usage();
@ -1401,20 +1393,20 @@ int adb_commandline(int argc, const char **argv) {
std::string vendor_src_path = product_file("vendor");
std::string oem_src_path = product_file("oem");
int rc = 0;
if (rc == 0 && (src.empty() || src == "system")) {
rc = do_sync_sync(system_src_path, "/system", list_only);
bool okay = true;
if (okay && (src.empty() || src == "system")) {
okay = do_sync_sync(system_src_path, "/system", list_only);
}
if (rc == 0 && (src.empty() || src == "vendor") && directory_exists(vendor_src_path)) {
rc = do_sync_sync(vendor_src_path, "/vendor", list_only);
if (okay && (src.empty() || src == "vendor") && directory_exists(vendor_src_path)) {
okay = do_sync_sync(vendor_src_path, "/vendor", list_only);
}
if (rc == 0 && (src.empty() || src == "oem") && directory_exists(oem_src_path)) {
rc = do_sync_sync(oem_src_path, "/oem", list_only);
if (okay && (src.empty() || src == "oem") && directory_exists(oem_src_path)) {
okay = do_sync_sync(oem_src_path, "/oem", list_only);
}
if (rc == 0 && (src.empty() || src == "data")) {
rc = do_sync_sync(data_src_path, "/data", list_only);
if (okay && (src.empty() || src == "data")) {
okay = do_sync_sync(data_src_path, "/data", list_only);
}
return rc;
return okay ? 0 : 1;
}
/* passthrough commands */
else if (!strcmp(argv[0],"get-state") ||
@ -1535,20 +1527,16 @@ static int install_app(TransportType transport, const char* serial, int argc, co
return -1;
}
int result = -1;
const char* apk_file = argv[last_apk];
std::string apk_dest = android::base::StringPrintf(where, adb_basename(apk_file).c_str());
int err = do_sync_push(apk_file, apk_dest.c_str(), 0 /* no show progress */);
if (err) {
goto cleanup_apk;
} else {
argv[last_apk] = apk_dest.c_str(); /* destination name, not source location */
}
err = pm_command(transport, serial, argc, argv);
if (!do_sync_push(apk_file, apk_dest.c_str(), false)) goto cleanup_apk;
argv[last_apk] = apk_dest.c_str(); /* destination name, not source location */
result = pm_command(transport, serial, argc, argv);
cleanup_apk:
delete_file(transport, serial, apk_dest);
return err;
return result;
}
static int install_multiple_app(TransportType transport, const char* serial, int argc,

View File

@ -2,16 +2,16 @@
**
** Copyright 2006, Brian Swetland <swetland@frotz.net>
**
** 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
** 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
** 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
** 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.
*/
@ -688,7 +688,7 @@ void fdevent_loop()
fdevent_subproc_setup();
#endif // !ADB_HOST
for(;;) {
while (true) {
D("--- ---- waiting for events\n");
fdevent_process();

File diff suppressed because it is too large Load Diff

View File

@ -34,6 +34,7 @@
#include "adb_io.h"
#include "private/android_filesystem_config.h"
#include <base/stringprintf.h>
#include <base/strings.h>
static bool should_use_fs_config(const std::string& path) {
@ -76,38 +77,23 @@ static bool secure_mkdirs(const std::string& path) {
return true;
}
static int do_stat(int s, const char *path)
{
static bool do_stat(int s, const char* path) {
syncmsg msg;
struct stat st;
msg.stat.id = ID_STAT;
if(lstat(path, &st)) {
msg.stat.mode = 0;
msg.stat.size = 0;
msg.stat.time = 0;
} else {
msg.stat.mode = htoll(st.st_mode);
msg.stat.size = htoll(st.st_size);
msg.stat.time = htoll(st.st_mtime);
}
struct stat st;
memset(&st, 0, sizeof(st));
// TODO: add a way to report that the stat failed!
lstat(path, &st);
msg.stat.mode = htoll(st.st_mode);
msg.stat.size = htoll(st.st_size);
msg.stat.time = htoll(st.st_mtime);
return WriteFdExactly(s, &msg.stat, sizeof(msg.stat)) ? 0 : -1;
return WriteFdExactly(s, &msg.stat, sizeof(msg.stat));
}
static int do_list(int s, const char *path)
{
struct dirent *de;
struct stat st;
char tmp[1024 + 256 + 1];
char *fname;
size_t len = strlen(path);
memcpy(tmp, path, len);
tmp[len] = '/';
fname = tmp + len + 1;
static bool do_list(int s, const char* path) {
dirent* de;
syncmsg msg;
msg.dent.id = ID_DENT;
@ -116,22 +102,19 @@ static int do_list(int s, const char *path)
if (!d) goto done;
while ((de = readdir(d.get()))) {
int len = strlen(de->d_name);
std::string filename(android::base::StringPrintf("%s/%s", path, de->d_name));
/* not supposed to be possible, but
if it does happen, let's not buffer overrun */
if(len > 256) continue;
strcpy(fname, de->d_name);
if(lstat(tmp, &st) == 0) {
struct stat st;
if (lstat(filename.c_str(), &st) == 0) {
size_t d_name_length = strlen(de->d_name);
msg.dent.mode = htoll(st.st_mode);
msg.dent.size = htoll(st.st_size);
msg.dent.time = htoll(st.st_mtime);
msg.dent.namelen = htoll(len);
msg.dent.namelen = htoll(d_name_length);
if(!WriteFdExactly(s, &msg.dent, sizeof(msg.dent)) ||
!WriteFdExactly(s, de->d_name, len)) {
return -1;
if (!WriteFdExactly(s, &msg.dent, sizeof(msg.dent)) ||
!WriteFdExactly(s, de->d_name, d_name_length)) {
return false;
}
}
}
@ -142,43 +125,33 @@ done:
msg.dent.size = 0;
msg.dent.time = 0;
msg.dent.namelen = 0;
return WriteFdExactly(s, &msg.dent, sizeof(msg.dent)) ? 0 : -1;
return WriteFdExactly(s, &msg.dent, sizeof(msg.dent));
}
static int fail_message(int s, const char *reason)
{
static bool fail_message(int s, const std::string& reason) {
D("sync: failure: %s\n", reason.c_str());
syncmsg msg;
int len = strlen(reason);
D("sync: failure: %s\n", reason);
msg.data.id = ID_FAIL;
msg.data.size = htoll(len);
if(!WriteFdExactly(s, &msg.data, sizeof(msg.data)) ||
!WriteFdExactly(s, reason, len)) {
return -1;
} else {
return 0;
}
msg.data.size = htoll(reason.size());
return WriteFdExactly(s, &msg.data, sizeof(msg.data)) && WriteFdExactly(s, reason);
}
static int fail_errno(int s)
{
// TODO: callers of this have already failed, and should probably ignore its
// return value (http://b/23437039).
static bool fail_errno(int s) {
return fail_message(s, strerror(errno));
}
static int handle_send_file(int s, char *path, uid_t uid,
gid_t gid, mode_t mode, char *buffer, bool do_unlink)
{
static bool handle_send_file(int s, char *path, uid_t uid,
gid_t gid, mode_t mode, std::vector<char>& buffer, bool do_unlink) {
syncmsg msg;
unsigned int timestamp = 0;
int fd;
fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode);
int fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode);
if(fd < 0 && errno == ENOENT) {
if (!secure_mkdirs(path)) {
if(fail_errno(s))
return -1;
if (fail_errno(s)) return false;
fd = -1;
} else {
fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode);
@ -188,8 +161,7 @@ static int handle_send_file(int s, char *path, uid_t uid,
fd = adb_open_mode(path, O_WRONLY | O_CLOEXEC, mode);
}
if(fd < 0) {
if(fail_errno(s))
return -1;
if (fail_errno(s)) return false;
fd = -1;
} else {
if(fchown(fd, uid, gid) != 0) {
@ -205,7 +177,7 @@ static int handle_send_file(int s, char *path, uid_t uid,
fchmod(fd, mode);
}
for(;;) {
while (true) {
unsigned int len;
if(!ReadFdExactly(s, &msg.data, sizeof(msg.data)))
@ -220,22 +192,21 @@ static int handle_send_file(int s, char *path, uid_t uid,
goto fail;
}
len = ltohl(msg.data.size);
if(len > SYNC_DATA_MAX) {
if (len > buffer.size()) { // TODO: resize buffer?
fail_message(s, "oversize data message");
goto fail;
}
if(!ReadFdExactly(s, buffer, len))
goto fail;
if (!ReadFdExactly(s, &buffer[0], len)) goto fail;
if(fd < 0)
continue;
if(!WriteFdExactly(fd, buffer, len)) {
if (fd < 0) continue;
if (!WriteFdExactly(fd, &buffer[0], len)) {
int saved_errno = errno;
adb_close(fd);
if (do_unlink) adb_unlink(path);
fd = -1;
errno = saved_errno;
if(fail_errno(s)) return -1;
if (fail_errno(s)) return false;
}
}
@ -249,75 +220,67 @@ static int handle_send_file(int s, char *path, uid_t uid,
msg.status.id = ID_OKAY;
msg.status.msglen = 0;
if(!WriteFdExactly(s, &msg.status, sizeof(msg.status)))
return -1;
if (!WriteFdExactly(s, &msg.status, sizeof(msg.status))) return false;
}
return 0;
return true;
fail:
if(fd >= 0)
adb_close(fd);
if (fd >= 0) adb_close(fd);
if (do_unlink) adb_unlink(path);
return -1;
return false;
}
#if defined(_WIN32)
extern int handle_send_link(int s, char *path, char *buffer) __attribute__((error("no symlinks on Windows")));
extern bool handle_send_link(int s, char *path, std::vector<char>& buffer) __attribute__((error("no symlinks on Windows")));
#else
static int handle_send_link(int s, char *path, char *buffer)
{
static bool handle_send_link(int s, char *path, std::vector<char>& buffer) {
syncmsg msg;
unsigned int len;
int ret;
if(!ReadFdExactly(s, &msg.data, sizeof(msg.data)))
return -1;
if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) return false;
if(msg.data.id != ID_DATA) {
if (msg.data.id != ID_DATA) {
fail_message(s, "invalid data message: expected ID_DATA");
return -1;
return false;
}
len = ltohl(msg.data.size);
if(len > SYNC_DATA_MAX) {
if (len > buffer.size()) { // TODO: resize buffer?
fail_message(s, "oversize data message");
return -1;
return false;
}
if(!ReadFdExactly(s, buffer, len))
return -1;
if (!ReadFdExactly(s, &buffer[0], len)) return false;
ret = symlink(buffer, path);
if(ret && errno == ENOENT) {
ret = symlink(&buffer[0], path);
if (ret && errno == ENOENT) {
if (!secure_mkdirs(path)) {
fail_errno(s);
return -1;
return false;
}
ret = symlink(buffer, path);
ret = symlink(&buffer[0], path);
}
if(ret) {
if (ret) {
fail_errno(s);
return -1;
return false;
}
if(!ReadFdExactly(s, &msg.data, sizeof(msg.data)))
return -1;
if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) return false;
if(msg.data.id == ID_DONE) {
if (msg.data.id == ID_DONE) {
msg.status.id = ID_OKAY;
msg.status.msglen = 0;
if(!WriteFdExactly(s, &msg.status, sizeof(msg.status)))
return -1;
if (!WriteFdExactly(s, &msg.status, sizeof(msg.status))) return false;
} else {
fail_message(s, "invalid data message: expected ID_DONE");
return -1;
return false;
}
return 0;
return true;
}
#endif
static int do_send(int s, char *path, char *buffer)
{
static bool do_send(int s, char* path, std::vector<char>& buffer) {
unsigned int mode;
bool is_link = false;
bool do_unlink;
@ -365,32 +328,28 @@ static int do_send(int s, char *path, char *buffer)
return handle_send_file(s, path, uid, gid, mode, buffer, do_unlink);
}
static int do_recv(int s, const char *path, char *buffer)
{
syncmsg msg;
int fd, r;
fd = adb_open(path, O_RDONLY | O_CLOEXEC);
if(fd < 0) {
if(fail_errno(s)) return -1;
return 0;
static bool do_recv(int s, const char* path, std::vector<char>& buffer) {
int fd = adb_open(path, O_RDONLY | O_CLOEXEC);
if (fd < 0) {
if (fail_errno(s)) return false;
return true;
}
syncmsg msg;
msg.data.id = ID_DATA;
for(;;) {
r = adb_read(fd, buffer, SYNC_DATA_MAX);
if(r <= 0) {
if(r == 0) break;
if(errno == EINTR) continue;
r = fail_errno(s);
while (true) {
int r = adb_read(fd, &buffer[0], buffer.size());
if (r <= 0) {
if (r == 0) break;
if (errno == EINTR) continue;
bool status = fail_errno(s);
adb_close(fd);
return r;
return status;
}
msg.data.size = htoll(r);
if(!WriteFdExactly(s, &msg.data, sizeof(msg.data)) ||
!WriteFdExactly(s, buffer, r)) {
if (!WriteFdExactly(s, &msg.data, sizeof(msg.data)) || !WriteFdExactly(s, &buffer[0], r)) {
adb_close(fd);
return -1;
return false;
}
}
@ -398,66 +357,62 @@ static int do_recv(int s, const char *path, char *buffer)
msg.data.id = ID_DONE;
msg.data.size = 0;
if(!WriteFdExactly(s, &msg.data, sizeof(msg.data))) {
return -1;
}
return 0;
return WriteFdExactly(s, &msg.data, sizeof(msg.data));
}
void file_sync_service(int fd, void *cookie)
{
syncmsg msg;
static bool handle_sync_command(int fd, std::vector<char>& buffer) {
D("sync: waiting for request\n");
SyncRequest request;
if (!ReadFdExactly(fd, &request, sizeof(request))) {
fail_message(fd, "command read failure");
return false;
}
size_t path_length = ltohl(request.path_length);
if (path_length > 1024) {
fail_message(fd, "path too long");
return false;
}
char name[1025];
unsigned namelen;
if (!ReadFdExactly(fd, name, path_length)) {
fail_message(fd, "filename read failure");
return false;
}
name[path_length] = 0;
char *buffer = reinterpret_cast<char*>(malloc(SYNC_DATA_MAX));
if(buffer == 0) goto fail;
const char* id = reinterpret_cast<const char*>(&request.id);
D("sync: '%.4s' '%s'\n", id, name);
for(;;) {
D("sync: waiting for command\n");
if(!ReadFdExactly(fd, &msg.req, sizeof(msg.req))) {
fail_message(fd, "command read failure");
break;
}
namelen = ltohl(msg.req.namelen);
if(namelen > 1024) {
fail_message(fd, "invalid namelen");
break;
}
if(!ReadFdExactly(fd, name, namelen)) {
fail_message(fd, "filename read failure");
break;
}
name[namelen] = 0;
msg.req.namelen = 0;
D("sync: '%s' '%s'\n", (char*) &msg.req, name);
switch(msg.req.id) {
case ID_STAT:
if(do_stat(fd, name)) goto fail;
break;
case ID_LIST:
if(do_list(fd, name)) goto fail;
break;
case ID_SEND:
if(do_send(fd, name, buffer)) goto fail;
break;
case ID_RECV:
if(do_recv(fd, name, buffer)) goto fail;
break;
case ID_QUIT:
goto fail;
default:
fail_message(fd, "unknown command");
goto fail;
}
switch (request.id) {
case ID_STAT:
if (!do_stat(fd, name)) return false;
break;
case ID_LIST:
if (!do_list(fd, name)) return false;
break;
case ID_SEND:
if (!do_send(fd, name, buffer)) return false;
break;
case ID_RECV:
if (!do_recv(fd, name, buffer)) return false;
break;
case ID_QUIT:
return false;
default:
fail_message(fd, android::base::StringPrintf("unknown command '%.4s' (%08x)",
id, request.id));
return false;
}
return true;
}
void file_sync_service(int fd, void* cookie) {
std::vector<char> buffer(SYNC_DATA_MAX);
while (handle_sync_command(fd, buffer)) {
}
fail:
if(buffer != 0) free(buffer);
D("sync: done\n");
adb_close(fd);
}

View File

@ -26,7 +26,6 @@
#define ID_STAT MKID('S','T','A','T')
#define ID_LIST MKID('L','I','S','T')
#define ID_ULNK MKID('U','L','N','K')
#define ID_SEND MKID('S','E','N','D')
#define ID_RECV MKID('R','E','C','V')
#define ID_DENT MKID('D','E','N','T')
@ -36,41 +35,41 @@
#define ID_FAIL MKID('F','A','I','L')
#define ID_QUIT MKID('Q','U','I','T')
struct SyncRequest {
uint32_t id; // ID_STAT, et cetera.
uint32_t path_length; // <= 1024
// Followed by 'path_length' bytes of path (not NUL-terminated).
} __attribute__((packed)) ;
union syncmsg {
unsigned id;
struct {
unsigned id;
unsigned namelen;
} req;
struct {
struct __attribute__((packed)) {
unsigned id;
unsigned mode;
unsigned size;
unsigned time;
} stat;
struct {
struct __attribute__((packed)) {
unsigned id;
unsigned mode;
unsigned size;
unsigned time;
unsigned namelen;
} dent;
struct {
struct __attribute__((packed)) {
unsigned id;
unsigned size;
} data;
struct {
struct __attribute__((packed)) {
unsigned id;
unsigned msglen;
} status;
} ;
};
void file_sync_service(int fd, void *cookie);
int do_sync_ls(const char *path);
int do_sync_push(const char *lpath, const char *rpath, bool show_progress);
int do_sync_sync(const std::string& lpath, const std::string& rpath, bool list_only);
int do_sync_pull(const char *rpath, const char *lpath, bool show_progress, int pullTime);
void file_sync_service(int fd, void* cookie);
bool do_sync_ls(const char* path);
bool do_sync_push(const char* lpath, const char* rpath, bool show_progress);
bool do_sync_sync(const std::string& lpath, const std::string& rpath, bool list_only);
bool do_sync_pull(const char* rpath, const char* lpath, bool show_progress, int copy_attrs);
#define SYNC_DATA_MAX (64*1024)

View File

@ -438,8 +438,7 @@ static int create_subproc_thread(const char *name, SubprocessType type) {
}
#endif
int service_to_fd(const char *name)
{
int service_to_fd(const char* name) {
int ret = -1;
if(!strncmp(name, "tcp:", 4)) {
@ -503,13 +502,11 @@ int service_to_fd(const char *name)
} else if(!strncmp(name, "unroot:", 7)) {
ret = create_service_thread(restart_unroot_service, NULL);
} else if(!strncmp(name, "backup:", 7)) {
ret = create_subproc_thread(
android::base::StringPrintf("/system/bin/bu backup %s",
(name + 7)).c_str(),
SubprocessType::kRaw);
} else if(!strncmp(name, "restore:", 8)) {
ret = create_subproc_thread("/system/bin/bu restore",
ret = create_subproc_thread(android::base::StringPrintf("/system/bin/bu backup %s",
(name + 7)).c_str(),
SubprocessType::kRaw);
} else if(!strncmp(name, "restore:", 8)) {
ret = create_subproc_thread("/system/bin/bu restore", SubprocessType::kRaw);
} else if(!strncmp(name, "tcpip:", 6)) {
int port;
if (sscanf(name + 6, "%d", &port) != 1) {
@ -667,8 +664,7 @@ static void connect_service(int fd, void* data) {
#endif
#if ADB_HOST
asocket* host_service_to_socket(const char* name, const char *serial)
{
asocket* host_service_to_socket(const char* name, const char* serial) {
if (!strcmp(name,"track-devices")) {
return create_device_tracker();
} else if (!strncmp(name, "wait-for-", strlen("wait-for-"))) {

View File

@ -865,8 +865,7 @@ void atransport::add_feature(const std::string& feature) {
}
bool atransport::CanUseFeature(const std::string& feature) const {
return has_feature(feature) &&
supported_features().count(feature) > 0;
return has_feature(feature) && supported_features().count(feature) > 0;
}
#if ADB_HOST