file.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:25k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * file.c: configuration file handling
  3.  *****************************************************************************
  4.  * Copyright (C) 2001-2007 the VideoLAN team
  5.  * $Id: 58a8d520036bd0e22a67c8905fc504a46eb88db2 $
  6.  *
  7.  * Authors: Gildas Bazin <gbazin@videolan.org>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  22.  *****************************************************************************/
  23. #ifdef HAVE_CONFIG_H
  24. # include "config.h"
  25. #endif
  26. #include <vlc_common.h>
  27. #include "../libvlc.h"
  28. #include "vlc_charset.h"
  29. #include "vlc_keys.h"
  30. #include <errno.h>                                                  /* errno */
  31. #include <assert.h>
  32. #include <limits.h>
  33. #include <fcntl.h>
  34. #include <sys/stat.h>
  35. #ifdef __APPLE__
  36. #   include <xlocale.h>
  37. #elif defined(HAVE_USELOCALE)
  38. #include <locale.h>
  39. #endif
  40. #include "configuration.h"
  41. #include "modules/modules.h"
  42. static char *ConfigKeyToString( int );
  43. static inline char *strdupnull (const char *src)
  44. {
  45.     return src ? strdup (src) : NULL;
  46. }
  47. /**
  48.  * Get the user's configuration file
  49.  */
  50. static char *config_GetConfigFile( vlc_object_t *obj )
  51. {
  52.     char *psz_file = config_GetPsz( obj, "config" );
  53.     if( psz_file == NULL )
  54.     {
  55.         char *psz_dir = config_GetUserConfDir();
  56.         if( asprintf( &psz_file, "%s" DIR_SEP CONFIG_FILE, psz_dir ) == -1 )
  57.             psz_file = NULL;
  58.         free( psz_dir );
  59.     }
  60.     return psz_file;
  61. }
  62. static FILE *config_OpenConfigFile( vlc_object_t *p_obj )
  63. {
  64.     char *psz_filename = config_GetConfigFile( p_obj );
  65.     if( psz_filename == NULL )
  66.         return NULL;
  67.     msg_Dbg( p_obj, "opening config file (%s)", psz_filename );
  68.     FILE *p_stream = utf8_fopen( psz_filename, "rt" );
  69.     if( p_stream == NULL && errno != ENOENT )
  70.     {
  71.         msg_Err( p_obj, "cannot open config file (%s): %m",
  72.                  psz_filename );
  73.     }
  74. #if !( defined(WIN32) || defined(__APPLE__) || defined(SYS_BEOS) )
  75.     else if( p_stream == NULL && errno == ENOENT )
  76.     {
  77.         /* This is the fallback for pre XDG Base Directory
  78.          * Specification configs */
  79.         char *psz_old;
  80.         if( asprintf( &psz_old, "%s" DIR_SEP CONFIG_DIR DIR_SEP CONFIG_FILE,
  81.                       config_GetHomeDir() ) != -1 )
  82.         {
  83.             p_stream = utf8_fopen( psz_old, "rt" );
  84.             if( p_stream )
  85.             {
  86.                 /* Old config file found. We want to write it at the
  87.                  * new location now. */
  88.                 msg_Info( p_obj->p_libvlc, "Found old config file at %s. "
  89.                           "VLC will now use %s.", psz_old, psz_filename );
  90.                 char *psz_readme;
  91.                 if( asprintf(&psz_readme,"%s"DIR_SEP CONFIG_DIR DIR_SEP"README",
  92.                               config_GetHomeDir() ) != -1 )
  93.                 {
  94.                     FILE *p_readme = utf8_fopen( psz_readme, "wt" );
  95.                     if( p_readme )
  96.                     {
  97.                         fprintf( p_readme, "The VLC media player "
  98.                                  "configuration folder has moved to complyn"
  99.                                  "with the XDG Base Directory Specification "
  100.                                  "version 0.6. Yournconfiguration has been "
  101.                                  "copied to the new location:n%snYou can "
  102.                                  "delete this directory and all its contents.",
  103.                                   psz_filename);
  104.                         fclose( p_readme );
  105.                     }
  106.                     free( psz_readme );
  107.                 }
  108.                 /* Remove the old configuration file so that --reset-config
  109.                  * can work properly. */
  110.                 unlink( psz_old );
  111.             }
  112.             free( psz_old );
  113.         }
  114.     }
  115. #endif
  116.     free( psz_filename );
  117.     return p_stream;
  118. }
  119. static int strtoi (const char *str)
  120. {
  121.     char *end;
  122.     long l;
  123.     errno = 0;
  124.     l = strtol (str, &end, 0);
  125.     if (!errno)
  126.     {
  127.         if ((l > INT_MAX) || (l < INT_MIN))
  128.             errno = ERANGE;
  129.         if (*end)
  130.             errno = EINVAL;
  131.     }
  132.     return (int)l;
  133. }
  134. /*****************************************************************************
  135.  * config_LoadConfigFile: loads the configuration file.
  136.  *****************************************************************************
  137.  * This function is called to load the config options stored in the config
  138.  * file.
  139.  *****************************************************************************/
  140. int __config_LoadConfigFile( vlc_object_t *p_this, const char *psz_module_name )
  141. {
  142.     FILE *file;
  143.     file = config_OpenConfigFile (p_this);
  144.     if (file == NULL)
  145.         return VLC_EGENERIC;
  146.     /* Look for the selected module, if NULL then save everything */
  147.     module_t **list = module_list_get (NULL);
  148.     /* Look for UTF-8 Byte Order Mark */
  149.     char * (*convert) (const char *) = strdupnull;
  150.     char bom[3];
  151.     if ((fread (bom, 1, 3, file) != 3)
  152.      || memcmp (bom, "xEFxBBxBF", 3))
  153.     {
  154.         convert = FromLocaleDup;
  155.         rewind (file); /* no BOM, rewind */
  156.     }
  157.     module_t *module = NULL;
  158.     char line[1024], section[1022];
  159.     section[0] = '';
  160.     /* Ensure consistent number formatting... */
  161.     locale_t loc = newlocale (LC_NUMERIC_MASK, "C", NULL);
  162.     locale_t baseloc = uselocale (loc);
  163.     while (fgets (line, 1024, file) != NULL)
  164.     {
  165.         /* Ignore comments and empty lines */
  166.         switch (line[0])
  167.         {
  168.             case '#':
  169.             case 'n':
  170.             case '':
  171.                 continue;
  172.         }
  173.         if (line[0] == '[')
  174.         {
  175.             char *ptr = strchr (line, ']');
  176.             if (ptr == NULL)
  177.                 continue; /* syntax error; */
  178.             *ptr = '';
  179.             /* New section ( = a given module) */
  180.             strcpy (section, line + 1);
  181.             module = NULL;
  182.             if ((psz_module_name == NULL)
  183.              || (strcmp (psz_module_name, section) == 0))
  184.             {
  185.                 for (int i = 0; list[i]; i++)
  186.                 {
  187.                     module_t *m = list[i];
  188.                     if ((strcmp (section, m->psz_object_name) == 0)
  189.                      && (m->i_config_items > 0)) /* ignore config-less modules */
  190.                     {
  191.                         module = m;
  192.                         if (psz_module_name != NULL)
  193.                             msg_Dbg (p_this,
  194.                                      "loading config for module "%s"",
  195.                                      section);
  196.                         break;
  197.                     }
  198.                 }
  199.             }
  200.             continue;
  201.         }
  202.         if (module == NULL)
  203.             continue; /* no need to parse if there is no matching module */
  204.         char *ptr = strchr (line, 'n');
  205.         if (ptr != NULL)
  206.             *ptr = '';
  207.         /* look for option name */
  208.         const char *psz_option_name = line;
  209.         ptr = strchr (line, '=');
  210.         if (ptr == NULL)
  211.             continue; /* syntax error */
  212.         *ptr = '';
  213.         const char *psz_option_value = ptr + 1;
  214.         /* try to match this option with one of the module's options */
  215.         for (size_t i = 0; i < module->confsize; i++)
  216.         {
  217.             module_config_t *p_item = module->p_config + i;
  218.             if ((p_item->i_type & CONFIG_HINT)
  219.              || strcmp (p_item->psz_name, psz_option_name))
  220.                 continue;
  221.             /* We found it */
  222.             errno = 0;
  223.             vlc_mutex_lock( p_item->p_lock );
  224.             switch( p_item->i_type )
  225.             {
  226.                 case CONFIG_ITEM_BOOL:
  227.                 case CONFIG_ITEM_INTEGER:
  228.                 {
  229.                     long l = strtoi (psz_option_value);
  230.                     if (errno)
  231.                         msg_Warn (p_this, "Integer value (%s) for %s: %m",
  232.                                   psz_option_value, psz_option_name);
  233.                     else
  234.                         p_item->saved.i = p_item->value.i = (int)l;
  235.                     break;
  236.                 }
  237.                 case CONFIG_ITEM_FLOAT:
  238.                     if( !*psz_option_value )
  239.                         break;                    /* ignore empty option */
  240.                     p_item->value.f = (float)atof (psz_option_value);
  241.                     p_item->saved.f = p_item->value.f;
  242.                     break;
  243.                 case CONFIG_ITEM_KEY:
  244.                     if( !*psz_option_value )
  245.                         break;                    /* ignore empty option */
  246.                     p_item->value.i = ConfigStringToKey(psz_option_value);
  247.                     p_item->saved.i = p_item->value.i;
  248.                     break;
  249.                 default:
  250.                     /* free old string */
  251.                     free( (char*) p_item->value.psz );
  252.                     free( (char*) p_item->saved.psz );
  253.                     p_item->value.psz = convert (psz_option_value);
  254.                     p_item->saved.psz = strdupnull (p_item->value.psz);
  255.                     break;
  256.             }
  257.             vlc_mutex_unlock( p_item->p_lock );
  258.             break;
  259.         }
  260.     }
  261.     if (ferror (file))
  262.     {
  263.         msg_Err (p_this, "error reading configuration: %m");
  264.         clearerr (file);
  265.     }
  266.     fclose (file);
  267.     module_list_free (list);
  268.     if (loc != (locale_t)0)
  269.     {
  270.         uselocale (baseloc);
  271.         freelocale (loc);
  272.     }
  273.     return 0;
  274. }
  275. /*****************************************************************************
  276.  * config_CreateDir: Create configuration directory if it doesn't exist.
  277.  *****************************************************************************/
  278. int config_CreateDir( vlc_object_t *p_this, const char *psz_dirname )
  279. {
  280.     if( !psz_dirname || !*psz_dirname ) return -1;
  281.     if( utf8_mkdir( psz_dirname, 0700 ) == 0 )
  282.         return 0;
  283.     switch( errno )
  284.     {
  285.         case EEXIST:
  286.             return 0;
  287.         case ENOENT:
  288.         {
  289.             /* Let's try to create the parent directory */
  290.             char psz_parent[strlen( psz_dirname ) + 1], *psz_end;
  291.             strcpy( psz_parent, psz_dirname );
  292.             psz_end = strrchr( psz_parent, DIR_SEP_CHAR );
  293.             if( psz_end && psz_end != psz_parent )
  294.             {
  295.                 *psz_end = '';
  296.                 if( config_CreateDir( p_this, psz_parent ) == 0 )
  297.                 {
  298.                     if( !utf8_mkdir( psz_dirname, 0700 ) )
  299.                         return 0;
  300.                 }
  301.             }
  302.         }
  303.     }
  304.     msg_Err( p_this, "could not create %s: %m", psz_dirname );
  305.     return -1;
  306. }
  307. static int
  308. config_Write (FILE *file, const char *desc, const char *type,
  309.               bool comment, const char *name, const char *fmt, ...)
  310. {
  311.     va_list ap;
  312.     int ret;
  313.     if (desc == NULL)
  314.         desc = "?";
  315.     if (fprintf (file, "# %s (%s)n%s%s=", desc, vlc_gettext (type),
  316.                  comment ? "#" : "", name) < 0)
  317.         return -1;
  318.     va_start (ap, fmt);
  319.     ret = vfprintf (file, fmt, ap);
  320.     va_end (ap);
  321.     if (ret < 0)
  322.         return -1;
  323.     if (fputs ("nn", file) == EOF)
  324.         return -1;
  325.     return 0;
  326. }
  327. static int config_PrepareDir (vlc_object_t *obj)
  328. {
  329.     char *psz_configdir = config_GetUserConfDir ();
  330.     if (psz_configdir == NULL) /* XXX: This should never happen */
  331.         return -1;
  332.     int ret = config_CreateDir (obj, psz_configdir);
  333.     free (psz_configdir);
  334.     return ret;
  335. }
  336. /*****************************************************************************
  337.  * config_SaveConfigFile: Save a module's config options.
  338.  *****************************************************************************
  339.  * This will save the specified module's config options to the config file.
  340.  * If psz_module_name is NULL then we save all the modules config options.
  341.  * It's no use to save the config options that kept their default values, so
  342.  * we'll try to be a bit clever here.
  343.  *
  344.  * When we save we mustn't delete the config options of the modules that
  345.  * haven't been loaded. So we cannot just create a new config file with the
  346.  * config structures we've got in memory.
  347.  * I don't really know how to deal with this nicely, so I will use a completly
  348.  * dumb method ;-)
  349.  * I will load the config file in memory, but skipping all the sections of the
  350.  * modules we want to save. Then I will create a brand new file, dump the file
  351.  * loaded in memory and then append the sections of the modules we want to
  352.  * save.
  353.  * Really stupid no ?
  354.  *****************************************************************************/
  355. static int SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name,
  356.                            bool b_autosave )
  357. {
  358.     module_t *p_parser;
  359.     FILE *file = NULL;
  360.     char *permanent = NULL, *temporary = NULL;
  361.     char p_line[1024], *p_index2;
  362.     unsigned long i_sizebuf = 0;
  363.     char *p_bigbuffer = NULL, *p_index;
  364.     bool b_backup;
  365.     int i_index;
  366.     if( config_PrepareDir( p_this ) )
  367.     {
  368.         msg_Err( p_this, "no configuration directory" );
  369.         goto error;
  370.     }
  371.     file = config_OpenConfigFile( p_this );
  372.     if( file != NULL )
  373.     {
  374.         struct stat st;
  375.         /* Some users make vlcrc read-only to prevent changes.
  376.          * The atomic replacement scheme breaks this "feature",
  377.          * so we check for read-only by hand. */
  378.         if (fstat (fileno (file), &st)
  379.          || !(st.st_mode & S_IWUSR))
  380.         {
  381.             msg_Err (p_this, "configuration file is read-only");
  382.             goto error;
  383.         }
  384.         i_sizebuf = ( st.st_size < LONG_MAX ) ? st.st_size : 0;
  385.     }
  386.     p_bigbuffer = p_index = malloc( i_sizebuf+1 );
  387.     if( !p_bigbuffer )
  388.         goto error;
  389.     p_bigbuffer[0] = 0;
  390.     /* List all available modules */
  391.     module_t **list = module_list_get (NULL);
  392.     /* backup file into memory, we only need to backup the sections we won't
  393.      * save later on */
  394.     b_backup = false;
  395.     while( file && fgets( p_line, 1024, file ) )
  396.     {
  397.         if( (p_line[0] == '[') && (p_index2 = strchr(p_line,']')))
  398.         {
  399.             /* we found a section, check if we need to do a backup */
  400.             for( i_index = 0; (p_parser = list[i_index]) != NULL; i_index++ )
  401.             {
  402.                 if( ((p_index2 - &p_line[1])
  403.                        == (int)strlen(p_parser->psz_object_name) )
  404.                     && !memcmp( &p_line[1], p_parser->psz_object_name,
  405.                                 strlen(p_parser->psz_object_name) ) )
  406.                 {
  407.                     if( !psz_module_name )
  408.                         break;
  409.                     else if( !strcmp( psz_module_name,
  410.                                       p_parser->psz_object_name ) )
  411.                         break;
  412.                 }
  413.             }
  414.             if( list[i_index] == NULL )
  415.             {
  416.                 /* we don't have this section in our list so we need to back
  417.                  * it up */
  418.                 *p_index2 = 0;
  419. #if 0
  420.                 msg_Dbg( p_this, "backing up config for unknown module "%s"",
  421.                                  &p_line[1] );
  422. #endif
  423.                 *p_index2 = ']';
  424.                 b_backup = true;
  425.             }
  426.             else
  427.             {
  428.                 b_backup = false;
  429.             }
  430.         }
  431.         /* save line if requested and line is valid (doesn't begin with a
  432.          * space, tab, or eol) */
  433.         if( b_backup && (p_line[0] != 'n') && (p_line[0] != ' ')
  434.             && (p_line[0] != 't') )
  435.         {
  436.             strcpy( p_index, p_line );
  437.             p_index += strlen( p_line );
  438.         }
  439.     }
  440.     if( file )
  441.         fclose( file );
  442.     file = NULL;
  443.     /*
  444.      * Save module config in file
  445.      */
  446.     permanent = config_GetConfigFile (p_this);
  447.     if (!permanent)
  448.     {
  449.         module_list_free (list);
  450.         goto error;
  451.     }
  452.     if (asprintf (&temporary, "%s.%u", permanent,
  453. #ifdef UNDER_CE
  454.                   GetCurrentProcessId ()
  455. #else
  456.                   getpid ()
  457. #endif
  458.                  ) == -1)
  459.     {
  460.         temporary = NULL;
  461.         module_list_free (list);
  462.         goto error;
  463.     }
  464.     /* The temporary configuration file is per-PID. Therefore SaveConfigFile()
  465.      * should be serialized against itself within a given process. */
  466.     static vlc_mutex_t lock = VLC_STATIC_MUTEX;
  467.     vlc_mutex_lock (&lock);
  468.     int fd = utf8_open (temporary, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR|S_IWUSR);
  469.     if (fd == -1)
  470.     {
  471.         vlc_mutex_unlock (&lock);
  472.         module_list_free (list);
  473.         goto error;
  474.     }
  475.     file = fdopen (fd, "wt");
  476.     if (file == NULL)
  477.     {
  478.         close (fd);
  479.         vlc_mutex_unlock (&lock);
  480.         module_list_free (list);
  481.         goto error;
  482.     }
  483.     fprintf( file, "xEFxBBxBF###n###  " COPYRIGHT_MESSAGE "n###nn"
  484.        "###n### lines beginning with a '#' character are commentsn###nn" );
  485.     /* Ensure consistent number formatting... */
  486.     locale_t loc = newlocale (LC_NUMERIC_MASK, "C", NULL);
  487.     locale_t baseloc = uselocale (loc);
  488.     /* Look for the selected module, if NULL then save everything */
  489.     for( i_index = 0; (p_parser = list[i_index]) != NULL; i_index++ )
  490.     {
  491.         module_config_t *p_item, *p_end;
  492.         if( psz_module_name && strcmp( psz_module_name,
  493.                                        p_parser->psz_object_name ) )
  494.             continue;
  495.         if( !p_parser->i_config_items )
  496.             continue;
  497.         if( psz_module_name )
  498.             msg_Dbg( p_this, "saving config for module "%s"",
  499.                      p_parser->psz_object_name );
  500.         fprintf( file, "[%s]", p_parser->psz_object_name );
  501.         if( p_parser->psz_longname )
  502.             fprintf( file, " # %snn", p_parser->psz_longname );
  503.         else
  504.             fprintf( file, "nn" );
  505.         for( p_item = p_parser->p_config, p_end = p_item + p_parser->confsize;
  506.              p_item < p_end;
  507.              p_item++ )
  508.         {
  509.             if ((p_item->i_type & CONFIG_HINT) /* ignore hint */
  510.              || p_item->b_removed              /* ignore deprecated option */
  511.              || p_item->b_unsaveable)          /* ignore volatile option */
  512.                 continue;
  513.             vlc_mutex_lock (p_item->p_lock);
  514.             /* Do not save the new value in the configuration file
  515.              * if doing an autosave, and the item is not an "autosaved" one. */
  516.             bool b_retain = b_autosave && !p_item->b_autosave;
  517.             if (IsConfigIntegerType (p_item->i_type))
  518.             {
  519.                 int val = b_retain ? p_item->saved.i : p_item->value.i;
  520.                 if (p_item->i_type == CONFIG_ITEM_KEY)
  521.                 {
  522.                     char *psz_key = ConfigKeyToString (val);
  523.                     config_Write (file, p_item->psz_text, N_("key"),
  524.                                   val == p_item->orig.i,
  525.                                   p_item->psz_name, "%s",
  526.                                   psz_key ? psz_key : "");
  527.                     free (psz_key);
  528.                 }
  529.                 else
  530.                     config_Write (file, p_item->psz_text,
  531.                                   (p_item->i_type == CONFIG_ITEM_BOOL)
  532.                                       ? N_("boolean") : N_("integer"),
  533.                                   val == p_item->orig.i,
  534.                                   p_item->psz_name, "%d", val);
  535.                 p_item->saved.i = val;
  536.             }
  537.             else
  538.             if (IsConfigFloatType (p_item->i_type))
  539.             {
  540.                 float val = b_retain ? p_item->saved.f : p_item->value.f;
  541.                 config_Write (file, p_item->psz_text, N_("float"),
  542.                               val == p_item->orig.f,
  543.                               p_item->psz_name, "%f", val);
  544.                 p_item->saved.f = val;
  545.             }
  546.             else
  547.             {
  548.                 const char *psz_value = b_retain ? p_item->saved.psz
  549.                                                  : p_item->value.psz;
  550.                 bool modified;
  551.                 assert (IsConfigStringType (p_item->i_type));
  552.                 if (b_retain && (psz_value == NULL)) /* FIXME: hack */
  553.                     psz_value = p_item->orig.psz;
  554.                 modified =
  555.                     (psz_value != NULL)
  556.                         ? ((p_item->orig.psz != NULL)
  557.                             ? (strcmp (psz_value, p_item->orig.psz) != 0)
  558.                             : true)
  559.                         : (p_item->orig.psz != NULL);
  560.                 config_Write (file, p_item->psz_text, N_("string"),
  561.                               !modified, p_item->psz_name, "%s",
  562.                               psz_value ? psz_value : "");
  563.                 if ( !b_retain )
  564.                 {
  565.                     free ((char *)p_item->saved.psz);
  566.                     if( (psz_value && p_item->orig.psz &&
  567.                          strcmp( psz_value, p_item->orig.psz )) ||
  568.                         !psz_value || !p_item->orig.psz)
  569.                         p_item->saved.psz = strdupnull (psz_value);
  570.                     else
  571.                         p_item->saved.psz = NULL;
  572.                 }
  573.             }
  574.             if (!b_retain)
  575.                 p_item->b_dirty = false;
  576.             vlc_mutex_unlock (p_item->p_lock);
  577.         }
  578.     }
  579.     module_list_free (list);
  580.     if (loc != (locale_t)0)
  581.     {
  582.         uselocale (baseloc);
  583.         freelocale (loc);
  584.     }
  585.     /*
  586.      * Restore old settings from the config in file
  587.      */
  588.     fputs( p_bigbuffer, file );
  589.     free( p_bigbuffer );
  590.     /*
  591.      * Flush to disk and replace atomically
  592.      */
  593.     fflush (file); /* Flush from run-time */
  594. #ifndef WIN32
  595.     fdatasync (fd); /* Flush from OS */
  596.     /* Atomically replace the file... */
  597.     if (utf8_rename (temporary, permanent))
  598.         utf8_unlink (temporary);
  599.     /* (...then synchronize the directory, err, TODO...) */
  600.     /* ...and finally close the file */
  601.     vlc_mutex_unlock (&lock);
  602. #endif
  603.     fclose (file);
  604. #ifdef WIN32
  605.     /* Windows cannot remove open files nor overwrite existing ones */
  606.     utf8_unlink (permanent);
  607.     if (utf8_rename (temporary, permanent))
  608.         utf8_unlink (temporary);
  609.     vlc_mutex_unlock (&lock);
  610. #endif
  611.     free (temporary);
  612.     free (permanent);
  613.     return 0;
  614. error:
  615.     if( file )
  616.         fclose( file );
  617.     free (temporary);
  618.     free (permanent);
  619.     free( p_bigbuffer );
  620.     return -1;
  621. }
  622. int config_AutoSaveConfigFile( vlc_object_t *p_this )
  623. {
  624.     size_t i_index;
  625.     bool save = false;
  626.     assert( p_this );
  627.     /* Check if there's anything to save */
  628.     module_t **list = module_list_get (NULL);
  629.     for( i_index = 0; list[i_index] && !save; i_index++ )
  630.     {
  631.         module_t *p_parser = list[i_index];
  632.         module_config_t *p_item, *p_end;
  633.         if( !p_parser->i_config_items ) continue;
  634.         for( p_item = p_parser->p_config, p_end = p_item + p_parser->confsize;
  635.              p_item < p_end && !save;
  636.              p_item++ )
  637.         {
  638.             vlc_mutex_lock (p_item->p_lock);
  639.             save = p_item->b_autosave && p_item->b_dirty;
  640.             vlc_mutex_unlock (p_item->p_lock);
  641.         }
  642.     }
  643.     module_list_free (list);
  644.     return save ? VLC_SUCCESS : SaveConfigFile( p_this, NULL, true );
  645. }
  646. int __config_SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name )
  647. {
  648.     return SaveConfigFile( p_this, psz_module_name, false );
  649. }
  650. int ConfigStringToKey( const char *psz_key )
  651. {
  652.     int i_key = 0;
  653.     unsigned int i;
  654.     const char *psz_parser = strchr( psz_key, '-' );
  655.     while( psz_parser && psz_parser != psz_key )
  656.     {
  657.         for( i = 0; i < sizeof(vlc_modifiers) / sizeof(key_descriptor_t); i++ )
  658.         {
  659.             if( !strncasecmp( vlc_modifiers[i].psz_key_string, psz_key,
  660.                               strlen( vlc_modifiers[i].psz_key_string ) ) )
  661.             {
  662.                 i_key |= vlc_modifiers[i].i_key_code;
  663.             }
  664.         }
  665.         psz_key = psz_parser + 1;
  666.         psz_parser = strchr( psz_key, '-' );
  667.     }
  668.     for( i = 0; i < sizeof(vlc_keys) / sizeof( key_descriptor_t ); i++ )
  669.     {
  670.         if( !strcasecmp( vlc_keys[i].psz_key_string, psz_key ) )
  671.         {
  672.             i_key |= vlc_keys[i].i_key_code;
  673.             break;
  674.         }
  675.     }
  676.     return i_key;
  677. }
  678. char *ConfigKeyToString( int i_key )
  679. {
  680.     char *psz_key = malloc( 100 );
  681.     char *p;
  682.     size_t index;
  683.     if ( !psz_key )
  684.     {
  685.         return NULL;
  686.     }
  687.     *psz_key = '';
  688.     p = psz_key;
  689.     for( index = 0; index < (sizeof(vlc_modifiers) / sizeof(key_descriptor_t));
  690.          index++ )
  691.     {
  692.         if( i_key & vlc_modifiers[index].i_key_code )
  693.         {
  694.             p += sprintf( p, "%s-", vlc_modifiers[index].psz_key_string );
  695.         }
  696.     }
  697.     for( index = 0; index < (sizeof(vlc_keys) / sizeof( key_descriptor_t));
  698.          index++)
  699.     {
  700.         if( (int)( i_key & ~KEY_MODIFIER ) == vlc_keys[index].i_key_code )
  701.         {
  702.             p += sprintf( p, "%s", vlc_keys[index].psz_key_string );
  703.             break;
  704.         }
  705.     }
  706.     return psz_key;
  707. }