X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fconfig%2Ffile.c;h=9ad9537e30d4de172c33339fe1d18776e93fbfcf;hb=61e310a3237ac9bf852613ce0c615c4f610659f6;hp=9b779ab1b420ed9372435da63dcd57bac6d75d10;hpb=152b1687c0ec112f3ab1360006d048d6b9cf7258;p=vlc diff --git a/src/config/file.c b/src/config/file.c index 9b779ab1b4..9ad9537e30 100644 --- a/src/config/file.c +++ b/src/config/file.c @@ -1,24 +1,24 @@ /***************************************************************************** * file.c: configuration file handling ***************************************************************************** - * Copyright (C) 2001-2007 the VideoLAN team + * Copyright (C) 2001-2007 VLC authors and VideoLAN * $Id$ * * Authors: Gildas Bazin * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #ifdef HAVE_CONFIG_H @@ -32,20 +32,24 @@ #include #ifdef __APPLE__ # include -#else +#elif defined(HAVE_USELOCALE) #include #endif +#ifdef HAVE_UNISTD_H +# include +#endif #include #include "../libvlc.h" -#include "vlc_charset.h" -#include "vlc_keys.h" +#include +#include +#include +#include +#include #include "configuration.h" #include "modules/modules.h" -static char *ConfigKeyToString( int ); - static inline char *strdupnull (const char *src) { return src ? strdup (src) : NULL; @@ -56,10 +60,11 @@ static inline char *strdupnull (const char *src) */ static char *config_GetConfigFile( vlc_object_t *obj ) { - char *psz_file = config_GetPsz( obj, "config" ); + char *psz_file = var_CreateGetNonEmptyString( obj, "config" ); + var_Destroy( obj, "config" ); if( psz_file == NULL ) { - char *psz_dir = config_GetUserConfDir(); + char *psz_dir = config_GetUserDir( VLC_CONFIG_DIR ); if( asprintf( &psz_file, "%s" DIR_SEP CONFIG_FILE, psz_dir ) == -1 ) psz_file = NULL; @@ -76,23 +81,26 @@ static FILE *config_OpenConfigFile( vlc_object_t *p_obj ) msg_Dbg( p_obj, "opening config file (%s)", psz_filename ); - FILE *p_stream = utf8_fopen( psz_filename, "rt" ); + FILE *p_stream = vlc_fopen( psz_filename, "rt" ); if( p_stream == NULL && errno != ENOENT ) { msg_Err( p_obj, "cannot open config file (%s): %m", psz_filename ); } -#if !( defined(WIN32) || defined(__APPLE__) || defined(SYS_BEOS) ) +#if !( defined(WIN32) || defined(__APPLE__) || defined(__OS2__) ) else if( p_stream == NULL && errno == ENOENT ) { /* This is the fallback for pre XDG Base Directory * Specification configs */ + char *home = config_GetUserDir(VLC_HOME_DIR); char *psz_old; - if( asprintf( &psz_old, "%s" DIR_SEP CONFIG_DIR DIR_SEP CONFIG_FILE, - config_GetHomeDir() ) != -1 ) + + if( home != NULL + && asprintf( &psz_old, "%s/.vlc/" CONFIG_FILE, + home ) != -1 ) { - p_stream = utf8_fopen( psz_old, "rt" ); + p_stream = vlc_fopen( psz_old, "rt" ); if( p_stream ) { /* Old config file found. We want to write it at the @@ -100,10 +108,10 @@ static FILE *config_OpenConfigFile( vlc_object_t *p_obj ) msg_Info( p_obj->p_libvlc, "Found old config file at %s. " "VLC will now use %s.", psz_old, psz_filename ); char *psz_readme; - if( asprintf(&psz_readme,"%s"DIR_SEP CONFIG_DIR DIR_SEP"README", - config_GetHomeDir() ) != -1 ) + if( asprintf(&psz_readme,"%s/.vlc/README", + home ) != -1 ) { - FILE *p_readme = utf8_fopen( psz_readme, "wt" ); + FILE *p_readme = vlc_fopen( psz_readme, "wt" ); if( p_readme ) { fprintf( p_readme, "The VLC media player " @@ -117,9 +125,14 @@ static FILE *config_OpenConfigFile( vlc_object_t *p_obj ) } free( psz_readme ); } + /* Remove the old configuration file so that --reset-config + * can work properly. Fortunately, Linux allows removing + * open files - with most filesystems. */ + unlink( psz_old ); } free( psz_old ); } + free( home ); } #endif free( psz_filename ); @@ -127,32 +140,35 @@ static FILE *config_OpenConfigFile( vlc_object_t *p_obj ) } -static int strtoi (const char *str) +static int64_t strtoi (const char *str) { char *end; - long l; + long long l; errno = 0; - l = strtol (str, &end, 0); + l = strtoll (str, &end, 0); if (!errno) { - if ((l > INT_MAX) || (l < INT_MIN)) +#if (LLONG_MAX > 0x7fffffffffffffffLL) + if (l > 0x7fffffffffffffffLL + || l < -0x8000000000000000LL) errno = ERANGE; +#endif if (*end) errno = EINVAL; } - return (int)l; + return l; } - +#undef config_LoadConfigFile /***************************************************************************** * config_LoadConfigFile: loads the configuration file. ***************************************************************************** * This function is called to load the config options stored in the config * file. *****************************************************************************/ -int __config_LoadConfigFile( vlc_object_t *p_this, const char *psz_module_name ) +int config_LoadConfigFile( vlc_object_t *p_this ) { FILE *file; @@ -160,9 +176,6 @@ int __config_LoadConfigFile( vlc_object_t *p_this, const char *psz_module_name ) if (file == NULL) return VLC_EGENERIC; - /* Look for the selected module, if NULL then save everything */ - module_t **list = module_list_get (NULL); - /* Look for UTF-8 Byte Order Mark */ char * (*convert) (const char *) = strdupnull; char bom[3]; @@ -174,130 +187,69 @@ int __config_LoadConfigFile( vlc_object_t *p_this, const char *psz_module_name ) rewind (file); /* no BOM, rewind */ } - module_t *module = NULL; - char line[1024], section[1022]; - section[0] = '\0'; + char *line = NULL; + size_t bufsize; + ssize_t linelen; /* Ensure consistent number formatting... */ locale_t loc = newlocale (LC_NUMERIC_MASK, "C", NULL); locale_t baseloc = uselocale (loc); - while (fgets (line, 1024, file) != NULL) + vlc_rwlock_wrlock (&config_lock); + while ((linelen = getline (&line, &bufsize, file)) != -1) { - /* Ignore comments and empty lines */ - switch (line[0]) - { - case '#': - case '\n': - case '\0': - continue; - } - - if (line[0] == '[') - { - char *ptr = strchr (line, ']'); - if (ptr == NULL) - continue; /* syntax error; */ - *ptr = '\0'; - - /* New section ( = a given module) */ - strcpy (section, line + 1); - module = NULL; - - if ((psz_module_name == NULL) - || (strcmp (psz_module_name, section) == 0)) - { - for (int i = 0; list[i]; i++) - { - module_t *m = list[i]; - - if ((strcmp (section, m->psz_object_name) == 0) - && (m->i_config_items > 0)) /* ignore config-less modules */ - { - module = m; - if (psz_module_name != NULL) - msg_Dbg (p_this, - "loading config for module \"%s\"", - section); - break; - } - } - } + line[linelen - 1] = '\0'; /* trim newline */ + /* Ignore comments, section and empty lines */ + if (memchr ("#[", line[0], 3) != NULL) continue; - } - - if (module == NULL) - continue; /* no need to parse if there is no matching module */ - - char *ptr = strchr (line, '\n'); - if (ptr != NULL) - *ptr = '\0'; /* look for option name */ const char *psz_option_name = line; - ptr = strchr (line, '='); + char *ptr = strchr (line, '='); if (ptr == NULL) continue; /* syntax error */ - *ptr = '\0'; - const char *psz_option_value = ptr + 1; - - /* try to match this option with one of the module's options */ - for (size_t i = 0; i < module->confsize; i++) - { - module_config_t *p_item = module->p_config + i; - - if ((p_item->i_type & CONFIG_HINT) - || strcmp (p_item->psz_name, psz_option_name)) - continue; - /* We found it */ - errno = 0; + module_config_t *item = config_FindConfig (p_this, psz_option_name); + if (item == NULL) + continue; - vlc_mutex_lock( p_item->p_lock ); - switch( p_item->i_type ) + const char *psz_option_value = ptr + 1; + switch (CONFIG_CLASS(item->i_type)) + { + case CONFIG_ITEM_BOOL: + case CONFIG_ITEM_INTEGER: { - case CONFIG_ITEM_BOOL: - case CONFIG_ITEM_INTEGER: - { - long l = strtoi (psz_option_value); - if (errno) - msg_Warn (p_this, "Integer value (%s) for %s: %m", - psz_option_value, psz_option_name); - else - p_item->saved.i = p_item->value.i = (int)l; - break; - } - - case CONFIG_ITEM_FLOAT: - if( !*psz_option_value ) - break; /* ignore empty option */ - p_item->value.f = (float)atof (psz_option_value); - p_item->saved.f = p_item->value.f; - break; - - case CONFIG_ITEM_KEY: - if( !*psz_option_value ) - break; /* ignore empty option */ - p_item->value.i = ConfigStringToKey(psz_option_value); - p_item->saved.i = p_item->value.i; - break; - - default: - /* free old string */ - free( (char*) p_item->value.psz ); - free( (char*) p_item->saved.psz ); - - p_item->value.psz = convert (psz_option_value); - p_item->saved.psz = strdupnull (p_item->value.psz); - break; + int64_t l; + + errno = 0; + l = strtoi (psz_option_value); + if ((l > item->max.i) || (l < item->min.i)) + errno = ERANGE; + if (errno) + msg_Warn (p_this, "Integer value (%s) for %s: %m", + psz_option_value, psz_option_name); + else + item->value.i = l; + break; } - vlc_mutex_unlock( p_item->p_lock ); - break; + + case CONFIG_ITEM_FLOAT: + if (!*psz_option_value) + break; /* ignore empty option */ + item->value.f = (float)atof (psz_option_value); + break; + + default: + free ((char *)item->value.psz); + item->value.psz = convert (psz_option_value); + break; } } + vlc_rwlock_unlock (&config_lock); + free (line); if (ferror (file)) { @@ -306,7 +258,6 @@ int __config_LoadConfigFile( vlc_object_t *p_this, const char *psz_module_name ) } fclose (file); - module_list_free (list); if (loc != (locale_t)0) { uselocale (baseloc); @@ -322,7 +273,7 @@ int config_CreateDir( vlc_object_t *p_this, const char *psz_dirname ) { if( !psz_dirname || !*psz_dirname ) return -1; - if( utf8_mkdir( psz_dirname, 0700 ) == 0 ) + if( vlc_mkdir( psz_dirname, 0700 ) == 0 ) return 0; switch( errno ) @@ -342,19 +293,19 @@ int config_CreateDir( vlc_object_t *p_this, const char *psz_dirname ) *psz_end = '\0'; if( config_CreateDir( p_this, psz_parent ) == 0 ) { - if( !utf8_mkdir( psz_dirname, 0700 ) ) + if( !vlc_mkdir( psz_dirname, 0700 ) ) return 0; } } } } - msg_Err( p_this, "could not create %s: %m", psz_dirname ); + msg_Warn( p_this, "could not create %s: %m", psz_dirname ); return -1; } static int -config_Write (FILE *file, const char *type, const char *desc, +config_Write (FILE *file, const char *desc, const char *type, bool comment, const char *name, const char *fmt, ...) { va_list ap; @@ -381,8 +332,8 @@ config_Write (FILE *file, const char *type, const char *desc, static int config_PrepareDir (vlc_object_t *obj) { - char *psz_configdir = config_GetUserConfDir (); - if (psz_configdir == NULL) /* XXX: This should never happen */ + char *psz_configdir = config_GetUserDir (VLC_CONFIG_DIR); + if (psz_configdir == NULL) return -1; int ret = config_CreateDir (obj, psz_configdir); @@ -390,186 +341,100 @@ static int config_PrepareDir (vlc_object_t *obj) return ret; } -/***************************************************************************** - * config_SaveConfigFile: Save a module's config options. - ***************************************************************************** - * This will save the specified module's config options to the config file. - * If psz_module_name is NULL then we save all the modules config options. - * It's no use to save the config options that kept their default values, so - * we'll try to be a bit clever here. - * - * When we save we mustn't delete the config options of the modules that - * haven't been loaded. So we cannot just create a new config file with the - * config structures we've got in memory. - * I don't really know how to deal with this nicely, so I will use a completly - * dumb method ;-) - * I will load the config file in memory, but skipping all the sections of the - * modules we want to save. Then I will create a brand new file, dump the file - * loaded in memory and then append the sections of the modules we want to - * save. - * Really stupid no ? - *****************************************************************************/ -static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name, - bool b_autosave ) +#undef config_SaveConfigFile +/** + * Saves the in-memory configuration into a file. + * @return 0 on success, -1 on error. + */ +int config_SaveConfigFile (vlc_object_t *p_this) { - module_t *p_parser; - FILE *file = NULL; - char *permanent = NULL, *temporary = NULL; - char p_line[1024], *p_index2; - unsigned long i_sizebuf = 0; - char *p_bigbuffer = NULL, *p_index; - bool b_backup; - int i_index; if( config_PrepareDir( p_this ) ) { msg_Err( p_this, "no configuration directory" ); - goto error; + return -1; } - file = config_OpenConfigFile( p_this ); - if( file != NULL ) + /* + * Save module config in file + */ + char *temporary; + char *permanent = config_GetConfigFile (p_this); + if (permanent == NULL) + return -1; + if (asprintf (&temporary, "%s.%u", permanent, getpid ()) == -1) { - /* look for file size */ - fseek( file, 0L, SEEK_END ); - i_sizebuf = ftell( file ); - fseek( file, 0L, SEEK_SET ); - if( i_sizebuf >= LONG_MAX ) - i_sizebuf = 0; + free (permanent); + return -1; } - - p_bigbuffer = p_index = malloc( i_sizebuf+1 ); - if( !p_bigbuffer ) - goto error; - p_bigbuffer[0] = 0; - - /* List all available modules */ - module_t **list = module_list_get (NULL); - - /* backup file into memory, we only need to backup the sections we won't - * save later on */ - b_backup = false; - while( file && fgets( p_line, 1024, file ) ) + else { - if( (p_line[0] == '[') && (p_index2 = strchr(p_line,']'))) - { - - /* we found a section, check if we need to do a backup */ - for( i_index = 0; (p_parser = list[i_index]) != NULL; i_index++ ) - { - if( ((p_index2 - &p_line[1]) - == (int)strlen(p_parser->psz_object_name) ) - && !memcmp( &p_line[1], p_parser->psz_object_name, - strlen(p_parser->psz_object_name) ) ) - { - if( !psz_module_name ) - break; - else if( !strcmp( psz_module_name, - p_parser->psz_object_name ) ) - break; - } - } - - if( list[i_index] == NULL ) - { - /* we don't have this section in our list so we need to back - * it up */ - *p_index2 = 0; -#if 0 - msg_Dbg( p_this, "backing up config for unknown module \"%s\"", - &p_line[1] ); -#endif - *p_index2 = ']'; - - b_backup = true; - } - else - { - b_backup = false; - } - } + struct stat st; - /* save line if requested and line is valid (doesn't begin with a - * space, tab, or eol) */ - if( b_backup && (p_line[0] != '\n') && (p_line[0] != ' ') - && (p_line[0] != '\t') ) + /* Some users make vlcrc read-only to prevent changes. + * The atomic replacement scheme breaks this "feature", + * so we check for read-only by hand. */ + if (stat (permanent, &st) == 0 && !(st.st_mode & S_IWUSR)) { - strcpy( p_index, p_line ); - p_index += strlen( p_line ); + msg_Err (p_this, "configuration file is read-only"); + goto error; } } - if( file ) - fclose( file ); - file = NULL; - - /* - * Save module config in file - */ - permanent = config_GetConfigFile (p_this); - if (!permanent) - { - module_list_free (list); - goto error; - } - if (asprintf (&temporary, "%s.%u", permanent, -#ifdef UNDER_CE - GetCurrentProcessId () -#else - getpid () -#endif - ) == -1) - { - temporary = NULL; - module_list_free (list); - goto error; - } + /* Configuration lock must be taken before vlcrc serializer below. */ + vlc_rwlock_rdlock (&config_lock); - /* The temporary configuration file is per-PID. Therefore SaveConfigFile() + /* The temporary configuration file is per-PID. Therefore this function * should be serialized against itself within a given process. */ static vlc_mutex_t lock = VLC_STATIC_MUTEX; vlc_mutex_lock (&lock); - int fd = utf8_open (temporary, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR|S_IWUSR); + int fd = vlc_open (temporary, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR|S_IWUSR); if (fd == -1) { + vlc_rwlock_unlock (&config_lock); vlc_mutex_unlock (&lock); - module_list_free (list); goto error; } - file = fdopen (fd, "wt"); + FILE *file = fdopen (fd, "wt"); if (file == NULL) { + msg_Err (p_this, "cannot create configuration file: %m"); + vlc_rwlock_unlock (&config_lock); close (fd); vlc_mutex_unlock (&lock); - module_list_free (list); goto error; } - fprintf( file, "\xEF\xBB\xBF###\n### " COPYRIGHT_MESSAGE "\n###\n\n" - "###\n### lines beginning with a '#' character are comments\n###\n\n" ); + fprintf( file, + "\xEF\xBB\xBF###\n" + "### "PACKAGE_NAME" "PACKAGE_VERSION"\n" + "###\n" + "\n" + "###\n" + "### lines beginning with a '#' character are comments\n" + "###\n" + "\n" ); /* Ensure consistent number formatting... */ locale_t loc = newlocale (LC_NUMERIC_MASK, "C", NULL); locale_t baseloc = uselocale (loc); + /* We would take the config lock here. But this would cause a lock + * inversion with the serializer above and config_AutoSaveConfigFile(). + vlc_rwlock_rdlock (&config_lock);*/ + /* Look for the selected module, if NULL then save everything */ - for( i_index = 0; (p_parser = list[i_index]) != NULL; i_index++ ) + module_t **list = module_list_get (NULL); + module_t *p_parser; + for (int i = 0; (p_parser = list[i]) != NULL; i++) { module_config_t *p_item, *p_end; - if( psz_module_name && strcmp( psz_module_name, - p_parser->psz_object_name ) ) - continue; - if( !p_parser->i_config_items ) continue; - if( psz_module_name ) - msg_Dbg( p_this, "saving config for module \"%s\"", - p_parser->psz_object_name ); - - fprintf( file, "[%s]", p_parser->psz_object_name ); + fprintf( file, "[%s]", module_get_object (p_parser) ); if( p_parser->psz_longname ) fprintf( file, " # %s\n\n", p_parser->psz_longname ); else @@ -579,86 +444,44 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name, p_item < p_end; p_item++ ) { - if ((p_item->i_type & CONFIG_HINT) /* ignore hint */ + if (!CONFIG_ITEM(p_item->i_type) /* ignore hint */ || p_item->b_removed /* ignore deprecated option */ || p_item->b_unsaveable) /* ignore volatile option */ continue; - vlc_mutex_lock (p_item->p_lock); - - /* Do not save the new value in the configuration file - * if doing an autosave, and the item is not an "autosaved" one. */ - bool b_retain = b_autosave && !p_item->b_autosave; - if (IsConfigIntegerType (p_item->i_type)) { - int val = b_retain ? p_item->saved.i : p_item->value.i; - if (p_item->i_type == CONFIG_ITEM_KEY) - { - char *psz_key = ConfigKeyToString (val); - config_Write (file, p_item->psz_text, N_("key"), - val == p_item->orig.i, - p_item->psz_name, "%s", - psz_key ? psz_key : ""); - free (psz_key); - } - else - config_Write (file, p_item->psz_text, - (p_item->i_type == CONFIG_ITEM_BOOL) - ? N_("boolean") : N_("integer"), - val == p_item->orig.i, - p_item->psz_name, "%d", val); - p_item->saved.i = val; + int64_t val = p_item->value.i; + config_Write (file, p_item->psz_text, + (CONFIG_CLASS(p_item->i_type) == CONFIG_ITEM_BOOL) + ? N_("boolean") : N_("integer"), + val == p_item->orig.i, + p_item->psz_name, "%"PRId64, val); } else if (IsConfigFloatType (p_item->i_type)) { - float val = b_retain ? p_item->saved.f : p_item->value.f; + float val = p_item->value.f; config_Write (file, p_item->psz_text, N_("float"), val == p_item->orig.f, p_item->psz_name, "%f", val); - p_item->saved.f = val; } else { - const char *psz_value = b_retain ? p_item->saved.psz - : p_item->value.psz; + const char *psz_value = p_item->value.psz; bool modified; assert (IsConfigStringType (p_item->i_type)); - if (b_retain && (psz_value == NULL)) /* FIXME: hack */ - psz_value = p_item->orig.psz; - - modified = - (psz_value != NULL) - ? ((p_item->orig.psz != NULL) - ? (strcmp (psz_value, p_item->orig.psz) != 0) - : true) - : (p_item->orig.psz != NULL); - + modified = !!strcmp (psz_value ? psz_value : "", + p_item->orig.psz ? p_item->orig.psz : ""); config_Write (file, p_item->psz_text, N_("string"), !modified, p_item->psz_name, "%s", psz_value ? psz_value : ""); - - if ( !b_retain ) - { - - free ((char *)p_item->saved.psz); - if( (psz_value && p_item->orig.psz && - strcmp( psz_value, p_item->orig.psz )) || - !psz_value || !p_item->orig.psz) - p_item->saved.psz = strdupnull (psz_value); - else - p_item->saved.psz = NULL; - } } - - if (!b_retain) - p_item->b_dirty = false; - vlc_mutex_unlock (p_item->p_lock); } } + vlc_rwlock_unlock (&config_lock); module_list_free (list); if (loc != (locale_t)0) @@ -667,30 +490,36 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name, freelocale (loc); } - /* - * Restore old settings from the config in file - */ - fputs( p_bigbuffer, file ); - free( p_bigbuffer ); - /* * Flush to disk and replace atomically */ fflush (file); /* Flush from run-time */ -#ifndef WIN32 + if (ferror (file)) + { + vlc_unlink (temporary); + vlc_mutex_unlock (&lock); + msg_Err (p_this, "cannot write configuration file"); + fclose (file); + goto error; + } +#if defined(__APPLE__) || defined(__ANDROID__) + fsync (fd); /* Flush from OS */ +#else fdatasync (fd); /* Flush from OS */ +#endif +#if defined (WIN32) || defined (__OS2__) + /* Windows cannot (re)move open files nor overwrite existing ones */ + fclose (file); + vlc_unlink (permanent); +#endif /* Atomically replace the file... */ - utf8_rename (temporary, permanent); + if (vlc_rename (temporary, permanent)) + vlc_unlink (temporary); /* (...then synchronize the directory, err, TODO...) */ /* ...and finally close the file */ vlc_mutex_unlock (&lock); -#endif +#if !defined (WIN32) && !defined (__OS2__) fclose (file); -#ifdef WIN32 - /* Windows cannot remove open files nor overwrite existing ones */ - utf8_unlink (permanent); - utf8_rename (temporary, permanent); - vlc_mutex_unlock (&lock); #endif free (temporary); @@ -698,111 +527,25 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name, return 0; error: - if( file ) - fclose( file ); free (temporary); free (permanent); - free( p_bigbuffer ); return -1; } int config_AutoSaveConfigFile( vlc_object_t *p_this ) { - size_t i_index; - bool save = false; + int ret = 0; assert( p_this ); - /* Check if there's anything to save */ - module_t **list = module_list_get (NULL); - for( i_index = 0; list[i_index] && !save; i_index++ ) + vlc_rwlock_rdlock (&config_lock); + if (config_dirty) { - module_t *p_parser = list[i_index]; - module_config_t *p_item, *p_end; - - if( !p_parser->i_config_items ) continue; - - for( p_item = p_parser->p_config, p_end = p_item + p_parser->confsize; - p_item < p_end && !save; - p_item++ ) - { - vlc_mutex_lock (p_item->p_lock); - save = p_item->b_autosave && p_item->b_dirty; - vlc_mutex_unlock (p_item->p_lock); - } - } - module_list_free (list); - - return save ? VLC_SUCCESS : SaveConfigFile( p_this, NULL, true ); -} - -int __config_SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name ) -{ - return SaveConfigFile( p_this, psz_module_name, false ); -} - -int ConfigStringToKey( const char *psz_key ) -{ - int i_key = 0; - size_t i; - const char *psz_parser = strchr( psz_key, '-' ); - while( psz_parser && psz_parser != psz_key ) - { - for( i = 0; i < vlc_num_modifiers; ++i ) - { - if( !strncasecmp( vlc_modifiers[i].psz_key_string, psz_key, - strlen( vlc_modifiers[i].psz_key_string ) ) ) - { - i_key |= vlc_modifiers[i].i_key_code; - } - } - psz_key = psz_parser + 1; - psz_parser = strchr( psz_key, '-' ); + /* Note: this will get the read lock recursively. Ok. */ + ret = config_SaveConfigFile (p_this); + config_dirty = (ret != 0); } - for( i = 0; i < vlc_num_keys; ++i ) - { - if( !strcasecmp( vlc_keys[i].psz_key_string, psz_key ) ) - { - i_key |= vlc_keys[i].i_key_code; - break; - } - } - return i_key; -} - -char *ConfigKeyToString( int i_key ) -{ - // Worst case appears to be 45 characters: - // "Command-Meta-Ctrl-Shift-Alt-Browser Favorites" - enum { keylen=64 }; - char *psz_key = malloc( keylen ); - char *p; - size_t index; - - if ( !psz_key ) - { - return NULL; - } - *psz_key = '\0'; - p = psz_key; + vlc_rwlock_unlock (&config_lock); - for( index = 0; index < vlc_num_modifiers; ++index ) - { - if( i_key & vlc_modifiers[index].i_key_code ) - { - p += snprintf( p, keylen-(psz_key-p), "%s-", - vlc_modifiers[index].psz_key_string ); - } - } - for( index = 0; index < vlc_num_keys; ++index ) - { - if( (int)( i_key & ~KEY_MODIFIER ) == vlc_keys[index].i_key_code ) - { - p += snprintf( p, keylen-(psz_key-p), "%s", - vlc_keys[index].psz_key_string ); - break; - } - } - return psz_key; + return ret; } -