diff options
author | Martin Willi <martin@revosec.ch> | 2013-11-21 12:19:20 +0100 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2014-01-23 15:55:32 +0100 |
commit | 1c4a3459f72da4391c1befe22e62356d838af46d (patch) | |
tree | a60e5be4cf8c95c05b891f84df5ffa1069ec65ef /src/libstrongswan/utils/chunk.c | |
parent | 595b6d9a828538072dcf65c276b848a02698fdfe (diff) | |
download | strongswan-1c4a3459f72da4391c1befe22e62356d838af46d.tar.bz2 strongswan-1c4a3459f72da4391c1befe22e62356d838af46d.tar.xz |
chunk: Use dynamically allocated buffer in chunk_from_fd()
When acting on files, we can use fstat() to estimate the buffer size. On
non-file FDs, we dynamically increase an allocated buffer.
Additionally we slightly change the function signature to properly handle
zero-length files and add appropriate unit tests.
Diffstat (limited to 'src/libstrongswan/utils/chunk.c')
-rw-r--r-- | src/libstrongswan/utils/chunk.c | 53 |
1 files changed, 41 insertions, 12 deletions
diff --git a/src/libstrongswan/utils/chunk.c b/src/libstrongswan/utils/chunk.c index 5c00c5b32..e308418df 100644 --- a/src/libstrongswan/utils/chunk.c +++ b/src/libstrongswan/utils/chunk.c @@ -247,33 +247,62 @@ bool chunk_write(chunk_t chunk, char *path, char *label, mode_t mask, bool force /** * Described in header. */ -chunk_t chunk_from_fd(int fd) +bool chunk_from_fd(int fd, chunk_t *out) { - char buf[8096]; - char *pos = buf; - ssize_t len, total = 0; + struct stat sb; + char *buf, *tmp; + ssize_t len, total = 0, bufsize; + + if (fstat(fd, &sb) == 0 && S_ISREG(sb.st_mode)) + { + bufsize = sb.st_size; + } + else + { + bufsize = 256; + } + buf = malloc(bufsize); + if (!buf) + { /* for huge files */ + return FALSE; + } while (TRUE) { - len = read(fd, pos, buf + sizeof(buf) - pos); + len = read(fd, buf + total, bufsize - total); if (len < 0) { - DBG1(DBG_LIB, "reading from file descriptor failed: %s", - strerror(errno)); - return chunk_empty; + free(buf); + return FALSE; } if (len == 0) { break; } total += len; - if (total == sizeof(buf)) + if (total == bufsize) { - DBG1(DBG_LIB, "buffer too small to read from file descriptor"); - return chunk_empty; + bufsize *= 2; + tmp = realloc(buf, bufsize); + if (!tmp) + { + free(buf); + return FALSE; + } + buf = tmp; } } - return chunk_clone(chunk_create(buf, total)); + if (total == 0) + { + free(buf); + buf = NULL; + } + else if (total < bufsize) + { + buf = realloc(buf, total); + } + *out = chunk_create(buf, total); + return TRUE; } /** |