Преглед на файлове

If we write the annotation but not the microdescriptor, rewind.

This fixes bug 9047 (and some parts of 9031, 8922, 8883 that weren't
fixed in 8822).  Bugfix on 0.2.2.6-alpha.
Nick Mathewson преди 11 години
родител
ревизия
caa0d15c49
променени са 4 файла, в които са добавени 32 реда и са изтрити 6 реда
  1. 6 0
      changes/bug9047
  2. 12 0
      src/common/compat.c
  3. 1 0
      src/common/compat.h
  4. 13 6
      src/or/microdesc.c

+ 6 - 0
changes/bug9047

@@ -0,0 +1,6 @@
+  o Minor bugfixes:
+    - If for some reason we fail to write a microdescriptor while
+      rebuilding the cache, do not let the annotations from that
+      microdescriptor linger in the cache file, and do not let the
+      microdescriptor stay recorded as present in its old location.
+      Fixes bug 9047; bugfix on 0.2.2.6-alpha.

+ 12 - 0
src/common/compat.c

@@ -900,6 +900,18 @@ tor_fd_seekend(int fd)
 #endif
 }
 
+/** Move <b>fd</b> to position <b>pos</b> in the file. Return -1 on error, 0
+ * on success. */
+int
+tor_fd_setpos(int fd, off_t pos)
+{
+#ifdef _WIN32
+  return _lseek(fd, pos, SEEK_SET) < 0 ? -1 : 0;
+#else
+  return lseek(fd, pos, SEEK_SET) < 0 ? -1 : 0;
+#endif
+}
+
 #undef DEBUG_SOCKET_COUNTING
 #ifdef DEBUG_SOCKET_COUNTING
 /** A bitarray of all fds that should be passed to tor_socket_close(). Only

+ 1 - 0
src/common/compat.h

@@ -411,6 +411,7 @@ tor_lockfile_t *tor_lockfile_lock(const char *filename, int blocking,
 void tor_lockfile_unlock(tor_lockfile_t *lockfile);
 
 off_t tor_fd_getpos(int fd);
+int tor_fd_setpos(int fd, off_t pos);
 int tor_fd_seekend(int fd);
 
 #ifdef _WIN32

+ 13 - 6
src/or/microdesc.c

@@ -74,7 +74,7 @@ static ssize_t
 dump_microdescriptor(int fd, microdesc_t *md, size_t *annotation_len_out)
 {
   ssize_t r = 0;
-  size_t written;
+  ssize_t written;
   if (md->body == NULL) {
     *annotation_len_out = 0;
     return 0;
@@ -99,10 +99,10 @@ dump_microdescriptor(int fd, microdesc_t *md, size_t *annotation_len_out)
 
   md->off = tor_fd_getpos(fd);
   written = write_all(fd, md->body, md->bodylen, 0);
-  if (written != md->bodylen) {
+  if (written != (ssize_t)md->bodylen) {
     log_warn(LD_DIR,
-             "Couldn't dump microdescriptor (wrote %lu out of %lu): %s",
-             (unsigned long)written, (unsigned long)md->bodylen,
+             "Couldn't dump microdescriptor (wrote %ld out of %lu): %s",
+             (long)written, (unsigned long)md->bodylen,
              strerror(errno));
     return -1;
   }
@@ -456,8 +456,15 @@ microdesc_cache_rebuild(microdesc_cache_t *cache, int force)
 
     size = dump_microdescriptor(fd, md, &annotation_len);
     if (size < 0) {
-      /* XXX handle errors from dump_microdescriptor() */
-      /* log?  return -1?  die?  coredump the universe? */
+      if (md->saved_location != SAVED_IN_CACHE)
+        tor_free(md->body);
+      md->saved_location = SAVED_NOWHERE;
+      md->off = 0;
+      md->bodylen = 0;
+      md->no_save = 1;
+
+      /* rewind, in case it was a partial write. */
+      tor_fd_setpos(fd, off);
       continue;
     }
     tor_assert(((size_t)size) == annotation_len + md->bodylen);