diff options
author | Alex Dowad <alexinbeijing@gmail.com> | 2015-05-19 20:15:15 +0200 |
---|---|---|
committer | Timo Teräs <timo.teras@iki.fi> | 2015-05-26 08:38:45 +0300 |
commit | 4c3712ecb443a141227265ecc4394104a1b15801 (patch) | |
tree | c0ce3c848bccec0220558e390bc5b45cf18c9c33 | |
parent | c6d273fc34605ed5655a36fda2e35d0a2d85969b (diff) | |
download | apk-tools-4c3712ecb443a141227265ecc4394104a1b15801.tar.bz2 apk-tools-4c3712ecb443a141227265ecc4394104a1b15801.tar.xz |
detect failures in writing to file during final flush of buffers
In practice this should fix to e.g. not wipe out /etc/apk/world if
final flush to /etc/apk/world.new fails.
This was prompted by an incident the other day where I ran the root
partition of an Alpine box out of space using 'apk add', and apk
helpfully wiped the contents of /etc/apk/world at the same time.
It might be tricky to try to reproduce exactly the same failure,
but from an examination of the code, setting 'rc' before the final
call to fdo_flush rather than after is one possible cause of this
behavior. (If the entire contents of /etc/apk/world.new are buffered,
and all get written out in the final fdo_flush call, and that call
fails, fdo_close will still happily rename /etc/apk/world.new to
/etc/apk/world.)
-rw-r--r-- | src/io.c | 4 |
1 files changed, 3 insertions, 1 deletions
@@ -778,9 +778,11 @@ static int fdo_close(void *stream) { struct apk_fd_ostream *fos = container_of(stream, struct apk_fd_ostream, os); - int rc = fos->rc; + int rc; fdo_flush(fos); + rc = fos->rc; + if (fos->fd > STDERR_FILENO && close(fos->fd) < 0) rc = -errno; |