diff options
Diffstat (limited to 'src/hardware/utils.c')
-rw-r--r-- | src/hardware/utils.c | 382 |
1 files changed, 382 insertions, 0 deletions
diff --git a/src/hardware/utils.c b/src/hardware/utils.c new file mode 100644 index 0000000..da7bbfa --- /dev/null +++ b/src/hardware/utils.c @@ -0,0 +1,382 @@ +/* + * Copyright (C) 2013 Red Hat, Inc. All rights reserved. + * + * 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. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: Peter Schiffer <pschiffe@redhat.com> + */ + +#include "utils.h" + + +short read_fp_to_2d_buffer(FILE *fp, char ***buffer, unsigned *buffer_size) +{ + short ret = -1; + ssize_t read; + size_t line_len = 0; + unsigned tmp_buffer_lines, lines_read = 0; + char **tmp_buffer, *line = NULL; + + free_2d_buffer(buffer, buffer_size); + + if (!fp) { + warn("Given file pointer is NULL."); + ret = -2; + goto done; + } + + /* allocate buffer */ + tmp_buffer_lines = 128; + tmp_buffer = (char **)calloc(tmp_buffer_lines, sizeof(char *)); + if (!tmp_buffer) { + warn("Failed to allocate memory."); + ret = -3; + goto done; + } + + while ((read = getline(&line, &line_len, fp)) != -1) { + /* filter comment lines */ + if (read > 0 && line[0] == '#') { + continue; + } + + /* reallocate if needed */ + if (lines_read >= tmp_buffer_lines) { + tmp_buffer_lines *= 2; + char **newtmp = (char **)realloc(tmp_buffer, + tmp_buffer_lines * sizeof(char *)); + if (!newtmp) { + warn("Failed to allocate memory."); + ret = -4; + goto done; + } + tmp_buffer = newtmp; + } + + /* copy trimmed line to buffer */ + tmp_buffer[lines_read] = trim(line, NULL); + if (!tmp_buffer[lines_read]) { + tmp_buffer[lines_read] = strdup(""); + if (!tmp_buffer[lines_read]) { + warn("Failed to allocate memory."); + ret = -5; + goto done; + } + } + lines_read++; + } + + if (lines_read < 1) { + warn("No data read from given source."); + ret = -6; + goto done; + } + + /* reallocate buffer to free unused space */ + if (tmp_buffer_lines > lines_read) { + tmp_buffer_lines = lines_read; + char **newtmp = (char **)realloc(tmp_buffer, + tmp_buffer_lines * sizeof(char *)); + if (!newtmp) { + warn("Failed to allocate memory."); + ret = -7; + goto done; + } + tmp_buffer = newtmp; + } + + *buffer_size = tmp_buffer_lines; + *buffer = tmp_buffer; + + ret = 0; + +done: + if (line) { + free(line); + } + line = NULL; + + if (ret != 0) { + free_2d_buffer(&tmp_buffer, &tmp_buffer_lines); + } + + return ret; +} + +void free_2d_buffer(char ***buffer, unsigned *buffer_size) +{ + unsigned i, tmp_buffer_lines = *buffer_size; + char **tmp_buffer = *buffer; + + if (tmp_buffer_lines > 0) { + for (i = 0; i < tmp_buffer_lines; i++) { + if (tmp_buffer[i]) { + free(tmp_buffer[i]); + } + tmp_buffer[i] = NULL; + } + free(tmp_buffer); + } + + tmp_buffer = NULL; + *buffer_size = 0; + *buffer = NULL; +} + +short run_command(const char *command, char ***buffer, unsigned *buffer_size) +{ + FILE *fp; + short ret = -1; + + /* if command is empty */ + if (!command || strlen(command) < 1) { + warn("Given command is empty."); + ret = -2; + goto done; + } + + /* execute command */ + debug("Running command: \"%s\"", command); + fp = popen(command, "r"); + if (!fp) { + warn("Failed to run command: \"%s\"; Error: %s", + command, strerror(errno)); + ret = -3; + goto done; + } + + if (read_fp_to_2d_buffer(fp, buffer, buffer_size) != 0) { + ret = -4; + goto done; + } + + ret = 0; + +done: + if (fp) { + int ret_code = pclose(fp); + if (ret_code == -1) { + warn("Failed to run command: \"%s\"; Error: %s", + command, strerror(errno)); + if (ret == 0) { + ret = -5; + } + } else if (ret_code != 0) { + warn("Command \"%s\" exited unexpectedly.", command); + if (ret == 0) { + ret = -6; + } + } + } + + if (ret != 0) { + free_2d_buffer(buffer, buffer_size); + } + + return ret; +} + +short read_file(const char *filename, char ***buffer, unsigned *buffer_size) +{ + FILE *fp; + short ret = -1; + + /* open file */ + debug("Reading \"%s\" file.", filename); + fp = fopen(filename, "r"); + if (!fp) { + warn("Failed to open \"%s\" file.", filename); + ret = -2; + goto done; + } + + if (read_fp_to_2d_buffer(fp, buffer, buffer_size) != 0) { + ret = -3; + goto done; + } + + ret = 0; + +done: + if (fp) { + fclose(fp); + } + + if (ret != 0) { + free_2d_buffer(buffer, buffer_size); + } + + return ret; +} + +char *copy_string_part_after_delim(const char *str, const char *delim) +{ + if (!str || strlen(str) < 1 || !delim || strlen(delim) < 1) { + return NULL; + } + + char *p, *out = NULL; + size_t delim_len = strlen(delim); + + /* if str contains delim and there is something after it */ + if ((p = strstr(str, delim)) && strlen(p + delim_len) > 0) { + out = trim(p + delim_len, NULL); + } + + return out; +} + +char *trim(const char *str, const char *delims) +{ + char *out; + const char *default_delims = WHITESPACES; + size_t l; + + /* if string is empty */ + if (!str || strlen(str) < 1) { + return NULL; + } + + if (!delims) { + delims = default_delims; + } + + /* trim start of the string */ + while (strchr(delims, str[0]) && str[0] != '\0') { + str++; + } + + l = strlen(str); + + /* if string was only white spaces */ + if (l < 1) { + return NULL; + } + + /* shorten length of string if there are trailing white spaces */ + while (strchr(delims, str[l - 1]) && l != 0) { + l--; + } + + /* sanity check */ + if (l < 1) { + return NULL; + } + + /* copy string */ + out = strndup(str, l); + if (!out) { + warn("Failed to allocate memory."); + } + + return out; +} + +short explode(const char *str, const char *delims, char ***buffer, unsigned *buffer_size) +{ + size_t l; + short ret = -1; + unsigned item = 0, tmp_buffer_size; + char *default_delims = WHITESPACES, *trimmed_str = NULL, *ts, **tmp_buffer; + + free_2d_buffer(buffer, buffer_size); + + if (!str || strlen(str) < 1) { + ret = 0; + goto done; + } + + if (!delims) { + delims = default_delims; + } + + trimmed_str = trim(str, delims); + if (!trimmed_str || strlen(trimmed_str) < 1) { + ret = 0; + goto done; + } + + tmp_buffer_size = 128; + tmp_buffer = (char **)calloc(tmp_buffer_size, sizeof(char *)); + if (!tmp_buffer) { + warn("Failed to allocate memory."); + ret = -2; + goto done; + } + + ts = trimmed_str; + while (ts[0] != '\0') { + /* skip leading delimiters of substring */ + while (strchr(delims, ts[0]) && ts[0] != '\0') { + ts++; + } + /* find length of valid substring */ + l = 0; + while (!strchr(delims, ts[l]) && ts[l] != '\0') { + l++; + } + /* reallocate if needed */ + if (item >= tmp_buffer_size) { + tmp_buffer_size *= 2; + char **new_temp = (char **)realloc(tmp_buffer, + tmp_buffer_size * sizeof(char *)); + if (!new_temp) { + warn("Failed to allocate memory."); + ret = -3; + goto done; + } + tmp_buffer = new_temp; + } + /* copy the substring */ + tmp_buffer[item] = strndup(ts, l); + if (!tmp_buffer[item]) { + warn("Failed to allocate memory."); + ret = -4; + goto done; + } + item++; + ts += l; + } + + /* reallocate to save unused space */ + if (tmp_buffer_size > item) { + tmp_buffer_size = item; + char **new_temp = (char **)realloc(tmp_buffer, + tmp_buffer_size * sizeof(char *)); + if (!new_temp) { + warn("Failed to allocate memory."); + ret = -5; + goto done; + } + tmp_buffer = new_temp; + } + + *buffer_size = tmp_buffer_size; + *buffer = tmp_buffer; + + ret = 0; + +done: + if (trimmed_str) { + free(trimmed_str); + } + trimmed_str = NULL; + + if (ret != 0) { + free_2d_buffer(&tmp_buffer, &tmp_buffer_size); + } + + return ret; +} |