On 12/30/2011 05:29 AM, Wayne Xia wrote:
δΊ 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(a)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?
I would not say bad, just odd looking to me. In general, we've not had
this level of
detail in return codes thus far. IIRC, you're using these as "extended"
error codes
via errorno, so the caller can get more detail if the API returns an unexpected
result. With that in mind, I don't have an objection.
>> +
>> +#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(a)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(a)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
>
>
--
Chip Vincent
Open Virtualization
IBM Linux Technology Center
cvincent(a)linux.vnet.ibm.com