inifile.c

来自「一个可以替代windows ODBC驱动程序管理器的通用ODBC数据库引擎」· C语言 代码 · 共 1,268 行 · 第 1/2 页

C
1,268
字号
/* *  inifile.c * *  $Id: inifile.c,v 1.1 2001/06/07 00:48:50 source Exp $ * *  Configuration File Management * *  The iODBC driver manager. * *  Copyright (C) 2001 by OpenLink Software <iodbc@openlinksw.com> * *  This library is free software; you can redistribute it and/or *  modify it under the terms of the GNU Library General Public *  License as published by the Free Software Foundation; either *  version 2 of the License, or (at your option) any later version. * *  This library 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 *  Library General Public License for more details. * *  You should have received a copy of the GNU Library General Public *  License along with this library; if not, write to the Free *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <iodbc.h>#include <iodbcinst.h>#include <stdarg.h>#include <stdio.h>#include <string.h>#ifndef _MAC#include <sys/types.h>#include <sys/stat.h>#endif#include <unistd.h>#include <ctype.h>#include "inifile.h"#include "misc.h"extern BOOL ValidDSN (LPCSTR lpszDSN);static PCFGENTRY __iodbcdm_cfg_poolalloc (PCONFIG p, u_int count);static int __iodbcdm_cfg_parse (PCONFIG pconfig);/*** READ MODULE ****/#ifndef O_BINARY#define O_BINARY 0#endif#ifdef _MACstatic intstrcasecmp (const char *s1, const char *s2){  int cmp;  while (*s1)    {      if ((cmp = toupper (*s1) - toupper (*s2)) != 0)	return cmp;      s1++;      s2++;    }  return (*s2) ? -1 : 0;}#endif/* *  Initialize a configuration */int_iodbcdm_cfg_init (PCONFIG *ppconf, const char *filename, int doCreate){  PCONFIG pconfig;  *ppconf = NULL;  if (!filename)    return -1;  if ((pconfig = (PCONFIG) calloc (1, sizeof (TCONFIG))) == NULL)    return -1;  pconfig->fileName = strdup (filename);  if (pconfig->fileName == NULL)    {      _iodbcdm_cfg_done (pconfig);      return -1;    }  /* If the file does not exist, try to create it */  if (doCreate && access (pconfig->fileName, 0) == -1)    {      int fd;      fd = creat (filename, 0644);      if (fd)	close (fd);    }  if (_iodbcdm_cfg_refresh (pconfig) == -1)    {      _iodbcdm_cfg_done (pconfig);      return -1;    }  *ppconf = pconfig;  return 0;}/* *  Free all data associated with a configuration */int_iodbcdm_cfg_done (PCONFIG pconfig){  if (pconfig)    {      _iodbcdm_cfg_freeimage (pconfig);      if (pconfig->fileName)	free (pconfig->fileName);      free (pconfig);    }  return 0;}/* *  Free the content specific data of a configuration */int_iodbcdm_cfg_freeimage (PCONFIG pconfig){  char *saveName;  PCFGENTRY e;  u_int i;  if (pconfig->image)    free (pconfig->image);  if (pconfig->entries)    {      e = pconfig->entries;      for (i = 0; i < pconfig->numEntries; i++, e++)	{	  if (e->flags & CFE_MUST_FREE_SECTION)	    free (e->section);	  if (e->flags & CFE_MUST_FREE_ID)	    free (e->id);	  if (e->flags & CFE_MUST_FREE_VALUE)	    free (e->value);	  if (e->flags & CFE_MUST_FREE_COMMENT)	    free (e->comment);	}      free (pconfig->entries);    }  saveName = pconfig->fileName;  memset (pconfig, 0, sizeof (TCONFIG));  pconfig->fileName = saveName;  return 0;}/* *  This procedure reads an copy of the file into memory *  caching the content based on stat */int_iodbcdm_cfg_refresh (PCONFIG pconfig){  struct stat sb;  char *mem;  int fd;  if (pconfig == NULL || stat (pconfig->fileName, &sb) == -1)    return -1;  /*   *  If our image is dirty, ignore all local changes   *  and force a reread of the image, thus ignoring all mods   */  if (pconfig->dirty)    _iodbcdm_cfg_freeimage (pconfig);  /*   *  Check to see if our incore image is still valid   */  if (pconfig->image && sb.st_size == pconfig->size      && sb.st_mtime == pconfig->mtime)    return 0;  /*   *  Now read the full image   */  if ((fd = open (pconfig->fileName, O_RDONLY | O_BINARY)) == -1)    return -1;  mem = (char *) malloc (sb.st_size + 1);  if (mem == NULL || read (fd, mem, sb.st_size) != sb.st_size)    {      free (mem);      close (fd);      return -1;    }  mem[sb.st_size] = 0;  close (fd);  /*   *  Store the new copy   */  _iodbcdm_cfg_freeimage (pconfig);  pconfig->image = mem;  pconfig->size = sb.st_size;  pconfig->mtime = sb.st_mtime;  if (__iodbcdm_cfg_parse (pconfig) == -1)    {      _iodbcdm_cfg_freeimage (pconfig);      return -1;    }  return 1;}#define iseolchar(C) (strchr ("\n\r\x1a", C) != NULL)#define iswhite(C) (strchr ("\f\t ", C) != NULL)static char *__iodbcdm_cfg_skipwhite (char *s){  while (*s && iswhite (*s))    s++;  return s;}static int__iodbcdm_cfg_getline (char **pCp, char **pLinePtr){  char *start;  char *cp = *pCp;  while (*cp && iseolchar (*cp))    cp++;  start = cp;  if (pLinePtr)    *pLinePtr = cp;  while (*cp && !iseolchar (*cp))    cp++;  if (*cp)    {      *cp++ = 0;      *pCp = cp;      while (--cp >= start && iswhite (*cp));      cp[1] = 0;    }  else    *pCp = cp;  return *start ? 1 : 0;}static char *rtrim (char *str){  char *endPtr;  if (str == NULL || *str == '\0')    return NULL;  for (endPtr = &str[strlen (str) - 1]; endPtr >= str && isspace (*endPtr);      endPtr--);  endPtr[1] = 0;  return endPtr >= str ? endPtr : NULL;}/* *  Parse the in-memory copy of the configuration data */static int__iodbcdm_cfg_parse (PCONFIG pconfig){  int isContinue, inString;  char *imgPtr;  char *endPtr;  char *lp;  char *section;  char *id;  char *value;  char *comment;  if (_iodbcdm_cfg_valid (pconfig))    return 0;  endPtr = pconfig->image + pconfig->size;  for (imgPtr = pconfig->image; imgPtr < endPtr;)    {      if (!__iodbcdm_cfg_getline (&imgPtr, &lp))	continue;      section = id = value = comment = NULL;      /*         *  Skip leading spaces       */      if (iswhite (*lp))	{	  lp = __iodbcdm_cfg_skipwhite (lp);	  isContinue = 1;	}      else	isContinue = 0;      /*       *  Parse Section       */      if (*lp == '[')	{	  section = __iodbcdm_cfg_skipwhite (lp + 1);	  if ((lp = strchr (section, ']')) == NULL)	    continue;	  *lp++ = 0;	  if (rtrim (section) == NULL)	    {	      section = NULL;	      continue;	    }	  lp = __iodbcdm_cfg_skipwhite (lp);	}      else if (*lp != ';')	{	  /* Try to parse	   *   1. Key = Value	   *   2. Value (iff isContinue)	   */	  if (!isContinue)	    {	      /* Parse `<Key> = ..' */	      id = lp;	      if ((lp = strchr (id, '=')) == NULL)		continue;	      *lp++ = 0;	      rtrim (id);	      lp = __iodbcdm_cfg_skipwhite (lp);	    }	  /* Parse value */	  inString = 0;	  value = lp;	  while (*lp)	    {	      if (inString)		{		  if (*lp == inString)		    inString = 0;		}	      else if (*lp == '"' || *lp == '\'')		inString = *lp;	      else if (*lp == ';' && iswhite (lp[-1]))		{		  *lp = 0;		  comment = lp + 1;		  rtrim (value);		  break;		}	      lp++;	    }	}      /*       *  Parse Comment       */      if (*lp == ';')	comment = lp + 1;      if (_iodbcdm_cfg_storeentry (pconfig, section, id, value, comment,	      0) == -1)	{	  pconfig->dirty = 1;	  return -1;	}    }  pconfig->flags |= CFG_VALID;  return 0;}int_iodbcdm_cfg_storeentry (    PCONFIG pconfig,    char *section,    char *id,    char *value,    char *comment,    int dynamic){  PCFGENTRY data;  if ((data = __iodbcdm_cfg_poolalloc (pconfig, 1)) == NULL)    return -1;  data->flags = 0;  if (dynamic)    {      if (section)	section = strdup (section);      if (id)	id = strdup (id);      if (value)	value = strdup (value);      if (comment)	comment = strdup (value);      if (section)	data->flags |= CFE_MUST_FREE_SECTION;      if (id)	data->flags |= CFE_MUST_FREE_ID;      if (value)	data->flags |= CFE_MUST_FREE_VALUE;      if (comment)	data->flags |= CFE_MUST_FREE_COMMENT;    }  data->section = section;  data->id = id;  data->value = value;  data->comment = comment;  return 0;}static PCFGENTRY__iodbcdm_cfg_poolalloc (PCONFIG p, u_int count){  PCFGENTRY newBase;  u_int newMax;  if (p->numEntries + count > p->maxEntries)    {      newMax =	  p->maxEntries ? count + p->maxEntries + p->maxEntries / 2 : count +	  4096 / sizeof (TCFGENTRY);      newBase = (PCFGENTRY) malloc (newMax * sizeof (TCFGENTRY));      if (newBase == NULL)	return NULL;      if (p->entries)	{	  memcpy (newBase, p->entries, p->numEntries * sizeof (TCFGENTRY));	  free (p->entries);	}      p->entries = newBase;      p->maxEntries = newMax;    }  newBase = &p->entries[p->numEntries];  p->numEntries += count;  return newBase;}/*** COMPATIBILITY LAYER ***/int_iodbcdm_cfg_rewind (PCONFIG pconfig){  if (!_iodbcdm_cfg_valid (pconfig))    return -1;  pconfig->flags = CFG_VALID;  pconfig->cursor = 0;  return 0;}/* *  returns: *	 0 success *	-1 no next entry * *	section	id	value	flags		meaning *	!0	0	!0	SECTION		[value] *	!0	!0	!0	DEFINE		id = value|id="value"|id='value' *	!0	0	!0	0		value *	0	0	0	EOF		end of file encountered */int_iodbcdm_cfg_nextentry (PCONFIG pconfig){  PCFGENTRY e;  if (!_iodbcdm_cfg_valid (pconfig) || _iodbcdm_cfg_eof (pconfig))    return -1;  pconfig->flags &= ~(CFG_TYPEMASK);  pconfig->id = pconfig->value = NULL;  while (1)    {      if (pconfig->cursor >= pconfig->numEntries)	{	  pconfig->flags |= CFG_EOF;	  return -1;	}      e = &pconfig->entries[pconfig->cursor++];      if (e->section)	{	  pconfig->section = e->section;	  pconfig->flags |= CFG_SECTION;	  return 0;	}      if (e->value)	{	  pconfig->value = e->value;	  if (e->id)	    {	      pconfig->id = e->id;	      pconfig->flags |= CFG_DEFINE;	    }	  else	    pconfig->flags |= CFG_CONTINUE;	  return 0;	}    }}int_iodbcdm_cfg_find (PCONFIG pconfig, char *section, char *id){  int atsection;  if (!_iodbcdm_cfg_valid (pconfig) || _iodbcdm_cfg_rewind (pconfig))    return -1;  atsection = 0;  while (_iodbcdm_cfg_nextentry (pconfig) == 0)    {      if (atsection)	{	  if (_iodbcdm_cfg_section (pconfig))	    return -1;	  else if (_iodbcdm_cfg_define (pconfig))	    {	      char *szId = _iodbcdm_remove_quotes (pconfig->id);	      int bSame;	      if (szId)		{		  bSame = !strcasecmp (szId, id);		  free (szId);		  if (bSame)		    return 0;		}	    }	}      else if (_iodbcdm_cfg_section (pconfig)	  && !strcasecmp (pconfig->section, section))	{	  if (id == NULL)	    return 0;	  atsection = 1;	}    }  return -1;}/*** WRITE MODULE ****//* *  Change the configuration * *  section id    value		action *  -------------------------------------------------------------------------- *   value  value value		update '<entry>=<string>' in section <section> *   value  value NULL		delete '<entry>' from section <section> *   value  NULL  NULL		delete section <section> */int_iodbcdm_cfg_write (    PCONFIG pconfig,    char *section,    char *id,    char *value){  PCFGENTRY e, e2, eSect;  int idx;  int i;  if (!_iodbcdm_cfg_valid (pconfig) || section == NULL)    return -1;  /* find the section */  e = pconfig->entries;  i = pconfig->numEntries;  eSect = 0;  while (i--)    {      if (e->section && !strcasecmp (e->section, section))	{	  eSect = e;	  break;	}      e++;    }  /* did we find the section? */  if (!eSect)    {      /* check for delete operation on a nonexisting section */      if (!id || !value)	return 0;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?