diff options
author | Behdad Esfahbod <behdad@behdad.org> | 2013-09-27 18:18:34 -0400 |
---|---|---|
committer | Behdad Esfahbod <behdad@behdad.org> | 2013-09-27 18:18:34 -0400 |
commit | a43839c166da7cc0a89bd7eb0b78b991bdff5471 (patch) | |
tree | a3dd889baf0569f8330143420e87dbd05c06a92c /src/vtestream-file.h | |
parent | fae64189d5370681dccbe4f96c6f0a86153caa3f (diff) | |
download | vte-a43839c166da7cc0a89bd7eb0b78b991bdff5471.tar.gz |
[stream-file] Recover from a disk-full situation
Diffstat (limited to 'src/vtestream-file.h')
-rw-r--r-- | src/vtestream-file.h | 38 |
1 files changed, 25 insertions, 13 deletions
diff --git a/src/vtestream-file.h b/src/vtestream-file.h index 6d2371ef..c11a3155 100644 --- a/src/vtestream-file.h +++ b/src/vtestream-file.h @@ -48,6 +48,19 @@ pwrite (int fd, char *data, gsize len, gsize offset) } #endif +static void +_xtruncate (gint fd, gsize offset) +{ + int ret; + + if (G_UNLIKELY (!fd)) + return; + + do { + ret = ftruncate (fd, offset); + } while (ret == -1 && errno == EINTR); +} + static gsize _xpread (int fd, char *data, gsize len, gsize offset) { @@ -78,6 +91,7 @@ static void _xpwrite (int fd, const char *data, gsize len, gsize offset) { gsize ret; + gboolean truncated = FALSE; g_assert (fd || !len); @@ -86,6 +100,17 @@ _xpwrite (int fd, const char *data, gsize len, gsize offset) if (G_UNLIKELY (ret == (gsize) -1)) { if (errno == EINTR) continue; + else if (errno == EINVAL && !truncated) + { + /* Perhaps previous writes failed and now we are + * seeking past end of file. Try extending it + * and retry. This allows recovering from a + * "/tmp is full" error. + */ + _xtruncate (fd, offset); + truncated = TRUE; + continue; + } else break; } @@ -97,19 +122,6 @@ _xpwrite (int fd, const char *data, gsize len, gsize offset) } } -static void -_xtruncate (gint fd, gsize offset) -{ - int ret; - - if (G_UNLIKELY (!fd)) - return; - - do { - ret = ftruncate (fd, offset); - } while (ret == -1 && errno == EINTR); -} - static gboolean _xwrite_contents (gint fd, GOutputStream *output, GCancellable *cancellable, GError **error) { |