#include <vlc_common.h>
#include "../libvlc.h"
-#include "vlc_charset.h"
-#include "vlc_keys.h"
+#include <vlc_charset.h>
+#include <vlc_fs.h>
+#include <vlc_keys.h>
+#include <vlc_modules.h>
#include "configuration.h"
#include "modules/modules.h"
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",
&& 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
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 "
}
-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, const char *psz_module_name )
{
FILE *file;
locale_t loc = newlocale (LC_NUMERIC_MASK, "C", NULL);
locale_t baseloc = uselocale (loc);
+ vlc_rwlock_wrlock (&config_lock);
while (fgets (line, 1024, file) != NULL)
{
/* Ignore comments and empty lines */
/* We found it */
errno = 0;
- vlc_mutex_lock( p_item->p_lock );
switch( p_item->i_type )
{
case CONFIG_ITEM_BOOL:
case CONFIG_ITEM_INTEGER:
{
- long l = strtoi (psz_option_value);
+ int64_t l = strtoi (psz_option_value);
+ if ((l > p_item->max.i) || (l < p_item->min.i))
+ errno = ERANGE;
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;
+ p_item->saved.i = p_item->value.i = l;
break;
}
p_item->saved.psz = strdupnull (p_item->value.psz);
break;
}
- vlc_mutex_unlock( p_item->p_lock );
break;
}
}
+ vlc_rwlock_unlock (&config_lock);
if (ferror (file))
{
{
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 )
*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;
}
if( config_PrepareDir( p_this ) )
{
msg_Err( p_this, "no configuration directory" );
- goto error;
+ return -1;
}
file = config_OpenConfigFile( p_this );
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()
* 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");
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++ )
{
|| 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;
+ int64_t val = b_retain ? p_item->saved.i : p_item->value.i;
if (p_item->i_type == CONFIG_ITEM_KEY)
{
char *psz_key = ConfigKeyToString (val);
(p_item->i_type == CONFIG_ITEM_BOOL)
? N_("boolean") : N_("integer"),
val == p_item->orig.i,
- p_item->psz_name, "%d", val);
+ p_item->psz_name, "%"PRId64, val);
p_item->saved.i = val;
}
else
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)
* Flush to disk and replace atomically
*/
fflush (file); /* Flush from run-time */
+ if (ferror (file))
+ {
+ vlc_unlink (temporary);
+ vlc_mutex_unlock (&lock);
+ msg_Err (p_this, "cannot write configuration file");
+ clearerr (file);
+ goto error;
+ }
#ifndef WIN32
+#ifdef __APPLE__
+ fsync (fd); /* Flush from OS */
+#else
fdatasync (fd); /* Flush from OS */
+#endif
/* Atomically replace the file... */
- if (utf8_rename (temporary, permanent))
- utf8_unlink (temporary);
+ if (vlc_rename (temporary, permanent))
+ vlc_unlink (temporary);
/* (...then synchronize the directory, err, TODO...) */
/* ...and finally close the file */
vlc_mutex_unlock (&lock);
fclose (file);
#ifdef WIN32
/* Windows cannot remove open files nor overwrite existing ones */
- utf8_unlink (permanent);
- if (utf8_rename (temporary, permanent))
- utf8_unlink (temporary);
+ vlc_unlink (permanent);
+ if (vlc_rename (temporary, permanent))
+ vlc_unlink (temporary);
vlc_mutex_unlock (&lock);
#endif
int config_AutoSaveConfigFile( vlc_object_t *p_this )
{
- size_t i_index;
+ int ret = VLC_SUCCESS;
bool save = false;
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);
+ for (size_t i_index = 0; list[i_index] && !save; i_index++)
{
module_t *p_parser = list[i_index];
module_config_t *p_item, *p_end;
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 );
+ if (save)
+ /* Note: this will get the read lock recursively. Ok. */
+ ret = SaveConfigFile (p_this, NULL, true);
+ vlc_rwlock_unlock (&config_lock);
+
+ module_list_free (list);
+ return ret;
}
-int __config_SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name )
+#undef config_SaveConfigFile
+int config_SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name )
{
return SaveConfigFile( p_this, psz_module_name, false );
}