|
|
|
|
@ -522,12 +522,15 @@ static bool output_config(sink_t *sink, output_t *output, const format_t *reques
|
|
|
|
|
|
|
|
|
|
static void content_free(content_t *s) {
|
|
|
|
|
g_string_free(s->s, TRUE);
|
|
|
|
|
g_free(s->name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static content_t *output_make_content(GString *s) {
|
|
|
|
|
static content_t *output_make_content(GString *s, output_t *output) {
|
|
|
|
|
content_t *ret = obj_alloc0(content_t, content_free);
|
|
|
|
|
ret->s = s;
|
|
|
|
|
if (output->file_name && output->file_name[0])
|
|
|
|
|
ret->name = g_strdup(output->file_name);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -557,12 +560,63 @@ content_t *output_get_content(output_t *output) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
output->content = output_make_content(content);
|
|
|
|
|
output->content = output_make_content(content, output);
|
|
|
|
|
|
|
|
|
|
return obj_get(output->content);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC(FILE, fclose)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void output_content_failure(content_t *c) {
|
|
|
|
|
unsigned int exp = 0;
|
|
|
|
|
if (!atomic_compare_exchange(&c->failed, &exp, 1))
|
|
|
|
|
return; // already done
|
|
|
|
|
|
|
|
|
|
// find output file name
|
|
|
|
|
const char *prefix;
|
|
|
|
|
char buf[33];
|
|
|
|
|
if (c->name)
|
|
|
|
|
prefix = c->name;
|
|
|
|
|
else {
|
|
|
|
|
rand_hex_str(buf, 16);
|
|
|
|
|
prefix = buf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_autoptr(char) fn = g_strdup_printf("%s/backup-%s", output_dir, prefix);
|
|
|
|
|
|
|
|
|
|
if (g_file_test(fn, G_FILE_TEST_EXISTS)) {
|
|
|
|
|
char suffix[17];
|
|
|
|
|
rand_hex_str(suffix, 8);
|
|
|
|
|
g_free(fn);
|
|
|
|
|
fn = g_strdup_printf("%s/backup-%s%s", output_dir, prefix, suffix);
|
|
|
|
|
if (g_file_test(fn, G_FILE_TEST_EXISTS)) {
|
|
|
|
|
ilog(LOG_ERR, "Failed to write emergency backup to '%s': file exists",
|
|
|
|
|
fn);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_autoptr(FILE) fp = fopen(fn, "wb");
|
|
|
|
|
if (!fp) {
|
|
|
|
|
ilog(LOG_ERR, "Failed to write emergency backup to '%s': %s",
|
|
|
|
|
fn, strerror(errno));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ssize_t written = fwrite(c->s->str, 1, c->s->len, fp);
|
|
|
|
|
if (written < 0)
|
|
|
|
|
ilog(LOG_ERR, "Failed to write emergency backup to '%s': %s",
|
|
|
|
|
fn, strerror(errno));
|
|
|
|
|
else if (written != c->s->len)
|
|
|
|
|
ilog(LOG_ERR, "Failed to write emergency backup to '%s': short write",
|
|
|
|
|
fn);
|
|
|
|
|
else
|
|
|
|
|
ilog(LOG_NOTICE, "Wrote emergency backup to '%s'", fn);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static bool output_shutdown(output_t *output) {
|
|
|
|
|
if (!output)
|
|
|
|
|
return false;
|
|
|
|
|
@ -581,7 +635,7 @@ static bool output_shutdown(output_t *output) {
|
|
|
|
|
else if (output->membuf) {
|
|
|
|
|
if (output->membuf->len) {
|
|
|
|
|
obj_release(output->content);
|
|
|
|
|
output->content = output_make_content(output->membuf);
|
|
|
|
|
output->content = output_make_content(output->membuf, output);
|
|
|
|
|
output->membuf = NULL;
|
|
|
|
|
ret = true;
|
|
|
|
|
}
|
|
|
|
|
|