[Libvirt-cim] [PATCH 14/15] vlan extension - function lib - add the helper functions

Wayne Xia xiawenc at linux.vnet.ibm.com
Fri Dec 30 10:29:51 UTC 2011


于 2011-12-24 4:18, Chip Vincent 写道:
> On 12/07/2011 04:25 AM, Wayne Xia wrote:
>> this is the helper function for the lib.
>>
>> Signed-off-by: Wayne Xia<xiawenc at linux.vnet.ibm.com>
>> ---
>> libxkutil/host_network_error.h | 28 ++
>> libxkutil/host_network_helper.c | 659
>> +++++++++++++++++++++++++++++++++++++++
>> libxkutil/host_network_helper.h | 192 ++++++++++++
>> 3 files changed, 879 insertions(+), 0 deletions(-)
>> create mode 100644 libxkutil/host_network_error.h
>> create mode 100644 libxkutil/host_network_helper.c
>> create mode 100644 libxkutil/host_network_helper.h
>>
>> diff --git a/libxkutil/host_network_error.h
>> b/libxkutil/host_network_error.h
>> new file mode 100644
>> index 0000000..d809033
>> --- /dev/null
>> +++ b/libxkutil/host_network_error.h
>> @@ -0,0 +1,28 @@
>> +#ifndef HOST_NETWORK_ERROR_H
>> +#define HOST_NETWORK_ERROR_H
>> +
>> +#define ERR_REQUEST_NOT_SUPPORT -1
>> +
>> +#define ERR_COMMAND_NOT_SET -11
>> +#define ERR_COMMAND_PIPE_ERR -12
>> +#define ERR_COMMAND_NOT_SUPPORT -13
>> +#define ERR_COMMAND_NO_PERMISSION -14
>> +#define ERR_COMMAND_NO_READY -15
>> +#define ERR_COMMAND_PARAMETER_WRONG -16
>> +#define ERR_COMMAND_EXECUTION -17
>> +
>> +#define ERR_DEVICE_EXCEED_MAXNUM -100
>> +#define ERR_DEVICE_EXIST -101
>> +#define ERR_DEVICE_NOT_EXIST -102
>> +#define ERR_DEVICE_ALREADY_DONE -103
>> +#define ERR_DEVICE_CONNECT_OTHER -104
>> +
>> +#define ERR_FILE_OP_FAIL -125
>> +#define ERR_FILE_EMPTY -126
>> +#define ERR_FILE_TOO_LARGE -127
>> +#define ERR_FILE_CONT_TOO_LARGE -128
>> +#define ERR_FILE_LOCK_FAIL -129
>> +
>> +#define ERR_PERSIST_NOT_REDHAT -200
> Any particular reason for negative numbers?

    No, just a custom to use negative number indicating errors. Is that
bad?

>> +
>> +#endif
>> diff --git a/libxkutil/host_network_helper.c
>> b/libxkutil/host_network_helper.c
>> new file mode 100644
>> index 0000000..dc9f775
>> --- /dev/null
>> +++ b/libxkutil/host_network_helper.c
>> @@ -0,0 +1,659 @@
>> +/*
>> + * Copyright IBM Corp. 2011
>> + *
>> + * Authors:
>> + * Wenchao Xia<xiawenc at cn.ibm.com>
>> + *
>> + * This library is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU Lesser General Public
>> + * License as published by the Free Software Foundation; either
>> + * version 2.1 of the License, or (at your option) any later version.
>> + */
>> +
>> +
>> +
>> +#include<string.h>
>> +#include<sys/types.h>
>> +#include<sys/stat.h>
>> +#include<unistd.h>
>> +#include<fcntl.h>
>> +
>> +#include "host_network_helper.h"
>> +#include "host_network_error.h"
>> +
>> +#define CONFIGURE_FILE_MAX_SIZE 2048
>> +
>> +#define PIPE_CMD_SUFFIX " 2>&1"
>> +
>> +static int g_linux_version = LINUX_UNKNOWN;
> I assume this is needed because the parse output varies?

     Tried some version, it seems the output was almost the same, but
persisting of configuration was linux distribution depending.

>> +
>> +static int compare_qos_8021q(const void *p1, const void *p2)
>> +{
>> + const VLAN_Qos_8021q_elem *qos1 = (VLAN_Qos_8021q_elem *)p1;
>> + const VLAN_Qos_8021q_elem *qos2 = (VLAN_Qos_8021q_elem *)p2;
>> + int ret = 0;
>> + if ((qos1->from)> (qos2->from)) {
>> + ret = 1;
>> + }
>> + return ret;
>> +}
>> +
>> +/* it need to be checked see whether these are the conditions */
>> +int vlan_8021q_qos_check_valid(VLAN_Qos_8021q *pqos)
>> +{
>> + int ret = 1;
>> + int i = 0;
>> + int last_num = -1;
>> + if ((pqos->count< 0) || (pqos->count> 8)) {
>> + ret = 0;
>> + goto out;
>> + } else if (pqos->count == 0) {
>> + goto out;
>> + }
>> + qsort((void *)pqos->values, pqos->count, sizeof(VLAN_Qos_8021q_elem),
>> + compare_qos_8021q);
>> +
>> + while (i< pqos->count) {
>> + if (pqos->values[i].from == last_num) {
>> + CU_DEBUG("error: vlan 802.1.q qos setting have same<from> values: "
>> + "last is %d, new is %d", last_num, pqos->values[i].from);
>> + ret = 0;
>> + goto out;
>> + }
>> + last_num = pqos->values[i].from;
>> + if ((pqos->values[i].from< 0) || (pqos->values[i].from>= 8)) {
>> + CU_DEBUG("error: vlan 802.1.q qos setting have outbound value: "
>> + "from is %d.", pqos->values[i].from);
>> + ret = 0;
>> + goto out;
>> + }
>> + if ((pqos->values[i].to< 0) || (pqos->values[i].to>= 8)) {
>> + CU_DEBUG("error: vlan 802.1.q qos setting have outbound value: "
>> + "to is %d.", pqos->values[i].to);
>> + ret = 0;
>> + goto out;
>> + }
>> + i++;
>> + }
>> +
>> + out:
>> + return ret;
>> +}
>> +
>> +int vlan_8021q_qos_str_to_num(VLAN_Qos_8021q *pqos, const char* str)
>> +{
>> + int ret = 1;
>> + char *str_line = NULL;
>> + char *temp;
>> + char *saveptr = NULL;
>> + char *invalptr1, *invalptr2;
>> + int qos_num1, qos_num2;
>> + VLAN_Qos_8021q qos;
>> +
>> + if (str == NULL) {
>> + ret = 0;
>> + goto out;
>> + }
>> + if (str[0] == '\0') {
>> + ret = 1;
>> + pqos->count = 0;
>> + CU_DEBUG("empty vlan 802.1.q qos string found.");
>> + goto out;
>> + }
>> + str_line = SAFE_STRDUP(str);
>> + qos.count = 0;
>> +
>> + temp = strtok_r(str_line, " ",&saveptr);
>> + while (temp != NULL) {
>> + qos_num1 = strtol(temp,&invalptr1, 10);
>> + if (temp == invalptr1) {
>> + ret = 0;
>> + goto out;
>> + }
>> + if (*invalptr1 != ':') {
>> + ret = 0;
>> + goto out;
>> + }
>> + invalptr1++;
>> + qos_num2 = strtol(invalptr1,&invalptr2, 10);
>> + if (invalptr1 == invalptr2) {
>> + ret = 0;
>> + goto out;
>> + }
>> + if (*invalptr2 != '\0') {
>> + ret = 0;
>> + goto out;
>> + }
>> + if (qos.count>= 8) {
>> + ret = 0;
>> + CU_DEBUG("too many settings found in vlan 802.1.q qos string [%s]",
>> + str);
>> + goto out;
>> + }
>> + qos.values[qos.count].from = qos_num1;
>> + qos.values[qos.count].to = qos_num2;
>> + qos.count++;
>> + temp = strtok_r(NULL, " ",&saveptr);
>> + }
>> + ret = vlan_8021q_qos_check_valid(&qos);
>> + if (ret == 1) {
>> + *pqos = qos;
>> + }
>> +
>> + out:
>> + if (ret != 1) {
>> + CU_DEBUG("vlan 802.1.q qos string [%s] is invalid.", str);
>> + }
>> + SAFE_FREE(str_line);
>> + return ret;
>> +}
>> +
>> +int vlan_8021q_qos_num_to_str(char **str, const VLAN_Qos_8021q *pqos)
>> +{
>> + char temp[16];
>> + int i;
>> + VLAN_Qos_8021q qos = *pqos;
>> + int ret = vlan_8021q_qos_check_valid(&qos);
>> + if (ret != 1) {
>> + goto out;
>> + }
>> + SAFE_MALLOC(*str, 64);
>> + *str[0] = '\0';
>> + if (qos.count == 0) {
>> + goto out;
>> + }
>> + i = 0;
>> + snprintf(temp, sizeof(temp), "%d:%d",
>> + qos.values[i].from, qos.values[i].to);
>> + strcat(*str, temp);
>> + i++;
>> + while (i< qos.count) {
>> + strcat(*str, " ");
>> + snprintf(temp, sizeof(temp), "%d:%d",
>> + qos.values[i].from, qos.values[i].to);
>> + strcat(*str, temp);
>> + i++;
>> + }
>> +
>> + out:
>> + return ret;
>> +}
>> +
>> +int netmask_easy_to_inaddr(struct in_addr *paddr, const char* pmask)
>> +{
>> + long mask_one_num = -1;
>> + unsigned char *p;
>> + int bitnum;
>> +
>> + mask_one_num = strtol(pmask, NULL, 10);
>> + if ((mask_one_num< 0) || (mask_one_num> 32)) {
>> + return 0;
>> + }
>> +
>> + /* use network byte order */
>> + p = (unsigned char *)&paddr->s_addr;
>> + memset(p, 0, 4);
>> + while (mask_one_num> 8) {
>> + *(p++) = 255;
>> + mask_one_num -= 8;
>> + }
>> + bitnum = 7;
>> + while (mask_one_num> 0) {
>> + *p = *p + (1<<bitnum);
>> + mask_one_num--;
>> + bitnum--;
>> + }
>> + return 1;
>> +}
>> +
>> +char *strtok_onetime(const char *str, const char *delim)
>> +{
>> + char *t = strstr(str, delim);
>> + char *ret_char;
>> + int len;
>> + if (t == NULL) {
>> + return NULL;
>> + }
>> + len = t - str;
>> + if (len<= 0) {
>> + return NULL;
>> + }
>> + SAFE_MALLOC(ret_char, len+1);
>> + strncpy(ret_char, str, len);
>> + ret_char[len] = '\0';
>> +
>> + return ret_char;
>> +}
>> +
>> +char *combine_file_name(const char *prefix, const char *name)
>> +{
>> + char *ret = NULL;
>> + int size;
>> + size = strlen(prefix) + strlen(name) + 1;
>> + SAFE_CALLOC(ret, size, sizeof(char));
>> + snprintf(ret, size, "%s%s", prefix, name);
>> + return ret;
>> +}
>> +
>> +/* return the whole content length that need update. The data length
>> keep
>> + unchanged in the head part is returned in *unchanged_len which could be
>> + used to avoid write whole data later.
>> + requriement: cont must contain end character, prefix must be not
>> NULL */
>> +static int replace_prop_str(char *cont, const int maxsize, const char
>> *prefix,
>> + const char *prop, int *unchanged_len)
>> +{
>> + int target_len, origin_len;
>> + int cont_len;
>> + int valid_len = 0;
>> + int prefix_len, prop_len = 0;
>> + char *endchar1 = "\n";
>> + char *pprop_start, *pprop_end;
>> + int head_len;
>> +
>> + cont_len = strlen(cont);
>> + head_len = cont_len;
>> + prefix_len = strlen(prefix);
>> + if ((prop == NULL) || (*prop == '\0')) {
>> + /* want the property removed */
>> + target_len = 0;
>> + } else {
>> + /* want the property changed */
>> + prop_len = strlen(prop);
>> + target_len = prefix_len + prop_len;
>> + }
>> +
>> + pprop_start = strstr(cont, prefix);
>> + if (pprop_start == NULL) {
>> + /* the content do not exist in original contents */
>> + if (target_len> 0) {
>> + /* add the property */
>> + if ((cont_len + target_len)>= maxsize) {
>> + CU_DEBUG("buffer is too small for the operation.");
>> + valid_len = -1;
>> + goto out;
>> + }
>> + strcat(cont, prefix);
>> + strcat(cont, prop);
>> + valid_len = cont_len + target_len;
>> + } else {
>> + /* remove the property, but it do not exist, so skip */
>> + }
>> + } else {
>> + /* the content exist in original contents */
>> + /* locate the end of the property */
>> + pprop_end = strstr(pprop_start, endchar1);
>> + if (pprop_end == NULL) {
>> + /* last line */
>> + origin_len = strlen(pprop_start);
>> + pprop_end = cont+cont_len;
>> + } else {
>> + origin_len = pprop_end - pprop_start;
>> + }
>> + if (target_len> 0) {
>> + /* change the property */
>> + /* check the bound */
>> + if ((cont_len + target_len - origin_len)>= maxsize) {
>> + CU_DEBUG("buffer is too small for the operation.");
>> + valid_len = -1;
>> + goto out;
>> + }
>> + /* move contents in the tail */
>> + memmove(pprop_end+target_len-origin_len, pprop_end,
>> + cont+cont_len+1-pprop_end);
>> + /* copy the content of the new string */
>> + memcpy(pprop_start+prefix_len, prop, prop_len);
>> + head_len = pprop_start - cont + prefix_len;
>> + } else {
>> + /* remove the property */
>> + /* move contents in the tail to replace original string*/
>> + memmove(pprop_end+target_len-origin_len, pprop_end,
>> + cont+cont_len+1-pprop_end);
>> + head_len = pprop_start - cont;
>> + }
>> + valid_len = cont_len + target_len - origin_len;
>> + }
>> +
>> + out:
>> + if (unchanged_len != NULL) {
>> + *unchanged_len = head_len;
>> + }
>> + return valid_len;
>> +}
>> +
>> +int configure_file_replace_attr(const char *path, const char *prefix,
>> + const char *prop)
>> +{
>> + int fd = -1;
>> + int fop_ret;
>> + struct stat s;
>> + struct flock lock;
>> + int lock_state = -1;
>> + char *cont = NULL;
>> + char *pbuff;
>> + int write_len;
>> + int cont_len_update;
>> + int cont_len_unchanged;
>> + int ret = 0;
>> +
>> + if ((prefix == NULL) || (*prefix == '\0')) {
>> + CU_DEBUG("no prefix for property set, could not replace the content.");
>> + goto out;
>> + }
>> +
>> + fd = open(path, O_RDWR, 0644);
>> + if (fd< 0) {
>> + CU_DEBUG("Unable to open [%s], it does not exist.", path);
>> + ret = ERR_FILE_OP_FAIL;
>> + goto out;
>> + }
>> +
>> + lock.l_type = F_WRLCK;
>> + lock.l_start = 0;
>> + lock.l_whence = SEEK_SET;
>> + lock.l_len = 0;
>> + lock_state = fcntl(fd, F_SETLK,&lock);
>> + if (lock_state< 0) {
>> + CU_DEBUG("Failed to lock file [%s], it may be locked by other.", path);
>> + ret = ERR_FILE_LOCK_FAIL;
>> + goto out;
>> + }
>> +
>> + fstat(fd,&s);
>> + if (s.st_size == 0) {
>> + CU_DEBUG("file [%s] is empty, will not replace attr for it.", path);
>> + ret = ERR_FILE_EMPTY;
>> + goto out;
>> + } else if (s.st_size>= CONFIGURE_FILE_MAX_SIZE) {
>> + CU_DEBUG("file [%s] is too large, "
>> + "it have %lld bytes, will not read it.",
>> + path, (long long)s.st_size);
>> + ret = ERR_FILE_TOO_LARGE;
>> + goto out;
>> + }
>> +
>> + SAFE_MALLOC(cont, CONFIGURE_FILE_MAX_SIZE);
>> + lseek(fd, 0, SEEK_SET);
>> + fop_ret = read(fd, cont, s.st_size);
>> + cont[s.st_size] = '\0';
>> + cont_len_update = replace_prop_str(cont, CONFIGURE_FILE_MAX_SIZE,
>> + prefix, prop,&cont_len_unchanged);
>> + if (cont_len_update< 0) {
>> + CU_DEBUG("file [%s] is too big to expand it with [%s%s].",
>> + path, prefix, prop);
>> + ret = ERR_FILE_TOO_LARGE;
>> + goto out;
>> + } else if (cont_len_update == 0) {
>> + CU_DEBUG("the contents was not changed, do not need update it");
>> + ret = 1;
>> + goto out;
>> + } else {
>> + if (ftruncate(fd, cont_len_unchanged) != 0) {
>> + CU_DEBUG("file [%s] Unable to truncate it", path);
>> + ret = ERR_FILE_OP_FAIL;
>> + goto out;
>> + }
>> + write_len = cont_len_update-cont_len_unchanged;
>> + if (write_len> 0) {
>> + lseek(fd, cont_len_unchanged, SEEK_SET);
>> + CU_DEBUG("writing file [%s] for %d bytes with offset %d,"
>> + " cont is :\n%s\n",
>> + path, write_len, cont_len_unchanged, cont);
>> + pbuff = cont+cont_len_unchanged;
>> + fop_ret = write(fd, pbuff, write_len);
>> + }
>> + }
>> + ret = 1;
>> +
>> + out:
>> + if (fd>= 0) {
>> + if (lock_state>= 0) {
>> + lock.l_type = F_UNLCK;
>> + fcntl(fd, F_SETLK,&lock);
>> + }
>> + close(fd);
>> + }
>> + SAFE_FREE(cont);
>> + return ret;
>> +}
>> +
>> +int configure_file_update(const char *path, const char *cont)
>> +{
>> + int fd = -1;
>> + int fop_ret;
>> + struct flock lock;
>> + int lock_state = -1;
>> + int write_len;
>> + int ret = 0;
>> +
>> + fd = open(path, O_RDWR|O_CREAT, 0644);
>> + if (fd< 0) {
>> + CU_DEBUG("Unable to open [%s], it does not exist.", path);
>> + ret = ERR_FILE_OP_FAIL;
>> + goto out;
>> + }
>> +
>> + lock.l_type = F_WRLCK;
>> + lock.l_start = 0;
>> + lock.l_whence = SEEK_SET;
>> + lock.l_len = 0;
>> + lock_state = fcntl(fd, F_SETLK,&lock);
>> + if (lock_state< 0) {
>> + CU_DEBUG("Failed to lock file [%s], it may be locked by other.", path);
>> + ret = ERR_FILE_LOCK_FAIL;
>> + goto out;
>> + }
>> +
>> + if (ftruncate(fd, 0) != 0) {
>> + CU_DEBUG("file [%s] Unable to truncate it", path);
>> + ret = ERR_FILE_OP_FAIL;
>> + goto out;
>> + }
>> +
>> + write_len = strlen(cont);
>> + if (write_len> 0) {
>> + lseek(fd, 0, SEEK_SET);
>> + CU_DEBUG("writing file [%s] for %d bytes with offset 0,"
>> + " cont is :\n%s\n",
>> + path, write_len, cont);
>> + fop_ret = write(fd, cont, write_len);
>> + }
>> + ret = 1;
>> +
>> + out:
>> + if (fd>= 0) {
>> + if (lock_state>= 0) {
>> + lock.l_type = F_UNLCK;
>> + fcntl(fd, F_SETLK,&lock);
>> + }
>> + close(fd);
>> + }
>> + return ret;
>> +}
>> +
>> +int configure_file_remove(const char *path)
>> +{
>> + int fd_ret;
>> + int ret = 0;
>> + if (access(path, F_OK) == 0) {
>> + CU_DEBUG("Deleting %s.", path);
>> + fd_ret = remove(path);
>> + if (fd_ret != 0) {
>> + CU_DEBUG("failed to remove %s.", path);
>> + ret = ERR_FILE_OP_FAIL;
>> + goto out;
>> + }
>> + }
>> +
>> + ret = 1;
>> + out:
>> + return ret;
>> +}
>> +
>> +FILE *pipe_excute_command_type_read(char *cmd, const int buf_size,
>> + const char *type, int *errno)
>> +{
>> + FILE *stream = NULL;
>> + char *suffix = PIPE_CMD_SUFFIX;
>> + if ((strlen(cmd) + strlen(suffix))>= buf_size) {
>> + CU_DEBUG("cmd [%s] is too long to append the suffix", cmd);
>> + *errno = ERR_COMMAND_NO_READY;
>> + goto out;
>> + }
>> + strcat(cmd, suffix);
>> + CU_DEBUG("excuting readonly cmd [%s].", cmd);
>> + stream = popen(cmd, type);
>> + if (stream == NULL) {
>> + CU_DEBUG("Failed to open pipe to run command");
>> + *errno = ERR_COMMAND_PIPE_ERR;
>> + }
>> +
>> +out:
>> + return stream;
>> +}
>> +
>> +FILE *pipe_excute_command_type_write(char *cmd, const int buf_size,
>> + const char *type, int *errno)
>> +{
>> + FILE *stream = NULL;
>> + char *suffix = PIPE_CMD_SUFFIX;
>> + if ((strlen(cmd) + strlen(suffix))>= buf_size) {
>> + CU_DEBUG("cmd [%s] is too long to append the suffix", cmd);
>> + *errno = ERR_COMMAND_NO_READY;
>> + goto out;
>> + }
>> + strcat(cmd, suffix);
>> + CU_DEBUG("excuting system modification cmd [%s].", cmd);
>> + stream = popen(cmd, type);
>> + if (stream == NULL) {
>> + CU_DEBUG("Failed to open pipe to run command");
>> + *errno = ERR_COMMAND_PIPE_ERR;
>> + }
>> + usleep(10000);
>> +
>> +out:
>> + return stream;
>> +}
>> +
>> +int get_host_linux_version(void)
>> +{
>> + FILE *stream = NULL;
>> + char cmd[64];
>> + char buff[256];
>> + int linenum;
>> + int errno;
>> +
>> + if (g_linux_version != LINUX_UNKNOWN) {
>> + goto out;
>> + }
>> +
>> + cmd[0] = '\0';
>> + strcat(cmd, "lsb_release -a");
>> + stream = pipe_excute_command_type_read(cmd, sizeof(cmd), "r",&errno);
>> + if (stream == NULL) {
>> + goto out;
>> + }
>> +
>> + linenum = -1;
>> + g_linux_version = LINUX_OTHER;
>> + while (fgets(buff, 256, stream) != NULL) {
>> + linenum++;
>> + if (linenum == 0) {
>> + if (NULL == strstr(buff, "LSB")) {
>> + CU_DEBUG("ERR: unable to get linux distribution version.");
>> + g_linux_version = LINUX_FAIL_TO_GET;
>> + }
>> + }
>> + if ((NULL != strstr(buff, "Red Hat")) ||
>> + (NULL != strstr(buff, "RedHat"))) {
>> + g_linux_version = LINUX_REDHAT;
>> + break;
>> + }
>> + }
>> +
>> + out:
>> + if (stream != NULL) {
>> + pclose(stream);
>> + }
>> + return g_linux_version;
>> +}
>> +
>> +char *translate_error_no(int errno)
>> +{
>> + char *ret = NULL;
>> + switch (errno) {
>> + case ERR_REQUEST_NOT_SUPPORT:
>> + ret = "request is not supported now";
>> + break;
>> +
>> + case ERR_COMMAND_NOT_SET:
>> + ret = "command is not set.";
>> + break;
>> + case ERR_COMMAND_PIPE_ERR:
>> + ret = "failed in creating pipe to execute the command.";
>> + break;
>> + case ERR_COMMAND_NOT_SUPPORT:
>> + ret = "command is not found, check u environment.";
>> + break;
>> + case ERR_COMMAND_NO_PERMISSION:
>> + ret = "not enough authority to execute the command.";
>> + break;
>> + case ERR_COMMAND_NO_READY:
>> + ret = "failed to build up the command line, check your input, "
>> + "maybe it is too long.";
>> + break;
>> + case ERR_COMMAND_PARAMETER_WRONG:
>> + ret = "got invalid paramenter, check your input.";
>> + break;
>> + case ERR_COMMAND_EXECUTION:
>> + ret = "error happened in the excution of command.";
>> + break;
>> +
>> + case ERR_DEVICE_EXCEED_MAXNUM:
>> + ret = "too many devices found or set, check the environment.";
>> + break;
>> + case ERR_DEVICE_EXIST:
>> + ret = "device already exist, can not execute the command.";
>> + break;
>> + case ERR_DEVICE_NOT_EXIST:
>> + ret = "device do not exist, can not execute the command.";
>> + break;
>> + case ERR_DEVICE_ALREADY_DONE:
>> + ret = "the operation you want have been done before, "
>> + "will not do it again.";
>> + break;
>> + case ERR_DEVICE_CONNECT_OTHER:
>> + ret = "the device you want to connect have been connect to another"
>> + " device, can't change it directly.";
>> + break;
>> +
>> + case ERR_FILE_OP_FAIL:
>> + ret = "failed in accessing the file.";
>> + break;
>> + case ERR_FILE_EMPTY:
>> + ret = "the file it want is empty.";
>> + break;
>> + case ERR_FILE_TOO_LARGE:
>> + ret = "the file it want is too large.";
>> + break;
>> + case ERR_FILE_CONT_TOO_LARGE:
>> + ret = "the content it want to combine to file is too large.";
>> + break;
>> + case ERR_FILE_LOCK_FAIL:
>> + ret = "failed in locking the file, "
>> + "check if other process is using it.";
>> + break;
>> +
>> + case ERR_PERSIST_NOT_REDHAT:
>> + ret = "host is not a RedHat distribution, can't persist the "
>> + "configuration, it would not take effect after host is "
>> + "rebooted. Other version would be supported in the future. "
>> + "If you are sure host is RedHat, make sure command "
>> + "<lsb_release -a> could work.";
>> + break;
>> +
>> + default:
>> + ret = "internal error.";
>> + break;
>> + }
>> + return ret;
>> +}
>> diff --git a/libxkutil/host_network_helper.h
>> b/libxkutil/host_network_helper.h
>> new file mode 100644
>> index 0000000..a232221
>> --- /dev/null
>> +++ b/libxkutil/host_network_helper.h
>> @@ -0,0 +1,192 @@
>> +/*
>> + * Copyright IBM Corp. 2011
>> + *
>> + * Authors:
>> + * Wenchao Xia<xiawenc at cn.ibm.com>
>> + *
>> + * This library is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU Lesser General Public
>> + * License as published by the Free Software Foundation; either
>> + * version 2.1 of the License, or (at your option) any later version.
>> + */
>> +
>> +
>> +#ifndef HOST_NETWORK_HELPER_H
>> +#define HOST_NETWORK_HELPER_H
>> +
>> +#include<stdio.h>
>> +#include<stdlib.h>
>> +#include<arpa/inet.h>
>> +
>> +#include "host_network_basic.h"
>> +
>> +#ifdef TESTLIB
>> +#include "TestDefines.h"
>> +#else
>> +#include<libcmpiutil/libcmpiutil.h>
>> +#endif
>> +
>> +#define LINUX_FAIL_TO_GET -2
>> +#define LINUX_UNKNOWN -1
>> +#define LINUX_OTHER 0
>> +#define LINUX_REDHAT 1
>> +
>> +#define CMD_DEBUG_LEVEL 2
>> +
>> +/* macro functions */
>> +#define CMD_DEBUG(lvl, fmt, args...) do { \
>> + if (CMD_DEBUG_LEVEL&& (lvl)<= CMD_DEBUG_LEVEL) { \
>> + debug_print(fmt, ##args); \
>> + } \
>> +} while (0)
>> +
>> +#define SAFE_MALLOC(p, size) \
>> +{ \
>> + (p) = malloc((size)); \
>> + if ((p) == NULL) { \
>> + CU_DEBUG("malloc failed."); \
>> + } \
>> +}
>> +
>> +#define SAFE_CALLOC(p, nmen, size) \
>> +{ \
>> + (p) = calloc((nmen), (size)); \
>> + if ((p) == NULL) { \
>> + CU_DEBUG("calloc failed."); \
>> + } \
>> +}
>> +
>> +#define SAFE_FREE(p) {free(p); (p) = NULL; }
>> +
>> +
>> +/* Macro used to compare two char*, it would skip if ref is NULL. It
>> would
>> + only set the result when src != ref, user need to set the result to
>> 1 by
>> + default before use the macro. If not set, the it could be used to do
>> + check multi times in "one fail all die" mode. Empty lines is the place
>> + where result should be set to 1. */
>> +#define CHARS_COMPARE_BY_REF(src, ref, result) do { \
>> + if ((ref) == NULL) { \
>> + ; \
>> + } else { \
>> + if ((src) == NULL) { \
>> + (result) = 0; \
>> + } else { \
>> + if (0 == strcmp((src), (ref))) { \
>> + ; \
>> + } else { \
>> + (result) = 0; \
>> + } \
>> + } \
>> + } \
>> +} while (0)
>> +
>> +#define CHARS_COMPARE_CASE_BY_REF(src, ref, result) do { \
>> + if ((ref) == NULL) { \
>> + ; \
>> + } else { \
>> + if ((src) == NULL) { \
>> + (result) = 0; \
>> + } else { \
>> + if (0 == strcasecmp((src), (ref))) { \
>> + ; \
>> + } else { \
>> + (result) = 0; \
>> + } \
>> + } \
>> + } \
>> +} while (0)
>> +
>> +#define NUM_COMPARE_BY_REF(src, ref, result, default) do { \
>> + if ((ref) == (default)) { \
>> + ; \
>> + } else { \
>> + if ((src) == (ref)) { \
>> + ; \
>> + } else { \
>> + result = 0; \
>> + } \
>> + } \
>> +} while (0)
>> +
>> +#define CHARS_MERGE_NORMAL(dest, src) do { \
>> + if (((dest) == NULL)&& ((src) != NULL)) { \
>> + (dest) = strdup((src)); \
>> + } \
>> +} while (0)
>> +
>> +#define CHARS_MERGE_MOVE(dest, src) do { \
>> + if (((dest) == NULL)&& ((src) != NULL)) { \
>> + (dest) = (src); \
>> + (src) = NULL; \
>> + } \
>> +} while (0)
>> +
>> +#define NUM_MERGE(dest, src, default) do { \
>> + if ((dest) == (default)) { \
>> + (dest) = (src); \
>> + } \
>> +} while (0)
>> +
>> +/* this macro may cause "p" to be excuted twice if it is a function */
>> +#define SAFE_STRDUP(p) (p) == NULL ? NULL : strdup(p);
>> +
>> +/* this macro make sure "src" to be excuted once if it is function,
>> so it is
>> + safe for functions that have state logged, such as "strtok" */
>> +#define SAFE_STRDUP_WITH_FUNC(dest, src, iter) do { \
>> + (iter) = (src); \
>> + if ((iter) == NULL) { \
>> + (dest) = NULL; \
>> + } else { \
>> + (dest) = strdup((iter)); \
>> + } \
>> +} while (0)
>> +
>> +#define SAFE_PSTR_ARRAY_DUP(ppdest, dest_num, ppsrc, src_num, iter)
>> do { \
>> + (dest_num) = (src_num); \
>> + (ppdest) = NULL; \
>> + if (((ppsrc) != NULL)&& ((src_num)> 0)) { \
>> + SAFE_CALLOC((ppdest), (src_num), sizeof(char *)); \
>> + (iter) = 0; \
>> + while ((iter)< (src_num)) { \
>> + *((ppdest)+(iter)) = SAFE_STRDUP(*((ppsrc)+(iter))); \
>> + (iter)++; \
>> + } \
>> + } \
>> +} while (0)
>> +
>> +/* functions */
>> +/* this function convert ip mask "24" in "192.1.0.9/24" to real mask
>> num as
>> + 255.255.255.0 */
>> +int netmask_easy_to_inaddr(struct in_addr *paddr, const char *pmask);
>> +
>> +/* this function would sort the pqos and check its values. */
>> +int vlan_8021q_qos_check_valid(VLAN_Qos_8021q *pqos);
>> +
>> +/* converting qos string of 802.1.Q, it should be as "0:0 1:0 2:0" */
>> +int vlan_8021q_qos_str_to_num(VLAN_Qos_8021q *pqos, const char *str);
>> +int vlan_8021q_qos_num_to_str(char **str, const VLAN_Qos_8021q *pqos);
>> +
>> +/* following functions would return FILE popened, so it need pclose
>> later,
>> + cmd would be appended so it must be writable. */
>> +FILE *pipe_excute_command_type_read(char *cmd, const int buf_size,
>> + const char *type, int *errno);
>> +FILE *pipe_excute_command_type_write(char *cmd, const int buf_size,
>> + const char *type, int *errno);
>> +
>> +/* following functions would return string by malloc, so it need free
>> later */
>> +char *strtok_onetime(const char *str, const char *delim);
>> +char *combine_file_name(const char *prefix, const char *name);
>> +
>> +/* write the configuration file */
>> +int configure_file_update(const char *path, const char *cont);
>> +/* remove the configuration file */
>> +int configure_file_remove(const char *path);
>> +/* replace one attribute, the file have format with one line for one
>> propety */
>> +int configure_file_replace_attr(const char *path, const char *prefix,
>> + const char *prop);
>> +
>> +int get_host_linux_version(void);
>> +
>> +char *translate_error_no(int errno);
>> +
>> +#endif
>
>


-- 
Best Regards

Wayne Xia
mail:xiawenc at linux.vnet.ibm.com
tel:86-010-82450803




More information about the Libvirt-cim mailing list