⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ioconf.c

📁 linux下查看系统工具原码,如IOSTAT等
💻 C
字号:
/* * ioconf: ioconf configuration file handling code * Original code (C) 2004 by Red Hat (Charlie Bennett <ccb@redhat.com>) * * Modified and maintained by Sebastien GODARD (sysstat <at> wanadoo.fr) * *************************************************************************** * 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 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., * * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA                   * *************************************************************************** */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <linux/major.h>#include "ioconf.h"#ifdef USE_NLS#include <locale.h>#include <libintl.h>#define _(string) gettext(string)#else#define _(string) (string)#endifstatic unsigned int ioc_parsed = 0;static struct ioc_entry *ioconf[MAX_BLKDEV + 1];/* *************************************************************************** * Free ioc_entry structures *************************************************************************** */static void ioc_free(void){   unsigned int i;   struct ioc_entry **p;   /* Take out all of the references first */   for (i = 0, p = ioconf; i < MAX_BLKDEV; ++i, ++p) {      if ((*p == NULL) || ((*p)->live))	 continue;      if ((*p)->desc != (*p)->blkp->desc) {	 /* Not a shared description */	 free((*p)->desc);      }      free(*p);      *p = NULL;   }   /* Now the live ones */   for (i = 0, p = ioconf; i < MAX_BLKDEV; ++i, ++p) {      if (*p == NULL)	 continue;      free((*p)->blkp);      free(*p);      *p = NULL;   }}/* *************************************************************************** * ioc_conv - Turn a number into a string in radix <radix> using symbol *   set (and ordering) syms.  Use nozero to generate strings *   in which the number system uses a single sym for the *   radix value (not 2, like decimal) and adds a column only *   at radix+1.  If decimal were like this: * *   (no zero) 1 2 3 4 5 6 7 8 9 0 11 12 13 14 15 16 17 18 19 10 ... *************************************************************************** */static char *ioc_conv(int radix, int nozero, const char *syms,		      unsigned int val){   static char out[17];   char *p;   int j;   *(p = out + 16) = '\0';   val += nozero;   if (val == 0) {      if (!nozero) {	 *--p = '0';      }      return (p);	/* Empty string if nozero radix gets val == 0 */   }   while (val > 0) {      *--p = syms[j = val % radix];      val /= radix;      if (nozero && (j == 0)) {	 /* Comp for 10 in nozero bases */	 --val;      }   }   return (p);}char *ioc_ito10(unsigned int n){   return (ioc_conv(10, 0, "0123456789", n));}char *ioc_ito26(unsigned int n){   return (ioc_conv(26, 1, "zabcdefghijklmnopqrstuvwxy", n));}/* *************************************************************************** * ioc_init() - internalize the ioconf file * * given:    void * does:     parses IOCONF into ioconf, an array of ioc_entry * *           Only entries having lines in IOCONF will have valid pointers * return:   1 on success *           0 on failure *************************************************************************** */int ioc_init(void){   FILE	*fp;   unsigned int	i, major, indirect, count = 0;   char	buf[IOC_LINESIZ + 1];   char	cfmt[IOC_FMTLEN + 1];   char	dfmt[IOC_FMTLEN + 1];   char	pfmt[IOC_FMTLEN + 1];   char	desc[IOC_DESCLEN + 1];   struct ioc_entry  *iocp = NULL;   struct blk_config *blkp = NULL;   if ((fp = fopen(IOCONF, "r")) == NULL)      return 0;   while (fgets(buf, IOC_LINESIZ, fp)) {      if ((*buf == '#') || (*buf == '\n'))	 continue;      /*       * Preallocate some (probably) needed data structures       */      IOC_ALLOC(blkp, struct blk_config, BLK_CONFIG_SIZE);      IOC_ALLOC(iocp, struct ioc_entry, IOC_ENTRY_SIZE);      memset(blkp, 0, BLK_CONFIG_SIZE);      memset(iocp, 0, IOC_ENTRY_SIZE);      i = sscanf(buf, "%u:%u:%u:%s",		 &major, &indirect, &iocp->ctrlno, desc);      if (i != 4) {	 i = sscanf(buf, "%u:%u:%u",		    &major, &indirect, &iocp->ctrlno);      }      if ((i == 3) || (i == 4)) {	 /* indirect record */	 if (indirect == 0) {	    /* conventional usage for unsupported device */	    continue;	 }	 if (indirect >= MAX_BLKDEV) {	    fprintf(stderr, "%s: Indirect major #%u out of range\n",		    IOCONF, indirect);	    continue;	 }	 if (ioconf[indirect] == NULL) {	    fprintf(stderr,		    "%s: Indirect record '%u:%u:%u:...'"		    " references not yet seen major %u\n",		    IOCONF, major, indirect, iocp->ctrlno, major);	    continue;	 }	 /*	  * Cool. Point this device at its referent.	  * Skip last: (last field my be empty...)	  * if it was empty and : was in the sscanf spec	  * we'd only see 3 fields...	  */	 if (i == 3) {	    /* reference the mothership */	    iocp->desc = ioconf[indirect]->blkp->desc;	 }	 else {	    IOC_ALLOC(iocp->desc, char, IOC_DESCLEN + 1);	    strncpy(iocp->desc, desc, IOC_DESCLEN);	 }	 ioconf[major] = iocp;	 iocp->blkp = ioconf[indirect]->blkp;	 iocp->live = 0;	 iocp = NULL;	 continue;	 /* all done with indirect record */      }      /* maybe it's a full record? */      i = sscanf(buf, "%u:%[^:]:%[^:]:%d:%[^:]:%u:%[^:]:%u:%s",		 &major, blkp->name,		 cfmt, &iocp->ctrlno,		 dfmt, &blkp->dcount,		 pfmt, &blkp->pcount,		 desc);      if (i != 9) {	 fprintf(stderr, "%s: Malformed %d field record: %s\n",		 IOCONF, i, buf);	 continue;      }      /* this is a full-fledged direct record */      if ((major == 0) || (major >= MAX_BLKDEV)) {	 fprintf(stderr, "%s: major #%u out of range\n",		 __FUNCTION__, major);	 continue;      }      /* is this an exception record? */      if (*cfmt == 'x') {	 struct blk_config *xblkp;	 /*	  * device has an aliased minor	  * for now we only support on exception per major	  * (catering to initrd: (1,250))	  */	 if (ioconf[major] == NULL) {	    fprintf(stderr, "%s: type 'x' record for"		    " major #%u must follow the base record - ignored\n",		    IOCONF, major);	    continue;	 }	 xblkp = ioconf[major]->blkp;	 if (xblkp->ext) {	    /*	     * Enforce one minor exception per major policy	     * note: this applies to each major number and	     * all of it's indirect (short form) majors	     */	    fprintf(stderr, "%s: duplicate 'x' record for"		    " major #%u - ignored\ninput line: %s\n",		    IOCONF, major, buf);	    continue;	 }	 /*	  * Decorate the base major struct with the	  * exception info	  */	 xblkp->ext_minor = iocp->ctrlno;	 strcpy(xblkp->ext_name, blkp->name);	 xblkp->ext = 1;	 continue;      }      /*       * Preformat the sprintf format strings for generating       * c-d-p info in ioc_name()       */      /* basename of device + provided string + controller # */      if (*cfmt == '*') {	 strcpy(blkp->cfmt, blkp->name);      }      else {	 sprintf(blkp->cfmt, "%s%s%%d", blkp->name, cfmt);	 ++(blkp->ctrl_explicit);      }      /* Disk */      *blkp->dfmt = '\0';      switch (*dfmt) {       case 'a':	 blkp->cconv = ioc_ito26;	 strcpy(blkp->dfmt, "%s");	 break;       case '%':	 strcpy(blkp->dfmt, dfmt + 1);       case 'd':	 blkp->cconv = ioc_ito10;	 strcat(blkp->dfmt, "%s");	 break;      }      /* Partition */      sprintf(blkp->pfmt, "%s%%d", (*pfmt == '*') ? "" : pfmt);      /*       * We're good to go.       * Stuff the ioc_entry and ref it.       */      iocp->live = 1;      iocp->blkp = blkp;      iocp->desc = NULL;      ioconf[major] = iocp;      strncpy(blkp->desc, desc, IOC_DESCLEN);      blkp = NULL; iocp = NULL;      ++count;   }   fclose(fp);   /*    * These will become leaks if we ever 'continue'    * after IOC_ALLOC( blkp->desc ... ).    * Right Now, we don't.    */   if (blkp != NULL)      free(blkp);   if (iocp != NULL)      free(iocp);   /* Indicate that ioconf file has been parsed */   ioc_parsed = 1;   return (count);}/* *************************************************************************** *  ioc_name() - Generate a name from a maj,min pair * *  Returns NULL if major or minor are out of range *  otherwise returns a pointer to a static string containing *  the generated name. *************************************************************************** */char *ioc_name(unsigned int major, unsigned int minor){   static char name[IOC_DEVLEN + 1];   struct ioc_entry *p;   int base, offset;   if ((MAX_BLKDEV <= major) || (IOC_MAXMINOR <= minor)) {      return (NULL);   }   if (!ioc_parsed && !ioc_init())      return (NULL);   p = ioconf[major];   /* Invalid major or minor numbers? */   if ((p == NULL) || (minor >= (p->blkp->dcount * p->blkp->pcount))) {      /*       * That minor test is only there for IDE-style devices       *  that have no minors over 128.       */      strcpy(name, K_NODEV);      return (name);   }   /* Is this an extension record? */   if (p->blkp->ext && (p->blkp->ext_minor == minor)) {      strcpy(name, p->blkp->ext_name);      return (name);   }   /* OK.  we're doing an actual device name... */   /*    * Assemble base + optional controller info    * this is of course too clever by half    * the parser has already cooked cfmt, dfmt to make this easy    * (we parse once but may generate lots of names)    */   base = p->ctrlno * p->blkp->dcount;   offset = minor / p->blkp->pcount;   if (!p->blkp->ctrl_explicit)      offset += base;   /*    * These sprintfs can't be coalesced because the first might    * ignore its first arg    */   sprintf(name, p->blkp->cfmt, p->ctrlno);   sprintf(name + strlen(name), p->blkp->dfmt, p->blkp->cconv(offset));   if (!IS_WHOLE(major, minor)) {      /*       * Tack on partition info, format string cooked (curried?) by       * the parser       */      sprintf(name + strlen(name), p->blkp->pfmt, minor % p->blkp->pcount);   }   return (name);}/* *************************************************************************** * Predicate: Returns 1 if dev (major,minor) is a whole disk device. *            Returns 0 otherwise. *************************************************************************** */int ioc_iswhole(unsigned int major, unsigned int minor){   if (!ioc_parsed && !ioc_init())      return 0;   if (major >= MAX_BLKDEV)      /*       * Later: Handle Linux long major numbers here.       * Now: This is an error.       */      return 0;   if (ioconf[major] == NULL)      /* Device not registered */      return 0 ;  return (IS_WHOLE(major, minor));}

⌨️ 快捷键说明

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