summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomas Bzatek <tbzatek@redhat.com>2012-06-25 17:32:01 +0200
committerTomas Bzatek <tbzatek@redhat.com>2012-06-25 17:37:03 +0200
commitff748cd275fba9b6cc14f1efa94534fbf0f23caa (patch)
tree80ecff83bbe8730fd5c665dd60111515ebf0ce7d
parenta1abfe3ea48e92ae96a6d867272c9cf31bece9f7 (diff)
downloadgvfs-ff748cd275fba9b6cc14f1efa94534fbf0f23caa.tar.gz
fuse: Split padding size in blocks for ftruncate()
Don't allocate whole padding block, write in smaller pieces instead. As an bonus, check for block write result and break if error occurred, passing it further up. Found by David Zeuthen.
-rw-r--r--client/gvfsfusedaemon.c27
1 files changed, 23 insertions, 4 deletions
diff --git a/client/gvfsfusedaemon.c b/client/gvfsfusedaemon.c
index 78279239..c760f14c 100644
--- a/client/gvfsfusedaemon.c
+++ b/client/gvfsfusedaemon.c
@@ -1845,6 +1845,28 @@ file_handle_get_size (FileHandle *fh,
return res;
}
+#define PAD_BLOCK_SIZE 65536
+
+static gint
+pad_file (FileHandle *fh, gsize num, goffset current_size)
+{
+ gpointer buf;
+ gsize written;
+ gint res;
+
+ res = 0;
+ buf = g_malloc0 (PAD_BLOCK_SIZE);
+ for (written = 0; written < num; written += PAD_BLOCK_SIZE)
+ {
+ res = write_stream (fh, buf, MIN (num - written, PAD_BLOCK_SIZE), current_size + written);
+ if (res < 0)
+ break;
+ }
+ g_free (buf);
+
+ return (res < 0 ? res : 0);
+}
+
static gint
vfs_ftruncate (const gchar *path, off_t size, struct fuse_file_info *fi)
{
@@ -1902,10 +1924,7 @@ vfs_ftruncate (const gchar *path, off_t size, struct fuse_file_info *fi)
/* If the truncated size is larger than the current size
* then we need to pad out the difference with 0's */
goffset orig_pos = g_seekable_tell (G_SEEKABLE (fh->stream));
- gsize buf_size = size - current_size;
- gpointer buf = g_malloc0 (buf_size);
- write_stream (fh, buf, buf_size, current_size);
- g_free (buf);
+ result = pad_file (fh, size - current_size, current_size);
g_seekable_seek (G_SEEKABLE (fh->stream), orig_pos, G_SEEK_SET, NULL, NULL);
}
}