]> git.sesse.net Git - vlc/blobdiff - src/config/file.c
ConfigKeyToString: binary search
[vlc] / src / config / file.c
index 4012ea2ee828e0f371f0a7fa8ddb22ea20ba8d88..5d0f3772a3995b32a1f72ddc16558cb4c691258e 100644 (file)
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU 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 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
 # include "config.h"
 #endif
 
-#include <vlc_common.h>
-#include "../libvlc.h"
-#include "vlc_charset.h"
-#include "vlc_keys.h"
-
 #include <errno.h>                                                  /* errno */
 #include <assert.h>
 #include <limits.h>
 #include <fcntl.h>
+#include <sys/stat.h>
 #ifdef __APPLE__
 #   include <xlocale.h>
 #else
 #include <locale.h>
 #endif
 
+#include <vlc_common.h>
+#include "../libvlc.h"
+#include "vlc_charset.h"
+#include "vlc_keys.h"
+
 #include "configuration.h"
 #include "modules/modules.h"
 
-static char *ConfigKeyToString( int );
-
 static inline char *strdupnull (const char *src)
 {
     return src ? strdup (src) : NULL;
@@ -58,7 +57,7 @@ static char *config_GetConfigFile( vlc_object_t *obj )
     char *psz_file = config_GetPsz( 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;
@@ -67,7 +66,7 @@ static char *config_GetConfigFile( vlc_object_t *obj )
     return psz_file;
 }
 
-static FILE *config_OpenConfigFile( vlc_object_t *p_obj, const char *mode )
+static FILE *config_OpenConfigFile( vlc_object_t *p_obj )
 {
     char *psz_filename = config_GetConfigFile( p_obj );
     if( psz_filename == NULL )
@@ -75,7 +74,7 @@ static FILE *config_OpenConfigFile( vlc_object_t *p_obj, const char *mode )
 
     msg_Dbg( p_obj, "opening config file (%s)", psz_filename );
 
-    FILE *p_stream = utf8_fopen( psz_filename, mode );
+    FILE *p_stream = utf8_fopen( psz_filename, "rt" );
     if( p_stream == NULL && errno != ENOENT )
     {
         msg_Err( p_obj, "cannot open config file (%s): %m",
@@ -83,15 +82,18 @@ static FILE *config_OpenConfigFile( vlc_object_t *p_obj, const char *mode )
 
     }
 #if !( defined(WIN32) || defined(__APPLE__) || defined(SYS_BEOS) )
-    else if( p_stream == NULL && errno == ENOENT && mode[0] == 'r' )
+    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, mode );
+            p_stream = utf8_fopen( psz_old, "rt" );
             if( p_stream )
             {
                 /* Old config file found. We want to write it at the
@@ -99,8 +101,8 @@ static FILE *config_OpenConfigFile( vlc_object_t *p_obj, const char *mode )
                 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" );
                     if( p_readme )
@@ -119,8 +121,10 @@ static FILE *config_OpenConfigFile( vlc_object_t *p_obj, const char *mode )
             }
             free( psz_old );
         }
+        free( home );
     }
 #endif
+    free( psz_filename );
     return p_stream;
 }
 
@@ -154,7 +158,7 @@ int __config_LoadConfigFile( vlc_object_t *p_this, const char *psz_module_name )
 {
     FILE *file;
 
-    file = config_OpenConfigFile (p_this, "rt");
+    file = config_OpenConfigFile (p_this);
     if (file == NULL)
         return VLC_EGENERIC;
 
@@ -352,7 +356,7 @@ int config_CreateDir( vlc_object_t *p_this, const char *psz_dirname )
 }
 
 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;
@@ -379,8 +383,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);
@@ -410,7 +414,6 @@ static int config_PrepareDir (vlc_object_t *obj)
 static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name,
                            bool b_autosave )
 {
-    libvlc_priv_t *priv = libvlc_priv (p_this->p_libvlc);
     module_t *p_parser;
     FILE *file = NULL;
     char *permanent = NULL, *temporary = NULL;
@@ -420,24 +423,27 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name,
     bool b_backup;
     int i_index;
 
-    /* Acquire config file lock */
-    vlc_mutex_lock( &priv->config_lock );
-
     if( config_PrepareDir( p_this ) )
     {
         msg_Err( p_this, "no configuration directory" );
         goto error;
     }
 
-    file = config_OpenConfigFile( p_this, "rt" );
+    file = config_OpenConfigFile( p_this );
     if( file != NULL )
     {
-        /* 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;
+        struct stat st;
+
+        /* 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 (fstat (fileno (file), &st)
+         || !(st.st_mode & S_IWUSR))
+        {
+            msg_Err (p_this, "configuration file is read-only");
+            goto error;
+        }
+        i_sizebuf = ( st.st_size < LONG_MAX ) ? st.st_size : 0;
     }
 
     p_bigbuffer = p_index = malloc( i_sizebuf+1 );
@@ -521,9 +527,15 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name,
         goto error;
     }
 
+    /* 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);
     if (fd == -1)
     {
+        vlc_mutex_unlock (&lock);
         module_list_free (list);
         goto error;
     }
@@ -531,6 +543,7 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name,
     if (file == NULL)
     {
         close (fd);
+        vlc_mutex_unlock (&lock);
         module_list_free (list);
         goto error;
     }
@@ -669,16 +682,19 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name,
 #ifndef WIN32
     fdatasync (fd); /* Flush from OS */
     /* Atomically replace the file... */
-    rename (temporary, permanent);
+    if (utf8_rename (temporary, permanent))
+        utf8_unlink (temporary);
     /* (...then synchronize the directory, err, TODO...) */
     /* ...and finally close the file */
+    vlc_mutex_unlock (&lock);
 #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);
+    utf8_unlink (permanent);
+    if (utf8_rename (temporary, permanent))
+        utf8_unlink (temporary);
+    vlc_mutex_unlock (&lock);
 #endif
 
     free (temporary);
@@ -688,7 +704,6 @@ static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name,
 error:
     if( file )
         fclose( file );
-    vlc_mutex_unlock( &priv->config_lock );
     free (temporary);
     free (permanent);
     free( p_bigbuffer );
@@ -729,66 +744,3 @@ 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;
-    unsigned int i;
-    const char *psz_parser = strchr( psz_key, '-' );
-    while( psz_parser && psz_parser != psz_key )
-    {
-        for( i = 0; i < sizeof(vlc_modifiers) / sizeof(key_descriptor_t); 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, '-' );
-    }
-    for( i = 0; i < sizeof(vlc_keys) / sizeof( key_descriptor_t ); 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 )
-{
-    char *psz_key = malloc( 100 );
-    char *p;
-    size_t index;
-
-    if ( !psz_key )
-    {
-        return NULL;
-    }
-    *psz_key = '\0';
-    p = psz_key;
-
-    for( index = 0; index < (sizeof(vlc_modifiers) / sizeof(key_descriptor_t));
-         index++ )
-    {
-        if( i_key & vlc_modifiers[index].i_key_code )
-        {
-            p += sprintf( p, "%s-", vlc_modifiers[index].psz_key_string );
-        }
-    }
-    for( index = 0; index < (sizeof(vlc_keys) / sizeof( key_descriptor_t));
-         index++)
-    {
-        if( (int)( i_key & ~KEY_MODIFIER ) == vlc_keys[index].i_key_code )
-        {
-            p += sprintf( p, "%s", vlc_keys[index].psz_key_string );
-            break;
-        }
-    }
-    return psz_key;
-}
-