lib/commit: Use provided length when doing writes
This is prep for storage space checks, where we look at free space after parsing the metadata, before we write anything. We did length-limited writes in the fd-based input path, but not for the `GInputStream` path which in practice is used for HTTP pulls. Closes: #987 Approved by: jlebon
This commit is contained in:
parent
3348baf6eb
commit
8d4d638e99
|
|
@ -481,10 +481,27 @@ create_regular_tmpfile_linkable_with_content (OstreeRepo *self,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_autoptr(GOutputStream) temp_out = g_unix_output_stream_new (tmpf.fd, FALSE);
|
/* We used to do a g_output_stream_splice(), but there are two issues with that:
|
||||||
if (g_output_stream_splice (temp_out, input, 0,
|
* - We want to honor the size provided, to avoid malicious content that says it's
|
||||||
cancellable, error) < 0)
|
* e.g. 10 bytes but is actually gigabytes.
|
||||||
return FALSE;
|
* - Due to GLib bugs that pointlessly calls `poll()` on the output fd for every write
|
||||||
|
*/
|
||||||
|
char buf[8192];
|
||||||
|
guint64 remaining = length;
|
||||||
|
while (remaining > 0)
|
||||||
|
{
|
||||||
|
const gssize bytes_read =
|
||||||
|
g_input_stream_read (input, buf, MIN (remaining, sizeof (buf)), cancellable, error);
|
||||||
|
if (bytes_read < 0)
|
||||||
|
return FALSE;
|
||||||
|
else if (G_UNLIKELY (bytes_read == 0 && remaining > 0))
|
||||||
|
return glnx_throw (error, "Unexpected EOF with %" G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT " bytes remaining", remaining, length);
|
||||||
|
else if (bytes_read == 0)
|
||||||
|
break;
|
||||||
|
if (glnx_loop_write (tmpf.fd, buf, bytes_read) < 0)
|
||||||
|
return glnx_throw_errno_prefix (error, "write");
|
||||||
|
remaining -= bytes_read;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fchmod (tmpf.fd, 0644) < 0)
|
if (fchmod (tmpf.fd, 0644) < 0)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue