summaryrefslogtreecommitdiffstats
path: root/src/hardware/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/hardware/utils.c')
-rw-r--r--src/hardware/utils.c382
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;
+}