commit caa0d15c4902a8d376a2a79bfbfdb21bf047366a Author: Nick Mathewson nickm@torproject.org Date: Thu Jun 13 12:29:01 2013 -0400
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. --- changes/bug9047 | 6 ++++++ src/common/compat.c | 12 ++++++++++++ src/common/compat.h | 1 + src/or/microdesc.c | 19 +++++++++++++------ 4 files changed, 32 insertions(+), 6 deletions(-)
diff --git a/changes/bug9047 b/changes/bug9047 new file mode 100644 index 0000000..497f0d3 --- /dev/null +++ b/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. diff --git a/src/common/compat.c b/src/common/compat.c index c97a454..24b44fb 100644 --- a/src/common/compat.c +++ b/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 diff --git a/src/common/compat.h b/src/common/compat.h index f0a34aa..8ab7190 100644 --- a/src/common/compat.h +++ b/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 diff --git a/src/or/microdesc.c b/src/or/microdesc.c index 05e3b41..b93bd83 100644 --- a/src/or/microdesc.c +++ b/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);