diff --git a/stream/stream.c b/stream/stream.c index ad79b2aa34..5cca42e2a4 100644 --- a/stream/stream.c +++ b/stream/stream.c @@ -354,6 +354,7 @@ static int stream_create_instance(const stream_info_t *sinfo, s->path = talloc_strdup(s, path); s->mode = flags & (STREAM_READ | STREAM_WRITE); s->requested_buffer_size = opts->buffer_size; + s->allow_partial_read = flags & STREAM_ALLOW_PARTIAL_READ; if (flags & STREAM_LESS_NOISE) mp_msg_set_max_level(s->log, MSGL_WARN); @@ -802,7 +803,9 @@ int stream_skip_bom(struct stream *s) // Read the rest of the stream into memory (current pos to EOF), and return it. // talloc_ctx: used as talloc parent for the returned allocation // max_size: must be set to >0. If the file is larger than that, it is treated -// as error. This is a minor robustness measure. +// as error. This is a minor robustness measure. If the stream is +// created with STREAM_ALLOW_PARTIAL_READ flag, partial result up to +// max_size is returned instead. // returns: stream contents, or .start/.len set to NULL on error // If the file was empty, but no error happened, .start will be non-NULL and // .len will be 0. @@ -821,16 +824,22 @@ struct bstr stream_read_complete(struct stream *s, void *talloc_ctx, int padding = 1; char *buf = NULL; int64_t size = stream_get_size(s) - stream_tell(s); - if (size > max_size) + if (size > max_size && !s->allow_partial_read) return (struct bstr){NULL, 0}; if (size > 0) bufsize = size + padding; else bufsize = 1000; + if (s->allow_partial_read) + bufsize = MPMIN(bufsize, max_size + padding); while (1) { buf = talloc_realloc_size(talloc_ctx, buf, bufsize); int readsize = stream_read(s, buf + total_read, bufsize - total_read); total_read += readsize; + if (total_read >= max_size && s->allow_partial_read) { + total_read = max_size; + break; + } if (total_read < bufsize) break; if (bufsize > max_size) { diff --git a/stream/stream.h b/stream/stream.h index 9d68ca8e27..eb44e23a1f 100644 --- a/stream/stream.h +++ b/stream/stream.h @@ -38,21 +38,22 @@ // flags for stream_open_ext (this includes STREAM_READ and STREAM_WRITE) // stream->mode -#define STREAM_READ 0 -#define STREAM_WRITE (1 << 0) +#define STREAM_READ 0 +#define STREAM_WRITE (1 << 0) -#define STREAM_SILENT (1 << 1) +#define STREAM_SILENT (1 << 1) // Origin value for "security". This is an integer within the flags bit-field. -#define STREAM_ORIGIN_DIRECT (1 << 2) // passed from cmdline or loadfile -#define STREAM_ORIGIN_FS (2 << 2) // referenced from playlist on unix FS -#define STREAM_ORIGIN_NET (3 << 2) // referenced from playlist on network -#define STREAM_ORIGIN_UNSAFE (4 << 2) // from a grotesque source +#define STREAM_ORIGIN_DIRECT (1 << 2) // passed from cmdline or loadfile +#define STREAM_ORIGIN_FS (2 << 2) // referenced from playlist on unix FS +#define STREAM_ORIGIN_NET (3 << 2) // referenced from playlist on network +#define STREAM_ORIGIN_UNSAFE (4 << 2) // from a grotesque source -#define STREAM_ORIGIN_MASK (7 << 2) // for extracting origin value from flags +#define STREAM_ORIGIN_MASK (7 << 2) // for extracting origin value from flags -#define STREAM_LOCAL_FS_ONLY (1 << 5) // stream_file only, no URLs -#define STREAM_LESS_NOISE (1 << 6) // try to log errors only +#define STREAM_LOCAL_FS_ONLY (1 << 5) // stream_file only, no URLs +#define STREAM_LESS_NOISE (1 << 6) // try to log errors only +#define STREAM_ALLOW_PARTIAL_READ (1 << 7) // allows partial read with stream_read_file() // end flags for stream_open_ext (the naming convention sucks) @@ -155,6 +156,7 @@ typedef struct stream { bool is_local_fs : 1; // from the filesystem bool is_directory : 1; // directory on the filesystem bool access_references : 1; // open other streams + bool allow_partial_read : 1; // allows partial read with stream_read_file() struct mp_log *log; struct mpv_global *global;