LIBADB_SRC_FILES := \
adb.c \
adb_auth.c \
+ adb_io.cpp \
adb_listeners.c \
sockets.c \
transport.c \
include $(BUILD_HOST_STATIC_LIBRARY)
LIBADB_TEST_SRCS := \
+ adb_io_test.cpp \
transport_test.cpp \
include $(CLEAR_VARS)
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)
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
#include "sysdeps.h"
#include "adb.h"
#include "adb_auth.h"
+#include "adb_io.h"
#include "adb_listeners.h"
#include "transport.h"
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
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
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;
}
#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;
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;
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;
}
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;
}
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;
// 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;
return 0;
}
- if(readx(fd, buf, 4)) goto oops;
+ if(!ReadFdExactly(fd, buf, 4)) goto oops;
buf[4] = 0;
n = strtoul(buf, 0, 16);
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;
--- /dev/null
+/*
+ * 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 <unistd.h>
+
+#include "adb_trace.h"
+#include "transport.h"
+
+bool ReadFdExactly(int fd, void* buf, size_t len) {
+ char* p = reinterpret_cast<char*>(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<const unsigned char*>(buf), len0);
+ }
+#endif
+
+ return true;
+}
+
+bool WriteFdExactly(int fd, const void* buf, size_t len) {
+ const char* p = reinterpret_cast<const char*>(buf);
+ int r;
+
+#if ADB_TRACE
+ D("writex: fd=%d len=%d: ", fd, (int)len);
+ if (ADB_TRACING) {
+ dump_hex(reinterpret_cast<const unsigned char*>(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));
+}
--- /dev/null
+/*
+ * 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 <stdbool.h>
+#include <sys/types.h>
+
+#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 */
--- /dev/null
+/*
+ * 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 <gtest/gtest.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <string>
+
+#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());
+}
#if !ADB_HOST
#include <android/log.h>
+#else
+#include <stdio.h>
#endif
#ifdef __cplusplus
#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, ...);
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;
printf("\n");
}
- if(readx(fd, buf, 4)){
+ if(!ReadFdExactly(fd, buf, 4)){
fprintf(stderr,"* error reading response *\n");
adb_close(fd);
return -1;
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;
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;
#include <stdarg.h>
#include <stddef.h>
+#include "adb_io.h"
#include "adb_trace.h"
#include "fdevent.h"
-#include "transport.h"
#include "sysdeps.h"
#define TRACE_TAG TRACE_FDEVENT
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)) {
#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;
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);
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),
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;
}
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;
}
{
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)
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;
}
}
sbuf->size = htoll(ret);
- if(writex(fd, sbuf, sizeof(unsigned) * 2 + ret)){
+ if(!WriteFdExactly(fd, sbuf, sizeof(unsigned) * 2 + ret)){
err = -1;
break;
}
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;
}
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;
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;
}
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;
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;
}
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;
}
for(;;) {
- if(readx(fd, &msg.data, sizeof(msg.data))) {
+ if(!ReadFdExactly(fd, &msg.data, sizeof(msg.data))) {
return -1;
}
id = msg.data.id;
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;
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;
#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) {
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)
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;
}
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)
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;
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) {
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);
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;
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) {
fail_message(s, "oversize data message");
return -1;
}
- if(readx(s, buffer, len))
+ if(!ReadFdExactly(s, buffer, len))
return -1;
ret = symlink(buffer, path);
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");
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;
}
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;
}
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;
}
fail_message(fd, "invalid namelen");
break;
}
- if(readx(fd, name, namelen)) {
+ if(!ReadFdExactly(fd, name, namelen)) {
fail_message(fd, "filename read failure");
break;
}
#include "sysdeps.h"
#include "adb.h"
+#include "adb_io.h"
#include "fdevent.h"
-#include "transport.h"
/* TODO:
** - sync with vsync to avoid tearing
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 */
}
/* 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:
#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;
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];
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);
#define TRACE_TAG TRACE_SERVICES
#include "adb.h"
+#include "adb_io.h"
#include "file_sync_service.h"
#include "transport.h"
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);
}
}
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);
}
}
if (port <= 0) {
snprintf(buf, sizeof(buf), "invalid port\n");
- writex(fd, buf, strlen(buf));
+ WriteFdExactly(fd, buf, strlen(buf));
adb_close(fd);
return;
}
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);
}
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);
}
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
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);
}
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);
}
// 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
#define TRACE_TAG TRACE_SOCKETS
#include "adb.h"
+#include "adb_io.h"
#if !ADB_HOST
#include "cutils/properties.h"
#endif
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;
# undef _WIN32
#endif
+/*
+ * TEMP_FAILURE_RETRY is defined by some, but not all, versions of
+ * <unistd.h>. (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 <ctype.h>
extern char* adb_strtok_r(char *str, const char *delim, char **saveptr);
-#ifdef __cplusplus
-}
-#endif
-
#else /* !_WIN32 a.k.a. Unix */
#include "fdevent.h"
extern "C" {
#endif
-/*
- * TEMP_FAILURE_RETRY is defined by some, but not all, versions of
- * <unistd.h>. (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 ":"
#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.
#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)) {
#ifndef __TRANSPORT_H
#define __TRANSPORT_H
+#include <stdbool.h>
#include <sys/types.h>
#include "adb.h"
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.
#define TRACE_TAG TRACE_TRANSPORT
#include "adb.h"
+#include "adb_io.h"
#if !ADB_HOST
#include "cutils/properties.h"
#endif
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;
}
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;
}
{
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;
}