Two new functions like write_bytes_to_file: one takes a list of byte-and-len structs; one appends.

svn:r5024
This commit is contained in:
Nick Mathewson 2005-09-13 06:19:31 +00:00
parent 82b3b6249c
commit d4fb1fcd6c
2 changed files with 75 additions and 17 deletions

View File

@ -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); return write_bytes_to_file(fname, str, strlen(str), bin);
} }
/** As write_str_to_file, but does not assume a NUL-terminated * /* DOCDOC */
* string. Instead, we write <b>len</b> bytes, starting at <b>str</b>. */ static int
int write_bytes_to_file(const char *fname, const char *str, size_t len, write_chunks_to_file_impl(const char *fname, const smartlist_t *chunks,
int bin) int open_flags)
{ {
size_t tempname_len; size_t tempname_len;
char *tempname; 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; tempname_len = strlen(fname)+16;
tor_assert(tempname_len > strlen(fname)); /*check for overflow*/ tor_assert(tempname_len > strlen(fname)); /*check for overflow*/
tempname = tor_malloc(tempname_len); tempname = tor_malloc(tempname_len);
if (tor_snprintf(tempname, tempname_len, "%s.tmp", fname)<0) { if (open_flags & O_APPEND) {
log(LOG_WARN, "Failed to generate filename"); strlcpy(tempname, fname, tempname_len);
goto err; } 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) { < 0) {
log(LOG_WARN, "Couldn't open \"%s\" for writing: %s", tempname, log(LOG_WARN, "Couldn't open \"%s\" for writing: %s", tempname,
strerror(errno)); strerror(errno));
goto err; goto err;
} }
result = write_all(fd, str, len, 0); SMARTLIST_FOREACH(chunks, sized_chunk_t *, chunk,
if (result < 0 || (size_t)result != len) { {
log(LOG_WARN, "Error writing to \"%s\": %s", tempname, strerror(errno)); result = write_all(fd, chunk->bytes, chunk->len, 0);
close(fd); if (result < 0 || (size_t)result != chunk->len) {
goto err; log(LOG_WARN, "Error writing to \"%s\": %s", tempname, strerror(errno));
} close(fd);
goto err;
}
});
if (close(fd)) { if (close(fd)) {
log(LOG_WARN,"Error flushing to \"%s\": %s", tempname, strerror(errno)); log(LOG_WARN,"Error flushing to \"%s\": %s", tempname, strerror(errno));
goto err; goto err;
} }
if (replace_file(tempname, fname)) { if (!(open_flags & O_APPEND)) {
log(LOG_WARN, "Error replacing \"%s\": %s", fname, strerror(errno)); if (replace_file(tempname, fname)) {
goto err; log(LOG_WARN, "Error replacing \"%s\": %s", fname, strerror(errno));
goto err;
}
} }
tor_free(tempname); tor_free(tempname);
return 0; return 0;
@ -927,6 +936,45 @@ int write_bytes_to_file(const char *fname, const char *str, size_t len,
return -1; 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 <b>len</b> bytes, starting at <b>str</b>. */
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 <b>filename</b> into a newly allocated /** Read the contents of <b>filename</b> into a newly allocated
* string; return the string on success or NULL on failure. * string; return the string on success or NULL on failure.
*/ */

View File

@ -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_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 write_bytes_to_file(const char *fname, const char *str, size_t len,
int bin); 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 *read_file_to_str(const char *filename, int bin);
char *parse_line_from_str(char *line, char **key_out, char **value_out); char *parse_line_from_str(char *line, char **key_out, char **value_out);
char *expand_filename(const char *filename); char *expand_filename(const char *filename);