From d4fb1fcd6cdaaa7f8ffefbb7c6d44045b5081197 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 13 Sep 2005 06:19:31 +0000 Subject: [PATCH] Two new functions like write_bytes_to_file: one takes a list of byte-and-len structs; one appends. svn:r5024 --- src/common/util.c | 82 +++++++++++++++++++++++++++++++++++++---------- src/common/util.h | 10 ++++++ 2 files changed, 75 insertions(+), 17 deletions(-) diff --git a/src/common/util.c b/src/common/util.c index 8805ef053a..dd02661718 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -884,10 +884,10 @@ write_str_to_file(const char *fname, const char *str, int bin) return write_bytes_to_file(fname, str, strlen(str), bin); } -/** As write_str_to_file, but does not assume a NUL-terminated * - * string. Instead, we write len bytes, starting at str. */ -int write_bytes_to_file(const char *fname, const char *str, size_t len, - int bin) +/* DOCDOC */ +static int +write_chunks_to_file_impl(const char *fname, const smartlist_t *chunks, + int open_flags) { size_t tempname_len; char *tempname; @@ -896,29 +896,38 @@ int write_bytes_to_file(const char *fname, const char *str, size_t len, tempname_len = strlen(fname)+16; tor_assert(tempname_len > strlen(fname)); /*check for overflow*/ tempname = tor_malloc(tempname_len); - if (tor_snprintf(tempname, tempname_len, "%s.tmp", fname)<0) { - log(LOG_WARN, "Failed to generate filename"); - goto err; + if (open_flags & O_APPEND) { + strlcpy(tempname, fname, tempname_len); + } else { + if (tor_snprintf(tempname, tempname_len, "%s.tmp", fname)<0) { + log(LOG_WARN, "Failed to generate filename"); + goto err; + } } - if ((fd = open(tempname, O_WRONLY|O_CREAT|O_TRUNC|(bin?O_BINARY:O_TEXT), 0600)) + if ((fd = open(tempname, open_flags, 0600)) < 0) { log(LOG_WARN, "Couldn't open \"%s\" for writing: %s", tempname, strerror(errno)); goto err; } - result = write_all(fd, str, len, 0); - if (result < 0 || (size_t)result != len) { - log(LOG_WARN, "Error writing to \"%s\": %s", tempname, strerror(errno)); - close(fd); - goto err; - } + SMARTLIST_FOREACH(chunks, sized_chunk_t *, chunk, + { + result = write_all(fd, chunk->bytes, chunk->len, 0); + if (result < 0 || (size_t)result != chunk->len) { + log(LOG_WARN, "Error writing to \"%s\": %s", tempname, strerror(errno)); + close(fd); + goto err; + } + }); if (close(fd)) { log(LOG_WARN,"Error flushing to \"%s\": %s", tempname, strerror(errno)); goto err; } - if (replace_file(tempname, fname)) { - log(LOG_WARN, "Error replacing \"%s\": %s", fname, strerror(errno)); - goto err; + if (!(open_flags & O_APPEND)) { + if (replace_file(tempname, fname)) { + log(LOG_WARN, "Error replacing \"%s\": %s", fname, strerror(errno)); + goto err; + } } tor_free(tempname); return 0; @@ -927,6 +936,45 @@ int write_bytes_to_file(const char *fname, const char *str, size_t len, return -1; } +/* DOCDOC */ +int +write_chunks_to_file(const char *fname, const smartlist_t *chunks, int bin) +{ + int flags = O_WRONLY|O_CREAT|O_TRUNC|(bin?O_BINARY:O_TEXT); + return write_chunks_to_file_impl(fname, chunks, flags); +} + +/** As write_str_to_file, but does not assume a NUL-terminated * + * string. Instead, we write len bytes, starting at str. */ +int +write_bytes_to_file(const char *fname, const char *str, size_t len, + int bin) +{ + int flags = O_WRONLY|O_CREAT|O_TRUNC|(bin?O_BINARY:O_TEXT); + int r; + sized_chunk_t c = { str, len }; + smartlist_t *chunks = smartlist_create(); + smartlist_add(chunks, &c); + r = write_chunks_to_file_impl(fname, chunks, flags); + smartlist_free(chunks); + return r; +} + +/* DOCDOC */ +int +append_bytes_to_file(const char *fname, const char *str, size_t len, + int bin) +{ + int flags = O_WRONLY|O_CREAT|O_APPEND|(bin?O_BINARY:O_TEXT); + int r; + sized_chunk_t c = { str, len }; + smartlist_t *chunks = smartlist_create(); + smartlist_add(chunks, &c); + r = write_chunks_to_file_impl(fname, chunks, flags); + smartlist_free(chunks); + return r; +} + /** Read the contents of filename into a newly allocated * string; return the string on success or NULL on failure. */ diff --git a/src/common/util.h b/src/common/util.h index d2a0051ceb..791b023e25 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -121,6 +121,16 @@ int check_private_dir(const char *dirname, cpd_check_t check); int write_str_to_file(const char *fname, const char *str, int bin); int write_bytes_to_file(const char *fname, const char *str, size_t len, int bin); +typedef struct sized_chunk_t { + const char *bytes; + size_t len; +} sized_chunk_t; +struct smartlist_t; +int write_chunks_to_file(const char *fname, const struct smartlist_t *chunks, + int bin); +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); char *parse_line_from_str(char *line, char **key_out, char **value_out); char *expand_filename(const char *filename);