Make compdirs work again, closing ticket #15

This commit is contained in:
Ron Pedde 2006-03-26 22:07:33 +00:00
parent a06fa36c21
commit 9a396eca29
3 changed files with 279 additions and 74 deletions

View File

@ -74,14 +74,16 @@ typedef struct _CONF_ELEMENTS {
/** Forwards */ /** Forwards */
static int _conf_verify(LL_HANDLE pll); static int _conf_verify(LL_HANDLE pll);
static LL_ITEM *_conf_fetch_item(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 *term); static int _conf_exists(LL_HANDLE pll, char *section, char *key);
static void _conf_lock(void); static void _conf_lock(void);
static void _conf_unlock(void); static void _conf_unlock(void);
static int _conf_write(FILE *fp, LL *pll, int sublevel, char *parent); static int _conf_write(FILE *fp, LL *pll, int sublevel, char *parent);
static CONF_ELEMENTS *_conf_get_keyinfo(char *section, char *key); static CONF_ELEMENTS *_conf_get_keyinfo(char *section, char *key);
static int _conf_makedir(char *path, char *user); static int _conf_makedir(char *path, char *user);
static int _conf_existdir(char *path); 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[] = { static CONF_ELEMENTS conf_elements[] = {
{ 1, 0, CONF_T_STRING,"general","runas" }, { 1, 0, CONF_T_STRING,"general","runas" },
@ -130,7 +132,7 @@ int _conf_makedir(char *path,char *user) {
pathdup=strdup(path); pathdup=strdup(path);
if(!pathdup) { if(!pathdup) {
DPRINTF(E_FATAL,L_CONF,"Malloc error\n"); DPRINTF(E_FATAL,L_CONF,"Malloc error\n");
} }
next_token=pathdup+1; next_token=pathdup+1;
@ -141,21 +143,21 @@ int _conf_makedir(char *path,char *user) {
strcat(path_buffer,"/"); strcat(path_buffer,"/");
strcat(path_buffer,token); strcat(path_buffer,token);
if(!_conf_existdir(path_buffer)) { if(!_conf_existdir(path_buffer)) {
/* FIXME: this is wrong -- it should really be 0700 owned by /* FIXME: this is wrong -- it should really be 0700 owned by
* the runas user. That would require some os_ indirection * the runas user. That would require some os_ indirection
*/ */
DPRINTF(E_DBG,L_CONF,"Making %s\n",path_buffer); DPRINTF(E_DBG,L_CONF,"Making %s\n",path_buffer);
if((mkdir(path_buffer,0700)) && (errno != EEXIST)) { if((mkdir(path_buffer,0700)) && (errno != EEXIST)) {
free(pathdup); free(pathdup);
DPRINTF(E_LOG,L_CONF,"Could not make dirctory %s: %s\n", DPRINTF(E_LOG,L_CONF,"Could not make dirctory %s: %s\n",
path_buffer,strerror(errno)); path_buffer,strerror(errno));
return FALSE; return FALSE;
} }
os_chown(path_buffer,user); os_chown(path_buffer,user);
} }
retval = TRUE; retval = TRUE;
} }
} }
free(pathdup); free(pathdup);
@ -241,10 +243,10 @@ void _conf_unlock() {
* *
* @param pll top level linked list to test (config tree) * @param pll top level linked list to test (config tree)
* @param section section to term (key) is in * @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 * @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 *psection;
LL_ITEM *pitem; 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) if(psection->type != LL_TYPE_LL)
return NULL; 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 NULL;
return pitem; 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 pll config tree to test
* @param section section to find the term under * @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 * @returns TRUE if key exists, FALSE otherwise
*/ */
int _conf_exists(LL_HANDLE pll, char *section, char *term) { int _conf_exists(LL_HANDLE pll, char *section, char *key) {
if(!_conf_fetch_item(pll,section,term)) if(!_conf_fetch_item(pll,section,key))
return FALSE; return FALSE;
return TRUE; return TRUE;
@ -312,37 +314,37 @@ int _conf_verify(LL_HANDLE pll) {
} }
} }
if(pce->type == CONF_T_EXISTPATH) { if(pce->type == CONF_T_EXISTPATH) {
/* first, need to resolve */ /* first, need to resolve */
pi = _conf_fetch_item(pll,pce->section, pce->term); pi = _conf_fetch_item(pll,pce->section, pce->term);
if(pi) { if(pi) {
memset(resolved_path,0,sizeof(resolved_path)); memset(resolved_path,0,sizeof(resolved_path));
if(pi->value.as_string) { if(pi->value.as_string) {
DPRINTF(E_SPAM,L_CONF,"Found %s/%s as %s... checking\n", DPRINTF(E_SPAM,L_CONF,"Found %s/%s as %s... checking\n",
pce->section, pce->term, pi->value.as_string); pce->section, pce->term, pi->value.as_string);
/* verify it exists, creating it if necessary */ /* verify it exists, creating it if necessary */
if(!_conf_existdir(pi->value.as_string)) { if(!_conf_existdir(pi->value.as_string)) {
user = "nobody"; user = "nobody";
ptemp = _conf_fetch_item(pll, "general", "runas"); ptemp = _conf_fetch_item(pll, "general", "runas");
if(ptemp) { if(ptemp) {
user = ptemp->value.as_string; 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);
}
}
if(_conf_existdir(pi->value.as_string)) { if(!_conf_makedir(pi->value.as_string,user)) {
realpath(pi->value.as_string,resolved_path); is_valid=0;
free(pi->value.as_string); DPRINTF(E_LOG,L_CONF,"Can't make path %s, invalid config.\n",
pi->value.as_string = strdup(resolved_path); 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++; pce++;
@ -365,6 +367,7 @@ int conf_read(char *file) {
FILE *fin; FILE *fin;
int err; int err;
LL_HANDLE pllnew, plltemp, pllcurrent, pllcomment; LL_HANDLE pllnew, plltemp, pllcurrent, pllcomment;
LL_ITEM *pli;
char linebuffer[CONF_LINEBUFFER+1]; char linebuffer[CONF_LINEBUFFER+1];
char keybuffer[256]; char keybuffer[256];
char *comment, *term, *value, *delim; char *comment, *term, *value, *delim;
@ -378,6 +381,8 @@ int conf_read(char *file) {
int ws=0; int ws=0;
CONF_ELEMENTS *pce; CONF_ELEMENTS *pce;
int key_type; int key_type;
char **valuearray;
int index;
if(conf_main_file) { if(conf_main_file) {
conf_close(); conf_close();
@ -523,6 +528,30 @@ int conf_read(char *file) {
switch(key_type) { switch(key_type) {
case CONF_T_MULTICOMMA: 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; break;
case CONF_T_INT: case CONF_T_INT:
case CONF_T_STRING: 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 * @returns a pointer to an allocated string containing the required
* configuration key * configuration key
*/ */
char *conf_alloc_string (char *section, char *key, char *dflt) { char *conf_alloc_string(char *section, char *key, char *dflt) {
int size = -1; LL_ITEM *pitem;
char *out; char *result;
char *retval;
/* FIXME: races */ _conf_lock();
conf_get_string(section, key, dflt, NULL, &size); pitem = _conf_fetch_item(conf_main,section,key);
out = (char *)malloc(size * sizeof(char)); 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) if(result == NULL) {
return 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) { int _conf_write(FILE *fp, LL *pll, int sublevel, char *parent) {
LL_ITEM *pli; LL_ITEM *pli;
LL_ITEM *ppre, *pin; LL_ITEM *ppre, *pin;
LL_ITEM *plitemp;
char keybuffer[256]; char keybuffer[256];
if(!pll) if(!pll)
@ -896,8 +940,11 @@ int _conf_write(FILE *fp, LL *pll, int sublevel, char *parent) {
switch(pli->type) { switch(pli->type) {
case LL_TYPE_LL: case LL_TYPE_LL:
if(sublevel) { if(sublevel) {
/* something wrong! */ /* must be multivalued */
DPRINTF(E_LOG,L_CONF,"LL in sublevel: %s\n",pli->key); plitemp = NULL;
while((plitemp = ll_get_next(pli->value.as_ll,plitemp))) {
fprintf(fp,"%s = %s\n",pli->key,plitemp->value.as_string);
}
} else { } else {
fprintf(fp,"[%s]",pli->key); fprintf(fp,"[%s]",pli->key);
if(pin) { if(pin) {
@ -978,6 +1025,7 @@ int _conf_split(char *s, char *delimiters, char ***argvp) {
const char *snew; const char *snew;
char *t; char *t;
char *tokptr; char *tokptr;
char *tmp;
if ((s == NULL) || (delimiters == NULL) || (argvp == NULL)) if ((s == NULL) || (delimiters == NULL) || (argvp == NULL))
return -1; return -1;
@ -989,8 +1037,13 @@ int _conf_split(char *s, char *delimiters, char ***argvp) {
strcpy(t, snew); strcpy(t, snew);
numtokens = 0; numtokens = 0;
tokptr = NULL; tokptr = NULL;
while(strtok_r(t,delimiters,&tokptr) != NULL) tmp = t;
while(strtok_r(tmp,delimiters,&tokptr) != NULL) {
tmp=NULL;
numtokens++; numtokens++;
}
DPRINTF(E_DBG,L_CONF,"Found %d tokens in %s\n",numtokens,s);
if ((*argvp = malloc((numtokens + 1)*sizeof(char *))) == NULL) { if ((*argvp = malloc((numtokens + 1)*sizeof(char *))) == NULL) {
free(t); free(t);
@ -1002,10 +1055,157 @@ int _conf_split(char *s, char *delimiters, char ***argvp) {
else { else {
strcpy(t, snew); strcpy(t, snew);
tokptr = NULL; tokptr = NULL;
for (i = 0; i < numtokens; i++) tmp = t;
*((*argvp) + i) = strtok_r(t, delimiters, &tokptr); 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; *((*argvp) + numtokens) = NULL;
return numtokens; 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++;
}
}

View File

@ -45,4 +45,7 @@ extern int conf_isset(char *section, char *key);
extern int conf_iswritable(void); extern int conf_iswritable(void);
extern int conf_write(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_ */ #endif /* _CONFIG_H_ */

View File

@ -261,22 +261,24 @@ int scan_init(char *path) {
* check to see if a particular path is a complation path * check to see if a particular path is a complation path
* *
* @param path path to check * @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) { int scan_is_compdir(char *path) {
#if 0
int current=0; int current=0;
char **compdirs;
if(!config.complist) if(!conf_get_array("general","compdirs",&compdirs))
return 0; return FALSE;
while(config.complist[current]) { while(compdirs[current]) {
if(strcasestr(path,config.complist[current])) if(strcasestr(path,compdirs[current])) {
return 1; conf_dispose_array(compdirs);
return TRUE;
}
current++; current++;
} }
#endif conf_dispose_array(compdirs);
return 0; return FALSE;
} }
@ -660,7 +662,7 @@ void make_composite_tags(MP3FILE *song) {
if(!song->artist) { if(!song->artist) {
if (song->orchestra && song->conductor) { if (song->orchestra && song->conductor) {
len = (int)strlen(song->orchestra) + len = (int)strlen(song->orchestra) +
(int)strlen(sep) + (int)strlen(sep) +
(int)strlen(song->conductor); (int)strlen(song->conductor);
ptmp = (char*)malloc(len + 1); 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); sprintf(ptmp,"%s%s%s",song->artist, sep, song->title);
free(song->title); free(song->title);
song->title = ptmp; song->title = ptmp;
if(va_artist) { if(va_artist) {
ptmp = strdup(va_artist); ptmp = strdup(va_artist);
if(ptmp) { if(ptmp) {
@ -695,7 +697,7 @@ void make_composite_tags(MP3FILE *song) {
} }
} }
} }
if(song->url) if(song->url)
song->data_kind=1; song->data_kind=1;
else else