Commit e61b137f authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

Replace the configuration file atomically

Another VLC instance could get a corrupt configuration otherwise.
parent 5e322450
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <errno.h> /* errno */ #include <errno.h> /* errno */
#include <assert.h> #include <assert.h>
#include <limits.h> #include <limits.h>
#include <fcntl.h>
#ifdef __APPLE__ #ifdef __APPLE__
# include <xlocale.h> # include <xlocale.h>
#else #else
...@@ -420,10 +421,11 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name, ...@@ -420,10 +421,11 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name,
{ {
libvlc_priv_t *priv = libvlc_priv (p_this->p_libvlc); libvlc_priv_t *priv = libvlc_priv (p_this->p_libvlc);
module_t *p_parser; module_t *p_parser;
FILE *file; FILE *file = NULL;
char *permanent = NULL, *temporary = NULL;
char p_line[1024], *p_index2; char p_line[1024], *p_index2;
unsigned long i_sizebuf = 0; unsigned long i_sizebuf = 0;
char *p_bigbuffer, *p_index; char *p_bigbuffer = NULL, *p_index;
bool b_backup; bool b_backup;
int i_index; int i_index;
...@@ -433,8 +435,7 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name, ...@@ -433,8 +435,7 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name,
if( config_PrepareDir( p_this ) ) if( config_PrepareDir( p_this ) )
{ {
msg_Err( p_this, "no configuration directory" ); msg_Err( p_this, "no configuration directory" );
vlc_mutex_unlock( &priv->config_lock ); goto error;
return -1;
} }
file = config_OpenConfigFile( p_this, "rt" ); file = config_OpenConfigFile( p_this, "rt" );
...@@ -450,11 +451,7 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name, ...@@ -450,11 +451,7 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name,
p_bigbuffer = p_index = malloc( i_sizebuf+1 ); p_bigbuffer = p_index = malloc( i_sizebuf+1 );
if( !p_bigbuffer ) if( !p_bigbuffer )
{ goto error;
if( file ) fclose( file );
vlc_mutex_unlock( &priv->config_lock );
return -1;
}
p_bigbuffer[0] = 0; p_bigbuffer[0] = 0;
/* List all available modules */ /* List all available modules */
...@@ -512,20 +509,39 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name, ...@@ -512,20 +509,39 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name,
p_index += strlen( p_line ); p_index += strlen( p_line );
} }
} }
if( file ) fclose( file ); if( file )
fclose( file );
file = NULL;
/* /*
* Save module config in file * Save module config in file
*/ */
permanent = config_GetConfigFile (p_this);
if (!permanent)
{
module_list_free (list);
goto error;
}
file = config_OpenConfigFile (p_this, "wt"); if (asprintf (&temporary, "%s.%u", permanent, getpid ()) == -1)
if( !file )
{ {
temporary = NULL;
module_list_free (list); module_list_free (list);
free( p_bigbuffer ); goto error;
vlc_mutex_unlock( &priv->config_lock ); }
return -1;
int fd = utf8_open (temporary, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR|S_IWUSR);
if (fd == -1)
{
module_list_free (list);
goto error;
}
file = fdopen (fd, "wt");
if (file == NULL)
{
close (fd);
module_list_free (list);
goto error;
} }
fprintf( file, "\xEF\xBB\xBF###\n### " COPYRIGHT_MESSAGE "\n###\n\n" fprintf( file, "\xEF\xBB\xBF###\n### " COPYRIGHT_MESSAGE "\n###\n\n"
...@@ -652,10 +668,37 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name, ...@@ -652,10 +668,37 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name,
fputs( p_bigbuffer, file ); fputs( p_bigbuffer, file );
free( p_bigbuffer ); free( p_bigbuffer );
fclose( file ); /*
vlc_mutex_unlock( &priv->config_lock ); * Flush to disk and replace atomically
*/
fflush (file); /* Flush from run-time */
#ifndef WIN32
fdatasync (fd); /* Flush from OS */
/* Atomically replace the file... */
rename (temporary, permanent);
/* (...then synchronize the directory, err, TODO...) */
/* ...and finally close the file */
#endif
vlc_mutex_unlock (&priv->config_lock);
fclose (file);
#ifdef WIN32
/* Windows cannot remove open files nor overwrite existing ones */
remove (permanent);
rename (temporary, permanent);
#endif
free (temporary);
free (permanent);
return 0; return 0;
error:
if( file )
fclose( file );
vlc_mutex_unlock( &priv->config_lock );
free (temporary);
free (permanent);
free( p_bigbuffer );
return -1;
} }
int config_AutoSaveConfigFile( vlc_object_t *p_this ) int config_AutoSaveConfigFile( vlc_object_t *p_this )
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment