replace common qcom sources with samsung ones

This commit is contained in:
SaschaNes
2025-08-12 22:13:00 +02:00
parent ba24dcded9
commit 6f7753de11
5682 changed files with 2450203 additions and 103634 deletions

View File

@@ -0,0 +1,2 @@
include $(call all-subdir-makefiles)

View File

@@ -0,0 +1,3 @@
AUTOMAKE_OPTIONS = foreign
SUBDIRS = src

View File

@@ -0,0 +1,51 @@
#!/bin/sh
# Copyright (c) 2015, The Linux Foundation. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
# * Neither the name of The Linux Foundation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
ACLOCAL=`which aclocal`
AUTOCONF=`which autoconf`
AUTOMAKE=`which automake`
if [ ! -x "$ACLOCAL" ]; then
echo "Missing 'aclocal'; not in path. Make sure it is installed!"
exit -1
fi
if [ ! -x "$AUTOCONF" ]; then
echo "Missing 'autoconf'; not in path. Make sure it is installed!"
exit -1
fi
if [ ! -x "$AUTOMAKE" ]; then
echo "Missing 'automake'; not in path. Make sure it is installed!"
exit -1
fi
$ACLOCAL
$AUTOCONF
$AUTOMAKE -a

View File

@@ -0,0 +1,56 @@
# -*- Autoconf -*-
# Copyright (c) 2015, The Linux Foundation. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
# * Neither the name of The Linux Foundation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.68])
AC_INIT([Data Top], [1.0.4], [harouth@codeaurora.org])
AC_CONFIG_SRCDIR([src/datatop.c])
#AC_CONFIG_HEADERS([src/config.h])
AC_CONFIG_FILES([Makefile
src/Makefile])
# Checks for programs.
AC_PROG_CC
# Checks for libraries.
# Checks for header files.
AC_CHECK_HEADERS([stdlib.h string.h])
# Checks for typedefs, structures, and compiler characteristics.
# Checks for library functions.
AC_FUNC_MALLOC
#### Generate Makefile Data
AM_INIT_AUTOMAKE([datatop], [1.0.4])
AC_OUTPUT

View File

@@ -0,0 +1,36 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := datatop.c
LOCAL_SRC_FILES += datatop_cpu_stats_poll.c
LOCAL_SRC_FILES += datatop_dev_poll.c
LOCAL_SRC_FILES += datatop_dual_line_poll.c
LOCAL_SRC_FILES += datatop_fileops.c
LOCAL_SRC_FILES += datatop_gen_poll.c
LOCAL_SRC_FILES += datatop_helpers.c
LOCAL_SRC_FILES += datatop_linked_list.c
LOCAL_SRC_FILES += datatop_meminfo_file_poll.c
LOCAL_SRC_FILES += datatop_opt.c
LOCAL_SRC_FILES += datatop_single_line_poll.c
LOCAL_SRC_FILES += datatop_stat_poll.c
LOCAL_SRC_FILES += datatop_str.c
LOCAL_SRC_FILES += datatop_sys_snap.c
LOCAL_SRC_FILES += datatop_value_only_poll.c
LOCAL_SRC_FILES += datatop_ip_table_poll.c
LOCAL_CFLAGS := -Wall -Wextra -Werror -pedantic -std=c99
LOCAL_CFLAGS += -DVERSION="\"1.0.4"\"
LOCAL_CFLAGS += -DHAVE_STRL_FUNCTIONS
LOCAL_CFLAGS += -D _BSD_SOURCE
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_CLANG := true
LOCAL_MODULE := datatop
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH_32 := $(TARGET_OUT_VENDOR)/lib
LOCAL_MODULE_PATH_64 := $(TARGET_OUT_VENDOR)/lib64
include $(BUILD_EXECUTABLE)

View File

@@ -0,0 +1,23 @@
## Makefile.am for main application
CFLAGS := -std=c99 # Target c99 for portability
CFLAGS += -Wall -Wextra -Werror -pedantic # Strict code quality enforcement
CFLAGS += -g -D _BSD_SOURCE # Enable debugging and BSD time functions
bin_PROGRAMS = datatop
datatop_SOURCES := datatop.c
datatop_SOURCES += datatop_fileops.c
datatop_SOURCES += datatop_dual_line_poll.c
datatop_SOURCES += datatop_single_line_poll.c
datatop_SOURCES += datatop_meminfo_file_poll.c
datatop_SOURCES += datatop_dev_poll.c
datatop_SOURCES += datatop_stat_poll.c
datatop_SOURCES += datatop_value_only_poll.c
datatop_SOURCES += datatop_str.c
datatop_SOURCES += datatop_cpu_stats_poll.c
datatop_SOURCES += datatop_helpers.c
datatop_SOURCES += datatop_linked_list.c
datatop_SOURCES += datatop_opt.c
datatop_SOURCES += datatop_gen_poll.c
datatop_SOURCES += datatop_sys_snap.c
datatop_SOURCES += datatop_ip_table_poll.c

View File

@@ -0,0 +1,306 @@
/************************************************************************
Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
************************************************************************/
/**
* @file datatop.c
* @brief Executes commands for application.
*
* Contains the main() function where program executes. Calls appropriate
* methods based on user's CLI commands. Executes parsing function to
* determine necessary output and handles errors which may arise during the
* parse. Initiliazes files for data collection. Will call functions designed
* to poll and print the data in understandable format.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <pthread.h>
#include "datatop_interface.h"
#include "datatop_linked_list.h"
#include "datatop_opt.h"
#include "datatop_fileops.h"
#include "datatop_polling.h"
#include "datatop_gen_poll.h"
#define DTOP_SEC_TO_USEC(x) ((x)*1000000)
#define DTOP_USEC_TO_SEC(x) ((x)/1000000)
struct dtop_linked_list *first_dpg_list;
struct cli_opts usr_cl_opts;
/**
* @brief Prints the datapoint names and values to the terminal.
*
* @param dpg_list A pointer to the first node of a linked list which
* contains all data_point_gatherer structs to print.
*/
void dtop_print_terminal(struct dtop_linked_list *dpg_list)
{
struct dtop_linked_list *curr_ptr = dpg_list;
struct dtop_data_point_gatherer *dpset;
while (curr_ptr) {
dpset = (struct dtop_data_point_gatherer *) curr_ptr->data;
dtop_print_dpg(dpset);
curr_ptr = curr_ptr->next_ptr;
}
}
/**
* @brief Polls the data periodically and prints to file specified by the user.
*
* Polls the data as often as specified by the user in their CLI arguments
* and outputs the data to a file also specified in CLI arguments. Then prints
* a snapshot of delta(dp_value) to the terminal.
*
* @param dpg_list A pointer to the first node of a linked list which contains
* all data_point_gatherer structs to poll and print.
* @param fw A pointer to the file which will be printed to.
* @return FILE_ERROR - Writing to file was unsuccessful.
* @return FILE_SUCCESS - Writing to file was successful.
*/
int dtop_poll_periodically(struct dtop_linked_list *dpg_list, FILE *fw)
{
struct timeval tv, timeout;
fd_set rfds;
time_t curtime, endtime;
int inp, quit = 0;
struct dtop_linked_list *curr_ptr = dpg_list;
struct dtop_data_point_gatherer *dpset;
struct timeval ftime, itime, polltime;
gettimeofday(&tv, NULL);
curtime = DTOP_SEC_TO_USEC(tv.tv_sec)+tv.tv_usec;
endtime = DTOP_SEC_TO_USEC(tv.tv_sec)+ DTOP_SEC_TO_USEC(usr_cl_opts.poll_time);
/* print all of our datapoint names as column headers in csv format */
if (fprintf(fw, "\"Time\",") < 0)
return FILE_ERROR;
while (curr_ptr) {
dpset = (struct dtop_data_point_gatherer *) curr_ptr->data;
if (dtop_print_dpg_names_csv(dpset, fw) == FILE_ERROR)
return FILE_ERROR;
curr_ptr = curr_ptr->next_ptr;
}
if (fprintf(fw, "\n") < 0)
return FILE_ERROR;
dtop_print_interactive_opts();
gettimeofday(&itime, NULL);
/* periodically poll the datapoints and print in csv format */
while (curtime < endtime
|| usr_cl_opts.poll_time == POLL_NOT_SPECIFIED) {
FD_ZERO(&rfds);
FD_SET(0, &rfds);
timeout.tv_sec = DTOP_USEC_TO_SEC(usr_cl_opts.poll_per);
timeout.tv_usec = (usr_cl_opts.poll_per%1000000);
//ftime is right before timeout calculations for most acurate calculations
gettimeofday(&ftime, NULL);
timersub(&ftime, &itime, &polltime);
timersub(&timeout,&polltime, &timeout);
inp = select(1, &rfds, NULL, NULL, &timeout);
gettimeofday(&itime, NULL);
if (inp) {
char s[4];
scanf("%s", s);
if (strcmp(s, "quit") == 0
|| strcmp(s, "q") == 0) {
quit = QUIT;
break;
}
if (strcmp(s, "i") == 0) {
dtop_print_snapshot_diff(first_dpg_list);
dtop_reset_dp_initial_values(first_dpg_list);
}
if (strcmp(s, "l") == 0)
dtop_print_snapshot_diff(first_dpg_list);
}
gettimeofday(&tv, NULL);
curtime = DTOP_SEC_TO_USEC(tv.tv_sec)+tv.tv_usec;
dtop_poll(dpg_list);
if (dtop_print_time_at_poll(fw) == FILE_ERROR)
return FILE_ERROR;
if (dtop_write_pollingdata_csv(dpg_list, fw) == FILE_ERROR)
return FILE_ERROR;
}
if (quit != QUIT)
dtop_print_snapshot_diff(dpg_list);
return FILE_SUCCESS;
}
static void dtop_set_niceness(int niceness)
{
int pid, rc;
pid = getpid();
printf("Requesting nice %d\n", niceness);
rc = setpriority(PRIO_PROCESS, pid, niceness);
if (rc != 0)
fprintf(stderr, "Error setting priority [%d]\n", errno);
rc = getpriority(PRIO_PROCESS, pid);
printf("Running with nice %d.\n", rc);
}
int main(int argc, char **argv)
{
int parse_status;
pthread_t tid;
printf("DataTop - Version %s\n", VERSION);
printf("(c)2014-2015 Linux Foundation\n");
dtop_load_default_options(&usr_cl_opts);
parse_status = dtop_parse_cli_opts(&usr_cl_opts, argc, argv);
switch (parse_status) {
case PARSE_SUCCESS:
dtop_set_niceness(usr_cl_opts.priority);
break;
case PARSE_FORCE_EXIT:
exit(EXIT_SUCCESS);
break;
case PARSE_FAILURE:
default:
printf("Failed to parse command line arguments.\n");
exit(EXIT_FAILURE);
break;
}
if (usr_cl_opts.iptables_rules_routes == OPT_CHOSE) {
if (usr_cl_opts.out_dir[0] == '\0') {
printf("Please provide an out directory.\n");
exit(EXIT_FAILURE);
}
}
dtop_dual_line_init("/proc/net/netstat");
dtop_dual_line_init("/proc/net/snmp");
dtop_single_line_init("/proc/net/snmp6");
dtop_gen_init("/proc/sys/net/");
dtop_gen_init("/sys/module/rmnet/parameters/");
dtop_gen_init("/sys/module/rmnet_perf/parameters/");
dtop_gen_init("/sys/module/rmnet_shs/parameters/");
dtop_gen_init("/sys/module/rmnet_data/parameters/");
dtop_gen_init("/sys/class/net/rmnet_mhi0/statistics/");
dtop_gen_init("/sys/class/net/usb_rmnet0/statistics/");
dtop_gen_init("/sys/class/net/rmnet_ipa0/statistics/");
dtop_meminfo_init();
dtop_dev_init();
dtop_stat_init();
dtop_cpu_stats_init();
dtop_gen_init("/sys/kernel/debug/clk/bimc_clk/");
dtop_gen_init("/sys/kernel/debug/clk/snoc_clk/");
dtop_gen_init("/sys/kernel/debug/clk/pnoc_clk/");
if (usr_cl_opts.iptables_rules_routes == OPT_CHOSE) {
printf("Datatop IP Tables, rules, routes\n");
dtop_ip_table_init(usr_cl_opts.out_dir);
if(0 != pthread_create(&tid, NULL, &dtop_ip_table_start_poll, NULL)) {
printf("Unable to create capture_ip_tables_rules_routes thread\n");
}
}
if (usr_cl_opts.print_cl == OPT_CHOSE) {
dtop_poll(first_dpg_list);
dtop_print_terminal(first_dpg_list);
}
if (usr_cl_opts.print_csv == OPT_CHOSE) {
FILE *to_file = NULL;
if ((dtop_open_writing_file(usr_cl_opts.file_name,
&to_file)) == VALID) {
printf("\nData being polled for %ld seconds.\n",
usr_cl_opts.poll_time);
if (dtop_poll_periodically(first_dpg_list, to_file)
== FILE_ERROR) {
fprintf(stderr, "err=%d: %s\n", errno,
strerror(errno));
dtop_close_file(to_file);
deconstruct_dpgs(first_dpg_list);
dtop_rem_linked_list(first_dpg_list);
exit(EXIT_FAILURE);
}
dtop_close_file(to_file);
} else {
printf("File Can Not Be Opened\n");
exit(EXIT_FAILURE);
}
}
if (usr_cl_opts.snapshot_file) {
if (dtop_print_system_snapshot(usr_cl_opts.snapshot_file)
== FILE_ERROR) {
fprintf(stderr, "err=%d: %s\n", errno,
strerror(errno));
deconstruct_dpgs(first_dpg_list);
dtop_rem_linked_list(first_dpg_list);
exit(EXIT_FAILURE);
}
}
if (usr_cl_opts.print_cl == OPT_NOT_CHOSE &&
usr_cl_opts.print_csv == OPT_NOT_CHOSE) {
if ((!usr_cl_opts.snapshot_file)
|| usr_cl_opts.poll_time_selected == POLL_TIME_SELECTED) {
printf("\nData will now be polled for %ld seconds.\n",
usr_cl_opts.poll_time);
dtop_poll(first_dpg_list);
sleep(usr_cl_opts.poll_time);
dtop_poll(first_dpg_list);
dtop_print_snapshot_diff(first_dpg_list);
}
}
deconstruct_dpgs(first_dpg_list);
dtop_rem_linked_list(first_dpg_list);
return 0;
}
/**
* @brief Adds each dpg as a node to a linked list.
*
* Called when a dpg is initialized.
*
* @param dpg A pointer to a data_point_gatherer struct which is to be added to the linked list.
*/
void dtop_register(struct dtop_data_point_gatherer *dpg)
{
if (dpg)
first_dpg_list = dtop_add_linked_list(dpg, first_dpg_list);
}

View File

@@ -0,0 +1,182 @@
/************************************************************************
Copyright (c) 2015, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
************************************************************************/
/**
* @file datatop_cpu_stats_poll.c
* @brief Calls dtop_value_only_init for necessary cpu datapoints.
*
* File contains methods for determing number of cpu's online and calling
* correct initialization function to gather scaling_cur_freq data point
* for each cpu along with each cpu's online status.
*/
#include <unistd.h>
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <ctype.h>
#include "datatop_interface.h"
#include "datatop_fileops.h"
#include "datatop_str.h"
#include "datatop_polling.h"
#define DTOP_GEN_SIZE 8192
#define DTOP_GEN_LINE (DTOP_GEN_SIZE>>2)
#define NO_CPUS_ONLINE -1
/**
* @brief Searches /sys/devices/system/cpu/ directory to get find number of CPUs.
*
* @return Number of CPUs found in directory.
*/
static int dtop_cpu_search(void)
{
DIR *dp;
struct dirent *entry;
struct stat s;
int cpu_amt;
char cwd[1024];
if (!getcwd(cwd, sizeof(cwd))) {
fprintf(stderr, "Failed to get current working dir\n");
return -1;
}
dp = opendir("/sys/devices/system/cpu/");
if (dp == NULL) {
fprintf(stderr, "err=%d: %s\n", errno, strerror(errno));
fprintf(stderr, "Cannot open directory: %s\n",
"/sys/devices/system/cpu/");
return NO_CPUS_ONLINE;
}
chdir("/sys/devices/system/cpu/");
cpu_amt = 0;
while ((entry = readdir(dp))) {
if (stat(entry->d_name, &s)) {
printf("stat err=%d: %s\n", errno, strerror(errno));
return NO_CPUS_ONLINE;
}
if (entry->d_name[0] == 'c' &&
entry->d_name[1] == 'p' &&
entry->d_name[2] == 'u' &&
(isdigit(entry->d_name[3]))) {
cpu_amt++;
}
}
closedir(dp);
chdir(cwd);
return cpu_amt;
}
/**
* @brief Creates a dpg designed for CPU online and CPU scaling_cur_freq stats.
*
* @param name Name of file dpg represents.
*/
static void construct_cpu_stat_dpg(char *name)
{
char *file = malloc(strlen(name) + 1);
struct dtop_data_point *dp =
malloc(sizeof(struct dtop_data_point));
struct dtop_data_point_gatherer *dpg = malloc
(sizeof(struct dtop_data_point_gatherer));
strlcpy(file, name, strlen(name) + 1);
dp[0].type = DTOP_ULONG;
dp[0].name = malloc(5);
strlcpy(dp[0].name, "", 5);
dp[0].prefix = NULL;
dp[0].data.d_ulong = 0;
dp[0].initial_data.d_ulong = 0;
dp[0].skip = DO_NOT_SKIP;
dp[0].initial_data_populated = NOT_POPULATED;
dpg->prefix = file;
dpg->file = file;
dpg->poll = dtop_value_only_poll;
dpg->data_points = dp;
dpg->data_points_len = 1;
dpg->deconstruct = dtop_value_only_dpg_deconstructor;
dtop_register(dpg);
}
/**
* @brief Calls dpg constructor for necessary CPU stat files.
*
* Creates file names based on number of CPUs found and calls the
* dpg constructor for them.
*
* @param file Directory where the CPUs are found.
* @param add String which is concatenated onto file and represents
* the path after a CPU directory is entered.
* @param cpu_amt Amount of CPUs found on device.
*/
static void cpu_poll_helper(char *file, char *add, int cpu_amt)
{
int i;
for (i = 0; i < cpu_amt; i++) {
char *cpu_num = malloc(5);
char *newfile;
int nf_len;
snprintf(cpu_num, 5, "%d", i);
nf_len = strlen(file) + strlen(add) + strlen(cpu_num) + 2;
newfile = malloc(nf_len);
strlcpy(newfile, file, nf_len);
strlcat(newfile, cpu_num, nf_len);
strlcat(newfile, add, nf_len);
free(cpu_num);
construct_cpu_stat_dpg(newfile);
free(newfile);
}
}
/**
* @brief Calls necessary functions for CPU stat dpgs.
*/
void dtop_cpu_stats_init(void)
{
int cpu_amt;
char *file = "/sys/devices/system/cpu/cpu";
char *add = "/cpufreq/scaling_cur_freq";
cpu_amt = dtop_cpu_search();
cpu_poll_helper(file, add, cpu_amt);
add = "/online";
cpu_poll_helper(file, add, cpu_amt);
}

View File

@@ -0,0 +1,320 @@
/************************************************************************
Copyright (c) 2015, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
************************************************************************/
/**
* @file datatop_dev_poll.c
* @brief Adds ability for data collection from /proc/net/dev
*
* File contains methods for searching and polling data from
* "/proc/net/dev"
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "datatop_interface.h"
#include "datatop_fileops.h"
#include "datatop_str.h"
#define DTOP_DEV_SIZE 8192
#define DTOP_DEV_LINE (DTOP_DEV_SIZE>>2)
/**
* @struct dtop_dev_vars
* @brief Struct used to hold necessary variables for /proc/net/dev dpg
*
* @var dtop_dev_vars::line
* Array of strings where necessary dp names and values are held.
* @var dtop_dev_vars::line_count
* Number of lines the file is that the dpg represents.
*/
struct dtop_dev_vars {
char **line;
int line_count;
};
/**
* @brief Parses lines with data in "/proc/net/dev"
*
* @param line1 Line to parse to find datapoint names and values.
* @param len1 Length of line1.
* @param index Index in the dictionary the key (name) is added to.
* @param dict Dictionary the keys and values are added to.
*/
static void dt_dev_parse(char *line1, int len1,
int index, struct dt_procdict *dict)
{
int i, start = 0;
int j, k, n;
i = 0;
while (line1[i] == ' ' || line1[i] == ' ')
i++;
dict->key[index] = &line1[i];
for (i = 0; i < len1; i++) {
if (line1[i] == ':') {
line1[i+1] = 0;
start = i+2;
break;
}
}
k = 0;
for (j = start; j < len1; j++) {
if (line1[j] != ' ' && line1[j] != ' ') {
dict->val[k] = &line1[j];
n = j;
while (line1[n] != 0 && line1[n] != ' ' && line1[n] != ' ')
n++;
if (n < len1)
line1[n] = 0;
j = n;
k++;
}
}
}
/**
* @brief Stores the data collected from "/proc/net/dev"
*
* @param dpg Struct that polled data is added to.
* @return DTOP_POLL_IO_ERR - Poll of dpg unsuccessful.
* @return DTOP_POLL_OK - Poll of dpg successful.
*/
int dtop_dev_poll(struct dtop_data_point_gatherer *dpg)
{
char *data;
int *line_len = malloc(sizeof(int) *
((struct dtop_dev_vars *)
(dpg->priv))->line_count);
int read;
struct dt_procdict *dict = malloc(sizeof(struct dt_procdict)
*((struct dtop_dev_vars *)
(dpg->priv))->line_count-2);
int j, n, sum;
int index = 0;
int dp = 0;
read = dt_read_file(dpg->file, &data, DTOP_DEV_SIZE);
if (read == 0 || data == 0)
return DTOP_POLL_IO_ERR;
sum = 0;
/* Assigns each line read from the file, a length */
for (n = 0; n < ((struct dtop_dev_vars *)
(dpg->priv))->line_count; n++) {
line_len[n] = dt_read_line(((struct dtop_dev_vars *)
(dpg->priv))->line[n],
DTOP_DEV_LINE, data,
DTOP_DEV_SIZE, sum);
if (n <= (((struct dtop_dev_vars *)
(dpg->priv))->line_count - 1)) {
sum += (line_len[n] + 1);
}
}
for (n = 2; n < ((struct dtop_dev_vars *)
(dpg->priv))->line_count; n++) {
dt_dev_parse(((struct dtop_dev_vars *)
(dpg->priv))->line[n], line_len[n],
index, &dict[index]);
index++;
}
/* Assigns the dp value to the dp struct */
for (n = 2; n < ((struct dtop_dev_vars *)
(dpg->priv))->line_count; n++) {
for (j = 0; j < 16; j++) {
dtop_store_dp(&(dpg->data_points[dp]),
dict[n-2].val[j]);
dp++;
}
}
dt_free(&data);
free(line_len);
free(dict);
return DTOP_POLL_OK;
}
/**
* @brief Frees dynamically allocated "/proc/net/dev" dpg.
*
* Frees the memory of the dpg along with it's data_points
* and other malloc'd memory no longer needed.
*
* @param dpg Dpg to deconstruct and deallocate memory for.
*/
static void dtop_dev_dpg_deconstructor
(struct dtop_data_point_gatherer *dpset)
{
int i, j, dp;
dp = 0;
for (j = 0; j < ((((struct dtop_dev_vars *)
(dpset->priv))->line_count)-2); j++) {
for (i = 0; i < 16; i++) {
free(dpset->data_points[dp].prefix);
dp++;
}
}
free(dpset->data_points);
for (i = 0; i < ((struct dtop_dev_vars *)
(dpset->priv))->line_count; i++)
free(((struct dtop_dev_vars *)(dpset->priv))->line[i]);
free(((struct dtop_dev_vars *)(dpset->priv))->line);
free(((struct dtop_dev_vars *)(dpset->priv)));
free(dpset);
}
/**
* @brief Creates a dpg for "/proc/net/dev" file
*
* Dynamically allocates memory for dpg which is then added to a linked list
* via the dtop_register(dpg) function call.
*
* @param data_points dtop_data_point struct that dpg points to.
* @param storage dtop_dev_vars struct that holds relevant dpg variables.
*/
static void construct_dev_file_dpg(struct dtop_dev_vars *storage,
int dp_count, struct dtop_data_point *data_points)
{
struct dtop_data_point_gatherer *dpg = malloc
(sizeof(struct dtop_data_point_gatherer));
dpg->prefix = "/proc/net/dev";
dpg->file = "/proc/net/dev";
dpg->poll = dtop_dev_poll;
dpg->data_points = data_points;
dpg->priv = (struct dtop_dev_vars *)storage;
dpg->data_points_len = dp_count;
dpg->deconstruct = dtop_dev_dpg_deconstructor;
dtop_register(dpg);
}
/**
* @brief Scans "/proc/net/dev in order to autodetect dps.
*
* Searches through "/proc/net/dev" file for all available data
* points to create as dp structs.
*
* @param name This is the file name "/proc/net/dev" passed in by dtop_dev_init
* @param storage dtop_dev_vars struct where relevant variables are stored.
*/
int dtop_dev_search(char *name, struct dtop_dev_vars *storage)
{
int i, n, sum;
char *data;
int *line_len = malloc(sizeof(int) * storage->line_count);
int read;
struct dt_procdict dict;
struct dt_procdict dev_dict;
struct dtop_data_point *data_points = malloc
(sizeof(struct dtop_data_point) * 16 * (storage->line_count-2));
int dp_count = (16 * (storage->line_count - 2));
int index = 0;
int dp = 0;
storage->line = malloc(storage->line_count * sizeof(*storage->line));
for (i = 0; i < storage->line_count; i++)
storage->line[i] = malloc(sizeof(char) * DTOP_DEV_LINE);
dev_dict.val[0] = "bytes";
dev_dict.val[1] = "packets";
dev_dict.val[2] = "errs";
dev_dict.val[3] = "drop";
dev_dict.val[4] = "fifo";
dev_dict.val[5] = "frame";
dev_dict.val[6] = "compressed";
dev_dict.val[7] = "multicast";
dev_dict.val[8] = "bytes";
dev_dict.val[9] = "packets";
dev_dict.val[10] = "errs";
dev_dict.val[11] = "drop";
dev_dict.val[12] = "fifo";
dev_dict.val[13] = "colls";
dev_dict.val[14] = "carrier";
dev_dict.val[15] = "compressed";
read = dt_read_file(name, &data, DTOP_DEV_SIZE);
if (read == 0 || data == 0)
return DTOP_POLL_IO_ERR;
sum = 0;
/* Assigns each line read from the file, a length */
for (n = 0; n < storage->line_count; n++) {
line_len[n] = dt_read_line(storage->line[n],
DTOP_DEV_LINE, data,
DTOP_DEV_SIZE, sum);
if (n < (storage->line_count - 1))
sum += (line_len[n] + 1);
}
construct_dev_file_dpg(storage, dp_count, data_points);
for (n = 2; n < storage->line_count; n++) {
dt_dev_parse(storage->line[n], line_len[n], index, &dict);
index++;
}
for (n = 2; n < storage->line_count; n++) {
for (i = 0; i < 16; i++) {
char *pref = malloc(30 * sizeof(char));
data_points[dp].skip = 0;
data_points[dp].initial_data_populated = NOT_POPULATED;
if (i < 8)
strlcpy(pref, "Receive:", 30 * sizeof(char));
else if (i >= 8)
strlcpy(pref, "Transmit:", 30 * sizeof(char));
strlcat(pref, dev_dict.val[i], 30 * sizeof(char));
data_points[dp].prefix = pref;
data_points[dp].name = dict.key[n-2];
data_points[dp].type = DTOP_ULONG;
dp++;
}
index++;
}
free(line_len);
dt_free(&data);
return DTOP_POLL_OK;
}
/**
* @brief Calls dtop_search for "/proc/net/dev" file.
*/
void dtop_dev_init(void)
{
struct dtop_dev_vars *storage = malloc
(sizeof(struct dtop_dev_vars));
storage->line_count = dtop_get_file_line_amount("/proc/net/dev");
dtop_dev_search("/proc/net/dev", storage);
}

View File

@@ -0,0 +1,319 @@
/************************************************************************
Copyright (c) 2015, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
************************************************************************/
/**
* @file datatop_dual_line_poll.c
* @brief Adds ability for data collection from dual line files.
*
* File contains methods for searching and polling data from
* dual line files, meaning the first line contains the dp names
* while the second line contains the corresponding values.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "datatop_interface.h"
#include "datatop_fileops.h"
#include "datatop_str.h"
#define DTOP_DUAL_SIZE 8192
#define DTOP_DUAL_LINE (DTOP_DUAL_SIZE>>2)
/**
* @struct dtop_dual_line_vars
* @brief Struct used to hold necessary variables for dual_line_file dpgs.
*
* @var dtop_dual_line_vars::line
* Array of strings where necessary dp names and values are held.
* @var dtop_dual_line_vars::line2
* Array of strings where necessary dp names and values are held.
* @var dtop_dual_line_vars::line_count
* Number of lines the file is that the dpg represents.
*/
struct dtop_dual_line_vars {
char **line;
char **line2;
int line_count;
};
/**
* @brief Stores the data collected from a dual_line file.
*
* @param dpg Struct that polled data is added to.
* @return DTOP_POLL_IO_ERR - Poll of dpg unsuccessful.
* @return DTOP_POLL_OK - Poll of dpg successful.
*/
int dtop_dual_line_poll(struct dtop_data_point_gatherer *dpg)
{
char *data;
int *line_len = malloc(sizeof(int) *
((struct dtop_dual_line_vars *)
(dpg->priv))->line_count);
int *line_len2 = malloc(sizeof(int) *
((struct dtop_dual_line_vars *)
(dpg->priv))->line_count);
int read;
struct dt_procdict *dict = malloc(sizeof(struct dt_procdict)
* (((struct dtop_dual_line_vars *)
(dpg->priv))->line_count/2));
struct dt_procdict *prefix_dict = malloc(sizeof(struct dt_procdict)
* (((struct dtop_dual_line_vars *)
(dpg->priv))->line_count/2));
int i, j, k, n, sum, sum2;
read = dt_read_file(dpg->file, &data, DTOP_DUAL_SIZE);
if (read == 0 || data == 0)
return DTOP_POLL_IO_ERR;
sum = 0;
sum2 = 0;
/* Assigns each line read from the file, a length */
for (n = 0; n < ((struct dtop_dual_line_vars *)
(dpg->priv))->line_count; n++) {
line_len[n] = dt_read_line(((struct dtop_dual_line_vars *)
(dpg->priv))->line[n],
DTOP_DUAL_LINE, data,
DTOP_DUAL_SIZE, sum);
line_len2[n] = dt_read_line(((struct dtop_dual_line_vars *)
(dpg->priv))->line2[n],
DTOP_DUAL_LINE, data,
DTOP_DUAL_SIZE, sum2);
if (n <= (((struct dtop_dual_line_vars *)
(dpg->priv))->line_count-2)) {
sum += (line_len[n] + 1);
sum2 += (line_len2[n] + 1);
}
}
/* Stores dp names and values in dictionary */
for (i = 0; i < (((struct dtop_dual_line_vars *)
(dpg->priv))->line_count/2); i++)
dt_parse_proc_dictionary(((struct dtop_dual_line_vars *)
(dpg->priv))->line[2*i],
line_len[2*i],
((struct dtop_dual_line_vars *)
(dpg->priv))->line[(2*i)+1],
line_len[(2*i)+1],
&dict[i]);
/* Stores dp prefices in dictionary */
for (i = 0; i < (((struct dtop_dual_line_vars *)
(dpg->priv))->line_count/2); i++)
dt_parse_for_prefix(((struct dtop_dual_line_vars *)
(dpg->priv))->line2[2*i], line_len2[2*i],
&prefix_dict[i]);
/* Assigns a dp value to each dp struct */
for (k = 0; k < (((struct dtop_dual_line_vars *)
(dpg->priv))->line_count/2); k++) {
for (j = 0; j < dpg->data_points_len; j++) {
i = dt_find_dict_idx(dpg->data_points[j].name,
&dict[k]);
if (i >= 0 && i < dict[k].max &&
(strcmp(dpg->data_points[j].prefix,
prefix_dict[k].val[i]) == 0))
dtop_store_dp(&(dpg->data_points[j]),
dict[k].val[i]);
}
}
dt_free(&data);
free(line_len);
free(line_len2);
free(dict);
free(prefix_dict);
return DTOP_POLL_OK;
}
/**
* @brief Frees dynamically allocated dual_line_file dpgs.
*
* Frees the memory of the dpg along with it's data_points
* and other malloc'd memory no longer needed.
*
* @param dpg Dpg to deconstruct and deallocate memory for.
*/
static void dtop_dual_line_dpg_deconstructor
(struct dtop_data_point_gatherer *dpset)
{
int i;
free(dpset->data_points);
for (i = 0; i < ((struct dtop_dual_line_vars *)
(dpset->priv))->line_count; i++) {
free(((struct dtop_dual_line_vars *)(dpset->priv))->line[i]);
free(((struct dtop_dual_line_vars *)(dpset->priv))->line2[i]);
}
free(((struct dtop_dual_line_vars *)(dpset->priv))->line);
free(((struct dtop_dual_line_vars *)(dpset->priv))->line2);
free(((struct dtop_dual_line_vars *)(dpset->priv)));
free(dpset);
}
/**
* @brief Creates a dpg for a dual_line file.
*
* Dynamically allocates memory for dpg which is then added to a linked list
* via the dtop_register(dpg) function call.
*
* @param name Name of file dpg represents.
* @param data_points dtop_data_point struct that dpg points to.
* @param storage dtop_dual_line_vars struct that hold relevant dpg variables.
* @param dp_count Number of datapoints in dtop_data_point struct array.
*/
static void construct_dual_line_file_dpg(char *name, struct dtop_data_point
*data_points, struct dtop_dual_line_vars *storage, int dp_count)
{
struct dtop_data_point_gatherer *dpg = malloc
(sizeof(struct dtop_data_point_gatherer));
dpg->prefix = name;
dpg->file = name;
dpg->poll = dtop_dual_line_poll;
dpg->data_points = data_points;
dpg->priv = (struct dtop_dual_line_vars *)storage;
dpg->data_points_len = dp_count;
dpg->deconstruct = dtop_dual_line_dpg_deconstructor;
dtop_register(dpg);
}
/**
* @brief Scans a dual_line file for all datapoints and creats dps.
*
* Searches through a dual_line file (Key on one line with value on next line)
* for all available data points to create as dp structs.
*
* @param name Name of file.
* @param storage dtop_dual_line_vars struct where relevant variables are stored.
*/
int dtop_dual_line_search(char *name, struct dtop_dual_line_vars *storage)
{
int i, j, k, n, sum, sum2;
char *data;
int *line_len = malloc(sizeof(int) * storage->line_count);
int *line_len2 = malloc(sizeof(int) * storage->line_count);
int read;
struct dt_procdict *dict, *prefix_dict;
struct dtop_data_point *data_points;
int dp_count = 0;
storage->line = malloc(storage->line_count * sizeof(*storage->line));
storage->line2 = malloc(storage->line_count * sizeof(*storage->line2));
for (i = 0; i < storage->line_count; i++) {
storage->line[i] = malloc(sizeof(char) * DTOP_DUAL_LINE);
storage->line2[i] = malloc(sizeof(char) * DTOP_DUAL_LINE);
}
dict = malloc(sizeof(struct dt_procdict) * (storage->line_count/2));
prefix_dict = malloc(sizeof(struct dt_procdict)
* (storage->line_count/2));
read = dt_read_file(name, &data, DTOP_DUAL_SIZE);
if (read == 0 || data == 0)
return DTOP_POLL_IO_ERR;
sum = 0;
sum2 = 0;
/* Assigns each line read from the file, a length */
for (n = 0; n < storage->line_count; n++) {
line_len[n] = dt_read_line(storage->line[n],
DTOP_DUAL_LINE, data,
DTOP_DUAL_SIZE, sum);
line_len2[n] = dt_read_line(storage->line2[n],
DTOP_DUAL_LINE, data,
DTOP_DUAL_SIZE, sum2);
if (n <= (storage->line_count-2)) {
sum += (line_len[n] + 1);
sum2 += (line_len2[n] + 1);
}
}
/* Stores dp names and prefixes in dictionaries */
for (i = 0; i < (storage->line_count/2); i++)
dt_parse_proc_dictionary(storage->line[2*i], line_len[2*i],
storage->line[(2*i)+1], line_len[(2*i)+1], &dict[i]);
for (i = 0; i < (storage->line_count/2); i++)
dt_parse_for_prefix(storage->line2[2*i], line_len2[2*i],
&prefix_dict[i]);
/* Finds how many data points were gathered from the file */
for (j = 0; j < (storage->line_count/2); j++) {
for (i = 0; i < dict[j].max; i++)
dp_count++;
}
data_points = malloc(dp_count * sizeof(struct dtop_data_point));
k = 0;
/* Creates a dtop_data_point struct for each dp found in the file */
for (j = 0; j < (storage->line_count/2); j++)
for (i = 0; i < dict[j].max; i++) {
if (dict[j].val[i][0] == '-')
data_points[k].type = DTOP_LONG;
else
data_points[k].type = DTOP_ULONG;
data_points[k].name = dict[j].key[i];
data_points[k].prefix = prefix_dict[j].val[i];
data_points[k].skip = DO_NOT_SKIP;
data_points[k].initial_data_populated = NOT_POPULATED;
k++;
}
/* Calls dpg constructor, dpg will point to the dp struct */
construct_dual_line_file_dpg(name, data_points, storage, dp_count);
free(line_len);
free(line_len2);
free(dict);
free(prefix_dict);
dt_free(&data);
return DTOP_POLL_OK;
}
/**
* @brief Calls dtop_search for a file with dual line pairs.
*/
void dtop_dual_line_init(char *name)
{
struct dtop_dual_line_vars *storage = malloc
(sizeof(struct dtop_dual_line_vars));
storage->line_count = dtop_get_file_line_amount(name);
if (storage->line_count%2 != 0) {
printf("Dual line file, %s, contains error.\n", name);
printf("Data will not be collected from %s\n", name);
return;
}
dtop_dual_line_search(name, storage);
}

View File

@@ -0,0 +1,202 @@
/************************************************************************
Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
************************************************************************/
/**
* @file datatop_fileops.c
* @brief Declares functions for reading and writing to files.
*
* Declares functions called when reading from files which data is collected.
* Also contains methods to handle files which will be written to.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include "datatop_interface.h"
#include "datatop_linked_list.h"
#include "datatop_opt.h"
#include "datatop_fileops.h"
/**
* @brief Reads the lines from files which we are collecting data from.
*
* @param file File which is read from
* @param buffer Pointer to buffer where data will be read. The buffer is allocated
* in dt_read_file() and passed back to the caller. Caller should
* free this when done.
* @param len Maximum amount of data which should be read from the file.
* @return Number of bytes of data placed in *buffer.
*/
int dt_read_file(const char *file, char **buffer, int len)
{
int read;
FILE *fp;
*buffer = (char *)malloc(len);
if (!(*buffer)) {
fprintf(stderr, "%s(): malloc(%d) failed\n", __func__, len);
return 0;
}
fp = fopen(file, "r");
if (!fp) {
fprintf(stderr, "%s(): Failed to open %s: ", __func__, file);
fprintf(stderr, "Error: %s\n", strerror(errno));
free(*buffer);
*buffer = 0;
return 0;
}
read = fread(*buffer, sizeof(char), len, fp);
fclose(fp);
return read;
}
/**
* @brief Deallocates memory no longer being used.
*
* @param buffer Buffer to be deallocated.
*/
void dt_free(char **buffer)
{
free(*buffer);
*buffer = 0;
}
/**
* @brief Checks for access to a file for writing.
*
* @param fw File to check access of.
* @return INVALID - File already exists or write access denied.
* @return VALID - File does not exist and can be written to.
*/
int dtop_check_writefile_access(char *fw)
{
if (!access(fw, F_OK)) {
printf("File specified already exists\n");
return INVALID;
}
if (!access(fw, W_OK)) {
printf("Permission to write to specified file denied\n");
return INVALID;
}
return VALID;
}
/**
* @brief Checks for the presence of a dir.
*
* @param fw Dir to check the presence
* @return INVALID - Out dir doesn't exist.
* @return VALID - Out dir exist and can be written to.
*/
int dtop_check_out_dir_presence(char *fw)
{
if (access(fw, F_OK)) {
printf("Out dir not present\n");
return INVALID;
}
return VALID;
}
/**
* @brief Creates a directory
*
* @param New directory full path.
* @return INVALID - Out dir doesn't exist or write access denied.
* @return VALID - Out dir exist and can be written to.
*/
int dtop_create_dir(char *full_path)
{
if (!mkdir(full_path, 0755)) {
printf("Unable to create dir: %s, errno: %d\n", full_path, errno);
return INVALID;
}
return VALID;
}
/**
* @brief Opens file and handles possible errors.
*
* @param fw File path to be opened.
* @param to_file Pointer to the *file that is opened.
* @return VALID - File opened successfully.
* @return INVALID - File could not be opened.
*/
int dtop_open_writing_file(char *fw, FILE **to_file)
{
*to_file = fopen(fw, "w");
if (*to_file) {
return VALID;
} else {
fprintf(stderr, "Value of errno: %d\n", errno);
fprintf(stderr, "Error opening file: %s\n", strerror(errno));
fprintf(stderr, "Please try writing to a non-existent file\n");
printf("See datatop -h for help\n");
return INVALID;
}
}
/**
* @brief Closes a file if not a standard stream.
*
* @param fw File to be closed.
*/
void dtop_close_file(FILE *fw)
{
if (fw != stdout && fw != stderr && fw != stdin)
fclose(fw);
}
/**
* @brief Helper function to find number of lines in dual_line file.
*
* @return Number of lines in a dual_line file.
*/
int dtop_get_file_line_amount(char *name)
{
signed char rc = 0;
int line_count = 0;
FILE *file = fopen(name, "r");
while (rc != EOF) {
if (rc == '\n')
line_count++;
rc = fgetc(file);
}
fclose(file);
return line_count;
}

View File

@@ -0,0 +1,50 @@
/************************************************************************
Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
************************************************************************/
/**
* @file datatop_fileops.h
* @brief Declares functions held within datatop_fileops.h
*/
#ifndef DATATOP_FILEOPS_H
#define DATATOP_FILEOPS_H
#include "datatop_interface.h"
#include "datatop_linked_list.h"
#include "datatop_opt.h"
int dt_read_file(const char *file, char **buffer, int len);
void dt_free(char **buffer);
int dtop_check_writefile_access(char *fw);
int dtop_check_out_dir_presence(char *fw);
int dtop_create_dir(char *full_path);
int dtop_open_writing_file(char *fw, FILE **to_file);
void dtop_close_file(FILE *fw);
int dtop_get_file_line_amount(char *file);
#endif /* DATATOP_FILEOPS_H */

View File

@@ -0,0 +1,280 @@
/************************************************************************
Copyright (c) 2015, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
************************************************************************/
/**
* @file datatop_gen_poll.c
* @brief Contains functions which add ability to scan directories for data points.
*
* Contains functions that search through a directory and create dpg's for any
* important data values found which can then be polled for data collection.
*/
#include <unistd.h>
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "datatop_interface.h"
#include "datatop_fileops.h"
#include "datatop_str.h"
#include "datatop_gen_poll.h"
#define DTOP_GEN_SIZE 8192
#define DTOP_GEN_LINE (DTOP_GEN_SIZE>>2)
/**
* @brief Searches a file to find the number of data values it contains.
*
* @param dpg The struct which contains the file to search.
* @return Number of datapoints found in the file.
*/
static int get_number_of_values(struct dtop_data_point_gatherer *dpg)
{
char *data;
int read;
char line[DTOP_GEN_LINE];
int line_len;
int i, num;
read = dt_read_file(dpg->file, &data, DTOP_GEN_SIZE);
line_len = dt_read_line(line, DTOP_GEN_LINE, data, DTOP_GEN_SIZE, 0);
if (read == 0) {
return 0;
}
if (line_len < 1) {
dt_free(&data);
return 0;
}
num = 1;
for (i = 0; i < line_len; i++) {
if ((line[i] == ' ' || line[i] == ','
|| line[i] == ' ') &&line[i+1] != 0)
num++;
}
dt_free(&data);
return num;
}
/**
* @brief Stores the data collected from a dpg that was constructed during dtop_search.
*
* @param dpg Struct that polled data is added to.
* @return DTOP_POLL_IO_ERR - Poll of dpg unsuccessful.
* @return DTOP_POLL_OK - Poll of dpg successful.
*/
int dtop_gen_poll(struct dtop_data_point_gatherer *dpg)
{
char *data;
int read;
char line[DTOP_GEN_LINE];
int line_len;
struct dt_procdict dict;
int i;
read = dt_read_file(dpg->file, &data, DTOP_GEN_SIZE);
line_len = dt_read_line(line, DTOP_GEN_LINE, data, DTOP_GEN_SIZE, 0);
if (read == 0 || data == 0)
return DTOP_POLL_IO_ERR;
dt_single_line_parse(line, line_len, &dict);
for (i = 0; i < dpg->data_points_len; i++) {
if (dict.val[i][0] == '-')
dpg->data_points[i].type = DTOP_LONG;
dtop_store_dp(&(dpg->data_points[i]), dict.val[i]);
}
dt_free(&data);
return DTOP_POLL_OK;
}
/**
* @brief Frees dynamically allocated dpg's.
*
* Frees the memory of dpg variables and the dpg for all dynamically allocated
* dpgs.
*
* @param dpg Dpg to deconstruct and deallocate memory for.
*/
static void dtop_gen_dpg_deconstructor(struct dtop_data_point_gatherer *dpset)
{
int i;
for (i = 0; i < dpset->data_points_len; i++)
free(dpset->data_points[i].name);
free(dpset->data_points);
free(dpset->file);
free(dpset->prefix);
free(dpset);
}
/**
* @brief Creates a dpg and all necessary dp's corresponding to it.
*
* Dynamically allocates memory for dpg and dp structs which are then
* created and added to a linked_list of dpgs through the dtop_register
* function.
*
* @param dir Directory which file is located in, assigned to the dpg prefix.
* @param name Name of file that dpg represents, assigned to a dp name.
*/
static void dpg_construction(char *dir, char *name)
{
int num, i;
int both_len = strlen(dir) + strlen(name) + 1;
char *both = malloc(both_len);
char *maindir;
struct dtop_data_point_gatherer *dpg = malloc
(sizeof(struct dtop_data_point_gatherer));
strlcpy(both, dir, both_len);
strlcat(both, name, both_len);
maindir = malloc(strlen(dir) + 1);
strlcpy(maindir, dir, strlen(dir) + 1);
dpg->prefix = maindir;
dpg->file = both;
dpg->poll = dtop_gen_poll;
dpg->deconstruct = dtop_gen_dpg_deconstructor;
num = get_number_of_values(dpg);
if (num != 0) {
struct dtop_data_point *dp = malloc
(num * sizeof(struct dtop_data_point));
for (i = 0; i < num; i++) {
if (num == 1) {
dp[i].name = malloc(strlen(name) + 1);
strlcpy(dp[i].name, name, strlen(name) + 1);
} else {
char *add = malloc(7 * sizeof(char));
char *newname;
int nn_len, dpn_len;
snprintf(add, 7 * sizeof(char), "[%d]:", i);
nn_len = strlen(name) + strlen(add) + 1;
newname = malloc(nn_len);
strlcpy(newname, name, nn_len);
strlcat(newname, add, nn_len);
dpn_len = strlen(newname) + 1;
dp[i].name = malloc(dpn_len);
strlcpy(dp[i].name, newname, dpn_len);
free(add);
free(newname);
}
dp[i].prefix = NULL;
dp[i].type = DTOP_ULONG;
dp[i].skip = DO_NOT_SKIP;
dp[i].initial_data_populated = NOT_POPULATED;
}
dpg->data_points = dp;
dpg->data_points_len = num;
dtop_register(dpg);
} else {
free(dpg->prefix);
free(dpg->file);
free(dpg);
}
}
/**
* @brief Scans a directory for all important datapoints to be collected.
*
* Recursively scans a directory and locates all files which data will be
* collected from.
*
* @param dir Directory to search.
*/
static int dtop_search(char *dir)
{
DIR *dp;
struct dirent *entry;
struct stat s;
char cwd[1024];
if (!getcwd(cwd, sizeof(cwd))) {
fprintf(stderr, "Failed to get current working dir\n");
return -1;
}
dp = opendir(dir);
if (dp == NULL) {
fprintf(stderr, "err=%d: %s\n", errno, strerror(errno));
fprintf(stderr, "Cannot open directory: %s\n", dir);
return DIR_FAILURE;
}
chdir(dir);
while ((entry = readdir(dp))) {
if (stat(entry->d_name, &s)) {
printf("stat err=%d: %s\n", errno, strerror(errno));
return DIR_FAILURE;
}
if (strcmp(".", entry->d_name) != 0 &&
strcmp("..", entry->d_name) != 0 &&
S_ISREG(s.st_mode)) {
dpg_construction(dir, entry->d_name);
} else if (strcmp(".", entry->d_name) != 0 &&
strcmp("..", entry->d_name) != 0 &&
S_ISDIR(s.st_mode)) {
int nd_len = strlen(dir) + strlen(entry->d_name) + 2;
char *newdir = malloc(nd_len);
strlcpy(newdir, dir, nd_len);
strlcat(newdir, entry->d_name, nd_len);
strlcat(newdir, "/", nd_len);
dtop_search(newdir);
free(newdir);
}
}
closedir(dp);
chdir(cwd);
return DIR_SUCCESS;
}
/**
* @brief Calls dtop_search for any specified directory.
*
* @param dir Directory to search.
*/
void dtop_gen_init(char *dir)
{
dtop_search(dir);
}

View File

@@ -0,0 +1,43 @@
/************************************************************************
Copyright (c) 2015, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
************************************************************************/
/**
* @file datatop_gen_poll.h
* @brief Declares functions held within datatop_gen_poll.c
*/
#ifndef DATATOP_GEN_POLL_H
#define DATATOP_GEN_POLL_H
#define DIR_SUCCESS 0
#define DIR_FAILURE 1
void dtop_gen_init(char *dir);
#endif /* DATATOP_GEN_POLL_H */

View File

@@ -0,0 +1,478 @@
/************************************************************************
Copyright (c) 2015, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
************************************************************************/
/**
* @file datatop_helpers.c
* @brief Contains functions which output data.
*
* Contains functions which are used for printing data to output streams.
* Handles all formatting for data output. Also contains functions which
* are responsible for data gathering and collection.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
#include <sys/time.h>
#include <string.h>
#include <errno.h>
#include "datatop_interface.h"
#include "datatop_linked_list.h"
#include "datatop_fileops.h"
/**
* @brief Prints the name and prefix of a datapoint.
*
* @param dp Dp whose name and prefix is printed.
* @param prefix Directory where dp is contained.
* @param fw File to print the information to.
* @return FILE_ERROR - Writing to file was unsuccessful.
* @return FILE_SUCCESS - Writing to file was successful.
*/
static int dtop_format_dp_names(struct dtop_data_point *dp, const char
*prefix, FILE *fw)
{
if (dp->prefix) {
if (fprintf(fw, "\"%s:%s:%s\",", prefix, dp->prefix,
dp->name) < 0)
return FILE_ERROR;
} else {
if (fprintf(fw, "\"%s::%s\",", prefix, dp->name) < 0)
return FILE_ERROR;
}
return FILE_SUCCESS;
}
/**
* @brief Prints the value of a datapoint.
*
* Checks the type of the value and will print it accordingly.
*
* @param dp Pointer to the data_point struct which holds the value that will
* be printed.
* @param fw File to print the information to.
* @return FILE_ERROR - Writing to file was unsuccessful.
* @return FILE_SUCCESS - Writing to file was successful.
*/
static int dtop_format_dp_values(struct dtop_data_point *dp, FILE *fw)
{
switch (dp->type) {
case DTOP_ULONG:
if (fprintf(fw, "%"PRIu64, dp->data.d_ulong) < 0)
return FILE_ERROR;
break;
case DTOP_LONG:
if (fprintf(fw, "%"PRId64, dp->data.d_long) < 0)
return FILE_ERROR;
break;
case DTOP_UINT:
if (fprintf(fw, "%d", dp->data.d_uint) < 0)
return FILE_ERROR;
break;
case DTOP_INT:
if (fprintf(fw, "%u", dp->data.d_uint) < 0)
return FILE_ERROR;
break;
case DTOP_UCHAR:
if (fprintf(fw, "%c,", dp->data.d_uchar) < 0)
return FILE_ERROR;
if (fprintf(fw, "(0x%02X)", dp->data.d_uchar) < 0)
return FILE_ERROR;
break;
case DTOP_CHAR:
if (fprintf(fw, "%c,", dp->data.d_char) < 0)
return FILE_ERROR;
if (fprintf(fw, "(%d)", dp->data.d_char) < 0)
return FILE_ERROR;
break;
case DTOP_STR:
if (fprintf(fw, "\"%s\"", dp->data.d_str) < 0)
return FILE_ERROR;
break;
default:
if (fprintf(fw, "UNKNOWN_TYPE") < 0)
return FILE_ERROR;
break;
}
return FILE_SUCCESS;
}
/**
* @brief Prints the name and prefix of a dp, formatted appropriately.
*
* @param dpset data_point_gatherer used to access dp directory.
* @param dp data_point used to get datapoint prefix if available.
*/
static void dtop_format_text_for_snapshot
(struct dtop_data_point_gatherer *dpset, struct dtop_data_point dp)
{
printf("%s:", dpset->prefix);
if (dp.prefix)
printf("%s:", dp.prefix);
printf("%s::", dp.name);
}
/**
* @brief Prints a datapoint value to a specified csv file.
*
* @param dp Datapoint that holds the value to be printed.
* @param fw File to print to.
* @return FILE_ERROR - Writing to file was unsuccessful.
* @return FILE_SUCCESS - Writing to file was successful.
*/
static int dtop_print_dp_csv(struct dtop_data_point *dp, FILE *fw)
{
if (dtop_format_dp_values(dp, fw) == FILE_ERROR)
return FILE_ERROR;
if (fprintf(fw, ",") < 0)
return FILE_ERROR;
return FILE_SUCCESS;
}
/**
* @brief Prints a datapoint value to the terminal.
*
* @param dp Holds the value to be printed print.
* @param prefix Used to print prefix of the data_point.
*/
static void dtop_print_dp(struct dtop_data_point *dp, const char *prefix)
{
dtop_format_dp_names(dp, prefix, stdout);
printf(" ");
dtop_format_dp_values(dp, stdout);
printf("\n");
}
/**
* @brief Finds delta(value) of a datapoint.
*
* Function accounts for different types that values may be.
*
* @param dpset Pointer to a data_point used as another parameter for printing.
* @param dp Datapoint which contains the value to find the difference of.
*/
static void dtop_handle_dp_type_for_snapshot(
struct dtop_data_point_gatherer *dpset, struct dtop_data_point dp)
{
int64_t int64;
switch (dp.type) {
case DTOP_ULONG:
default:
/* This is less than ideal. Replace with 128-bit ops later */
int64 = (int64_t)dp.data.d_ulong
- (int64_t)dp.initial_data.d_ulong;
if (int64 != 0) {
dtop_format_text_for_snapshot(dpset, dp);
printf("%"PRId64"\n", int64);
}
break;
case DTOP_LONG:
/* This is less than ideal. Replace with 128-bit ops later */
int64 = (int64_t)dp.data.d_long
- (int64_t)dp.initial_data.d_long;
if (int64 != 0) {
dtop_format_text_for_snapshot(dpset, dp);
printf("%"PRId64"\n", int64);
}
break;
case DTOP_UINT:
int64 = (int64_t)dp.data.d_uint
- (int64_t)dp.initial_data.d_uint;
if (int64 != 0) {
dtop_format_text_for_snapshot(dpset, dp);
printf("%"PRId64"\n", int64);
}
break;
case DTOP_INT:
int64 = (int64_t)dp.data.d_int
- (int64_t)dp.initial_data.d_int;
if (int64 != 0) {
dtop_format_text_for_snapshot(dpset, dp);
printf("%"PRId64"\n", int64);
}
break;
}
}
/**
* @brief Calls the dtop_print_dp_csv function for each data_point a dpg has access to.
*
* @param dpg A data_point_gatherer struct that is iterated through for each datapoint.
* @param fw File to print datapoint values to.
* @return FILE_ERROR - Writing to file was unsuccessful.
* @return FILE_SUCCESS - Writing to file was successful.
*/
static int dtop_print_dpg_csv(struct dtop_data_point_gatherer *dpg, FILE *fw)
{
int i;
for (i = 0; i < dpg->data_points_len; i++)
if (dtop_print_dp_csv(&(dpg->data_points[i]), fw) == FILE_ERROR)
return FILE_ERROR;
return FILE_SUCCESS;
}
/**
* @brief Calls the dtop_format_dp_names function for each data_point a dpg has access to.
*
* @param dpg A data_point_gatherer struct that is iterated through for each datapoint.
* @param fw File to printg datapoint names and prefixes to.
* @return FILE_ERROR - Writing to file was unsuccessful.
* @return FILE_SUCCESS - Writing to file was successful.
*/
int dtop_print_dpg_names_csv(struct dtop_data_point_gatherer *dpg, FILE *fw)
{
int i;
for (i = 0; i < dpg->data_points_len; i++)
if (dtop_format_dp_names(&(dpg->data_points[i]),
dpg->prefix, fw) == FILE_ERROR)
return FILE_ERROR;
return FILE_SUCCESS;
}
/**
* @brief Prints all dp values to a specified file.
*
* This function is responsible for the printing of all data_point values
* to a specified file. It will iterate through the linked list which contains
* all of the dpgs and will print each dp value, being sure to flush the buffer.
*
* @param dpg_list Pointer to first node of linked list which contains all dpgs.
* @param fw File that data prints to.
* @return FILE_ERROR - Writing to file was unsuccessful.
* @return FILE_SUCCESS - Writing to file was successful.
*/
int dtop_write_pollingdata_csv(struct dtop_linked_list *dpg_list, FILE *fw)
{
struct dtop_linked_list *curr_ptr = dpg_list;
struct dtop_data_point_gatherer *dpset;
while (curr_ptr) {
dpset = (struct dtop_data_point_gatherer *) curr_ptr->data;
if (dtop_print_dpg_csv(dpset, fw) == FILE_ERROR)
return FILE_ERROR;
curr_ptr = curr_ptr->next_ptr;
fflush(fw);
}
if (fprintf(fw, "\n") < 0)
return FILE_ERROR;
return FILE_SUCCESS;
}
/**
* @brief Calls the dtop_print_dp function for each data_point a dpg has access to.
*
* @param dpg A data_point_gatherer struct that is iterated through for each datapoint.
*/
void dtop_print_dpg(struct dtop_data_point_gatherer *dpg)
{
int i;
for (i = 0; i < dpg->data_points_len; i++)
dtop_print_dp(&(dpg->data_points[i]), dpg->prefix);
}
/**
* @brief Stores the values for the datapoints and populates the initial value.
*
* @param dp A datapoint whose value will be stored.
* @param str Str used for sscanf function call to find value of dp.
*/
void dtop_store_dp(struct dtop_data_point *dp, const char *str)
{
switch (dp->type) {
case DTOP_ULONG:
sscanf(str, "%"PRIu64, &(dp->data.d_ulong));
if (dp->initial_data_populated == NOT_POPULATED) {
dp->initial_data.d_ulong = dp->data.d_ulong;
dp->initial_data_populated = POPULATED;
}
break;
case DTOP_LONG:
sscanf(str, "%"PRId64, &(dp->data.d_long));
if (dp->initial_data_populated == NOT_POPULATED) {
dp->initial_data.d_long = dp->data.d_long;
dp->initial_data_populated = POPULATED;
}
break;
case DTOP_UINT:
sscanf(str, "%u", &(dp->data.d_uint));
if (dp->initial_data_populated == NOT_POPULATED) {
dp->initial_data.d_uint = dp->data.d_uint;
dp->initial_data_populated = POPULATED;
}
break;
case DTOP_INT:
sscanf(str, "%d", &(dp->data.d_int));
if (dp->initial_data_populated == NOT_POPULATED) {
dp->initial_data.d_int = dp->data.d_int;
dp->initial_data_populated = POPULATED;
}
break;
case DTOP_UCHAR:
sscanf(str, "%c", &(dp->data.d_uchar));
if (dp->initial_data_populated == NOT_POPULATED) {
dp->initial_data.d_uchar = dp->data.d_uchar;
dp->initial_data_populated = POPULATED;
}
break;
case DTOP_CHAR:
sscanf(str, "%c", &(dp->data.d_char));
if (dp->initial_data_populated == NOT_POPULATED) {
dp->initial_data.d_char = dp->data.d_char;
dp->initial_data_populated = POPULATED;
}
break;
case DTOP_STR:
sscanf(str, "%s", dp->data.d_str);
if (dp->initial_data_populated == NOT_POPULATED) {
memcpy(dp->initial_data.d_str, dp->data.d_str,
DTOP_DP_MAX_STR_LEN);
dp->initial_data_populated = POPULATED;
}
break;
default:
break;
}
}
/**
* @brief Responsible for calculating and printing current time to file.
*
* Prints the time since 1970, in Seconds and Milliseconds.
*
* @param fw File that time is printed to.
* @return FILE_ERROR - Writing to file was unsuccessful.
* @return FILE_SUCCESS - Writing to file was successful.
*/
int dtop_print_time_at_poll(FILE *fw)
{
struct timeval tv;
gettimeofday(&tv, NULL);
if (fprintf(fw, "%10ld", tv.tv_sec) < 0)
return FILE_ERROR;
if (fprintf(fw, ".%06ld,", tv.tv_usec) < 0)
return FILE_ERROR;
return FILE_SUCCESS;
}
/**
* @brief Polls all dp values and updates each value.
*
* @param dpg_list Pointer to first node of linked list which contains all dpgs.
*/
void dtop_poll(struct dtop_linked_list *dpg_list)
{
struct dtop_linked_list *curr_ptr = dpg_list;
struct dtop_data_point_gatherer *dpset;
while (curr_ptr) {
dpset = (struct dtop_data_point_gatherer *) curr_ptr->data;
dpset->poll(dpset);
curr_ptr = curr_ptr->next_ptr;
}
}
/**
* @brief Prints the delta(value) of all data_points to terminal.
*
* @param dpg_list Pointer to first node of linked list which contains all dpgs.
*/
void dtop_print_snapshot_diff(struct dtop_linked_list *dpg_list)
{
int i;
struct dtop_linked_list *curr_ptr = dpg_list;
struct dtop_data_point_gatherer *dpset;
printf("\n");
printf("Change In Datapoint Values\n");
printf("---------------------------\n");
while (curr_ptr) {
dpset = (struct dtop_data_point_gatherer *) curr_ptr->data;
for (i = 0; i < dpset->data_points_len; i++)
dtop_handle_dp_type_for_snapshot(dpset,
dpset->data_points[i]);
curr_ptr = curr_ptr->next_ptr;
}
printf("\n");
}
/**
* @brief Resets the initial values of all data_points.
*
* @param dpg_list Pointer to first node of linked list which contains all dpgs.
*/
void dtop_reset_dp_initial_values(struct dtop_linked_list *dpg_list)
{
int i;
struct dtop_linked_list *curr_ptr = dpg_list;
struct dtop_data_point_gatherer *dpset;
while (curr_ptr) {
dpset = (struct dtop_data_point_gatherer *) curr_ptr->data;
for (i = 0; i < dpset->data_points_len; i++)
dpset->data_points[i].initial_data_populated
= NOT_POPULATED;
curr_ptr = curr_ptr->next_ptr;
}
}
/**
* @brief Calls deconstructor method for all dpgs dynamically created.
*
* Checks to see if each dpg created has a deconstructor method. If not null,
* function calls the appropiate deconstructor method to deallocate memory.
*
* @param dpg_list Pointer to first node of linked list which contains all dpgs.
*/
void deconstruct_dpgs(struct dtop_linked_list *dpg_list)
{
struct dtop_linked_list *curr_ptr = dpg_list;
struct dtop_data_point_gatherer *dpset;
while (curr_ptr) {
dpset = (struct dtop_data_point_gatherer *) curr_ptr->data;
if (dpset->deconstruct)
dpset->deconstruct(dpset);
curr_ptr = curr_ptr->next_ptr;
}
}

View File

@@ -0,0 +1,166 @@
/************************************************************************
Copyright (c) 2015, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
************************************************************************/
/**
* @file datatop_interface.h
* @brief Declares functions held within datatop.c and datatop_helpers.c
*
* Declares functions which are held within datatop.c and datatop_helpers.c.
* Also defines data structures used for storing data gathered during polling
* such as datapoint names, values, and prefixes along with other valuable
* information.
*/
#ifndef DATATOP_INTERFACE_H
#define DATATOP_INTERFACE_H
#include <inttypes.h>
#include "datatop_linked_list.h"
#define DTOP_ULONG 0
#define DTOP_LONG 1
#define DTOP_UINT 2
#define DTOP_INT 3
#define DTOP_UCHAR 4
#define DTOP_CHAR 5
#define DTOP_STR 6
#define FILE_ERROR -1
#define FILE_SUCCESS 0
#define SKIP 1
#define DO_NOT_SKIP 0
#define POPULATED 1
#define NOT_POPULATED 0
#define DTOP_POLL_OK 0
#define DTOP_POLL_IO_ERR 1
#define NOT_CHECKED 0
#define QUIT 1
#define DTOP_DP_MAX_STR_LEN 32
#define DTOP_DP_HFILL .initial_data_populated = NOT_POPULATED, \
.skip = 0
/**
* @struct dtop_data_union
* @brief Provides the type for dp value.
*/
union dtop_data_union {
uint64_t d_ulong;
int64_t d_long;
uint32_t d_uint;
int32_t d_int;
uint8_t d_uchar;
int8_t d_char;
char d_str[DTOP_DP_MAX_STR_LEN];
};
/**
* @struct dtop_data_point
* @brief Individual datapoint in a file.
*
* @var dtop_data_point::name
* Stores the datapoints name.
* @var dtop_data_point::prefix
* Stores the individual prefix for the dp.
* @var dtop_data_point::type
* Type dp value is, see definitions.
* @var dtop_data_point::initial_data
* Holds the initial value of the dp the first time it was polled.
* @var dtop_data_point::initial_data_populated
* Variable that is changed when initial_data is populated.
* @var dtop_data_point::data
* Value of the dp at the most recent poll.
*/
struct dtop_data_point {
char *name;
char *prefix;
/* Results of polling */
char type;
union dtop_data_union initial_data;
char initial_data_populated;
union dtop_data_union data;
/* Skip on subsequent polls */
char skip;
};
/**
* @struct dtop_data_point_gatherer
* @brief Struct used to hold data about a set of collected data.
*
* @var dtop_data_point_gatherer::prefix
* Name of directory which data is collected from.
* @var dtop_data_point_gatherer::file
* File path that data is collected from.
* @var dtop_data_point_gatherer::poll
* Poll function takes a dtop_data_point_gatherer as parameter.
* int equals, DTOP_POLL_IO_ERR - Poll of dpg unsuccessful, or
* DTOP_POLL_OK - Poll of dpg successful.
* @var dtop_data_point_gatherer::data_points
* Pointer to a dtop_data_point struct (dp).
* @var dtop_data_point_gatherer::data_points_len
* Number of elements in the array of dp's the dpg accesses.
*/
struct dtop_data_point_gatherer {
char *prefix;
char *file;
int (*poll)(struct dtop_data_point_gatherer *dpg);
void (*deconstruct)(struct dtop_data_point_gatherer *dpg);
struct dtop_data_point *data_points;
int data_points_len;
/* Private data */
void *priv;
};
void dtop_register(struct dtop_data_point_gatherer *dpg);
void dtop_store_dp(struct dtop_data_point *dp, const char *str);
void dtop_print_dpg(struct dtop_data_point_gatherer *dpg);
void get_snapshot_diff(struct dtop_linked_list *dpg_list);
void dtop_print_snapshot_diff(struct dtop_linked_list *dpg_list);
void dtop_poll(struct dtop_linked_list *dpg_list);
int dtop_print_time_at_poll(FILE *fw);
int dtop_print_dpg_names_csv(struct dtop_data_point_gatherer *dpg, FILE *fw);
int dtop_write_pollingdata_csv(struct dtop_linked_list *dpg_list, FILE *fw);
void dtop_reset_dp_initial_values(struct dtop_linked_list *dpg_list);
void deconstruct_dpgs(struct dtop_linked_list *dpg_list);
int dtop_print_system_snapshot(char *file);
#ifndef HAVE_STRL_FUNCTIONS
#define strlcpy(X,Y,Z) strcpy(X,Y)
#define strlcat(X,Y,Z) strcat(X,Y)
#endif /* HAVE_STRL_FUNCTIONS */
#endif /* DATATOP_INTERFACE_H */

View File

@@ -0,0 +1,344 @@
/************************************************************************
Copyright (c) 2016, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
************************************************************************/
/**
* @file datatop_ip_table_poll.c
* @brief Adds ability for TP Tables, Rules and Routes data collection
Unlike other polls, this is intended for running as a separate
thread as it can cause delays of > 3sec per poll
*
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <pthread.h>
#include "datatop_interface.h"
#include "datatop_fileops.h"
#include "datatop_str.h"
#include "datatop_polling.h"
#define DTOP_IPTRR_POLL_PERIOD 5.00
/**
* @struct dtop_ip_table_vars
* @brief Struct used to hold necessary variables for /proc/stat dpg
*
* @var dtop_ip_table_vars::line
* Array of strings where necessary dp names and values are held.
* @var dtop_ip_table_vars::line_count
* Number of lines the file is that the dpg represents.
*/
struct dtop_ip_table_vars {
char *out_dir;
}dtop_ip_table_storage;
struct dtop_linked_list *ip_dpg_list = NULL;
pthread_mutex_t dtop_ip_table_lock;
/**
* @brief Perform IP table command and store it in a file
*
* @param dpg Struct that polled data is added to.
* @return DTOP_POLL_IO_ERR - Poll of dpg unsuccessful.
* @return DTOP_POLL_OK - Poll of dpg successful.
*/
int dtop_ip_table_poll(struct dtop_data_point_gatherer *dpg)
{
FILE *fd;
FILE *fo = (FILE *)dpg->file;
char buf[1001];
time_t rawtime;
struct tm * timeinfo;
if(fo == NULL)
{
fprintf(stderr, "Could not fopen: %s\n", dpg->file);
return DTOP_POLL_IO_ERR;
}
time ( &rawtime );
timeinfo = gmtime ( &rawtime );
fprintf ( fo, "============\nStart: %s==========\n", asctime (timeinfo) );
fflush(fo);
/* redirect stderr to output file */
dup2(fileno(fo), 2);
fd = popen((char *)dpg->priv, "r");
if(fd == NULL)
{
fprintf(stderr, "Could not popen: %s\n", (char *)dpg->priv);
return DTOP_POLL_IO_ERR;
}
while(fgets(buf, 1000, fd) != NULL)
{
fputs(buf, fo);
}
fprintf ( fo, "============\nEnd: %s==========\n\n", asctime (timeinfo) );
fflush(fo);
pclose(fd);
return DTOP_POLL_OK;
}
/**
* @brief Frees dynamically allocated IP table dpg.
*
* Frees the memory of the dpg along with it's data_points
* and other malloc'd memory no longer needed.
*
* @param dpg Dpg to deconstruct and deallocate memory for.
*/
static void dtop_ip_table_dpg_deconstructor
(struct dtop_data_point_gatherer *dpset)
{
free(dpset->prefix);
if(dpset->file)
{
fclose((FILE *)dpset->file);
}
free(dpset);
}
/**
* @brief Registers a new IP table dpg to the list.
*
* @param dpg Dpg to construct and allocate memory for.
*/
void dtop_ip_table_register(struct dtop_data_point_gatherer *dpg)
{
if (dpg)
ip_dpg_list = dtop_add_linked_list(dpg, ip_dpg_list);
}
/**
* @brief Open the files for writing the output for each dpg.
*
* @param None
*/
int dtop_ip_table_init_files()
{
struct dtop_data_point_gatherer *dpset;
struct dtop_linked_list *curr_ptr = ip_dpg_list;
FILE *fd;
while(curr_ptr)
{
dpset = (struct dtop_data_point_gatherer *) curr_ptr->data;
fd = fopen(dpset->prefix, "a+");
if(!fd)
{
fprintf(stderr, "Could not fopen: %s\n", dpset->prefix);
return DTOP_POLL_IO_ERR;
}
dpset->file = (char *)fd;
curr_ptr = curr_ptr->next_ptr;
}
return DTOP_POLL_OK;
}
/**
* @brief Perform cleanup of IP table dgp list at exit.
*
* @param None
*/
void dtop_ip_table_poll_cleanup()
{
pthread_mutex_lock(&dtop_ip_table_lock);
deconstruct_dpgs(ip_dpg_list);
dtop_rem_linked_list(ip_dpg_list);
pthread_mutex_unlock(&dtop_ip_table_lock);
}
/**
* @brief The thread to poll for IP table data.
*
* @param arg ptr
*/
void *dtop_ip_table_start_poll(void *arg)
{
time_t start_t, curr_t;
double diff_t = 9999999.00; /* some high # > DTOP_IPTRR_POLL_PERIOD */
int ret = DTOP_POLL_OK;
(void) arg;
if (pthread_mutex_init(&dtop_ip_table_lock, NULL) != 0)
{
printf("\n mutex init failed\n");
return NULL;
}
atexit(dtop_ip_table_poll_cleanup);
if(DTOP_POLL_OK != ( ret = dtop_ip_table_init_files()))
{
return NULL;
}
while(1)
{
struct dtop_linked_list *curr_ptr = ip_dpg_list;
struct dtop_data_point_gatherer *dpset;
pthread_mutex_lock(&dtop_ip_table_lock);
if (diff_t >= DTOP_IPTRR_POLL_PERIOD)
{
printf("Poll for IP Tables, Rules & Routes\n");
time(&start_t);
while (curr_ptr)
{
dpset = (struct dtop_data_point_gatherer *) curr_ptr->data;
dpset->poll(dpset);
curr_ptr = curr_ptr->next_ptr;
}
}
pthread_mutex_unlock(&dtop_ip_table_lock);
/* sleep for 500 milliseconds */
usleep(500 * 1000);
time(&curr_t);
diff_t = difftime(curr_t, start_t);
}
return NULL;
}
/**
* @brief Creates a dpg for ip table command
*
* Dynamically allocates memory for dpg which is then added to a linked list
* via the dtop_register(dpg) function call.
*
* @param data_points dtop_data_point struct that dpg points to.
* @param storage dtop_ip_table_vars struct that holds relevant dpg variables.
*/
/*static void construct_ip_table_dpg(struct dtop_data_point
*data_points, struct dtop_ip_table_vars *command, int dp_count)
*/
static void construct_ip_table_dpg(char *command)
{
struct dtop_data_point_gatherer *dpg = malloc
(sizeof(struct dtop_data_point_gatherer));
char *file_name = (char *)malloc(strlen(command)+ 1 + 1 + strlen(dtop_ip_table_storage.out_dir) + 4);
int i, fname_start_ind;
strcpy(file_name, dtop_ip_table_storage.out_dir);
strcat(file_name, "/");
fname_start_ind = strlen(file_name);
strcat(file_name, command);
strcat(file_name, ".txt");
for(i=fname_start_ind; file_name[i]; i++)
{
if(file_name[i] == ' ')
file_name[i] = '_';
if(file_name[i] == '/')
file_name[i] = '-';
}
dpg->prefix = file_name;
dpg->poll = dtop_ip_table_poll;
dpg->priv = (char *)command;
dpg->file = NULL;
dpg->deconstruct = dtop_ip_table_dpg_deconstructor;
dtop_ip_table_register(dpg);
}
/*
* @brief Scans "/proc/stat" in order to autodetect dps.
*
* Searches through "/proc/stat" file for all available data
* points to create as dp structs.
*
* @param storage dtop_ip_table_vars struct where relevant variables are stored.
*/
/**
* @brief Calls dtop_search for "/proc/stat" file.
*/
void dtop_ip_table_init(char *out_dir)
{
dtop_ip_table_storage.out_dir = out_dir;
construct_ip_table_dpg("ip xfrm state show");
construct_ip_table_dpg("ip xfrm policy show");
construct_ip_table_dpg("ip addr");
construct_ip_table_dpg("iptables -t raw -L -n -v");
construct_ip_table_dpg("iptables -t mangle -L -n -v");
construct_ip_table_dpg("iptables -L -n -v");
construct_ip_table_dpg("iptables -t nat -L -n -v");
construct_ip_table_dpg("ip6tables -t raw -L -n -v");
construct_ip_table_dpg("ip6tables -t mangle -L -n -v");
construct_ip_table_dpg("ip6tables -L -n -v");
construct_ip_table_dpg("ip6tables -t nat -L -n -v");
construct_ip_table_dpg("ip rule show");
construct_ip_table_dpg("ip -6 rule show");
construct_ip_table_dpg("ip route show table all");
construct_ip_table_dpg("ip -6 route show table all");
construct_ip_table_dpg("ip route show table rmnet_data0");
construct_ip_table_dpg("ip route show table rmnet_data1");
construct_ip_table_dpg("ip route show table rmnet_data2");
construct_ip_table_dpg("ip route show table rmnet_data6");
construct_ip_table_dpg("ip route show table rmnet_data7");
construct_ip_table_dpg("ip route show table r_rmnet_data0");
construct_ip_table_dpg("ip route show table r_rmnet_data1");
construct_ip_table_dpg("ip route show table r_rmnet_data2");
construct_ip_table_dpg("ip route show table r_rmnet_data6");
construct_ip_table_dpg("ip route show table r_rmnet_data7");
construct_ip_table_dpg("ip -6 route show table rmnet_data0");
construct_ip_table_dpg("ip -6 route show table rmnet_data1");
construct_ip_table_dpg("ip -6 route show table rmnet_data2");
construct_ip_table_dpg("ip -6 route show table rmnet_data6");
construct_ip_table_dpg("ip -6 route show table rmnet_data7");
construct_ip_table_dpg("ip -6 route show table r_rmnet_data0");
construct_ip_table_dpg("ip -6 route show table r_rmnet_data1");
construct_ip_table_dpg("ip -6 route show table r_rmnet_data2");
construct_ip_table_dpg("ip -6 route show table r_rmnet_data6");
construct_ip_table_dpg("ip -6 route show table r_rmnet_data7");
construct_ip_table_dpg("ip route show table wlan0");
construct_ip_table_dpg("ip -6 route show table wlan0");
construct_ip_table_dpg("ip route show table dummy0");
construct_ip_table_dpg("ip -6 route show table dummy0");
construct_ip_table_dpg("cat /proc/net/xfrm_stat");
construct_ip_table_dpg("cat /proc/sys/net/ipv4/ip_forward");
construct_ip_table_dpg("cat /proc/sys/net/ipv6/conf/all/forwarding");
printf("Poll for IP Tables, Rules & Routes every 5 seconds\n");
}

View File

@@ -0,0 +1,84 @@
/************************************************************************
Copyright (c) 2015, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
************************************************************************/
/**
* @file datatop_linked_list.c
* @brief Necessary linked_list functions created.
*
* Holds function which adds to or creates a linked list
* used for storing dtop_data_point_gatherer's (dpg's).
* Datapoints are stored in linked list for ability to
* iteratively poll and print efficiently. Handles creation
* and deletion of memory for linked list nodes.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "datatop_linked_list.h"
/**
* @brief Adds a node to the beginning of a linked list.
*
* @param data A void pointer which can hold any data in the node.
* @param list The list that is added to.
* @return Updated linked list struct.
*/
struct dtop_linked_list *dtop_add_linked_list(void *data,
struct dtop_linked_list *list)
{
struct dtop_linked_list *list_node;
list_node = malloc(sizeof(struct dtop_linked_list));
if (!list_node) {
fprintf(stderr, "failed to allocate memory.\n");
exit(EXIT_FAILURE);
}
list_node->data = data;
list_node->next_ptr = list;
list = list_node;
return list;
}
/**
* @brief Deletes a linked list.
*
* @param head_ptr Pointer to the first node in the linked list that is to be deleted.
*/
void dtop_rem_linked_list(struct dtop_linked_list *head_ptr)
{
struct dtop_linked_list *tmp_ptr = NULL;
while (head_ptr) {
tmp_ptr = head_ptr;
head_ptr = head_ptr->next_ptr;
free(tmp_ptr);
}
}

View File

@@ -0,0 +1,59 @@
/************************************************************************
Copyright (c) 2015, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
************************************************************************/
/**
* @file datatop_linked_list.h
* @brief Defines linked list struct and declares linked list methods.
*
* Defines linked list struct which can be used for any data
* storage. Declares methods held within datatop_linked_list.c.
*/
#ifndef DATATOP_LINKED_LIST_H
#define DATATOP_LINKED_LIST_H
/**
* @struct dtop_linked_list
* @brief Struct used to represent linked list node that stores a pointer with any type.
*
* @var dtop_linked_list::next_ptr
* Pointer to next node in the list.
* @var dtop_linked_list::data
* Pointer to data the node stores.
*/
struct dtop_linked_list {
struct dtop_linked_list *next_ptr;
void *data;
};
struct dtop_linked_list *dtop_add_linked_list(void *data,
struct dtop_linked_list *list);
void dtop_rem_linked_list(struct dtop_linked_list *head_ptr);
#endif /* DATATOP_LINKED_LIST_H */

View File

@@ -0,0 +1,282 @@
/************************************************************************
Copyright (c) 2015, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
************************************************************************/
/**
* @file datatop_meminfo_file_poll.c
* @brief Adds ability for data collection from /proc/meminfo
*
* File contains methods for searching and polling data from
* "/proc/meminfo"
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include "datatop_interface.h"
#include "datatop_fileops.h"
#include "datatop_str.h"
#define DTOP_MEM_SIZE 8192
#define DTOP_MEM_LINE (DTOP_MEM_SIZE>>2)
/**
* @struct dtop_meminfo_vars
* @brief Struct used to hold necessary variables for /proc/meminfo dpg
*
* @var dtop_meminfo_vars::line
* Array of strings where necessary dp names and values are held.
* @var dtop_meminfo_vars::line_count
* Number of lines the file is that the dpg represents.
*/
struct dtop_meminfo_vars {
char **line;
int line_count;
};
/**
* @brief Parses lines with data in "/proc/meminfo"
*
* @param line1 Line to parse to find datapoint names and values.
* @param len1 Length of line1.
* @param l Index in the dictionary the key/value pair is added to.
* @param dict Dictionary the keys and values are added to.
*/
int dt_meminfo_parse(char *line1, int len1,
int l, struct dt_procdict *dict)
{
int i, k, n;
if (len1 < 1)
return 0;
if (line1 == 0 || dict == 0)
return 0;
k = l;
dict->key[k] = &line1[0];
for (i = 0; i < len1 && k < DTOP_DICT_SIZE; i++) {
if (line1[i] == ' ' || line1[i] == ' ') {
line1[i] = 0;
n = i+1;
while (line1[n] == ' ' || line1[n] == ' ')
n++;
dict->val[k] = &line1[n];
while (line1[n] != ' ')
n++;
line1[n] = 0;
break;
}
}
k++;
dict->max = k;
return k;
}
/**
* @brief Stores the data collected from a "/proc/meminfo"
*
* @param dpg Struct that polled data is added to.
* @return DTOP_POLL_IO_ERR - Poll of dpg unsuccessful.
* @return DTOP_POLL_OK - Poll of dpg successful.
*/
int dtop_meminfo_poll(struct dtop_data_point_gatherer *dpg)
{
char *data;
int *line_len = malloc(sizeof(int) *
((struct dtop_meminfo_vars *)
(dpg->priv))->line_count);
int read;
struct dt_procdict dict;
int i, j, n, sum;
read = dt_read_file(dpg->file, &data, DTOP_MEM_SIZE);
if (read == 0 || data == 0)
return DTOP_POLL_IO_ERR;
sum = 0;
/* Assigns each line read from the file, a length */
for (n = 0; n < ((struct dtop_meminfo_vars *)
(dpg->priv))->line_count; n++) {
line_len[n] = dt_read_line(((struct dtop_meminfo_vars *)
(dpg->priv))->line[n],
DTOP_MEM_LINE, data,
DTOP_MEM_SIZE, sum);
if (n <= (((struct dtop_meminfo_vars *)
(dpg->priv))->line_count - 1)) {
sum += (line_len[n] + 1);
}
}
/* Stores dp names and values in dictionary */
for (i = 0; i < dpg->data_points_len; i++)
dt_meminfo_parse(((struct dtop_meminfo_vars *)
(dpg->priv))->line[i], line_len[i], i, &dict);
/* Assigns the dp value to the dp struct */
for (j = 0; j < dpg->data_points_len; j++) {
i = dt_find_dict_idx(dpg->data_points[j].name, &dict);
if (i >= 0 && i < dict.max) {
sscanf(dict.val[i], "%" PRIu64,
&(dpg->data_points[i].data.d_ulong));
dpg->data_points[i].data.d_ulong *= 1024;
if (dpg->data_points[i].
initial_data_populated == NOT_POPULATED) {
dpg->data_points[i].initial_data.d_ulong
= dpg->data_points[i].data.d_ulong;
dpg->data_points[i].initial_data_populated
= POPULATED;
}
}
}
dt_free(&data);
free(line_len);
return DTOP_POLL_OK;
}
/**
* @brief Frees dynamically allocated "/proc/meminfo" dpg.
*
* Frees the memory of the dpg along with it's data_points
* and other malloc'd memory no longer needed.
*
* @param dpg Dpg to deconstruct and deallocate memory for.
*/
static void dtop_meminfo_dpg_deconstructor
(struct dtop_data_point_gatherer *dpset)
{
int i;
free(dpset->data_points);
for (i = 0; i < ((struct dtop_meminfo_vars *)
(dpset->priv))->line_count; i++)
free(((struct dtop_meminfo_vars *)(dpset->priv))->line[i]);
free(((struct dtop_meminfo_vars *)(dpset->priv))->line);
free(((struct dtop_meminfo_vars *)(dpset->priv)));
free(dpset);
}
/**
* @brief Creates a dpg for "/proc/meminfo" file
*
* Dynamically allocates memory for dpg which is then added to a linked list
* via the dtop_register(dpg) function call.
*
* @param data_points dtop_data_point struct that dpg points to.
* @param storage dtop_meminfo_vars struct that holds relevant dpg variables.
*/
static void construct_meminfo_file_dpg(struct dtop_data_point
*data_points, struct dtop_meminfo_vars *storage)
{
struct dtop_data_point_gatherer *dpg = malloc
(sizeof(struct dtop_data_point_gatherer));
dpg->prefix = "/proc/meminfo";
dpg->file = "/proc/meminfo";
dpg->poll = dtop_meminfo_poll;
dpg->data_points = data_points;
dpg->priv = (struct dtop_meminfo_vars *)storage;
dpg->data_points_len = storage->line_count;
dpg->deconstruct = dtop_meminfo_dpg_deconstructor;
dtop_register(dpg);
}
/**
* @brief Scans "/proc/meminfo in order to autodetect dps.
*
* Searches through "/proc/meminfo" file for all available data
* points to create as dp structs.
*
* @param storage dtop_meminfo_vars struct where relevant variables are stored.
*/
int dtop_meminfo_search(struct dtop_meminfo_vars *storage)
{
int i, k, n, sum;
char *data;
int *line_len = malloc(sizeof(int) * storage->line_count);
int read;
struct dt_procdict dict;
struct dtop_data_point *data_points;
storage->line = malloc(storage->line_count * sizeof(*storage->line));
for (i = 0; i < storage->line_count; i++)
storage->line[i] = malloc(sizeof(char) * DTOP_MEM_LINE);
read = dt_read_file("/proc/meminfo", &data, DTOP_MEM_SIZE);
if (read == 0 || data == 0)
return DTOP_POLL_IO_ERR;
sum = 0;
/* Assigns each line read from the file, a length */
for (n = 0; n < storage->line_count; n++) {
line_len[n] = dt_read_line(storage->line[n],
DTOP_MEM_LINE, data,
DTOP_MEM_SIZE, sum);
if (n < (storage->line_count - 1))
sum += (line_len[n] + 1);
}
/* Stores dp names in dictionary */
for (i = 0; i < (storage->line_count); i++)
dt_parse_proc_same_line_key_and_val(storage->line[i],
line_len[i], i, &dict);
data_points = malloc
(storage->line_count * sizeof(struct dtop_data_point));
k = 0;
/* Creates a dtop_data_point struct for each dp found in the file */
for (i = 0; i < dict.max; i++) {
data_points[i].name = dict.key[i];
data_points[i].prefix = NULL;
data_points[i].type = DTOP_ULONG;
k++;
}
/* Calls dpg constructor, dpg will point to the dp struct */
construct_meminfo_file_dpg(data_points, storage);
free(line_len);
dt_free(&data);
return DTOP_POLL_OK;
}
/**
* @brief Calls dtop_search for "/proc/meminfo" file.
*/
void dtop_meminfo_init(void)
{
struct dtop_meminfo_vars *storage = malloc
(sizeof(struct dtop_meminfo_vars));
storage->line_count = dtop_get_file_line_amount("/proc/meminfo");
dtop_meminfo_search(storage);
}

View File

@@ -0,0 +1,215 @@
/************************************************************************
Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
************************************************************************/
/**
* @file datatop_opt.c
* @brief Adds getopt functionality for CLI commands.
*
* Contains method for getopt functionality used for parsing
* the CLI arguments into executable commands. Handles
* errors which arise when parsing.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <getopt.h>
#include <time.h>
#include "datatop_opt.h"
#include "datatop_interface.h"
#include "datatop_linked_list.h"
#include "datatop_fileops.h"
/**
* @brief Populate the comand line options with sane defaults
*
* @param clopts Struct used to hold data regarding CLI arguments.
*/
void dtop_load_default_options(struct cli_opts *clopts)
{
memset(clopts, 0, sizeof(struct cli_opts));
clopts->priority = DEFAULT_NICE;
}
/**
* @brief Parses all CLI commands for main() to execute.
*
* @param clopts Struct used to hold data regarding CLI arguments.
* @param argc Parameter used to read CLI commands from.
* @param argv Parameter used to read CLI arguments from.
* @return PARSE_SUCCESS - CLI arguments read successfully,
* @return PARSE_FAILURE - CLI arguments and/or input not valid.
* @return PARSE_FORCE_EXIT - Exit immediately, print help options.
*/
int dtop_parse_cli_opts(struct cli_opts *clopts, int argc, char **argv)
{
int option;
time_t rawtime;
struct tm * timeinfo;
char timestamp[100];
time ( &rawtime );
timeinfo = gmtime ( &rawtime );
strftime (timestamp, 100,"%F_%H-%M-%S",timeinfo);
if (!clopts || !*argv) {
printf("Internal Error: Null Pointer\n");
goto error;
}
while ((option = getopt(argc, argv, "phri:t:w:o:s:n:")) != -1) {
switch (option) {
case 'p':
clopts->print_cl = OPT_CHOSE;
break;
case 'h':
dtop_print_help_opts();
return PARSE_FORCE_EXIT;
break;
case 'n':
clopts->priority = strtol(optarg, 0, 10);
if (clopts->priority > 19 || clopts->priority < -20) {
printf("Argument for -n is not valid. ");
printf("Must be between -20 and 19.\n");
goto error;
}
break;
case 'i':
clopts->poll_per = strtol(optarg, 0, 10);
if (clopts->poll_per < 200000) {
printf("Argument for -i is not valid. ");
printf("Must be atleast 200000\n");
goto error;
}
break;
case 't':
clopts->poll_time = strtol(optarg, 0, 10);
clopts->poll_time_selected = POLL_TIME_SELECTED;
if (clopts->poll_time <= 0) {
printf("Argument for -t is not valid. ");
printf("Must be positive integer.\n");
goto error;
}
break;
case 'w':
if (dtop_check_writefile_access(optarg) == VALID) {
clopts->file_name = optarg;
clopts->print_csv = OPT_CHOSE;
} else {
goto error;
}
break;
case 'o':
if (dtop_check_out_dir_presence(optarg) != VALID) {
goto error;
}
if(strlen(optarg) + strlen(timestamp) > OUT_DIR_LEN_MAX) {
printf("Out dir too long!");
goto error;
}
strcpy(clopts->out_dir, optarg);
strcat(clopts->out_dir, "/");
strcat(clopts->out_dir, timestamp);
if(dtop_create_dir(clopts->out_dir) != INVALID) {
goto error;
}
break;
case 's':
if (dtop_check_writefile_access(optarg) == VALID)
clopts->snapshot_file = optarg;
else
goto error;
break;
case 'r':
clopts->iptables_rules_routes = OPT_CHOSE;
break;
case '?':
default:
goto error;
}
}
if (clopts->poll_time == 0) {
if (clopts->print_csv == 1)
clopts->poll_time = POLL_NOT_SPECIFIED;
else
clopts->poll_time = POLL_TIME_DEFAULT;
}
if (clopts->poll_per == 0)
clopts->poll_per = DEFAULT_POLL_INTERVAL;
return PARSE_SUCCESS;
error:
printf("See datatop -h for help\n");
return PARSE_FAILURE;
}
/**
* @brief Prints the options the user has for the program to terminal.
*/
void dtop_print_help_opts(void)
{
printf("The following datatop commands are:\n");
printf("\t-p\t\t\tPrint output to terminal\n");
printf("\t-i , u-seconds\t\tSpecify polling period \n");
printf("\t-t , seconds\t\tSpecify polling duration\n");
printf("\t-w , file name (.csv)\tWrite output to a file\n");
printf("\t-s , file name\t\tPrint system snapshot to a file\n");
printf("\t-n , nice value\t\tSet niceness (default 19)\n");
printf("\t-r , \t\t\tCapture IPTables, Rules and Routes\n");
printf("\t-o , out directory for -w options\t\tOut dir where the set of files are saved\n");
printf("\t-h\t\t\tGet help\n");
}
/**
* @brief Prints the interactive options the user can enter during runtime.
*/
void dtop_print_interactive_opts(void)
{
printf("The following interactive commands are:\n");
printf("\tq | quit\tTerminate program at any time\n");
printf("\ti\t\tPrint dp differences, reset initial dp values\n");
printf("\tl\t\tPrint dp differences since last reset\n");
printf("\n");
}

View File

@@ -0,0 +1,91 @@
/************************************************************************
Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
************************************************************************/
/**
* @file datatop_opt.h
* @brief Declares methods and defines struct used within datatop_opt.c
*
* Struct defined is used when parsing the CLI arguments.
*/
#ifndef DATATOP_OPT_H
#define DATATOP_OPT_H
#define OPT_CHOSE 1
#define OPT_NOT_CHOSE 0
#define DEFAULT_POLL_INTERVAL 1000000
#define POLL_NOT_SPECIFIED -1
#define POLL_TIME_DEFAULT 30
#define POLL_TIME_SELECTED 1
#define PARSE_SUCCESS 0
#define PARSE_FAILURE -1
#define PARSE_FORCE_EXIT -2
#define VALID 0
#define INVALID -1
#define DEFAULT_NICE 19 /* Lowest priority */
#define OUT_DIR_LEN_MAX 150
/**
* @struct cli_opts
* @brief Struct used to store arguments from CLI input.
*
* @var cli_opts::print_cl
* Represents -p argument.
* @var cli_opts::poll_per
* Polling frequency argument.
* @var cli_opts::poll_time
* Polling duration argument.
* @var cli_opts::cli_help
* Represents -h argument.
* @var cli_opts::file_name
* File name argument.
* @var cli_opts::print_csv
* Represents -w argument.
*/
struct cli_opts {
int print_cl; /* -p option */
long int poll_per; /* -i option */
long int poll_time; /* -t option */
int cli_help; /* -h option */
char *file_name; /* -w option */
char *snapshot_file; /* -s option */
int iptables_rules_routes; /* -r option */
char out_dir[OUT_DIR_LEN_MAX]; /* -o option */
int print_csv;
int poll_time_selected;
int priority; /* -n option (niceness) */
};
int dtop_parse_cli_opts(struct cli_opts *clopts, int argc, char **argv);
void dtop_print_help_opts(void);
void dtop_print_interactive_opts(void);
void dtop_load_default_options(struct cli_opts *clopts);
#endif /* DATATOP_OPT_H */

View File

@@ -0,0 +1,51 @@
/************************************************************************
Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
************************************************************************/
/**
* @file datatop_dual_line_poll.h
* @brief Declares methods held in datatop_dual_line_poll.c
*/
#ifndef DATATOP_DUAL_LINE_POLL_H
#define DATATOP_DUAL_LINE_POLL_H
void dtop_dual_line_init(char *name);
void dtop_single_line_init(char *name);
void dtop_value_only_init(char *name);
void dtop_meminfo_init(void);
void dtop_dev_init(void);
void dtop_stat_init(void);
void dtop_ip_table_init(char *out_dir);
void *dtop_ip_table_start_poll(void * arg);
void dtop_cpu_stats_init(void);
int dtop_value_only_poll(struct dtop_data_point_gatherer *dpg);
void dtop_value_only_dpg_deconstructor
(struct dtop_data_point_gatherer *dpset);
#endif /* DATATOP_DUAL_LINE_POLL_H */

View File

@@ -0,0 +1,243 @@
/************************************************************************
Copyright (c) 2015, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
************************************************************************/
/**
* @file datatop_single_line_poll.c
* @brief Adds ability for data collection from single line files
*
* File contains methods for searching and polling data from
* single line files, meaning a file with multiple lines, but each
* line contains the name of the dp, followed by the value.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "datatop_interface.h"
#include "datatop_fileops.h"
#include "datatop_str.h"
#define DTOP_SINGLE_SIZE 8192
#define DTOP_SINGLE_LINE (DTOP_SINGLE_SIZE>>2)
/**
* @struct dtop_single_line_vars
* @brief Struct used to hold necessary variables for dual_line_file dpgs.
*
* @var dtop_single_line_vars::line
* Array of strings where necessary dp names and values are held.
* @var dtop_single_line_vars::line_count
* Number of lines the file is that the dpg represents.
*/
struct dtop_single_line_vars {
char **line;
int line_count;
};
/**
* @brief Stores the data collected from a single_line files.
*
* @param dpg Struct that polled data is added to.
* @return DTOP_POLL_IO_ERR - Poll of dpg unsuccessful.
* @return DTOP_POLL_OK - Poll of dpg successful.
*/
int dtop_single_line_poll(struct dtop_data_point_gatherer *dpg)
{
char *data;
int *line_len = malloc(sizeof(int) *
((struct dtop_single_line_vars *)
(dpg->priv))->line_count);
int read;
struct dt_procdict dict;
int i, j, n, sum;
read = dt_read_file(dpg->file, &data, DTOP_SINGLE_SIZE);
if (read == 0 || data == 0)
return DTOP_POLL_IO_ERR;
sum = 0;
/* Assigns each line read from the file, a length */
for (n = 0; n < ((struct dtop_single_line_vars *)
(dpg->priv))->line_count; n++) {
line_len[n] = dt_read_line(((struct dtop_single_line_vars *)
(dpg->priv))->line[n],
DTOP_SINGLE_LINE, data,
DTOP_SINGLE_SIZE, sum);
if (n <= (((struct dtop_single_line_vars *)
(dpg->priv))->line_count - 1)) {
sum += (line_len[n] + 1);
}
}
/* Stores dp names and values in dictionary */
for (i = 0; i < dpg->data_points_len; i++)
dt_parse_proc_same_line_key_and_val((
(struct dtop_single_line_vars *)
(dpg->priv))->line[i], line_len[i], i, &dict);
/* Assigns the dp value to the dp struct */
for (j = 0; j < dpg->data_points_len; j++) {
i = dt_find_dict_idx(dpg->data_points[j].name, &dict);
if (i >= 0 && i < dict.max)
dtop_store_dp(&(dpg->data_points[j]),
dict.val[i]);
}
dt_free(&data);
free(line_len);
return DTOP_POLL_OK;
}
/**
* @brief Frees dynamically allocated single_line_file dpgs.
*
* Frees the memory of the dpg along with it's data_points
* and other malloc'd memory no longer needed.
*
* @param dpg Dpg to deconstruct and deallocate memory for.
*/
static void dtop_single_line_dpg_deconstructor
(struct dtop_data_point_gatherer *dpset)
{
int i;
free(dpset->data_points);
for (i = 0; i < ((struct dtop_single_line_vars *)
(dpset->priv))->line_count; i++)
free(((struct dtop_single_line_vars *)(dpset->priv))->line[i]);
free(((struct dtop_single_line_vars *)(dpset->priv))->line);
free(((struct dtop_single_line_vars *)(dpset->priv)));
free(dpset);
}
/**
* @brief Creates a dpg for a single_line file.
*
* Dynamically allocates memory for dpg which is then added to a linked list
* via the dtop_register(dpg) function call.
*
* @param name Name of file dpg represents.
* @param data_points dtop_data_point struct that dpg points to.
* @param storage dtop_single_line_vars struct that holds relevant dpg variables.
*/
static void construct_single_line_file_dpg(char *name, struct dtop_data_point
*data_points, struct dtop_single_line_vars *storage)
{
struct dtop_data_point_gatherer *dpg = malloc
(sizeof(struct dtop_data_point_gatherer));
dpg->prefix = name;
dpg->file = name;
dpg->poll = dtop_single_line_poll;
dpg->data_points = data_points;
dpg->priv = (struct dtop_single_line_vars *)storage;
dpg->data_points_len = storage->line_count;
dpg->deconstruct = dtop_single_line_dpg_deconstructor;
dtop_register(dpg);
}
/**
* @brief Scans a single_line file for all datapoints and creats dps.
*
* Searches through a single_line file (Key followed by value on the
* same line) for all available data points to create as dp structs.
*
* @param name Name of file.
* @param storage dtop_single_line_vars struct where relevant variables are stored.
*/
int dtop_single_line_search(char *name, struct dtop_single_line_vars *storage)
{
int i, k, n, sum;
char *data;
int *line_len = malloc(sizeof(int) * storage->line_count);
int read;
struct dt_procdict dict;
struct dtop_data_point *data_points;
storage->line = malloc(storage->line_count * sizeof(*storage->line));
for (i = 0; i < storage->line_count; i++)
storage->line[i] = malloc(sizeof(char) * DTOP_SINGLE_LINE);
read = dt_read_file(name, &data, DTOP_SINGLE_SIZE);
if (read == 0 || data == 0)
return DTOP_POLL_IO_ERR;
sum = 0;
/* Assigns each line read from the file, a length */
for (n = 0; n < storage->line_count; n++) {
line_len[n] = dt_read_line(storage->line[n],
DTOP_SINGLE_LINE, data,
DTOP_SINGLE_SIZE, sum);
if (n < (storage->line_count - 1))
sum += (line_len[n] + 1);
}
/* Stores dp names and values in dictionary */
for (i = 0; i < (storage->line_count); i++)
dt_parse_proc_same_line_key_and_val(storage->line[i],
line_len[i], i, &dict);
data_points = malloc
(storage->line_count * sizeof(struct dtop_data_point));
k = 0;
/* Creates a dtop_data_point struct for each dp found in the file */
for (i = 0; i < dict.max; i++) {
if (dict.val[i][0] == '-')
data_points[k].type = DTOP_LONG;
else
data_points[k].type = DTOP_ULONG;
data_points[i].name = dict.key[i];
data_points[i].prefix = NULL;
k++;
}
/* Calls dpg constructor, dpg will point to the dp struct */
construct_single_line_file_dpg(name, data_points, storage);
free(line_len);
dt_free(&data);
return DTOP_POLL_OK;
}
/**
* @brief Calls dtop_search for a files with single line format.
*
* Single line format refers to a file, where each line contains
* the name of a dp, followed by the value of a dp.
*/
void dtop_single_line_init(char *name)
{
struct dtop_single_line_vars *storage = malloc
(sizeof(struct dtop_single_line_vars));
storage->line_count = dtop_get_file_line_amount(name);
dtop_single_line_search(name, storage);
}

View File

@@ -0,0 +1,319 @@
/************************************************************************
Copyright (c) 2015, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
************************************************************************/
/**
* @file datatop_stat_poll.c
* @brief Adds ability for data collection from /proc/stat
*
* File contains methods for searching and polling data from
* "/proc/stat"
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "datatop_interface.h"
#include "datatop_fileops.h"
#include "datatop_str.h"
#define DTOP_STAT_SIZE 16384
#define DTOP_STAT_LINE (DTOP_STAT_SIZE>>2)
/**
* @struct dtop_stat_vars
* @brief Struct used to hold necessary variables for /proc/stat dpg
*
* @var dtop_stat_vars::line
* Array of strings where necessary dp names and values are held.
* @var dtop_stat_vars::line_count
* Number of lines the file is that the dpg represents.
*/
struct dtop_stat_vars {
char **line;
int line_count;
};
/**
* @brief Parses lines with data in "/proc/stat"
*
* @param line1 Line to parse to find datapoint names and values.
* @param len1 Length of line1.
* @param n_index Index in the dictionary the key (name) is added to.
* @param v_index Index in the dictionary the value is added to.
* @param dict Dictionary the keys and values are added to.
*/
static int dt_stat_parse(char *line1, int len1,
int n_index, int v_index, struct dt_procdict *dict)
{
int i, k, j, start = 0;
if (len1 < 1)
return 0;
if (line1 == 0 || dict == 0)
return 0;
dict->key[n_index] = &line1[0];
for (i = 0; i < len1; i++) {
if (line1[i] == ' ') {
line1[i] = 0;
start = (i+1);
break;
}
}
k = v_index;
for (i = start; i < len1 && k < DTOP_DICT_SIZE; i++) {
if (line1[i] != ' ') {
dict->val[k] = &line1[i];
for (j = i; j < len1; j++) {
if (line1[j] == ' ') {
line1[j] = 0;
break;
}
}
i = j;
k++;
}
}
dict->max = k;
return k;
}
/**
* @brief Stores the data collected from "/proc/stat"
*
* @param dpg Struct that polled data is added to.
* @return DTOP_POLL_IO_ERR - Poll of dpg unsuccessful.
* @return DTOP_POLL_OK - Poll of dpg successful.
*/
int dtop_stat_poll(struct dtop_data_point_gatherer *dpg)
{
char *data;
int *line_len = malloc(sizeof(int) *
((struct dtop_stat_vars *)
(dpg->priv))->line_count);
int read;
struct dt_procdict dict;
int i, n, sum;
int dp_count = 0;
read = dt_read_file(dpg->file, &data, DTOP_STAT_SIZE);
if (read == 0 || data == 0)
return DTOP_POLL_IO_ERR;
sum = 0;
/* Assigns each line read from the file, a length */
for (n = 0; n < ((struct dtop_stat_vars *)
(dpg->priv))->line_count; n++) {
line_len[n] = dt_read_line(((struct dtop_stat_vars *)
(dpg->priv))->line[n],
DTOP_STAT_LINE, data,
DTOP_STAT_SIZE, sum);
if (n <= (((struct dtop_stat_vars *)
(dpg->priv))->line_count - 1)) {
sum += (line_len[n] + 1);
}
}
/* Stores dp names and values in dictionary */
for (i = 0; i < ((struct dtop_stat_vars *)(dpg->priv))->line_count; i++)
dp_count = dt_stat_parse(((struct dtop_stat_vars *)
(dpg->priv))->line[i], line_len[i], i, dp_count, &dict);
/* Assigns the dp value to the dp struct */
for (n = 0; n < dp_count; n++) {
dtop_store_dp(&(dpg->data_points[n]),
dict.val[n]);
}
dt_free(&data);
free(line_len);
return DTOP_POLL_OK;
}
/**
* @brief Frees dynamically allocated "/proc/stat" dpg.
*
* Frees the memory of the dpg along with it's data_points
* and other malloc'd memory no longer needed.
*
* @param dpg Dpg to deconstruct and deallocate memory for.
*/
static void dtop_stat_dpg_deconstructor
(struct dtop_data_point_gatherer *dpset)
{
int i;
for (i = 0; i < dpset->data_points_len; i++)
free(dpset->data_points[i].name);
free(dpset->data_points);
for (i = 0; i < ((struct dtop_stat_vars *)
(dpset->priv))->line_count; i++)
free(((struct dtop_stat_vars *)(dpset->priv))->line[i]);
free(((struct dtop_stat_vars *)(dpset->priv))->line);
free(((struct dtop_stat_vars *)(dpset->priv)));
free(dpset);
}
/**
* @brief Creates a dpg for "/proc/stat" file
*
* Dynamically allocates memory for dpg which is then added to a linked list
* via the dtop_register(dpg) function call.
*
* @param data_points dtop_data_point struct that dpg points to.
* @param storage dtop_stat_vars struct that holds relevant dpg variables.
* @param dp_count Number of data_points in data_points array
*/
static void construct_stat_file_dpg(struct dtop_data_point
*data_points, struct dtop_stat_vars *storage, int dp_count)
{
struct dtop_data_point_gatherer *dpg = malloc
(sizeof(struct dtop_data_point_gatherer));
dpg->prefix = "/proc/stat";
dpg->file = "/proc/stat";
dpg->poll = dtop_stat_poll;
dpg->data_points = data_points;
dpg->priv = (struct dtop_stat_vars *)storage;
dpg->data_points_len = dp_count;
dpg->deconstruct = dtop_stat_dpg_deconstructor;
dtop_register(dpg);
}
/**
* @brief Scans "/proc/stat" in order to autodetect dps.
*
* Searches through "/proc/stat" file for all available data
* points to create as dp structs.
*
* @param storage dtop_stat_vars struct where relevant variables are stored.
*/
int dtop_stat_search(struct dtop_stat_vars *storage)
{
int i, n, sum;
char *data;
int *line_len = malloc(sizeof(int) * storage->line_count);
int read;
struct dt_procdict dict;
int dp_count = 0;
int end;
int *dp_per_line;
struct dtop_data_point *data_points;
int count = 0;
storage->line = malloc(storage->line_count * sizeof(*storage->line));
for (i = 0; i < storage->line_count; i++)
storage->line[i] = malloc(sizeof(char) * DTOP_STAT_LINE);
read = dt_read_file("/proc/stat", &data, DTOP_STAT_SIZE);
if (read == 0 || data == 0)
return DTOP_POLL_IO_ERR;
sum = 0;
/* Assigns each line read from the file, a length */
for (n = 0; n < storage->line_count; n++) {
line_len[n] = dt_read_line(storage->line[n],
DTOP_STAT_LINE, data,
DTOP_STAT_SIZE, sum);
if (n < (storage->line_count - 1))
sum += (line_len[n] + 1);
}
dp_per_line = malloc(sizeof(int) * (storage->line_count));
/* Stores dp names in dictionary */
for (i = 0; i < (storage->line_count); i++) {
end = dp_count;
dp_count = dt_stat_parse(storage->line[i],
line_len[i], i, dp_count, &dict);
dp_per_line[i] = (dp_count - end);
}
data_points = malloc(dp_count * sizeof(struct dtop_data_point));
for (i = 0; i < (storage->line_count); i++) {
for (n = 0; n < dp_per_line[i]; n++) {
if (dp_per_line[i] == 1) {
int dk_len = strlen(dict.key[i]) + 1;
int dp_len;
char *newname = malloc(dk_len);
strlcpy(newname, dict.key[i], dk_len);
dp_len = strlen(newname) + 1;
data_points[count].name = malloc(dp_len);
strlcpy(data_points[count].name, newname,
dp_len);
free(newname);
} else {
char *add = malloc(15 * sizeof(char));
char *newname;
int nn_len, dpn_len;
snprintf(add, 15 * sizeof(char), "[%d]:", n);
nn_len = strlen(dict.key[i]) + strlen(add) + 1;
newname = malloc(nn_len);
strlcpy(newname, dict.key[i], nn_len);
strlcat(newname, add, nn_len);
dpn_len = strlen(newname) + 1;
data_points[count].name = malloc(dpn_len);
strlcpy(data_points[count].name, newname,
dpn_len);
free(newname);
free(add);
}
data_points[count].prefix = NULL;
data_points[count].type = DTOP_ULONG;
data_points[count].initial_data_populated
= NOT_POPULATED;
data_points[count].skip = DO_NOT_SKIP;
count++;
}
}
/* Calls dpg constructor, dpg will point to the dp struct */
construct_stat_file_dpg(data_points, storage, dp_count);
free(dp_per_line);
free(line_len);
dt_free(&data);
return DTOP_POLL_OK;
}
/**
* @brief Calls dtop_search for "/proc/stat" file.
*/
void dtop_stat_init(void)
{
struct dtop_stat_vars *storage = malloc
(sizeof(struct dtop_stat_vars));
storage->line_count = dtop_get_file_line_amount("/proc/stat");
dtop_stat_search(storage);
}

View File

@@ -0,0 +1,260 @@
/************************************************************************
Copyright (c) 2015, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
************************************************************************/
/**
* @file datatop_str.c
* @brief Algorithms used for storing and polling data created.
*
* Methods created which store collected data from files in
* dictionaries for many different file formats.
*/
#include <stdio.h>
#include <string.h>
#include "datatop_str.h"
/** @brief Reads an individual line from a file.
*
* Will read from buf2 until either a '\n' is reached, or the end of buf1
* or buf2 is reached. The result is guaranteed to be null terminated.
*
* @param buf1 Destination buffer to store the read line.
* @param len1 Size of destination buffer.
* @param buf2 Source buffer to read lines from. Const, will not be
* modified by this function.
* @param len2 Size of the source buffer.
* @param start Offset (in bytes) to start reading from source buffer.
* @return Length of line (of chars).
*/
int dt_read_line(char *buf1, int len1, const char *buf2, int len2, int start)
{
int i, j;
if (len1 < 1 || len2 < 1 || start < 0 || start > len2)
return 0;
if (buf1 == 0 || buf2 == 0)
return 0;
i = 0;
j = start;
while ((i < (len1-1)) && (j < len2)) {
buf1[i] = buf2[j];
if (buf1[i] == '\n')
break;
i++;
j++;
}
buf1[i] = 0;
return i;
}
/**
* @brief Parses files that have Names and Values on separate lines.
*
* Use this method to parse files that have names on one line, followed by
* the corresponding values on the next line. Such as "/proc/net/netstat"
*
* @param line1 First line that is parsed to store the datapoint names as keys.
* @param len1 Length of line1.
* @param line2 Second line that is parsed to store the datapoint values as dictionary values.
* @param len2 Length of line2.
* @param dict Dictionary that keys and values are added to.
* @return Number of key/val pairs in the dictionary.
*/
int dt_parse_proc_dictionary(char *line1, int len1, char *line2,
int len2, struct dt_procdict *dict)
{
int i, j, k;
if (len1 < 1 || len2 < 1)
return 0;
if (line1 == 0 || line2 == 0 || dict == 0)
return 0;
k = 0;
for (i = 0; i < len1 && k < DTOP_DICT_SIZE; i++) {
if (line1[i] == ' ') {
dict->key[k] = &line1[i+1];
line1[i] = 0;
k++;
}
}
j = k;
k = 0;
for (i = 0; i < len2 && k < DTOP_DICT_SIZE; i++) {
if (line2[i] == ' ') {
dict->val[k] = &line2[i+1];
line2[i] = 0;
k++;
}
}
if (j != k) {
if (k < j)
j = k;
fprintf(stderr, "Warning, list index length mismatch\n");
}
dict->max = j;
return j;
}
/**
* @brief Parses line for prefixes for files that have individual data_point prefixes.
*
* Use this method for lines that have a prefix before data begins. Such as
* "/proc/net/snmp"
*
* @param line1 Line to parse to find datapoint prefix.
* @param len1 Length of line1.
* @param dict Dictionary prefix is being added to.
*/
void dt_parse_for_prefix(char *line1, int len1, struct dt_procdict *dict)
{
int i, j, k;
if (len1 < 1)
return;
if (line1 == 0 || dict == 0)
return;
k = 0;
for (i = 0; i < len1 && k < DTOP_DICT_SIZE; i++) {
if (line1[i] == ' ') {
dict->key[k] = &line1[i+1];
line1[i] = 0;
k++;
}
}
for (j = 0; j < k; j++)
dict->val[j] = &line1[0];
for (j = 0; j < len1; j++) {
if (line1[j] == ':')
line1[j] = 0;
}
}
/**
* @brief Finds the dictionary index of a data_point name.
*
* @param str Name of data_point that is to be located in dict.
* @param dict Dictionary to look through for dp name.
* @return Dictionary index of name if found.
* @return -1 if name not found in dictionary keys.
*/
int dt_find_dict_idx(const char *str, struct dt_procdict *dict)
{
int i;
if (str == 0 || dict == 0)
return -1;
for (i = 0; i < dict->max; i++) {
if (dict->key[i] && !strcmp(str, dict->key[i]))
return i;
}
return -1;
}
/**
* @brief Parses files that have Names and Values on same line.
*
* Use this method to parse lines that have a dp name followed
* by a dp value. Such as "/proc/net/snmp6"
*
* @param line1 Line to parse to find datapoint names and values.
* @param len1 Length of line1.
* @param l Index in the dictionary the key/val pair is added to.
* @param dict Dictionary the keys and values are added to.
* @return Number of key/val pairs in the dictionary.
*/
int dt_parse_proc_same_line_key_and_val(char *line1, int len1,
int l, struct dt_procdict *dict)
{
int i, k, n;
if (len1 < 1)
return 0;
if (line1 == 0 || dict == 0)
return 0;
k = l;
for (i = 0; i < len1 && k < DTOP_DICT_SIZE; i++) {
if (line1[i] == ' ') {
dict->key[k] = &line1[0];
line1[i] = 0;
for (n = i+1; n < len1; n++) {
if (line1[n] != ' ') {
dict->val[k] = &line1[n+1];
break;
}
}
break;
}
}
k++;
dict->max = k;
return k;
}
/**
* @brief Parses files that have a single line.
*
* Parses a single line file for csv, tab-separated, space-separated, and single
* value formats and adds values to a dictionary. Such as
* "/proc/sys/net/ipv4/ping_group_range"
*
* Use this method to parse lines that contain only values.
*
* @param line1 Line to parse.
* @param len1 Length of line1.
* @param dict Dictionary datapoints are added to.
* @return Number of values dictionary holds.
*/
int dt_single_line_parse(char *line1, int len1, struct dt_procdict *dict)
{
int i, k;
k = 0;
dict->val[k] = &line1[0];
k++;
for (i = 0; i < len1; i++) {
if (line1[i] == ' ' || line1[i] == ',' || line1[i] == ' ') {
line1[i] = 0;
dict->val[k] = &line1[i+1];
k++;
}
}
dict->max = k;
return k;
}

View File

@@ -0,0 +1,70 @@
/************************************************************************
Copyright (c) 2015, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
************************************************************************/
/**
* @file datatop_str.h
* @brief Declares methods held in datatop_str.c and defines dictionary struct.
*/
#ifndef DATATOP_STR_H
#define DATATOP_STR_H
#define DTOP_DICT_SIZE 2048
/**
* @struct dt_procdict
* @brief Struct used to create dictionary for parsing purposes.
*
* @var dt_procdict::max
* Number of key/val pairs in dictionary.
* @var dt_procdict::key
* Holds the key that is used to access the value.
* @var dt_procdict::val
* Value that the key accesses.
*/
struct dt_procdict {
int max;
char *key[DTOP_DICT_SIZE];
char *val[DTOP_DICT_SIZE];
};
int dt_read_line(char *buf1, int len1, const char *buf2, int len2, int start);
int dt_parse_proc_dictionary(char *line1, int len1, char *line2, int len2,
struct dt_procdict *dict);
int dt_find_dict_idx(const char *str, struct dt_procdict *dict);
int dt_parse_proc_same_line_key_and_val(char *line1, int len1, int l,
struct dt_procdict *dict);
void dt_parse_for_prefix(char *line1, int len1, struct dt_procdict *dict);
int dt_single_line_parse(char *line1, int len1, struct dt_procdict *dict);
#endif /* DATATOP_STR_H */

View File

@@ -0,0 +1,199 @@
/************************************************************************
Copyright (c) 2015, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
************************************************************************/
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include "datatop_interface.h"
#include "datatop_fileops.h"
#include "datatop_str.h"
#include "datatop_opt.h"
#define DTOP_SNAP_SIZE 8192
#define DTOP_SNAP_LINE (DTOP_SNAP_SIZE>>2)
static int dtop_system_snapshot_helper_print(char *file, const char *str)
{
FILE *snap_file = fopen(file, "a");
if (snap_file) {
if (fprintf(snap_file, "%s", str) < 0) {
fclose(snap_file);
return FILE_ERROR;
}
} else {
return FILE_ERROR;
}
fflush(snap_file);
fclose(snap_file);
return FILE_SUCCESS;
}
/**
* @brief A helper function to dtop_print_system_snapshot.
*
* @param fw File that desired system data is printed to.
* @return FILE_ERROR - Writing to file was unsuccessful.
* @return FILE_SUCCESS - Writing to file was successful.
*/
static int dtop_run_and_log(char *file, const char *c1, const char **args)
{
int i;
pid_t child_pid;
i = 0;
dtop_system_snapshot_helper_print(file, "\n"
"--------------------------------------------------------------\n"
"Command: ");
while(args[i] != 0) {
dtop_system_snapshot_helper_print(file, args[i++]);
dtop_system_snapshot_helper_print(file, " ");
}
dtop_system_snapshot_helper_print(file, "\n");
child_pid = fork();
if (child_pid == 0) {
int fd = open(file, O_WRONLY | O_APPEND | O_CREAT,
S_IRUSR | S_IWUSR);
dup2(fd, STDOUT_FILENO);
dup2(fd, STDERR_FILENO);
close(fd);
execvp(c1, (char * const *)args);
printf("Failed to execute %s\n", c1);
printf("errno=%d error=%s\n", errno, strerror(errno));
close(STDOUT_FILENO);
close(STDERR_FILENO);
exit(0);
} else if (child_pid < 0) {
return FILE_ERROR;
} else {
int return_status;
waitpid(child_pid, &return_status, 0);
if (return_status != 0)
return FILE_ERROR;
}
return FILE_SUCCESS;
}
/* IPv4 */
const char *ip_addr_cmd[] = {"ip", "addr", 0};
const char *ip_route_cmd[] = {"ip", "route", 0};
const char *ip_route_all_tables_cmd[] = {"ip", "route", "show", "table", "all", 0};
const char *ip_rule_cmd[] = {"ip", "rule", "show", 0};
const char *ip_tables_cmd[] = {"iptables", "-L", "-n", "-v", 0};
const char *ip_tables_nat_cmd[] = {"iptables", "-t", "nat", "-L", "-n", "-v", 0};
const char *ip_tables_mangle_cmd[] = {"iptables", "-t", "mangle", "-L", "-n", "-v", 0};
const char *ip_tables_raw_cmd[] = {"iptables", "-t", "raw", "-L", "-n", "-v", 0};
/* IPv6 */
const char *ip6_addr_cmd[] = {"ip", "-6", "addr", 0};
const char *ip6_route_cmd[] = {"ip", "-6", "route", 0};
const char *ip6_route_all_tables_cmd[] = {"ip", "-6", "route", "show", "table", "all", 0};
const char *ip6_rule_cmd[] = {"ip", "-6", "rule", "show", 0};
const char *ip6_tables_cmd[] = {"ip6tables", "-L", "-n", "-v", 0};
const char *ip6_tables_nat_cmd[] = {"ip6tables", "-t", "nat", "-L", "-n", "-v", 0};
const char *ip6_tables_mangle_cmd[] = {"ip6tables", "-t", "mangle", "-L", "-n", "-v", 0};
const char *ip6_tables_raw_cmd[] = {"ip6tables", "-t", "raw", "-L", "-n", "-v", 0};
/* Misc */
const char *rps_config[] = {"cat", "/sys/class/net/rmnet_mhi0/queues/rx-0/rps_cpus", 0};
const char *if_config[] = {"/data/busybox/busybox", "ifconfig", 0};
const char *netcfg[] = {"netcfg", 0};
const char *softnet_stat[] = {"cat", "/proc/net/softnet_stat", 0};
/* XFRM logging */
const char *xfrm_state[] = {"ip", "xfrm", "state", "show", 0};
const char *xfrm_policy[] = {"ip", "xfrm", "policy", "show", 0};
const char *xfrm_netstat[] = {"cat", "/proc/net/xfrm_stat", 0};
#define DO_DTOP_RUN_AND_LOG(X) \
dtop_run_and_log(file, X[0], X);
/**
* @brief Prints a System snapshot to a file specified by the user.
*
* @param fw File that system snapshot is printed to.
* @return FILE_ERROR - Writing to file was unsuccessful.
* @return FILE_SUCCESS - Writing to file was successful.
*/
int dtop_print_system_snapshot(char *file)
{
dtop_system_snapshot_helper_print(file,
"==============================================================\n"
" System Data Snapshot - Captured with Data Top \n"
" Version ");
dtop_system_snapshot_helper_print(file, VERSION);
dtop_system_snapshot_helper_print(file, "\n"
"==============================================================\n"
"\n");
/* IPv4 */
DO_DTOP_RUN_AND_LOG(ip_addr_cmd);
DO_DTOP_RUN_AND_LOG(ip_route_cmd);
DO_DTOP_RUN_AND_LOG(ip_route_all_tables_cmd);
DO_DTOP_RUN_AND_LOG(ip_rule_cmd);
DO_DTOP_RUN_AND_LOG(ip_tables_cmd);
DO_DTOP_RUN_AND_LOG(ip_tables_nat_cmd);
DO_DTOP_RUN_AND_LOG(ip_tables_mangle_cmd);
DO_DTOP_RUN_AND_LOG(ip_tables_raw_cmd);
/* IPv6 */
DO_DTOP_RUN_AND_LOG(ip6_addr_cmd);
DO_DTOP_RUN_AND_LOG(ip6_route_cmd);
DO_DTOP_RUN_AND_LOG(ip6_route_all_tables_cmd);
DO_DTOP_RUN_AND_LOG(ip6_rule_cmd);
DO_DTOP_RUN_AND_LOG(ip6_tables_cmd);
DO_DTOP_RUN_AND_LOG(ip6_tables_nat_cmd);
DO_DTOP_RUN_AND_LOG(ip6_tables_mangle_cmd);
DO_DTOP_RUN_AND_LOG(ip6_tables_raw_cmd);
/* Misc */
DO_DTOP_RUN_AND_LOG(rps_config);
DO_DTOP_RUN_AND_LOG(if_config);
DO_DTOP_RUN_AND_LOG(netcfg);
DO_DTOP_RUN_AND_LOG(softnet_stat);
/* XFRM logging */
DO_DTOP_RUN_AND_LOG(xfrm_state);
DO_DTOP_RUN_AND_LOG(xfrm_policy);
DO_DTOP_RUN_AND_LOG(xfrm_netstat);
return FILE_SUCCESS;
}

View File

@@ -0,0 +1,201 @@
/************************************************************************
Copyright (c) 2015, The Linux Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
************************************************************************/
/**
* @file datatop_value_only_poll.c
* @brief Adds ability for data collection from files with only values
*
* File contains methods for searching and polling data from
* value_only files, meaning a file with a single line, containing
* only values.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "datatop_interface.h"
#include "datatop_fileops.h"
#include "datatop_str.h"
#define DTOP_SINGLE_SIZE 8192
#define DTOP_SINGLE_LINE (DTOP_SINGLE_SIZE>>2)
/**
* @brief Stores the data collected from a value_only files.
*
* @param dpg Struct that polled data is added to.
* @return DTOP_POLL_IO_ERR - Poll of dpg unsuccessful.
* @return DTOP_POLL_OK - Poll of dpg successful.
*/
int dtop_value_only_poll(struct dtop_data_point_gatherer *dpg)
{
char *data;
int line_len;
char line[DTOP_SINGLE_LINE];
int read;
struct dt_procdict dict;
int j;
FILE *check = fopen(dpg->file, "r");
if (check) {
fclose(check);
read = dt_read_file(dpg->file, &data, DTOP_SINGLE_SIZE);
} else {
return DTOP_POLL_IO_ERR;
}
if (read == 0 || data == 0)
return DTOP_POLL_IO_ERR;
line_len = dt_read_line(line, DTOP_SINGLE_LINE, data,
DTOP_SINGLE_SIZE, 0);
/* Stores dp values in dictionary */
dt_single_line_parse(line, line_len, &dict);
/* Assigns the dp value to the dp struct */
for (j = 0; j < dpg->data_points_len; j++)
dtop_store_dp(&(dpg->data_points[j]), dict.val[j]);
dt_free(&data);
return DTOP_POLL_OK;
}
/**
* @brief Frees dynamically allocated single line dpg.
*
* Frees the memory of the dpg along with it's data_points
* and other malloc'd memory no longer needed.
*
* @param dpg Dpg to deconstruct and deallocate memory for.
*/
void dtop_value_only_dpg_deconstructor
(struct dtop_data_point_gatherer *dpset)
{
int i;
for (i = 0; i < dpset->data_points_len; i++)
free(dpset->data_points[i].name);
free(dpset->data_points);
free(dpset->file);
free(dpset);
}
/**
* @brief Creates a dpg for a single line file.
*
* Dynamically allocates memory for dpg which is then added to a linked list
* via the dtop_register(dpg) function call.
*
* @param name Name of file dpg represents.
* @param data_points dtop_data_point struct that dpg points to.
* @param dp_count Number of data_points in data_points array
*/
static void construct_value_only_dpg(char *name, struct dtop_data_point
*data_points, int dp_count)
{
struct dtop_data_point_gatherer *dpg = malloc
(sizeof(struct dtop_data_point_gatherer));
dpg->prefix = name;
dpg->file = name;
dpg->poll = dtop_value_only_poll;
dpg->data_points = data_points;
dpg->data_points_len = dp_count;
dpg->deconstruct = dtop_value_only_dpg_deconstructor;
dtop_register(dpg);
}
/**
* @brief Scans a single line file in order to autodetect dps.
*
* Searches through a file that contains a single line and only
* values in order to detect and create dp's/
*
* @param name Name of file to scan.
*/
int dtop_value_only_search(char *name)
{
int i;
char *data;
char line[DTOP_SINGLE_LINE];
int line_len;
int read;
struct dt_procdict dict;
struct dtop_data_point *data_points;
read = dt_read_file(name, &data, DTOP_SINGLE_SIZE);
if (read == 0 || data == 0) {
free(name);
return DTOP_POLL_IO_ERR;
}
line_len = dt_read_line(line,
DTOP_SINGLE_LINE, data,
DTOP_SINGLE_SIZE, 0);
/* Stores dp values in dictionary */
dt_single_line_parse(line, line_len, &dict);
data_points = malloc(dict.max * sizeof(struct dtop_data_point));
/* Creates a dtop_data_point struct for each dp found in the file */
for (i = 0; i < dict.max; i++) {
char *newname = malloc(sizeof(10));
if (dict.val[i][0] == '-')
data_points[i].type = DTOP_LONG;
else
data_points[i].type = DTOP_ULONG;
data_points[i].name = malloc(sizeof(10));
if (dict.max > 1)
snprintf(newname, sizeof(10), "[%d]:", i);
else
strlcpy(newname, "", sizeof(10));
strlcpy(data_points[i].name, newname, sizeof(10));
free(newname);
data_points[i].prefix = NULL;
data_points[i].skip = DO_NOT_SKIP;
data_points[i].initial_data_populated = NOT_POPULATED;
}
/* Calls dpg constructor, dpg will point to the dp struct */
construct_value_only_dpg(name, data_points, dict.max);
dt_free(&data);
return DTOP_POLL_OK;
}
/**
* @brief Calls dtop_search for files with a single line and only values.
*/
void dtop_value_only_init(char *name)
{
char *file = malloc(strlen(name) + 1);
strlcpy(file, name, strlen(name) + 1);
dtop_value_only_search(file);
}