diff --git a/src/util/string.c b/src/util/string.c index ee1cfa15..b8865568 100644 --- a/src/util/string.c +++ b/src/util/string.c @@ -4,8 +4,13 @@ #include "config.h" #endif +#ifndef _GNU_SOURCE +#define _GNU_SOURCE /* XXX: fseeko, ftello */ +#endif + #include #include +#include #include #include @@ -325,6 +330,46 @@ add_string_to_string(struct string *string, struct string *from) return add_bytes_to_string(string, from->source, from->length); } +struct string * +add_file_to_string(struct string *string, unsigned char *filename) +{ + FILE *file; + off_t filelen; + int newlength; + + assertm(string && filename, "[add_file_to_string]"); + if_assert_failed { return NULL; } + + check_string_magic(string); + + file = fopen(filename, "rb"); + if (!file) return NULL; + + if (fseeko(file, 0, SEEK_END)) goto err; + + filelen = ftello(file); + if (filelen == -1) goto err; + + if (fseeko(file, 0, SEEK_SET)) goto err; + + newlength = string->length + filelen; + if (!realloc_string(string, newlength)) goto err; + + string->length += fread(string->source + string->length, 1, + (size_t) filelen, file); + string->source[string->length] = 0; + fclose(file); + + if (string->length != newlength) goto err; + + return string; + +err: + fclose(file); + + return NULL; +} + struct string * string_concat(struct string *string, ...) { diff --git a/src/util/string.h b/src/util/string.h index 6d8715bd..7390061c 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -157,6 +157,7 @@ struct string *add_to_string(struct string *string, const unsigned char *source); struct string *add_char_to_string(struct string *string, unsigned char character); struct string *add_string_to_string(struct string *to, struct string *from); +struct string *add_file_to_string(struct string *string, unsigned char *filename); struct string *add_crlf_to_string(struct string *string); /* Adds each C string to @string until a terminating NULL is met. */ diff --git a/src/viewer/text/textarea.c b/src/viewer/text/textarea.c index 680216b7..a5dc6ed4 100644 --- a/src/viewer/text/textarea.c +++ b/src/viewer/text/textarea.c @@ -314,32 +314,17 @@ save_textarea_file(unsigned char *value) static unsigned char * load_textarea_file(unsigned char *filename, size_t maxlength) { - unsigned char *value = NULL; - FILE *file = fopen(filename, "rb+"); - off_t filelen = -1; + struct string file; - if (!file) return NULL; + if (!init_string(&file) + || !add_file_to_string(&file, filename)) + return NULL; - if (!fseeko(file, 0, SEEK_END)) { - filelen = ftello(file); - if (filelen != -1 && fseeko(file, 0, SEEK_SET)) - filelen = -1; - } - - if (filelen >= 0 && filelen <= maxlength) { - value = mem_alloc((size_t) (filelen + 1)); - if (value) { - size_t bread; - - bread = fread(value, 1, (size_t) filelen, file); - value[bread] = 0; - } - } - - fclose(file); unlink(filename); - return value; + if (file.length > maxlength) { done_string(&file); return NULL; } + + return file.source; } void