Merge "debuggerd: report crashes even when out of file descriptors."
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 89a20f0..29d6e65 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -94,6 +94,18 @@
     abort();
 }
 
+uint32_t calculate_apacket_checksum(const apacket* p) {
+    const unsigned char* x = reinterpret_cast<const unsigned char*>(p->data);
+    uint32_t sum = 0;
+    size_t count = p->msg.data_length;
+
+    while (count-- > 0) {
+        sum += *x++;
+    }
+
+    return sum;
+}
+
 apacket* get_apacket(void)
 {
     apacket* p = reinterpret_cast<apacket*>(malloc(sizeof(apacket)));
diff --git a/adb/adb.h b/adb/adb.h
index 0b9fe5b..8064c17 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -18,6 +18,7 @@
 #define __ADB_H
 
 #include <limits.h>
+#include <stdint.h>
 #include <sys/types.h>
 
 #include <string>
@@ -56,25 +57,27 @@
 struct usb_handle;
 
 struct amessage {
-    unsigned command;       /* command identifier constant      */
-    unsigned arg0;          /* first argument                   */
-    unsigned arg1;          /* second argument                  */
-    unsigned data_length;   /* length of payload (0 is allowed) */
-    unsigned data_check;    /* checksum of data payload         */
-    unsigned magic;         /* command ^ 0xffffffff             */
+    uint32_t command;     /* command identifier constant      */
+    uint32_t arg0;        /* first argument                   */
+    uint32_t arg1;        /* second argument                  */
+    uint32_t data_length; /* length of payload (0 is allowed) */
+    uint32_t data_check;  /* checksum of data payload         */
+    uint32_t magic;       /* command ^ 0xffffffff             */
 };
 
 struct apacket
 {
     apacket *next;
 
-    unsigned len;
-    unsigned char *ptr;
+    size_t len;
+    char* ptr;
 
     amessage msg;
-    unsigned char data[MAX_PAYLOAD];
+    char data[MAX_PAYLOAD];
 };
 
+uint32_t calculate_apacket_checksum(const apacket* packet);
+
 /* the adisconnect structure is used to record a callback that
 ** will be called whenever a transport is disconnected (e.g. by the user)
 ** this should be used to cleanup objects that depend on the
diff --git a/adb/adb_auth.h b/adb/adb_auth.h
index 4db83a4..a6f224f 100644
--- a/adb/adb_auth.h
+++ b/adb/adb_auth.h
@@ -36,11 +36,10 @@
 void adb_auth_init();
 
 int adb_auth_keygen(const char* filename);
-int adb_auth_sign(RSA* key, const unsigned char* token, size_t token_size, unsigned char* sig);
 std::string adb_auth_get_userkey();
 std::deque<std::shared_ptr<RSA>> adb_auth_get_private_keys();
 
-void send_auth_response(uint8_t *token, size_t token_size, atransport *t);
+void send_auth_response(const char* token, size_t token_size, atransport* t);
 
 #else // !ADB_HOST
 
@@ -50,8 +49,8 @@
 void adbd_auth_verified(atransport *t);
 
 void adbd_cloexec_auth_socket();
-bool adbd_auth_verify(uint8_t* token, size_t token_size, uint8_t* sig, int sig_len);
-void adbd_auth_confirm_key(unsigned char *data, size_t len, atransport *t);
+bool adbd_auth_verify(const char* token, size_t token_size, const char* sig, int sig_len);
+void adbd_auth_confirm_key(const char* data, size_t len, atransport* t);
 
 void send_auth_request(atransport *t);
 
diff --git a/adb/adb_auth_host.cpp b/adb/adb_auth_host.cpp
index b5b9b97..ff2d76d 100644
--- a/adb/adb_auth_host.cpp
+++ b/adb/adb_auth_host.cpp
@@ -298,14 +298,15 @@
     return result;
 }
 
-int adb_auth_sign(RSA* key, const unsigned char* token, size_t token_size, unsigned char* sig) {
+static int adb_auth_sign(RSA* key, const char* token, size_t token_size, char* sig) {
     if (token_size != TOKEN_SIZE) {
         D("Unexpected token size %zd", token_size);
         return 0;
     }
 
     unsigned int len;
-    if (!RSA_sign(NID_sha1, token, token_size, sig, &len, key)) {
+    if (!RSA_sign(NID_sha1, reinterpret_cast<const uint8_t*>(token), token_size,
+                  reinterpret_cast<uint8_t*>(sig), &len, key)) {
         return 0;
     }
 
@@ -448,7 +449,7 @@
     send_packet(p, t);
 }
 
-void send_auth_response(uint8_t* token, size_t token_size, atransport* t) {
+void send_auth_response(const char* token, size_t token_size, atransport* t) {
     std::shared_ptr<RSA> key = t->NextKey();
     if (key == nullptr) {
         // No more private keys to try, send the public key.
diff --git a/adb/adbd_auth.cpp b/adb/adbd_auth.cpp
index fa76c8d..b5f87be 100644
--- a/adb/adbd_auth.cpp
+++ b/adb/adbd_auth.cpp
@@ -46,7 +46,7 @@
 
 bool auth_required = true;
 
-bool adbd_auth_verify(uint8_t* token, size_t token_size, uint8_t* sig, int sig_len) {
+bool adbd_auth_verify(const char* token, size_t token_size, const char* sig, int sig_len) {
     static constexpr const char* key_paths[] = { "/adb_keys", "/data/misc/adb/adb_keys", nullptr };
 
     for (const auto& path : key_paths) {
@@ -78,7 +78,9 @@
                     continue;
                 }
 
-                bool verified = (RSA_verify(NID_sha1, token, token_size, sig, sig_len, key) == 1);
+                bool verified =
+                    (RSA_verify(NID_sha1, reinterpret_cast<const uint8_t*>(token), token_size,
+                                reinterpret_cast<const uint8_t*>(sig), sig_len, key) == 1);
                 RSA_free(key);
                 if (verified) return true;
             }
@@ -121,7 +123,7 @@
     }
 }
 
-void adbd_auth_confirm_key(unsigned char* key, size_t len, atransport* t) {
+void adbd_auth_confirm_key(const char* key, size_t len, atransport* t) {
     if (!usb_transport) {
         usb_transport = t;
         t->AddDisconnect(&usb_disconnect);
diff --git a/adb/sockets.cpp b/adb/sockets.cpp
index b809c4f..fff6049 100644
--- a/adb/sockets.cpp
+++ b/adb/sockets.cpp
@@ -122,7 +122,7 @@
 }
 
 static int local_socket_enqueue(asocket* s, apacket* p) {
-    D("LS(%d): enqueue %d", s->id, p->len);
+    D("LS(%d): enqueue %zu", s->id, p->len);
 
     p->ptr = p->data;
 
@@ -195,7 +195,7 @@
 
     /* dispose of any unwritten data */
     for (p = s->pkt_first; p; p = n) {
-        D("LS(%d): discarding %d bytes", s->id, p->len);
+        D("LS(%d): discarding %zu bytes", s->id, p->len);
         n = p->next;
         put_apacket(p);
     }
@@ -305,7 +305,7 @@
 
     if (ev & FDE_READ) {
         apacket* p = get_apacket();
-        unsigned char* x = p->data;
+        char* x = p->data;
         const size_t max_payload = s->get_max_payload();
         size_t avail = max_payload;
         int r = 0;
@@ -553,7 +553,7 @@
     s->close(s);
 }
 
-static unsigned unhex(unsigned char* s, int len) {
+static unsigned unhex(char* s, int len) {
     unsigned n = 0, c;
 
     while (len-- > 0) {
@@ -665,7 +665,7 @@
     TransportType type = kTransportAny;
 #endif
 
-    D("SS(%d): enqueue %d", s->id, p->len);
+    D("SS(%d): enqueue %zu", s->id, p->len);
 
     if (s->pkt_first == 0) {
         s->pkt_first = p;
@@ -698,7 +698,7 @@
     D("SS(%d): len is %d", s->id, len);
     /* can't do anything until we have the full header */
     if ((len + 4) > p->len) {
-        D("SS(%d): waiting for %d more bytes", s->id, len + 4 - p->len);
+        D("SS(%d): waiting for %zu more bytes", s->id, len + 4 - p->len);
         return 0;
     }
 
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 9880902..7b4bb1c 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -150,32 +150,17 @@
     }
 }
 
-void send_packet(apacket *p, atransport *t)
-{
-    unsigned char *x;
-    unsigned sum;
-    unsigned count;
-
+void send_packet(apacket* p, atransport* t) {
     p->msg.magic = p->msg.command ^ 0xffffffff;
-
-    count = p->msg.data_length;
-    x = (unsigned char *) p->data;
-    sum = 0;
-    while(count-- > 0){
-        sum += *x++;
-    }
-    p->msg.data_check = sum;
+    p->msg.data_check = calculate_apacket_checksum(p);
 
     print_packet("send", p);
 
     if (t == NULL) {
-        D("Transport is null");
-        // Zap errno because print_packet() and other stuff have errno effect.
-        errno = 0;
-        fatal_errno("Transport is null");
+        fatal("Transport is null");
     }
 
-    if(write_packet(t->transport_socket, t->serial, &p)){
+    if (write_packet(t->transport_socket, t->serial, &p)) {
         fatal_errno("cannot enqueue packet on transport socket");
     }
 }
@@ -1052,23 +1037,11 @@
     return 0;
 }
 
-int check_data(apacket *p)
-{
-    unsigned count, sum;
-    unsigned char *x;
-
-    count = p->msg.data_length;
-    x = p->data;
-    sum = 0;
-    while(count-- > 0) {
-        sum += *x++;
-    }
-
-    if(sum != p->msg.data_check) {
+int check_data(apacket* p) {
+    if (calculate_apacket_checksum(p) != p->msg.data_check) {
         return -1;
-    } else {
-        return 0;
     }
+    return 0;
 }
 
 #if ADB_HOST
diff --git a/adb/transport.h b/adb/transport.h
index aaa8be4..621516c 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -112,7 +112,7 @@
     std::shared_ptr<RSA> NextKey();
 #endif
 
-    unsigned char token[TOKEN_SIZE] = {};
+    char token[TOKEN_SIZE] = {};
     size_t failed_auth_attempts = 0;
 
     const std::string connection_state_name() const;
diff --git a/base/include/android-base/parseint.h b/base/include/android-base/parseint.h
index ed75e2d..7415409 100644
--- a/base/include/android-base/parseint.h
+++ b/base/include/android-base/parseint.h
@@ -31,7 +31,7 @@
 template <typename T>
 bool ParseUint(const char* s, T* out,
                T max = std::numeric_limits<T>::max()) {
-  int base = (s[0] == '0' && s[1] == 'x') ? 16 : 10;
+  int base = (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) ? 16 : 10;
   errno = 0;
   char* end;
   unsigned long long int result = strtoull(s, &end, base);
@@ -53,7 +53,7 @@
 bool ParseInt(const char* s, T* out,
               T min = std::numeric_limits<T>::min(),
               T max = std::numeric_limits<T>::max()) {
-  int base = (s[0] == '0' && s[1] == 'x') ? 16 : 10;
+  int base = (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) ? 16 : 10;
   errno = 0;
   char* end;
   long long int result = strtoll(s, &end, base);
diff --git a/cpio/mkbootfs.c b/cpio/mkbootfs.c
index 0e35323..b89c395 100644
--- a/cpio/mkbootfs.c
+++ b/cpio/mkbootfs.c
@@ -51,6 +51,8 @@
 #define CANNED_LINE_LENGTH  (1024)
 #endif
 
+#define TRAILER "TRAILER!!!"
+
 static int verbose = 0;
 static int total_size = 0;
 
@@ -80,8 +82,8 @@
     } else {
         // Use the compiled-in fs_config() function.
         unsigned st_mode = s->st_mode;
-        fs_config(path, S_ISDIR(s->st_mode), target_out_path,
-                       &s->st_uid, &s->st_gid, &st_mode, &capabilities);
+        int is_dir = S_ISDIR(s->st_mode) || strcmp(path, TRAILER) == 0;
+        fs_config(path, is_dir, target_out_path, &s->st_uid, &s->st_gid, &st_mode, &capabilities);
         s->st_mode = (typeof(s->st_mode)) st_mode;
     }
 }
@@ -140,7 +142,7 @@
 {
     struct stat s;
     memset(&s, 0, sizeof(s));
-    _eject(&s, "TRAILER!!!", 10, 0, 0);
+    _eject(&s, TRAILER, 10, 0, 0);
 
     while(total_size & 0xff) {
         total_size++;
diff --git a/fastboot/Android.mk b/fastboot/Android.mk
index 7112d1d..d69a81f 100644
--- a/fastboot/Android.mk
+++ b/fastboot/Android.mk
@@ -21,7 +21,6 @@
 LOCAL_C_INCLUDES := \
   $(LOCAL_PATH)/../adb \
   $(LOCAL_PATH)/../mkbootimg \
-  $(LOCAL_PATH)/../../extras/ext4_utils \
   $(LOCAL_PATH)/../../extras/f2fs_utils \
 
 LOCAL_SRC_FILES := \
diff --git a/fastboot/fs.cpp b/fastboot/fs.cpp
index 8539e23..9b73165 100644
--- a/fastboot/fs.cpp
+++ b/fastboot/fs.cpp
@@ -1,7 +1,6 @@
 #include "fs.h"
 
 #include "fastboot.h"
-#include "make_ext4fs.h"
 #include "make_f2fs.h"
 
 #include <errno.h>
@@ -12,6 +11,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <ext4_utils/make_ext4fs.h>
 #include <sparse/sparse.h>
 
 static int generate_ext4_image(int fd, long long partSize, const std::string& initial_dir)
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index b11ce75..2ed6b91 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -30,20 +30,18 @@
 #include <time.h>
 #include <unistd.h>
 
-#include <ext4.h>
-#include <ext4_crypt_init_extensions.h>
-#include <ext4_sb.h>
-
 #include <cutils/android_reboot.h>
 #include <cutils/partition_utils.h>
 #include <cutils/properties.h>
+#include <ext4_utils/ext4.h>
+#include <ext4_utils/ext4_crypt_init_extensions.h>
+#include <ext4_utils/ext4_sb.h>
+#include <ext4_utils/ext4_utils.h>
+#include <ext4_utils/wipe.h>
 #include <linux/loop.h>
 #include <logwrap/logwrap.h>
 #include <private/android_filesystem_config.h>
 
-#include "ext4_utils.h"
-#include "wipe.h"
-
 #include "fs_mgr_priv.h"
 #include "fs_mgr_priv_verity.h"
 
diff --git a/fs_mgr/fs_mgr_format.c b/fs_mgr/fs_mgr_format.c
index 7ee5832..7c3b1ed 100644
--- a/fs_mgr/fs_mgr_format.c
+++ b/fs_mgr/fs_mgr_format.c
@@ -24,13 +24,13 @@
 #include <cutils/partition_utils.h>
 #include <sys/mount.h>
 
+#include <ext4_utils/ext4_utils.h>
+#include <ext4_utils/ext4.h>
+#include <ext4_utils/make_ext4fs.h>
 #include <selinux/selinux.h>
 #include <selinux/label.h>
 #include <selinux/android.h>
 
-#include "ext4_utils.h"
-#include "ext4.h"
-#include "make_ext4fs.h"
 #include "fs_mgr_priv.h"
 #include "cryptfs.h"
 
diff --git a/include/cutils/native_handle.h b/include/cutils/native_handle.h
index 31695cb..813dadc 100644
--- a/include/cutils/native_handle.h
+++ b/include/cutils/native_handle.h
@@ -57,6 +57,15 @@
 native_handle_t* native_handle_create(int numFds, int numInts);
 
 /*
+ * native_handle_clone
+ *
+ * creates a native_handle_t and initializes it from another native_handle_t.
+ * Must be destroyed with native_handle_delete().
+ *
+ */
+native_handle_t* native_handle_clone(const native_handle_t* handle);
+
+/*
  * native_handle_delete
  * 
  * frees a native_handle_t allocated with native_handle_create().
diff --git a/init/Android.mk b/init/Android.mk
index 4a8df32..704304e 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -74,7 +74,6 @@
 
 LOCAL_MODULE:= init
 LOCAL_C_INCLUDES += \
-    system/extras/ext4_utils \
     system/core/mkbootimg
 
 LOCAL_FORCE_STATIC_EXECUTABLE := true
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 200b723..f4ba018 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -37,8 +37,6 @@
 #include <unistd.h>
 #include <linux/loop.h>
 #include <linux/module.h>
-#include <ext4_crypt.h>
-#include <ext4_crypt_init_extensions.h>
 
 #include <selinux/selinux.h>
 #include <selinux/label.h>
@@ -51,6 +49,8 @@
 #include <bootloader_message_writer.h>
 #include <cutils/partition_utils.h>
 #include <cutils/android_reboot.h>
+#include <ext4_utils/ext4_crypt.h>
+#include <ext4_utils/ext4_crypt_init_extensions.h>
 #include <logwrap/logwrap.h>
 
 #include "action.h"
diff --git a/init/init_parser.cpp b/init/init_parser.cpp
index 9ec26af..d017390 100644
--- a/init/init_parser.cpp
+++ b/init/init_parser.cpp
@@ -122,14 +122,20 @@
         return false;
     }
     dirent* current_file;
+    std::vector<std::string> files;
     while ((current_file = readdir(config_dir.get()))) {
-        std::string current_path =
-            android::base::StringPrintf("%s/%s", path.c_str(), current_file->d_name);
         // Ignore directories and only process regular files.
         if (current_file->d_type == DT_REG) {
-            if (!ParseConfigFile(current_path)) {
-                LOG(ERROR) << "could not import file '" << current_path << "'";
-            }
+            std::string current_path =
+                android::base::StringPrintf("%s/%s", path.c_str(), current_file->d_name);
+            files.emplace_back(current_path);
+        }
+    }
+    // Sort first so we load files in a consistent order (bug 31996208)
+    std::sort(files.begin(), files.end());
+    for (const auto& file : files) {
+        if (!ParseConfigFile(file)) {
+            LOG(ERROR) << "could not import file '" << file << "'";
         }
     }
     return true;
diff --git a/libcutils/native_handle.c b/libcutils/native_handle.c
index 7f3479d..cae146d 100644
--- a/libcutils/native_handle.c
+++ b/libcutils/native_handle.c
@@ -44,6 +44,27 @@
     return h;
 }
 
+native_handle_t* native_handle_clone(const native_handle_t* handle)
+{
+    native_handle_t* clone = native_handle_create(handle->numFds, handle->numInts);
+    int i;
+
+    for (i = 0; i < handle->numFds; i++) {
+        clone->data[i] = dup(handle->data[i]);
+        if (clone->data[i] < 0) {
+            clone->numFds = i;
+            native_handle_close(clone);
+            native_handle_delete(clone);
+            return NULL;
+        }
+    }
+
+    memcpy(&clone->data[handle->numFds], &handle->data[handle->numFds],
+            sizeof(int) * handle->numInts);
+
+    return clone;
+}
+
 int native_handle_delete(native_handle_t* h)
 {
     if (h) {
diff --git a/libsparse/output_file.c b/libsparse/output_file.c
index 6578d99..2115998 100644
--- a/libsparse/output_file.c
+++ b/libsparse/output_file.c
@@ -63,7 +63,7 @@
 	int (*open)(struct output_file *, int fd);
 	int (*skip)(struct output_file *, int64_t);
 	int (*pad)(struct output_file *, int64_t);
-	int (*write)(struct output_file *, void *, int);
+	int (*write)(struct output_file *, void *, size_t);
 	void (*close)(struct output_file *);
 };
 
@@ -149,18 +149,23 @@
 	return 0;
 }
 
-static int file_write(struct output_file *out, void *data, int len)
+static int file_write(struct output_file *out, void *data, size_t len)
 {
-	int ret;
+	ssize_t ret;
 	struct output_file_normal *outn = to_output_file_normal(out);
 
-	ret = write(outn->fd, data, len);
-	if (ret < 0) {
-		error_errno("write");
-		return -1;
-	} else if (ret < len) {
-		error("incomplete write");
-		return -1;
+	while (len > 0) {
+		ret = write(outn->fd, data, len);
+		if (ret < 0) {
+			if (errno == EINTR) {
+				continue;
+			}
+			error_errno("write");
+			return -1;
+		}
+
+		data = (char *)data + ret;
+		len -= ret;
 	}
 
 	return 0;
@@ -232,18 +237,20 @@
 	return 0;
 }
 
-static int gz_file_write(struct output_file *out, void *data, int len)
+static int gz_file_write(struct output_file *out, void *data, size_t len)
 {
 	int ret;
 	struct output_file_gz *outgz = to_output_file_gz(out);
 
-	ret = gzwrite(outgz->gz_fd, data, len);
-	if (ret < 0) {
-		error_errno("gzwrite");
-		return -1;
-	} else if (ret < len) {
-		error("incomplete gzwrite");
-		return -1;
+	while (len > 0) {
+		ret = gzwrite(outgz->gz_fd, data,
+			      min(len, (unsigned int)INT_MAX));
+		if (ret == 0) {
+			error("gzwrite %s", gzerror(outgz->gz_fd, NULL));
+			return -1;
+		}
+		len -= ret;
+		data = (char *)data + ret;
 	}
 
 	return 0;
@@ -293,7 +300,7 @@
 	return -1;
 }
 
-static int callback_file_write(struct output_file *out, void *data, int len)
+static int callback_file_write(struct output_file *out, void *data, size_t len)
 {
 	struct output_file_callback *outc = to_output_file_callback(out);
 
@@ -698,14 +705,16 @@
 	int ret;
 	int64_t aligned_offset;
 	int aligned_diff;
-	int buffer_size;
+	uint64_t buffer_size;
 	char *ptr;
 
 	aligned_offset = offset & ~(4096 - 1);
 	aligned_diff = offset - aligned_offset;
-	buffer_size = len + aligned_diff;
+	buffer_size = (uint64_t)len + (uint64_t)aligned_diff;
 
 #ifndef _WIN32
+	if (buffer_size > SIZE_MAX)
+		return -E2BIG;
 	char *data = mmap64(NULL, buffer_size, PROT_READ, MAP_SHARED, fd,
 			aligned_offset);
 	if (data == MAP_FAILED) {
diff --git a/sdcard/fuse.cpp b/sdcard/fuse.cpp
index f549606..d4c51fd 100644
--- a/sdcard/fuse.cpp
+++ b/sdcard/fuse.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
 #define LOG_TAG "sdcard"
 
 #include "fuse.h"
@@ -223,7 +227,8 @@
 }
 
 static int touch(char* path, mode_t mode) {
-    int fd = open(path, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW, mode);
+    int fd = TEMP_FAILURE_RETRY(open(path, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW | O_CLOEXEC,
+                                     mode));
     if (fd == -1) {
         if (errno == EEXIST) {
             return 0;
@@ -469,27 +474,34 @@
     hdr.len = sizeof(hdr);
     hdr.error = err;
     hdr.unique = unique;
-    write(fuse->fd, &hdr, sizeof(hdr));
+    ssize_t ret = TEMP_FAILURE_RETRY(write(fuse->fd, &hdr, sizeof(hdr)));
+    if (ret == -1) {
+        PLOG(ERROR) << "*** STATUS FAILED ***";
+    } else if (static_cast<size_t>(ret) != sizeof(hdr)) {
+        LOG(ERROR) << "*** STATUS FAILED: written " << ret << " expected "
+                   << sizeof(hdr) << " ***";
+    }
 }
 
 static void fuse_reply(struct fuse *fuse, __u64 unique, void *data, int len)
 {
     struct fuse_out_header hdr;
-    struct iovec vec[2];
-    int res;
-
     hdr.len = len + sizeof(hdr);
     hdr.error = 0;
     hdr.unique = unique;
 
+    struct iovec vec[2];
     vec[0].iov_base = &hdr;
     vec[0].iov_len = sizeof(hdr);
     vec[1].iov_base = data;
     vec[1].iov_len = len;
 
-    res = writev(fuse->fd, vec, 2);
-    if (res < 0) {
+    ssize_t ret = TEMP_FAILURE_RETRY(writev(fuse->fd, vec, 2));
+    if (ret == -1) {
         PLOG(ERROR) << "*** REPLY FAILED ***";
+    } else if (static_cast<size_t>(ret) != sizeof(hdr) + len) {
+        LOG(ERROR) << "*** REPLY FAILED: written " << ret << " expected "
+                   << sizeof(hdr) + len << " ***";
     }
 }
 
@@ -501,7 +513,7 @@
     struct fuse_entry_out out;
     struct stat s;
 
-    if (lstat(path, &s) < 0) {
+    if (lstat(path, &s) == -1) {
         return -errno;
     }
 
@@ -528,7 +540,7 @@
     struct fuse_attr_out out;
     struct stat s;
 
-    if (lstat(path, &s) < 0) {
+    if (lstat(path, &s) == -1) {
         return -errno;
     }
     memset(&out, 0, sizeof(out));
@@ -542,10 +554,7 @@
         const __u64 child, const char* name) {
     struct fuse_out_header hdr;
     struct fuse_notify_delete_out data;
-    struct iovec vec[3];
     size_t namelen = strlen(name);
-    int res;
-
     hdr.len = sizeof(hdr) + sizeof(data) + namelen + 1;
     hdr.error = FUSE_NOTIFY_DELETE;
     hdr.unique = 0;
@@ -555,6 +564,7 @@
     data.namelen = namelen;
     data.padding = 0;
 
+    struct iovec vec[3];
     vec[0].iov_base = &hdr;
     vec[0].iov_len = sizeof(hdr);
     vec[1].iov_base = &data;
@@ -562,10 +572,15 @@
     vec[2].iov_base = (void*) name;
     vec[2].iov_len = namelen + 1;
 
-    res = writev(fuse->fd, vec, 3);
+    ssize_t ret = TEMP_FAILURE_RETRY(writev(fuse->fd, vec, 3));
     /* Ignore ENOENT, since other views may not have seen the entry */
-    if (res < 0 && errno != ENOENT) {
-        PLOG(ERROR) << "*** NOTIFY FAILED ***";
+    if (ret == -1) {
+        if (errno != ENOENT) {
+            PLOG(ERROR) << "*** NOTIFY FAILED ***";
+        }
+    } else if (static_cast<size_t>(ret) != sizeof(hdr) + sizeof(data) + namelen + 1) {
+        LOG(ERROR) << "*** NOTIFY FAILED: written " << ret << " expected "
+                   << sizeof(hdr) + sizeof(data) + namelen + 1 << " ***";
     }
 }
 
@@ -665,7 +680,7 @@
     /* XXX: incomplete implementation on purpose.
      * chmod/chown should NEVER be implemented.*/
 
-    if ((req->valid & FATTR_SIZE) && truncate64(path, req->size) < 0) {
+    if ((req->valid & FATTR_SIZE) && TEMP_FAILURE_RETRY(truncate64(path, req->size)) == -1) {
         return -errno;
     }
 
@@ -727,7 +742,7 @@
         return -EACCES;
     }
     __u32 mode = (req->mode & (~0777)) | 0664;
-    if (mknod(child_path, mode, req->rdev) < 0) {
+    if (mknod(child_path, mode, req->rdev) == -1) {
         return -errno;
     }
     return fuse_reply_entry(fuse, hdr->unique, parent_node, name, actual_name, child_path);
@@ -757,7 +772,7 @@
         return -EACCES;
     }
     __u32 mode = (req->mode & (~0777)) | 0775;
-    if (mkdir(child_path, mode) < 0) {
+    if (mkdir(child_path, mode) == -1) {
         return -errno;
     }
 
@@ -804,7 +819,7 @@
     if (!check_caller_access_to_name(fuse, hdr, parent_node, name, W_OK)) {
         return -EACCES;
     }
-    if (unlink(child_path) < 0) {
+    if (unlink(child_path) == -1) {
         return -errno;
     }
     pthread_mutex_lock(&fuse->global->lock);
@@ -854,7 +869,7 @@
     if (!check_caller_access_to_name(fuse, hdr, parent_node, name, W_OK)) {
         return -EACCES;
     }
-    if (rmdir(child_path) < 0) {
+    if (rmdir(child_path) == -1) {
         return -errno;
     }
     pthread_mutex_lock(&fuse->global->lock);
@@ -942,7 +957,7 @@
 
     DLOG(INFO) << "[" << handler->token << "] RENAME " << old_child_path << "->" << new_child_path;
     res = rename(old_child_path, new_child_path);
-    if (res < 0) {
+    if (res == -1) {
         res = -errno;
         goto io_error;
     }
@@ -1004,8 +1019,8 @@
         return -ENOMEM;
     }
     DLOG(INFO) << "[" << handler->token << "] OPEN " << path;
-    h->fd = open(path, req->flags);
-    if (h->fd < 0) {
+    h->fd = TEMP_FAILURE_RETRY(open(path, req->flags));
+    if (h->fd == -1) {
         free(h);
         return -errno;
     }
@@ -1035,8 +1050,8 @@
     if (size > MAX_READ) {
         return -EINVAL;
     }
-    res = pread64(h->fd, read_buffer, size, offset);
-    if (res < 0) {
+    res = TEMP_FAILURE_RETRY(pread64(h->fd, read_buffer, size, offset));
+    if (res == -1) {
         return -errno;
     }
     fuse_reply(fuse, unique, read_buffer, res);
@@ -1059,8 +1074,8 @@
 
     DLOG(INFO) << "[" << handler->token << "] WRITE " << std::hex << h << std::dec
                << "(" << h->fd << ") " << req->size << "@" << req->offset;
-    res = pwrite64(h->fd, buffer, req->size, req->offset);
-    if (res < 0) {
+    res = TEMP_FAILURE_RETRY(pwrite64(h->fd, buffer, req->size, req->offset));
+    if (res == -1) {
         return -errno;
     }
     out.size = res;
@@ -1084,7 +1099,7 @@
     if (res < 0) {
         return -ENOENT;
     }
-    if (statfs(fuse->global->root.name, &stat) < 0) {
+    if (TEMP_FAILURE_RETRY(statfs(fuse->global->root.name, &stat)) == -1) {
         return -errno;
     }
     memset(&out, 0, sizeof(out));
@@ -1293,7 +1308,6 @@
     return NO_STATUS;
 }
 
-
 static int handle_fuse_request(struct fuse *fuse, struct fuse_handler* handler,
         const struct fuse_in_header *hdr, const void *data, size_t data_len)
 {
@@ -1427,7 +1441,7 @@
     for (;;) {
         ssize_t len = TEMP_FAILURE_RETRY(read(fuse->fd,
                 handler->request_buffer, sizeof(handler->request_buffer)));
-        if (len < 0) {
+        if (len == -1) {
             if (errno == ENODEV) {
                 LOG(ERROR) << "[" << handler->token << "] someone stole our marbles!";
                 exit(2);
@@ -1436,14 +1450,14 @@
             continue;
         }
 
-        if ((size_t)len < sizeof(struct fuse_in_header)) {
+        if (static_cast<size_t>(len) < sizeof(struct fuse_in_header)) {
             LOG(ERROR) << "[" << handler->token << "] request too short: len=" << len;
             continue;
         }
 
         const struct fuse_in_header* hdr =
             reinterpret_cast<const struct fuse_in_header*>(handler->request_buffer);
-        if (hdr->len != (size_t)len) {
+        if (hdr->len != static_cast<size_t>(len)) {
             LOG(ERROR) << "[" << handler->token << "] malformed header: len=" << len
                        << ", hdr->len=" << hdr->len;
             continue;
diff --git a/sdcard/sdcard.cpp b/sdcard/sdcard.cpp
index 70bbf26..bc502a0 100644
--- a/sdcard/sdcard.cpp
+++ b/sdcard/sdcard.cpp
@@ -111,7 +111,7 @@
     char event_buf[512];
 
     int nfd = inotify_init();
-    if (nfd < 0) {
+    if (nfd == -1) {
         PLOG(ERROR) << "inotify_init failed";
         return;
     }
@@ -142,17 +142,19 @@
         }
 
         int event_pos = 0;
-        int res = read(nfd, event_buf, sizeof(event_buf));
-        if (res < (int) sizeof(*event)) {
-            if (errno == EINTR)
-                continue;
+        ssize_t res = TEMP_FAILURE_RETRY(read(nfd, event_buf, sizeof(event_buf)));
+        if (res == -1) {
             PLOG(ERROR) << "failed to read inotify event";
             return;
+        } else if (static_cast<size_t>(res) < sizeof(*event)) {
+            LOG(ERROR) << "failed to read inotify event: read " << res << " expected "
+                       << sizeof(event_buf);
+            return;
         }
 
-        while (res >= (int) sizeof(*event)) {
+        while (res >= static_cast<ssize_t>(sizeof(*event))) {
             int event_size;
-            event = (struct inotify_event *) (event_buf + event_pos);
+            event = reinterpret_cast<struct inotify_event*>(event_buf + event_pos);
 
             DLOG(INFO) << "inotify event: " << std::hex << event->mask << std::dec;
             if ((event->mask & IN_IGNORED) == IN_IGNORED) {
@@ -171,7 +173,7 @@
 static int fuse_setup(struct fuse* fuse, gid_t gid, mode_t mask) {
     char opts[256];
 
-    fuse->fd = open("/dev/fuse", O_RDWR);
+    fuse->fd = TEMP_FAILURE_RETRY(open("/dev/fuse", O_RDWR | O_CLOEXEC));
     if (fuse->fd == -1) {
         PLOG(ERROR) << "failed to open fuse device";
         return -1;
@@ -182,8 +184,8 @@
     snprintf(opts, sizeof(opts),
             "fd=%i,rootmode=40000,default_permissions,allow_other,user_id=%d,group_id=%d",
             fuse->fd, fuse->global->uid, fuse->global->gid);
-    if (mount("/dev/fuse", fuse->dest_path, "fuse", MS_NOSUID | MS_NODEV | MS_NOEXEC |
-            MS_NOATIME, opts) != 0) {
+    if (mount("/dev/fuse", fuse->dest_path, "fuse", MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME,
+              opts) == -1) {
         PLOG(ERROR) << "failed to mount fuse filesystem";
         return -1;
     }
@@ -321,7 +323,7 @@
             fsuid, fsgid, multi_user?"multiuser,":"", mask, userid, gid);
 
     if (mount(source_path.c_str(), dest_path.c_str(), "sdcardfs",
-                        MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME, opts.c_str()) != 0) {
+              MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME, opts.c_str()) == -1) {
         PLOG(ERROR) << "failed to mount sdcardfs filesystem";
         return false;
     }
@@ -480,7 +482,7 @@
 
     rlim.rlim_cur = 8192;
     rlim.rlim_max = 8192;
-    if (setrlimit(RLIMIT_NOFILE, &rlim)) {
+    if (setrlimit(RLIMIT_NOFILE, &rlim) == -1) {
         PLOG(ERROR) << "setting RLIMIT_NOFILE failed";
     }