diff --git a/lrzip_private.h b/lrzip_private.h index 3dcb939..0778c89 100644 --- a/lrzip_private.h +++ b/lrzip_private.h @@ -337,6 +337,10 @@ struct rzip_control { const char *util_infile; char delete_infile; const char *util_outfile; +#define STREAM_BUCKET_SIZE 20 + size_t sinfo_buckets; + size_t sinfo_idx; + struct stream_info **sinfo_queue; char delete_outfile; FILE *outputfile; char library_mode : 1; diff --git a/rzip.c b/rzip.c index 9a3a00e..ad7419c 100644 --- a/rzip.c +++ b/rzip.c @@ -1117,9 +1117,18 @@ retry: void rzip_control_free(rzip_control *control) { - if (!control) return; + size_t x; + if (!control) return; - free(control->tmpdir); - if (control->suffix && control->suffix[0]) free(control->suffix); - free(control); + free(control->tmpdir); + free(control->outname); + free(control->outdir); + if (control->suffix && control->suffix[0]) free(control->suffix); + + for (x = 0; x < control->sinfo_idx; x++) { + free(control->sinfo_queue[x]->s); + free(control->sinfo_queue[x]); + } + free(control->sinfo_queue); + free(control); } diff --git a/stream.c b/stream.c index c946bfa..2153c27 100644 --- a/stream.c +++ b/stream.c @@ -1797,11 +1797,28 @@ int close_stream_out(rzip_control *control, void *ss) for (i = 0; i < sinfo->num_streams; i++) rewrite_encrypted(control, sinfo, sinfo->s[i].last_headofs); } + if (control->library_mode) { + if (!control->sinfo_buckets) { + /* no streams added */ + control->sinfo_queue = calloc(STREAM_BUCKET_SIZE + 1, sizeof(void*)); + if (!control->sinfo_queue) return -1; + control->sinfo_buckets++; + } else if (control->sinfo_idx == STREAM_BUCKET_SIZE * control->sinfo_buckets + 1) { + /* all buckets full, create new bucket */ + void *tmp; + tmp = realloc(control->sinfo_queue, (++control->sinfo_buckets * STREAM_BUCKET_SIZE + 1) * sizeof(void*)); + if (!tmp) return -1; + control->sinfo_queue = tmp; + memset(control->sinfo_queue + control->sinfo_idx, 0, ((control->sinfo_buckets * STREAM_BUCKET_SIZE + 1) - control->sinfo_idx) * sizeof(void*)); + } + control->sinfo_queue[control->sinfo_idx++] = sinfo; + } #if 0 - /* These cannot be freed because their values are read after the next - * stream has started so they're not properly freed and just dropped on - * program exit! FIXME */ + /* These cannot be freed immediately because their values are read after the next + * stream has started. Instead (in library mode), they are stored and only freed + * after the entire operation has completed. + */ free(sinfo->s); free(sinfo); #endif