stream: add STREAM_ALLOW_PARTIAL_READ flag

This allows stream_read_complete() to return partial result
instead of error if the file size is larger than the limit.
This commit is contained in:
nanahi
2024-10-21 01:03:22 -04:00
committed by Avi Halachmi
parent fad946d778
commit c2e71ceb07
2 changed files with 23 additions and 12 deletions

View File

@@ -354,6 +354,7 @@ static int stream_create_instance(const stream_info_t *sinfo,
s->path = talloc_strdup(s, path); s->path = talloc_strdup(s, path);
s->mode = flags & (STREAM_READ | STREAM_WRITE); s->mode = flags & (STREAM_READ | STREAM_WRITE);
s->requested_buffer_size = opts->buffer_size; s->requested_buffer_size = opts->buffer_size;
s->allow_partial_read = flags & STREAM_ALLOW_PARTIAL_READ;
if (flags & STREAM_LESS_NOISE) if (flags & STREAM_LESS_NOISE)
mp_msg_set_max_level(s->log, MSGL_WARN); 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. // 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 // 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 // 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 // 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 // If the file was empty, but no error happened, .start will be non-NULL and
// .len will be 0. // .len will be 0.
@@ -821,16 +824,22 @@ struct bstr stream_read_complete(struct stream *s, void *talloc_ctx,
int padding = 1; int padding = 1;
char *buf = NULL; char *buf = NULL;
int64_t size = stream_get_size(s) - stream_tell(s); 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}; return (struct bstr){NULL, 0};
if (size > 0) if (size > 0)
bufsize = size + padding; bufsize = size + padding;
else else
bufsize = 1000; bufsize = 1000;
if (s->allow_partial_read)
bufsize = MPMIN(bufsize, max_size + padding);
while (1) { while (1) {
buf = talloc_realloc_size(talloc_ctx, buf, bufsize); buf = talloc_realloc_size(talloc_ctx, buf, bufsize);
int readsize = stream_read(s, buf + total_read, bufsize - total_read); int readsize = stream_read(s, buf + total_read, bufsize - total_read);
total_read += readsize; total_read += readsize;
if (total_read >= max_size && s->allow_partial_read) {
total_read = max_size;
break;
}
if (total_read < bufsize) if (total_read < bufsize)
break; break;
if (bufsize > max_size) { if (bufsize > max_size) {

View File

@@ -38,21 +38,22 @@
// flags for stream_open_ext (this includes STREAM_READ and STREAM_WRITE) // flags for stream_open_ext (this includes STREAM_READ and STREAM_WRITE)
// stream->mode // stream->mode
#define STREAM_READ 0 #define STREAM_READ 0
#define STREAM_WRITE (1 << 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. // 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_DIRECT (1 << 2) // passed from cmdline or loadfile
#define STREAM_ORIGIN_FS (2 << 2) // referenced from playlist on unix FS #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_NET (3 << 2) // referenced from playlist on network
#define STREAM_ORIGIN_UNSAFE (4 << 2) // from a grotesque source #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_LOCAL_FS_ONLY (1 << 5) // stream_file only, no URLs
#define STREAM_LESS_NOISE (1 << 6) // try to log errors only #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) // 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_local_fs : 1; // from the filesystem
bool is_directory : 1; // directory on the filesystem bool is_directory : 1; // directory on the filesystem
bool access_references : 1; // open other streams bool access_references : 1; // open other streams
bool allow_partial_read : 1; // allows partial read with stream_read_file()
struct mp_log *log; struct mp_log *log;
struct mpv_global *global; struct mpv_global *global;