Parcourir la source

[1470] Correct bug concerning status return check

Original code checked the wrong variable when doing a status check
on read(2)/write(2).
Stephen Morris il y a 13 ans
Parent
commit
3f83fac07d
1 fichiers modifiés avec 44 ajouts et 27 suppressions
  1. 44 27
      src/lib/util/io/fd.cc

+ 44 - 27
src/lib/util/io/fd.cc

@@ -23,46 +23,63 @@ namespace io {
 
 bool
 write_data(const int fd, const void *buffer_v, const size_t length) {
-    const unsigned char *buffer(static_cast<const unsigned char *>(buffer_v));
-    size_t rest(length);
-    // Just keep writing until all is written
-    while (rest) {
-        ssize_t written(write(fd, buffer, rest));
-        if (rest == -1) {
-            if (errno == EINTR) { // Just keep going
-                continue;
-            } else {
+
+    const unsigned char* buffer(static_cast<const unsigned char*>(buffer_v));
+    size_t remaining = length;  // Amount remaining to be written
+
+    while (remaining > 0) {
+        ssize_t amount = write(fd, buffer, remaining);
+        if (amount == -1) {
+            // Some error.  Ignore interrupted system calls otherwise return
+            // an error indication.
+            if (errno != EINTR) {
                 return false;
             }
-        } else { // Wrote something
-            rest -= written;
-            buffer += written;
+
+        } else if (amount > 0) {
+            // Wrote "amount" bytes from the buffer
+            remaining -= amount;
+            buffer += amount;
+
+        } else {
+            // Wrote zero bytes from the buffer. We should not get here as any
+            // error that causes zero bytes to be written should have returned
+            // -1.  However, write(2) can return 0, and in this case we
+            // interpret it as an error.
+            return (false);
         }
     }
-    return true;
+    return (true);
 }
 
 ssize_t
 read_data(const int fd, void *buffer_v, const size_t length) {
-    unsigned char *buffer(static_cast<unsigned char *>(buffer_v));
-    size_t rest(length), already(0);
-    while (rest) { // Stil something to read
-        ssize_t amount(read(fd, buffer, rest));
-        if (rest == -1) {
-            if (errno == EINTR) { // Continue on interrupted call
-                continue;
-            } else {
+
+    unsigned char* buffer(static_cast<unsigned char*>(buffer_v));
+    size_t remaining = length;   // Amount remaining to be read
+
+    while (remaining > 0) {
+        ssize_t amount = read(fd, buffer, remaining);
+        if (amount == -1) {
+            // Some error.  Ignore interrupted system calls otherwise return
+            // an error indication.
+            if (errno != EINTR) {
                 return -1;
             }
-        } else if (amount) {
-            already += amount;
-            rest -= amount;
+
+        } else if (amount > 0) {
+            // Read "amount" bytes into the buffer
+            remaining -= amount;
             buffer += amount;
-        } else { // EOF
-            return already;
+
+        } else {
+            // EOF - end the read
+            break;
         }
     }
-    return already;
+
+    // Return total number of bytes read
+    return (static_cast<ssize_t>(length - remaining));
 }
 
 }