diff --git a/ChangeLog b/ChangeLog index 0abd417449..743a2c00c5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -62,6 +62,7 @@ Changes in version 0.1.2.7-alpha - 2007-??-?? unstable ones. - Handle TTL values correctly on reverse DNS lookups. - Stop using the reserved ac_cv namespace in our configure script. + - Call stat() slightly less often; use fstat() when possible. o Major features: - Weight directory requests by advertised bandwidth. Now we can diff --git a/src/common/compat.c b/src/common/compat.c index 6838db9043..9c9da66d6b 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -241,14 +241,14 @@ tor_munmap_file(tor_mmap_t *handle) tor_mmap_t * tor_mmap_file(const char *filename) { - size_t size; - char *res = read_file_to_str(filename, 1, &size); + struct stat st; + char *res = read_file_to_str(filename, 1, &st); tor_mmap_t *handle; if (! res) return NULL; handle = tor_malloc_zero(sizeof(tor_mmap_t)); handle->data = res; - handle->size = size; + handle->size = st.st_size; return handle; } void diff --git a/src/common/util.c b/src/common/util.c index f249b4551c..d7027b848c 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -1375,30 +1375,27 @@ append_bytes_to_file(const char *fname, const char *str, size_t len, * be truncated. */ char * -read_file_to_str(const char *filename, int bin, size_t *size_out) +read_file_to_str(const char *filename, int bin, struct stat *stat_out) { int fd; /* router file */ struct stat statbuf; - char *string, *f; + char *string; int r; tor_assert(filename); - f = tor_strdup(filename); - clean_name_for_stat(f); - r = stat(f, &statbuf); - tor_free(f); - if (r < 0) { - log_info(LD_FS,"Could not stat \"%s\".",filename); - return NULL; - } - fd = open(filename,O_RDONLY|(bin?O_BINARY:O_TEXT),0); if (fd<0) { log_warn(LD_FS,"Could not open \"%s\".",filename); return NULL; } + if (fstat(fd, &statbuf)<0) { + close(fd); + log_info(LD_FS,"Could not fstat \"%s\".",filename); + return NULL; + } + if ((uint64_t)(statbuf.st_size)+1 > SIZE_T_MAX) return NULL; @@ -1414,26 +1411,31 @@ read_file_to_str(const char *filename, int bin, size_t *size_out) } string[r] = '\0'; /* NUL-terminate the result. */ - if (bin && r != statbuf.st_size) { - /* If we're in binary mode, then we'd better have an exact match for - * size. Otherwise, win32 encoding may throw us off, and that's okay. */ - log_warn(LD_FS,"Could read only %d of %ld bytes of file \"%s\".", - r, (long)statbuf.st_size,filename); - tor_free(string); - close(fd); - return NULL; - } #ifdef MS_WINDOWS if (!bin && strchr(string, '\r')) { log_debug(LD_FS, "We didn't convert CRLF to LF as well as we hoped " "when reading %s. Coping.", filename); tor_strstrip(string, "\r"); + r = strlen(string); } + if (!bin) { + statbuf.st_size = (size_t) r; + } else #endif + if (r != statbuf.st_size) { + /* Unless we're using text mode on win32, we'd better have an exact + * match for size. */ + log_warn(LD_FS,"Could read only %d of %ld bytes of file \"%s\".", + r, (long)statbuf.st_size,filename); + tor_free(string); + close(fd); + return NULL; + } close(fd); - if (size_out) - *size_out = (size_t) r; + if (stat_out) { + memcpy(stat_out, &statbuf, sizeof(struct stat)); + } return string; } diff --git a/src/common/util.h b/src/common/util.h index 3ada73d4b7..b659e5f04e 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -182,7 +182,8 @@ int write_chunks_to_file(const char *fname, const struct smartlist_t *chunks, int append_bytes_to_file(const char *fname, const char *str, size_t len, int bin); -char *read_file_to_str(const char *filename, int bin, size_t *size_out) +struct stat; +char *read_file_to_str(const char *filename, int bin, struct stat *stat_out) ATTR_MALLOC; char *parse_line_from_str(char *line, char **key_out, char **value_out); char *expand_filename(const char *filename); diff --git a/src/or/dns.c b/src/or/dns.c index 3137a67de8..c86bd9c571 100644 --- a/src/or/dns.c +++ b/src/or/dns.c @@ -1529,8 +1529,8 @@ configure_nameservers(int force) evdns_set_log_fn(evdns_log_cb); if (conf_fname) { if (stat(conf_fname, &st)) { - log_warn(LD_EXIT, "Unable to stat resolver configuration in '%s'", - conf_fname); + log_warn(LD_EXIT, "Unable to stat resolver configuration in '%s': %s", + conf_fname, strerror(errno)); return -1; } if (!force && resolv_conf_fname && !strcmp(conf_fname,resolv_conf_fname) diff --git a/src/or/routerlist.c b/src/or/routerlist.c index f177b153a0..46b958d9dc 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -118,8 +118,8 @@ int router_reload_networkstatus(void) { char filename[512]; - struct stat st; smartlist_t *entries; + struct stat st; char *s; tor_assert(get_options()->DataDirectory); if (!networkstatus_list) @@ -138,9 +138,8 @@ router_reload_networkstatus(void) } tor_snprintf(filename,sizeof(filename),"%s/cached-status/%s", get_options()->DataDirectory, fn); - s = read_file_to_str(filename, 0, NULL); + s = read_file_to_str(filename, 0, &st); if (s) { - stat(filename, &st); if (router_set_networkstatus(s, st.st_mtime, NS_FROM_CACHE, NULL)<0) { log_warn(LD_FS, "Couldn't load networkstatus from \"%s\"",filename); } @@ -353,7 +352,6 @@ router_reload_router_list(void) or_options_t *options = get_options(); size_t fname_len = strlen(options->DataDirectory)+32; char *fname = tor_malloc(fname_len), *contents; - struct stat st; if (!routerlist) router_get_routerlist(); /* mallocs and inits it in place */ @@ -376,7 +374,6 @@ router_reload_router_list(void) options->DataDirectory); contents = read_file_to_str(fname, 1, NULL); if (contents) { - stat(fname, &st); router_load_routers_from_string(contents, SAVED_IN_JOURNAL, NULL); tor_free(contents);