From cc731cc76786b6bdc58764aad9924c0d0c8d645f Mon Sep 17 00:00:00 2001 From: Dan Albert Date: Tue, 24 Feb 2015 21:26:58 -0800 Subject: [PATCH] Test readx/writex (now renamed). Renamed readx/writex to ReadFdExactly/WriteFdExactly respectively. These read/write a full fixed-size buffer. If the whole buffer cannot be read/written, these functions return an error. Rename write_string to WriteStringFully. Move the TEMP_FAILURE_RETRY definition in sysdeps.h out of the !Windows section. It seems Windows won't actually interrupt a call, but it's easier to just define it than to #ifdef each call. Change-Id: Ia8ddffa2a52764a2f9a281c96c937660e002b9b9 --- adb/Android.mk | 6 +- adb/adb.c | 13 ++-- adb/adb_client.c | 20 +++--- adb/adb_io.cpp | 93 +++++++++++++++++++++++++ adb/adb_io.h | 53 ++++++++++++++ adb/adb_io_test.cpp | 142 ++++++++++++++++++++++++++++++++++++++ adb/adb_trace.h | 2 + adb/commandline.c | 12 ++-- adb/fdevent.cpp | 4 +- adb/file_sync_client.c | 66 +++++++++--------- adb/file_sync_service.c | 40 +++++------ adb/framebuffer_service.c | 14 ++-- adb/remount_service.c | 19 ++--- adb/services.c | 27 ++++---- adb/sockets.c | 13 +++- adb/sysdeps.h | 34 ++++----- adb/transport.c | 70 +------------------ adb/transport.h | 11 ++- adb/transport_local.c | 7 +- 19 files changed, 435 insertions(+), 211 deletions(-) create mode 100644 adb/adb_io.cpp create mode 100644 adb/adb_io.h create mode 100644 adb/adb_io_test.cpp diff --git a/adb/Android.mk b/adb/Android.mk index 86d178a2b..adad69f5b 100644 --- a/adb/Android.mk +++ b/adb/Android.mk @@ -19,6 +19,7 @@ ADB_CLANG := LIBADB_SRC_FILES := \ adb.c \ adb_auth.c \ + adb_io.cpp \ adb_listeners.c \ sockets.c \ transport.c \ @@ -69,6 +70,7 @@ endif include $(BUILD_HOST_STATIC_LIBRARY) LIBADB_TEST_SRCS := \ + adb_io_test.cpp \ transport_test.cpp \ include $(CLEAR_VARS) @@ -77,7 +79,7 @@ LOCAL_MODULE := adbd_test LOCAL_CFLAGS := -DADB_HOST=0 $(LIBADB_CFLAGS) LOCAL_SRC_FILES := $(LIBADB_TEST_SRCS) LOCAL_STATIC_LIBRARIES := libadbd -LOCAL_SHARED_LIBRARIES := liblog +LOCAL_SHARED_LIBRARIES := liblog libcutils libutils include $(BUILD_NATIVE_TEST) include $(CLEAR_VARS) @@ -85,10 +87,12 @@ LOCAL_CLANG := $(ADB_CLANG) LOCAL_MODULE := adb_test LOCAL_CFLAGS := -DADB_HOST=1 $(LIBADB_CFLAGS) LOCAL_SRC_FILES := $(LIBADB_TEST_SRCS) services.c +LOCAL_SHARED_LIBRARIES := liblog LOCAL_STATIC_LIBRARIES := \ libadb \ libcrypto_static \ libcutils \ + libutils \ ifeq ($(HOST_OS),linux) LOCAL_LDLIBS += -lrt -ldl -lpthread diff --git a/adb/adb.c b/adb/adb.c index 9c0bd8c26..5f244a583 100644 --- a/adb/adb.c +++ b/adb/adb.c @@ -30,6 +30,7 @@ #include "sysdeps.h" #include "adb.h" #include "adb_auth.h" +#include "adb_io.h" #include "adb_listeners.h" #include "transport.h" @@ -263,8 +264,8 @@ static void send_msg_with_header(int fd, const char* msg, size_t msglen) { if (msglen > 0xffff) msglen = 0xffff; snprintf(header, sizeof(header), "%04x", (unsigned)msglen); - writex(fd, header, 4); - writex(fd, msg, msglen); + WriteFdExactly(fd, header, 4); + WriteFdExactly(fd, msg, msglen); } #endif @@ -274,8 +275,8 @@ static void send_msg_with_okay(int fd, const char* msg, size_t msglen) { if (msglen > 0xffff) msglen = 0xffff; snprintf(header, sizeof(header), "OKAY%04x", (unsigned)msglen); - writex(fd, header, 8); - writex(fd, msg, msglen); + WriteFdExactly(fd, header, 8); + WriteFdExactly(fd, msg, msglen); } #endif // ADB_HOST @@ -790,9 +791,9 @@ int handle_forward_request(const char* service, transport_type ttype, char* seri if(r == 0) { #if ADB_HOST /* On the host: 1st OKAY is connect, 2nd OKAY is status */ - writex(reply_fd, "OKAY", 4); + WriteFdExactly(reply_fd, "OKAY", 4); #endif - writex(reply_fd, "OKAY", 4); + WriteFdExactly(reply_fd, "OKAY", 4); return 1; } diff --git a/adb/adb_client.c b/adb/adb_client.c index 9bf7b2bb2..5d2bbd713 100644 --- a/adb/adb_client.c +++ b/adb/adb_client.c @@ -27,7 +27,7 @@ #define TRACE_TAG TRACE_ADB #include "adb_client.h" -#include "transport.h" +#include "adb_io.h" #include "zipfile/zipfile.h" static transport_type __adb_transport = kTransportAny; @@ -138,7 +138,7 @@ static int switch_socket_transport(int fd) len = strlen(service); snprintf(tmp, sizeof tmp, "%04x", len); - if(writex(fd, tmp, 4) || writex(fd, service, len)) { + if(!WriteFdExactly(fd, tmp, 4) || !WriteFdExactly(fd, service, len)) { strcpy(__adb_error, "write failure during connection"); adb_close(fd); return -1; @@ -159,7 +159,7 @@ int adb_status(int fd) unsigned char buf[5]; unsigned len; - if(readx(fd, buf, 4)) { + if(!ReadFdExactly(fd, buf, 4)) { strcpy(__adb_error, "protocol fault (no status)"); return -1; } @@ -175,14 +175,14 @@ int adb_status(int fd) return -1; } - if(readx(fd, buf, 4)) { + if(!ReadFdExactly(fd, buf, 4)) { strcpy(__adb_error, "protocol fault (status len)"); return -1; } buf[4] = 0; len = strtoul((char*)buf, 0, 16); if(len > 255) len = 255; - if(readx(fd, __adb_error, len)) { + if(!ReadFdExactly(fd, __adb_error, len)) { strcpy(__adb_error, "protocol fault (status read)"); return -1; } @@ -218,7 +218,7 @@ int _adb_connect(const char *service) return -1; } - if(writex(fd, tmp, 4) || writex(fd, service, len)) { + if(!WriteFdExactly(fd, tmp, 4) || !WriteFdExactly(fd, service, len)) { strcpy(__adb_error, "write failure during connection"); adb_close(fd); return -1; @@ -263,12 +263,12 @@ int adb_connect(const char *service) // if we have a file descriptor, then parse version result if(fd >= 0) { - if(readx(fd, buf, 4)) goto error; + if(!ReadFdExactly(fd, buf, 4)) goto error; buf[4] = 0; n = strtoul(buf, 0, 16); if(n > sizeof(buf)) goto error; - if(readx(fd, buf, n)) goto error; + if(!ReadFdExactly(fd, buf, n)) goto error; adb_close(fd); if (sscanf(buf, "%04x", &version) != 1) goto error; @@ -338,7 +338,7 @@ char *adb_query(const char *service) return 0; } - if(readx(fd, buf, 4)) goto oops; + if(!ReadFdExactly(fd, buf, 4)) goto oops; buf[4] = 0; n = strtoul(buf, 0, 16); @@ -350,7 +350,7 @@ char *adb_query(const char *service) tmp = malloc(n + 1); if(tmp == 0) goto oops; - if(readx(fd, tmp, n) == 0) { + if(!ReadFdExactly(fd, tmp, n) == 0) { tmp[n] = 0; adb_close(fd); return tmp; diff --git a/adb/adb_io.cpp b/adb/adb_io.cpp new file mode 100644 index 000000000..ca208ad70 --- /dev/null +++ b/adb/adb_io.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2015 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. + */ + +#define TRACE_TAG TRACE_RWX + +#include "sysdeps.h" +#include "adb_io.h" + +#include + +#include "adb_trace.h" +#include "transport.h" + +bool ReadFdExactly(int fd, void* buf, size_t len) { + char* p = reinterpret_cast(buf); + +#if ADB_TRACE + size_t len0 = len; +#endif + + D("readx: fd=%d wanted=%zu\n", fd, len); + while (len > 0) { + int r = TEMP_FAILURE_RETRY(adb_read(fd, p, len)); + if (r > 0) { + len -= r; + p += r; + } else if (r == -1) { + D("readx: fd=%d error %d: %s\n", fd, errno, strerror(errno)); + return false; + } else { + D("readx: fd=%d disconnected\n", fd); + errno = 0; + return false; + } + } + +#if ADB_TRACE + D("readx: fd=%d wanted=%zu got=%zu\n", fd, len0, len0 - len); + if (ADB_TRACING) { + dump_hex(reinterpret_cast(buf), len0); + } +#endif + + return true; +} + +bool WriteFdExactly(int fd, const void* buf, size_t len) { + const char* p = reinterpret_cast(buf); + int r; + +#if ADB_TRACE + D("writex: fd=%d len=%d: ", fd, (int)len); + if (ADB_TRACING) { + dump_hex(reinterpret_cast(buf), len); + } +#endif + + while (len > 0) { + r = TEMP_FAILURE_RETRY(adb_write(fd, p, len)); + if (r == -1) { + D("writex: fd=%d error %d: %s\n", fd, errno, strerror(errno)); + if (errno == EAGAIN) { + adb_sleep_ms(1); // just yield some cpu time + continue; + } else if (errno == EPIPE) { + D("writex: fd=%d disconnected\n", fd); + errno = 0; + return false; + } + } else { + len -= r; + p += r; + } + } + return true; +} + +bool WriteStringFully(int fd, const char* str) { + return WriteFdExactly(fd, str, strlen(str)); +} diff --git a/adb/adb_io.h b/adb/adb_io.h new file mode 100644 index 000000000..7d09e7ba5 --- /dev/null +++ b/adb/adb_io.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2015 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. + */ + +#ifndef ADB_IO_H +#define ADB_IO_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * 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 WriteFdExactly, but with an implicit len = strlen(buf). */ +bool WriteStringFully(int fd, const char* str); + +#ifdef __cplusplus +} +#endif + +#endif /* ADB_IO_H */ diff --git a/adb/adb_io_test.cpp b/adb/adb_io_test.cpp new file mode 100644 index 000000000..330d9ce5c --- /dev/null +++ b/adb/adb_io_test.cpp @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2015 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 "adb_io.h" + +#include + +#include +#include +#include + +#include + +#include "utils/file.h" + +class TemporaryFile { + public: + TemporaryFile() { + init("/data/local/tmp"); + if (fd == -1) { + init("/tmp"); + } + } + + ~TemporaryFile() { + close(fd); + unlink(filename); + } + + int fd; + char filename[1024]; + + private: + void init(const char* tmp_dir) { + snprintf(filename, sizeof(filename), "%s/TemporaryFile-XXXXXX", tmp_dir); + fd = mkstemp(filename); + } +}; + +TEST(io, ReadFdExactly_whole) { + const char expected[] = "Foobar"; + TemporaryFile tf; + ASSERT_NE(-1, tf.fd); + + ASSERT_TRUE(android::WriteStringToFd(expected, tf.fd)) << strerror(errno); + ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0)); + + // Test reading the whole file. + char buf[sizeof(expected)] = {}; + ASSERT_TRUE(ReadFdExactly(tf.fd, buf, sizeof(buf) - 1)) << strerror(errno); + EXPECT_STREQ(expected, buf); +} + +TEST(io, ReadFdExactly_eof) { + const char expected[] = "Foobar"; + TemporaryFile tf; + ASSERT_NE(-1, tf.fd); + + ASSERT_TRUE(android::WriteStringToFd(expected, tf.fd)) << strerror(errno); + ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0)); + + // Test that not having enough data will fail. + char buf[sizeof(expected) + 1] = {}; + ASSERT_FALSE(ReadFdExactly(tf.fd, buf, sizeof(buf))); + EXPECT_EQ(0, errno) << strerror(errno); +} + +TEST(io, ReadFdExactly_partial) { + const char input[] = "Foobar"; + TemporaryFile tf; + ASSERT_NE(-1, tf.fd); + + ASSERT_TRUE(android::WriteStringToFd(input, tf.fd)) << strerror(errno); + ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0)); + + // Test reading a partial file. + char buf[sizeof(input) - 1] = {}; + ASSERT_TRUE(ReadFdExactly(tf.fd, buf, sizeof(buf) - 1)); + + std::string expected(input); + expected.pop_back(); + EXPECT_STREQ(expected.c_str(), buf); +} + +TEST(io, WriteFdExactly_whole) { + const char expected[] = "Foobar"; + TemporaryFile tf; + ASSERT_NE(-1, tf.fd); + + // Test writing the whole string to the file. + ASSERT_TRUE(WriteFdExactly(tf.fd, expected, sizeof(expected))) + << strerror(errno); + ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0)); + + std::string s; + ASSERT_TRUE(android::ReadFdToString(tf.fd, &s)); + EXPECT_STREQ(expected, s.c_str()); +} + +TEST(io, WriteFdExactly_partial) { + const char buf[] = "Foobar"; + TemporaryFile tf; + ASSERT_NE(-1, tf.fd); + + // Test writing a partial string to the file. + ASSERT_TRUE(WriteFdExactly(tf.fd, buf, sizeof(buf) - 2)) << strerror(errno); + ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0)); + + std::string expected(buf); + expected.pop_back(); + + std::string s; + ASSERT_TRUE(android::ReadFdToString(tf.fd, &s)); + EXPECT_EQ(expected, s); +} + +TEST(io, WriteStringFully) { + const char str[] = "Foobar"; + TemporaryFile tf; + ASSERT_NE(-1, tf.fd); + + // Test writing a partial string to the file. + ASSERT_TRUE(WriteStringFully(tf.fd, str)) << strerror(errno); + ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0)); + + std::string s; + ASSERT_TRUE(android::ReadFdToString(tf.fd, &s)); + EXPECT_STREQ(str, s.c_str()); +} diff --git a/adb/adb_trace.h b/adb/adb_trace.h index 69b6c697b..ef5dc2409 100644 --- a/adb/adb_trace.h +++ b/adb/adb_trace.h @@ -19,6 +19,8 @@ #if !ADB_HOST #include +#else +#include #endif #ifdef __cplusplus diff --git a/adb/commandline.c b/adb/commandline.c index 2a02c38d4..a8ad7bd9f 100644 --- a/adb/commandline.c +++ b/adb/commandline.c @@ -35,10 +35,10 @@ #define TRACE_TAG TRACE_ADB #include "adb.h" -#include "adb_client.h" #include "adb_auth.h" +#include "adb_client.h" +#include "adb_io.h" #include "file_sync_service.h" -#include "transport.h" static int do_cmd(transport_type ttype, char* serial, char *cmd, ...); @@ -486,7 +486,7 @@ int adb_download_buffer(const char *service, const char *fn, const void* data, i while(sz > 0) { unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz; - if(writex(fd, ptr, xfer)) { + if(!WriteFdExactly(fd, ptr, xfer)) { adb_status(fd); fprintf(stderr,"* failed to write data '%s' *\n", adb_error()); return -1; @@ -502,7 +502,7 @@ int adb_download_buffer(const char *service, const char *fn, const void* data, i printf("\n"); } - if(readx(fd, buf, 4)){ + if(!ReadFdExactly(fd, buf, 4)){ fprintf(stderr,"* error reading response *\n"); adb_close(fd); return -1; @@ -587,7 +587,7 @@ int adb_sideload_host(const char* fn) { int last_percent = -1; for (;;) { - if (readx(fd, buf, 8)) { + if (!ReadFdExactly(fd, buf, 8)) { fprintf(stderr, "* failed to read command: %s\n", adb_error()); status = -1; goto done; @@ -614,7 +614,7 @@ int adb_sideload_host(const char* fn) { to_write = sz - offset; } - if(writex(fd, start, to_write)) { + if(!WriteFdExactly(fd, start, to_write)) { adb_status(fd); fprintf(stderr,"* failed to write data '%s' *\n", adb_error()); status = -1; diff --git a/adb/fdevent.cpp b/adb/fdevent.cpp index bd0f3b26e..45d33db03 100644 --- a/adb/fdevent.cpp +++ b/adb/fdevent.cpp @@ -28,9 +28,9 @@ #include #include +#include "adb_io.h" #include "adb_trace.h" #include "fdevent.h" -#include "transport.h" #include "sysdeps.h" #define TRACE_TAG TRACE_FDEVENT @@ -528,7 +528,7 @@ static void fdevent_subproc_event_func(int fd, unsigned ev, if(ev & FDE_READ){ int subproc_fd; - if(readx(fd, &subproc_fd, sizeof(subproc_fd))) { + if(!ReadFdExactly(fd, &subproc_fd, sizeof(subproc_fd))) { FATAL("Failed to read the subproc's fd from fd=%d\n", fd); } if((subproc_fd < 0) || (subproc_fd >= fd_table_max)) { diff --git a/adb/file_sync_client.c b/adb/file_sync_client.c index cf446e2ed..3a0c66616 100644 --- a/adb/file_sync_client.c +++ b/adb/file_sync_client.c @@ -30,8 +30,8 @@ #include "adb.h" #include "adb_client.h" +#include "adb_io.h" #include "file_sync_service.h" -#include "transport.h" #include "zipfile/zipfile.h" static unsigned long long total_bytes; @@ -87,7 +87,7 @@ void sync_quit(int fd) msg.req.id = ID_QUIT; msg.req.namelen = 0; - writex(fd, &msg.req, sizeof(msg.req)); + WriteFdExactly(fd, &msg.req, sizeof(msg.req)); } typedef void (*sync_ls_cb)(unsigned mode, unsigned size, unsigned time, const char *name, void *cookie); @@ -104,20 +104,20 @@ int sync_ls(int fd, const char *path, sync_ls_cb func, void *cookie) msg.req.id = ID_LIST; msg.req.namelen = htoll(len); - if(writex(fd, &msg.req, sizeof(msg.req)) || - writex(fd, path, len)) { + if(!WriteFdExactly(fd, &msg.req, sizeof(msg.req)) || + !WriteFdExactly(fd, path, len)) { goto fail; } for(;;) { - if(readx(fd, &msg.dent, sizeof(msg.dent))) break; + if(!ReadFdExactly(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; + if(!ReadFdExactly(fd, buf, len)) break; buf[len] = 0; func(ltohl(msg.dent.mode), @@ -150,12 +150,12 @@ int sync_readtime(int fd, const char *path, unsigned int *timestamp, msg.req.id = ID_STAT; msg.req.namelen = htoll(len); - if(writex(fd, &msg.req, sizeof(msg.req)) || - writex(fd, path, len)) { + if(!WriteFdExactly(fd, &msg.req, sizeof(msg.req)) || + !WriteFdExactly(fd, path, len)) { return -1; } - if(readx(fd, &msg.stat, sizeof(msg.stat))) { + if(!ReadFdExactly(fd, &msg.stat, sizeof(msg.stat))) { return -1; } @@ -176,8 +176,8 @@ static int sync_start_readtime(int fd, const char *path) msg.req.id = ID_STAT; msg.req.namelen = htoll(len); - if(writex(fd, &msg.req, sizeof(msg.req)) || - writex(fd, path, len)) { + if(!WriteFdExactly(fd, &msg.req, sizeof(msg.req)) || + !WriteFdExactly(fd, path, len)) { return -1; } @@ -189,7 +189,7 @@ static int sync_finish_readtime(int fd, unsigned int *timestamp, { syncmsg msg; - if(readx(fd, &msg.stat, sizeof(msg.stat))) + if(!ReadFdExactly(fd, &msg.stat, sizeof(msg.stat))) return -1; if(msg.stat.id != ID_STAT) @@ -210,12 +210,12 @@ int sync_readmode(int fd, const char *path, unsigned *mode) msg.req.id = ID_STAT; msg.req.namelen = htoll(len); - if(writex(fd, &msg.req, sizeof(msg.req)) || - writex(fd, path, len)) { + if(!WriteFdExactly(fd, &msg.req, sizeof(msg.req)) || + !WriteFdExactly(fd, path, len)) { return -1; } - if(readx(fd, &msg.stat, sizeof(msg.stat))) { + if(!ReadFdExactly(fd, &msg.stat, sizeof(msg.stat))) { return -1; } @@ -265,7 +265,7 @@ static int write_data_file(int fd, const char *path, syncsendbuf *sbuf, int show } sbuf->size = htoll(ret); - if(writex(fd, sbuf, sizeof(unsigned) * 2 + ret)){ + if(!WriteFdExactly(fd, sbuf, sizeof(unsigned) * 2 + ret)){ err = -1; break; } @@ -295,7 +295,7 @@ static int write_data_buffer(int fd, char* file_buffer, int size, syncsendbuf *s memcpy(sbuf->data, &file_buffer[total], count); sbuf->size = htoll(count); - if(writex(fd, sbuf, sizeof(unsigned) * 2 + count)){ + if(!WriteFdExactly(fd, sbuf, sizeof(unsigned) * 2 + count)){ err = -1; break; } @@ -327,7 +327,7 @@ static int write_data_link(int fd, const char *path, syncsendbuf *sbuf) sbuf->size = htoll(len + 1); sbuf->id = ID_DATA; - ret = writex(fd, sbuf, sizeof(unsigned) * 2 + len + 1); + ret = !WriteFdExactly(fd, sbuf, sizeof(unsigned) * 2 + len + 1); if(ret) return -1; @@ -356,8 +356,8 @@ static int sync_send(int fd, const char *lpath, const char *rpath, 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)) { + if(!WriteFdExactly(fd, &msg.req, sizeof(msg.req)) || + !WriteFdExactly(fd, rpath, len) || !WriteFdExactly(fd, tmp, r)) { free(file_buffer); goto fail; } @@ -374,17 +374,17 @@ static int sync_send(int fd, const char *lpath, const char *rpath, msg.data.id = ID_DONE; msg.data.size = htoll(mtime); - if(writex(fd, &msg.data, sizeof(msg.data))) + if(!WriteFdExactly(fd, &msg.data, sizeof(msg.data))) goto fail; - if(readx(fd, &msg.status, sizeof(msg.status))) + if(!ReadFdExactly(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)) { + if(!ReadFdExactly(fd, sbuf->data, len)) { return -1; } sbuf->data[len] = 0; @@ -440,12 +440,12 @@ int sync_recv(int fd, const char *rpath, const char *lpath, int show_progress) stat_msg.req.id = ID_STAT; stat_msg.req.namelen = htoll(len); - if (writex(fd, &stat_msg.req, sizeof(stat_msg.req)) || - writex(fd, rpath, len)) { + if (!WriteFdExactly(fd, &stat_msg.req, sizeof(stat_msg.req)) || + !WriteFdExactly(fd, rpath, len)) { return -1; } - if (readx(fd, &stat_msg.stat, sizeof(stat_msg.stat))) { + if (!ReadFdExactly(fd, &stat_msg.stat, sizeof(stat_msg.stat))) { return -1; } @@ -456,12 +456,12 @@ int sync_recv(int fd, const char *rpath, const char *lpath, int show_progress) msg.req.id = ID_RECV; msg.req.namelen = htoll(len); - if(writex(fd, &msg.req, sizeof(msg.req)) || - writex(fd, rpath, len)) { + if(!WriteFdExactly(fd, &msg.req, sizeof(msg.req)) || + !WriteFdExactly(fd, rpath, len)) { return -1; } - if(readx(fd, &msg.data, sizeof(msg.data))) { + if(!ReadFdExactly(fd, &msg.data, sizeof(msg.data))) { return -1; } id = msg.data.id; @@ -480,7 +480,7 @@ int sync_recv(int fd, const char *rpath, const char *lpath, int show_progress) } for(;;) { - if(readx(fd, &msg.data, sizeof(msg.data))) { + if(!ReadFdExactly(fd, &msg.data, sizeof(msg.data))) { return -1; } id = msg.data.id; @@ -495,12 +495,12 @@ int sync_recv(int fd, const char *rpath, const char *lpath, int show_progress) return -1; } - if(readx(fd, buffer, len)) { + if(!ReadFdExactly(fd, buffer, len)) { adb_close(lfd); return -1; } - if(writex(lfd, buffer, len)) { + if(!WriteFdExactly(lfd, buffer, len)) { fprintf(stderr,"cannot write '%s': %s\n", rpath, strerror(errno)); adb_close(lfd); return -1; @@ -523,7 +523,7 @@ remote_error: if(id == ID_FAIL) { len = ltohl(msg.data.size); if(len > 256) len = 256; - if(readx(fd, buffer, len)) { + if(!ReadFdExactly(fd, buffer, len)) { return -1; } buffer[len] = 0; diff --git a/adb/file_sync_service.c b/adb/file_sync_service.c index 0944e5d64..0b289e85a 100644 --- a/adb/file_sync_service.c +++ b/adb/file_sync_service.c @@ -29,9 +29,9 @@ #define TRACE_TAG TRACE_SYNC #include "adb.h" +#include "adb_io.h" #include "file_sync_service.h" #include "private/android_filesystem_config.h" -#include "transport.h" /* TODO: use fs_config to configure permissions on /data */ static bool is_on_system(const char *name) { @@ -97,7 +97,7 @@ static int do_stat(int s, const char *path) msg.stat.time = htoll(st.st_mtime); } - return writex(s, &msg.stat, sizeof(msg.stat)); + return WriteFdExactly(s, &msg.stat, sizeof(msg.stat)) ? 0 : -1; } static int do_list(int s, const char *path) @@ -135,8 +135,8 @@ static int do_list(int s, const char *path) msg.dent.time = htoll(st.st_mtime); msg.dent.namelen = htoll(len); - if(writex(s, &msg.dent, sizeof(msg.dent)) || - writex(s, de->d_name, len)) { + if(!WriteFdExactly(s, &msg.dent, sizeof(msg.dent)) || + !WriteFdExactly(s, de->d_name, len)) { closedir(d); return -1; } @@ -151,7 +151,7 @@ done: msg.dent.size = 0; msg.dent.time = 0; msg.dent.namelen = 0; - return writex(s, &msg.dent, sizeof(msg.dent)); + return !WriteFdExactly(s, &msg.dent, sizeof(msg.dent)) ? 0 : -1; } static int fail_message(int s, const char *reason) @@ -163,8 +163,8 @@ static int fail_message(int s, const char *reason) msg.data.id = ID_FAIL; msg.data.size = htoll(len); - if(writex(s, &msg.data, sizeof(msg.data)) || - writex(s, reason, len)) { + if(!WriteFdExactly(s, &msg.data, sizeof(msg.data)) || + !WriteFdExactly(s, reason, len)) { return -1; } else { return 0; @@ -217,7 +217,7 @@ static int handle_send_file(int s, char *path, uid_t uid, for(;;) { unsigned int len; - if(readx(s, &msg.data, sizeof(msg.data))) + if(!ReadFdExactly(s, &msg.data, sizeof(msg.data))) goto fail; if(msg.data.id != ID_DATA) { @@ -233,12 +233,12 @@ static int handle_send_file(int s, char *path, uid_t uid, fail_message(s, "oversize data message"); goto fail; } - if(readx(s, buffer, len)) + if(!ReadFdExactly(s, buffer, len)) goto fail; if(fd < 0) continue; - if(writex(fd, buffer, len)) { + if(!WriteFdExactly(fd, buffer, len)) { int saved_errno = errno; adb_close(fd); if (do_unlink) adb_unlink(path); @@ -258,7 +258,7 @@ static int handle_send_file(int s, char *path, uid_t uid, msg.status.id = ID_OKAY; msg.status.msglen = 0; - if(writex(s, &msg.status, sizeof(msg.status))) + if(!WriteFdExactly(s, &msg.status, sizeof(msg.status))) return -1; } return 0; @@ -279,7 +279,7 @@ static int handle_send_link(int s, char *path, char *buffer) unsigned int len; int ret; - if(readx(s, &msg.data, sizeof(msg.data))) + if(!ReadFdExactly(s, &msg.data, sizeof(msg.data))) return -1; if(msg.data.id != ID_DATA) { @@ -292,7 +292,7 @@ static int handle_send_link(int s, char *path, char *buffer) fail_message(s, "oversize data message"); return -1; } - if(readx(s, buffer, len)) + if(!ReadFdExactly(s, buffer, len)) return -1; ret = symlink(buffer, path); @@ -308,13 +308,13 @@ static int handle_send_link(int s, char *path, char *buffer) return -1; } - if(readx(s, &msg.data, sizeof(msg.data))) + if(!ReadFdExactly(s, &msg.data, sizeof(msg.data))) return -1; if(msg.data.id == ID_DONE) { msg.status.id = ID_OKAY; msg.status.msglen = 0; - if(writex(s, &msg.status, sizeof(msg.status))) + if(!WriteFdExactly(s, &msg.status, sizeof(msg.status))) return -1; } else { fail_message(s, "invalid data message: expected ID_DONE"); @@ -396,8 +396,8 @@ static int do_recv(int s, const char *path, char *buffer) return r; } msg.data.size = htoll(r); - if(writex(s, &msg.data, sizeof(msg.data)) || - writex(s, buffer, r)) { + if(!WriteFdExactly(s, &msg.data, sizeof(msg.data)) || + !WriteFdExactly(s, buffer, r)) { adb_close(fd); return -1; } @@ -407,7 +407,7 @@ static int do_recv(int s, const char *path, char *buffer) msg.data.id = ID_DONE; msg.data.size = 0; - if(writex(s, &msg.data, sizeof(msg.data))) { + if(!WriteFdExactly(s, &msg.data, sizeof(msg.data))) { return -1; } @@ -426,7 +426,7 @@ void file_sync_service(int fd, void *cookie) for(;;) { D("sync: waiting for command\n"); - if(readx(fd, &msg.req, sizeof(msg.req))) { + if(!ReadFdExactly(fd, &msg.req, sizeof(msg.req))) { fail_message(fd, "command read failure"); break; } @@ -435,7 +435,7 @@ void file_sync_service(int fd, void *cookie) fail_message(fd, "invalid namelen"); break; } - if(readx(fd, name, namelen)) { + if(!ReadFdExactly(fd, name, namelen)) { fail_message(fd, "filename read failure"); break; } diff --git a/adb/framebuffer_service.c b/adb/framebuffer_service.c index 5665a56a1..9d17d2cac 100644 --- a/adb/framebuffer_service.c +++ b/adb/framebuffer_service.c @@ -29,8 +29,8 @@ #include "sysdeps.h" #include "adb.h" +#include "adb_io.h" #include "fdevent.h" -#include "transport.h" /* TODO: ** - sync with vsync to avoid tearing @@ -82,9 +82,9 @@ void framebuffer_service(int fd, void *cookie) fd_screencap = fds[0]; /* read w, h & format */ - if(readx(fd_screencap, &w, 4)) goto done; - if(readx(fd_screencap, &h, 4)) goto done; - if(readx(fd_screencap, &f, 4)) goto done; + if(!ReadFdExactly(fd_screencap, &w, 4)) goto done; + if(!ReadFdExactly(fd_screencap, &h, 4)) goto done; + if(!ReadFdExactly(fd_screencap, &f, 4)) goto done; fbinfo.version = DDMS_RAWIMAGE_VERSION; /* see hardware/hardware.h */ @@ -164,15 +164,15 @@ void framebuffer_service(int fd, void *cookie) } /* write header */ - if(writex(fd, &fbinfo, sizeof(fbinfo))) goto done; + if(!WriteFdExactly(fd, &fbinfo, sizeof(fbinfo))) goto done; /* write data */ for(i = 0; i < fbinfo.size; i += bsize) { bsize = sizeof(buf); if (i + bsize > fbinfo.size) bsize = fbinfo.size - i; - if(readx(fd_screencap, buf, bsize)) goto done; - if(writex(fd, buf, bsize)) goto done; + if(!ReadFdExactly(fd_screencap, buf, bsize)) goto done; + if(!WriteFdExactly(fd, buf, bsize)) goto done; } done: diff --git a/adb/remount_service.c b/adb/remount_service.c index 7e5613ab6..2fe05c3c0 100644 --- a/adb/remount_service.c +++ b/adb/remount_service.c @@ -27,8 +27,8 @@ #define TRACE_TAG TRACE_ADB #include "adb.h" +#include "adb_io.h" #include "cutils/properties.h" -#include "transport.h" static int system_ro = 1; static int vendor_ro = 1; @@ -108,11 +108,6 @@ errout: return rc; } -static void write_string(int fd, const char* str) -{ - writex(fd, str, strlen(str)); -} - void remount_service(int fd, void *cookie) { char buffer[200]; @@ -138,30 +133,30 @@ void remount_service(int fd, void *cookie) both ? " and " : "", vendor_verified ? "vendor" : "", both ? "s" : ""); - write_string(fd, buffer); + WriteStringFully(fd, buffer); snprintf(buffer, sizeof(buffer), "Use \"adb disable-verity\" to disable verity.\n" "If you do not, remount may succeed, however, you will still " "not be able to write to these volumes.\n"); - write_string(fd, buffer); + WriteStringFully(fd, buffer); } if (remount("/system", &system_ro)) { snprintf(buffer, sizeof(buffer), "remount of system failed: %s\n",strerror(errno)); - write_string(fd, buffer); + WriteStringFully(fd, buffer); } if (hasVendorPartition()) { if (remount("/vendor", &vendor_ro)) { snprintf(buffer, sizeof(buffer), "remount of vendor failed: %s\n",strerror(errno)); - write_string(fd, buffer); + WriteStringFully(fd, buffer); } } if (!system_ro && (!vendor_ro || !hasVendorPartition())) - write_string(fd, "remount succeeded\n"); + WriteStringFully(fd, "remount succeeded\n"); else { - write_string(fd, "remount failed\n"); + WriteStringFully(fd, "remount failed\n"); } adb_close(fd); diff --git a/adb/services.c b/adb/services.c index 2325c0f59..84f2137da 100644 --- a/adb/services.c +++ b/adb/services.c @@ -36,6 +36,7 @@ #define TRACE_TAG TRACE_SERVICES #include "adb.h" +#include "adb_io.h" #include "file_sync_service.h" #include "transport.h" @@ -65,20 +66,20 @@ void restart_root_service(int fd, void *cookie) if (getuid() == 0) { snprintf(buf, sizeof(buf), "adbd is already running as root\n"); - writex(fd, buf, strlen(buf)); + WriteFdExactly(fd, buf, strlen(buf)); adb_close(fd); } else { property_get("ro.debuggable", value, ""); if (strcmp(value, "1") != 0) { snprintf(buf, sizeof(buf), "adbd cannot run as root in production builds\n"); - writex(fd, buf, strlen(buf)); + WriteFdExactly(fd, buf, strlen(buf)); adb_close(fd); return; } property_set("service.adb.root", "1"); snprintf(buf, sizeof(buf), "restarting adbd as root\n"); - writex(fd, buf, strlen(buf)); + WriteFdExactly(fd, buf, strlen(buf)); adb_close(fd); } } @@ -89,12 +90,12 @@ void restart_unroot_service(int fd, void *cookie) if (getuid() != 0) { snprintf(buf, sizeof(buf), "adbd not running as root\n"); - writex(fd, buf, strlen(buf)); + WriteFdExactly(fd, buf, strlen(buf)); adb_close(fd); } else { property_set("service.adb.root", "0"); snprintf(buf, sizeof(buf), "restarting adbd as non root\n"); - writex(fd, buf, strlen(buf)); + WriteFdExactly(fd, buf, strlen(buf)); adb_close(fd); } } @@ -107,7 +108,7 @@ void restart_tcp_service(int fd, void *cookie) if (port <= 0) { snprintf(buf, sizeof(buf), "invalid port\n"); - writex(fd, buf, strlen(buf)); + WriteFdExactly(fd, buf, strlen(buf)); adb_close(fd); return; } @@ -115,7 +116,7 @@ void restart_tcp_service(int fd, void *cookie) snprintf(value, sizeof(value), "%d", port); property_set("service.adb.tcp.port", value); snprintf(buf, sizeof(buf), "restarting in TCP mode port: %d\n", port); - writex(fd, buf, strlen(buf)); + WriteFdExactly(fd, buf, strlen(buf)); adb_close(fd); } @@ -125,7 +126,7 @@ void restart_usb_service(int fd, void *cookie) property_set("service.adb.tcp.port", "0"); snprintf(buf, sizeof(buf), "restarting in USB mode\n"); - writex(fd, buf, strlen(buf)); + WriteFdExactly(fd, buf, strlen(buf)); adb_close(fd); } @@ -140,14 +141,14 @@ void reboot_service(int fd, void *arg) ret = snprintf(property_val, sizeof(property_val), "reboot,%s", (char *) arg); if (ret >= (int) sizeof(property_val)) { snprintf(buf, sizeof(buf), "reboot string too long. length=%d\n", ret); - writex(fd, buf, strlen(buf)); + WriteFdExactly(fd, buf, strlen(buf)); goto cleanup; } ret = property_set(ANDROID_RB_PROPERTY, property_val); if (ret < 0) { snprintf(buf, sizeof(buf), "reboot failed: %d\n", ret); - writex(fd, buf, strlen(buf)); + WriteFdExactly(fd, buf, strlen(buf)); goto cleanup; } // Don't return early. Give the reboot command time to take effect @@ -350,7 +351,7 @@ static void subproc_waiter_service(int fd, void *cookie) D("shell exited fd=%d of pid=%d err=%d\n", fd, pid, errno); if (SHELL_EXIT_NOTIFY_FD >=0) { int res; - res = writex(SHELL_EXIT_NOTIFY_FD, &fd, sizeof(fd)); + res = WriteFdExactly(SHELL_EXIT_NOTIFY_FD, &fd, sizeof(fd)) ? 0 : -1; D("notified shell exit via fd=%d for pid=%d res=%d errno=%d\n", SHELL_EXIT_NOTIFY_FD, pid, res, errno); } @@ -518,7 +519,7 @@ static void wait_for_state(int fd, void* cookie) atransport *t = acquire_one_transport(sinfo->state, sinfo->transport, sinfo->serial, &err); if(t != 0) { - writex(fd, "OKAY", 4); + WriteFdExactly(fd, "OKAY", 4); } else { sendfailmsg(fd, err); } @@ -644,7 +645,7 @@ static void connect_service(int fd, void* cookie) // Send response for emulator and device snprintf(resp, sizeof(resp), "%04x%s",(unsigned)strlen(buf), buf); - writex(fd, resp, strlen(resp)); + WriteFdExactly(fd, resp, strlen(resp)); adb_close(fd); } #endif diff --git a/adb/sockets.c b/adb/sockets.c index 7da6d5771..d34f8c6d4 100644 --- a/adb/sockets.c +++ b/adb/sockets.c @@ -25,6 +25,7 @@ #define TRACE_TAG TRACE_SOCKETS #include "adb.h" +#include "adb_io.h" #if !ADB_HOST #include "cutils/properties.h" #endif @@ -39,10 +40,16 @@ int sendfailmsg(int fd, const char *reason) char buf[9]; int len; len = strlen(reason); - if(len > 0xffff) len = 0xffff; + if (len > 0xffff) { + len = 0xffff; + } + snprintf(buf, sizeof buf, "FAIL%04x", len); - if(writex(fd, buf, 8)) return -1; - return writex(fd, reason, len); + if (!WriteFdExactly(fd, buf, 8)) { + return -1; + } + + return WriteFdExactly(fd, reason, len) ? 0 : -1; } static unsigned local_socket_next_id = 1; diff --git a/adb/sysdeps.h b/adb/sysdeps.h index ec847b5e4..c317e3ae9 100644 --- a/adb/sysdeps.h +++ b/adb/sysdeps.h @@ -24,6 +24,21 @@ # undef _WIN32 #endif +/* + * TEMP_FAILURE_RETRY is defined by some, but not all, versions of + * . (Alas, it is not as standard as we'd hoped!) So, if it's + * not already defined, then define it here. + */ +#ifndef TEMP_FAILURE_RETRY +/* Used to retry syscalls that can return EINTR. */ +#define TEMP_FAILURE_RETRY(exp) ({ \ + typeof (exp) _rc; \ + do { \ + _rc = (exp); \ + } while (_rc == -1 && errno == EINTR); \ + _rc; }) +#endif + #ifdef _WIN32 #include @@ -264,10 +279,6 @@ static __inline__ int adb_is_absolute_host_path( const char* path ) extern char* adb_strtok_r(char *str, const char *delim, char **saveptr); -#ifdef __cplusplus -} -#endif - #else /* !_WIN32 a.k.a. Unix */ #include "fdevent.h" @@ -291,21 +302,6 @@ extern char* adb_strtok_r(char *str, const char *delim, char **saveptr); extern "C" { #endif -/* - * TEMP_FAILURE_RETRY is defined by some, but not all, versions of - * . (Alas, it is not as standard as we'd hoped!) So, if it's - * not already defined, then define it here. - */ -#ifndef TEMP_FAILURE_RETRY -/* Used to retry syscalls that can return EINTR. */ -#define TEMP_FAILURE_RETRY(exp) ({ \ - typeof (exp) _rc; \ - do { \ - _rc = (exp); \ - } while (_rc == -1 && errno == EINTR); \ - _rc; }) -#endif - #define OS_PATH_SEPARATOR '/' #define OS_PATH_SEPARATOR_STR "/" #define ENV_PATH_SEPARATOR_STR ":" diff --git a/adb/transport.c b/adb/transport.c index 19515950e..e2c204ed2 100644 --- a/adb/transport.c +++ b/adb/transport.c @@ -44,7 +44,7 @@ ADB_MUTEX_DEFINE( transport_lock ); #if ADB_TRACE #define MAX_DUMP_HEX_LEN 16 -static void dump_hex( const unsigned char* ptr, size_t len ) +void dump_hex(const unsigned char* ptr, size_t len) { int nn, len2 = len; // Build a string instead of logging each character. @@ -1145,74 +1145,6 @@ void unregister_usb_transport(usb_handle *usb) #undef TRACE_TAG #define TRACE_TAG TRACE_RWX -int readx(int fd, void *ptr, size_t len) -{ - char *p = ptr; - int r; -#if ADB_TRACE - size_t len0 = len; -#endif - D("readx: fd=%d wanted=%zu\n", fd, len); - while(len > 0) { - r = adb_read(fd, p, len); - if(r > 0) { - len -= r; - p += r; - } else { - if (r < 0) { - D("readx: fd=%d error %d: %s\n", fd, errno, strerror(errno)); - if (errno == EINTR) - continue; - } else { - D("readx: fd=%d disconnected\n", fd); - } - return -1; - } - } - -#if ADB_TRACE - D("readx: fd=%d wanted=%zu got=%zu\n", fd, len0, len0 - len); - if (ADB_TRACING) { - dump_hex( ptr, len0 ); - } -#endif - return 0; -} - -int writex(int fd, const void *ptr, size_t len) -{ - char *p = (char*) ptr; - int r; - -#if ADB_TRACE - D("writex: fd=%d len=%d: ", fd, (int)len); - if (ADB_TRACING) { - dump_hex( ptr, len ); - } -#endif - while(len > 0) { - r = adb_write(fd, p, len); - if(r > 0) { - len -= r; - p += r; - } else { - if (r < 0) { - D("writex: fd=%d error %d: %s\n", fd, errno, strerror(errno)); - if (errno == EINTR) - continue; - if (errno == EAGAIN) { - adb_sleep_ms(1); // just yield some cpu time - continue; - } - } else { - D("writex: fd=%d disconnected\n", fd); - } - return -1; - } - } - return 0; -} - int check_header(apacket *p) { if(p->msg.magic != (p->msg.command ^ 0xffffffff)) { diff --git a/adb/transport.h b/adb/transport.h index 9802b919b..352bbe4ec 100644 --- a/adb/transport.h +++ b/adb/transport.h @@ -17,6 +17,7 @@ #ifndef __TRANSPORT_H #define __TRANSPORT_H +#include #include #include "adb.h" @@ -25,13 +26,9 @@ extern "C" { #endif -/* - * Convenience wrappers around read/write that will retry on - * EINTR and/or short read/write. Returns 0 on success, -1 - * on error or EOF. - */ -int readx(int fd, void *ptr, size_t len); -int writex(int fd, const void *ptr, size_t len); +#if ADB_TRACE +void dump_hex(const unsigned char* ptr, size_t len); +#endif /* * Obtain a transport from the available transports. diff --git a/adb/transport_local.c b/adb/transport_local.c index e07f2f709..440d4c50d 100644 --- a/adb/transport_local.c +++ b/adb/transport_local.c @@ -24,6 +24,7 @@ #define TRACE_TAG TRACE_TRANSPORT #include "adb.h" +#include "adb_io.h" #if !ADB_HOST #include "cutils/properties.h" #endif @@ -43,7 +44,7 @@ static atransport* local_transports[ ADB_LOCAL_TRANSPORT_MAX ]; static int remote_read(apacket *p, atransport *t) { - if(readx(t->sfd, &p->msg, sizeof(amessage))){ + if(!ReadFdExactly(t->sfd, &p->msg, sizeof(amessage))){ D("remote local: read terminated (message)\n"); return -1; } @@ -53,7 +54,7 @@ static int remote_read(apacket *p, atransport *t) return -1; } - if(readx(t->sfd, p->data, p->msg.data_length)){ + if(!ReadFdExactly(t->sfd, p->data, p->msg.data_length)){ D("remote local: terminated (data)\n"); return -1; } @@ -70,7 +71,7 @@ static int remote_write(apacket *p, atransport *t) { int length = p->msg.data_length; - if(writex(t->sfd, &p->msg, sizeof(amessage) + length)) { + if(!WriteFdExactly(t->sfd, &p->msg, sizeof(amessage) + length)) { D("remote local: write terminated\n"); return -1; }