[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] porting xen-detect ASM code into a shared library
Hello list.I'm trying to port xen-detect.c ASM code into cfengine, which is currently build as a shared library. However, I'm facing a compilation error: misc.c: In function 'Xen_cpuid':misc.c:1376: error: can't find a register in class 'BREG' while reloading 'asm' misc.c:1376: error: 'asm' operand has impossible constraintsFrom http://sam.zoy.org/blog/2007-04-13-shlib-with-non-pic-code-have-inline-assembly-and-pic-mix-well, it appears to be caused by the mix of -fPIC flag (mandatory for shared libraries in linux distributions), and the use of ebx register. Given than I'm quite clueless about ASM, I can't figure out how to solve this issue. Also, I slightly modified xen-detect.c code to better integration with cfengine code (dropped pv_context flags, as pv host are already detected by presence of /proc/xen entry, and turned method signature to non-static). Just tell me if I did something wrong. Lastly, is this ASM code supposed to be portable among various Unix and architectures ? Original file + patch included. Any help welcome. -- Guillaume Rousse Moyens Informatiques - INRIA Futurs Tel: 01 69 35 69 62 diff -Naur --exclude '*~' --exclude '.*' cfengine-2.2.7/src/misc.c cfengine-2.2.7-better-xen-detection/src/misc.c --- cfengine-2.2.7/src/misc.c 2008-04-23 19:28:51.000000000 +0200 +++ cfengine-2.2.7-better-xen-detection/src/misc.c 2008-07-10 11:11:31.000000000 +0200 @@ -587,10 +587,16 @@ if (stat("/proc/xen/capabilities",&statbuf) != -1) { - Verbose("\nThis appears to be a xen system.\n"); + Verbose("\nThis appears to be a xen pv system.\n"); AddClassToHeap("xen"); Xen_domain(); } +else if (Xen_hv_check()) + { + Verbose("\nThis appears to be a xen hv system.\n"); + AddClassToHeap("xen"); + AddClassToHeap("xen_domu_hv"); + } } @@ -1356,10 +1362,38 @@ } if (sufficient < 1) { - AddClassToHeap("xen_domu"); + AddClassToHeap("xen_domu_pv"); sufficient = 1; } } return sufficient < 1 ? 1 : 0; } + +void Xen_cpuid(uint32_t idx, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, + uint32_t *edx) +{ + asm volatile ( + "test %1,%1 ; jz 1f ; ud2a ; .ascii \"xen\" ; 1: cpuid" + : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) + : "0" (idx), "1" (0) ); +} + +int Xen_hv_check(void) + +{ + uint32_t eax, ebx, ecx, edx; + char signature[13]; + + Xen_cpuid(0x40000000, &eax, &ebx, &ecx, &edx); + *(uint32_t *)(signature + 0) = ebx; + *(uint32_t *)(signature + 4) = ecx; + *(uint32_t *)(signature + 8) = edx; + signature[12] = '\0'; + + if ( strcmp("XenVMMXenVMM", signature) || (eax < 0x40000002) ) + return 0; + + Xen_cpuid(0x40000001, &eax, &ebx, &ecx, &edx); + return 1; +} /* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 PARTICULARmandar 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 */ /*********************************************************************/ /* */ /* TOOLKITS: "object" library */ /* */ /*********************************************************************/ #include "cf.defs.h" #include "cf.extern.h" #include "../pub/global.h" #include <db.h> /*********************************************************************/ /* TOOLKIT : files/directories */ /*********************************************************************/ int DirPush(char *name,struct stat *sb) /* Enter dir and check for race exploits */ { if (chdir(name) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Could not change to directory %s, mode %o in tidy",name,sb->st_mode & 07777); CfLog(cfinform,OUTPUT,"chdir"); return false; } else { Debug("Changed directory to %s\n",name); } CheckLinkSecurity(sb,name); return true; } /**********************************************************************/ void DirPop(int goback,char * name,struct stat *sb) /* Exit dir and check for race exploits */ { if (goback && TRAVLINKS) { if (chdir(name) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Error in backing out of recursive descent securely to %s",name); CfLog(cferror,OUTPUT,"chdir"); HandleSignal(SIGTERM); } CheckLinkSecurity(sb,name); } else if (goback) { if (chdir("..") == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Error in backing out of recursive descent securely to %s",name); CfLog(cferror,OUTPUT,"chdir"); HandleSignal(SIGTERM); } } } /**********************************************************************/ void CheckLinkSecurity(struct stat *sb,char *name) { struct stat security; Debug("Checking the inode and device to make sure we are where we think we are...\n"); if (stat(".",&security) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Could not stat directory %s after entering!",name); CfLog(cferror,OUTPUT,"stat"); return; } if ((sb->st_dev != security.st_dev) || (sb->st_ino != security.st_ino)) { snprintf(OUTPUT,CF_BUFSIZE,"SERIOUS SECURITY ALERT: path race exploited in recursion to/from %s. Not safe for agent to continue - aborting",name); CfLog(cferror,OUTPUT,""); HandleSignal(SIGTERM); /* Exits */ } } /**********************************************************************/ void TruncateFile(char *name) { struct stat statbuf; int fd; if (stat(name,&statbuf) == -1) { Debug2("cfengine: didn't find %s to truncate\n",name); return; } else { if ((fd = creat(name,000)) == -1) /* dummy mode ignored */ { snprintf(OUTPUT,CF_BUFSIZE*2,"creat(%s) failed\n",name); CfLog(cferror,OUTPUT,"creat"); } else { close(fd); } } } /*************************************************************************/ int FileSecure (char *name) { struct stat statbuf; if (PARSEONLY || !CFPARANOID) { return true; } if (stat(name,&statbuf) == -1) { return false; } if (statbuf.st_uid != getuid()) { snprintf(OUTPUT,CF_BUFSIZE*2,"File %s is not owned by uid %d (security exception)",name,getuid()); CfLog(cferror,OUTPUT,""); } /* Is the file writable by ANYONE except the owner ? */ if (statbuf.st_mode & (S_IWGRP | S_IWOTH)) { snprintf(OUTPUT,CF_BUFSIZE*2,"File %s (owner %d) is writable by others (security exception)",name,getuid()); CfLog(cferror,OUTPUT,""); return false; } return true; } /*************************************************************************/ int IgnoredOrExcluded(enum actions action,char *file,struct Item *inclusions,struct Item *exclusions) { char *lastnode; Debug("IgnoredOrExcluded(%s)\n",file); if (strstr(file,"/")) { for (lastnode = file+strlen(file); *lastnode != '/'; lastnode--) { } lastnode++; } else { lastnode = file; } if ((inclusions != NULL) && !IsWildItemIn(inclusions,lastnode)) { Debug("cfengine: skipping non-included pattern %s\n",file); return true; } switch(action) { case image: if (IsWildItemIn(VEXCLUDECOPY,lastnode) || IsWildItemIn(exclusions,lastnode)) { Debug("Skipping excluded pattern %s\n",file); return true; } break; case links: if (IsWildItemIn(VEXCLUDELINK,lastnode) || IsWildItemIn(exclusions,lastnode)) { Debug("Skipping excluded pattern %s\n",file); return true; } break; default: if (IsWildItemIn(exclusions,lastnode)) { Debug("Skipping excluded pattern %s\n",file); return true; } } return false; } /*********************************************************************/ void Banner(char *string) { Verbose("---------------------------------------------------------------------\n"); Verbose("%s\n",string); Verbose("---------------------------------------------------------------------\n\n"); } /*******************************************************************/ int ShellCommandReturnsZero(char *comm,int useshell) { int status, i, argc = 0; pid_t pid; char arg[CF_MAXSHELLARGS][CF_BUFSIZE]; char **argv; if (!useshell) { /* Build argument array */ for (i = 0; i < CF_MAXSHELLARGS; i++) { memset (arg[i],0,CF_BUFSIZE); } argc = SplitCommand(comm,arg); if (argc == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Too many arguments in %s\n",comm); CfLog(cferror,OUTPUT,""); return false; } } if ((pid = fork()) < 0) { FatalError("Failed to fork new process"); } else if (pid == 0) /* child */ { if (useshell) { if (execl("/bin/sh","sh","-c",comm,NULL) == -1) { yyerror("script failed"); perror("execl"); exit(1); } } else { argv = (char **) malloc((argc+1)*sizeof(char *)); if (argv == NULL) { FatalError("Out of memory"); } for (i = 0; i < argc; i++) { argv[i] = arg[i]; } argv[i] = (char *) NULL; if (execv(arg[0],argv) == -1) { yyerror("script failed"); perror("execvp"); exit(1); } free((char *)argv); } } else /* parent */ { pid_t wait_result; while ((wait_result = wait(&status)) != pid) { if (wait_result <= 0) { snprintf(OUTPUT,CF_BUFSIZE,"Wait for child failed\n"); CfLog(cfinform,OUTPUT,"wait"); return false; } } if (WIFSIGNALED(status)) { Debug("Script %s returned: %d\n",comm,WTERMSIG(status)); return false; } if (! WIFEXITED(status)) { return false; } if (WEXITSTATUS(status) == 0) { Debug("Shell command returned 0\n"); return true; } else { Debug("Shell command was non-zero: %d\n",WEXITSTATUS(status)); return false; } } return false; } /*********************************************************************/ void SetClassesOnScript(char *execstr,char *classes,char *elseclasses,int useshell) { FILE *pp; int print; char line[CF_BUFSIZE],*sp; switch (useshell) { case 'y': pp = cfpopen_sh(execstr,"r"); break; default: pp = cfpopen(execstr,"r"); break; } if (pp == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open pipe to command %s\n",execstr); CfLog(cferror,OUTPUT,"popen"); return; } while (!feof(pp)) { if (ferror(pp)) /* abortable */ { snprintf(OUTPUT,CF_BUFSIZE*2,"Shell command pipe %s\n",execstr); CfLog(cferror,OUTPUT,"ferror"); break; } ReadLine(line,CF_BUFSIZE,pp); if (strstr(line,"cfengine-die")) { break; } if (ferror(pp)) /* abortable */ { snprintf(OUTPUT,CF_BUFSIZE*2,"Shell command pipe %s\n",execstr); CfLog(cferror,OUTPUT,"ferror"); break; } /* * Dumb script - echo non-empty lines to standard output. */ print = false; for (sp = line; *sp != '\0'; sp++) { if (! isspace((int)*sp)) { print = true; break; } } if (print) { Verbose("%s:%s: %s\n",VPREFIX,execstr,line); } } cfpclose_def(pp,classes,elseclasses); } /*********************************************************************/ char *UnQuote(char *s) { if (s[strlen(s)-1] == '\"') { s[strlen(s)-1] = '\0'; } if (s[0] == '\"') { return s+1; } else { return s; } } /*********************************************************************/ void AddListSeparator(char *s) { if (s[strlen(s)-1] != LISTSEPARATOR) { s[strlen(s)+1] = '\0'; s[strlen(s)] = LISTSEPARATOR; } } /*********************************************************************/ void ChopListSeparator(char *s) { if (s[strlen(s)-1] == LISTSEPARATOR) { s[strlen(s)-1] = '\0'; } } /*******************************************************************/ void IDClasses() { struct stat statbuf; char *sp; int i = 0; AddClassToHeap("any"); /* This is a reserved word / wildcard */ snprintf(VBUFF,CF_BUFSIZE,"cfengine_%s",CanonifyName(VERSION)); AddClassToHeap(VBUFF); for (sp = VBUFF+strlen(VBUFF); i < 2; sp--) { if (*sp == '_') { i++; *sp = '\0'; AddClassToHeap(VBUFF); } } #ifdef LINUX /* {Mandrake,Fedora} has a symlink at /etc/redhat-release pointing to * /etc/{mandrake,fedora}-release, so we else-if around that */ if (stat("/etc/mandrake-release",&statbuf) != -1) { Verbose("This appears to be a mandrake system.\n"); AddClassToHeap("Mandrake"); linux_mandrake_version(); } else if (stat("/etc/fedora-release",&statbuf) != -1) { Verbose("This appears to be a fedora system.\n"); AddClassToHeap("redhat"); AddClassToHeap("fedora"); linux_fedora_version(); } else if (stat("/etc/redhat-release",&statbuf) != -1) { Verbose("This appears to be a redhat system.\n"); AddClassToHeap("redhat"); linux_redhat_version(); } if (stat("/etc/generic-release",&statbuf) != -1) { Verbose("\nThis appears to be a sun cobalt system.\n"); AddClassToHeap("SunCobalt"); } if (stat("/etc/SuSE-release",&statbuf) != -1) { Verbose("\nThis appears to be a SuSE system.\n"); AddClassToHeap("SuSE"); linux_suse_version(); } #define SLACKWARE_ANCIENT_VERSION_FILENAME "/etc/slackware-release" #define SLACKWARE_VERSION_FILENAME "/etc/slackware-version" if (stat(SLACKWARE_VERSION_FILENAME,&statbuf) != -1) { Verbose("\nThis appears to be a slackware system.\n"); AddClassToHeap("slackware"); linux_slackware_version(SLACKWARE_VERSION_FILENAME); } else if (stat(SLACKWARE_ANCIENT_VERSION_FILENAME,&statbuf) != -1) { Verbose("\nThis appears to be an ancient slackware system.\n"); AddClassToHeap("slackware"); linux_slackware_version(SLACKWARE_ANCIENT_VERSION_FILENAME); } if (stat("/etc/generic-release",&statbuf) != -1) { Verbose("\nThis appears to be a sun cobalt system.\n"); AddClassToHeap("SunCobalt"); } if (stat("/etc/debian_version",&statbuf) != -1) { Verbose("\nThis appears to be a debian system.\n"); AddClassToHeap("debian"); debian_version(); } if (stat("/etc/UnitedLinux-release",&statbuf) != -1) { Verbose("\nThis appears to be a UnitedLinux system.\n"); AddClassToHeap("UnitedLinux"); } if (stat("/etc/gentoo-release",&statbuf) != -1) { Verbose("\nThis appears to be a gentoo system.\n"); AddClassToHeap("gentoo"); } lsb_version(); #endif if (stat("/proc/vmware/version",&statbuf) != -1 || stat("/etc/vmware-release",&statbuf) != -1) { Verbose("\nThis appears to be a VMware Server ESX system.\n"); AddClassToHeap("VMware"); VM_version(); } else if (stat("/etc/vmware",&statbuf) != -1) { if (S_ISDIR(statbuf.st_mode)) { Verbose("\nThis appears to be a VMware xSX system.\n"); AddClassToHeap("VMware"); VM_version(); } } if (stat("/proc/xen/capabilities",&statbuf) != -1) { Verbose("\nThis appears to be a xen system.\n"); AddClassToHeap("xen"); Xen_domain(); } } /*********************************************************************************/ int linux_fedora_version(void) { #define FEDORA_ID "Fedora" #define RELEASE_FLAG "release " /* We are looking for one of the following strings... * * Fedora Core release 1 (Yarrow) * Fedora release 7 (Zodfoobar) */ #define FEDORA_REL_FILENAME "/etc/fedora-release" FILE *fp; /* The full string read in from fedora-release */ char relstring[CF_MAXVARSIZE]; char classbuf[CF_MAXVARSIZE]; /* Fedora */ char *vendor=""; /* Where the numerical release will be found */ char *release=NULL; int major = -1; char strmajor[CF_MAXVARSIZE]; /* Grab the first line from the file and then close it. */ if ((fp = fopen(FEDORA_REL_FILENAME,"r")) == NULL) { return 1; } fgets(relstring, sizeof(relstring), fp); fclose(fp); Verbose("Looking for fedora core linux info...\n"); /* First, try to grok the vendor */ if(!strncmp(relstring, FEDORA_ID, strlen(FEDORA_ID))) { vendor = "fedora"; } else { Verbose("Could not identify OS distro from %s\n", FEDORA_REL_FILENAME); return 2; } /* Now, grok the release. We assume that all the strings will * have the word 'release' before the numerical release. */ release = strstr(relstring, RELEASE_FLAG); if(release == NULL) { Verbose("Could not find a numeric OS release in %s\n", FEDORA_REL_FILENAME); return 2; } else { release += strlen(RELEASE_FLAG); if (sscanf(release, "%d", &major) == 1) { sprintf(strmajor, "%d", major); } } if (major != -1 && (strcmp(vendor,"") != 0)) { classbuf[0] = '\0'; strcat(classbuf, vendor); AddClassToHeap(classbuf); strcat(classbuf, "_"); strcat(classbuf, strmajor); AddClassToHeap(classbuf); } return 0; } /*********************************************************************************/ int linux_redhat_version(void) { #define REDHAT_ID "Red Hat Linux" #define REDHAT_AS_ID "Red Hat Enterprise Linux AS" #define REDHAT_AS21_ID "Red Hat Linux Advanced Server" #define REDHAT_ES_ID "Red Hat Enterprise Linux ES" #define REDHAT_WS_ID "Red Hat Enterprise Linux WS" #define REDHAT_C_ID "Red Hat Enterprise Linux Client" #define REDHAT_S_ID "Red Hat Enterprise Linux Server" #define MANDRAKE_ID "Linux Mandrake" #define MANDRAKE_10_1_ID "Mandrakelinux" #define WHITEBOX_ID "White Box Enterprise Linux" #define CENTOS_ID "CentOS" #define SCIENTIFIC_SL_ID "Scientific Linux SL" #define SCIENTIFIC_CERN_ID "Scientific Linux CERN" #define RELEASE_FLAG "release " /* We are looking for one of the following strings... * * Red Hat Linux release 6.2 (Zoot) * Red Hat Linux Advanced Server release 2.1AS (Pensacola) * Red Hat Enterprise Linux AS release 3 (Taroon) * Red Hat Enterprise Linux WS release 3 (Taroon) * Red Hat Enterprise Linux Client release 5 (Tikanga) * Red Hat Enterprise Linux Server release 5 (Tikanga) * Linux Mandrake release 7.1 (helium) * Red Hat Enterprise Linux ES release 2.1 (Panama) * White Box Enterprise linux release 3.0 (Liberation) * Scientific Linux SL Release 4.0 (Beryllium) * CentOS release 4.0 (Final) */ #define RH_REL_FILENAME "/etc/redhat-release" FILE *fp; /* The full string read in from redhat-release */ char relstring[CF_MAXVARSIZE]; char classbuf[CF_MAXVARSIZE]; /* Red Hat, Mandrake */ char *vendor=""; /* as (Advanced Server, Enterprise) */ char *edition=""; /* Where the numerical release will be found */ char *release=NULL; int i; int major = -1; char strmajor[CF_MAXVARSIZE]; int minor = -1; char strminor[CF_MAXVARSIZE]; /* Grab the first line from the file and then close it. */ if ((fp = fopen(RH_REL_FILENAME,"r")) == NULL) { return 1; } fgets(relstring, sizeof(relstring), fp); fclose(fp); Verbose("Looking for redhat linux info in \"%s\"\n",relstring); /* First, try to grok the vendor and the edition (if any) */ if(!strncmp(relstring, REDHAT_ES_ID, strlen(REDHAT_ES_ID))) { vendor = "redhat"; edition = "es"; } else if(!strncmp(relstring, REDHAT_WS_ID, strlen(REDHAT_WS_ID))) { vendor = "redhat"; edition = "ws"; } else if(!strncmp(relstring, REDHAT_WS_ID, strlen(REDHAT_WS_ID))) { vendor = "redhat"; edition = "ws"; } else if(!strncmp(relstring, REDHAT_AS_ID, strlen(REDHAT_AS_ID)) || !strncmp(relstring, REDHAT_AS21_ID, strlen(REDHAT_AS21_ID))) { vendor = "redhat"; edition = "as"; } else if(!strncmp(relstring, REDHAT_S_ID, strlen(REDHAT_S_ID))) { vendor = "redhat"; edition = "s"; } else if(!strncmp(relstring, REDHAT_C_ID, strlen(REDHAT_C_ID))) { vendor = "redhat"; edition = "c"; } else if(!strncmp(relstring, REDHAT_ID, strlen(REDHAT_ID))) { vendor = "redhat"; } else if(!strncmp(relstring, MANDRAKE_ID, strlen(MANDRAKE_ID))) { vendor = "mandrake"; } else if(!strncmp(relstring, MANDRAKE_10_1_ID, strlen(MANDRAKE_10_1_ID))) { vendor = "mandrake"; } else if(!strncmp(relstring, WHITEBOX_ID, strlen(WHITEBOX_ID))) { vendor = "whitebox"; } else if(!strncmp(relstring, SCIENTIFIC_SL_ID, strlen(SCIENTIFIC_SL_ID))) { vendor = "scientific"; edition = "sl"; } else if(!strncmp(relstring, SCIENTIFIC_CERN_ID, strlen(SCIENTIFIC_CERN_ID))) { vendor = "scientific"; edition = "cern"; } else if(!strncmp(relstring, CENTOS_ID, strlen(CENTOS_ID))) { vendor = "centos"; } else { Verbose("Could not identify OS distro from %s\n", RH_REL_FILENAME); return 2; } /* Now, grok the release. For AS, we neglect the AS at the end of the * numerical release because we already figured out that it *is* AS * from the infomation above. We assume that all the strings will * have the word 'release' before the numerical release. */ /* Convert relstring to lowercase so that vendors like Scientific Linux don't fall through the cracks. */ for (i = 0; i < strlen(relstring); i++) { relstring[i] = tolower(relstring[i]); } release = strstr(relstring, RELEASE_FLAG); if(release == NULL) { Verbose("Could not find a numeric OS release in %s\n", RH_REL_FILENAME); return 2; } else { release += strlen(RELEASE_FLAG); if (sscanf(release, "%d.%d", &major, &minor) == 2) { sprintf(strmajor, "%d", major); sprintf(strminor, "%d", minor); } /* red hat 9 is *not* red hat 9.0. * and same thing with RHEL AS 3 */ else if (sscanf(release, "%d", &major) == 1) { sprintf(strmajor, "%d", major); minor = -2; } } if (major != -1 && minor != -1 && (strcmp(vendor,"") != 0)) { classbuf[0] = '\0'; strcat(classbuf, vendor); AddClassToHeap(classbuf); strcat(classbuf, "_"); if (strcmp(edition,"") != 0) { strcat(classbuf, edition); AddClassToHeap(classbuf); strcat(classbuf, "_"); } strcat(classbuf, strmajor); AddClassToHeap(classbuf); if (minor != -2) { strcat(classbuf, "_"); strcat(classbuf, strminor); AddClassToHeap(classbuf); } } return 0; } /******************************************************************/ int linux_suse_version(void) { #define SUSE_REL_FILENAME "/etc/SuSE-release" /* Check if it's a SuSE Enterprise version (all in lowercase) */ #define SUSE_SLES8_ID "suse sles-8" #define SUSE_SLES_ID "suse linux enterprise server" #define SUSE_RELEASE_FLAG "linux " /* The full string read in from SuSE-release */ char relstring[CF_MAXVARSIZE]; char classbuf[CF_MAXVARSIZE]; char vbuf[CF_BUFSIZE]; /* Where the numerical release will be found */ char *release=NULL; int i,version; int major = -1; char strmajor[CF_MAXVARSIZE]; int minor = -1; char strminor[CF_MAXVARSIZE]; FILE *fp; /* Grab the first line from the file and then close it. */ if ((fp = fopen(SUSE_REL_FILENAME,"r")) == NULL) { return 1; } fgets(relstring, sizeof(relstring), fp); fclose(fp); /* Check if it's a SuSE Enterprise version */ Verbose("Looking for SuSE enterprise info in \"%s\"\n",relstring); /* Convert relstring to lowercase to handle rename of SuSE to * SUSE with SUSE 10.0. */ for (i = 0; i < strlen(relstring); i++) { relstring[i] = tolower(relstring[i]); } /* Check if it's a SuSE Enterprise version (all in lowercase) */ if (!strncmp(relstring, SUSE_SLES8_ID, strlen(SUSE_SLES8_ID))) { classbuf[0] = '\0'; strcat(classbuf, "SLES8"); AddClassToHeap(classbuf); } else { for (version = 9; version < 13; version++) { snprintf(vbuf,CF_BUFSIZE,"%s %d ",SUSE_SLES_ID,version); Debug("Checking for suse [%s]\n",vbuf); if (!strncmp(relstring, vbuf, strlen(vbuf))) { snprintf(classbuf,CF_MAXVARSIZE,"SLES%d",version); AddClassToHeap(classbuf); } } } /* Determine release version. We assume that the version follows * the string "SuSE Linux" or "SUSE LINUX". */ release = strstr(relstring, SUSE_RELEASE_FLAG); if (release == NULL) { Verbose("Could not find a numeric OS release in %s\n",SUSE_REL_FILENAME); return 2; } else { release += strlen(SUSE_RELEASE_FLAG); sscanf(release, "%d.%d", &major, &minor); sprintf(strmajor, "%d", major); sprintf(strminor, "%d", minor); } if(major != -1 && minor != -1) { classbuf[0] = '\0'; strcat(classbuf, "SuSE"); AddClassToHeap(classbuf); strcat(classbuf, "_"); strcat(classbuf, strmajor); AddClassToHeap(classbuf); strcat(classbuf, "_"); strcat(classbuf, strminor); AddClassToHeap(classbuf); } return 0; } int linux_slackware_version(char *filename) { int major = -1; int minor = -1; int release = -1; char classname[CF_MAXVARSIZE] = ""; FILE *fp; if ((fp = fopen(filename,"r")) == NULL) { return 1; } Verbose("Looking for Slackware version...\n"); switch (fscanf(fp, "Slackware %d.%d.%d", &major, &minor, &release)) { case 3: Verbose("This appears to be a Slackware %u.%u.%u system.", major, minor, release); snprintf(classname, CF_MAXVARSIZE, "slackware_%u_%u_%u", major, minor, release); AddClassToHeap(classname); /* Fall-through */ case 2: Verbose("This appears to be a Slackware %u.%u system.", major, minor); snprintf(classname, CF_MAXVARSIZE, "slackware_%u_%u", major, minor); AddClassToHeap(classname); /* Fall-through */ case 1: Verbose("This appears to be a Slackware %u system.", major); snprintf(classname, CF_MAXVARSIZE, "slackware_%u", major); AddClassToHeap(classname); break; case 0: Verbose("No Slackware version number found.\n"); fclose(fp); return 2; } fclose(fp); return 0; } /******************************************************************/ int debian_version(void) /* Andrew Stribblehill */ { #define DEBIAN_VERSION_FILENAME "/etc/debian_version" int major = -1; int release = -1; char classname[CF_MAXVARSIZE] = ""; FILE *fp; if ((fp = fopen(DEBIAN_VERSION_FILENAME,"r")) == NULL) { return 1; } Verbose("Looking for Debian version...\n"); switch (fscanf(fp, "%d.%d", &major, &release)) { case 2: Verbose("This appears to be a Debian %u.%u system.", major, release); snprintf(classname, CF_MAXVARSIZE, "debian_%u_%u", major, release); AddClassToHeap(classname); /* Fall-through */ case 1: Verbose("This appears to be a Debian %u system.", major); snprintf(classname, CF_MAXVARSIZE, "debian_%u", major); AddClassToHeap(classname); break; case 0: Verbose("No Debian version number found.\n"); fclose(fp); return 2; } fclose(fp); return 0; } /******************************************************************/ int linux_mandrake_version(void) { /* We are looking for one of the following strings... */ #define MANDRAKE_ID "Linux Mandrake" #define MANDRAKE_REV_ID "Mandrake Linux" #define MANDRAKE_10_1_ID "Mandrakelinux" #define RELEASE_FLAG "release " #define MANDRAKE_REL_FILENAME "/etc/mandrake-release" FILE *fp; /* The full string read in from mandrake-release */ char relstring[CF_MAXVARSIZE]; char classbuf[CF_MAXVARSIZE]; /* I've never seen Mandrake-Move or the other 'editions', so I'm not going to try and support them here. Contributions welcome. */ /* Where the numerical release will be found */ char *release=NULL; char *vendor=NULL; int major = -1; char strmajor[CF_MAXVARSIZE]; int minor = -1; char strminor[CF_MAXVARSIZE]; /* Grab the first line from the file and then close it. */ if ((fp = fopen(MANDRAKE_REL_FILENAME,"r")) == NULL) { return 1; } fgets(relstring, sizeof(relstring), fp); fclose(fp); Verbose("Looking for Mandrake linux info in \"%s\"\n",relstring); /* Older Mandrakes had the 'Mandrake Linux' string in reverse order */ if(!strncmp(relstring, MANDRAKE_ID, strlen(MANDRAKE_ID))) { vendor = "mandrake"; } else if(!strncmp(relstring, MANDRAKE_REV_ID, strlen(MANDRAKE_REV_ID))) { vendor = "mandrake"; } else if(!strncmp(relstring, MANDRAKE_10_1_ID, strlen(MANDRAKE_10_1_ID))) { vendor = "mandrake"; } else { Verbose("Could not identify OS distro from %s\n", MANDRAKE_REL_FILENAME); return 2; } /* Now, grok the release. We assume that all the strings will * have the word 'release' before the numerical release. */ release = strstr(relstring, RELEASE_FLAG); if(release == NULL) { Verbose("Could not find a numeric OS release in %s\n", MANDRAKE_REL_FILENAME); return 2; } else { release += strlen(RELEASE_FLAG); if (sscanf(release, "%d.%d", &major, &minor) == 2) { sprintf(strmajor, "%d", major); sprintf(strminor, "%d", minor); } else { Verbose("Could not break down release version numbers in %s\n", MANDRAKE_REL_FILENAME); } } if (major != -1 && minor != -1 && strcmp(vendor, "")) { classbuf[0] = '\0'; strcat(classbuf, vendor); AddClassToHeap(classbuf); strcat(classbuf, "_"); strcat(classbuf, strmajor); AddClassToHeap(classbuf); if (minor != -2) { strcat(classbuf, "_"); strcat(classbuf, strminor); AddClassToHeap(classbuf); } } return 0; } /******************************************************************/ static void * lsb_release(const char *command, const char *key) { char * info = NULL; FILE * fp; snprintf(VBUFF, CF_BUFSIZE, "%s %s", command, key); if ((fp = cfpopen(VBUFF, "r")) == NULL) { return NULL; } if (ReadLine(VBUFF, CF_BUFSIZE, fp)) { char * buffer = VBUFF; strsep(&buffer, ":"); while((*buffer != '\0') && isspace(*buffer)) { buffer++; } info = buffer; while((*buffer != '\0') && !isspace(*buffer)) { *buffer = tolower(*buffer++); } *buffer = '\0'; info = strdup(info); } cfpclose(fp); return info; } /******************************************************************/ int lsb_version(void) { #define LSB_RELEASE_COMMAND "lsb_release" char classname[CF_MAXVARSIZE]; char *distrib = NULL; char *release = NULL; char *codename = NULL; int major = 0; int minor = 0; char *path, *dir, *rest; struct stat statbuf; path = rest = strdup(getenv("PATH")); if (strlen(path) == 0) { return 1; } for (; dir = strsep(&rest, ":") ;) { snprintf(VBUFF, CF_BUFSIZE, "%s/" LSB_RELEASE_COMMAND, dir); if (stat(VBUFF,&statbuf) != -1) { free(path); path = strdup(VBUFF); Verbose("\nThis appears to be a LSB compliant system.\n"); AddClassToHeap("lsb_compliant"); break; } } if (!dir) { free(path); return 1; } if ((distrib = lsb_release(path, "--id")) != NULL) { snprintf(classname, CF_MAXVARSIZE, "%s", distrib); AddClassToHeap(classname); if ((codename = lsb_release(path, "--codename")) != NULL) { snprintf(classname, CF_MAXVARSIZE, "%s_%s", distrib, codename); AddClassToHeap(classname); } if ((release = lsb_release(path, "--release")) != NULL) { switch (sscanf(release, "%d.%d\n", &major, &minor)) { case 2: snprintf(classname, CF_MAXVARSIZE, "%s_%u_%u", distrib, major, minor); AddClassToHeap(classname); case 1: snprintf(classname, CF_MAXVARSIZE, "%s_%u", distrib, major); AddClassToHeap(classname); } } free(path); return 0; } else { free(path); return 2; } } /******************************************************************/ int VM_version(void) { FILE *fp; char *sp,buffer[CF_BUFSIZE],classbuf[CF_BUFSIZE],version[CF_BUFSIZE]; struct stat statbuf; int major,minor,bug; int len = 0; int sufficient = 0; /* VMware Server ESX >= 3 has version info in /proc */ if ((fp = fopen("/proc/vmware/version","r")) != NULL) { ReadLine(buffer,CF_BUFSIZE,fp); Chop(buffer); if (sscanf(buffer,"VMware ESX Server %d.%d.%d",&major,&minor,&bug) > 0) { snprintf(classbuf,CF_BUFSIZE,"VMware ESX Server %d",major); AddClassToHeap(CanonifyName(classbuf)); snprintf(classbuf,CF_BUFSIZE,"VMware ESX Server %d.%d",major,minor); AddClassToHeap(CanonifyName(classbuf)); snprintf(classbuf,CF_BUFSIZE,"VMware ESX Server %d.%d.%d",major,minor,bug); AddClassToHeap(CanonifyName(classbuf)); sufficient = 1; } else if (sscanf(buffer,"VMware ESX Server %s",version) > 0) { snprintf(classbuf,CF_BUFSIZE,"VMware ESX Server %s",version); AddClassToHeap(CanonifyName(classbuf)); sufficient = 1; } fclose(fp); } /* Fall back to checking for other files */ if (sufficient < 1 && ((fp = fopen("/etc/vmware-release","r")) != NULL) || (fp = fopen("/etc/issue","r")) != NULL) { ReadLine(buffer,CF_BUFSIZE,fp); Chop(buffer); AddClassToHeap(CanonifyName(buffer)); /* Strip off the release code name e.g. "(Dali)" */ if ((sp = strchr(buffer,'(')) != NULL) { *sp = 0; Chop(buffer); AddClassToHeap(CanonifyName(buffer)); } sufficient = 1; fclose(fp); } return sufficient < 1 ? 1 : 0; } /******************************************************************/ int Xen_domain(void) { FILE *fp; char buffer[CF_BUFSIZE]; int sufficient = 0; /* xen host will have "control_d" in /proc/xen/capabilities, xen guest will not */ if ((fp = fopen("/proc/xen/capabilities","r")) != NULL) { while (!feof(fp)) { ReadLine(buffer,CF_BUFSIZE,fp); if (strstr(buffer,"control_d")) { AddClassToHeap("xen_dom0"); sufficient = 1; } } if (sufficient < 1) { AddClassToHeap("xen_domu"); sufficient = 1; } } return sufficient < 1 ? 1 : 0; } _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |