gio: Don't allow skipping past the end of GLocalFileInputStream

The overridden implementation of the skip method for
GLocalFileInputStream allows skipping past the end of the file which is
inconsistent with the documentation.  Prevent this by first seeking to
the end of the file and then seeking backwards from there as much as
is necessary.

https://bugzilla.gnome.org/show_bug.cgi?id=711048
This commit is contained in:
Ross Lagerwall 2013-10-29 06:02:59 +02:00
parent dc172f0616
commit 89f9615835
2 changed files with 31 additions and 4 deletions

View File

@ -185,7 +185,7 @@ g_local_file_input_stream_skip (GInputStream *stream,
GCancellable *cancellable, GCancellable *cancellable,
GError **error) GError **error)
{ {
off_t res, start; off_t start, end;
GLocalFileInputStream *file; GLocalFileInputStream *file;
file = G_LOCAL_FILE_INPUT_STREAM (stream); file = G_LOCAL_FILE_INPUT_STREAM (stream);
@ -205,8 +205,8 @@ g_local_file_input_stream_skip (GInputStream *stream,
return -1; return -1;
} }
res = lseek (file->priv->fd, count, SEEK_CUR); end = lseek (file->priv->fd, 0, SEEK_END);
if (res == -1) if (end == -1)
{ {
int errsv = errno; int errsv = errno;
@ -217,7 +217,22 @@ g_local_file_input_stream_skip (GInputStream *stream,
return -1; return -1;
} }
return res - start; if (end - start > count)
{
end = lseek (file->priv->fd, count - (end - start), SEEK_CUR);
if (end == -1)
{
int errsv = errno;
g_set_error (error, G_IO_ERROR,
g_io_error_from_errno (errsv),
_("Error seeking in file: %s"),
g_strerror (errsv));
return -1;
}
}
return end - start;
} }
static gboolean static gboolean

View File

@ -62,6 +62,18 @@ verify_iostream (GFileIOStream *file_iostream)
verify_pos (iostream, strlen (original_data)); verify_pos (iostream, strlen (original_data));
res = g_seekable_seek (G_SEEKABLE (iostream),
10, G_SEEK_SET,
NULL, NULL);
res = g_input_stream_skip (in, 5, NULL, NULL);
g_assert (res == 5);
verify_pos (iostream, 15);
res = g_input_stream_skip (in, 10000, NULL, NULL);
g_assert (res == strlen (original_data) - 15);
verify_pos (iostream, strlen (original_data));
res = g_seekable_seek (G_SEEKABLE (iostream), res = g_seekable_seek (G_SEEKABLE (iostream),
10, G_SEEK_SET, 10, G_SEEK_SET,
NULL, NULL); NULL, NULL);