Re: [PATCH] fuse: Support ftruncate where requested size > current size



Great addition, thanks for the patch, we're not giving much love to the
fuse daemon these days.

The second part (zero filling) looks good to me, I just did not get the
first part - not using FGilexxputStream but GFile instead. Was there a
strong reason? I mean, if the file is still open, g_file_query_info()
may not give correct information until the file is closed. This heavily
depends on the particular backend naturally.

-- 
Tomas Bzatek <tbzatek redhat com>

On Thu, 2012-05-17 at 23:58 -0500, Jeff Smith wrote:
> When ftruncate is called with a size greater than the current size
> of the file, the expected behavior is that the file size increases to
> the requested size, and the new space is zero-filled.  SQLite depends
> on this behavior when opening a database using 'write-ahead log'
> journaling.
> 
> Signed-off-by: Jeff Smith <whydoubt yahoo com>
> ---
> On iOS 5, the SQLite database MediaLibrary.sqlite uses write-ahead
> logging.  Without this patch, the only way to do anything with the
> database (even to dump it) is to copy it from the iPod/iPhone to a
> local filesystem, and then work with it.
> 
>  client/gvfsfusedaemon.c |   26 ++++++++++++++++----------
>  1 file changed, 16 insertions(+), 10 deletions(-)
> 
> diff --git a/client/gvfsfusedaemon.c b/client/gvfsfusedaemon.c
> index 8cf1c01..9f11678 100644
> --- a/client/gvfsfusedaemon.c
> +++ b/client/gvfsfusedaemon.c
> @@ -1814,6 +1814,7 @@ vfs_rmdir (const gchar *path)
>  
>  static gboolean
>  file_handle_get_size (FileHandle *fh,
> +		      GFile *file,
>  		      goffset *size)
>  {
>    GFileInfo *info;
> @@ -1822,15 +1823,9 @@ file_handle_get_size (FileHandle *fh,
>    if (fh->stream == NULL)
>      return FALSE;
>    
> -  info = NULL;
> -  if (fh->op == FILE_OP_READ)
> -    info = g_file_input_stream_query_info (fh->stream,
> -					   G_FILE_ATTRIBUTE_STANDARD_SIZE,
> -					   NULL, NULL);
> -  else if (fh->op == FILE_OP_WRITE)
> -    info = g_file_output_stream_query_info (fh->stream,
> -					    G_FILE_ATTRIBUTE_STANDARD_SIZE,
> -					    NULL, NULL);
> +  info = g_file_query_info (file,
> +			    G_FILE_ATTRIBUTE_STANDARD_SIZE,
> +			    0, NULL, NULL);
>  
>    res = FALSE;
>    if (info)
> @@ -1891,11 +1886,22 @@ vfs_ftruncate (const gchar *path, off_t size, struct fuse_file_info *fi)
>                        fh->stream = NULL;
>                      }
>                  }
> -              else if (file_handle_get_size (fh, &current_size) &&
> +              else if (file_handle_get_size (fh, file, &current_size) &&
>  		       current_size == size)
>  		{
>  		  /* Don't have to do anything to succeed */
>  		}
> +              else if ((current_size < size) && g_seekable_can_seek(G_SEEKABLE(fh->stream)))
> +                {
> +                  /* 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);
> +                  g_seekable_seek (G_SEEKABLE(fh->stream), orig_pos, G_SEEK_SET, NULL, NULL);
> +                }
>  	      else
>  		{
>  		  result = -ENOTSUP;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]