mirror of
https://github.com/owntone/owntone-server.git
synced 2024-12-27 15:45:56 -05:00
Make compdirs work again, closing ticket #15
This commit is contained in:
parent
a06fa36c21
commit
9a396eca29
324
src/conf.c
324
src/conf.c
@ -74,14 +74,16 @@ typedef struct _CONF_ELEMENTS {
|
||||
|
||||
/** Forwards */
|
||||
static int _conf_verify(LL_HANDLE pll);
|
||||
static LL_ITEM *_conf_fetch_item(LL_HANDLE pll, char *section, char *term);
|
||||
static int _conf_exists(LL_HANDLE pll, char *section, char *term);
|
||||
static LL_ITEM *_conf_fetch_item(LL_HANDLE pll, char *section, char *key);
|
||||
static int _conf_exists(LL_HANDLE pll, char *section, char *key);
|
||||
static void _conf_lock(void);
|
||||
static void _conf_unlock(void);
|
||||
static int _conf_write(FILE *fp, LL *pll, int sublevel, char *parent);
|
||||
static CONF_ELEMENTS *_conf_get_keyinfo(char *section, char *key);
|
||||
static int _conf_makedir(char *path, char *user);
|
||||
static int _conf_existdir(char *path);
|
||||
static int _conf_split(char *s, char *delimiters, char ***argvp);
|
||||
static void _conf_dispose_split(char **argv);
|
||||
|
||||
static CONF_ELEMENTS conf_elements[] = {
|
||||
{ 1, 0, CONF_T_STRING,"general","runas" },
|
||||
@ -130,7 +132,7 @@ int _conf_makedir(char *path,char *user) {
|
||||
|
||||
pathdup=strdup(path);
|
||||
if(!pathdup) {
|
||||
DPRINTF(E_FATAL,L_CONF,"Malloc error\n");
|
||||
DPRINTF(E_FATAL,L_CONF,"Malloc error\n");
|
||||
}
|
||||
|
||||
next_token=pathdup+1;
|
||||
@ -141,21 +143,21 @@ int _conf_makedir(char *path,char *user) {
|
||||
strcat(path_buffer,"/");
|
||||
strcat(path_buffer,token);
|
||||
|
||||
if(!_conf_existdir(path_buffer)) {
|
||||
/* FIXME: this is wrong -- it should really be 0700 owned by
|
||||
* the runas user. That would require some os_ indirection
|
||||
*/
|
||||
DPRINTF(E_DBG,L_CONF,"Making %s\n",path_buffer);
|
||||
if((mkdir(path_buffer,0700)) && (errno != EEXIST)) {
|
||||
free(pathdup);
|
||||
DPRINTF(E_LOG,L_CONF,"Could not make dirctory %s: %s\n",
|
||||
path_buffer,strerror(errno));
|
||||
return FALSE;
|
||||
}
|
||||
os_chown(path_buffer,user);
|
||||
}
|
||||
retval = TRUE;
|
||||
}
|
||||
if(!_conf_existdir(path_buffer)) {
|
||||
/* FIXME: this is wrong -- it should really be 0700 owned by
|
||||
* the runas user. That would require some os_ indirection
|
||||
*/
|
||||
DPRINTF(E_DBG,L_CONF,"Making %s\n",path_buffer);
|
||||
if((mkdir(path_buffer,0700)) && (errno != EEXIST)) {
|
||||
free(pathdup);
|
||||
DPRINTF(E_LOG,L_CONF,"Could not make dirctory %s: %s\n",
|
||||
path_buffer,strerror(errno));
|
||||
return FALSE;
|
||||
}
|
||||
os_chown(path_buffer,user);
|
||||
}
|
||||
retval = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
free(pathdup);
|
||||
@ -241,10 +243,10 @@ void _conf_unlock() {
|
||||
*
|
||||
* @param pll top level linked list to test (config tree)
|
||||
* @param section section to term (key) is in
|
||||
* @param term term/key to look for
|
||||
* @param key key to look for
|
||||
* @returns LL_ITEM of the key, or NULL
|
||||
*/
|
||||
LL_ITEM *_conf_fetch_item(LL_HANDLE pll, char *section, char *term) {
|
||||
LL_ITEM *_conf_fetch_item(LL_HANDLE pll, char *section, char *key) {
|
||||
LL_ITEM *psection;
|
||||
LL_ITEM *pitem;
|
||||
|
||||
@ -254,7 +256,7 @@ LL_ITEM *_conf_fetch_item(LL_HANDLE pll, char *section, char *term) {
|
||||
if(psection->type != LL_TYPE_LL)
|
||||
return NULL;
|
||||
|
||||
if(!(pitem = ll_fetch_item(psection->value.as_ll,term)))
|
||||
if(!(pitem = ll_fetch_item(psection->value.as_ll,key)))
|
||||
return NULL;
|
||||
|
||||
return pitem;
|
||||
@ -265,11 +267,11 @@ LL_ITEM *_conf_fetch_item(LL_HANDLE pll, char *section, char *term) {
|
||||
*
|
||||
* @param pll config tree to test
|
||||
* @param section section to find the term under
|
||||
* @param term key to search for under the specified section
|
||||
* @param key key to search for under the specified section
|
||||
* @returns TRUE if key exists, FALSE otherwise
|
||||
*/
|
||||
int _conf_exists(LL_HANDLE pll, char *section, char *term) {
|
||||
if(!_conf_fetch_item(pll,section,term))
|
||||
int _conf_exists(LL_HANDLE pll, char *section, char *key) {
|
||||
if(!_conf_fetch_item(pll,section,key))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
@ -312,37 +314,37 @@ int _conf_verify(LL_HANDLE pll) {
|
||||
}
|
||||
}
|
||||
if(pce->type == CONF_T_EXISTPATH) {
|
||||
/* first, need to resolve */
|
||||
/* first, need to resolve */
|
||||
pi = _conf_fetch_item(pll,pce->section, pce->term);
|
||||
if(pi) {
|
||||
memset(resolved_path,0,sizeof(resolved_path));
|
||||
if(pi->value.as_string) {
|
||||
DPRINTF(E_SPAM,L_CONF,"Found %s/%s as %s... checking\n",
|
||||
pce->section, pce->term, pi->value.as_string);
|
||||
DPRINTF(E_SPAM,L_CONF,"Found %s/%s as %s... checking\n",
|
||||
pce->section, pce->term, pi->value.as_string);
|
||||
|
||||
/* verify it exists, creating it if necessary */
|
||||
if(!_conf_existdir(pi->value.as_string)) {
|
||||
user = "nobody";
|
||||
ptemp = _conf_fetch_item(pll, "general", "runas");
|
||||
if(ptemp) {
|
||||
user = ptemp->value.as_string;
|
||||
}
|
||||
|
||||
if(!_conf_makedir(pi->value.as_string,user)) {
|
||||
is_valid=0;
|
||||
DPRINTF(E_LOG,L_CONF,"Can't make path %s, invalid config.\n",
|
||||
resolved_path);
|
||||
}
|
||||
}
|
||||
/* verify it exists, creating it if necessary */
|
||||
if(!_conf_existdir(pi->value.as_string)) {
|
||||
user = "nobody";
|
||||
ptemp = _conf_fetch_item(pll, "general", "runas");
|
||||
if(ptemp) {
|
||||
user = ptemp->value.as_string;
|
||||
}
|
||||
|
||||
if(_conf_existdir(pi->value.as_string)) {
|
||||
realpath(pi->value.as_string,resolved_path);
|
||||
free(pi->value.as_string);
|
||||
pi->value.as_string = strdup(resolved_path);
|
||||
if(!_conf_makedir(pi->value.as_string,user)) {
|
||||
is_valid=0;
|
||||
DPRINTF(E_LOG,L_CONF,"Can't make path %s, invalid config.\n",
|
||||
resolved_path);
|
||||
}
|
||||
}
|
||||
|
||||
DPRINTF(E_SPAM,L_CONF,"Resolved to %s\n",resolved_path);
|
||||
}
|
||||
}
|
||||
if(_conf_existdir(pi->value.as_string)) {
|
||||
realpath(pi->value.as_string,resolved_path);
|
||||
free(pi->value.as_string);
|
||||
pi->value.as_string = strdup(resolved_path);
|
||||
|
||||
DPRINTF(E_SPAM,L_CONF,"Resolved to %s\n",resolved_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pce++;
|
||||
@ -365,6 +367,7 @@ int conf_read(char *file) {
|
||||
FILE *fin;
|
||||
int err;
|
||||
LL_HANDLE pllnew, plltemp, pllcurrent, pllcomment;
|
||||
LL_ITEM *pli;
|
||||
char linebuffer[CONF_LINEBUFFER+1];
|
||||
char keybuffer[256];
|
||||
char *comment, *term, *value, *delim;
|
||||
@ -378,6 +381,8 @@ int conf_read(char *file) {
|
||||
int ws=0;
|
||||
CONF_ELEMENTS *pce;
|
||||
int key_type;
|
||||
char **valuearray;
|
||||
int index;
|
||||
|
||||
if(conf_main_file) {
|
||||
conf_close();
|
||||
@ -523,6 +528,30 @@ int conf_read(char *file) {
|
||||
|
||||
switch(key_type) {
|
||||
case CONF_T_MULTICOMMA:
|
||||
/* first, see if we already have a tree... */
|
||||
pli = ll_fetch_item(pllcurrent,term);
|
||||
if(!pli) {
|
||||
if((ll_create(&plltemp) != LL_E_SUCCESS)) {
|
||||
DPRINTF(E_FATAL,L_CONF,"Could not create "
|
||||
"linked list.\n");
|
||||
}
|
||||
ll_add_ll(pllcurrent,term,plltemp);
|
||||
ll_set_flags(plltemp,0); /* allow dups */
|
||||
} else {
|
||||
plltemp = pli->value.as_ll;
|
||||
}
|
||||
|
||||
/* got list, break comma sep and add */
|
||||
if(_conf_split(value,",",&valuearray) >= 0) {
|
||||
index = 0;
|
||||
while(valuearray[index]) {
|
||||
ll_add_string(plltemp,term,valuearray[index]);
|
||||
index++;
|
||||
}
|
||||
_conf_dispose_split(valuearray);
|
||||
} else {
|
||||
ll_add_string(plltemp,term,value);
|
||||
}
|
||||
break;
|
||||
case CONF_T_INT:
|
||||
case CONF_T_STRING:
|
||||
@ -730,18 +759,31 @@ int conf_get_string(char *section, char *key, char *dflt, char *out, int *size)
|
||||
* @returns a pointer to an allocated string containing the required
|
||||
* configuration key
|
||||
*/
|
||||
char *conf_alloc_string (char *section, char *key, char *dflt) {
|
||||
int size = -1;
|
||||
char *out;
|
||||
char *conf_alloc_string(char *section, char *key, char *dflt) {
|
||||
LL_ITEM *pitem;
|
||||
char *result;
|
||||
char *retval;
|
||||
|
||||
/* FIXME: races */
|
||||
conf_get_string(section, key, dflt, NULL, &size);
|
||||
out = (char *)malloc(size * sizeof(char));
|
||||
_conf_lock();
|
||||
pitem = _conf_fetch_item(conf_main,section,key);
|
||||
if((!pitem) || (pitem->type != LL_TYPE_STRING)) {
|
||||
result = dflt;
|
||||
} else {
|
||||
result = pitem->value.as_string;
|
||||
}
|
||||
|
||||
if(conf_get_string (section, key, dflt, out, &size) != CONF_E_SUCCESS)
|
||||
return NULL;
|
||||
if(result == NULL) {
|
||||
_conf_unlock();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return out;
|
||||
retval = strdup(result);
|
||||
|
||||
if(!retval) {
|
||||
DPRINTF(E_FATAL,L_CONF,"Malloc error in conf_alloc_string\n");
|
||||
}
|
||||
_conf_unlock();
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
@ -868,6 +910,8 @@ int conf_write(void) {
|
||||
int _conf_write(FILE *fp, LL *pll, int sublevel, char *parent) {
|
||||
LL_ITEM *pli;
|
||||
LL_ITEM *ppre, *pin;
|
||||
LL_ITEM *plitemp;
|
||||
|
||||
char keybuffer[256];
|
||||
|
||||
if(!pll)
|
||||
@ -896,8 +940,11 @@ int _conf_write(FILE *fp, LL *pll, int sublevel, char *parent) {
|
||||
switch(pli->type) {
|
||||
case LL_TYPE_LL:
|
||||
if(sublevel) {
|
||||
/* something wrong! */
|
||||
DPRINTF(E_LOG,L_CONF,"LL in sublevel: %s\n",pli->key);
|
||||
/* must be multivalued */
|
||||
plitemp = NULL;
|
||||
while((plitemp = ll_get_next(pli->value.as_ll,plitemp))) {
|
||||
fprintf(fp,"%s = %s\n",pli->key,plitemp->value.as_string);
|
||||
}
|
||||
} else {
|
||||
fprintf(fp,"[%s]",pli->key);
|
||||
if(pin) {
|
||||
@ -978,6 +1025,7 @@ int _conf_split(char *s, char *delimiters, char ***argvp) {
|
||||
const char *snew;
|
||||
char *t;
|
||||
char *tokptr;
|
||||
char *tmp;
|
||||
|
||||
if ((s == NULL) || (delimiters == NULL) || (argvp == NULL))
|
||||
return -1;
|
||||
@ -989,8 +1037,13 @@ int _conf_split(char *s, char *delimiters, char ***argvp) {
|
||||
strcpy(t, snew);
|
||||
numtokens = 0;
|
||||
tokptr = NULL;
|
||||
while(strtok_r(t,delimiters,&tokptr) != NULL)
|
||||
tmp = t;
|
||||
while(strtok_r(tmp,delimiters,&tokptr) != NULL) {
|
||||
tmp=NULL;
|
||||
numtokens++;
|
||||
}
|
||||
|
||||
DPRINTF(E_DBG,L_CONF,"Found %d tokens in %s\n",numtokens,s);
|
||||
|
||||
if ((*argvp = malloc((numtokens + 1)*sizeof(char *))) == NULL) {
|
||||
free(t);
|
||||
@ -1002,10 +1055,157 @@ int _conf_split(char *s, char *delimiters, char ***argvp) {
|
||||
else {
|
||||
strcpy(t, snew);
|
||||
tokptr = NULL;
|
||||
for (i = 0; i < numtokens; i++)
|
||||
*((*argvp) + i) = strtok_r(t, delimiters, &tokptr);
|
||||
tmp = t;
|
||||
for (i = 0; i < numtokens; i++) {
|
||||
*((*argvp) + i) = strtok_r(tmp, delimiters, &tokptr);
|
||||
tmp=NULL;
|
||||
DPRINTF(E_DBG,L_CONF,"Token %d: %s\n",i+1,(*argvp)[i]);
|
||||
}
|
||||
}
|
||||
|
||||
*((*argvp) + numtokens) = NULL;
|
||||
return numtokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* implode a multivalued term in a perl sense.
|
||||
*
|
||||
* @param section section of term to implode
|
||||
* @param key key of term to implode
|
||||
* @pararm delimiter what to "glue" them with
|
||||
* @returns imploded string (preallocated), or NULL
|
||||
*/
|
||||
char *conf_implode(char *section, char *key, char *delimiter) {
|
||||
LL_ITEM *pitem;
|
||||
LL_ITEM *penum;
|
||||
int count;
|
||||
int len;
|
||||
char *retval;
|
||||
|
||||
_conf_lock();
|
||||
pitem = _conf_fetch_item(conf_main,section,key);
|
||||
if((!pitem) || (pitem->type != LL_TYPE_LL)) {
|
||||
_conf_unlock();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* otherwise, alloc a string and go */
|
||||
count = len = 0;
|
||||
penum = NULL;
|
||||
while((penum = ll_get_next(pitem->value.as_ll,penum))) {
|
||||
if(penum->type != LL_TYPE_STRING) {
|
||||
DPRINTF(E_FATAL,L_CONF,"multivalued property not a string?\n");
|
||||
}
|
||||
len += strlen(penum->value.as_string);
|
||||
count++;
|
||||
}
|
||||
|
||||
if(!count) {
|
||||
_conf_unlock();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
len += (strlen(delimiter) * (count-1));
|
||||
retval = (char*)malloc(len + 1);
|
||||
if(!retval) {
|
||||
DPRINTF(E_FATAL,L_CONF,"conf_implode: malloc\n");
|
||||
}
|
||||
|
||||
memset(retval,0,len+1);
|
||||
penum = NULL;
|
||||
while((penum = ll_get_next(pitem->value.as_ll,penum))) {
|
||||
strcat(retval,penum->value.as_string);
|
||||
if(--count) {
|
||||
strcat(retval,delimiter);
|
||||
}
|
||||
}
|
||||
|
||||
_conf_unlock();
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* dispose of the argv set that was created in _conf_split
|
||||
*
|
||||
* @param argv string array to delete
|
||||
*/
|
||||
void _conf_dispose_split(char **argv) {
|
||||
if(!argv)
|
||||
return;
|
||||
|
||||
if(argv[0])
|
||||
free(argv[0]);
|
||||
|
||||
free(argv);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* return a multi-valued item as an array (values)
|
||||
*
|
||||
* @param section section to fetch
|
||||
* @param key multivalued key to get from array
|
||||
* @returns TRUE on success, FALSE on failure
|
||||
*/
|
||||
int conf_get_array(char *section, char *key, char ***argvp) {
|
||||
LL_ITEM *pitem, *penum;
|
||||
int count;
|
||||
int len;
|
||||
|
||||
_conf_lock();
|
||||
pitem = _conf_fetch_item(conf_main,section,key);
|
||||
if((!pitem) || (pitem->type != LL_TYPE_LL)) {
|
||||
_conf_unlock();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* otherwise, alloc a string and go */
|
||||
count = 0;
|
||||
penum = NULL;
|
||||
while((penum = ll_get_next(pitem->value.as_ll,penum))) {
|
||||
if(penum->type != LL_TYPE_STRING) {
|
||||
DPRINTF(E_FATAL,L_CONF,"multivalued property not a string?\n");
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
/* now we have a count, alloc an argv */
|
||||
len = (count+1) * sizeof(char*);
|
||||
*(argvp) = (char**)malloc(len);
|
||||
if(!*(argvp)) {
|
||||
DPRINTF(E_FATAL,L_CONF,"conf_get_array: malloc\n");
|
||||
}
|
||||
|
||||
memset(*(argvp),0,len);
|
||||
|
||||
count=0;
|
||||
penum=NULL;
|
||||
while((penum = ll_get_next(pitem->value.as_ll,penum))) {
|
||||
(*argvp)[count] = strdup(penum->value.as_string);
|
||||
if(!(*argvp)[count]) {
|
||||
DPRINTF(E_FATAL,L_CONF,"conf_get_array: malloc\n");
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
_conf_unlock();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* dispose of the array created above
|
||||
*
|
||||
* @param argv argv pointer created
|
||||
*/
|
||||
void conf_dispose_array(char **argv) {
|
||||
int index=0;
|
||||
|
||||
if(!argv)
|
||||
return;
|
||||
|
||||
|
||||
while(argv[index]) {
|
||||
free(argv[index]);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
@ -45,4 +45,7 @@ extern int conf_isset(char *section, char *key);
|
||||
extern int conf_iswritable(void);
|
||||
extern int conf_write(void);
|
||||
|
||||
extern char *conf_implode(char *section, char *key, char *delimiter);
|
||||
extern int conf_get_array(char *section, char *key, char ***argvp);
|
||||
extern void conf_dispose_array(char **argv);
|
||||
#endif /* _CONFIG_H_ */
|
||||
|
@ -261,22 +261,24 @@ int scan_init(char *path) {
|
||||
* check to see if a particular path is a complation path
|
||||
*
|
||||
* @param path path to check
|
||||
* @returns 1 if it is a compilation path, 0 otherwise
|
||||
* @returns TRUE if it is a compilation path, FALSE otherwise
|
||||
*/
|
||||
int scan_is_compdir(char *path) {
|
||||
#if 0
|
||||
int current=0;
|
||||
char **compdirs;
|
||||
|
||||
if(!config.complist)
|
||||
return 0;
|
||||
if(!conf_get_array("general","compdirs",&compdirs))
|
||||
return FALSE;
|
||||
|
||||
while(config.complist[current]) {
|
||||
if(strcasestr(path,config.complist[current]))
|
||||
return 1;
|
||||
while(compdirs[current]) {
|
||||
if(strcasestr(path,compdirs[current])) {
|
||||
conf_dispose_array(compdirs);
|
||||
return TRUE;
|
||||
}
|
||||
current++;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
conf_dispose_array(compdirs);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
@ -660,7 +662,7 @@ void make_composite_tags(MP3FILE *song) {
|
||||
|
||||
if(!song->artist) {
|
||||
if (song->orchestra && song->conductor) {
|
||||
len = (int)strlen(song->orchestra) +
|
||||
len = (int)strlen(song->orchestra) +
|
||||
(int)strlen(sep) +
|
||||
(int)strlen(song->conductor);
|
||||
ptmp = (char*)malloc(len + 1);
|
||||
@ -685,7 +687,7 @@ void make_composite_tags(MP3FILE *song) {
|
||||
sprintf(ptmp,"%s%s%s",song->artist, sep, song->title);
|
||||
free(song->title);
|
||||
song->title = ptmp;
|
||||
|
||||
|
||||
if(va_artist) {
|
||||
ptmp = strdup(va_artist);
|
||||
if(ptmp) {
|
||||
@ -695,7 +697,7 @@ void make_composite_tags(MP3FILE *song) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(song->url)
|
||||
song->data_kind=1;
|
||||
else
|
||||
|
Loading…
Reference in New Issue
Block a user