diff options
author | bojan <bojan@13f79535-47bb-0310-9956-ffa450edef68> | 2012-02-06 20:54:16 +0000 |
---|---|---|
committer | bojan <bojan@13f79535-47bb-0310-9956-ffa450edef68> | 2012-02-06 20:54:16 +0000 |
commit | fbefa19103b3becb3f27c3c3dd0e7a9712165cbe (patch) | |
tree | 8903b8d7816766a90c183c2a1a68d4b19853191f | |
parent | 4c11a08dde53cedef71a041300342d1c7ce0ed7d (diff) | |
download | libapr-fbefa19103b3becb3f27c3c3dd0e7a9712165cbe.tar.gz |
Backport r1044440 from trunk to 1.4.x.
Fix file_trunc for buffered files. Make sure the write buffer is flushed before truncate call
git-svn-id: http://svn.apache.org/repos/asf/apr/apr/branches/1.4.x@1241173 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | CHANGES | 3 | ||||
-rw-r--r-- | file_io/unix/seek.c | 26 |
2 files changed, 28 insertions, 1 deletions
@@ -1,6 +1,9 @@ -*- coding: utf-8 -*- Changes for APR 1.4.6 + *) Flush write buffer before truncate call on a file. + [Mladen Turk] + *) Security: oCERT-2011-003 Randomise hashes by providing a seed. [Bojan Smojver, Branko Čibej, Ruediger Pluem et al.] diff --git a/file_io/unix/seek.c b/file_io/unix/seek.c index 77ef96e7d..e70805d7f 100644 --- a/file_io/unix/seek.c +++ b/file_io/unix/seek.c @@ -33,7 +33,7 @@ static apr_status_t setptr(apr_file_t *thefile, apr_off_t pos ) if (newbufpos >= 0 && newbufpos <= thefile->dataRead) { thefile->bufpos = newbufpos; rv = APR_SUCCESS; - } + } else { if (lseek(thefile->filedes, pos, SEEK_SET) != -1) { thefile->bufpos = thefile->dataRead = 0; @@ -98,6 +98,30 @@ APR_DECLARE(apr_status_t) apr_file_seek(apr_file_t *thefile, apr_seek_where_t wh apr_status_t apr_file_trunc(apr_file_t *fp, apr_off_t offset) { + if (fp->buffered) { + int rc = 0; + file_lock(fp); + if (fp->direction == 1 && fp->bufpos != 0) { + apr_off_t len = fp->filePtr + fp->bufpos; + if (offset < len) { + /* New file end fall below our write buffer limit. + * Figure out if and what needs to be flushed. + */ + apr_off_t off = len - offset; + if (off >= 0 && off <= fp->bufpos) + fp->bufpos = fp->bufpos - (size_t)off; + else + fp->bufpos = 0; + } + rc = apr_file_flush_locked(fp); + /* Reset buffer positions for write mode */ + fp->bufpos = fp->direction = fp->dataRead = 0; + } + if (rc) { + return rc; + } + file_unlock(fp); + } if (ftruncate(fp->filedes, offset) == -1) { return errno; } |