/* * utils.c: utilities * * Author: Jia Ming Pan * Copyright (c) 2005 International Business Machines * * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include "cluster_info.h" #include "utils.h" int debug_level = 10; static char * pathname_encode(const char *); int cim_init_logger(const char * entity) { char * inherit_debuglevel; int debug_level = 2; inherit_debuglevel = getenv(HADEBUGVAL); if (inherit_debuglevel != NULL) { debug_level = atoi(inherit_debuglevel); if (debug_level > 2) { debug_level = 2; } } cl_log_set_entity(entity); cl_log_enable_stderr(debug_level?TRUE:FALSE); cl_log_set_facility(HA_LOG_FACILITY); return HA_OK; } int run_shell_cmnd(const char *cmnd, int *ret, char ***out, char ***err) /* err not used currently */ { FILE * fstream = NULL; char buffer [4096]; int cmnd_rc, rc, i; DEBUG_ENTER(); if ( (fstream = popen(cmnd, "r")) == NULL ){ cl_log(LOG_ERR, "run_shell_cmnd: popen error: %s", strerror(errno)); return HA_FAIL; } if ( (*out = cim_malloc(sizeof(char*)) ) == NULL ) { cl_log(LOG_ERR, "run_shell_cmnd: failed malloc."); return HA_FAIL; } (*out)[0] = NULL; i = 0; while (!feof(fstream)) { if ( fgets(buffer, 4096, fstream) != NULL ){ /** add buffer to out **/ *out = cim_realloc(*out, (i+2) * sizeof(char*)); if ( *out == NULL ) { rc = HA_FAIL; goto exit; } (*out)[i] = cim_strdup(buffer); (*out)[i+1] = NULL; }else{ continue; } i++; } rc = HA_OK; exit: if ( (cmnd_rc = pclose(fstream)) == -1 ){ /*** WARNING log ***/ cl_log(LOG_WARNING, "failed to close pipe."); } *ret = cmnd_rc; DEBUG_LEAVE(); return rc; } char ** regex_search(const char * reg, const char * str, int * len) { regex_t regexp; const int maxmatch = 16; regmatch_t pm[16]; int i, ret, nmatch = 0; char **match = NULL; DEBUG_ENTER(); *len = 0; ret = regcomp(®exp, reg, REG_EXTENDED); if ( ret != 0) { cl_log(LOG_ERR, "regex_search: error regcomp regex %s.", reg); return HA_FAIL; } ret = regexec(®exp, str, nmatch, pm, 0); if ( ret == REG_NOMATCH ){ regfree(®exp); cl_log(LOG_ERR, "regex_search: no match."); return NULL; }else if (ret != 0){ cl_log(LOG_ERR, "regex_search: error regexec.\n"); regfree(®exp); return NULL; } for(nmatch=0; pm[nmatch].rm_so != -1 && nmatch < maxmatch; nmatch++); if ( (match = cim_malloc(nmatch*sizeof(char *))) == NULL ) { cl_log(LOG_ERR, "regex_search: alloc_failed."); regfree(®exp); return NULL; } *len = nmatch; for(i = 0; i < maxmatch && i < nmatch; i++){ int str_len = pm[i].rm_eo - pm[i].rm_so; if ((match[i] = cim_malloc(str_len + 1))) { strncpy( match[i], str + pm[i].rm_so, str_len); match[i][str_len] = EOS; } } regfree(®exp); DEBUG_LEAVE(); return match; } void free_2d_zarray(void *zarray, cim_free_t free) { void ** z = (void **)zarray; int i = 0; void * p; while ((p=z[i++])) { free(p); } cim_free(z); } void free_2d_array(void * a, int len, cim_free_t free) { int i; void ** array = (void **)a; for (i=0; iuuid[i]); } return str; } void cim_assert(const char * assertion, int line, const char * file) { cl_log(LOG_ERR, "Assertion \"%s\" failed on line %d in file \"%s\"" , assertion, line, file); exit(1); } char ** split_string(const char* string, int *len, const char *delim) { char **strings = NULL; const char *p; *len = 0; while(*string){ char * token = NULL; /* eat up delim chars */ while (*string && strchr(delim, *string)) { string++; continue; } if(!*string) { break; } /* reach a delim char */ p = string; while ( *p && !strchr(delim, *p) ) { p ++; continue; } /* copy string~(p-1) to token */ token = cim_malloc(p-string+1); if ( token == NULL ) { return strings; } memcpy(token, string, p - string); token[p-string] = EOS; strings = cim_realloc(strings, (*len+1) * sizeof(char *)); if ( strings == NULL ) { return NULL; } strings[*len] = token; *len = *len + 1; string = p; } return strings; } int cim_msg2disk(const char *objpathname, struct ha_msg *msg) { struct stat st; FILE *fobj; char pathname[MAXLEN], *buf; char *msgstr = NULL; if ( stat(HA_CIM_VARDIR, &st) < 0 ) { if ( errno == ENOENT ) { /* not exist, create */ if ( mkdir(HA_CIM_VARDIR, 0660) < 0){ cl_log(LOG_ERR,"msg2disk: mkdir failed."); cl_log(LOG_ERR,"reason:%s",strerror(errno)); return HA_FAIL; } } else { cl_log(LOG_ERR, "msg2disk: stat faild."); cl_log(LOG_ERR,"reason:%d(%s)",errno,strerror(errno)); return HA_FAIL; } } /* check stat */ /* write msg*/ if((buf = pathname_encode(objpathname))== NULL ) { return HA_FAIL; } snprintf(pathname, MAXLEN, "%s/%s", HA_CIM_VARDIR, buf); cim_free(buf); if ( ( fobj = fopen(pathname, "w") ) == NULL ) { cl_log(LOG_WARNING, "msg2disk: can't open file."); cl_log(LOG_WARNING, "reason:%d(%s)", errno, strerror(errno)); return HA_FAIL; } if ( msg->nfields == 0 ) { fclose(fobj); return HA_OK; } if ((msgstr = msg2string(msg)) == NULL ) { cl_log(LOG_ERR, "cim_msg2disk: msgstr NULL."); return HA_FAIL; } fprintf(fobj, "%s", msgstr); fclose(fobj); return HA_OK; } struct ha_msg* cim_disk2msg(const char *objpathname) { char pathname[MAXLEN], *buf; FILE *fobj = NULL; int ret; int bytes = 0; struct stat st; struct ha_msg *msg = NULL; if((buf = pathname_encode(objpathname))== NULL ) { return NULL; } snprintf(pathname, MAXLEN, "%s/%s", HA_CIM_VARDIR, buf); cim_free(buf); if ( ( ret = stat(pathname, &st)) < 0 ) { cl_log(LOG_WARNING, "disk2msg: stat faild for %s.", pathname); cl_log(LOG_WARNING,"reason:%d(%s)",errno,strerror(errno)); return NULL; } if (st.st_size == 0 ) { cl_log(LOG_WARNING, "disk2msg: size of %s is zero.", objpathname); return NULL; } if ((buf = cim_malloc(st.st_size)) == NULL ) { cl_log(LOG_ERR, "disk2msg: alloc msg failed for %s.", objpathname); return NULL; } if ( (fobj = fopen(pathname, "r")) == NULL ) { cl_log(LOG_WARNING, "msg2disk: can't open file %s.", pathname); cl_log(LOG_WARNING, "reason:%d(%s)", errno, strerror(errno)); return NULL; } while ( (ret = fread(buf, st.st_size, 1, fobj))){ bytes += ret*st.st_size; } if ( !feof(fobj) ) { cl_log(LOG_ERR, "msg2disk: read error for %s.", objpathname); cl_log(LOG_ERR, "reason: %d(%s).", errno, strerror(errno)); cim_free(msg); return NULL; } if ( bytes != st.st_size ) { cl_log(LOG_ERR, "msg2disk: incompete read:"); cl_log(LOG_ERR, "read: %d vs size: %d.", bytes, (int)st.st_size); cim_free(msg); return NULL; } msg = string2msg(buf, bytes); cim_free(buf); fclose(fobj); return msg; } int cim_disk_msg_del(const char *objpathname) { char fullpathname[MAXLEN]; char * pathname = pathname_encode(objpathname); snprintf(fullpathname, MAXLEN, "%s/%s", HA_CIM_VARDIR, pathname); cim_debug2(LOG_INFO, "%s: unlink %s", __FUNCTION__, fullpathname); unlink(fullpathname); cim_free(pathname); return HA_OK; } char* cim_dbget(const char *pathname, const char*key) { struct ha_msg *db = cim_disk2msg(pathname); const char * value; if ( db == NULL ) { return NULL; } value = cl_get_string(db, key); if ( value == NULL || strncmp(value, "null", MAXLEN) == 0) { return NULL; } return cim_strdup(value); } int cim_dbput(const char *pathname, const char*key, const char*value) { int ret; struct ha_msg* db = cim_disk2msg(pathname); if ( db == NULL ) { if ( (db = ha_msg_new(1)) == NULL ) { cl_log(LOG_ERR, "cim_dbput: alloc db failed."); return HA_FAIL; } } if ((cl_msg_modstring(db, key, value?value:"null")) != HA_OK ) { ha_msg_del(db); cl_log(LOG_ERR, "cim_dbput: put value failed."); return HA_FAIL; } ret = cim_msg2disk(pathname, db); ha_msg_del(db); return HA_OK; } int cim_dbdel(const char *pathname, const char*key) { int ret; struct ha_msg* db = cim_disk2msg(pathname); if ( db == NULL ) { cl_log(LOG_ERR, "cim_dbdel: get db failed."); return HA_FAIL; } if ((cl_msg_remove(db, key)) != HA_OK ) { ha_msg_del(db); cl_log(LOG_ERR, "cim_dbdel: remove failed."); return HA_FAIL; } ret = cim_msg2disk(pathname, db); ha_msg_del(db); return HA_OK; } struct ha_msg* cim_dbkeys(const char *pathname) { struct ha_msg * db = cim_disk2msg(pathname); struct ha_msg * list; int i; if ( db == NULL ) { cl_log(LOG_ERR, "cim_dbkeys: get db failed."); return NULL; } if ( (list = ha_msg_new(1)) == NULL ) { ha_msg_del(db); cl_log(LOG_ERR, "cim_dbkeys: alloc list failed."); return NULL; } for (i = 0; i < db->nfields; i++) { cim_list_add(list, db->names[i]); } ha_msg_del(db); return list; } static char* pathname_encode(const char *pathname) { char *new_pathname = NULL; char ch, *p; if ((new_pathname = cim_malloc(strlen(pathname)+1)) == NULL ) { cl_log(LOG_ERR, "pathname_enocde: alloc pathname failed."); return NULL; } p = new_pathname; while( (ch = *(pathname++)) ) { if (ch == '\\' || ch == '/') { *(p++) = '_'; } else { *(p++) = ch; } } *p = EOS; return new_pathname; } /**************************************************** * msg ****************************************************/ int cim_msg_children_count(struct ha_msg *parent) { int i, count = 0; for (i = 0; i < parent->nfields; i++) { if ( parent->types[i] == FT_STRUCT ) { count++; } } return count; } const char * cim_msg_child_name(struct ha_msg *parent, int index) { int i, current = 0; for (i = 0; i < parent->nfields; i++) { if ( parent->types[i] == FT_STRUCT ) { if ( index == current) { return parent->names[i]; } current++; } } return NULL; } struct ha_msg * cim_msg_child_index(struct ha_msg *parent, int index) { int i, current = 0; for (i = 0; i < parent->nfields; i++) { if ( parent->types[i] == FT_STRUCT ) { if ( index == current) { return parent->values[i]; } current++; } } return NULL; } int cim_list_find(struct ha_msg *list, const char *value) { int len = cim_list_length(list); int i = 0; for (i = 0; i