📄 file.c
字号:
/***************************************************************************** * file.c: configuration file handling ***************************************************************************** * Copyright (C) 2001-2007 the VideoLAN team * $Id: 894ebbb14e081062cd69a7f446e5881b0612b9a4 $ * * Authors: Gildas Bazin <gbazin@videolan.org> * * 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 * (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. * * 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>#ifdef __APPLE__# include <xlocale.h>#else#include <locale.h>#endif#include "configuration.h"#include "modules/modules.h"static char *ConfigKeyToString( int );static inline char *strdupnull (const char *src){ return src ? strdup (src) : NULL;}/** * Get the user's configuration file */static char *config_GetConfigFile( void ){ char *psz_dir = config_GetUserConfDir(); char *psz_configfile; if( asprintf( &psz_configfile, "%s" DIR_SEP CONFIG_FILE, psz_dir ) == -1 ) psz_configfile = NULL; free( psz_dir ); return psz_configfile;}static FILE *config_OpenConfigFile( vlc_object_t *p_obj, const char *mode ){ char *psz_filename = libvlc_priv (p_obj->p_libvlc)->psz_configfile; FILE *p_stream; if( !psz_filename ) { psz_filename = config_GetConfigFile(); } msg_Dbg( p_obj, "opening config file (%s)", psz_filename ); p_stream = utf8_fopen( psz_filename, mode ); 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) ) else if( p_stream == NULL && errno == ENOENT && mode[0] == 'r' ) { /* This is the fallback for pre XDG Base Directory * Specification configs */ char *psz_old; if( asprintf( &psz_old, "%s" DIR_SEP CONFIG_DIR DIR_SEP CONFIG_FILE, config_GetHomeDir() ) != -1 ) { p_stream = utf8_fopen( psz_old, mode ); if( p_stream ) { /* Old config file found. We want to write it at the * new location now. */ 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 ) { FILE *p_readme = utf8_fopen( psz_readme, "wt" ); if( p_readme ) { fprintf( p_readme, "The VLC media player " "configuration folder has moved to comply\n" "with the XDG Base Directory Specification " "version 0.6. Your\nconfiguration has been " "copied to the new location:\n%s\nYou can " "delete this directory and all its contents.", psz_filename); fclose( p_readme ); } free( psz_readme ); } } free( psz_old ); } }#endif else if( p_stream != NULL ) { libvlc_priv (p_obj->p_libvlc)->psz_configfile = psz_filename; } return p_stream;}static int strtoi (const char *str){ char *end; long l; errno = 0; l = strtol (str, &end, 0); if (!errno) { if ((l > INT_MAX) || (l < INT_MIN)) errno = ERANGE; if (*end) errno = EINVAL; } return (int)l;}/***************************************************************************** * 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 ){ libvlc_priv_t *priv = libvlc_priv (p_this->p_libvlc); vlc_list_t *p_list; FILE *file; file = config_OpenConfigFile (p_this, "rt"); if (file == NULL) return VLC_EGENERIC; /* Acquire config file lock */ vlc_mutex_lock( &priv->config_lock ); /* Look for the selected module, if NULL then save everything */ p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE ); /* Look for UTF-8 Byte Order Mark */ char * (*convert) (const char *) = strdupnull; char bom[3]; if ((fread (bom, 1, 3, file) != 3) || memcmp (bom, "\xEF\xBB\xBF", 3)) { convert = FromLocaleDup; rewind (file); /* no BOM, rewind */ } module_t *module = NULL; char line[1024], section[1022]; section[0] = '\0'; /* Ensure consistent number formatting... */ locale_t loc = newlocale (LC_NUMERIC_MASK, "C", NULL); locale_t baseloc = uselocale (loc); while (fgets (line, 1024, file) != NULL) { /* 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; i < p_list->i_count; i++) { module_t *m = (module_t *)p_list->p_values[i].p_object; 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; } } } 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, '='); 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; switch( p_item->i_type ) { 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: vlc_mutex_lock( p_item->p_lock ); /* 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); vlc_mutex_unlock( p_item->p_lock ); break; } break; } } if (ferror (file)) { msg_Err (p_this, "error reading configuration: %m"); clearerr (file); } fclose (file); vlc_list_release( p_list ); if (loc != (locale_t)0) { uselocale (baseloc); freelocale (loc); } vlc_mutex_unlock( &priv->config_lock ); return 0;}/***************************************************************************** * config_CreateDir: Create configuration directory if it doesn't exist. *****************************************************************************/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 ) return 0; switch( errno ) { case EEXIST: return 0; case ENOENT: { /* Let's try to create the parent directory */ char psz_parent[strlen( psz_dirname ) + 1], *psz_end; strcpy( psz_parent, psz_dirname ); psz_end = strrchr( psz_parent, DIR_SEP_CHAR ); if( psz_end && psz_end != psz_parent ) { *psz_end = '\0'; if( config_CreateDir( p_this, psz_parent ) == 0 ) { if( !utf8_mkdir( psz_dirname, 0700 ) ) return 0; } } } } msg_Err( p_this, "could not create %s: %m", psz_dirname ); return -1;}static intconfig_Write (FILE *file, const char *type, const char *desc, bool comment, const char *name, const char *fmt, ...){ va_list ap; int ret; if (desc == NULL) desc = "?"; if (fprintf (file, "# %s (%s)\n%s%s=", desc, _(type), comment ? "#" : "", name) < 0) return -1; va_start (ap, fmt); ret = vfprintf (file, fmt, ap); va_end (ap); if (ret < 0) return -1; if (fputs ("\n\n", file) == EOF) return -1; return 0;}/***************************************************************************** * config_SaveConfigFile: Save a module's config options.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -