Commit d81a3e23 authored by Moritz Grimm's avatar Moritz Grimm
Browse files

Add configuration migration tool

parent 5287bbdd
......@@ -9,11 +9,13 @@ Changes in 1.0.0, released on XXXX-XX-XX:
file settings have been added accordingly.
* The real-time status information is now enabled explicitly with the new
command line option -r.
* The configuration file structure has changed.
* TagLib (its C wrapper library) is now a mandatory dependency
* Support the new '@b@' placeholder for separate album metadata.
* The command line option -p has been added, causing ezstream to write a
locked PID file to a given location
* The configuration file structure has changed significantly. A configuration
migration tool (ezstream-cfgmigrate) has been added to assist in the
upgrade.
Changes in 0.6.0, released on 2015-01-18:
......
......@@ -212,6 +212,7 @@ AC_CONFIG_FILES([
build-aux/Makefile
compat/Makefile
doc/Makefile
doc/ezstream-cfgmigrate.1.in
doc/ezstream-file.sh.1.in
doc/ezstream.1.in
examples/Makefile
......
AUTOMAKE_OPTIONS = 1.10 foreign subdir-objects
man_MANS = ezstream.1 ezstream-file.sh.1
man_MANS = ezstream.1 ezstream-cfgmigrate.1 ezstream-file.sh.1
do_subst = sed \
-e 's|!!EXAMPLES_DIR!!|@EXAMPLES_DIR@|g'
......@@ -10,6 +10,9 @@ do_subst = sed \
ezstream.1: ezstream.1.in Makefile
$(do_subst) < $(builddir)/ezstream.1.in > ezstream.1
ezstream-cfgmigrate.1: ezstream-cfgmigrate.1.in Makefile
$(do_subst) < $(builddir)/ezstream-cfgmigrate.1.in > ezstream-cfgmigrate.1
ezstream-file.sh.1: ezstream-file.sh.1.in Makefile
$(do_subst) < $(builddir)/ezstream-file.sh.1.in > ezstream-file.sh.1
......
.\" Copyright (c) 2018 Moritz Grimm <mgrimm@mrsserver.net>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd @BUILD_DATE@
.Dt EZSTREAM-CFGMIGRATE 1
.Os @PACKAGE_NAME@ @PACKAGE_VERSION@
.Sh NAME
.Nm ezstream-cfgmigrate
.Nd migrate old ezstream configuration
.Sh SYNOPSIS
.Nm
.Bk -words
.Op Fl hv
.Fl 0 Ar v0-cfgfile
.Ek
.Sh DESCRIPTION
The
.Nm
utility reads configuration files from older versions of
.Nm ezstream
and prints its current equivalent to standard output.
.Pp
It supports reading XML configuration from
.Nm ezstream
version 0.x
.Pq zero .
.Ss Command line arguments
.Bl -tag -width Ds
.It Fl 0 Ar v0-cfgfile
.Pq The number zero.
.Pp
Read the XML configuration in
.Ar v0-cfgfile
and print its migrated content to standard output.
.It Fl h
Print a summary of available command line arguments with short descriptions
and exit.
.It Fl v
Increase logging verbosity.
May be used up to three times to also include debug logging output.
.El
.Sh SEE ALSO
.Xr ezstream 1 ,
.Xr ezstream-file.sh 1
.Sh AUTHORS
.An -nosplit
The
.Nm
program and this manual were written by
.An Moritz Grimm .
......@@ -114,7 +114,8 @@ Directory containing example configuration files for various uses of
as well as example playlist and metadata scripts.
.El
.Sh SEE ALSO
.Xr ezstream 1
.Xr ezstream 1 ,
.Xr ezstream-cfgmigrate 1
.Sh AUTHORS
.An -nosplit
The
......
......@@ -829,6 +829,7 @@ Directory containing example configuration files for various uses of
as well as example playlist and metadata scripts.
.El
.Sh SEE ALSO
.Xr ezstream-cfgmigrate 1 ,
.Xr ezstream-file.sh 1
.Sh AUTHORS
.Nm
......
......@@ -10,8 +10,9 @@ noinst_HEADERS = \
cfg_private.h \
cfg_server.h \
cfg_stream.h \
cfg_xmlfile.h \
cfgfile_xml.h \
cmdline.h \
ezconfig0.h \
ezstream.h \
log.h \
mdata.h \
......@@ -21,18 +22,18 @@ noinst_HEADERS = \
xalloc.h
libcommon_la_SOURCES = \
log.c \
util.c \
xalloc.c
libezstream_la_SOURCES = \
cfg.c \
cfg_decoder.c \
cfg_encoder.c \
cfg_intake.c \
cfg_server.c \
cfg_stream.c \
cfg_xmlfile.c \
cfgfile_xml.c \
log.c \
util.c \
xalloc.c
libezstream_la_SOURCES = \
cmdline.c \
mdata.c \
playlist.c \
......@@ -44,12 +45,19 @@ libezstream_la_LIBADD = @EZ_LIBS@ \
$(libezstream_la_DEPENDENCIES)
bin_SCRIPTS = ezstream-file.sh
bin_PROGRAMS = ezstream
bin_PROGRAMS = ezstream ezstream-cfgmigrate
ezstream_SOURCES = ezstream.c
ezstream_DEPENDENCIES = libezstream.la
ezstream_LDADD = $(ezstream_DEPENDENCIES)
ezstream_cfgmigrate_SOURCES = ezstream-cfgmigrate.c ezconfig0.c
ezstream_cfgmigrate_DEPENDENCIES = \
$(builddir)/libcommon.la \
$(top_builddir)/compat/libcompat.la
ezstream_cfgmigrate_LDADD = @EZ_LIBS@ \
$(ezstream_cfgmigrate_DEPENDENCIES)
AM_CPPFLAGS = @EZ_CPPFLAGS@ -I$(top_srcdir)/compat
AM_CFLAGS = @EZ_CFLAGS@
AM_LDFLAGS = @EZ_LDFLAGS@ -avoid-version
......
......@@ -27,7 +27,7 @@
#include <string.h>
#include "cfg_private.h"
#include "cfg_xmlfile.h"
#include "cfgfile_xml.h"
#include "log.h"
#include "xalloc.h"
......@@ -73,7 +73,7 @@ _cfg_load(void)
{
switch (cfg_program.config_type) {
case CFG_TYPE_XMLFILE:
if (0 > cfg_xmlfile_parse(cfg_program.config_file))
if (0 > cfgfile_xml_parse(cfg_program.config_file))
return (-1);
break;
default:
......
......@@ -54,7 +54,7 @@ cfg_decoder_list_create(void)
}
void
cfg_decoder_list_destroy(cfg_decoder_list_t *dl_p)
cfg_decoder_list_destroy(struct cfg_decoder_list **dl_p)
{
struct cfg_decoder_list *dl = *dl_p;
struct cfg_decoder *d;
......@@ -62,15 +62,26 @@ cfg_decoder_list_destroy(cfg_decoder_list_t *dl_p)
if (!dl)
return;
while (NULL != (d = TAILQ_FIRST(dl))) {
TAILQ_REMOVE(dl, d, entry);
cfg_decoder_destroy(&d);
}
while (NULL != (d = TAILQ_FIRST(dl)))
cfg_decoder_list_remove(dl, &d);
xfree(dl);
*dl_p = NULL;
}
unsigned int
cfg_decoder_list_nentries(struct cfg_decoder_list *dl)
{
struct cfg_decoder *d;
unsigned int n = 0;
TAILQ_FOREACH(d, dl, entry) {
n++;
}
return (n);
}
struct cfg_decoder *
cfg_decoder_list_find(struct cfg_decoder_list *dl, const char *name)
{
......@@ -115,6 +126,24 @@ cfg_decoder_list_get(struct cfg_decoder_list *dl, const char *name)
return (d);
}
void
cfg_decoder_list_remove(struct cfg_decoder_list *dl, struct cfg_decoder **d_p)
{
TAILQ_REMOVE(dl, *d_p, entry);
cfg_decoder_destroy(d_p);
}
void
cfg_decoder_list_foreach(struct cfg_decoder_list *dl,
void (*cb)(cfg_decoder_t, void *), void *cb_arg)
{
struct cfg_decoder *d;
TAILQ_FOREACH(d, dl, entry) {
cb(d, cb_arg);
}
}
struct cfg_decoder *
cfg_decoder_create(const char *name)
{
......@@ -271,6 +300,17 @@ cfg_decoder_extsupport(struct cfg_decoder *d, const char *ext)
return (0);
}
void
cfg_decoder_ext_foreach(struct cfg_decoder *d,
void (*cb)(const char *, void *), void *cb_arg)
{
struct file_ext *e;
TAILQ_FOREACH(e, &d->exts, entry) {
cb(e->ext, cb_arg);
}
}
const char *
cfg_decoder_get_name(struct cfg_decoder *d)
{
......
......@@ -23,6 +23,8 @@ typedef struct cfg_decoder_list * cfg_decoder_list_t;
cfg_decoder_list_t
cfg_decoder_list_create(void);
void cfg_decoder_list_destroy(cfg_decoder_list_t *);
unsigned int
cfg_decoder_list_nentries(cfg_decoder_list_t);
cfg_decoder_t
cfg_decoder_list_find(cfg_decoder_list_t, const char *);
......@@ -30,6 +32,9 @@ cfg_decoder_t
cfg_decoder_list_findext(cfg_decoder_list_t, const char *);
cfg_decoder_t
cfg_decoder_list_get(cfg_decoder_list_t, const char *);
void cfg_decoder_list_remove(cfg_decoder_list_t, cfg_decoder_t *);
void cfg_decoder_list_foreach(cfg_decoder_list_t, void (*)(cfg_decoder_t,
void *), void *);
cfg_decoder_t
cfg_decoder_create(const char *);
......@@ -45,6 +50,8 @@ int cfg_decoder_add_match(cfg_decoder_t, cfg_decoder_list_t, const char *,
int cfg_decoder_validate(cfg_decoder_t, const char **);
int cfg_decoder_extsupport(cfg_decoder_t, const char *);
void cfg_decoder_ext_foreach(cfg_decoder_t, void (*)(const char *, void *),
void *);
const char *
cfg_decoder_get_name(cfg_decoder_t);
......
......@@ -48,7 +48,7 @@ cfg_encoder_list_create(void)
}
void
cfg_encoder_list_destroy(cfg_encoder_list_t *el_p)
cfg_encoder_list_destroy(struct cfg_encoder_list **el_p)
{
struct cfg_encoder_list *el = *el_p;
struct cfg_encoder *e;
......@@ -56,15 +56,26 @@ cfg_encoder_list_destroy(cfg_encoder_list_t *el_p)
if (!el)
return;
while (NULL != (e = TAILQ_FIRST(el))) {
TAILQ_REMOVE(el, e, entry);
cfg_encoder_destroy(&e);
}
while (NULL != (e = TAILQ_FIRST(el)))
cfg_encoder_list_remove(el, &e);
xfree(el);
*el_p = NULL;
}
unsigned int
cfg_encoder_list_nentries(struct cfg_encoder_list *el)
{
struct cfg_encoder *e;
unsigned int n = 0;
TAILQ_FOREACH(e, el, entry) {
n++;
}
return (n);
}
struct cfg_encoder *
cfg_encoder_list_find(struct cfg_encoder_list *el, const char *name)
{
......@@ -95,6 +106,24 @@ cfg_encoder_list_get(struct cfg_encoder_list *el, const char *name)
return (e);
}
void
cfg_encoder_list_foreach(struct cfg_encoder_list *el,
void (*cb)(cfg_encoder_t, void *), void *cb_arg)
{
struct cfg_encoder *e;
TAILQ_FOREACH(e, el, entry) {
cb(e, cb_arg);
}
}
void
cfg_encoder_list_remove(struct cfg_encoder_list *el, struct cfg_encoder **e_p)
{
TAILQ_REMOVE(el, *e_p, entry);
cfg_encoder_destroy(e_p);
}
struct cfg_encoder *
cfg_encoder_create(const char *name)
{
......
......@@ -25,11 +25,16 @@ typedef struct cfg_encoder_list * cfg_encoder_list_t;
cfg_encoder_list_t
cfg_encoder_list_create(void);
void cfg_encoder_list_destroy(cfg_encoder_list_t *);
unsigned int
cfg_encoder_list_nentries(cfg_encoder_list_t);
cfg_encoder_t
cfg_encoder_list_find(cfg_encoder_list_t, const char *);
cfg_encoder_t
cfg_encoder_list_get(cfg_encoder_list_t, const char *);
void cfg_encoder_list_remove(cfg_encoder_list_t, cfg_encoder_t *o);
void cfg_encoder_list_foreach(cfg_encoder_list_t, void (*)(cfg_encoder_t,
void *), void *);
cfg_encoder_t
cfg_encoder_create(const char *);
......
......@@ -68,6 +68,19 @@ cfg_intake_list_destroy(cfg_intake_list_t *il_p)
*il_p = NULL;
}
unsigned int
cfg_intake_list_nentries(struct cfg_intake_list *il)
{
struct cfg_intake *i;
unsigned int n = 0;
TAILQ_FOREACH(i, il, entry) {
n++;
}
return (n);
}
struct cfg_intake *
cfg_intake_list_find(struct cfg_intake_list *il, const char *name)
{
......@@ -98,6 +111,17 @@ cfg_intake_list_get(struct cfg_intake_list *il, const char *name)
return (i);
}
void
cfg_intake_list_foreach(struct cfg_intake_list *il,
void (*cb)(cfg_intake_t, void *), void *cb_arg)
{
struct cfg_intake *i;
TAILQ_FOREACH(i, il, entry) {
cb(i, cb_arg);
}
}
struct cfg_intake *
cfg_intake_create(const char *name)
{
......@@ -228,6 +252,24 @@ cfg_intake_get_type(struct cfg_intake *i)
return (i->type);
}
const char *
cfg_intake_get_type_str(struct cfg_intake *i)
{
switch (i->type) {
case CFG_INTAKE_FILE:
return ("file");
case CFG_INTAKE_PLAYLIST:
return ("playlist");
case CFG_INTAKE_PROGRAM:
return ("program");
case CFG_INTAKE_STDIN:
return ("stdin");
case CFG_INTAKE_AUTODETECT:
default:
return ("autodetect");
}
}
const char *
cfg_intake_get_filename(struct cfg_intake *i)
{
......
......@@ -33,11 +33,15 @@ typedef struct cfg_intake_list * cfg_intake_list_t;
cfg_intake_list_t
cfg_intake_list_create(void);
void cfg_intake_list_destroy(cfg_intake_list_t *);
unsigned int
cfg_intake_list_nentries(cfg_intake_list_t);
cfg_intake_t
cfg_intake_list_find(cfg_intake_list_t, const char *);
cfg_intake_t
cfg_intake_list_get(cfg_intake_list_t, const char *);
void cfg_intake_list_foreach(cfg_intake_list_t, void (*)(cfg_intake_t,
void *), void *);
cfg_intake_t
cfg_intake_create(const char *);
......@@ -60,6 +64,8 @@ const char *
cfg_intake_get_name(cfg_intake_t);
enum cfg_intake_type
cfg_intake_get_type(cfg_intake_t);
const char *
cfg_intake_get_type_str(cfg_intake_t);
const char *
cfg_intake_get_filename(cfg_intake_t);
int cfg_intake_get_shuffle(cfg_intake_t);
......
......@@ -30,9 +30,6 @@
#define UCREDS_SIZE 256
#define CSUITE_SIZE 2048
#define DEFAULT_PORT 8000
#define DEFAULT_USER "source"
struct cfg_program {
char name[PATH_MAX];
enum cfg_config_type config_type;
......
......@@ -76,6 +76,19 @@ cfg_server_list_destroy(cfg_server_list_t *sl_p)
*sl_p = NULL;
}
unsigned int
cfg_server_list_nentries(struct cfg_server_list *sl)
{
struct cfg_server *s;
unsigned int n = 0;
TAILQ_FOREACH(s, sl, entry) {
n++;
}
return (n);
}
struct cfg_server *
cfg_server_list_find(struct cfg_server_list *sl, const char *name)
{
......@@ -106,6 +119,17 @@ cfg_server_list_get(struct cfg_server_list *sl, const char *name)
return (s);
}
void
cfg_server_list_foreach(struct cfg_server_list *sl,
void (*cb)(cfg_server_t, void *), void *cb_arg)
{
struct cfg_server *s;
TAILQ_FOREACH(s, sl, entry) {
cb(s, cb_arg);
}
}
struct cfg_server *
cfg_server_create(const char *name)
{
......@@ -355,13 +379,13 @@ cfg_server_get_hostname(struct cfg_server *s)
unsigned int
cfg_server_get_port(struct cfg_server *s)
{
return (s->port ? s->port : DEFAULT_PORT);
return (s->port ? s->port : CFG_SERVER_DEFAULT_PORT);
}
const char *
cfg_server_get_user(struct cfg_server *s)
{
return (s->user[0] ? s->user : DEFAULT_USER);
return (s->user[0] ? s->user : CFG_SERVER_DEFAULT_USER);
}
const char *
......@@ -376,6 +400,20 @@ cfg_server_get_tls(struct cfg_server *s)
return (s->tls);
}
const char *
cfg_server_get_tls_str(struct cfg_server *s)
{
switch (s->tls) {
case CFG_TLS_NONE:
return ("none");
case CFG_TLS_REQUIRED:
return ("required");
case CFG_TLS_MAY:
default:
return ("may");
}
}
const char *
cfg_server_get_tls_cipher_suite(struct cfg_server *s)
{
......
......@@ -17,6 +17,9 @@
#ifndef __CFG_SERVER_H__
#define __CFG_SERVER_H__
#define CFG_SERVER_DEFAULT_PORT 8000
#define CFG_SERVER_DEFAULT_USER "source"
enum cfg_server_protocol {
CFG_PROTO_HTTP = 0,
CFG_PROTO_HTTPS,
......@@ -38,11 +41,15 @@ typedef struct cfg_server_list * cfg_server_list_t;
cfg_server_list_t
cfg_server_list_create(void);
void cfg_server_list_destroy(cfg_server_list_t *);
unsigned int
cfg_server_list_nentries(cfg_server_list_t);
cfg_server_t
cfg_server_list_find(cfg_server_list_t, const char *);
cfg_server_t
cfg_server_list_get(cfg_server_list_t, const char *);
void cfg_server_list_foreach(cfg_server_list_t, void (*)(cfg_server_t,
void *), void *);
cfg_server_t
cfg_server_create(const char *);
......@@ -51,27 +58,27 @@ void cfg_server_destroy(cfg_server_t *);
int cfg_server_set_name(cfg_server_t, cfg_server_list_t, const char *,
const char **);
int cfg_server_set_protocol(cfg_server_t, cfg_server_list_t, const char *,
const char **);
const char **);
int cfg_server_set_hostname(cfg_server_t, cfg_server_list_t, const char *,
const char **);
const char **);
int cfg_server_set_port(cfg_server_t, cfg_server_list_t, const char *,
const char **);
const char **);
int cfg_server_set_user(cfg_server_t, cfg_server_list_t, const char *,
const char **);
const char **);
int cfg_server_set_password(cfg_server_t, cfg_server_list_t, const char *,
const char **);
const char **);
int cfg_server_set_tls(cfg_server_t, cfg_server_list_t, const char *,
const char **);
const char **);
int cfg_server_set_tls_cipher_suite(cfg_server_t, cfg_server_list_t,
const char *, const char **);
const char *, const char **);
int cfg_server_set_ca_dir(cfg_server_t, cfg_server_list_t, const char *,
const char **);
const char **);
int cfg_server_set_ca_file(cfg_server_t, cfg_server_list_t, const char *,
const char **);
const char **);
int cfg_server_set_client_cert(cfg_server_t, cfg_server_list_t,
const char *, const char **);
const char *, const char **);
int cfg_server_set_reconnect_attempts(cfg_server_t, cfg_server_list_t,
const char *, const char **);
const char *, const char **);
int cfg_server_validate(cfg_server_t, const char **);
......@@ -91,6 +98,8 @@ const char *
cfg_server_get_password(cfg_server_t);
enum cfg_server_tls
cfg_server_get_tls(cfg_server_t);
const char *
cfg_server_get_tls_str(cfg_server_t);
const char *
cfg_server_get_tls_cipher_suite(cfg_server_t);
const char *
......
......@@ -76,6 +76,19 @@ cfg_stream_list_destroy(cfg_stream_list_t *sl_p)