mirror of
https://github.com/owntone/owntone-server.git
synced 2025-04-23 03:55:42 -04:00
Finish out the config file stuff. Only missing comment preservation now
This commit is contained in:
parent
1d0a3c4149
commit
4402588e2d
179
src/conf.c
179
src/conf.c
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id$
|
* $idx: conf.c,v 1.4 2006/02/21 03:08:14 rpedde Exp $
|
||||||
* Functions for reading and writing the config file
|
* Functions for reading and writing the config file
|
||||||
*
|
*
|
||||||
* Copyright (C) 2006 Ron Pedde (ron@pedde.com)
|
* Copyright (C) 2006 Ron Pedde (ron@pedde.com)
|
||||||
@ -42,6 +42,7 @@
|
|||||||
/** Globals */
|
/** Globals */
|
||||||
static int ecode;
|
static int ecode;
|
||||||
static LL_HANDLE conf_main=NULL;
|
static LL_HANDLE conf_main=NULL;
|
||||||
|
static char *conf_main_file = NULL;
|
||||||
static pthread_mutex_t conf_mutex = PTHREAD_MUTEX_INITIALIZER;
|
static pthread_mutex_t conf_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
#define conf_LINEBUFFER 128
|
#define conf_LINEBUFFER 128
|
||||||
@ -55,7 +56,7 @@ 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 int _conf_exists(LL_HANDLE pll, char *section, char *term);
|
||||||
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);
|
||||||
|
|
||||||
typedef struct _CONF_ELEMENTS {
|
typedef struct _CONF_ELEMENTS {
|
||||||
int required;
|
int required;
|
||||||
@ -213,6 +214,12 @@ int conf_read(char *file) {
|
|||||||
int compat_mode=1;
|
int compat_mode=1;
|
||||||
int line=0;
|
int line=0;
|
||||||
|
|
||||||
|
if(conf_main_file) {
|
||||||
|
conf_close();
|
||||||
|
}
|
||||||
|
|
||||||
|
conf_main_file = strdup(file);
|
||||||
|
|
||||||
fin=fopen(file,"r");
|
fin=fopen(file,"r");
|
||||||
if(!fin) {
|
if(!fin) {
|
||||||
return CONF_E_FOPEN;
|
return CONF_E_FOPEN;
|
||||||
@ -326,8 +333,15 @@ int conf_read(char *file) {
|
|||||||
* do final config file shutdown
|
* do final config file shutdown
|
||||||
*/
|
*/
|
||||||
int conf_close(void) {
|
int conf_close(void) {
|
||||||
if(conf_main)
|
if(conf_main) {
|
||||||
ll_destroy(conf_main);
|
ll_destroy(conf_main);
|
||||||
|
conf_main = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(conf_main_file) {
|
||||||
|
free(conf_main_file);
|
||||||
|
conf_main_file = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return CONF_E_SUCCESS;
|
return CONF_E_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -395,3 +409,162 @@ int conf_get_string(char *section, char *key, char *dflt, char *out, int *size)
|
|||||||
_conf_unlock();
|
_conf_unlock();
|
||||||
return CONF_E_SUCCESS;
|
return CONF_E_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set (update) the config tree with a particular value.
|
||||||
|
* this accepts an int, but it actually adds it as a string.
|
||||||
|
* in that sense, it's really just a wrapper for conf_set_string
|
||||||
|
*
|
||||||
|
* @param section section that the key is in
|
||||||
|
* @param key key to update
|
||||||
|
* @param value value to set it to
|
||||||
|
* @returns E_CONF_SUCCESS on success, error code otherwise
|
||||||
|
*/
|
||||||
|
int conf_set_int(char *section, char *key, int value) {
|
||||||
|
char buffer[40]; /* ?? */
|
||||||
|
snprintf(buffer,sizeof(buffer),"%d",value);
|
||||||
|
|
||||||
|
return conf_set_string(section, key, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set (update) the config tree with a particular string value
|
||||||
|
*
|
||||||
|
* @param section section that the key is in
|
||||||
|
* @param key key to update
|
||||||
|
* @param value value to set it to
|
||||||
|
* @returns E_CONF_SUCCESS on success, error code otherwise
|
||||||
|
*/
|
||||||
|
int conf_set_string(char *section, char *key, char *value) {
|
||||||
|
LL_ITEM *pitem;
|
||||||
|
LL_ITEM *psection;
|
||||||
|
LL *section_ll;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
_conf_lock();
|
||||||
|
pitem = _conf_fetch_item(conf_main,section,key);
|
||||||
|
if(!pitem) {
|
||||||
|
/* fetch the section and add it to that list */
|
||||||
|
if(!(psection = ll_fetch_item(conf_main,section))) {
|
||||||
|
/* that subkey doesn't exist yet... */
|
||||||
|
if((err = ll_create(§ion_ll)) != LL_E_SUCCESS) {
|
||||||
|
DPRINTF(E_LOG,L_CONF,"Could not create linked list: %d\n",err);
|
||||||
|
_conf_unlock();
|
||||||
|
return CONF_E_UNKNOWN;
|
||||||
|
}
|
||||||
|
if((err=ll_add_ll(conf_main,section,section_ll)) != LL_E_SUCCESS) {
|
||||||
|
DPRINTF(E_LOG,L_CONF,"Error inserting new subkey: %d\n",err);
|
||||||
|
_conf_unlock();
|
||||||
|
return CONF_E_UNKNOWN;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
section_ll = psection->value.as_ll;
|
||||||
|
}
|
||||||
|
/* have the section, now add it */
|
||||||
|
if((err = ll_add_string(section_ll,key,value)) != LL_E_SUCCESS) {
|
||||||
|
DPRINTF(E_LOG,L_CONF,"Error in conf_set_string: "
|
||||||
|
"(%s/%s)\n",section,key);
|
||||||
|
_conf_unlock();
|
||||||
|
return CONF_E_UNKNOWN;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* we have the item, let's update it */
|
||||||
|
ll_update_string(pitem,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
_conf_unlock();
|
||||||
|
return CONF_E_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* determine if the configuration file is writable
|
||||||
|
*
|
||||||
|
* @returns TRUE if writable, FALSE otherwise
|
||||||
|
*/
|
||||||
|
int conf_iswritable(void) {
|
||||||
|
FILE *fp;
|
||||||
|
int retval = FALSE;
|
||||||
|
|
||||||
|
/* don't want configfile reopened under us */
|
||||||
|
_conf_lock();
|
||||||
|
|
||||||
|
if(!conf_main_file)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if((fp = fopen(conf_main_file,"r+")) != NULL) {
|
||||||
|
fclose(fp);
|
||||||
|
retval = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_conf_unlock();
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* write the current config tree back to the config file
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int conf_write(void) {
|
||||||
|
int retval = FALSE;
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
if(!conf_main_file) {
|
||||||
|
return CONF_E_NOCONF;
|
||||||
|
}
|
||||||
|
|
||||||
|
_conf_lock();
|
||||||
|
if((fp = fopen(conf_main_file,"w+")) != NULL) {
|
||||||
|
retval = _conf_write(fp,conf_main,0);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
_conf_unlock();
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* do the actual work of writing the config file
|
||||||
|
*
|
||||||
|
* @param fp file we are writing the config file to
|
||||||
|
* @param pll list we are dumping k/v pairs for
|
||||||
|
* @param sublevel whether this is the root, or a subkey
|
||||||
|
* @returns TRUE on success, FALSE otherwise
|
||||||
|
*/
|
||||||
|
int _conf_write(FILE *fp, LL *pll, int sublevel) {
|
||||||
|
LL_ITEM *pli;
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
if(!pll)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
/* write all the solo keys, first! */
|
||||||
|
pli = pll->itemlist.next;
|
||||||
|
while(pli) {
|
||||||
|
switch(pli->type) {
|
||||||
|
case LL_TYPE_LL:
|
||||||
|
if(sublevel) {
|
||||||
|
/* something wrong! */
|
||||||
|
DPRINTF(E_LOG,L_CONF,"LL in sublevel: %s\n",pli->key);
|
||||||
|
} else {
|
||||||
|
fprintf(fp,"[%s]\n",pli->key);
|
||||||
|
if(!_conf_write(fp, pli->value.as_ll, 1))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LL_TYPE_INT:
|
||||||
|
fprintf(fp,"%s=%d\n",pli->key,pli->value.as_int);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LL_TYPE_STRING:
|
||||||
|
fprintf(fp,"%s=%s\n",pli->key,pli->value.as_string);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pli = pli->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
#define CONF_E_BADHEADER 3
|
#define CONF_E_BADHEADER 3
|
||||||
#define CONF_E_PARSE 4
|
#define CONF_E_PARSE 4
|
||||||
#define CONF_E_OVERFLOW 5 /** <Buffer passed too small */
|
#define CONF_E_OVERFLOW 5 /** <Buffer passed too small */
|
||||||
|
#define CONF_E_NOCONF 6 /** <No open config file */
|
||||||
|
|
||||||
|
|
||||||
extern int conf_read(char *file);
|
extern int conf_read(char *file);
|
||||||
@ -36,5 +36,10 @@ extern int conf_close(void);
|
|||||||
extern int conf_get_int(char *section, char *key, int dflt);
|
extern int conf_get_int(char *section, char *key, int dflt);
|
||||||
extern int conf_get_string(char *section, char *key, char *dflt,
|
extern int conf_get_string(char *section, char *key, char *dflt,
|
||||||
char *out, int *size);
|
char *out, int *size);
|
||||||
|
extern int conf_set_int(char *section, char *key, int value);
|
||||||
|
extern int conf_set_string(char *section, char *key, char *value);
|
||||||
|
|
||||||
|
extern int conf_iswritable(void);
|
||||||
|
extern int conf_write(void);
|
||||||
|
|
||||||
#endif /* _CONFIG_H_ */
|
#endif /* _CONFIG_H_ */
|
||||||
|
@ -16,8 +16,15 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
if((err=conf_read(argv[1])) != CONF_E_SUCCESS) {
|
if((err=conf_read(argv[1])) != CONF_E_SUCCESS) {
|
||||||
printf("Error reading config: %d\n",err);
|
printf("Error reading config: %d\n",err);
|
||||||
|
conf_close();
|
||||||
} else {
|
} else {
|
||||||
printf("Read config!\n");
|
printf("Read config!\n");
|
||||||
|
conf_set_string("general","stupid","lalala");
|
||||||
|
conf_set_int("potato","yummy",0);
|
||||||
|
if(conf_iswritable()) {
|
||||||
|
printf("writing config\n");
|
||||||
|
conf_write();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
conf_close();
|
conf_close();
|
||||||
}
|
}
|
||||||
|
68
src/ll.c
68
src/ll.c
@ -35,6 +35,7 @@
|
|||||||
/** Internal functions */
|
/** Internal functions */
|
||||||
|
|
||||||
int _ll_add_item(LL *pl, char *key, void *vpval, int ival, int type);
|
int _ll_add_item(LL *pl, char *key, void *vpval, int ival, int type);
|
||||||
|
int _ll_update_item(LL_ITEM *pli, void *vpval, int ival, int type);
|
||||||
void _ll_dump(LL *pl, int depth);
|
void _ll_dump(LL *pl, int depth);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -167,6 +168,73 @@ int _ll_add_item(LL *pl, char *key, void* vpval, int ival, int type) {
|
|||||||
return LL_E_SUCCESS;
|
return LL_E_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* thin wrapper for _ll_update_item
|
||||||
|
*/
|
||||||
|
int ll_update_string(LL_ITEM *pli, char *cval) {
|
||||||
|
return _ll_update_item(pli,cval,0,LL_TYPE_STRING);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* thin wrapper for _ll_update_item
|
||||||
|
*/
|
||||||
|
int ll_update_int(LL_ITEM *pli, int ival) {
|
||||||
|
return _ll_update_item(pli,NULL,ival,LL_TYPE_INT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* thin wrapper for _ll_update_item.
|
||||||
|
*
|
||||||
|
* NOTE: There is a reasonable case to be made about
|
||||||
|
* what should happen to flags on an update. We'll just
|
||||||
|
* leave that to the caller, though.
|
||||||
|
*/
|
||||||
|
int ll_update_ll(LL_ITEM *pli, LL *pnew) {
|
||||||
|
int result;
|
||||||
|
|
||||||
|
result = _ll_update_item(pli,(void*)pnew,0,LL_TYPE_LL);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* update an item, given an item pointer
|
||||||
|
*/
|
||||||
|
int _ll_update_item(LL_ITEM *pli, void* vpval, int ival, int type) {
|
||||||
|
|
||||||
|
/* dispose of what used to be there*/
|
||||||
|
switch(pli->type) {
|
||||||
|
case LL_TYPE_LL:
|
||||||
|
ll_destroy(pli->value.as_ll);
|
||||||
|
break;
|
||||||
|
case LL_TYPE_STRING:
|
||||||
|
free(pli->value.as_string);
|
||||||
|
break;
|
||||||
|
case LL_TYPE_INT: /* fallthrough */
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pli->type = type;
|
||||||
|
|
||||||
|
switch(pli->type) {
|
||||||
|
case LL_TYPE_INT:
|
||||||
|
pli->value.as_int = ival;
|
||||||
|
break;
|
||||||
|
case LL_TYPE_LL:
|
||||||
|
pli->value.as_ll = (LL *)vpval;
|
||||||
|
break;
|
||||||
|
case LL_TYPE_STRING:
|
||||||
|
pli->value.as_string = strdup((char*)vpval);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return LL_E_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* internal function to get the ll item associated with
|
* internal function to get the ll item associated with
|
||||||
* a specific key, using the case sensitivity specified
|
* a specific key, using the case sensitivity specified
|
||||||
|
4
src/ll.h
4
src/ll.h
@ -63,6 +63,10 @@ extern int ll_add_string(LL *pl, char *key, char *cval);
|
|||||||
extern int ll_add_int(LL *pl, char *key, int ival);
|
extern int ll_add_int(LL *pl, char *key, int ival);
|
||||||
extern int ll_add_ll(LL *pl, char *key, LL *pnew);
|
extern int ll_add_ll(LL *pl, char *key, LL *pnew);
|
||||||
|
|
||||||
|
extern int ll_udpate_string(LL_ITEM *pli, char *cval);
|
||||||
|
extern int ll_update_int(LL_ITEM *pli, int ival);
|
||||||
|
extern int ll_update_ll(LL_ITEM *pli, LL *pnew);
|
||||||
|
|
||||||
extern int ll_set_flags(LL *pl, unsigned int flags);
|
extern int ll_set_flags(LL *pl, unsigned int flags);
|
||||||
extern int ll_get_flags(LL *pl, unsigned int *flags);
|
extern int ll_get_flags(LL *pl, unsigned int *flags);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user