mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-25 19:52:10 +01:00
Merge branch '587-seek-behaviour' into 'master'
ginputstream: Don’t skip off the end of resizable streams Closes #587 See merge request GNOME/glib!1952
This commit is contained in:
commit
7ec5405c5a
@ -411,12 +411,41 @@ g_input_stream_real_skip (GInputStream *stream,
|
|||||||
|
|
||||||
if (G_IS_SEEKABLE (stream) && g_seekable_can_seek (G_SEEKABLE (stream)))
|
if (G_IS_SEEKABLE (stream) && g_seekable_can_seek (G_SEEKABLE (stream)))
|
||||||
{
|
{
|
||||||
|
GSeekable *seekable = G_SEEKABLE (stream);
|
||||||
|
goffset start, end;
|
||||||
|
gboolean success;
|
||||||
|
|
||||||
|
/* g_seekable_seek() may try to set pending itself */
|
||||||
|
stream->priv->pending = FALSE;
|
||||||
|
|
||||||
|
start = g_seekable_tell (seekable);
|
||||||
|
|
||||||
if (g_seekable_seek (G_SEEKABLE (stream),
|
if (g_seekable_seek (G_SEEKABLE (stream),
|
||||||
count,
|
0,
|
||||||
G_SEEK_CUR,
|
G_SEEK_END,
|
||||||
cancellable,
|
cancellable,
|
||||||
NULL))
|
NULL))
|
||||||
return count;
|
{
|
||||||
|
end = g_seekable_tell (seekable);
|
||||||
|
g_assert (end >= start);
|
||||||
|
if (start > G_MAXSIZE - count || start + count > end)
|
||||||
|
{
|
||||||
|
stream->priv->pending = TRUE;
|
||||||
|
return end - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
success = g_seekable_seek (G_SEEKABLE (stream),
|
||||||
|
start + count,
|
||||||
|
G_SEEK_SET,
|
||||||
|
cancellable,
|
||||||
|
error);
|
||||||
|
stream->priv->pending = TRUE;
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
return count;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If not seekable, or seek failed, fall back to reading data: */
|
/* If not seekable, or seek failed, fall back to reading data: */
|
||||||
|
@ -68,10 +68,6 @@ static gssize g_local_file_input_stream_read (GInputStream *strea
|
|||||||
gsize count,
|
gsize count,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error);
|
GError **error);
|
||||||
static gssize g_local_file_input_stream_skip (GInputStream *stream,
|
|
||||||
gsize count,
|
|
||||||
GCancellable *cancellable,
|
|
||||||
GError **error);
|
|
||||||
static gboolean g_local_file_input_stream_close (GInputStream *stream,
|
static gboolean g_local_file_input_stream_close (GInputStream *stream,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error);
|
GError **error);
|
||||||
@ -104,7 +100,6 @@ g_local_file_input_stream_class_init (GLocalFileInputStreamClass *klass)
|
|||||||
GFileInputStreamClass *file_stream_class = G_FILE_INPUT_STREAM_CLASS (klass);
|
GFileInputStreamClass *file_stream_class = G_FILE_INPUT_STREAM_CLASS (klass);
|
||||||
|
|
||||||
stream_class->read_fn = g_local_file_input_stream_read;
|
stream_class->read_fn = g_local_file_input_stream_read;
|
||||||
stream_class->skip = g_local_file_input_stream_skip;
|
|
||||||
stream_class->close_fn = g_local_file_input_stream_close;
|
stream_class->close_fn = g_local_file_input_stream_close;
|
||||||
file_stream_class->tell = g_local_file_input_stream_tell;
|
file_stream_class->tell = g_local_file_input_stream_tell;
|
||||||
file_stream_class->can_seek = g_local_file_input_stream_can_seek;
|
file_stream_class->can_seek = g_local_file_input_stream_can_seek;
|
||||||
@ -175,62 +170,6 @@ g_local_file_input_stream_read (GInputStream *stream,
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gssize
|
|
||||||
g_local_file_input_stream_skip (GInputStream *stream,
|
|
||||||
gsize count,
|
|
||||||
GCancellable *cancellable,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
off_t start, end;
|
|
||||||
GLocalFileInputStream *file;
|
|
||||||
|
|
||||||
file = G_LOCAL_FILE_INPUT_STREAM (stream);
|
|
||||||
|
|
||||||
if (g_cancellable_set_error_if_cancelled (cancellable, error))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
start = lseek (file->priv->fd, 0, SEEK_CUR);
|
|
||||||
if (start == -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
end = lseek (file->priv->fd, 0, SEEK_END);
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
||||||
g_local_file_input_stream_close (GInputStream *stream,
|
g_local_file_input_stream_close (GInputStream *stream,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user