Merge changes from topic 'msm8998-opensource'

* changes:
  move thermal-engine time-services json-c to hardware/qcom/msm8998
  Move codeaurora and qcom/opensource modules to hardware/qcom/msm8998
This commit is contained in:
Alexey Polyudov
2017-02-24 16:16:32 +00:00
committed by Android (Google) Code Review
156 changed files with 0 additions and 54899 deletions

View File

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

View File

@@ -1,11 +0,0 @@
# Makefile.am - Automake script for Data-opensource
#
ACLOCAL_AMFLAGS = -I m4
AUTOMAKE_OPTIONS = foreign
SUBDIRS = rmnetctl/src rmnetctl/cli
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = data-oss.pc
EXTRA_DIST = $(pkgconfig_DATA)

View File

@@ -1,51 +0,0 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.65])
AC_INIT([data-oss], [1.0.0])
AM_INIT_AUTOMAKE
AC_OUTPUT(Makefile rmnetctl/src/Makefile rmnetctl/cli/Makefile data-oss.pc)
AC_CONFIG_SRCDIR([rmnetctl/src/librmnetctl.c])
#AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])
# Checks for programs.
AC_PROG_CC
AC_PROG_LIBTOOL
PKG_PROG_PKG_CONFIG
# Checks for libraries.
AC_ARG_WITH(sanitized-headers,
AS_HELP_STRING([--with-sanitized-headers=DIR],
[Specify the location of the sanitized Linux headers]),
[CPPFLAGS="$CPPFLAGS -idirafter $withval"])
AC_ARG_WITH([glib],
AC_HELP_STRING([--with-glib],
[enable glib, building HLOS systems which use glib]))
if (test "x${with_glib}" = "xyes"); then
AC_DEFINE(ENABLE_USEGLIB, 1, [Define if HLOS systems uses glib])
PKG_CHECK_MODULES(GTHREAD, gthread-2.0 >= 2.16, dummy=yes,
AC_MSG_ERROR(GThread >= 2.16 is required))
PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.16, dummy=yes,
AC_MSG_ERROR(GLib >= 2.16 is required))
GLIB_CFLAGS="$GLIB_CFLAGS $GTHREAD_CFLAGS"
GLIB_LIBS="$GLIB_LIBS $GTHREAD_LIBS"
AC_SUBST(GLIB_CFLAGS)
AC_SUBST(GLIB_LIBS)
fi
AM_CONDITIONAL(USE_GLIB, test "x${with_glib}" = "xyes")
# Checks for header files.
AC_CHECK_HEADERS([sys/socket.h stdint.h linux/netlink.h string.h stdio.h unistd.h stdlib.h linux/rmnet_data.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_OFF_T
# Checks for library functions.
AC_FUNC_MALLOC
#AC_FUNC_MMAP
#AC_CHECK_FUNCS([memset malloc sendto recvfrom ])
AC_OUTPUT

View File

@@ -1,10 +0,0 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: data-oss
Description: Data Opensource Components
Version: @VERSION@
Libs: -L${libdir} -lrmnetctl
Cflags: -I${includedir}/data-oss

View File

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

View File

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

View File

@@ -1,51 +0,0 @@
#!/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

@@ -1,56 +0,0 @@
# -*- 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

@@ -1,33 +0,0 @@
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
include $(BUILD_EXECUTABLE)

View File

@@ -1,23 +0,0 @@
## 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

@@ -1,300 +0,0 @@
/************************************************************************
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"
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 = tv.tv_sec;
endtime = tv.tv_sec + 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 = usr_cl_opts.poll_per;
timeout.tv_usec = 0;
//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 = tv.tv_sec;
dtop_poll(dpg_list);
printf("Polled at %ld.%06ld\n", tv.tv_sec, tv.tv_usec);
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) {
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_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

@@ -1,182 +0,0 @@
/************************************************************************
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

@@ -1,320 +0,0 @@
/************************************************************************
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] != ' ' && 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

@@ -1,319 +0,0 @@
/************************************************************************
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

@@ -1,202 +0,0 @@
/************************************************************************
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

@@ -1,50 +0,0 @@
/************************************************************************
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

@@ -1,280 +0,0 @@
/************************************************************************
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

@@ -1,43 +0,0 @@
/************************************************************************
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

@@ -1,478 +0,0 @@
/************************************************************************
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

@@ -1,166 +0,0 @@
/************************************************************************
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

@@ -1,346 +0,0 @@
/************************************************************************
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)
{
int i;
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()
{
struct dtop_data_point_gatherer *dpset;
struct dtop_linked_list *curr_ptr = ip_dpg_list;
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;
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

@@ -1,84 +0,0 @@
/************************************************************************
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

@@ -1,59 +0,0 @@
/************************************************************************
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

@@ -1,282 +0,0 @@
/************************************************************************
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

@@ -1,215 +0,0 @@
/************************************************************************
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 <= 0) {
printf("Argument for -i is not valid. ");
printf("Must be positive integer.\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 , 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

@@ -1,91 +0,0 @@
/************************************************************************
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 1
#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

@@ -1,51 +0,0 @@
/************************************************************************
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

@@ -1,243 +0,0 @@
/************************************************************************
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

@@ -1,319 +0,0 @@
/************************************************************************
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

@@ -1,260 +0,0 @@
/************************************************************************
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

@@ -1,70 +0,0 @@
/************************************************************************
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

@@ -1,199 +0,0 @@
/************************************************************************
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

@@ -1,201 +0,0 @@
/************************************************************************
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);
}

View File

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

View File

@@ -1,16 +0,0 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := rmnetcli.c
LOCAL_CFLAGS := -Wall -Werror
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../inc
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../src
LOCAL_C_INCLUDES += $(LOCAL_PATH)
LOCAL_MODULE := rmnetcli
LOCAL_MODULE_TAGS := optional
LOCAL_SHARED_LIBRARIES := librmnetctl
include $(BUILD_EXECUTABLE)

View File

@@ -1,9 +0,0 @@
AM_CFLAGS = -Wall -Werror -Wundef -Wstrict-prototypes -Wno-trigraphs
AM_CFLAGS += -I./../inc
rmnetcli_SOURCES = rmnetcli.c
bin_PROGRAMS = rmnetcli
requiredlibs = ../src/librmnetctl.la
rmnetcli_LDADD = $(requiredlibs)
LOCAL_MODULE := librmnetctl
LOCAL_PRELINK_MODULE := false
include $(BUILD_SHARED_LIBRARY)

View File

@@ -1,415 +0,0 @@
/******************************************************************************
R M N E T C L I . C
Copyright (c) 2013-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 rmnetcli.c
@brief command line interface to expose rmnet control API's
DESCRIPTION
File containing implementation of the command line interface to expose the
rmnet control configuration .
******************************************************************************/
/*===========================================================================
INCLUDE FILES
===========================================================================*/
#include <sys/socket.h>
#include <stdint.h>
#include <linux/netlink.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include "rmnetcli.h"
#include "librmnetctl.h"
#define RMNET_MAX_STR_LEN 16
#define _RMNETCLI_CHECKNULL(X) do { if (!X) { \
print_rmnet_api_status(RMNETCTL_INVALID_ARG, RMNETCTL_CFG_FAILURE_NO_COMMAND); \
rmnetctl_cleanup(handle); \
return RMNETCTL_INVALID_ARG; \
} } while (0);
#define _STRTOUI32(X) (uint32_t)strtoul(X, NULL, 0)
#define _STRTOUI16(X) (uint16_t)strtoul(X, NULL, 0)
#define _STRTOUI8(X) (uint8_t)strtoul(X, NULL, 0)
#define _STRTOI32(X) (int32_t)strtol(X, NULL, 0)
#define _5TABS "\n\t\t\t\t\t"
#define _2TABS "\n\t\t"
/*!
* @brief Contains a list of error message from CLI
*/
char rmnetcfg_error_code_text
[RMNETCFG_TOTAL_ERR_MSGS][RMNETCTL_ERR_MSG_SIZE] = {
"Help option Specified",
"ERROR: No\\Invalid command was specified\n",
"ERROR: Could not allocate buffer for Egress device\n"
};
/*!
* @brief Method to display the syntax for the commands
* @details Displays the syntax and usage for the commands
* @param void
* @return void
*/
static void rmnet_api_usage(void)
{
printf("RmNet API Usage:\n\n");
printf("rmnetcli help Displays this help\n");
printf("\n");
printf("rmnetcli assocnetdev <dev_name> Registers the RmNet");
printf(_5TABS" data driver on a particular");
printf(_5TABS" device.dev_name cannot");
printf(_5TABS" be larger than 15");
printf(_5TABS" characters. Returns");
printf(_5TABS" the status code.\n\n");
printf("rmnetcli unassocnetdev <dev_name> Unregisters the");
printf(_5TABS" RmNet data driver on a particular");
printf(_5TABS" device. dev_name cannot");
printf(_5TABS" be larger than 15");
printf(_5TABS" characters. Returns");
printf(_5TABS" the status code.\n\n");
printf("rmnetcli getnetdevassoc <dev_name> Get if the RmNet");
printf(_5TABS" data driver is registered on");
printf(_5TABS" a particular device.");
printf(_5TABS" dev_name cannot be");
printf(_5TABS" larger than 15");
printf(_5TABS" characters. Returns 1");
printf(_5TABS" if is registered and");
printf(_5TABS" 0 if it is not");
printf(_5TABS" registered\n\n");
printf("rmnetcli setledf <egress_flags> Sets the egress data");
printf(_2TABS" <agg_size> format for a particular link.");
printf(_2TABS" <agg_count> dev_name cannot be larger");
printf(_2TABS" <dev_name> than 15 characters.");
printf(_5TABS" Returns the status code\n\n");
printf("rmnetcli getledf <dev_name> Gets the egress data");
printf(_5TABS" format for a particular link.");
printf(_5TABS" dev_name cannot be larger");
printf(_5TABS" than 15. Returns the 4");
printf(_5TABS" byte unsigned integer");
printf(_5TABS" egress_flags\n\n");
printf("rmnetcli setlidf <ingress_flags> Sets the ingress");
printf(_2TABS" <tail_spacing> data format for a particular");
printf(_2TABS" <dev_name> link. ingress_flags is 4");
printf(_5TABS" byte unsigned integer.");
printf(_5TABS" tail_spacing is a one.");
printf(_5TABS" byte unsigned integer.");
printf(_5TABS" dev_name cannot be");
printf(_5TABS" larger than 15.");
printf(_5TABS" characters. Returns");
printf(_5TABS" the status code\n\n");
printf("rmnetcli getlidf <dev_name> Gets the ingress");
printf(_5TABS" data format for a particular");
printf(_5TABS" link. dev_name cannot be");
printf(_5TABS" larger than 15. Returns");
printf(_5TABS" the 4 byte unsigned");
printf(_5TABS" integer ingress_flags\n\n");
printf("rmnetcli setlepc <logical_ep_id> Sets the logical");
printf(_2TABS" <rmnet_mode> endpoint configuration for");
printf(_2TABS" <dev_name> a particular link.");
printf(_2TABS" <egress_dev_name> logical_ep_id are 32bit");
printf(_5TABS" integers from -1 to 31.");
printf(_5TABS" rmnet_mode is a 1 byte");
printf(_5TABS" unsigned integer of");
printf(_5TABS" value none, vnd or");
printf(_5TABS" bridged. dev_name");
printf(_5TABS" and egress_dev_name");
printf(_5TABS" cannot be larger");
printf(_5TABS" than 15 characters");
printf(_5TABS" Returns the status code\n\n");
printf("rmnetcli unsetlepc <logical_ep_id> Un-sets the logical");
printf(_2TABS" <dev_name> endpoint configuration for");
printf(_5TABS" a particular link.");
printf(_5TABS" integers from -1 to 31.");
printf(_5TABS" dev_name cannot be larger");
printf(_5TABS" than 15 characters");
printf(_5TABS" Returns the status code\n\n");
printf("rmnetcli getlepc <logical_ep_id> Sets the logical");
printf(_2TABS" <dev_name> endpoint configuration for a");
printf(_5TABS" particular link.");
printf(_5TABS" logical_ep_id are 32bit");
printf(_5TABS" integers from -1 to 31.");
printf(_5TABS" Returns the rmnet_mode");
printf(_5TABS" and egress_dev_name.");
printf(_5TABS" rmnet_mode is a 1");
printf(_5TABS" byte unsigned integer");
printf(_5TABS" of value none, vnd or");
printf(_5TABS" bridged. dev_name and");
printf(_5TABS" egress_dev_name cannot be");
printf(_5TABS" larger than 15 ");
printf(_5TABS" characters. Returns the");
printf(_5TABS" status code\n\n");
printf("rmnetcli newvnd <dev_id> Creates a new");
printf(_5TABS" virtual network device node.");
printf(_5TABS" dev_id is an int");
printf(_5TABS" less than 32. Returns");
printf(_5TABS" the status code\n\n");
printf("rmnetcli newvndprefix <dev_id> <name_prefix> Creates");
printf(_5TABS" virtual network device node.");
printf(_5TABS" dev_id is an int");
printf(_5TABS" less than 32. Prefix");
printf(_5TABS" must be less than");
printf(_5TABS" 15 chars. Returns");
printf(_5TABS" the status code\n\n");
printf("rmnetcli getvndname <dev_id> Get name of");
printf(_5TABS" network device node from id\n\n");
printf("rmnetcli freevnd <dev_id> Removes virtual");
printf(_5TABS" network device node. dev_name");
printf(_5TABS" cannot be larger than 15.");
printf(_5TABS" Returns the status code\n\n");
printf("rmnetcli addvnctcflow <dev_id> Add a modem flow");
printf(_2TABS" <mdm_flow_hndl> handle - tc flow handle");
printf(_2TABS" <tc_flow_hndl> mapping for a virtual network");
printf(_2TABS" device node\n\n");
printf("rmnetcli delvnctcflow <dev_id> Delete a modem flow");
printf(_2TABS" <mdm_flow_hndl> handle - tc flow handle");
printf(_2TABS" <tc_flow_hndl> mapping for a virtual network");
printf(_2TABS" device node\n\n");
}
static void print_rmnetctl_lib_errors(uint16_t error_number)
{
if ((error_number > RMNETCTL_API_SUCCESS) &&
(error_number < RMNETCTL_API_ERR_ENUM_LENGTH)) {
printf("%s", rmnetctl_error_code_text[error_number]);
}
if ((error_number >= RMNETCFG_ERR_NUM_START) &&
(error_number < RMNETCFG_ERR_NUM_START + RMNETCFG_TOTAL_ERR_MSGS)) {
printf("%s", rmnetcfg_error_code_text
[error_number - RMNETCFG_ERR_NUM_START]);
if ((error_number == RMNETCTL_CFG_SUCCESS_HELP_COMMAND) ||
(error_number == RMNETCTL_CFG_FAILURE_NO_COMMAND))
rmnet_api_usage();
}
}
/*!
* @brief Method to check the error numbers generated from API calls
* @details Displays the error messages based on each error code
* @param error_number Error number returned from the API and the CLI
* @return void
*/
static void print_rmnet_api_status(int return_code, uint16_t error_number)
{
if (return_code == RMNETCTL_SUCCESS)
printf("SUCCESS\n");
else if (return_code == RMNETCTL_LIB_ERR) {
printf("LIBRARY ");
print_rmnetctl_lib_errors(error_number);
} else if (return_code == RMNETCTL_KERNEL_ERR)
printf("KERNEL %s", rmnetctl_error_code_text[error_number]);
else if (return_code == RMNETCTL_INVALID_ARG)
printf("INVALID_ARG\n");
}
/*!
* @brief Method to make the API calls
* @details Checks for each type of parameter and calls the appropriate
* function based on the number of parameters and parameter type
* @param argc Number of arguments which vary based on the commands
* @param argv Value of the arguments which vary based on the commands
* @return RMNETCTL_SUCCESS if successful. Relevant data might be printed
* based on the message type
* @return RMNETCTL_LIB_ERR if there was a library error. Error code will be
* printed
* @return RMNETCTL_KERNEL_ERR if there was a error in the kernel. Error code will be
* printed
* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
*/
static int rmnet_api_call(int argc, char *argv[])
{
struct rmnetctl_hndl_s *handle = NULL;
uint16_t error_number = RMNETCTL_CFG_FAILURE_NO_COMMAND;
int return_code = RMNETCTL_LIB_ERR;
if ((!argc) || (!*argv)) {
print_rmnet_api_status(RMNETCTL_LIB_ERR,
RMNETCTL_CFG_FAILURE_NO_COMMAND);
return RMNETCTL_LIB_ERR;
}
if (!strcmp(*argv, "help")) {
print_rmnet_api_status(RMNETCTL_LIB_ERR,
RMNETCTL_CFG_SUCCESS_HELP_COMMAND);
return RMNETCTL_LIB_ERR;
}
return_code = rmnetctl_init(&handle, &error_number);
if (return_code!= RMNETCTL_SUCCESS) {
print_rmnet_api_status(return_code, error_number);
return RMNETCTL_LIB_ERR;
}
error_number = RMNETCTL_CFG_FAILURE_NO_COMMAND;
return_code = RMNETCTL_LIB_ERR;
if (!strcmp(*argv, "assocnetdev")) {
return_code = rmnet_associate_network_device(handle,
argv[1], &error_number, RMNETCTL_DEVICE_ASSOCIATE);
} else if (!strcmp(*argv, "unassocnetdev")) {
return_code = rmnet_associate_network_device(handle,
argv[1], &error_number, RMNETCTL_DEVICE_UNASSOCIATE);
} else if (!strcmp(*argv, "getnetdevassoc")) {
int register_status;
return_code = rmnet_get_network_device_associated(handle,
argv[1], &register_status, &error_number);
if (return_code == RMNETCTL_SUCCESS)
printf("register_status is %d\n", register_status);
} else if (!strcmp(*argv, "getledf")) {
uint32_t egress_flags;
uint16_t agg_size, agg_count;
return_code = rmnet_get_link_egress_data_format(handle,
argv[1], &egress_flags, &agg_size, &agg_count, &error_number);
if (return_code == RMNETCTL_SUCCESS) {
printf("egress_flags is %u\n", egress_flags);
printf("agg_size is %u\n", agg_size);
printf("agg_count is %u\n", agg_count);
}
} else if (!strcmp(*argv, "getlidf")) {
uint32_t ingress_flags;
uint8_t tail_spacing;
return_code = rmnet_get_link_ingress_data_format_tailspace(
handle, argv[1], &ingress_flags, &tail_spacing, &error_number);
if (return_code == RMNETCTL_SUCCESS) {
printf("ingress_flags is %u\n", ingress_flags);
printf("tail_spacing is %u\n", tail_spacing);
}
} else if (!strcmp(*argv, "newvndprefix")) {
_RMNETCLI_CHECKNULL(argv[1]);
_RMNETCLI_CHECKNULL(argv[2]);
return_code = rmnet_new_vnd_prefix(handle,
_STRTOUI32(argv[1]), &error_number, RMNETCTL_NEW_VND, argv[2]);
} else if (!strcmp(*argv, "newvnd")) {
_RMNETCLI_CHECKNULL(argv[1]);
return_code = rmnet_new_vnd(handle,
_STRTOUI32(argv[1]), &error_number, RMNETCTL_NEW_VND);
} else if (!strcmp(*argv, "getvndname")) {
char buffer[32];
memset(buffer, 0, 32);
_RMNETCLI_CHECKNULL(argv[1]);
return_code = rmnet_get_vnd_name(handle, _STRTOUI32(argv[1]),
&error_number, buffer, 32);
if (return_code == RMNETCTL_SUCCESS) {
printf("VND name: %s\n", buffer);
}
} else if (!strcmp(*argv, "freevnd")) {
_RMNETCLI_CHECKNULL(argv[1]);
return_code = rmnet_new_vnd(handle,
_STRTOUI32(argv[1]), &error_number, RMNETCTL_FREE_VND);
} else if (!strcmp(*argv, "setlidf")) {
_RMNETCLI_CHECKNULL(argv[1]);
_RMNETCLI_CHECKNULL(argv[2]);
_RMNETCLI_CHECKNULL(argv[3]);
return_code = rmnet_set_link_ingress_data_format_tailspace(
handle, _STRTOUI32(argv[1]), _STRTOUI8(argv[2]), argv[3],
&error_number);
} else if (!strcmp(*argv, "delvnctcflow")) {
_RMNETCLI_CHECKNULL(argv[1]);
_RMNETCLI_CHECKNULL(argv[2]);
_RMNETCLI_CHECKNULL(argv[3]);
return_code = rmnet_add_del_vnd_tc_flow(handle,
_STRTOUI32(argv[1]), _STRTOUI32(argv[2]), _STRTOUI32(argv[3]),
RMNETCTL_DEL_FLOW, &error_number);
} else if (!strcmp(*argv, "getlepc")) {
_RMNETCLI_CHECKNULL(argv[1]);
uint8_t rmnet_mode;
char *egress_dev_name;
egress_dev_name = NULL;
egress_dev_name = (char *)malloc(RMNET_MAX_STR_LEN
* sizeof(char));
if (!egress_dev_name) {
print_rmnet_api_status(RMNETCTL_LIB_ERR,
RMNETCTL_CFG_FAILURE_EGRESS_DEV_NAME_NULL);
rmnetctl_cleanup(handle);
return RMNETCTL_LIB_ERR;
}
return_code = rmnet_get_logical_ep_config(handle,
_STRTOI32(argv[1]), argv[2], &rmnet_mode,
&egress_dev_name, RMNET_MAX_STR_LEN, &error_number);
if (return_code == RMNETCTL_SUCCESS) {
printf("rmnet_mode is %u\n", rmnet_mode);
printf("egress_dev_name is %s\n", egress_dev_name);
}
free(egress_dev_name);
} else if (!strcmp(*argv, "addvnctcflow")) {
_RMNETCLI_CHECKNULL(argv[1]);
_RMNETCLI_CHECKNULL(argv[2]);
_RMNETCLI_CHECKNULL(argv[3]);
return_code = rmnet_add_del_vnd_tc_flow(handle,
_STRTOUI32(argv[1]), _STRTOUI32(argv[2]), _STRTOUI32(argv[3]),
RMNETCTL_ADD_FLOW, &error_number);
} else if (!strcmp(*argv, "setledf")) {
_RMNETCLI_CHECKNULL(argv[1]);
_RMNETCLI_CHECKNULL(argv[2]);
_RMNETCLI_CHECKNULL(argv[3]);
return_code = rmnet_set_link_egress_data_format(handle,
_STRTOUI32(argv[1]), _STRTOUI16(argv[2]), _STRTOUI16(argv[3]),
argv[4], &error_number);
} else if (!strcmp(*argv, "setlepc")) {
_RMNETCLI_CHECKNULL(argv[1]);
_RMNETCLI_CHECKNULL(argv[2]);
return_code = rmnet_set_logical_ep_config(handle,
_STRTOI32(argv[1]), _STRTOUI8(argv[2]), argv[3], argv[4],
&error_number);
} else if (!strcmp(*argv, "unsetlepc")) {
_RMNETCLI_CHECKNULL(argv[1]);
return_code = rmnet_unset_logical_ep_config(handle,
_STRTOI32(argv[1]), argv[2], &error_number);
}
print_rmnet_api_status(return_code, error_number);
rmnetctl_cleanup(handle);
return return_code;
}
/*!
* @brief Method which serves as en entry point to the rmnetcli function
* @details Entry point for the RmNet Netlink API. This is the command line
* interface for the RmNet API
* @param argc Number of arguments which vary based on the commands
* @param argv Value of the arguments which vary based on the commands
* @return RMNETCTL_SUCCESS if successful. Relevant data might be printed
* based on the message type
* @return RMNETCTL_LIB_ERR if there was a library error. Error code will be
* printed
* @return RMNETCTL_KERNEL_ERR if there was a error in the kernel. Error code will be
* printed
* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
*/
int main(int argc, char *argv[])
{
argc--;
argv++;
return rmnet_api_call(argc, argv);
}

View File

@@ -1,61 +0,0 @@
/******************************************************************************
R M N E T C L I . H
Copyright (c) 2013, 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 rmnetcli.h
@brief headers for the command line interface to expose rmnet control API's
DESCRIPTION
Header file containing definition for the command line interface to expose
rmnet control API's
******************************************************************************/
#ifndef RMNETCLI_H
#define RMNETCLI_H
/* Print the help for the commands since the help flag was used. */
#define RMNETCTL_CFG_SUCCESS_HELP_COMMAND 100
/* No/invalid API call was specified. So return an error. */
#define RMNETCTL_CFG_FAILURE_NO_COMMAND 101
/* The buffer for egress device name was NULL */
#define RMNETCTL_CFG_FAILURE_EGRESS_DEV_NAME_NULL 102
/* This should always be the value of the starting element */
#define RMNETCFG_ERR_NUM_START 100
/* This should always be the total number of error message from CLI */
#define RMNETCFG_TOTAL_ERR_MSGS 3
#endif /* not defined RMNETCLI_H */

View File

@@ -1,499 +0,0 @@
/******************************************************************************
L I B R M N E T C T L . H
Copyright (c) 2013-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 librmnetctl.h
* @brief rmnet control API's header file
*/
#ifndef LIBRMNETCTL_H
#define LIBRMNETCTL_H
/* RMNET API succeeded */
#define RMNETCTL_SUCCESS 0
/* RMNET API encountered an error while executing within the library. Check the
* error code in this case */
#define RMNETCTL_LIB_ERR 1
/* RMNET API encountered an error while executing in the kernel. Check the
* error code in this case */
#define RMNETCTL_KERNEL_ERR 2
/* RMNET API encountered an error because of invalid arguments*/
#define RMNETCTL_INVALID_ARG 3
/* Flag to associate a network device*/
#define RMNETCTL_DEVICE_ASSOCIATE 1
/* Flag to unassociate a network device*/
#define RMNETCTL_DEVICE_UNASSOCIATE 0
/* Flag to create a new virtual network device*/
#define RMNETCTL_NEW_VND 1
/* Flag to free a new virtual network device*/
#define RMNETCTL_FREE_VND 0
/* Flag to add a new flow*/
#define RMNETCTL_ADD_FLOW 1
/* Flag to delete an existing flow*/
#define RMNETCTL_DEL_FLOW 0
enum rmnetctl_error_codes_e {
/* API succeeded. This should always be the first element. */
RMNETCTL_API_SUCCESS = 0,
RMNETCTL_API_FIRST_ERR = 1,
/* API failed because not enough memory to create buffer to send
* message */
RMNETCTL_API_ERR_REQUEST_INVALID = RMNETCTL_API_FIRST_ERR,
/* API failed because not enough memory to create buffer for the
* response message */
RMNETCTL_API_ERR_RESPONSE_INVALID = 2,
/* API failed because could not send the message to kernel */
RMNETCTL_API_ERR_MESSAGE_SEND = 3,
/* API failed because could not receive message from the kernel */
RMNETCTL_API_ERR_MESSAGE_RECEIVE = 4,
RMNETCTL_INIT_FIRST_ERR = 5,
/* Invalid process id. So return an error. */
RMNETCTL_INIT_ERR_PROCESS_ID = RMNETCTL_INIT_FIRST_ERR,
/* Invalid socket descriptor id. So return an error. */
RMNETCTL_INIT_ERR_NETLINK_FD = 6,
/* Could not bind the socket to the Netlink file descriptor */
RMNETCTL_INIT_ERR_BIND = 7,
/* Invalid user id. Only root has access to this function. (NA) */
RMNETCTL_INIT_ERR_INVALID_USER = 8,
RMNETCTL_API_SECOND_ERR = 9,
/* API failed because the RmNet handle for the transaction was NULL */
RMNETCTL_API_ERR_HNDL_INVALID = RMNETCTL_API_SECOND_ERR,
/* API failed because the request buffer for the transaction was NULL */
RMNETCTL_API_ERR_REQUEST_NULL = 10,
/* API failed because the response buffer for the transaction was NULL*/
RMNETCTL_API_ERR_RESPONSE_NULL = 11,
/* API failed because the request and response type do not match*/
RMNETCTL_API_ERR_MESSAGE_TYPE = 12,
/* API failed because the return type is invalid */
RMNETCTL_API_ERR_RETURN_TYPE = 13,
/* API failed because the string was truncated */
RMNETCTL_API_ERR_STRING_TRUNCATION = 14,
/* These error are 1-to-1 with rmnet_data config errors in rmnet_data.h
for each conversion.
please keep the enums synced.
*/
RMNETCTL_KERNEL_FIRST_ERR = 15,
/* No error */
RMNETCTL_KERNEL_ERROR_NO_ERR = RMNETCTL_KERNEL_FIRST_ERR,
/* Invalid / unsupported message */
RMNETCTL_KERNEL_ERR_UNKNOWN_MESSAGE = 16,
/* Internal problem in the kernel module */
RMNETCTL_KERNEL_ERR_INTERNAL = 17,
/* Kernel is temporarily out of memory */
RMNETCTL_KERNEL_ERR_OUT_OF_MEM = 18,
/* Device already exists / Still in use */
RMETNCTL_KERNEL_ERR_DEVICE_IN_USE = 19,
/* Invalid request / Unsupported scenario */
RMNETCTL_KERNEL_ERR_INVALID_REQUEST = 20,
/* Device doesn't exist */
RMNETCTL_KERNEL_ERR_NO_SUCH_DEVICE = 21,
/* One or more of the arguments is invalid */
RMNETCTL_KERNEL_ERR_BAD_ARGS = 22,
/* Egress device is invalid */
RMNETCTL_KERNEL_ERR_BAD_EGRESS_DEVICE = 23,
/* TC handle is full */
RMNETCTL_KERNEL_ERR_TC_HANDLE_FULL = 24,
/* This should always be the last element */
RMNETCTL_API_ERR_ENUM_LENGTH
};
#define RMNETCTL_ERR_MSG_SIZE 100
/*!
* @brief Contains a list of error message from API
*/
char rmnetctl_error_code_text
[RMNETCTL_API_ERR_ENUM_LENGTH][RMNETCTL_ERR_MSG_SIZE] = {
"ERROR: API succeeded\n",
"ERROR: Unable to allocate the buffer to send message\n",
"ERROR: Unable to allocate the buffer to receive message\n",
"ERROR: Could not send the message to kernel\n",
"ERROR: Unable to receive message from the kernel\n",
"ERROR: Invalid process id\n",
"ERROR: Invalid socket descriptor id\n",
"ERROR: Could not bind to netlink socket\n",
"ERROR: Only root can access this API\n",
"ERROR: RmNet handle for the transaction was NULL\n",
"ERROR: Request buffer for the transaction was NULL\n",
"ERROR: Response buffer for the transaction was NULL\n",
"ERROR: Request and response type do not match\n",
"ERROR: Return type is invalid\n",
"ERROR: String was truncated\n",
/* Kernel errors */
"ERROR: Kernel call succeeded\n",
"ERROR: Invalid / Unsupported directive\n",
"ERROR: Internal problem in the kernel module\n",
"ERROR: The kernel is temporarily out of memory\n",
"ERROR: Device already exists / Still in use\n",
"ERROR: Invalid request / Unsupported scenario\n",
"ERROR: Device doesn't exist\n",
"ERROR: One or more of the arguments is invalid\n",
"ERROR: Egress device is invalid\n",
"ERROR: TC handle is full\n"
};
/*===========================================================================
DEFINITIONS AND DECLARATIONS
===========================================================================*/
typedef struct rmnetctl_hndl_s rmnetctl_hndl_t;
/*!
* @brief Public API to initialize the RMNET control driver
* @details Allocates memory for the RmNet handle. Creates and binds to a and
* netlink socket if successful
* @param **rmnetctl_hndl_t_val RmNet handle to be initialized
* @return RMNETCTL_SUCCESS if successful
* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
* @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
* Check error_code
* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
*/
int rmnetctl_init(rmnetctl_hndl_t **hndl, uint16_t *error_code);
/*!
* @brief Public API to clean up the RmNeT control handle
* @details Close the socket and free the RmNet handle
* @param *rmnetctl_hndl_t_val RmNet handle to be initialized
* @return void
*/
void rmnetctl_cleanup(rmnetctl_hndl_t *hndl);
/*!
* @brief Public API to register/unregister a RMNET driver on a particular device
* @details Message type is RMNET_NETLINK_ASSOCIATE_NETWORK_DEVICE or
* RMNET_NETLINK_UNASSOCIATE_NETWORK_DEVICE based on the flag for assoc_dev
* @param *rmnetctl_hndl_t_val RmNet handle for the Netlink message
* @param dev_name Device on which to register the RmNet driver
* @param error_code Status code of this operation
* @param assoc_dev registers the device if RMNETCTL_DEVICE_ASSOCIATE or
* unregisters the device if RMNETCTL_DEVICE_UNASSOCIATE
* @return RMNETCTL_SUCCESS if successful
* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
* @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
* Check error_code
* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
*/
int rmnet_associate_network_device(rmnetctl_hndl_t *hndl,
const char *dev_name,
uint16_t *error_code,
uint8_t assoc_dev);
/*!
* @brief Public API to get if a RMNET driver is registered on a particular
* device
* @details Message type is RMNET_NETLINK_GET_NETWORK_DEVICE_ASSOCIATED.
* @param *rmnetctl_hndl_t_val RmNet handle for the Netlink message
* @param dev_name Device on which to check if the RmNet driver is registered
* @param register_status 1 if RmNet data driver is registered on a particular
* device, 0 if not
* @param error_code Status code of this operation
* @return RMNETCTL_SUCCESS if successful
* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
* @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
* Check error_code
* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
*/
int rmnet_get_network_device_associated(rmnetctl_hndl_t *hndl,
const char *dev_name,
int *register_status,
uint16_t *error_code);
/*!
* @brief Public API to set the egress data format for a particular link.
* @details Message type is RMNET_NETLINK_SET_LINK_EGRESS_DATA_FORMAT.
* @param *rmnetctl_hndl_t_val RmNet handle for the Netlink message
* @param egress_flags Egress flags to be set on the device
* @param agg_size Max size of aggregated packets
* @param agg_count Number of packets to be aggregated
* @param dev_name Device on which to set the egress data format
* @param error_code Status code of this operation returned from the kernel
* @return RMNETCTL_SUCCESS if successful
* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
* @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
* Check error_code
* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
*/
int rmnet_set_link_egress_data_format(rmnetctl_hndl_t *hndl,
uint32_t egress_flags,
uint16_t agg_size,
uint16_t agg_count,
const char *dev_name,
uint16_t *error_code);
/*!
* @brief Public API to get the egress data format for a particular link.
* @details Message type is RMNET_NETLINK_GET_LINK_EGRESS_DATA_FORMAT.
* @param *rmnetctl_hndl_t_val RmNet handle for the Netlink message
* @param dev_name Device on which to get the egress data format
* @param egress_flags Egress flags from the device
* @param agg_count Number of packets to be aggregated
* @param error_code Status code of this operation returned from the kernel
* @return RMNETCTL_SUCCESS if successful
* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
* @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
* Check error_code
* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
*/
int rmnet_get_link_egress_data_format(rmnetctl_hndl_t *hndl,
const char *dev_name,
uint32_t *egress_flags,
uint16_t *agg_size,
uint16_t *agg_count,
uint16_t *error_code);
/*!
* @brief Public API to set the ingress data format for a particular link.
* @details Message type is RMNET_NETLINK_SET_LINK_INGRESS_DATA_FORMAT.
* @param *rmnetctl_hndl_t_val RmNet handle for the Netlink message
* @param ingress_flags Ingress flags from the device
* @param tail_spacing Tail spacing needed for the packet
* @param dev_name Device on which to set the ingress data format
* @param error_code Status code of this operation returned from the kernel
* @return RMNETCTL_SUCCESS if successful
* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
* @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
* Check error_code
* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
*/
int rmnet_set_link_ingress_data_format_tailspace(rmnetctl_hndl_t *hndl,
uint32_t ingress_flags,
uint8_t tail_spacing,
const char *dev_name,
uint16_t *error_code);
/*!
* @brief Public API to get the ingress data format for a particular link.
* @details Message type is RMNET_NETLINK_GET_LINK_INGRESS_DATA_FORMAT.
* @param *rmnetctl_hndl_t_val RmNet handle for the Netlink message
* @param dev_name Device on which to get the ingress data format
* @param ingress_flags Ingress flags from the device
* @param tail_spacing Tail spacing needed for the packet
* @param error_code Status code of this operation returned from the kernel
* @return RMNETCTL_SUCCESS if successful
* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
* @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
* Check error_code
* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
*/
int rmnet_get_link_ingress_data_format_tailspace(rmnetctl_hndl_t *hndl,
const char *dev_name,
uint32_t *ingress_flags,
uint8_t *tail_spacing,
uint16_t *error_code);
inline int rmnet_set_link_ingress_data_format(rmnetctl_hndl_t *hndl,
uint32_t ingress_flags,
const char *dev_name,
uint16_t *error_code)
{
return rmnet_set_link_ingress_data_format_tailspace(hndl,
ingress_flags,
0,
dev_name,
error_code);
}
inline int rmnet_get_link_ingress_data_format(rmnetctl_hndl_t *hndl,
const char *dev_name,
uint32_t *ingress_flags,
uint16_t *error_code)
{
return rmnet_get_link_ingress_data_format_tailspace(hndl,
dev_name,
ingress_flags,
0,
error_code);
}
/*!
* @brief Public API to set the logical endpoint configuration for a
* particular link.
* @details Message type is RMNET_NETLINK_SET_LOGICAL_EP_CONFIG.
* @param *rmnetctl_hndl_t_val RmNet handle for the Netlink message
* @param logical_ep_id Logical end point id on which the configuration is to be
* set
* @param rmnet_mode RmNet mode to be set on the device
* @param dev_name Device on which to set the logical end point configuration
* @param egress_dev_name Egress Device if operating in bridge mode
* @param error_code Status code of this operation returned from the kernel
* @return RMNETCTL_SUCCESS if successful
* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
* @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
* Check error_code
* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
*/
int rmnet_set_logical_ep_config(rmnetctl_hndl_t *hndl,
int32_t ep_id,
uint8_t operating_mode,
const char *dev_name,
const char *next_dev,
uint16_t *error_code);
/*!
* @brief Public API to un-set the logical endpoint configuration for a
* particular link.
* @details Message type is RMNET_NETLINK_UNSET_LOGICAL_EP_CONFIG.
* @param *rmnetctl_hndl_t_val RmNet handle for the Netlink message
* @param logical_ep_id Logical end point id on which the configuration is to be
* un-set
* @param dev_name Device on which to un-set the logical end point configuration
* @param error_code Status code of this operation returned from the kernel
* @return RMNETCTL_SUCCESS if successful
* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
* @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
* Check error_code
* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
*/
int rmnet_unset_logical_ep_config(rmnetctl_hndl_t *hndl,
int32_t ep_id,
const char *dev_name,
uint16_t *error_code);
/*!
* @brief Public API to get the logical endpoint configuration for a
* particular link.
* @details Message type is RMNET_NETLINK_GET_LOGICAL_EP_CONFIG.
* @param *rmnetctl_hndl_t_val RmNet handle for the Netlink message
* @param logical_ep_id Logical end point id from which to get the configuration
* @param dev_name Device on which to get the logical end point configuration
* @param rmnet_mode RmNet mode from the device
* @param next_dev Egress Device name
* @param next_dev_len Egress Device I/O string len
* @param error_code Status code of this operation returned from the kernel
* @return RMNETCTL_SUCCESS if successful
* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
* @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
* Check error_code
* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
*/
int rmnet_get_logical_ep_config(rmnetctl_hndl_t *hndl,
int32_t ep_id,
const char *dev_name,
uint8_t *operating_mode,
char **next_dev,
uint32_t next_dev_len,
uint16_t *error_code);
/*!
* @brief Public API to create a new virtual device node
* @details Message type is RMNET_NETLINK_NEW_VND or
* RMNETCTL_FREE_VND based on the flag for new_vnd
* @param hndl RmNet handle for the Netlink message
* @param id Node number to create the virtual network device node
* @param error_code Status code of this operation returned from the kernel
* @param new_vnd creates a new virtual network device if RMNETCTL_NEW_VND or
* frees the device if RMNETCTL_FREE_VND
* @return RMNETCTL_SUCCESS if successful
* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
* @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
* Check error_code
* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
*/
int rmnet_new_vnd(rmnetctl_hndl_t *hndl,
uint32_t id,
uint16_t *error_code,
uint8_t new_vnd);
/*!
* @brief Public API to create a new virtual device node with a custom prefix
* @details Message type is RMNET_NETLINK_NEW_VND or
* RMNETCTL_FREE_VND based on the flag for new_vnd
* @param hndl RmNet handle for the Netlink message
* @param id Node number to create the virtual network device node
* @param error_code Status code of this operation returned from the kernel
* @param new_vnd creates a new virtual network device if RMNETCTL_NEW_VND or
* frees the device if RMNETCTL_FREE_VND
* @param prefix Prefix to be used when naming the network interface
* @return RMNETCTL_SUCCESS if successful
* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
* @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
* Check error_code
* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
*/
int rmnet_new_vnd_prefix(rmnetctl_hndl_t *hndl,
uint32_t id,
uint16_t *error_code,
uint8_t new_vnd,
const char *prefix);
/*!
* @brief API to get the ASCII name of a virtual network device from its ID
* @param hndl RmNet handle for the Netlink message
* @param id Node number to create the virtual network device node
* @param error_code Status code of this operation returned from the kernel
* @param buf Buffer to store ASCII representation of device name
* @param buflen Length of the buffer
* @param prefix Prefix to be used when naming the network interface
* @return RMNETCTL_SUCCESS if successful
* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
* @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
* Check error_code
* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
*/
int rmnet_get_vnd_name(rmnetctl_hndl_t *hndl,
uint32_t id,
uint16_t *error_code,
char *buf,
uint32_t buflen);
/*!
* @brief Public API to set or clear a flow
* @details Message type is RMNET_NETLINK_ADD_VND_TC_FLOW or
* RMNET_NETLINK_DEL_VND_TC_FLOW based on the flag for set_flow
* @param *rmnetctl_hndl_t_val RmNet handle for the Netlink message
* @param id Node number to set or clear the flow on the virtual network
* device node
* @param map_flow_id Flow handle of the modem
* @param tc_flow_id Software flow handle
* @param set_flow sets the flow if RMNET_NETLINK_SET_FLOW or
* clears the flow if RMNET_NETLINK_CLEAR_FLOW
* @return RMNETCTL_SUCCESS if successful
* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
* @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
* Check error_code
* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
*/
int rmnet_add_del_vnd_tc_flow(rmnetctl_hndl_t *hndl,
uint32_t id,
uint32_t map_flow_id,
uint32_t tc_flow_id,
uint8_t set_flow,
uint16_t *error_code);
#endif /* not defined LIBRMNETCTL_H */

View File

@@ -1,65 +0,0 @@
/******************************************************************************
L I B R M N E T C T L _ H N D L. H
Copyright (c) 2013, 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 librmnetctl_hndl.h
* @brief rmnet control API's handle file
*/
#ifndef LIBRMNETCTL_HNDL_H
#define LIBRMNETCTL_HNDL_H
/*===========================================================================
DEFINITIONS AND DECLARATIONS
===========================================================================*/
/*!
* @brief Structure for RMNET control handles. A rmnet hndl contains the caller
* process id, the transaction id which is initialized to 0 for each new
* initialized handle and the netlink file descriptor for this handle.
* @var pid process id to be used for the netlink message
* @var transaction_id message number for debugging
* @var netlink_fd netlink file descriptor to be used
* @var src_addr source socket address properties for this message
* @var dest_addr destination socket address properties for this message
*/
struct rmnetctl_hndl_s {
uint32_t pid;
uint32_t transaction_id;
int netlink_fd;
struct sockaddr_nl src_addr, dest_addr;
};
#endif /* not defined LIBRMNETCTL_HNDL_H */

View File

@@ -1,22 +0,0 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_COPY_HEADERS_TO := dataservices/rmnetctl
LOCAL_COPY_HEADERS := ../inc/librmnetctl.h
LOCAL_SRC_FILES := librmnetctl.c
LOCAL_CFLAGS := -Wall -Werror
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../inc
LOCAL_C_INCLUDES += $(LOCAL_PATH)
ifeq ($(TARGET_COMPILE_WITH_MSM_KERNEL),true)
LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
endif
LOCAL_CLANG := true
LOCAL_MODULE := librmnetctl
LOCAL_MODULE_TAGS := optional
LOCAL_PRELINK_MODULE := false
include $(BUILD_SHARED_LIBRARY)

View File

@@ -1,16 +0,0 @@
AM_CFLAGS = -Wall -Werror -Wundef -Wstrict-prototypes -Wno-trigraphs
AM_CFLAGS += -I./../inc
librmnetctl_la_C = @C@
librmnetctl_la_SOURCES = librmnetctl.c
common_CFLAGS = -DUSE_GLIB @GLIB_CFLAGS@
common_LDFLAGS = -lpthread -lrt @GLIB_LIBS@
librmnetctl_la_CFLAGS := $(AM_CFLAGS) $(common_CFLAGS)
librmnetctl_la_LDFLAGS := -shared $(common_LDFLAGS)
library_includedir = $(pkgincludedir)
library_include_HEADERS = ./../inc/librmnetctl.h
lib_LTLIBRARIES = librmnetctl.la

View File

@@ -1,896 +0,0 @@
/******************************************************************************
L I B R M N E T C T L . C
Copyright (c) 2013-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 librmnetctl.c
* @brief rmnet control API's implementation file
*/
/*===========================================================================
INCLUDE FILES
===========================================================================*/
#include <sys/socket.h>
#include <stdint.h>
#include <linux/netlink.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <linux/rmnet_data.h>
#include "librmnetctl_hndl.h"
#include "librmnetctl.h"
#ifdef USE_GLIB
#include <glib.h>
#define strlcpy g_strlcpy
#endif
#define RMNETCTL_SOCK_FLAG 0
#define ROOT_USER_ID 0
#define MIN_VALID_PROCESS_ID 0
#define MIN_VALID_SOCKET_FD 0
#define KERNEL_PROCESS_ID 0
#define UNICAST 0
#define MAX_BUF_SIZE sizeof(struct nlmsghdr) + sizeof(struct rmnet_nl_msg_s)
#define INGRESS_FLAGS_MASK (RMNET_INGRESS_FIX_ETHERNET | \
RMNET_INGRESS_FORMAT_MAP | \
RMNET_INGRESS_FORMAT_DEAGGREGATION | \
RMNET_INGRESS_FORMAT_DEMUXING | \
RMNET_INGRESS_FORMAT_MAP_COMMANDS | \
RMNET_INGRESS_FORMAT_MAP_CKSUMV3 | \
RMNET_INGRESS_FORMAT_MAP_CKSUMV4)
#define EGRESS_FLAGS_MASK (RMNET_EGRESS_FORMAT__RESERVED__ | \
RMNET_EGRESS_FORMAT_MAP | \
RMNET_EGRESS_FORMAT_AGGREGATION | \
RMNET_EGRESS_FORMAT_MUXING | \
RMNET_EGRESS_FORMAT_MAP_CKSUMV3 | \
RMNET_EGRESS_FORMAT_MAP_CKSUMV4)
#define min(a, b) (((a) < (b)) ? (a) : (b))
/*===========================================================================
LOCAL FUNCTION DEFINITIONS
===========================================================================*/
/*!
* @brief Synchronous method to send and receive messages to and from the kernel
* using netlink sockets
* @details Increments the transaction id for each message sent to the kernel.
* Sends the netlink message to the kernel and receives the response from the
* kernel.
* @param *hndl RmNet handle for this transaction
* @param request Message to be sent to the kernel
* @param response Message received from the kernel
* @return RMNETCTL_API_SUCCESS if successfully able to send and receive message
* from the kernel
* @return RMNETCTL_API_ERR_HNDL_INVALID if RmNet handle for the transaction was
* NULL
* @return RMNETCTL_API_ERR_REQUEST_NULL not enough memory to create buffer for
* sending the message
* @return RMNETCTL_API_ERR_MESSAGE_SEND if could not send the message to kernel
* @return RMNETCTL_API_ERR_MESSAGE_RECEIVE if could not receive message from the
* kernel
* @return RMNETCTL_API_ERR_MESSAGE_TYPE if the request and response type do not
* match
*/
static uint16_t rmnetctl_transact(rmnetctl_hndl_t *hndl,
struct rmnet_nl_msg_s *request,
struct rmnet_nl_msg_s *response) {
uint8_t *request_buf, *response_buf;
struct nlmsghdr *nlmsghdr_val;
struct rmnet_nl_msg_s *rmnet_nl_msg_s_val;
ssize_t bytes_read = -1;
uint16_t return_code = RMNETCTL_API_ERR_HNDL_INVALID;
struct sockaddr_nl* __attribute__((__may_alias__)) saddr_ptr;
request_buf = NULL;
response_buf = NULL;
nlmsghdr_val = NULL;
rmnet_nl_msg_s_val = NULL;
do {
if (!hndl){
break;
}
if (!request){
return_code = RMNETCTL_API_ERR_REQUEST_NULL;
break;
}
if (!response){
return_code = RMNETCTL_API_ERR_RESPONSE_NULL;
break;
}
request_buf = (uint8_t *)malloc(MAX_BUF_SIZE * sizeof(uint8_t));
if (!request_buf){
return_code = RMNETCTL_API_ERR_REQUEST_NULL;
break;
}
response_buf = (uint8_t *)malloc(MAX_BUF_SIZE * sizeof(uint8_t));
if (!response_buf) {
return_code = RMNETCTL_API_ERR_RESPONSE_NULL;
break;
}
nlmsghdr_val = (struct nlmsghdr *)request_buf;
rmnet_nl_msg_s_val = (struct rmnet_nl_msg_s *)NLMSG_DATA(request_buf);
memset(request_buf, 0, MAX_BUF_SIZE*sizeof(uint8_t));
memset(response_buf, 0, MAX_BUF_SIZE*sizeof(uint8_t));
nlmsghdr_val->nlmsg_seq = hndl->transaction_id;
nlmsghdr_val->nlmsg_pid = hndl->pid;
nlmsghdr_val->nlmsg_len = MAX_BUF_SIZE;
memcpy((void *)NLMSG_DATA(request_buf), request,
sizeof(struct rmnet_nl_msg_s));
rmnet_nl_msg_s_val->crd = RMNET_NETLINK_MSG_COMMAND;
hndl->transaction_id++;
saddr_ptr = &hndl->dest_addr;
socklen_t addrlen = sizeof(struct sockaddr_nl);
if (sendto(hndl->netlink_fd,
request_buf,
MAX_BUF_SIZE,
RMNETCTL_SOCK_FLAG,
(struct sockaddr*)saddr_ptr,
sizeof(struct sockaddr_nl)) < 0) {
return_code = RMNETCTL_API_ERR_MESSAGE_SEND;
break;
}
saddr_ptr = &hndl->src_addr;
bytes_read = recvfrom(hndl->netlink_fd,
response_buf,
MAX_BUF_SIZE,
RMNETCTL_SOCK_FLAG,
(struct sockaddr*)saddr_ptr,
&addrlen);
if (bytes_read < 0) {
return_code = RMNETCTL_API_ERR_MESSAGE_RECEIVE;
break;
}
memcpy(response, (void *)NLMSG_DATA(response_buf),
sizeof(struct rmnet_nl_msg_s));
if (sizeof(*response) < sizeof(struct rmnet_nl_msg_s)) {
return_code = RMNETCTL_API_ERR_RESPONSE_NULL;
break;
}
if (request->message_type != response->message_type) {
return_code = RMNETCTL_API_ERR_MESSAGE_TYPE;
break;
}
return_code = RMNETCTL_SUCCESS;
} while(0);
free(request_buf);
free(response_buf);
return return_code;
}
/*!
* @brief Static function to check the dev name
* @details Checks if the name is not NULL and if the name is less than the
* RMNET_MAX_STR_LEN
* @param dev_name Name of the device
* @return RMNETCTL_SUCCESS if successful
* @return RMNETCTL_INVALID_ARG if invalid arguments were passed to the API
*/
static inline int _rmnetctl_check_dev_name(const char *dev_name) {
int return_code = RMNETCTL_INVALID_ARG;
do {
if (!dev_name)
break;
if (strlen(dev_name) >= RMNET_MAX_STR_LEN)
break;
return_code = RMNETCTL_SUCCESS;
} while(0);
return return_code;
}
/*!
* @brief Static function to check the string length after a copy
* @details Checks if the string length is not lesser than zero and lesser than
* RMNET_MAX_STR_LEN
* @param str_len length of the string after a copy
* @param error_code Status code of this operation
* @return RMNETCTL_SUCCESS if successful
* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
*/
static inline int _rmnetctl_check_len(size_t str_len, uint16_t *error_code) {
int return_code = RMNETCTL_LIB_ERR;
do {
if (str_len > RMNET_MAX_STR_LEN) {
*error_code = RMNETCTL_API_ERR_STRING_TRUNCATION;
break;
}
return_code = RMNETCTL_SUCCESS;
} while(0);
return return_code;
}
/*!
* @brief Static function to check the response type
* @details Checks if the response type of this message was return code
* @param crd The crd field passed
* @param error_code Status code of this operation
* @return RMNETCTL_SUCCESS if successful
* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
*/
static inline int _rmnetctl_check_code(int crd, uint16_t *error_code) {
int return_code = RMNETCTL_LIB_ERR;
do {
if (crd != RMNET_NETLINK_MSG_RETURNCODE) {
*error_code = RMNETCTL_API_ERR_RETURN_TYPE;
break;
}
return_code = RMNETCTL_SUCCESS;
} while(0);
return return_code;
}
/*!
* @brief Static function to check the response type
* @details Checks if the response type of this message was data
* @param crd The crd field passed
* @param error_code Status code of this operation
* @return RMNETCTL_SUCCESS if successful
* @return RMNETCTL_LIB_ERR if there was a library error. Check error_code
*/
static inline int _rmnetctl_check_data(int crd, uint16_t *error_code) {
int return_code = RMNETCTL_LIB_ERR;
do {
if (crd != RMNET_NETLINK_MSG_RETURNDATA) {
*error_code = RMNETCTL_API_ERR_RETURN_TYPE;
break;
}
return_code = RMNETCTL_SUCCESS;
} while(0);
return return_code;
}
/*!
* @brief Static function to set the return value
* @details Checks if the error_code from the transaction is zero for a return
* code type message and sets the message type as RMNETCTL_SUCCESS
* @param crd The crd field passed
* @param error_code Status code of this operation
* @return RMNETCTL_SUCCESS if successful
* @return RMNETCTL_KERNEL_ERR if there was an error in the kernel.
* Check error_code
*/
static inline int _rmnetctl_set_codes(int error_val, uint16_t *error_code) {
int return_code = RMNETCTL_KERNEL_ERR;
if (error_val == RMNET_CONFIG_OK)
return_code = RMNETCTL_SUCCESS;
else
*error_code = (uint16_t)error_val + RMNETCTL_KERNEL_FIRST_ERR;
return return_code;
}
/*===========================================================================
EXPOSED API
===========================================================================*/
int rmnetctl_init(rmnetctl_hndl_t **hndl, uint16_t *error_code)
{
pid_t pid = 0;
int netlink_fd = -1, return_code = RMNETCTL_LIB_ERR;
struct sockaddr_nl* __attribute__((__may_alias__)) saddr_ptr;
do {
if ((!hndl) || (!error_code)){
return_code = RMNETCTL_INVALID_ARG;
break;
}
*hndl = (rmnetctl_hndl_t *)malloc(sizeof(rmnetctl_hndl_t));
if (!*hndl) {
*error_code = RMNETCTL_API_ERR_HNDL_INVALID;
break;
}
memset(*hndl, 0, sizeof(rmnetctl_hndl_t));
pid = getpid();
if (pid < MIN_VALID_PROCESS_ID) {
free(*hndl);
*error_code = RMNETCTL_INIT_ERR_PROCESS_ID;
break;
}
(*hndl)->pid = (uint32_t)pid;
netlink_fd = socket(PF_NETLINK, SOCK_RAW, RMNET_NETLINK_PROTO);
if (netlink_fd < MIN_VALID_SOCKET_FD) {
free(*hndl);
*error_code = RMNETCTL_INIT_ERR_NETLINK_FD;
break;
}
(*hndl)->netlink_fd = netlink_fd;
memset(&(*hndl)->src_addr, 0, sizeof(struct sockaddr_nl));
(*hndl)->src_addr.nl_family = AF_NETLINK;
(*hndl)->src_addr.nl_pid = (*hndl)->pid;
saddr_ptr = &(*hndl)->src_addr;
if (bind((*hndl)->netlink_fd,
(struct sockaddr*)saddr_ptr,
sizeof(struct sockaddr_nl)) < 0) {
close((*hndl)->netlink_fd);
free(*hndl);
*error_code = RMNETCTL_INIT_ERR_BIND;
break;
}
memset(&(*hndl)->dest_addr, 0, sizeof(struct sockaddr_nl));
(*hndl)->dest_addr.nl_family = AF_NETLINK;
(*hndl)->dest_addr.nl_pid = KERNEL_PROCESS_ID;
(*hndl)->dest_addr.nl_groups = UNICAST;
return_code = RMNETCTL_SUCCESS;
} while(0);
return return_code;
}
void rmnetctl_cleanup(rmnetctl_hndl_t *hndl)
{
if (!hndl)
return;
close(hndl->netlink_fd);
free(hndl);
}
int rmnet_associate_network_device(rmnetctl_hndl_t *hndl,
const char *dev_name,
uint16_t *error_code,
uint8_t assoc_dev)
{
struct rmnet_nl_msg_s request, response;
size_t str_len = 0;
int return_code = RMNETCTL_LIB_ERR;
do {
if ((!hndl) || (!error_code) || _rmnetctl_check_dev_name(dev_name) ||
((assoc_dev != RMNETCTL_DEVICE_ASSOCIATE) &&
(assoc_dev != RMNETCTL_DEVICE_UNASSOCIATE))) {
return_code = RMNETCTL_INVALID_ARG;
break;
}
if (assoc_dev == RMNETCTL_DEVICE_ASSOCIATE)
request.message_type = RMNET_NETLINK_ASSOCIATE_NETWORK_DEVICE;
else
request.message_type = RMNET_NETLINK_UNASSOCIATE_NETWORK_DEVICE;
request.arg_length = RMNET_MAX_STR_LEN;
str_len = strlcpy((char *)(request.data), dev_name, (size_t)RMNET_MAX_STR_LEN);
if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
break;
if ((*error_code = rmnetctl_transact(hndl, &request, &response))
!= RMNETCTL_SUCCESS)
break;
if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
break;
return_code = _rmnetctl_set_codes(response.return_code, error_code);
} while(0);
return return_code;
}
int rmnet_get_network_device_associated(rmnetctl_hndl_t *hndl,
const char *dev_name,
int *register_status,
uint16_t *error_code) {
struct rmnet_nl_msg_s request, response;
size_t str_len = 0;
int return_code = RMNETCTL_LIB_ERR;
do {
if ((!hndl) || (!register_status) || (!error_code) ||
_rmnetctl_check_dev_name(dev_name)) {
return_code = RMNETCTL_INVALID_ARG;
break;
}
request.message_type = RMNET_NETLINK_GET_NETWORK_DEVICE_ASSOCIATED;
request.arg_length = RMNET_MAX_STR_LEN;
str_len = strlcpy((char *)(request.data), dev_name, RMNET_MAX_STR_LEN);
if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
break;
if ((*error_code = rmnetctl_transact(hndl, &request, &response))
!= RMNETCTL_SUCCESS)
break;
if (_rmnetctl_check_data(response.crd, error_code)
!= RMNETCTL_SUCCESS) {
if (_rmnetctl_check_code(response.crd, error_code)
== RMNETCTL_SUCCESS)
return_code = _rmnetctl_set_codes(response.return_code,
error_code);
break;
}
*register_status = response.return_code;
return_code = RMNETCTL_SUCCESS;
} while(0);
return return_code;
}
int rmnet_set_link_egress_data_format(rmnetctl_hndl_t *hndl,
uint32_t egress_flags,
uint16_t agg_size,
uint16_t agg_count,
const char *dev_name,
uint16_t *error_code) {
struct rmnet_nl_msg_s request, response;
size_t str_len = 0;
int return_code = RMNETCTL_LIB_ERR;
do {
if ((!hndl) || (!error_code) || _rmnetctl_check_dev_name(dev_name) ||
((~EGRESS_FLAGS_MASK) & egress_flags)) {
return_code = RMNETCTL_INVALID_ARG;
break;
}
request.message_type = RMNET_NETLINK_SET_LINK_EGRESS_DATA_FORMAT;
request.arg_length = RMNET_MAX_STR_LEN +
sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t);
str_len = strlcpy((char *)(request.data_format.dev),
dev_name,
RMNET_MAX_STR_LEN);
if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
break;
request.data_format.flags = egress_flags;
request.data_format.agg_size = agg_size;
request.data_format.agg_count = agg_count;
if ((*error_code = rmnetctl_transact(hndl, &request, &response))
!= RMNETCTL_SUCCESS)
break;
if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
break;
return_code = _rmnetctl_set_codes(response.return_code, error_code);
} while(0);
return return_code;
}
int rmnet_get_link_egress_data_format(rmnetctl_hndl_t *hndl,
const char *dev_name,
uint32_t *egress_flags,
uint16_t *agg_size,
uint16_t *agg_count,
uint16_t *error_code) {
struct rmnet_nl_msg_s request, response;
size_t str_len = 0;
int return_code = RMNETCTL_LIB_ERR;
do {
if ((!hndl) || (!egress_flags) || (!agg_size) || (!agg_count) ||
(!error_code) || _rmnetctl_check_dev_name(dev_name)) {
return_code = RMNETCTL_INVALID_ARG;
break;
}
request.message_type = RMNET_NETLINK_GET_LINK_EGRESS_DATA_FORMAT;
request.arg_length = RMNET_MAX_STR_LEN;
str_len = strlcpy((char *)(request.data_format.dev),
dev_name,
RMNET_MAX_STR_LEN);
if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
break;
if ((*error_code = rmnetctl_transact(hndl, &request, &response))
!= RMNETCTL_SUCCESS)
break;
if (_rmnetctl_check_data(response.crd, error_code)
!= RMNETCTL_SUCCESS) {
if (_rmnetctl_check_code(response.crd, error_code)
== RMNETCTL_SUCCESS)
return_code = _rmnetctl_set_codes(response.return_code,
error_code);
break;
}
*egress_flags = response.data_format.flags;
*agg_size = response.data_format.agg_size;
*agg_count = response.data_format.agg_count;
return_code = RMNETCTL_SUCCESS;
} while(0);
return return_code;
}
int rmnet_set_link_ingress_data_format_tailspace(rmnetctl_hndl_t *hndl,
uint32_t ingress_flags,
uint8_t tail_spacing,
const char *dev_name,
uint16_t *error_code) {
struct rmnet_nl_msg_s request, response;
size_t str_len = 0;
int return_code = RMNETCTL_LIB_ERR;
do {
if ((!hndl) || (!error_code) || _rmnetctl_check_dev_name(dev_name) ||
((~INGRESS_FLAGS_MASK) & ingress_flags)) {
return_code = RMNETCTL_INVALID_ARG;
break;
}
request.message_type = RMNET_NETLINK_SET_LINK_INGRESS_DATA_FORMAT;
request.arg_length = RMNET_MAX_STR_LEN +
sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t);
str_len = strlcpy((char *)(request.data_format.dev),
dev_name,
RMNET_MAX_STR_LEN);
if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
break;
request.data_format.flags = ingress_flags;
request.data_format.tail_spacing = tail_spacing;
if ((*error_code = rmnetctl_transact(hndl, &request, &response))
!= RMNETCTL_SUCCESS)
break;
if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
break;
return_code = _rmnetctl_set_codes(response.return_code, error_code);
} while(0);
return return_code;
}
int rmnet_get_link_ingress_data_format_tailspace(rmnetctl_hndl_t *hndl,
const char *dev_name,
uint32_t *ingress_flags,
uint8_t *tail_spacing,
uint16_t *error_code) {
struct rmnet_nl_msg_s request, response;
size_t str_len = 0;
int return_code = RMNETCTL_LIB_ERR;
do {
if ((!hndl) || (!error_code) ||
_rmnetctl_check_dev_name(dev_name)) {
return_code = RMNETCTL_INVALID_ARG;
break;
}
request.message_type = RMNET_NETLINK_GET_LINK_INGRESS_DATA_FORMAT;
request.arg_length = RMNET_MAX_STR_LEN;
str_len = strlcpy((char *)(request.data_format.dev),
dev_name,
RMNET_MAX_STR_LEN);
if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
break;
if ((*error_code = rmnetctl_transact(hndl, &request, &response))
!= RMNETCTL_SUCCESS)
break;
if (_rmnetctl_check_data(response.crd, error_code)
!= RMNETCTL_SUCCESS) {
if (_rmnetctl_check_code(response.crd, error_code)
== RMNETCTL_SUCCESS)
return_code = _rmnetctl_set_codes(response.return_code,
error_code);
break;
}
if (ingress_flags)
*ingress_flags = response.data_format.flags;
if (tail_spacing)
*tail_spacing = response.data_format.tail_spacing;
return_code = RMNETCTL_SUCCESS;
} while(0);
return return_code;
}
int rmnet_set_logical_ep_config(rmnetctl_hndl_t *hndl,
int32_t ep_id,
uint8_t operating_mode,
const char *dev_name,
const char *next_dev,
uint16_t *error_code) {
struct rmnet_nl_msg_s request, response;
size_t str_len = 0;
int return_code = RMNETCTL_LIB_ERR;
do {
if ((!hndl) || ((ep_id < -1) || (ep_id > 31)) || (!error_code) ||
_rmnetctl_check_dev_name(dev_name) ||
_rmnetctl_check_dev_name(next_dev) ||
operating_mode >= RMNET_EPMODE_LENGTH) {
return_code = RMNETCTL_INVALID_ARG;
break;
}
request.message_type = RMNET_NETLINK_SET_LOGICAL_EP_CONFIG;
request.arg_length = RMNET_MAX_STR_LEN +
RMNET_MAX_STR_LEN + sizeof(int32_t) + sizeof(uint8_t);
str_len = strlcpy((char *)(request.local_ep_config.dev),
dev_name,
RMNET_MAX_STR_LEN);
if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
break;
str_len = strlcpy((char *)(request.local_ep_config.next_dev),
next_dev,
RMNET_MAX_STR_LEN);
if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
break;
request.local_ep_config.ep_id = ep_id;
request.local_ep_config.operating_mode = operating_mode;
if ((*error_code = rmnetctl_transact(hndl, &request, &response))
!= RMNETCTL_SUCCESS)
break;
if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
break;
return_code = _rmnetctl_set_codes(response.return_code, error_code);
} while(0);
return return_code;
}
int rmnet_unset_logical_ep_config(rmnetctl_hndl_t *hndl,
int32_t ep_id,
const char *dev_name,
uint16_t *error_code) {
struct rmnet_nl_msg_s request, response;
size_t str_len = 0;
int return_code = RMNETCTL_LIB_ERR;
do {
if ((!hndl) || ((ep_id < -1) || (ep_id > 31)) || (!error_code) ||
_rmnetctl_check_dev_name(dev_name)) {
return_code = RMNETCTL_INVALID_ARG;
break;
}
request.message_type = RMNET_NETLINK_UNSET_LOGICAL_EP_CONFIG;
request.arg_length = RMNET_MAX_STR_LEN + sizeof(int32_t);
str_len = strlcpy((char *)(request.local_ep_config.dev),
dev_name,
RMNET_MAX_STR_LEN);
if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
break;
request.local_ep_config.ep_id = ep_id;
if ((*error_code = rmnetctl_transact(hndl, &request, &response))
!= RMNETCTL_SUCCESS)
break;
if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
break;
return_code = _rmnetctl_set_codes(response.return_code, error_code);
} while(0);
return return_code;
}
int rmnet_get_logical_ep_config(rmnetctl_hndl_t *hndl,
int32_t ep_id,
const char *dev_name,
uint8_t *operating_mode,
char **next_dev,
uint32_t next_dev_len,
uint16_t *error_code) {
struct rmnet_nl_msg_s request, response;
size_t str_len = 0;
int return_code = RMNETCTL_LIB_ERR;
do {
if ((!hndl) || (!operating_mode) || (!error_code) || ((ep_id < -1) ||
(ep_id > 31)) || _rmnetctl_check_dev_name(dev_name) || (!next_dev)
|| (0 == next_dev_len)) {
return_code = RMNETCTL_INVALID_ARG;
break;
}
request.message_type = RMNET_NETLINK_GET_LOGICAL_EP_CONFIG;
request.arg_length = RMNET_MAX_STR_LEN + sizeof(int32_t);
str_len = strlcpy((char *)(request.local_ep_config.dev),
dev_name,
RMNET_MAX_STR_LEN);
if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
break;
request.local_ep_config.ep_id = ep_id;
if ((*error_code = rmnetctl_transact(hndl, &request, &response))
!= RMNETCTL_SUCCESS)
break;
if (_rmnetctl_check_data(response.crd, error_code)
!= RMNETCTL_SUCCESS) {
if (_rmnetctl_check_code(response.crd, error_code)
== RMNETCTL_SUCCESS)
return_code = _rmnetctl_set_codes(response.return_code,
error_code);
break;
}
str_len = strlcpy(*next_dev,
(char *)(response.local_ep_config.next_dev),
min(RMNET_MAX_STR_LEN, next_dev_len));
if (_rmnetctl_check_len(str_len, error_code) != RMNETCTL_SUCCESS)
break;
*operating_mode = response.local_ep_config.operating_mode;
return_code = RMNETCTL_SUCCESS;
} while(0);
return return_code;
}
int rmnet_new_vnd_prefix(rmnetctl_hndl_t *hndl,
uint32_t id,
uint16_t *error_code,
uint8_t new_vnd,
const char *prefix)
{
struct rmnet_nl_msg_s request, response;
int return_code = RMNETCTL_LIB_ERR;
size_t str_len = 0;
do {
if ((!hndl) || (!error_code) ||
((new_vnd != RMNETCTL_NEW_VND) && (new_vnd != RMNETCTL_FREE_VND))) {
return_code = RMNETCTL_INVALID_ARG;
break;
}
memset(request.vnd.vnd_name, 0, RMNET_MAX_STR_LEN);
if (new_vnd == RMNETCTL_NEW_VND) {
if (prefix) {
request.message_type =RMNET_NETLINK_NEW_VND_WITH_PREFIX;
str_len = strlcpy((char *)request.vnd.vnd_name,
prefix, RMNET_MAX_STR_LEN);
if (_rmnetctl_check_len(str_len, error_code)
!= RMNETCTL_SUCCESS)
break;
} else {
request.message_type = RMNET_NETLINK_NEW_VND;
}
} else {
request.message_type = RMNET_NETLINK_FREE_VND;
}
request.arg_length = sizeof(uint32_t);
request.vnd.id = id;
if ((*error_code = rmnetctl_transact(hndl, &request, &response))
!= RMNETCTL_SUCCESS)
break;
if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
break;
return_code = _rmnetctl_set_codes(response.return_code, error_code);
} while(0);
return return_code;
}
int rmnet_new_vnd(rmnetctl_hndl_t *hndl,
uint32_t id,
uint16_t *error_code,
uint8_t new_vnd)
{
return rmnet_new_vnd_prefix(hndl, id, error_code, new_vnd, 0);
}
int rmnet_get_vnd_name(rmnetctl_hndl_t *hndl,
uint32_t id,
uint16_t *error_code,
char *buf,
uint32_t buflen)
{
struct rmnet_nl_msg_s request, response;
uint32_t str_len;
int return_code = RMNETCTL_LIB_ERR;
do {
if ((!hndl) || (!error_code) || (!buf) || (0 == buflen)) {
return_code = RMNETCTL_INVALID_ARG;
break;
}
request.message_type = RMNET_NETLINK_GET_VND_NAME;
request.arg_length = sizeof(uint32_t);
request.vnd.id = id;
if ((*error_code = rmnetctl_transact(hndl, &request, &response))
!= RMNETCTL_SUCCESS)
break;
if (_rmnetctl_check_data(response.crd, error_code)
!= RMNETCTL_SUCCESS) {
if (_rmnetctl_check_code(response.crd, error_code)
== RMNETCTL_SUCCESS)
return_code = _rmnetctl_set_codes(response.return_code,
error_code);
break;
}
str_len = (uint32_t)strlcpy(buf,
(char *)(response.vnd.vnd_name),
buflen);
if (str_len >= buflen) {
*error_code = RMNETCTL_API_ERR_STRING_TRUNCATION;
break;
}
return_code = RMNETCTL_SUCCESS;
} while (0);
return return_code;
}
int rmnet_add_del_vnd_tc_flow(rmnetctl_hndl_t *hndl,
uint32_t id,
uint32_t map_flow_id,
uint32_t tc_flow_id,
uint8_t set_flow,
uint16_t *error_code) {
struct rmnet_nl_msg_s request, response;
int return_code = RMNETCTL_LIB_ERR;
do {
if ((!hndl) || (!error_code) || ((set_flow != RMNETCTL_ADD_FLOW) &&
(set_flow != RMNETCTL_DEL_FLOW))) {
return_code = RMNETCTL_INVALID_ARG;
break;
}
if (set_flow == RMNETCTL_ADD_FLOW)
request.message_type = RMNET_NETLINK_ADD_VND_TC_FLOW;
else
request.message_type = RMNET_NETLINK_DEL_VND_TC_FLOW;
request.arg_length = (sizeof(uint32_t))*3;
request.flow_control.id = id;
request.flow_control.map_flow_id = map_flow_id;
request.flow_control.tc_flow_id = tc_flow_id;
if ((*error_code = rmnetctl_transact(hndl, &request, &response))
!= RMNETCTL_SUCCESS)
break;
if (_rmnetctl_check_code(response.crd, error_code) != RMNETCTL_SUCCESS)
break;
return_code = _rmnetctl_set_codes(response.return_code, error_code);
} while(0);
return return_code;
}

View File

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

View File

@@ -1,15 +0,0 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := sockev_cli.c
LOCAL_CFLAGS := -Wall -Werror
LOCAL_C_INCLUDES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
LOCAL_CLANG := true
LOCAL_MODULE := sockev
LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)

View File

@@ -1,96 +0,0 @@
/******************************************************************************
S O C K E V _ C L I . C
Copyright (c) 2013, 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 sockev_cli.c
@brief command line test utility to receive sockev netlink messages.
******************************************************************************/
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/sockev.h>
#include <stdlib.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#define SOCKEVCLI_ERROR -1
int main(void)
{
int skfd, rc;
socklen_t addrlen;
struct sockaddr_nl my_addr, src_addr;
struct nlmsghdr *nlh = NULL;
struct sknlsockevmsg *msg;
nlh = (struct nlmsghdr *)
malloc(NLMSG_SPACE(sizeof(struct sknlsockevmsg) + 16));
if (!nlh) {
fprintf(stderr, "malloc() failed\n");
return SOCKEVCLI_ERROR;
}
skfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_SOCKEV);
if (skfd < 0) {
fprintf(stderr, "nl_open_sock: socket failed\n");
return SOCKEVCLI_ERROR;
}
memset(&my_addr, 0, sizeof(struct sockaddr_nl));
my_addr.nl_family = AF_NETLINK;
my_addr.nl_pid = getpid();
my_addr.nl_groups = SKNLGRP_SOCKEV;
rc = bind(skfd, (struct sockaddr *)&my_addr,
sizeof(struct sockaddr_nl));
if (rc < 0) {
fprintf(stderr, "nl_open_sock: bind failed\n");
close(skfd);
return SOCKEVCLI_ERROR;
}
while (1) {
recvfrom(skfd, nlh, sizeof(struct sknlsockevmsg) + 16, 0,
(const struct sockaddr *)&src_addr, &addrlen);
msg = NLMSG_DATA(nlh);
printf("----------------------------\n");
printf("pid:\t%d\n", msg->pid);
printf("event:\t%s\n", msg->event);
printf("skfamily:\t0x%04X\n", msg->skfamily);
printf("skstate:\t%03d\n", msg->skstate);
printf("skprotocol:\t%03d\n", msg->skprotocol);
printf("sktype:\t0x%04X\n", msg->sktype);
printf("skflags:\t0x%016llX\n", msg->skflags);
}
return 0;
}

View File

@@ -1,43 +0,0 @@
#
# Copyright 2016 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := system/core/libsparse
LOCAL_SRC_FILES := gpt-utils.cpp
ifeq ($(TARGET_COMPILE_WITH_MSM_KERNEL),true)
LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
endif
LOCAL_SHARED_LIBRARIES := liblog
LOCAL_MODULE := libgptutils
LOCAL_MODULE_OWNER := qti
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := system/core/libsparse
LOCAL_SRC_FILES := gpt-utils.cpp
ifeq ($(TARGET_COMPILE_WITH_MSM_KERNEL),true)
LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
endif
LOCAL_SHARED_LIBRARIES += liblog libsparse libcutils
LOCAL_MODULE := libgptutils
LOCAL_MODULE_OWNER := qti
LOCAL_COPY_HEADERS_TO := gpt-utils/inc
LOCAL_COPY_HEADERS := gpt-utils.h
include $(BUILD_SHARED_LIBRARY)

File diff suppressed because it is too large Load Diff

View File

@@ -1,192 +0,0 @@
/*
* Copyright (c) 2013, 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.
*/
#ifndef __GPT_UTILS_H__
#define __GPT_UTILS_H__
#include <vector>
#include <string>
#include <map>
#ifdef __cplusplus
extern "C" {
#endif
#include <unistd.h>
#include <stdlib.h>
/******************************************************************************
* GPT HEADER DEFINES
******************************************************************************/
#define GPT_SIGNATURE "EFI PART"
#define HEADER_SIZE_OFFSET 12
#define HEADER_CRC_OFFSET 16
#define PRIMARY_HEADER_OFFSET 24
#define BACKUP_HEADER_OFFSET 32
#define FIRST_USABLE_LBA_OFFSET 40
#define LAST_USABLE_LBA_OFFSET 48
#define PENTRIES_OFFSET 72
#define PARTITION_COUNT_OFFSET 80
#define PENTRY_SIZE_OFFSET 84
#define PARTITION_CRC_OFFSET 88
#define TYPE_GUID_OFFSET 0
#define TYPE_GUID_SIZE 16
#define PTN_ENTRY_SIZE 128
#define UNIQUE_GUID_OFFSET 16
#define FIRST_LBA_OFFSET 32
#define LAST_LBA_OFFSET 40
#define ATTRIBUTE_FLAG_OFFSET 48
#define PARTITION_NAME_OFFSET 56
#define MAX_GPT_NAME_SIZE 72
/******************************************************************************
* AB RELATED DEFINES
******************************************************************************/
//Bit 48 onwords in the attribute field are the ones where we are allowed to
//store our AB attributes.
#define AB_FLAG_OFFSET (ATTRIBUTE_FLAG_OFFSET + 6)
#define GPT_DISK_INIT_MAGIC 0xABCD
#define AB_PARTITION_ATTR_SLOT_ACTIVE (0x1<<2)
#define AB_PARTITION_ATTR_BOOT_SUCCESSFUL (0x1<<6)
#define AB_PARTITION_ATTR_UNBOOTABLE (0x1<<7)
#define AB_SLOT_ACTIVE_VAL 0x3F
#define AB_SLOT_INACTIVE_VAL 0x0
#define AB_SLOT_ACTIVE 1
#define AB_SLOT_INACTIVE 0
#define AB_SLOT_A_SUFFIX "_a"
#define AB_SLOT_B_SUFFIX "_b"
#define PTN_XBL "xbl"
#define PTN_SWAP_LIST PTN_XBL, "sbl1", "rpm", "tz", "aboot", "hyp", "lksecapp", "keymaster", "cmnlib", "cmnlib32", "cmnlib64", "pmic", "apdp", "devcfg", "hosd", "keystore", "msadp"
#define AB_PTN_LIST PTN_SWAP_LIST, "boot", "system", "vendor", "modem", "bluetooth"
#define BOOT_DEV_DIR "/dev/block/bootdevice/by-name"
/******************************************************************************
* HELPER MACROS
******************************************************************************/
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
/******************************************************************************
* TYPES
******************************************************************************/
enum boot_update_stage {
UPDATE_MAIN = 1,
UPDATE_BACKUP,
UPDATE_FINALIZE
};
enum gpt_instance {
PRIMARY_GPT = 0,
SECONDARY_GPT
};
enum boot_chain {
NORMAL_BOOT = 0,
BACKUP_BOOT
};
struct gpt_disk {
//GPT primary header
uint8_t *hdr;
//primary header crc
uint32_t hdr_crc;
//GPT backup header
uint8_t *hdr_bak;
//backup header crc
uint32_t hdr_bak_crc;
//Partition entries array
uint8_t *pentry_arr;
//Partition entries array for backup table
uint8_t *pentry_arr_bak;
//Size of the pentry array
uint32_t pentry_arr_size;
//Size of each element in the pentry array
uint32_t pentry_size;
//CRC of the partition entry array
uint32_t pentry_arr_crc;
//CRC of the backup partition entry array
uint32_t pentry_arr_bak_crc;
//Path to block dev representing the disk
char devpath[PATH_MAX];
//Block size of disk
uint32_t block_size;
uint32_t is_initialized;
};
/******************************************************************************
* FUNCTION PROTOTYPES
******************************************************************************/
int prepare_boot_update(enum boot_update_stage stage);
//GPT disk methods
struct gpt_disk* gpt_disk_alloc();
//Free previously allocated gpt_disk struct
void gpt_disk_free(struct gpt_disk *disk);
//Get the details of the disk holding the partition whose name
//is passed in via dev
int gpt_disk_get_disk_info(const char *dev, struct gpt_disk *disk);
//Get pointer to partition entry from a allocated gpt_disk structure
uint8_t* gpt_disk_get_pentry(struct gpt_disk *disk,
const char *partname,
enum gpt_instance instance);
//Update the crc fields of the modified disk structure
int gpt_disk_update_crc(struct gpt_disk *disk);
//Write the contents of struct gpt_disk back to the actual disk
int gpt_disk_commit(struct gpt_disk *disk);
//Return if the current device is UFS based or not
int gpt_utils_is_ufs_device();
//Swtich betwieen using either the primary or the backup
//boot LUN for boot. This is required since UFS boot partitions
//cannot have a backup GPT which is what we use for failsafe
//updates of the other 'critical' partitions. This function will
//not be invoked for emmc targets and on UFS targets is only required
//to be invoked for XBL.
//
//The algorithm to do this is as follows:
//- Find the real block device(eg: /dev/block/sdb) that corresponds
// to the /dev/block/bootdevice/by-name/xbl(bak) symlink
//
//- Once we have the block device 'node' name(sdb in the above example)
// use this node to to locate the scsi generic device that represents
// it by checking the file /sys/block/sdb/device/scsi_generic/sgY
//
//- Once we locate sgY we call the query ioctl on /dev/sgy to switch
//the boot lun to either LUNA or LUNB
int gpt_utils_set_xbl_boot_partition(enum boot_chain chain);
//Given a vector of partition names as a input and a reference to a map,
//populate the map to indicate which physical disk each of the partitions
//sits on. The key in the map is the path to the block device where the
//partition lies and the value is a vector of strings indicating which of
//the passed in partition names sits on that device.
int gpt_utils_get_partition_map(std::vector<std::string>& partition_list,
std::map<std::string,std::vector<std::string>>& partition_map);
#ifdef __cplusplus
}
#endif
#endif /* __GPT_UTILS_H__ */

View File

@@ -1,5 +0,0 @@
Michael Clark <michael@metaparadigm.com>
Jehiah Czebotar <jehiah@gmail.com>
Eric Haszlakiewicz <hawicz+json-c@gmail.com>
C. Watford (christopher.watford@gmail.com)

View File

@@ -1,39 +0,0 @@
# This file is the top android makefile for all sub-modules.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
json_c_TOP := $(LOCAL_PATH)
JSON_C_BUILT_SOURCES := Android.mk
JSON_C_BUILT_SOURCES := $(patsubst %, $(abspath $(json_c_TOP))/%, $(JSON_C_BUILT_SOURCES))
.PHONY: json-c-configure json-c-configure-real
json-c-configure-real:
echo $(JSON_C_BUILT_SOURCES)
cd $(json_c_TOP) ; \
$(abspath $(json_c_TOP))/autogen.sh && \
CC="$(CONFIGURE_CC)" \
CFLAGS="$(CONFIGURE_CFLAGS)" \
LD=$(TARGET_LD) \
LDFLAGS="$(CONFIGURE_LDFLAGS)" \
CPP=$(CONFIGURE_CPP) \
CPPFLAGS="$(CONFIGURE_CPPFLAGS)" \
PKG_CONFIG_LIBDIR=$(CONFIGURE_PKG_CONFIG_LIBDIR) \
PKG_CONFIG_TOP_BUILD_DIR=/ \
ac_cv_func_malloc_0_nonnull=yes \
ac_cv_func_realloc_0_nonnull=yes \
$(abspath $(json_c_TOP))/$(CONFIGURE) --host=$(CONFIGURE_HOST) \
--prefix=/system \
&& \
for file in $(JSON_C_BUILT_SOURCES); do \
rm -f $$file && \
make -C $$(dirname $$file) $$(basename $$file) ; \
done
json-c-configure: json-c-configure-real
PA_CONFIGURE_TARGETS += json-c-configure
-include $(json_c_TOP)/Android.mk

View File

@@ -1,37 +0,0 @@
LIBJSON_ROOT := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libjson
LOCAL_PATH := $(LIBJSON_ROOT)
ifeq ($(TARGET_COMPILE_WITH_MSM_KERNEL),true)
LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
endif
LOCAL_COPY_HEADERS_TO := libjson/inc
LOCAL_COPY_HEADERS := bits.h \
config.h \
debug.h \
linkhash.h \
arraylist.h \
json.h \
json_config.h \
json_inttypes.h \
json_util.h \
json_object.h \
json_tokener.h \
json_object_iterator.h \
json_c_version.h
LOCAL_SRC_FILES := arraylist.c \
debug.c \
json_c_version.c \
json_object.c \
json_object_iterator.c \
json_tokener.c \
json_util.c \
libjson.c \
linkhash.c \
printbuf.c \
random_seed.c
LOCAL_CFLAGS += -Wno-unused-parameter -Werror
LOCAL_SHARED_LIBRARIES := libcutils libutils
LOCAL_MODULE_TAG := optional
include $(BUILD_SHARED_LIBRARY)

View File

@@ -1,42 +0,0 @@
Copyright (c) 2009-2012 Eric Haszlakiewicz
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
----------------------------------------------------------------
Copyright (c) 2004, 2005 Metaparadigm Pte Ltd
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,218 +0,0 @@
NEXT.VERSION
...nothing yet...
0.12
* Address security issues:
* CVE-2013-6371: hash collision denial of service
* CVE-2013-6370: buffer overflow if size_t is larger than int
* Avoid potential overflow in json_object_get_double
* Eliminate the mc_abort() function and MC_ABORT macro.
* Make the json_tokener_errors array local. It has been deprecated for
a while, and json_tokener_error_desc() should be used instead.
* change the floating point output format to %.17g so values with
more than 6 digits show up in the output.
* Remove the old libjson.so name compatibility support. The library is
only created as libjson-c.so now and headers are only installed
into the ${prefix}/json-c directory.
* When supported by the linker, add the -Bsymbolic-functions flag.
* Various changes to fix the build on MSVC.
* Make strict mode more strict:
* number must not start with 0
* no single-quote strings
* no comments
* trailing char not allowed
* only allow lowercase literals
* Added a json_object_new_double_s() convenience function to allow
an exact string representation of a double to be specified when
creating the object and use it in json_tokener_parse_ex() so
a re-serialized object more exactly matches the input.
* Add support NaN and Infinity
0.11
* IMPORTANT: the name of the library has changed to libjson-c.so and
the header files are now in include/json-c.
The pkgconfig name has also changed from json to json-c.
You should change your build to use appropriate -I and -l options.
A compatibility shim is in place so builds using the old name will
continue to work, but that will be removed in the next release.
* Maximum recursion depth is now a runtime option.
json_tokener_new() is provided for compatibility.
json_tokener_new_ex(depth)
* Include json_object_iterator.h in the installed headers.
* Add support for building on Android.
* Rewrite json_object_object_add to replace just the value if the key already exists so keys remain valid.
* Make it safe to delete keys while iterating with the json_object_object_foreach macro.
* Add a json_set_serializer() function to allow the string output of a json_object to be customized.
* Make float parsing locale independent.
* Add a json_tokener_set_flags() function and a JSON_TOKENER_STRICT flag.
* Enable -Werror when building.
* speed improvements to parsing 64-bit integers on systems with working sscanf
* Add a json_object_object_length function.
* Fix a bug (buffer overrun) when expanding arrays to more than 64 entries.
0.10
* Add a json_object_to_json_string_ext() function to allow output to be
formatted in a more human readable form.
* Add json_object_object_get_ex(), a NULL-safe get object method, to be able
to distinguish between a key not present and the value being NULL.
* Add an alternative iterator implementation, see json_object_iterator.h
* Make json_object_iter public to enable external use of the
json_object_object_foreachC macro.
* Add a printbuf_memset() function to provide an effecient way to set and
append things like whitespace indentation.
* Adjust json_object_is_type and json_object_get_type so they return
json_type_null for NULL objects and handle NULL passed to
json_objct_object_get().
* Rename boolean type to json_bool.
* Fix various compile issues for Visual Studio and MinGW.
* Allow json_tokener_parse_ex() to be re-used to parse multiple object.
Also, fix some parsing issues with capitalized hexadecimal numbers and
number in E notation.
* Add json_tokener_get_error() and json_tokener_error_desc() to better
encapsulate the process of retrieving errors while parsing.
* Various improvements to the documentation of many functions.
* Add new json_object_array_sort() function.
* Fix a bug in json_object_get_int(), which would incorrectly return 0
when called on a string type object.
Eric Haszlakiewicz
* Add a json_type_to_name() function.
Eric Haszlakiewicz
* Add a json_tokener_parse_verbose() function.
Jehiah Czebotar
* Improve support for null bytes within JSON strings.
Jehiah Czebotar
* Fix file descriptor leak if memory allocation fails in json_util
Zachary Blair, zack_blair at hotmail dot com
* Add int64 support. Two new functions json_object_net_int64 and
json_object_get_int64. Binary compatibility preserved.
Eric Haszlakiewicz, EHASZLA at transunion com
Rui Miguel Silva Seabra, rms at 1407 dot org
* Fix subtle bug in linkhash where lookup could hang after all slots
were filled then successively freed.
Spotted by Jean-Marc Naud, j dash m at newtraxtech dot com
* Make json_object_from_file take const char *filename
Spotted by Vikram Raj V, vsagar at attinteractive dot com
* Add handling of surrogate pairs (json_tokener.c, test4.c, Makefile.am)
Brent Miller, bdmiller at yahoo dash inc dot com
* Correction to comment describing printbuf_memappend in printbuf.h
Brent Miller, bdmiller at yahoo dash inc dot com
0.9
* Add README.html README-WIN32.html config.h.win32 to Makefile.am
Michael Clark, <michael@metaparadigm.com>
* Add const qualifier to the json_tokener_parse functions
Eric Haszlakiewicz, EHASZLA at transunion dot com
* Rename min and max so we can never clash with C or C++ std library
Ian Atha, thatha at yahoo dash inc dot com
* Fix any noticeable spelling or grammar errors.
* Make sure every va_start has a va_end.
* Check all pointers for validity.
Erik Hovland, erik at hovland dot org
* Fix json_object_get_boolean to return false for empty string
Spotted by Vitaly Kruglikov, Vitaly dot Kruglikov at palm dot com
* optimizations to json_tokener_parse_ex(), printbuf_memappend()
Brent Miller, bdmiller at yahoo dash inc dot com
* Disable REFCOUNT_DEBUG by default in json_object.c
* Don't use this as a variable, so we can compile with a C++ compiler
* Add casts from void* to type of assignment when using malloc
* Add #ifdef __cplusplus guards to all of the headers
* Add typedefs for json_object, json_tokener, array_list, printbuf, lh_table
Michael Clark, <michael@metaparadigm.com>
* Null pointer dereference fix. Fix json_object_get_boolean strlen test
to not return TRUE for zero length string. Remove redundant includes.
Erik Hovland, erik at hovland dot org
* Fixed warning reported by adding -Wstrict-prototypes
-Wold-style-definition to the compilatin flags.
Dotan Barak, dotanba at gmail dot com
* Add const correctness to public interfaces
Gerard Krol, g dot c dot krol at student dot tudelft dot nl
0.8
* Add va_end for every va_start
Dotan Barak, dotanba at gmail dot com
* Add macros to enable compiling out debug code
Geoffrey Young, geoff at modperlcookbook dot org
* Fix bug with use of capital E in numbers with exponents
Mateusz Loskot, mateusz at loskot dot net
* Add stddef.h include
* Patch allows for json-c compile with -Werror and not fail due to
-Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations
Geoffrey Young, geoff at modperlcookbook dot org
0.7
* Add escaping of backslash to json output
* Add escaping of foward slash on tokenizing and output
* Changes to internal tokenizer from using recursion to
using a depth state structure to allow incremental parsing
0.6
* Fix bug in escaping of control characters
Johan Björklund, johbjo09 at kth dot se
* Remove include "config.h" from headers (should only
be included from .c files)
Michael Clark <michael@metaparadigm.com>
0.5
* Make headers C++ compatible by change *this to *obj
* Add ifdef C++ extern "C" to headers
* Use simpler definition of min and max in bits.h
Larry Lansing, llansing at fuzzynerd dot com
* Remove automake 1.6 requirement
* Move autogen commands into autogen.sh. Update README
* Remove error pointer special case for Windows
* Change license from LGPL to MIT
Michael Clark <michael@metaparadigm.com>
0.4
* Fix additional error case in object parsing
* Add back sign reversal in nested object parse as error pointer
value is negative, while error value is positive.
Michael Clark <michael@metaparadigm.com>
0.3
* fix pointer arithmetic bug for error pointer check in is_error() macro
* fix type passed to printbuf_memappend in json_tokener
* update autotools bootstrap instructions in README
Michael Clark <michael@metaparadigm.com>
0.2
* printbuf.c - C. Watford (christopher.watford@gmail.com)
Added a Win32/Win64 compliant implementation of vasprintf
* debug.c - C. Watford (christopher.watford@gmail.com)
Removed usage of vsyslog on Win32/Win64 systems, needs to be handled
by a configure script
* json_object.c - C. Watford (christopher.watford@gmail.com)
Added scope operator to wrap usage of json_object_object_foreach, this
needs to be rethought to be more ANSI C friendly
* json_object.h - C. Watford (christopher.watford@gmail.com)
Added Microsoft C friendly version of json_object_object_foreach
* json_tokener.c - C. Watford (christopher.watford@gmail.com)
Added a Win32/Win64 compliant implementation of strndup
* json_util.c - C. Watford (christopher.watford@gmail.com)
Added cast and mask to suffice size_t v. unsigned int conversion
correctness
* json_tokener.c - sign reversal issue on error info for nested object parse
spotted by Johan Björklund (johbjo09 at kth.se)
* json_object.c - escape " in json_escape_str
* Change to automake and libtool to build shared and static library
Michael Clark <michael@metaparadigm.com>
0.1
* initial release

File diff suppressed because it is too large Load Diff

View File

@@ -1,74 +0,0 @@
include Makefile.am.inc
EXTRA_DIST = README.html README-WIN32.html config.h.win32 doc json-c.vcproj
SUBDIRS = . tests
lib_LTLIBRARIES = libjson-c.la
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = json-c.pc
libjson_cincludedir = $(includedir)/json-c
libjson_cinclude_HEADERS = \
arraylist.h \
bits.h \
debug.h \
json.h \
json_config.h \
json_c_version.h \
json_inttypes.h \
json_object.h \
json_object_iterator.h \
json_object_private.h \
json_tokener.h \
json_util.h \
linkhash.h \
printbuf.h \
random_seed.h
#libjsonx_includedir = $(libdir)/json-c-@VERSION@
#
#libjsonx_include_HEADERS = \
# json_config.h
libjson_c_la_LDFLAGS = -version-info 2:0:0 -no-undefined @JSON_BSYMBOLIC_LDFLAGS@
libjson_c_la_SOURCES = \
arraylist.c \
debug.c \
json_c_version.c \
json_object.c \
json_object_iterator.c \
json_tokener.c \
json_util.c \
linkhash.c \
printbuf.c \
random_seed.c
distclean-local:
-rm -rf $(testsubdir)
-rm -rf config.h.in~ Makefile.in aclocal.m4 autom4te.cache/ config.guess config.sub depcomp install-sh ltmain.sh missing
-rm -f INSTALL test-driver tests/Makefile.in compile
maintainer-clean-local:
-rm -rf configure
uninstall-local:
rm -rf "$(DESTDIR)@includedir@/json-c"
rm -f "$(DESTDIR)@includedir@/json"
ANDROID_CFLAGS = -I$(top_srcdir) -DHAVE_CONFIG_H
Android.mk: Makefile.am
androgenizer -:PROJECT json-c \
-:SHARED libjson-c \
-:TAGS eng debug \
-:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
-:SOURCES $(libjson_c_la_SOURCES) $(nodist_libjson_c_la_SOURCES) \
-:CFLAGS $(DEFS) $(ANDROID_CFLAGS) $(libjson_c_la_CFLAGS) \
-:LDFLAGS $(libjson_c_la_LDFLAGS) $(libjson_c_la_LIBADD) \
-:HEADER_TARGET json-c \
-:HEADERS $(libjson_cinclude_HEADERS) \
-:PASSTHROUGH LOCAL_ARM_MODE:=arm \
> $@

View File

@@ -1,2 +0,0 @@
AM_CFLAGS = -Wall -Werror -Wno-error=deprecated-declarations -Wextra -Wwrite-strings -Wno-unused-parameter -std=gnu99 -D_GNU_SOURCE -D_REENTRANT

View File

View File

@@ -1,50 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>JSON-C - A JSON implementation in C - Win32 specific notes</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
</head>
<body>
<h2>Windows specific notes for JSON-C</h2>
<p>Please send Win32 bug reports to <a href="mailto:christopher.watford@gmail.com">christopher.watford@gmail.com</a></p>
<p><b>Win32 Specific Changes:</b></p>
<ul>
<li>
Various functions have been redefined to their Win32 version (i.e. <tt>open</tt>
on win32 is <tt>_open</tt>)</li>
<li>
Implemented missing functions from MS's libc (i.e. <tt>vasprintf</tt>)</li>
<li>
Added code to allow Win64 support without integer resizing issues, this
probably makes it much nicer on 64bit machines everywhere (i.e. using <tt>ptrdiff_t</tt>
for pointer math)</li>
</ul>
<p><b>Porting Changelog:</b></p>
<dl>
<dt><tt>printbuf.c</tt> - C. Watford (christopher.watford@gmail.com)</dt>
<dd>
Added a Win32/Win64 compliant implementation of <tt>vasprintf</tt></dd>
<dt><tt>debug.c</tt> - C. Watford (christopher.watford@gmail.com)</dt>
<dd>
Removed usage of <tt>vsyslog</tt> on Win32/Win64 systems, needs to be handled
by a configure script</dd>
<dt><tt>json_object.c</tt> - C. Watford (christopher.watford@gmail.com)</dt>
<dd>
Added scope operator to wrap usage of <tt>json_object_object_foreach</tt>, this needs to be
rethought to be more ANSI C friendly</dd>
<dt><tt>json_object.h</tt> - C. Watford (christopher.watford@gmail.com)</dt>
<dd>
Added Microsoft C friendly version of <tt>json_object_object_foreach</tt></dd>
<dt><tt>json_tokener.c</tt> - C. Watford (christopher.watford@gmail.com)</dt>
<dd>
Added a Win32/Win64 compliant implementation of <tt>strndup</tt></dd>
<dt><tt>json_util.c</tt> - C. Watford (christopher.watford@gmail.com)</dt>
<dd>
Added cast and mask to suffice <tt>size_t</tt> v. <tt>unsigned int</tt>
conversion correctness</dd>
</dl>
<p>This program is free software; you can redistribute it and/or modify it under
the terms of the MIT License. See COPYING for details.</p>
<hr />
</body>
</html>

View File

@@ -1,34 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>JSON-C - A JSON implementation in C</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body>
<h2>JSON-C - A JSON implementation in C</h2>
<h3>Overview</h3>
<p>JSON-C implements a reference counting object model that allows you to easily
construct JSON objects in C, output them as JSON formatted strings and parse
JSON formatted strings back into the C representation of JSON objects.</p>
<h3>Building</h3>
<p>To setup JSON-C to build on your system please run <tt>configure</tt> and <tt>make</tt>.</p>
<p>If you are on Win32 and are not using the VS project file, be sure
to rename <tt>config.h.win32</tt> to <tt>config.h</tt> before building.</p>
<h3>Documentation</h3>
<P>Doxygen generated documentation exists <a href="doc/html/json__object_8h.html">here</a>
and Win32 specific notes can be found <a href="README-WIN32.html">here</a>.</P>
<h3><a href="https://github.com/json-c/json-c">GIT Reposository</a></h3>
<p><strong><code>git clone https://github.com/json-c/json-c.git</code></strong></p>
<h3><a href="http://groups.google.com/group/json-c">Mailing List</a></h3>
<pi>Send email to <strong><code>json-c <i>&lt;at&gt;</i> googlegroups <i>&lt;dot&gt;</i> com</code></strong></p>
<h3><a href="COPYING">License</a></h3>
<p>This program is free software; you can redistribute it and/or modify it under the terms of the MIT License..</p>
<hr/>
</body>
</html>

View File

@@ -1,63 +0,0 @@
`json-c`
========
Building on Unix with `git`, `gcc` and `autotools`
--------------------------------------------------
Home page for json-c: https://github.com/json-c/json-c/wiki
Caution: do **NOT** use sources from svn.metaparadigm.com,
they are old.
Prerequisites:
- `gcc`, `clang`, or another C compiler
- `libtool`
If you're not using a release tarball, you'll also need:
- `autoconf` (`autoreconf`)
- `automake`
Make sure you have a complete `libtool` install, including `libtoolize`.
`json-c` GitHub repo: https://github.com/json-c/json-c
```bash
$ git clone https://github.com/json-c/json-c.git
$ cd json-c
$ sh autogen.sh
```
followed by
```bash
$ ./configure
$ make
$ make install
```
To build and run the test programs:
```bash
$ make check
```
Linking to `libjson-c`
----------------------
If your system has `pkgconfig`,
then you can just add this to your `makefile`:
```make
CFLAGS += $(shell pkg-config --cflags json-c)
LDFLAGS += $(shell pkg-config --libs json-c)
```
Without `pkgconfig`, you would do something like this:
```make
JSON_C_DIR=/path/to/json_c/install
CFLAGS += -I$(JSON_C_DIR)/include/json-c
LDFLAGS+= -L$(JSON_C_DIR)/lib -ljson-c
```

View File

@@ -1,132 +0,0 @@
Release checklist:
release=0.12
git clone https://github.com/json-c/json-c json-c-${release}
cd json-c-${release}
Check that the compile works on Linux
Check that the compile works on NetBSD
Check that the compile works on Windows
Check ChangeLog to see if anything should be added.
Make any fixes/changes *before* branching.
git branch json-c-${release}
git checkout json-c-${release}
------------
Update the version in json_c_version.h
Update the version in Doxyfile
Update the version in configure.ac
Use ${release}.
Update the libjson_la_LDFLAGS line in Makefile.am to the new version.
Generally, unless we're doing a major release, change:
-version-info x:y:z
to
-version-info x:y+1:z
------------
Generate the configure script and other files:
sh autogen.sh
git add -f Makefile.in aclocal.m4 config.guess \
config.sub configure depcomp install-sh \
ltmain.sh missing tests/Makefile.in \
INSTALL
# check for anything else to be added:
git status --ignored
git commit
------------
Generate the doxygen documentation:
doxygen
git add -f doc
git commit doc
------------
cd ..
echo .git > excludes
echo autom4te.cache >> excludes
tar -czf json-c-${release}.tar.gz -X excludes json-c-${release}
echo doc >> excludes
tar -czf json-c-${release}-nodoc.tar.gz -X excludes json-c-${release}
------------
Tag the branch:
cd json-c-${release}
git tag -a json-c-${release}-$(date +%Y%m%d) -m "Release json-c-${release}"
git push origin json-c-${release}
git push --tags
------------
Go to Amazon S3 service at:
https://console.aws.amazon.com/s3/
Upload the two tarballs in the json-c_releases folder.
When uploading, use "Reduced Redundancy", and make the uploaded files publicly accessible.
Logout of Amazon S3, and verify that the files are visible.
https://s3.amazonaws.com/json-c_releases/releases/index.html
===================================
Post-release checklist:
git checkout master
Add new section to ChangeLog
Update the version in json_c_version.h
Update the version in Doxyfile
Update the version in configure.ac
Use ${release}.99 to indicate a version "newer" than anything on the branch.
Leave the libjson_la_LDFLAGS line in Makefile.am alone.
For more details see:
http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
------------
Update the gh-pages branch with new docs:
cd json-c-${release}
git checkout json-c-${release}
cd ..
git clone -b gh-pages https://github.com/json-c/json-c json-c-pages
cd json-c-pages
mkdir json-c-${release}
cp -R ../json-c-${release}/doc json-c-${release}/.
cp ../json-c-${release}/README-WIN32.html json-c-${release}/.
git add json-c-${release}
git commit
vi index.html
Add/change links to current release.
git commit index.html
git push
------------
Update checksums on wiki page.
cd ..
openssl sha -sha256 json-c*gz
openssl md5 json-c*gz
Copy and paste this output into the wiki page at:
https://github.com/json-c/json-c/wiki
------------
Send an email to the mailing list.

View File

@@ -1,102 +0,0 @@
/*
* $Id: arraylist.c,v 1.4 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#include "config.h"
#ifdef STDC_HEADERS
# include <stdlib.h>
# include <string.h>
#endif /* STDC_HEADERS */
#if defined(HAVE_STRINGS_H) && !defined(_STRING_H) && !defined(__USE_BSD)
# include <strings.h>
#endif /* HAVE_STRINGS_H */
#include "arraylist.h"
struct array_list*
array_list_new(array_list_free_fn *free_fn)
{
struct array_list *arr;
arr = (struct array_list*)calloc(1, sizeof(struct array_list));
if(!arr) return NULL;
arr->size = ARRAY_LIST_DEFAULT_SIZE;
arr->length = 0;
arr->free_fn = free_fn;
if(!(arr->array = (void**)calloc(sizeof(void*), arr->size))) {
free(arr);
return NULL;
}
return arr;
}
extern void
array_list_free(struct array_list *arr)
{
int i;
for(i = 0; i < arr->length; i++)
if(arr->array[i]) arr->free_fn(arr->array[i]);
free(arr->array);
free(arr);
}
void*
array_list_get_idx(struct array_list *arr, int i)
{
if(i >= arr->length) return NULL;
return arr->array[i];
}
static int array_list_expand_internal(struct array_list *arr, int max)
{
void *t;
int new_size;
if(max < arr->size) return 0;
new_size = arr->size << 1;
if (new_size < max)
new_size = max;
if(!(t = realloc(arr->array, new_size*sizeof(void*)))) return -1;
arr->array = (void**)t;
(void)memset(arr->array + arr->size, 0, (new_size-arr->size)*sizeof(void*));
arr->size = new_size;
return 0;
}
int
array_list_put_idx(struct array_list *arr, int idx, void *data)
{
if(array_list_expand_internal(arr, idx+1)) return -1;
if(arr->array[idx]) arr->free_fn(arr->array[idx]);
arr->array[idx] = data;
if(arr->length <= idx) arr->length = idx + 1;
return 0;
}
int
array_list_add(struct array_list *arr, void *data)
{
return array_list_put_idx(arr, arr->length, data);
}
void
array_list_sort(struct array_list *arr, int(*sort_fn)(const void *, const void *))
{
qsort(arr->array, arr->length, sizeof(arr->array[0]),
(int (*)(const void *, const void *))sort_fn);
}
int
array_list_length(struct array_list *arr)
{
return arr->length;
}

View File

@@ -1,56 +0,0 @@
/*
* $Id: arraylist.h,v 1.4 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#ifndef _arraylist_h_
#define _arraylist_h_
#ifdef __cplusplus
extern "C" {
#endif
#define ARRAY_LIST_DEFAULT_SIZE 32
typedef void (array_list_free_fn) (void *data);
struct array_list
{
void **array;
int length;
int size;
array_list_free_fn *free_fn;
};
extern struct array_list*
array_list_new(array_list_free_fn *free_fn);
extern void
array_list_free(struct array_list *al);
extern void*
array_list_get_idx(struct array_list *al, int i);
extern int
array_list_put_idx(struct array_list *al, int i, void *data);
extern int
array_list_add(struct array_list *al, void *data);
extern int
array_list_length(struct array_list *al);
extern void
array_list_sort(struct array_list *arr, int(*compar)(const void *, const void *));
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,13 +0,0 @@
#!/bin/sh
autoreconf -v --install || exit 1
# If there are any options, assume the user wants to run configure.
# To run configure w/o any options, use ./autogen.sh --configure
if [ $# -gt 0 ] ; then
case "$1" in
--conf*)
shift 1
;;
esac
exec ./configure "$@"
fi

View File

@@ -1,35 +0,0 @@
/**
* @file
* @deprecated Use json_util.h instead.
*
* $Id: bits.h,v 1.10 2006/01/30 23:07:57 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#ifndef _bits_h_
#define _bits_h_
/**
* @deprecated
*/
#define hexdigit(x) (((x) <= '9') ? (x) - '0' : ((x) & 7) + 9)
/**
* @deprecated
*/
#define error_ptr(error) ((void*)error)
/**
* @deprecated
*/
#define error_description(error) (json_tokener_get_error(error))
/**
* @deprecated
*/
#define is_error(ptr) (ptr == NULL)
#endif

View File

@@ -1,178 +0,0 @@
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* Enable RDRANR Hardware RNG Hash Seed */
/* #undef ENABLE_RDRAND */
/* Define if .gnu.warning accepts long strings. */
/* #undef HAS_GNU_WARNING_LONG */
/* Define to 1 if you have the declaration of `INFINITY', and to 0 if you
don't. */
#define HAVE_DECL_INFINITY 1
/* Define to 1 if you have the declaration of `isinf', and to 0 if you don't.
*/
#define HAVE_DECL_ISINF 1
/* Define to 1 if you have the declaration of `isnan', and to 0 if you don't.
*/
#define HAVE_DECL_ISNAN 1
/* Define to 1 if you have the declaration of `nan', and to 0 if you don't. */
#define HAVE_DECL_NAN 1
/* Define to 1 if you have the declaration of `_finite', and to 0 if you
don't. */
#define HAVE_DECL__FINITE 0
/* Define to 1 if you have the declaration of `_isnan', and to 0 if you don't.
*/
#define HAVE_DECL__ISNAN 0
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
/* #undef HAVE_DOPRNT */
/* Define to 1 if you have the <endian.h> header file. */
#define HAVE_ENDIAN_H 1
/* Define to 1 if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the <limits.h> header file. */
#define HAVE_LIMITS_H 1
/* Define to 1 if you have the <locale.h> header file. */
#define HAVE_LOCALE_H 1
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
to 0 otherwise. */
#define HAVE_MALLOC 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the `open' function. */
#define HAVE_OPEN 1
/* Define to 1 if your system has a GNU libc compatible `realloc' function,
and to 0 otherwise. */
#define HAVE_REALLOC 1
/* Define to 1 if you have the `setlocale' function. */
#define HAVE_SETLOCALE 1
/* Define to 1 if you have the `snprintf' function. */
#define HAVE_SNPRINTF 1
/* Define to 1 if you have the <stdarg.h> header file. */
#define HAVE_STDARG_H 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the `strcasecmp' function. */
#define HAVE_STRCASECMP 1
/* Define to 1 if you have the `strdup' function. */
#define HAVE_STRDUP 1
/* Define to 1 if you have the `strerror' function. */
#define HAVE_STRERROR 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the `strncasecmp' function. */
#define HAVE_STRNCASECMP 1
/* Define to 1 if you have the <syslog.h> header file. */
#define HAVE_SYSLOG_H 1
/* Define to 1 if you have the <sys/cdefs.h> header file. */
#define HAVE_SYS_CDEFS_H 1
/* Define to 1 if you have the <sys/param.h> header file. */
#define HAVE_SYS_PARAM_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if you have the `vasprintf' function. */
#define HAVE_VASPRINTF 1
/* Define to 1 if you have the `vprintf' function. */
#define HAVE_VPRINTF 1
/* Define to 1 if you have the `vsnprintf' function. */
#define HAVE_VSNPRINTF 1
/* Define to 1 if you have the `vsyslog' function. */
#define HAVE_VSYSLOG 1
/* Public define for json_inttypes.h */
#define JSON_C_HAVE_INTTYPES_H 1
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#define LT_OBJDIR ".libs/"
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
/* #undef NO_MINUS_C_MINUS_O */
/* Name of package */
#define PACKAGE "json-c"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "json-c@googlegroups.com"
/* Define to the full name of this package. */
#define PACKAGE_NAME "json-c"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "json-c 0.12.99"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "json-c"
/* Define to the home page for this package. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "0.12.99"
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Version number of package */
#define VERSION "0.12.99"
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
/* Define to rpl_malloc if the replacement function should be used. */
/* #undef malloc */
/* Define to rpl_realloc if the replacement function should be used. */
/* #undef realloc */
/* Define to `unsigned int' if <sys/types.h> does not define. */
/* #undef size_t */

View File

@@ -1,177 +0,0 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* Enable RDRANR Hardware RNG Hash Seed */
#undef ENABLE_RDRAND
/* Define if .gnu.warning accepts long strings. */
#undef HAS_GNU_WARNING_LONG
/* Define to 1 if you have the declaration of `INFINITY', and to 0 if you
don't. */
#undef HAVE_DECL_INFINITY
/* Define to 1 if you have the declaration of `isinf', and to 0 if you don't.
*/
#undef HAVE_DECL_ISINF
/* Define to 1 if you have the declaration of `isnan', and to 0 if you don't.
*/
#undef HAVE_DECL_ISNAN
/* Define to 1 if you have the declaration of `nan', and to 0 if you don't. */
#undef HAVE_DECL_NAN
/* Define to 1 if you have the declaration of `_finite', and to 0 if you
don't. */
#undef HAVE_DECL__FINITE
/* Define to 1 if you have the declaration of `_isnan', and to 0 if you don't.
*/
#undef HAVE_DECL__ISNAN
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
#undef HAVE_DOPRNT
/* Define to 1 if you have the <endian.h> header file. */
#undef HAVE_ENDIAN_H
/* Define to 1 if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H
/* Define to 1 if you have the <locale.h> header file. */
#undef HAVE_LOCALE_H
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
to 0 otherwise. */
#undef HAVE_MALLOC
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `open' function. */
#undef HAVE_OPEN
/* Define to 1 if your system has a GNU libc compatible `realloc' function,
and to 0 otherwise. */
#undef HAVE_REALLOC
/* Define to 1 if you have the `setlocale' function. */
#undef HAVE_SETLOCALE
/* Define to 1 if you have the `snprintf' function. */
#undef HAVE_SNPRINTF
/* Define to 1 if you have the <stdarg.h> header file. */
#undef HAVE_STDARG_H
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the `strcasecmp' function. */
#undef HAVE_STRCASECMP
/* Define to 1 if you have the `strdup' function. */
#undef HAVE_STRDUP
/* Define to 1 if you have the `strerror' function. */
#undef HAVE_STRERROR
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the `strncasecmp' function. */
#undef HAVE_STRNCASECMP
/* Define to 1 if you have the <syslog.h> header file. */
#undef HAVE_SYSLOG_H
/* Define to 1 if you have the <sys/cdefs.h> header file. */
#undef HAVE_SYS_CDEFS_H
/* Define to 1 if you have the <sys/param.h> header file. */
#undef HAVE_SYS_PARAM_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if you have the `vasprintf' function. */
#undef HAVE_VASPRINTF
/* Define to 1 if you have the `vprintf' function. */
#undef HAVE_VPRINTF
/* Define to 1 if you have the `vsnprintf' function. */
#undef HAVE_VSNPRINTF
/* Define to 1 if you have the `vsyslog' function. */
#undef HAVE_VSYSLOG
/* Public define for json_inttypes.h */
#undef JSON_C_HAVE_INTTYPES_H
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#undef LT_OBJDIR
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
#undef NO_MINUS_C_MINUS_O
/* Name of package */
#undef PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Version number of package */
#undef VERSION
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
/* Define to rpl_malloc if the replacement function should be used. */
#undef malloc
/* Define to rpl_realloc if the replacement function should be used. */
#undef realloc
/* Define to `unsigned int' if <sys/types.h> does not define. */
#undef size_t

View File

@@ -1,107 +0,0 @@
AC_PREREQ(2.52)
# Process this file with autoconf to produce a configure script.
AC_INIT([json-c], 0.12.99, [json-c@googlegroups.com])
AM_INIT_AUTOMAKE
AC_PROG_MAKE_SET
AC_ARG_ENABLE(rdrand,
AS_HELP_STRING([--enable-rdrand],
[Enable RDRAND Hardware RNG Hash Seed generation on supported x86/x64 platforms.]),
[if test x$enableval = xyes; then
enable_rdrand=yes
AC_DEFINE(ENABLE_RDRAND, 1, [Enable RDRANR Hardware RNG Hash Seed])
fi])
if test "x$enable_rdrand" = "xyes"; then
AC_MSG_RESULT([RDRAND Hardware RNG Hash Seed enabled on supported x86/x64 platforms])
else
AC_MSG_RESULT([RDRAND Hardware RNG Hash Seed disabled. Use --enable-rdrand to enable])
fi
# Checks for programs.
# Checks for libraries.
# Checks for header files.
AM_PROG_CC_C_O
AC_CONFIG_HEADER(config.h)
AC_CONFIG_HEADER(json_config.h)
AC_HEADER_STDC
AC_CHECK_HEADERS(fcntl.h limits.h strings.h syslog.h unistd.h [sys/cdefs.h] [sys/param.h] stdarg.h locale.h endian.h)
AC_CHECK_HEADER(inttypes.h,[AC_DEFINE([JSON_C_HAVE_INTTYPES_H],[1],[Public define for json_inttypes.h])])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_TYPE_SIZE_T
# Checks for library functions.
AC_FUNC_VPRINTF
AC_FUNC_MEMCMP
AC_FUNC_MALLOC
AC_FUNC_REALLOC
AC_CHECK_FUNCS(strcasecmp strdup strerror snprintf vsnprintf vasprintf open vsyslog strncasecmp setlocale)
AC_CHECK_DECLS([INFINITY], [], [], [[#include <math.h>]])
AC_CHECK_DECLS([nan], [], [], [[#include <math.h>]])
AC_CHECK_DECLS([isnan], [], [], [[#include <math.h>]])
AC_CHECK_DECLS([isinf], [], [], [[#include <math.h>]])
AC_CHECK_DECLS([_isnan], [], [], [[#include <float.h>]])
AC_CHECK_DECLS([_finite], [], [], [[#include <float.h>]])
#check if .section.gnu.warning accepts long strings (for __warn_references)
AC_LANG_PUSH([C])
AC_MSG_CHECKING([if .gnu.warning accepts long strings])
AC_LINK_IFELSE([AC_LANG_SOURCE([[
extern void json_object_get();
__asm__(".section .gnu.json_object_get,\n\t.ascii \"Please link against libjson-c instead of libjson\"\n\t.text");
int main(int c,char* v) {return 0;}
]])], [
AC_DEFINE(HAS_GNU_WARNING_LONG, 1, [Define if .gnu.warning accepts long strings.])
AC_MSG_RESULT(yes)
], [
AC_MSG_RESULT(no)
])
AC_LANG_POP([C])
AM_PROG_LIBTOOL
# Check for the -Bsymbolic-functions linker flag
AC_ARG_ENABLE([Bsymbolic],
[AS_HELP_STRING([--disable-Bsymbolic], [Avoid linking with -Bsymbolic-function])],
[],
[enable_Bsymbolic=check])
AS_IF([test "x$enable_Bsymbolic" = "xcheck"],
[
saved_LDFLAGS="${LDFLAGS}"
AC_MSG_CHECKING([for -Bsymbolic-functions linker flag])
LDFLAGS=-Wl,-Bsymbolic-functions
AC_TRY_LINK([], [int main (void) { return 0; }],
[
AC_MSG_RESULT([yes])
enable_Bsymbolic=yes
],
[
AC_MSG_RESULT([no])
enable_Bsymbolic=no
])
LDFLAGS="${saved_LDFLAGS}"
])
AS_IF([test "x$enable_Bsymbolic" = "xyes"], [JSON_BSYMBOLIC_LDFLAGS=-Wl[,]-Bsymbolic-functions])
AC_SUBST(JSON_BSYMBOLIC_LDFLAGS)
AC_CONFIG_FILES([
Makefile
json-c.pc
tests/Makefile
json-c-uninstalled.pc
])
AC_OUTPUT

View File

@@ -1,83 +0,0 @@
/*
* $Id: debug.c,v 1.5 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#if HAVE_SYSLOG_H
# include <syslog.h>
#endif /* HAVE_SYSLOG_H */
#if HAVE_UNISTD_H
# include <unistd.h>
#endif /* HAVE_UNISTD_H */
#if HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif /* HAVE_SYS_PARAM_H */
#include "debug.h"
static int _syslog = 0;
static int _debug = 0;
void mc_set_debug(int debug) { _debug = debug; }
int mc_get_debug(void) { return _debug; }
extern void mc_set_syslog(int syslog)
{
_syslog = syslog;
}
void mc_debug(const char *msg, ...)
{
va_list ap;
if(_debug) {
va_start(ap, msg);
#if HAVE_VSYSLOG
if(_syslog) {
vsyslog(LOG_DEBUG, msg, ap);
} else
#endif
vprintf(msg, ap);
va_end(ap);
}
}
void mc_error(const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
#if HAVE_VSYSLOG
if(_syslog) {
vsyslog(LOG_ERR, msg, ap);
} else
#endif
vfprintf(stderr, msg, ap);
va_end(ap);
}
void mc_info(const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
#if HAVE_VSYSLOG
if(_syslog) {
vsyslog(LOG_INFO, msg, ap);
} else
#endif
vfprintf(stderr, msg, ap);
va_end(ap);
}

View File

@@ -1,71 +0,0 @@
/*
* $Id: debug.h,v 1.5 2006/01/30 23:07:57 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#ifndef _DEBUG_H_
#define _DEBUG_H_
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
extern void mc_set_debug(int debug);
extern int mc_get_debug(void);
extern void mc_set_syslog(int syslog);
extern void mc_debug(const char *msg, ...);
extern void mc_error(const char *msg, ...);
extern void mc_info(const char *msg, ...);
#ifndef __STRING
#define __STRING(x) #x
#endif
#ifndef PARSER_BROKEN_FIXED
#define JASSERT(cond) do {} while(0)
#else
#define JASSERT(cond) do { \
if (!(cond)) { \
mc_error("cjson assert failure %s:%d : cond \"" __STRING(cond) "failed\n", __FILE__, __LINE__); \
*(int *)0 = 1;\
abort(); \
}\
} while(0)
#endif
#define MC_ERROR(x, ...) mc_error(x, ##__VA_ARGS__)
#ifdef MC_MAINTAINER_MODE
#define MC_SET_DEBUG(x) mc_set_debug(x)
#define MC_GET_DEBUG() mc_get_debug()
#define MC_SET_SYSLOG(x) mc_set_syslog(x)
#define MC_DEBUG(x, ...) mc_debug(x, ##__VA_ARGS__)
#define MC_INFO(x, ...) mc_info(x, ##__VA_ARGS__)
#else
#define MC_SET_DEBUG(x) if (0) mc_set_debug(x)
#define MC_GET_DEBUG() (0)
#define MC_SET_SYSLOG(x) if (0) mc_set_syslog(x)
#define MC_DEBUG(x, ...) if (0) mc_debug(x, ##__VA_ARGS__)
#define MC_INFO(x, ...) if (0) mc_info(x, ##__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,11 +0,0 @@
prefix=
exec_prefix=
libdir=@abs_top_builddir@
includedir=@abs_top_srcdir@
Name: json
Description: JSON implementation in C
Version: @VERSION@
Requires:
Libs: -L@abs_top_builddir@ -ljson-c
Cflags: -I@abs_top_srcdir@

View File

@@ -1,11 +0,0 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: json-c
Description: JSON implementation in C
Version: @VERSION@
Requires:
Libs: -L${libdir} -ljson-c
Cflags: -I${includedir}/json-c

View File

@@ -1,33 +0,0 @@
/*
* $Id: json.h,v 1.6 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#ifndef _json_h_
#define _json_h_
#ifdef __cplusplus
extern "C" {
#endif
#include "debug.h"
#include "linkhash.h"
#include "arraylist.h"
#include "json_util.h"
#include "json_object.h"
#include "json_tokener.h"
#include "json_object_iterator.h"
#include "json_c_version.h"
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,20 +0,0 @@
/*
* Copyright (c) 2012 Eric Haszlakiewicz
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*/
#include "config.h"
#include "json_c_version.h"
const char *json_c_version(void)
{
return JSON_C_VERSION;
}
int json_c_version_num(void)
{
return JSON_C_VERSION_NUM;
}

View File

@@ -1,22 +0,0 @@
/*
* Copyright (c) 2012 Eric Haszlakiewicz
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*/
#ifndef _json_c_version_h_
#define _json_c_version_h_
#define JSON_C_MAJOR_VERSION 0
#define JSON_C_MINOR_VERSION 12
#define JSON_C_MICRO_VERSION 99
#define JSON_C_VERSION_NUM ((JSON_C_MAJOR_VERSION << 16) | \
(JSON_C_MINOR_VERSION << 8) | \
JSON_C_MICRO_VERSION)
#define JSON_C_VERSION "0.12.99"
const char *json_c_version(void); /* Returns JSON_C_VERSION */
int json_c_version_num(void); /* Returns JSON_C_VERSION_NUM */
#endif

View File

@@ -1,4 +0,0 @@
/* json_config.h. Generated from json_config.h.in by configure. */
/* Define to 1 if you have the <inttypes.h> header file. */
#define JSON_C_HAVE_INTTYPES_H 1

View File

@@ -1,3 +0,0 @@
/* Define to 1 if you have the <inttypes.h> header file. */
#undef JSON_C_HAVE_INTTYPES_H

View File

@@ -1,28 +0,0 @@
#ifndef _json_inttypes_h_
#define _json_inttypes_h_
#include "json_config.h"
#if defined(_MSC_VER) && _MSC_VER <= 1700
/* Anything less than Visual Studio C++ 10 is missing stdint.h and inttypes.h */
typedef __int32 int32_t;
#define INT32_MIN ((int32_t)_I32_MIN)
#define INT32_MAX ((int32_t)_I32_MAX)
typedef __int64 int64_t;
#define INT64_MIN ((int64_t)_I64_MIN)
#define INT64_MAX ((int64_t)_I64_MAX)
#define PRId64 "I64d"
#define SCNd64 "I64d"
#else
#ifdef JSON_C_HAVE_INTTYPES_H
#include <inttypes.h>
#endif
/* inttypes.h includes stdint.h */
#endif
#endif

View File

@@ -1,913 +0,0 @@
/*
* $Id: json_object.c,v 1.17 2006/07/25 03:24:50 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <math.h>
#include <errno.h>
#include "debug.h"
#include "printbuf.h"
#include "linkhash.h"
#include "arraylist.h"
#include "json_inttypes.h"
#include "json_object.h"
#include "json_object_private.h"
#include "json_util.h"
#include "math_compat.h"
#if !defined(HAVE_STRDUP) && defined(_MSC_VER)
/* MSC has the version as _strdup */
# define strdup _strdup
#elif !defined(HAVE_STRDUP)
# error You do not have strdup on your system.
#endif /* HAVE_STRDUP */
#if !defined(HAVE_SNPRINTF) && defined(_MSC_VER)
/* MSC has the version as _snprintf */
# define snprintf _snprintf
#elif !defined(HAVE_SNPRINTF)
# error You do not have snprintf on your system.
#endif /* HAVE_SNPRINTF */
// Don't define this. It's not thread-safe.
/* #define REFCOUNT_DEBUG 1 */
const char *json_number_chars = "0123456789.+-eE";
const char *json_hex_chars = "0123456789abcdefABCDEF";
static void json_object_generic_delete(struct json_object* jso);
static struct json_object* json_object_new(enum json_type o_type);
static json_object_to_json_string_fn json_object_object_to_json_string;
static json_object_to_json_string_fn json_object_boolean_to_json_string;
static json_object_to_json_string_fn json_object_int_to_json_string;
static json_object_to_json_string_fn json_object_double_to_json_string;
static json_object_to_json_string_fn json_object_string_to_json_string;
static json_object_to_json_string_fn json_object_array_to_json_string;
/* ref count debugging */
#ifdef REFCOUNT_DEBUG
static struct lh_table *json_object_table;
static void json_object_init(void) __attribute__ ((constructor));
static void json_object_init(void) {
MC_DEBUG("json_object_init: creating object table\n");
json_object_table = lh_kptr_table_new(128, "json_object_table", NULL);
}
static void json_object_fini(void) __attribute__ ((destructor));
static void json_object_fini(void)
{
struct lh_entry *ent;
if (MC_GET_DEBUG())
{
if (json_object_table->count)
{
MC_DEBUG("json_object_fini: %d referenced objects at exit\n",
json_object_table->count);
lh_foreach(json_object_table, ent)
{
struct json_object* obj = (struct json_object*)ent->v;
MC_DEBUG("\t%s:%p\n", json_type_to_name(obj->o_type), obj);
}
}
}
MC_DEBUG("json_object_fini: freeing object table\n");
lh_table_free(json_object_table);
}
#endif /* REFCOUNT_DEBUG */
/* string escaping */
static int json_escape_str(struct printbuf *pb, char *str, int len)
{
int pos = 0, start_offset = 0;
unsigned char c;
while (len--)
{
c = str[pos];
switch(c)
{
case '\b':
case '\n':
case '\r':
case '\t':
case '\f':
case '"':
case '\\':
case '/':
if(pos - start_offset > 0)
printbuf_memappend(pb, str + start_offset, pos - start_offset);
if(c == '\b') printbuf_memappend(pb, "\\b", 2);
else if(c == '\n') printbuf_memappend(pb, "\\n", 2);
else if(c == '\r') printbuf_memappend(pb, "\\r", 2);
else if(c == '\t') printbuf_memappend(pb, "\\t", 2);
else if(c == '\f') printbuf_memappend(pb, "\\f", 2);
else if(c == '"') printbuf_memappend(pb, "\\\"", 2);
else if(c == '\\') printbuf_memappend(pb, "\\\\", 2);
else if(c == '/') printbuf_memappend(pb, "\\/", 2);
start_offset = ++pos;
break;
default:
if(c < ' ')
{
if(pos - start_offset > 0)
printbuf_memappend(pb, str + start_offset, pos - start_offset);
sprintbuf(pb, "\\u00%c%c",
json_hex_chars[c >> 4],
json_hex_chars[c & 0xf]);
start_offset = ++pos;
} else
pos++;
}
}
if (pos - start_offset > 0)
printbuf_memappend(pb, str + start_offset, pos - start_offset);
return 0;
}
/* reference counting */
extern struct json_object* json_object_get(struct json_object *jso)
{
if (jso)
jso->_ref_count++;
return jso;
}
int json_object_put(struct json_object *jso)
{
if(jso)
{
jso->_ref_count--;
if(!jso->_ref_count)
{
if (jso->_user_delete)
jso->_user_delete(jso, jso->_userdata);
jso->_delete(jso);
return 1;
}
}
return 0;
}
/* generic object construction and destruction parts */
static void json_object_generic_delete(struct json_object* jso)
{
#ifdef REFCOUNT_DEBUG
MC_DEBUG("json_object_delete_%s: %p\n",
json_type_to_name(jso->o_type), jso);
lh_table_delete(json_object_table, jso);
#endif /* REFCOUNT_DEBUG */
printbuf_free(jso->_pb);
free(jso);
}
static struct json_object* json_object_new(enum json_type o_type)
{
struct json_object *jso;
jso = (struct json_object*)calloc(sizeof(struct json_object), 1);
if (!jso)
return NULL;
jso->o_type = o_type;
jso->_ref_count = 1;
jso->_delete = &json_object_generic_delete;
#ifdef REFCOUNT_DEBUG
lh_table_insert(json_object_table, jso, jso);
MC_DEBUG("json_object_new_%s: %p\n", json_type_to_name(jso->o_type), jso);
#endif /* REFCOUNT_DEBUG */
return jso;
}
/* type checking functions */
int json_object_is_type(struct json_object *jso, enum json_type type)
{
if (!jso)
return (type == json_type_null);
return (jso->o_type == type);
}
enum json_type json_object_get_type(struct json_object *jso)
{
if (!jso)
return json_type_null;
return jso->o_type;
}
/* set a custom conversion to string */
void json_object_set_serializer(json_object *jso,
json_object_to_json_string_fn to_string_func,
void *userdata,
json_object_delete_fn *user_delete)
{
// First, clean up any previously existing user info
if (jso->_user_delete)
{
jso->_user_delete(jso, jso->_userdata);
}
jso->_userdata = NULL;
jso->_user_delete = NULL;
if (to_string_func == NULL)
{
// Reset to the standard serialization function
switch(jso->o_type)
{
case json_type_null:
jso->_to_json_string = NULL;
break;
case json_type_boolean:
jso->_to_json_string = &json_object_boolean_to_json_string;
break;
case json_type_double:
jso->_to_json_string = &json_object_double_to_json_string;
break;
case json_type_int:
jso->_to_json_string = &json_object_int_to_json_string;
break;
case json_type_object:
jso->_to_json_string = &json_object_object_to_json_string;
break;
case json_type_array:
jso->_to_json_string = &json_object_array_to_json_string;
break;
case json_type_string:
jso->_to_json_string = &json_object_string_to_json_string;
break;
}
return;
}
jso->_to_json_string = to_string_func;
jso->_userdata = userdata;
jso->_user_delete = user_delete;
}
/* extended conversion to string */
const char* json_object_to_json_string_ext(struct json_object *jso, int flags)
{
if (!jso)
return "null";
if ((!jso->_pb) && !(jso->_pb = printbuf_new()))
return NULL;
printbuf_reset(jso->_pb);
if(jso->_to_json_string(jso, jso->_pb, 0, flags) < 0)
return NULL;
return jso->_pb->buf;
}
/* backwards-compatible conversion to string */
const char* json_object_to_json_string(struct json_object *jso)
{
return json_object_to_json_string_ext(jso, JSON_C_TO_STRING_SPACED);
}
static void indent(struct printbuf *pb, int level, int flags)
{
if (flags & JSON_C_TO_STRING_PRETTY)
{
printbuf_memset(pb, -1, ' ', level * 2);
}
}
/* json_object_object */
static int json_object_object_to_json_string(struct json_object* jso,
struct printbuf *pb,
int level,
int flags)
{
int had_children = 0;
struct json_object_iter iter;
sprintbuf(pb, "{" /*}*/);
if (flags & JSON_C_TO_STRING_PRETTY)
sprintbuf(pb, "\n");
json_object_object_foreachC(jso, iter)
{
if (had_children)
{
sprintbuf(pb, ",");
if (flags & JSON_C_TO_STRING_PRETTY)
sprintbuf(pb, "\n");
}
had_children = 1;
if (flags & JSON_C_TO_STRING_SPACED)
sprintbuf(pb, " ");
indent(pb, level+1, flags);
sprintbuf(pb, "\"");
json_escape_str(pb, iter.key, strlen(iter.key));
if (flags & JSON_C_TO_STRING_SPACED)
sprintbuf(pb, "\": ");
else
sprintbuf(pb, "\":");
if(iter.val == NULL)
sprintbuf(pb, "null");
else
iter.val->_to_json_string(iter.val, pb, level+1,flags);
}
if (flags & JSON_C_TO_STRING_PRETTY)
{
if (had_children)
sprintbuf(pb, "\n");
indent(pb,level,flags);
}
if (flags & JSON_C_TO_STRING_SPACED)
return sprintbuf(pb, /*{*/ " }");
else
return sprintbuf(pb, /*{*/ "}");
}
static void json_object_lh_entry_free(struct lh_entry *ent)
{
free(ent->k);
json_object_put((struct json_object*)ent->v);
}
static void json_object_object_delete(struct json_object* jso)
{
lh_table_free(jso->o.c_object);
json_object_generic_delete(jso);
}
struct json_object* json_object_new_object(void)
{
struct json_object *jso = json_object_new(json_type_object);
if (!jso)
return NULL;
jso->_delete = &json_object_object_delete;
jso->_to_json_string = &json_object_object_to_json_string;
jso->o.c_object = lh_kchar_table_new(JSON_OBJECT_DEF_HASH_ENTRIES,
NULL, &json_object_lh_entry_free);
if (!jso->o.c_object)
{
json_object_generic_delete(jso);
errno = ENOMEM;
return NULL;
}
return jso;
}
struct lh_table* json_object_get_object(struct json_object *jso)
{
if (!jso)
return NULL;
switch(jso->o_type)
{
case json_type_object:
return jso->o.c_object;
default:
return NULL;
}
}
void json_object_object_add(struct json_object* jso, const char *key,
struct json_object *val)
{
// We lookup the entry and replace the value, rather than just deleting
// and re-adding it, so the existing key remains valid.
json_object *existing_value = NULL;
struct lh_entry *existing_entry;
existing_entry = lh_table_lookup_entry(jso->o.c_object, (void*)key);
if (!existing_entry)
{
lh_table_insert(jso->o.c_object, strdup(key), val);
return;
}
existing_value = (void *)existing_entry->v;
if (existing_value)
json_object_put(existing_value);
existing_entry->v = val;
}
int json_object_object_length(struct json_object *jso)
{
return lh_table_length(jso->o.c_object);
}
struct json_object* json_object_object_get(struct json_object* jso, const char *key)
{
struct json_object *result = NULL;
json_object_object_get_ex(jso, key, &result);
return result;
}
json_bool json_object_object_get_ex(struct json_object* jso, const char *key, struct json_object **value)
{
if (value != NULL)
*value = NULL;
if (NULL == jso)
return FALSE;
switch(jso->o_type)
{
case json_type_object:
return lh_table_lookup_ex(jso->o.c_object, (void*)key, (void**)value);
default:
if (value != NULL)
*value = NULL;
return FALSE;
}
}
void json_object_object_del(struct json_object* jso, const char *key)
{
lh_table_delete(jso->o.c_object, key);
}
/* json_object_boolean */
static int json_object_boolean_to_json_string(struct json_object* jso,
struct printbuf *pb,
int level,
int flags)
{
if (jso->o.c_boolean)
return sprintbuf(pb, "true");
else
return sprintbuf(pb, "false");
}
struct json_object* json_object_new_boolean(json_bool b)
{
struct json_object *jso = json_object_new(json_type_boolean);
if (!jso)
return NULL;
jso->_to_json_string = &json_object_boolean_to_json_string;
jso->o.c_boolean = b;
return jso;
}
json_bool json_object_get_boolean(struct json_object *jso)
{
if (!jso)
return FALSE;
switch(jso->o_type)
{
case json_type_boolean:
return jso->o.c_boolean;
case json_type_int:
return (jso->o.c_int64 != 0);
case json_type_double:
return (jso->o.c_double != 0);
case json_type_string:
return (jso->o.c_string.len != 0);
default:
return FALSE;
}
}
/* json_object_int */
static int json_object_int_to_json_string(struct json_object* jso,
struct printbuf *pb,
int level,
int flags)
{
return sprintbuf(pb, "%"PRId64, jso->o.c_int64);
}
struct json_object* json_object_new_int(int32_t i)
{
struct json_object *jso = json_object_new(json_type_int);
if (!jso)
return NULL;
jso->_to_json_string = &json_object_int_to_json_string;
jso->o.c_int64 = i;
return jso;
}
int32_t json_object_get_int(struct json_object *jso)
{
int64_t cint64;
enum json_type o_type;
if(!jso) return 0;
o_type = jso->o_type;
cint64 = jso->o.c_int64;
if (o_type == json_type_string)
{
/*
* Parse strings into 64-bit numbers, then use the
* 64-to-32-bit number handling below.
*/
if (json_parse_int64(jso->o.c_string.str, &cint64) != 0)
return 0; /* whoops, it didn't work. */
o_type = json_type_int;
}
switch(o_type) {
case json_type_int:
/* Make sure we return the correct values for out of range numbers. */
if (cint64 <= INT32_MIN)
return INT32_MIN;
else if (cint64 >= INT32_MAX)
return INT32_MAX;
else
return (int32_t)cint64;
case json_type_double:
return (int32_t)jso->o.c_double;
case json_type_boolean:
return jso->o.c_boolean;
default:
return 0;
}
}
struct json_object* json_object_new_int64(int64_t i)
{
struct json_object *jso = json_object_new(json_type_int);
if (!jso)
return NULL;
jso->_to_json_string = &json_object_int_to_json_string;
jso->o.c_int64 = i;
return jso;
}
int64_t json_object_get_int64(struct json_object *jso)
{
int64_t cint;
if (!jso)
return 0;
switch(jso->o_type)
{
case json_type_int:
return jso->o.c_int64;
case json_type_double:
return (int64_t)jso->o.c_double;
case json_type_boolean:
return jso->o.c_boolean;
case json_type_string:
if (json_parse_int64(jso->o.c_string.str, &cint) == 0)
return cint;
default:
return 0;
}
}
/* json_object_double */
static int json_object_double_to_json_string(struct json_object* jso,
struct printbuf *pb,
int level,
int flags)
{
char buf[128], *p, *q;
int size;
/* Although JSON RFC does not support
NaN or Infinity as numeric values
ECMA 262 section 9.8.1 defines
how to handle these cases as strings */
if(isnan(jso->o.c_double))
size = snprintf(buf, sizeof(buf), "NaN");
else if(isinf(jso->o.c_double))
if(jso->o.c_double > 0)
size = snprintf(buf, sizeof(buf), "Infinity");
else
size = snprintf(buf, sizeof(buf), "-Infinity");
else
size = snprintf(buf, sizeof(buf), "%.17g", jso->o.c_double);
p = strchr(buf, ',');
if (p) {
*p = '.';
} else {
p = strchr(buf, '.');
}
if (p && (flags & JSON_C_TO_STRING_NOZERO)) {
/* last useful digit, always keep 1 zero */
p++;
for (q=p ; *q ; q++) {
if (*q!='0') p=q;
}
/* drop trailing zeroes */
*(++p) = 0;
size = p-buf;
}
printbuf_memappend(pb, buf, size);
return size;
}
struct json_object* json_object_new_double(double d)
{
struct json_object *jso = json_object_new(json_type_double);
if (!jso)
return NULL;
jso->_to_json_string = &json_object_double_to_json_string;
jso->o.c_double = d;
return jso;
}
struct json_object* json_object_new_double_s(double d, const char *ds)
{
struct json_object *jso = json_object_new_double(d);
if (!jso)
return NULL;
char *new_ds = strdup(ds);
if (!new_ds)
{
json_object_generic_delete(jso);
errno = ENOMEM;
return NULL;
}
json_object_set_serializer(jso, json_object_userdata_to_json_string,
new_ds, json_object_free_userdata);
return jso;
}
int json_object_userdata_to_json_string(struct json_object *jso,
struct printbuf *pb, int level, int flags)
{
int userdata_len = strlen(jso->_userdata);
printbuf_memappend(pb, jso->_userdata, userdata_len);
return userdata_len;
}
void json_object_free_userdata(struct json_object *jso, void *userdata)
{
free(userdata);
}
double json_object_get_double(struct json_object *jso)
{
double cdouble;
char *errPtr = NULL;
if(!jso) return 0.0;
switch(jso->o_type) {
case json_type_double:
return jso->o.c_double;
case json_type_int:
return jso->o.c_int64;
case json_type_boolean:
return jso->o.c_boolean;
case json_type_string:
errno = 0;
cdouble = strtod(jso->o.c_string.str,&errPtr);
/* if conversion stopped at the first character, return 0.0 */
if (errPtr == jso->o.c_string.str)
return 0.0;
/*
* Check that the conversion terminated on something sensible
*
* For example, { "pay" : 123AB } would parse as 123.
*/
if (*errPtr != '\0')
return 0.0;
/*
* If strtod encounters a string which would exceed the
* capacity of a double, it returns +/- HUGE_VAL and sets
* errno to ERANGE. But +/- HUGE_VAL is also a valid result
* from a conversion, so we need to check errno.
*
* Underflow also sets errno to ERANGE, but it returns 0 in
* that case, which is what we will return anyway.
*
* See CERT guideline ERR30-C
*/
if ((HUGE_VAL == cdouble || -HUGE_VAL == cdouble) &&
(ERANGE == errno))
cdouble = 0.0;
return cdouble;
default:
return 0.0;
}
}
/* json_object_string */
static int json_object_string_to_json_string(struct json_object* jso,
struct printbuf *pb,
int level,
int flags)
{
sprintbuf(pb, "\"");
json_escape_str(pb, jso->o.c_string.str, jso->o.c_string.len);
sprintbuf(pb, "\"");
return 0;
}
static void json_object_string_delete(struct json_object* jso)
{
free(jso->o.c_string.str);
json_object_generic_delete(jso);
}
struct json_object* json_object_new_string(const char *s)
{
struct json_object *jso = json_object_new(json_type_string);
if (!jso)
return NULL;
jso->_delete = &json_object_string_delete;
jso->_to_json_string = &json_object_string_to_json_string;
jso->o.c_string.str = strdup(s);
if (!jso->o.c_string.str)
{
json_object_generic_delete(jso);
errno = ENOMEM;
return NULL;
}
jso->o.c_string.len = strlen(s);
return jso;
}
struct json_object* json_object_new_string_len(const char *s, int len)
{
struct json_object *jso = json_object_new(json_type_string);
if (!jso)
return NULL;
jso->_delete = &json_object_string_delete;
jso->_to_json_string = &json_object_string_to_json_string;
jso->o.c_string.str = (char*)malloc(len + 1);
if (!jso->o.c_string.str)
{
json_object_generic_delete(jso);
errno = ENOMEM;
return NULL;
}
memcpy(jso->o.c_string.str, (void *)s, len);
jso->o.c_string.str[len] = '\0';
jso->o.c_string.len = len;
return jso;
}
const char* json_object_get_string(struct json_object *jso)
{
if (!jso)
return NULL;
switch(jso->o_type)
{
case json_type_string:
return jso->o.c_string.str;
default:
return json_object_to_json_string(jso);
}
}
int json_object_get_string_len(struct json_object *jso)
{
if (!jso)
return 0;
switch(jso->o_type)
{
case json_type_string:
return jso->o.c_string.len;
default:
return 0;
}
}
/* json_object_array */
static int json_object_array_to_json_string(struct json_object* jso,
struct printbuf *pb,
int level,
int flags)
{
int had_children = 0;
int ii;
sprintbuf(pb, "[");
if (flags & JSON_C_TO_STRING_PRETTY)
sprintbuf(pb, "\n");
for(ii=0; ii < json_object_array_length(jso); ii++)
{
struct json_object *val;
if (had_children)
{
sprintbuf(pb, ",");
if (flags & JSON_C_TO_STRING_PRETTY)
sprintbuf(pb, "\n");
}
had_children = 1;
if (flags & JSON_C_TO_STRING_SPACED)
sprintbuf(pb, " ");
indent(pb, level + 1, flags);
val = json_object_array_get_idx(jso, ii);
if(val == NULL)
sprintbuf(pb, "null");
else
val->_to_json_string(val, pb, level+1, flags);
}
if (flags & JSON_C_TO_STRING_PRETTY)
{
if (had_children)
sprintbuf(pb, "\n");
indent(pb,level,flags);
}
if (flags & JSON_C_TO_STRING_SPACED)
return sprintbuf(pb, " ]");
else
return sprintbuf(pb, "]");
}
static void json_object_array_entry_free(void *data)
{
json_object_put((struct json_object*)data);
}
static void json_object_array_delete(struct json_object* jso)
{
array_list_free(jso->o.c_array);
json_object_generic_delete(jso);
}
struct json_object* json_object_new_array(void)
{
struct json_object *jso = json_object_new(json_type_array);
if (!jso)
return NULL;
jso->_delete = &json_object_array_delete;
jso->_to_json_string = &json_object_array_to_json_string;
jso->o.c_array = array_list_new(&json_object_array_entry_free);
return jso;
}
struct array_list* json_object_get_array(struct json_object *jso)
{
if (!jso)
return NULL;
switch(jso->o_type)
{
case json_type_array:
return jso->o.c_array;
default:
return NULL;
}
}
void json_object_array_sort(struct json_object *jso, int(*sort_fn)(const void *, const void *))
{
array_list_sort(jso->o.c_array, sort_fn);
}
int json_object_array_length(struct json_object *jso)
{
return array_list_length(jso->o.c_array);
}
int json_object_array_add(struct json_object *jso,struct json_object *val)
{
return array_list_add(jso->o.c_array, val);
}
int json_object_array_put_idx(struct json_object *jso, int idx,
struct json_object *val)
{
return array_list_put_idx(jso->o.c_array, idx, val);
}
struct json_object* json_object_array_get_idx(struct json_object *jso,
int idx)
{
return (struct json_object*)array_list_get_idx(jso->o.c_array, idx);
}

View File

@@ -1,617 +0,0 @@
/*
* $Id: json_object.h,v 1.12 2006/01/30 23:07:57 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#ifndef _json_object_h_
#define _json_object_h_
#ifdef __GNUC__
#define THIS_FUNCTION_IS_DEPRECATED(func) func __attribute__ ((deprecated))
#elif defined(_MSC_VER)
#define THIS_FUNCTION_IS_DEPRECATED(func) __declspec(deprecated) func
#else
#define THIS_FUNCTION_IS_DEPRECATED(func) func
#endif
#include "json_inttypes.h"
#ifdef __cplusplus
extern "C" {
#endif
#define JSON_OBJECT_DEF_HASH_ENTRIES 16
/**
* A flag for the json_object_to_json_string_ext() and
* json_object_to_file_ext() functions which causes the output
* to have no extra whitespace or formatting applied.
*/
#define JSON_C_TO_STRING_PLAIN 0
/**
* A flag for the json_object_to_json_string_ext() and
* json_object_to_file_ext() functions which causes the output to have
* minimal whitespace inserted to make things slightly more readable.
*/
#define JSON_C_TO_STRING_SPACED (1<<0)
/**
* A flag for the json_object_to_json_string_ext() and
* json_object_to_file_ext() functions which causes
* the output to be formatted.
*
* See the "Two Space Tab" option at http://jsonformatter.curiousconcept.com/
* for an example of the format.
*/
#define JSON_C_TO_STRING_PRETTY (1<<1)
/**
* A flag to drop trailing zero for float values
*/
#define JSON_C_TO_STRING_NOZERO (1<<2)
#undef FALSE
#define FALSE ((json_bool)0)
#undef TRUE
#define TRUE ((json_bool)1)
extern const char *json_number_chars;
extern const char *json_hex_chars;
/* CAW: added for ANSI C iteration correctness */
struct json_object_iter
{
char *key;
struct json_object *val;
struct lh_entry *entry;
};
/* forward structure definitions */
typedef int json_bool;
typedef struct printbuf printbuf;
typedef struct lh_table lh_table;
typedef struct array_list array_list;
typedef struct json_object json_object;
typedef struct json_object_iter json_object_iter;
typedef struct json_tokener json_tokener;
/**
* Type of custom user delete functions. See json_object_set_serializer.
*/
typedef void (json_object_delete_fn)(struct json_object *jso, void *userdata);
/**
* Type of a custom serialization function. See json_object_set_serializer.
*/
typedef int (json_object_to_json_string_fn)(struct json_object *jso,
struct printbuf *pb,
int level,
int flags);
/* supported object types */
typedef enum json_type {
/* If you change this, be sure to update json_type_to_name() too */
json_type_null,
json_type_boolean,
json_type_double,
json_type_int,
json_type_object,
json_type_array,
json_type_string
} json_type;
/* reference counting functions */
/**
* Increment the reference count of json_object, thereby grabbing shared
* ownership of obj.
*
* @param obj the json_object instance
*/
extern struct json_object* json_object_get(struct json_object *obj);
/**
* Decrement the reference count of json_object and free if it reaches zero.
* You must have ownership of obj prior to doing this or you will cause an
* imbalance in the reference count.
*
* @param obj the json_object instance
* @returns 1 if the object was freed.
*/
int json_object_put(struct json_object *obj);
/**
* Check if the json_object is of a given type
* @param obj the json_object instance
* @param type one of:
json_type_null (i.e. obj == NULL),
json_type_boolean,
json_type_double,
json_type_int,
json_type_object,
json_type_array,
json_type_string
*/
extern int json_object_is_type(struct json_object *obj, enum json_type type);
/**
* Get the type of the json_object. See also json_type_to_name() to turn this
* into a string suitable, for instance, for logging.
*
* @param obj the json_object instance
* @returns type being one of:
json_type_null (i.e. obj == NULL),
json_type_boolean,
json_type_double,
json_type_int,
json_type_object,
json_type_array,
json_type_string
*/
extern enum json_type json_object_get_type(struct json_object *obj);
/** Stringify object to json format.
* Equivalent to json_object_to_json_string_ext(obj, JSON_C_TO_STRING_SPACED)
* The pointer you get is an internal of your json object. You don't
* have to free it, later use of json_object_put() should be sufficient.
* If you can not ensure there's no concurrent access to *obj use
* strdup().
* @param obj the json_object instance
* @returns a string in JSON format
*/
extern const char* json_object_to_json_string(struct json_object *obj);
/** Stringify object to json format
* @see json_object_to_json_string() for details on how to free string.
* @param obj the json_object instance
* @param flags formatting options, see JSON_C_TO_STRING_PRETTY and other constants
* @returns a string in JSON format
*/
extern const char* json_object_to_json_string_ext(struct json_object *obj, int
flags);
/**
* Set a custom serialization function to be used when this particular object
* is converted to a string by json_object_to_json_string.
*
* If a custom serializer is already set on this object, any existing
* user_delete function is called before the new one is set.
*
* If to_string_func is NULL, the other parameters are ignored
* and the default behaviour is reset.
*
* The userdata parameter is optional and may be passed as NULL. If provided,
* it is passed to to_string_func as-is. This parameter may be NULL even
* if user_delete is non-NULL.
*
* The user_delete parameter is optional and may be passed as NULL, even if
* the userdata parameter is non-NULL. It will be called just before the
* json_object is deleted, after it's reference count goes to zero
* (see json_object_put()).
* If this is not provided, it is up to the caller to free the userdata at
* an appropriate time. (i.e. after the json_object is deleted)
*
* @param jso the object to customize
* @param to_string_func the custom serialization function
* @param userdata an optional opaque cookie
* @param user_delete an optional function from freeing userdata
*/
extern void json_object_set_serializer(json_object *jso,
json_object_to_json_string_fn to_string_func,
void *userdata,
json_object_delete_fn *user_delete);
/**
* Simply call free on the userdata pointer.
* Can be used with json_object_set_serializer().
*
* @param jso unused
* @param userdata the pointer that is passed to free().
*/
json_object_delete_fn json_object_free_userdata;
/**
* Copy the jso->_userdata string over to pb as-is.
* Can be used with json_object_set_serializer().
*
* @param jso The object whose _userdata is used.
* @param pb The destination buffer.
* @param level Ignored.
* @param flags Ignored.
*/
json_object_to_json_string_fn json_object_userdata_to_json_string;
/* object type methods */
/** Create a new empty object with a reference count of 1. The caller of
* this object initially has sole ownership. Remember, when using
* json_object_object_add or json_object_array_put_idx, ownership will
* transfer to the object/array. Call json_object_get if you want to maintain
* shared ownership or also add this object as a child of multiple objects or
* arrays. Any ownerships you acquired but did not transfer must be released
* through json_object_put.
*
* @returns a json_object of type json_type_object
*/
extern struct json_object* json_object_new_object(void);
/** Get the hashtable of a json_object of type json_type_object
* @param obj the json_object instance
* @returns a linkhash
*/
extern struct lh_table* json_object_get_object(struct json_object *obj);
/** Get the size of an object in terms of the number of fields it has.
* @param obj the json_object whose length to return
*/
extern int json_object_object_length(struct json_object* obj);
/** Add an object field to a json_object of type json_type_object
*
* The reference count will *not* be incremented. This is to make adding
* fields to objects in code more compact. If you want to retain a reference
* to an added object, independent of the lifetime of obj, you must wrap the
* passed object with json_object_get.
*
* Upon calling this, the ownership of val transfers to obj. Thus you must
* make sure that you do in fact have ownership over this object. For instance,
* json_object_new_object will give you ownership until you transfer it,
* whereas json_object_object_get does not.
*
* @param obj the json_object instance
* @param key the object field name (a private copy will be duplicated)
* @param val a json_object or NULL member to associate with the given field
*/
extern void json_object_object_add(struct json_object* obj, const char *key,
struct json_object *val);
/** Get the json_object associate with a given object field
*
* *No* reference counts will be changed. There is no need to manually adjust
* reference counts through the json_object_put/json_object_get methods unless
* you need to have the child (value) reference maintain a different lifetime
* than the owning parent (obj). Ownership of the returned value is retained
* by obj (do not do json_object_put unless you have done a json_object_get).
* If you delete the value from obj (json_object_object_del) and wish to access
* the returned reference afterwards, make sure you have first gotten shared
* ownership through json_object_get (& don't forget to do a json_object_put
* or transfer ownership to prevent a memory leak).
*
* @param obj the json_object instance
* @param key the object field name
* @returns the json_object associated with the given field name
* @deprecated Please use json_object_object_get_ex
*/
THIS_FUNCTION_IS_DEPRECATED(extern struct json_object* json_object_object_get(struct json_object* obj,
const char *key));
/** Get the json_object associated with a given object field.
*
* This returns true if the key is found, false in all other cases (including
* if obj isn't a json_type_object).
*
* *No* reference counts will be changed. There is no need to manually adjust
* reference counts through the json_object_put/json_object_get methods unless
* you need to have the child (value) reference maintain a different lifetime
* than the owning parent (obj). Ownership of value is retained by obj.
*
* @param obj the json_object instance
* @param key the object field name
* @param value a pointer where to store a reference to the json_object
* associated with the given field name.
*
* It is safe to pass a NULL value.
* @returns whether or not the key exists
*/
extern json_bool json_object_object_get_ex(struct json_object* obj,
const char *key,
struct json_object **value);
/** Delete the given json_object field
*
* The reference count will be decremented for the deleted object. If there
* are no more owners of the value represented by this key, then the value is
* freed. Otherwise, the reference to the value will remain in memory.
*
* @param obj the json_object instance
* @param key the object field name
*/
extern void json_object_object_del(struct json_object* obj, const char *key);
/**
* Iterate through all keys and values of an object.
*
* Adding keys to the object while iterating is NOT allowed.
*
* Deleting an existing key, or replacing an existing key with a
* new value IS allowed.
*
* @param obj the json_object instance
* @param key the local name for the char* key variable defined in the body
* @param val the local name for the json_object* object variable defined in
* the body
*/
#if defined(__GNUC__) && !defined(__STRICT_ANSI__) && __STDC_VERSION__ >= 199901L
# define json_object_object_foreach(obj,key,val) \
char *key; \
struct json_object *val __attribute__((__unused__)); \
for(struct lh_entry *entry ## key = json_object_get_object(obj)->head, *entry_next ## key = NULL; \
({ if(entry ## key) { \
key = (char*)entry ## key->k; \
val = (struct json_object*)entry ## key->v; \
entry_next ## key = entry ## key->next; \
} ; entry ## key; }); \
entry ## key = entry_next ## key )
#else /* ANSI C or MSC */
# define json_object_object_foreach(obj,key,val) \
char *key;\
struct json_object *val; \
struct lh_entry *entry ## key; \
struct lh_entry *entry_next ## key = NULL; \
for(entry ## key = json_object_get_object(obj)->head; \
(entry ## key ? ( \
key = (char*)entry ## key->k, \
val = (struct json_object*)entry ## key->v, \
entry_next ## key = entry ## key->next, \
entry ## key) : 0); \
entry ## key = entry_next ## key)
#endif /* defined(__GNUC__) && !defined(__STRICT_ANSI__) && __STDC_VERSION__ >= 199901L */
/** Iterate through all keys and values of an object (ANSI C Safe)
* @param obj the json_object instance
* @param iter the object iterator
*/
#define json_object_object_foreachC(obj,iter) \
for(iter.entry = json_object_get_object(obj)->head; (iter.entry ? (iter.key = (char*)iter.entry->k, iter.val = (struct json_object*)iter.entry->v, iter.entry) : 0); iter.entry = iter.entry->next)
/* Array type methods */
/** Create a new empty json_object of type json_type_array
* @returns a json_object of type json_type_array
*/
extern struct json_object* json_object_new_array(void);
/** Get the arraylist of a json_object of type json_type_array
* @param obj the json_object instance
* @returns an arraylist
*/
extern struct array_list* json_object_get_array(struct json_object *obj);
/** Get the length of a json_object of type json_type_array
* @param obj the json_object instance
* @returns an int
*/
extern int json_object_array_length(struct json_object *obj);
/** Sorts the elements of jso of type json_type_array
*
* Pointers to the json_object pointers will be passed as the two arguments
* to @sort_fn
*
* @param obj the json_object instance
* @param sort_fn a sorting function
*/
extern void json_object_array_sort(struct json_object *jso, int(*sort_fn)(const void *, const void *));
/** Add an element to the end of a json_object of type json_type_array
*
* The reference count will *not* be incremented. This is to make adding
* fields to objects in code more compact. If you want to retain a reference
* to an added object you must wrap the passed object with json_object_get
*
* @param obj the json_object instance
* @param val the json_object to be added
*/
extern int json_object_array_add(struct json_object *obj,
struct json_object *val);
/** Insert or replace an element at a specified index in an array (a json_object of type json_type_array)
*
* The reference count will *not* be incremented. This is to make adding
* fields to objects in code more compact. If you want to retain a reference
* to an added object you must wrap the passed object with json_object_get
*
* The reference count of a replaced object will be decremented.
*
* The array size will be automatically be expanded to the size of the
* index if the index is larger than the current size.
*
* @param obj the json_object instance
* @param idx the index to insert the element at
* @param val the json_object to be added
*/
extern int json_object_array_put_idx(struct json_object *obj, int idx,
struct json_object *val);
/** Get the element at specificed index of the array (a json_object of type json_type_array)
* @param obj the json_object instance
* @param idx the index to get the element at
* @returns the json_object at the specified index (or NULL)
*/
extern struct json_object* json_object_array_get_idx(struct json_object *obj,
int idx);
/* json_bool type methods */
/** Create a new empty json_object of type json_type_boolean
* @param b a json_bool TRUE or FALSE (0 or 1)
* @returns a json_object of type json_type_boolean
*/
extern struct json_object* json_object_new_boolean(json_bool b);
/** Get the json_bool value of a json_object
*
* The type is coerced to a json_bool if the passed object is not a json_bool.
* integer and double objects will return FALSE if there value is zero
* or TRUE otherwise. If the passed object is a string it will return
* TRUE if it has a non zero length. If any other object type is passed
* TRUE will be returned if the object is not NULL.
*
* @param obj the json_object instance
* @returns a json_bool
*/
extern json_bool json_object_get_boolean(struct json_object *obj);
/* int type methods */
/** Create a new empty json_object of type json_type_int
* Note that values are stored as 64-bit values internally.
* To ensure the full range is maintained, use json_object_new_int64 instead.
* @param i the integer
* @returns a json_object of type json_type_int
*/
extern struct json_object* json_object_new_int(int32_t i);
/** Create a new empty json_object of type json_type_int
* @param i the integer
* @returns a json_object of type json_type_int
*/
extern struct json_object* json_object_new_int64(int64_t i);
/** Get the int value of a json_object
*
* The type is coerced to a int if the passed object is not a int.
* double objects will return their integer conversion. Strings will be
* parsed as an integer. If no conversion exists then 0 is returned
* and errno is set to EINVAL. null is equivalent to 0 (no error values set)
*
* Note that integers are stored internally as 64-bit values.
* If the value of too big or too small to fit into 32-bit, INT32_MAX or
* INT32_MIN are returned, respectively.
*
* @param obj the json_object instance
* @returns an int
*/
extern int32_t json_object_get_int(struct json_object *obj);
/** Get the int value of a json_object
*
* The type is coerced to a int64 if the passed object is not a int64.
* double objects will return their int64 conversion. Strings will be
* parsed as an int64. If no conversion exists then 0 is returned.
*
* NOTE: Set errno to 0 directly before a call to this function to determine
* whether or not conversion was successful (it does not clear the value for
* you).
*
* @param obj the json_object instance
* @returns an int64
*/
extern int64_t json_object_get_int64(struct json_object *obj);
/* double type methods */
/** Create a new empty json_object of type json_type_double
* @param d the double
* @returns a json_object of type json_type_double
*/
extern struct json_object* json_object_new_double(double d);
/**
* Create a new json_object of type json_type_double, using
* the exact serialized representation of the value.
*
* This allows for numbers that would otherwise get displayed
* inefficiently (e.g. 12.3 => "12.300000000000001") to be
* serialized with the more convenient form.
*
* Note: this is used by json_tokener_parse_ex() to allow for
* an exact re-serialization of a parsed object.
*
* An equivalent sequence of calls is:
* @code
* jso = json_object_new_double(d);
* json_object_set_serializer(d, json_object_userdata_to_json_string,
* strdup(ds), json_object_free_userdata)
* @endcode
*
* @param d the numeric value of the double.
* @param ds the string representation of the double. This will be copied.
*/
extern struct json_object* json_object_new_double_s(double d, const char *ds);
/** Get the double floating point value of a json_object
*
* The type is coerced to a double if the passed object is not a double.
* integer objects will return their double conversion. Strings will be
* parsed as a double. If no conversion exists then 0.0 is returned and
* errno is set to EINVAL. null is equivalent to 0 (no error values set)
*
* If the value is too big to fit in a double, then the value is set to
* the closest infinity with errno set to ERANGE. If strings cannot be
* converted to their double value, then EINVAL is set & NaN is returned.
*
* Arrays of length 0 are interpreted as 0 (with no error flags set).
* Arrays of length 1 are effectively cast to the equivalent object and
* converted using the above rules. All other arrays set the error to
* EINVAL & return NaN.
*
* NOTE: Set errno to 0 directly before a call to this function to
* determine whether or not conversion was successful (it does not clear
* the value for you).
*
* @param obj the json_object instance
* @returns a double floating point number
*/
extern double json_object_get_double(struct json_object *obj);
/* string type methods */
/** Create a new empty json_object of type json_type_string
*
* A copy of the string is made and the memory is managed by the json_object
*
* @param s the string
* @returns a json_object of type json_type_string
*/
extern struct json_object* json_object_new_string(const char *s);
extern struct json_object* json_object_new_string_len(const char *s, int len);
/** Get the string value of a json_object
*
* If the passed object is not of type json_type_string then the JSON
* representation of the object is returned.
*
* The returned string memory is managed by the json_object and will
* be freed when the reference count of the json_object drops to zero.
*
* @param obj the json_object instance
* @returns a string
*/
extern const char* json_object_get_string(struct json_object *obj);
/** Get the string length of a json_object
*
* If the passed object is not of type json_type_string then zero
* will be returned.
*
* @param obj the json_object instance
* @returns int
*/
extern int json_object_get_string_len(struct json_object *obj);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,168 +0,0 @@
/**
*******************************************************************************
* @file json_object_iterator.c
*
* Copyright (c) 2009-2012 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
* @brief json-c forces clients to use its private data
* structures for JSON Object iteration. This API
* implementation corrects that by abstracting the
* private json-c details.
*
*******************************************************************************
*/
#include <stddef.h>
#include "json.h"
#include "json_object_private.h"
#include "json_object_iterator.h"
/**
* How It Works
*
* For each JSON Object, json-c maintains a linked list of zero
* or more lh_entry (link-hash entry) structures inside the
* Object's link-hash table (lh_table).
*
* Each lh_entry structure on the JSON Object's linked list
* represents a single name/value pair. The "next" field of the
* last lh_entry in the list is set to NULL, which terminates
* the list.
*
* We represent a valid iterator that refers to an actual
* name/value pair via a pointer to the pair's lh_entry
* structure set as the iterator's opaque_ field.
*
* We follow json-c's current pair list representation by
* representing a valid "end" iterator (one that refers past the
* last pair) with a NULL value in the iterator's opaque_ field.
*
* A JSON Object without any pairs in it will have the "head"
* field of its lh_table structure set to NULL. For such an
* object, json_object_iter_begin will return an iterator with
* the opaque_ field set to NULL, which is equivalent to the
* "end" iterator.
*
* When iterating, we simply update the iterator's opaque_ field
* to point to the next lh_entry structure in the linked list.
* opaque_ will become NULL once we iterate past the last pair
* in the list, which makes the iterator equivalent to the "end"
* iterator.
*/
/// Our current representation of the "end" iterator;
///
/// @note May not always be NULL
static const void* kObjectEndIterValue = NULL;
/**
* ****************************************************************************
*/
struct json_object_iterator
json_object_iter_begin(struct json_object* obj)
{
struct json_object_iterator iter;
struct lh_table* pTable;
/// @note json_object_get_object will return NULL if passed NULL
/// or a non-json_type_object instance
pTable = json_object_get_object(obj);
JASSERT(NULL != pTable);
/// @note For a pair-less Object, head is NULL, which matches our
/// definition of the "end" iterator
iter.opaque_ = pTable->head;
return iter;
}
/**
* ****************************************************************************
*/
struct json_object_iterator
json_object_iter_end(const struct json_object* obj)
{
struct json_object_iterator iter;
JASSERT(NULL != obj);
JASSERT(json_object_is_type(obj, json_type_object));
iter.opaque_ = kObjectEndIterValue;
return iter;
}
/**
* ****************************************************************************
*/
void
json_object_iter_next(struct json_object_iterator* iter)
{
JASSERT(NULL != iter);
JASSERT(kObjectEndIterValue != iter->opaque_);
iter->opaque_ = ((struct lh_entry *)iter->opaque_)->next;
}
/**
* ****************************************************************************
*/
const char*
json_object_iter_peek_name(const struct json_object_iterator* iter)
{
JASSERT(NULL != iter);
JASSERT(kObjectEndIterValue != iter->opaque_);
return (const char*)(((struct lh_entry *)iter->opaque_)->k);
}
/**
* ****************************************************************************
*/
struct json_object*
json_object_iter_peek_value(const struct json_object_iterator* iter)
{
JASSERT(NULL != iter);
JASSERT(kObjectEndIterValue != iter->opaque_);
return (struct json_object*)(((struct lh_entry *)iter->opaque_)->v);
}
/**
* ****************************************************************************
*/
json_bool
json_object_iter_equal(const struct json_object_iterator* iter1,
const struct json_object_iterator* iter2)
{
JASSERT(NULL != iter1);
JASSERT(NULL != iter2);
return (iter1->opaque_ == iter2->opaque_);
}
/**
* ****************************************************************************
*/
struct json_object_iterator
json_object_iter_init_default(void)
{
struct json_object_iterator iter;
/**
* @note Make this a negative, invalid value, such that
* accidental access to it would likely be trapped by the
* hardware as an invalid address.
*/
iter.opaque_ = NULL;
return iter;
}

View File

@@ -1,239 +0,0 @@
/**
*******************************************************************************
* @file json_object_iterator.h
*
* Copyright (c) 2009-2012 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
* @brief json-c forces clients to use its private data
* structures for JSON Object iteration. This API
* corrects that by abstracting the private json-c
* details.
*
* API attributes: <br>
* * Thread-safe: NO<br>
* * Reentrant: NO
*
*******************************************************************************
*/
#ifndef JSON_OBJECT_ITERATOR_H
#define JSON_OBJECT_ITERATOR_H
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Forward declaration for the opaque iterator information.
*/
struct json_object_iter_info_;
/**
* The opaque iterator that references a name/value pair within
* a JSON Object instance or the "end" iterator value.
*/
struct json_object_iterator {
const void* opaque_;
};
/**
* forward declaration of json-c's JSON value instance structure
*/
struct json_object;
/**
* Initializes an iterator structure to a "default" value that
* is convenient for initializing an iterator variable to a
* default state (e.g., initialization list in a class'
* constructor).
*
* @code
* struct json_object_iterator iter = json_object_iter_init_default();
* MyClass() : iter_(json_object_iter_init_default())
* @endcode
*
* @note The initialized value doesn't reference any specific
* pair, is considered an invalid iterator, and MUST NOT
* be passed to any json-c API that expects a valid
* iterator.
*
* @note User and internal code MUST NOT make any assumptions
* about and dependencies on the value of the "default"
* iterator value.
*
* @return json_object_iterator
*/
struct json_object_iterator
json_object_iter_init_default(void);
/** Retrieves an iterator to the first pair of the JSON Object.
*
* @warning Any modification of the underlying pair invalidates all
* iterators to that pair.
*
* @param obj JSON Object instance (MUST be of type json_object)
*
* @return json_object_iterator If the JSON Object has at
* least one pair, on return, the iterator refers
* to the first pair. If the JSON Object doesn't
* have any pairs, the returned iterator is
* equivalent to the "end" iterator for the same
* JSON Object instance.
*
* @code
* struct json_object_iterator it;
* struct json_object_iterator itEnd;
* struct json_object* obj;
*
* obj = json_tokener_parse("{'first':'george', 'age':100}");
* it = json_object_iter_begin(obj);
* itEnd = json_object_iter_end(obj);
*
* while (!json_object_iter_equal(&it, &itEnd)) {
* printf("%s\n",
* json_object_iter_peek_name(&it));
* json_object_iter_next(&it);
* }
*
* @endcode
*/
struct json_object_iterator
json_object_iter_begin(struct json_object* obj);
/** Retrieves the iterator that represents the position beyond the
* last pair of the given JSON Object instance.
*
* @warning Do NOT write code that assumes that the "end"
* iterator value is NULL, even if it is so in a
* particular instance of the implementation.
*
* @note The reason we do not (and MUST NOT) provide
* "json_object_iter_is_end(json_object_iterator* iter)"
* type of API is because it would limit the underlying
* representation of name/value containment (or force us
* to add additional, otherwise unnecessary, fields to
* the iterator structure). The "end" iterator and the
* equality test method, on the other hand, permit us to
* cleanly abstract pretty much any reasonable underlying
* representation without burdening the iterator
* structure with unnecessary data.
*
* @note For performance reasons, memorize the "end" iterator prior
* to any loop.
*
* @param obj JSON Object instance (MUST be of type json_object)
*
* @return json_object_iterator On return, the iterator refers
* to the "end" of the Object instance's pairs
* (i.e., NOT the last pair, but "beyond the last
* pair" value)
*/
struct json_object_iterator
json_object_iter_end(const struct json_object* obj);
/** Returns an iterator to the next pair, if any
*
* @warning Any modification of the underlying pair
* invalidates all iterators to that pair.
*
* @param iter [IN/OUT] Pointer to iterator that references a
* name/value pair; MUST be a valid, non-end iterator.
* WARNING: bad things will happen if invalid or "end"
* iterator is passed. Upon return will contain the
* reference to the next pair if there is one; if there
* are no more pairs, will contain the "end" iterator
* value, which may be compared against the return value
* of json_object_iter_end() for the same JSON Object
* instance.
*/
void
json_object_iter_next(struct json_object_iterator* iter);
/** Returns a const pointer to the name of the pair referenced
* by the given iterator.
*
* @param iter pointer to iterator that references a name/value
* pair; MUST be a valid, non-end iterator.
*
* @warning bad things will happen if an invalid or
* "end" iterator is passed.
*
* @return const char* Pointer to the name of the referenced
* name/value pair. The name memory belongs to the
* name/value pair, will be freed when the pair is
* deleted or modified, and MUST NOT be modified or
* freed by the user.
*/
const char*
json_object_iter_peek_name(const struct json_object_iterator* iter);
/** Returns a pointer to the json-c instance representing the
* value of the referenced name/value pair, without altering
* the instance's reference count.
*
* @param iter pointer to iterator that references a name/value
* pair; MUST be a valid, non-end iterator.
*
* @warning bad things will happen if invalid or
* "end" iterator is passed.
*
* @return struct json_object* Pointer to the json-c value
* instance of the referenced name/value pair; the
* value's reference count is not changed by this
* function: if you plan to hold on to this json-c node,
* take a look at json_object_get() and
* json_object_put(). IMPORTANT: json-c API represents
* the JSON Null value as a NULL json_object instance
* pointer.
*/
struct json_object*
json_object_iter_peek_value(const struct json_object_iterator* iter);
/** Tests two iterators for equality. Typically used to test
* for end of iteration by comparing an iterator to the
* corresponding "end" iterator (that was derived from the same
* JSON Object instance).
*
* @note The reason we do not (and MUST NOT) provide
* "json_object_iter_is_end(json_object_iterator* iter)"
* type of API is because it would limit the underlying
* representation of name/value containment (or force us
* to add additional, otherwise unnecessary, fields to
* the iterator structure). The equality test method, on
* the other hand, permits us to cleanly abstract pretty
* much any reasonable underlying representation.
*
* @param iter1 Pointer to first valid, non-NULL iterator
* @param iter2 POinter to second valid, non-NULL iterator
*
* @warning if a NULL iterator pointer or an uninitialized
* or invalid iterator, or iterators derived from
* different JSON Object instances are passed, bad things
* will happen!
*
* @return json_bool non-zero if iterators are equal (i.e., both
* reference the same name/value pair or are both at
* "end"); zero if they are not equal.
*/
json_bool
json_object_iter_equal(const struct json_object_iterator* iter1,
const struct json_object_iterator* iter2);
#ifdef __cplusplus
}
#endif
#endif /* JSON_OBJECT_ITERATOR_H */

View File

@@ -1,47 +0,0 @@
/*
* $Id: json_object_private.h,v 1.4 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#ifndef _json_object_private_h_
#define _json_object_private_h_
#ifdef __cplusplus
extern "C" {
#endif
typedef void (json_object_private_delete_fn)(struct json_object *o);
struct json_object
{
enum json_type o_type;
json_object_private_delete_fn *_delete;
json_object_to_json_string_fn *_to_json_string;
int _ref_count;
struct printbuf *_pb;
union data {
json_bool c_boolean;
double c_double;
int64_t c_int64;
struct lh_table *c_object;
struct array_list *c_array;
struct {
char *str;
int len;
} c_string;
} o;
json_object_delete_fn *_user_delete;
void *_userdata;
};
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,887 +0,0 @@
/*
* $Id: json_tokener.c,v 1.20 2006/07/25 03:24:50 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*
* Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved.
* The copyrights to the contents of this file are licensed under the MIT License
* (http://www.opensource.org/licenses/mit-license.php)
*/
#include "config.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <ctype.h>
#include <string.h>
#include <limits.h>
#include "debug.h"
#include "printbuf.h"
#include "arraylist.h"
#include "json_inttypes.h"
#include "json_object.h"
#include "json_tokener.h"
#include "json_util.h"
#ifdef HAVE_LOCALE_H
#include <locale.h>
#endif /* HAVE_LOCALE_H */
#define jt_hexdigit(x) (((x) <= '9') ? (x) - '0' : ((x) & 7) + 9)
#if !HAVE_STRDUP && defined(_MSC_VER)
/* MSC has the version as _strdup */
# define strdup _strdup
#elif !HAVE_STRDUP
# error You do not have strdup on your system.
#endif /* HAVE_STRDUP */
#if !HAVE_STRNCASECMP && defined(_MSC_VER)
/* MSC has the version as _strnicmp */
# define strncasecmp _strnicmp
#elif !HAVE_STRNCASECMP
# error You do not have strncasecmp on your system.
#endif /* HAVE_STRNCASECMP */
/* Use C99 NAN by default; if not available, nan("") should work too. */
#ifndef NAN
#define NAN nan("")
#endif /* !NAN */
static const char json_null_str[] = "null";
static const int json_null_str_len = sizeof(json_null_str) - 1;
static const char json_inf_str[] = "Infinity";
static const int json_inf_str_len = sizeof(json_inf_str) - 1;
static const char json_nan_str[] = "NaN";
static const int json_nan_str_len = sizeof(json_nan_str) - 1;
static const char json_true_str[] = "true";
static const int json_true_str_len = sizeof(json_true_str) - 1;
static const char json_false_str[] = "false";
static const int json_false_str_len = sizeof(json_false_str) - 1;
static const char* json_tokener_errors[] = {
"success",
"continue",
"nesting too deep",
"unexpected end of data",
"unexpected character",
"null expected",
"boolean expected",
"number expected",
"array value separator ',' expected",
"quoted object property name expected",
"object property name separator ':' expected",
"object value separator ',' expected",
"invalid string sequence",
"expected comment",
"buffer size overflow"
};
const char *json_tokener_error_desc(enum json_tokener_error jerr)
{
int jerr_int = (int)jerr;
if (jerr_int < 0 || jerr_int >= (int)(sizeof(json_tokener_errors) / sizeof(json_tokener_errors[0])))
return "Unknown error, invalid json_tokener_error value passed to json_tokener_error_desc()";
return json_tokener_errors[jerr];
}
enum json_tokener_error json_tokener_get_error(json_tokener *tok)
{
return tok->err;
}
/* Stuff for decoding unicode sequences */
#define IS_HIGH_SURROGATE(uc) (((uc) & 0xFC00) == 0xD800)
#define IS_LOW_SURROGATE(uc) (((uc) & 0xFC00) == 0xDC00)
#define DECODE_SURROGATE_PAIR(hi,lo) ((((hi) & 0x3FF) << 10) + ((lo) & 0x3FF) + 0x10000)
static unsigned char utf8_replacement_char[3] = { 0xEF, 0xBF, 0xBD };
struct json_tokener* json_tokener_new_ex(int depth)
{
struct json_tokener *tok;
tok = (struct json_tokener*)calloc(1, sizeof(struct json_tokener));
if (!tok) return NULL;
tok->stack = (struct json_tokener_srec *)calloc(depth, sizeof(struct json_tokener_srec));
if (!tok->stack) {
free(tok);
return NULL;
}
tok->pb = printbuf_new();
tok->max_depth = depth;
json_tokener_reset(tok);
return tok;
}
struct json_tokener* json_tokener_new(void)
{
return json_tokener_new_ex(JSON_TOKENER_DEFAULT_DEPTH);
}
void json_tokener_free(struct json_tokener *tok)
{
json_tokener_reset(tok);
if (tok->pb) printbuf_free(tok->pb);
if (tok->stack) free(tok->stack);
free(tok);
}
static void json_tokener_reset_level(struct json_tokener *tok, int depth)
{
tok->stack[depth].state = json_tokener_state_eatws;
tok->stack[depth].saved_state = json_tokener_state_start;
json_object_put(tok->stack[depth].current);
tok->stack[depth].current = NULL;
free(tok->stack[depth].obj_field_name);
tok->stack[depth].obj_field_name = NULL;
}
void json_tokener_reset(struct json_tokener *tok)
{
int i;
if (!tok)
return;
for(i = tok->depth; i >= 0; i--)
json_tokener_reset_level(tok, i);
tok->depth = 0;
tok->err = json_tokener_success;
}
struct json_object* json_tokener_parse(const char *str)
{
enum json_tokener_error jerr_ignored;
struct json_object* obj;
obj = json_tokener_parse_verbose(str, &jerr_ignored);
return obj;
}
struct json_object* json_tokener_parse_verbose(const char *str, enum json_tokener_error *error)
{
struct json_tokener* tok;
struct json_object* obj;
tok = json_tokener_new();
if (!tok)
return NULL;
obj = json_tokener_parse_ex(tok, str, -1);
*error = tok->err;
if(tok->err != json_tokener_success) {
if (obj != NULL)
json_object_put(obj);
obj = NULL;
}
json_tokener_free(tok);
return obj;
}
#define state tok->stack[tok->depth].state
#define saved_state tok->stack[tok->depth].saved_state
#define current tok->stack[tok->depth].current
#define obj_field_name tok->stack[tok->depth].obj_field_name
/* Optimization:
* json_tokener_parse_ex() consumed a lot of CPU in its main loop,
* iterating character-by character. A large performance boost is
* achieved by using tighter loops to locally handle units such as
* comments and strings. Loops that handle an entire token within
* their scope also gather entire strings and pass them to
* printbuf_memappend() in a single call, rather than calling
* printbuf_memappend() one char at a time.
*
* PEEK_CHAR() and ADVANCE_CHAR() macros are used for code that is
* common to both the main loop and the tighter loops.
*/
/* PEEK_CHAR(dest, tok) macro:
* Peeks at the current char and stores it in dest.
* Returns 1 on success, sets tok->err and returns 0 if no more chars.
* Implicit inputs: str, len vars
*/
#define PEEK_CHAR(dest, tok) \
(((tok)->char_offset == len) ? \
(((tok)->depth == 0 && state == json_tokener_state_eatws && saved_state == json_tokener_state_finish) ? \
(((tok)->err = json_tokener_success), 0) \
: \
(((tok)->err = json_tokener_continue), 0) \
) : \
(((dest) = *str), 1) \
)
/* ADVANCE_CHAR() macro:
* Incrementes str & tok->char_offset.
* For convenience of existing conditionals, returns the old value of c (0 on eof)
* Implicit inputs: c var
*/
#define ADVANCE_CHAR(str, tok) \
( ++(str), ((tok)->char_offset)++, c)
/* End optimization macro defs */
struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
const char *str, int len)
{
struct json_object *obj = NULL;
char c = '\1';
#ifdef HAVE_SETLOCALE
char *oldlocale=NULL, *tmplocale;
tmplocale = setlocale(LC_NUMERIC, NULL);
if (tmplocale) oldlocale = strdup(tmplocale);
setlocale(LC_NUMERIC, "C");
#endif
tok->char_offset = 0;
tok->err = json_tokener_success;
/* this interface is presently not 64-bit clean due to the int len argument
and the internal printbuf interface that takes 32-bit int len arguments
so the function limits the maximum string size to INT32_MAX (2GB).
If the function is called with len == -1 then strlen is called to check
the string length is less than INT32_MAX (2GB) */
if ((len < -1) || (len == -1 && strlen(str) > INT32_MAX)) {
tok->err = json_tokener_error_size;
return NULL;
}
while (PEEK_CHAR(c, tok)) {
redo_char:
switch(state) {
case json_tokener_state_eatws:
/* Advance until we change state */
while (isspace((int)c)) {
if ((!ADVANCE_CHAR(str, tok)) || (!PEEK_CHAR(c, tok)))
goto out;
}
if(c == '/' && !(tok->flags & JSON_TOKENER_STRICT)) {
printbuf_reset(tok->pb);
printbuf_memappend_fast(tok->pb, &c, 1);
state = json_tokener_state_comment_start;
} else {
state = saved_state;
goto redo_char;
}
break;
case json_tokener_state_start:
switch(c) {
case '{':
state = json_tokener_state_eatws;
saved_state = json_tokener_state_object_field_start;
current = json_object_new_object();
break;
case '[':
state = json_tokener_state_eatws;
saved_state = json_tokener_state_array;
current = json_object_new_array();
break;
case 'I':
case 'i':
state = json_tokener_state_inf;
printbuf_reset(tok->pb);
tok->st_pos = 0;
goto redo_char;
case 'N':
case 'n':
state = json_tokener_state_null; // or NaN
printbuf_reset(tok->pb);
tok->st_pos = 0;
goto redo_char;
case '\'':
if (tok->flags & JSON_TOKENER_STRICT) {
/* in STRICT mode only double-quote are allowed */
tok->err = json_tokener_error_parse_unexpected;
goto out;
}
case '"':
state = json_tokener_state_string;
printbuf_reset(tok->pb);
tok->quote_char = c;
break;
case 'T':
case 't':
case 'F':
case 'f':
state = json_tokener_state_boolean;
printbuf_reset(tok->pb);
tok->st_pos = 0;
goto redo_char;
#if defined(__GNUC__)
case '0' ... '9':
#else
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
#endif
case '-':
state = json_tokener_state_number;
printbuf_reset(tok->pb);
tok->is_double = 0;
goto redo_char;
default:
tok->err = json_tokener_error_parse_unexpected;
goto out;
}
break;
case json_tokener_state_finish:
if(tok->depth == 0) goto out;
obj = json_object_get(current);
json_tokener_reset_level(tok, tok->depth);
tok->depth--;
goto redo_char;
case json_tokener_state_inf: /* aka starts with 'i' */
{
int size_inf;
int is_negative = 0;
printbuf_memappend_fast(tok->pb, &c, 1);
size_inf = json_min(tok->st_pos+1, json_inf_str_len);
char *infbuf = tok->pb->buf;
if (*infbuf == '-')
{
infbuf++;
is_negative = 1;
}
if ((!(tok->flags & JSON_TOKENER_STRICT) &&
strncasecmp(json_inf_str, infbuf, size_inf) == 0) ||
(strncmp(json_inf_str, infbuf, size_inf) == 0)
)
{
if (tok->st_pos == json_inf_str_len)
{
current = json_object_new_double(is_negative ? -INFINITY : INFINITY);
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
goto redo_char;
}
} else {
tok->err = json_tokener_error_parse_unexpected;
goto out;
}
tok->st_pos++;
}
break;
case json_tokener_state_null: /* aka starts with 'n' */
{
int size;
int size_nan;
printbuf_memappend_fast(tok->pb, &c, 1);
size = json_min(tok->st_pos+1, json_null_str_len);
size_nan = json_min(tok->st_pos+1, json_nan_str_len);
if((!(tok->flags & JSON_TOKENER_STRICT) &&
strncasecmp(json_null_str, tok->pb->buf, size) == 0)
|| (strncmp(json_null_str, tok->pb->buf, size) == 0)
) {
if (tok->st_pos == json_null_str_len) {
current = NULL;
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
goto redo_char;
}
}
else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
strncasecmp(json_nan_str, tok->pb->buf, size_nan) == 0) ||
(strncmp(json_nan_str, tok->pb->buf, size_nan) == 0)
)
{
if (tok->st_pos == json_nan_str_len)
{
current = json_object_new_double(NAN);
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
goto redo_char;
}
} else {
tok->err = json_tokener_error_parse_null;
goto out;
}
tok->st_pos++;
}
break;
case json_tokener_state_comment_start:
if(c == '*') {
state = json_tokener_state_comment;
} else if(c == '/') {
state = json_tokener_state_comment_eol;
} else {
tok->err = json_tokener_error_parse_comment;
goto out;
}
printbuf_memappend_fast(tok->pb, &c, 1);
break;
case json_tokener_state_comment:
{
/* Advance until we change state */
const char *case_start = str;
while(c != '*') {
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
goto out;
}
}
printbuf_memappend_fast(tok->pb, case_start, 1+str-case_start);
state = json_tokener_state_comment_end;
}
break;
case json_tokener_state_comment_eol:
{
/* Advance until we change state */
const char *case_start = str;
while(c != '\n') {
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
goto out;
}
}
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
state = json_tokener_state_eatws;
}
break;
case json_tokener_state_comment_end:
printbuf_memappend_fast(tok->pb, &c, 1);
if(c == '/') {
MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
state = json_tokener_state_eatws;
} else {
state = json_tokener_state_comment;
}
break;
case json_tokener_state_string:
{
/* Advance until we change state */
const char *case_start = str;
while(1) {
if(c == tok->quote_char) {
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
current = json_object_new_string_len(tok->pb->buf, tok->pb->bpos);
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
break;
} else if(c == '\\') {
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
saved_state = json_tokener_state_string;
state = json_tokener_state_string_escape;
break;
}
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
goto out;
}
}
}
break;
case json_tokener_state_string_escape:
switch(c) {
case '"':
case '\\':
case '/':
printbuf_memappend_fast(tok->pb, &c, 1);
state = saved_state;
break;
case 'b':
case 'n':
case 'r':
case 't':
case 'f':
if(c == 'b') printbuf_memappend_fast(tok->pb, "\b", 1);
else if(c == 'n') printbuf_memappend_fast(tok->pb, "\n", 1);
else if(c == 'r') printbuf_memappend_fast(tok->pb, "\r", 1);
else if(c == 't') printbuf_memappend_fast(tok->pb, "\t", 1);
else if(c == 'f') printbuf_memappend_fast(tok->pb, "\f", 1);
state = saved_state;
break;
case 'u':
tok->ucs_char = 0;
tok->st_pos = 0;
state = json_tokener_state_escape_unicode;
break;
default:
tok->err = json_tokener_error_parse_string;
goto out;
}
break;
case json_tokener_state_escape_unicode:
{
unsigned int got_hi_surrogate = 0;
/* Handle a 4-byte sequence, or two sequences if a surrogate pair */
while(1) {
if(strchr(json_hex_chars, c)) {
tok->ucs_char += ((unsigned int)jt_hexdigit(c) << ((3-tok->st_pos++)*4));
if(tok->st_pos == 4) {
unsigned char unescaped_utf[4];
if (got_hi_surrogate) {
if (IS_LOW_SURROGATE(tok->ucs_char)) {
/* Recalculate the ucs_char, then fall thru to process normally */
tok->ucs_char = DECODE_SURROGATE_PAIR(got_hi_surrogate, tok->ucs_char);
} else {
/* Hi surrogate was not followed by a low surrogate */
/* Replace the hi and process the rest normally */
printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
}
got_hi_surrogate = 0;
}
if (tok->ucs_char < 0x80) {
unescaped_utf[0] = tok->ucs_char;
printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 1);
} else if (tok->ucs_char < 0x800) {
unescaped_utf[0] = 0xc0 | (tok->ucs_char >> 6);
unescaped_utf[1] = 0x80 | (tok->ucs_char & 0x3f);
printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 2);
} else if (IS_HIGH_SURROGATE(tok->ucs_char)) {
/* Got a high surrogate. Remember it and look for the
* the beginning of another sequence, which should be the
* low surrogate.
*/
got_hi_surrogate = tok->ucs_char;
/* Not at end, and the next two chars should be "\u" */
if ((tok->char_offset+1 != len) &&
(tok->char_offset+2 != len) &&
(str[1] == '\\') &&
(str[2] == 'u'))
{
/* Advance through the 16 bit surrogate, and move on to the
* next sequence. The next step is to process the following
* characters.
*/
if( !ADVANCE_CHAR(str, tok) || !ADVANCE_CHAR(str, tok) ) {
printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
}
/* Advance to the first char of the next sequence and
* continue processing with the next sequence.
*/
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
goto out;
}
tok->ucs_char = 0;
tok->st_pos = 0;
continue; /* other json_tokener_state_escape_unicode */
} else {
/* Got a high surrogate without another sequence following
* it. Put a replacement char in for the hi surrogate
* and pretend we finished.
*/
printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
}
} else if (IS_LOW_SURROGATE(tok->ucs_char)) {
/* Got a low surrogate not preceded by a high */
printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
} else if (tok->ucs_char < 0x10000) {
unescaped_utf[0] = 0xe0 | (tok->ucs_char >> 12);
unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
unescaped_utf[2] = 0x80 | (tok->ucs_char & 0x3f);
printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 3);
} else if (tok->ucs_char < 0x110000) {
unescaped_utf[0] = 0xf0 | ((tok->ucs_char >> 18) & 0x07);
unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 12) & 0x3f);
unescaped_utf[2] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
unescaped_utf[3] = 0x80 | (tok->ucs_char & 0x3f);
printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 4);
} else {
/* Don't know what we got--insert the replacement char */
printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
}
state = saved_state;
break;
}
} else {
tok->err = json_tokener_error_parse_string;
goto out;
}
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
if (got_hi_surrogate) /* Clean up any pending chars */
printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
goto out;
}
}
}
break;
case json_tokener_state_boolean:
{
int size1, size2;
printbuf_memappend_fast(tok->pb, &c, 1);
size1 = json_min(tok->st_pos+1, json_true_str_len);
size2 = json_min(tok->st_pos+1, json_false_str_len);
if((!(tok->flags & JSON_TOKENER_STRICT) &&
strncasecmp(json_true_str, tok->pb->buf, size1) == 0)
|| (strncmp(json_true_str, tok->pb->buf, size1) == 0)
) {
if(tok->st_pos == json_true_str_len) {
current = json_object_new_boolean(1);
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
goto redo_char;
}
} else if((!(tok->flags & JSON_TOKENER_STRICT) &&
strncasecmp(json_false_str, tok->pb->buf, size2) == 0)
|| (strncmp(json_false_str, tok->pb->buf, size2) == 0)) {
if(tok->st_pos == json_false_str_len) {
current = json_object_new_boolean(0);
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
goto redo_char;
}
} else {
tok->err = json_tokener_error_parse_boolean;
goto out;
}
tok->st_pos++;
}
break;
case json_tokener_state_number:
{
/* Advance until we change state */
const char *case_start = str;
int case_len=0;
while(c && strchr(json_number_chars, c)) {
++case_len;
if(c == '.' || c == 'e' || c == 'E')
tok->is_double = 1;
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
printbuf_memappend_fast(tok->pb, case_start, case_len);
goto out;
}
}
if (case_len>0)
printbuf_memappend_fast(tok->pb, case_start, case_len);
// Check for -Infinity
if (tok->pb->buf[0] == '-' && case_len == 1 &&
(c == 'i' || c == 'I'))
{
state = json_tokener_state_inf;
goto redo_char;
}
}
{
int64_t num64;
double numd;
if (!tok->is_double && json_parse_int64(tok->pb->buf, &num64) == 0) {
if (num64 && tok->pb->buf[0]=='0' && (tok->flags & JSON_TOKENER_STRICT)) {
/* in strict mode, number must not start with 0 */
tok->err = json_tokener_error_parse_number;
goto out;
}
current = json_object_new_int64(num64);
}
else if(tok->is_double && json_parse_double(tok->pb->buf, &numd) == 0)
{
current = json_object_new_double_s(numd, tok->pb->buf);
} else {
tok->err = json_tokener_error_parse_number;
goto out;
}
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
goto redo_char;
}
break;
case json_tokener_state_array_after_sep:
case json_tokener_state_array:
if(c == ']') {
if (state == json_tokener_state_array_after_sep &&
(tok->flags & JSON_TOKENER_STRICT))
{
tok->err = json_tokener_error_parse_unexpected;
goto out;
}
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
} else {
if(tok->depth >= tok->max_depth-1) {
tok->err = json_tokener_error_depth;
goto out;
}
state = json_tokener_state_array_add;
tok->depth++;
json_tokener_reset_level(tok, tok->depth);
goto redo_char;
}
break;
case json_tokener_state_array_add:
json_object_array_add(current, obj);
saved_state = json_tokener_state_array_sep;
state = json_tokener_state_eatws;
goto redo_char;
case json_tokener_state_array_sep:
if(c == ']') {
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
} else if(c == ',') {
saved_state = json_tokener_state_array_after_sep;
state = json_tokener_state_eatws;
} else {
tok->err = json_tokener_error_parse_array;
goto out;
}
break;
case json_tokener_state_object_field_start:
case json_tokener_state_object_field_start_after_sep:
if(c == '}') {
if (state == json_tokener_state_object_field_start_after_sep &&
(tok->flags & JSON_TOKENER_STRICT))
{
tok->err = json_tokener_error_parse_unexpected;
goto out;
}
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
} else if (c == '"' || c == '\'') {
tok->quote_char = c;
printbuf_reset(tok->pb);
state = json_tokener_state_object_field;
} else {
tok->err = json_tokener_error_parse_object_key_name;
goto out;
}
break;
case json_tokener_state_object_field:
{
/* Advance until we change state */
const char *case_start = str;
while(1) {
if(c == tok->quote_char) {
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
obj_field_name = strdup(tok->pb->buf);
saved_state = json_tokener_state_object_field_end;
state = json_tokener_state_eatws;
break;
} else if(c == '\\') {
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
saved_state = json_tokener_state_object_field;
state = json_tokener_state_string_escape;
break;
}
if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
printbuf_memappend_fast(tok->pb, case_start, str-case_start);
goto out;
}
}
}
break;
case json_tokener_state_object_field_end:
if(c == ':') {
saved_state = json_tokener_state_object_value;
state = json_tokener_state_eatws;
} else {
tok->err = json_tokener_error_parse_object_key_sep;
goto out;
}
break;
case json_tokener_state_object_value:
if(tok->depth >= tok->max_depth-1) {
tok->err = json_tokener_error_depth;
goto out;
}
state = json_tokener_state_object_value_add;
tok->depth++;
json_tokener_reset_level(tok, tok->depth);
goto redo_char;
case json_tokener_state_object_value_add:
json_object_object_add(current, obj_field_name, obj);
free(obj_field_name);
obj_field_name = NULL;
saved_state = json_tokener_state_object_sep;
state = json_tokener_state_eatws;
goto redo_char;
case json_tokener_state_object_sep:
if(c == '}') {
saved_state = json_tokener_state_finish;
state = json_tokener_state_eatws;
} else if(c == ',') {
saved_state = json_tokener_state_object_field_start_after_sep;
state = json_tokener_state_eatws;
} else {
tok->err = json_tokener_error_parse_object_value_sep;
goto out;
}
break;
}
if (!ADVANCE_CHAR(str, tok))
goto out;
} /* while(POP_CHAR) */
out:
if (c &&
(state == json_tokener_state_finish) &&
(tok->depth == 0) &&
(tok->flags & JSON_TOKENER_STRICT)) {
/* unexpected char after JSON data */
tok->err = json_tokener_error_parse_unexpected;
}
if (!c) { /* We hit an eof char (0) */
if(state != json_tokener_state_finish &&
saved_state != json_tokener_state_finish)
tok->err = json_tokener_error_parse_eof;
}
#ifdef HAVE_SETLOCALE
setlocale(LC_NUMERIC, oldlocale);
if (oldlocale) free(oldlocale);
#endif
if (tok->err == json_tokener_success)
{
json_object *ret = json_object_get(current);
int ii;
/* Partially reset, so we parse additional objects on subsequent calls. */
for(ii = tok->depth; ii >= 0; ii--)
json_tokener_reset_level(tok, ii);
return ret;
}
MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n",
json_tokener_errors[tok->err], tok->char_offset);
return NULL;
}
void json_tokener_set_flags(struct json_tokener *tok, int flags)
{
tok->flags = flags;
}

View File

@@ -1,208 +0,0 @@
/*
* $Id: json_tokener.h,v 1.10 2006/07/25 03:24:50 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#ifndef _json_tokener_h_
#define _json_tokener_h_
#include <stddef.h>
#include "json_object.h"
#ifdef __cplusplus
extern "C" {
#endif
enum json_tokener_error {
json_tokener_success,
json_tokener_continue,
json_tokener_error_depth,
json_tokener_error_parse_eof,
json_tokener_error_parse_unexpected,
json_tokener_error_parse_null,
json_tokener_error_parse_boolean,
json_tokener_error_parse_number,
json_tokener_error_parse_array,
json_tokener_error_parse_object_key_name,
json_tokener_error_parse_object_key_sep,
json_tokener_error_parse_object_value_sep,
json_tokener_error_parse_string,
json_tokener_error_parse_comment,
json_tokener_error_size
};
enum json_tokener_state {
json_tokener_state_eatws,
json_tokener_state_start,
json_tokener_state_finish,
json_tokener_state_null,
json_tokener_state_comment_start,
json_tokener_state_comment,
json_tokener_state_comment_eol,
json_tokener_state_comment_end,
json_tokener_state_string,
json_tokener_state_string_escape,
json_tokener_state_escape_unicode,
json_tokener_state_boolean,
json_tokener_state_number,
json_tokener_state_array,
json_tokener_state_array_add,
json_tokener_state_array_sep,
json_tokener_state_object_field_start,
json_tokener_state_object_field,
json_tokener_state_object_field_end,
json_tokener_state_object_value,
json_tokener_state_object_value_add,
json_tokener_state_object_sep,
json_tokener_state_array_after_sep,
json_tokener_state_object_field_start_after_sep,
json_tokener_state_inf
};
struct json_tokener_srec
{
enum json_tokener_state state, saved_state;
struct json_object *obj;
struct json_object *current;
char *obj_field_name;
};
#define JSON_TOKENER_DEFAULT_DEPTH 32
struct json_tokener
{
char *str;
struct printbuf *pb;
int max_depth, depth, is_double, st_pos, char_offset;
enum json_tokener_error err;
unsigned int ucs_char;
char quote_char;
struct json_tokener_srec *stack;
int flags;
};
/**
* Be strict when parsing JSON input. Use caution with
* this flag as what is considered valid may become more
* restrictive from one release to the next, causing your
* code to fail on previously working input.
*
* This flag is not set by default.
*
* @see json_tokener_set_flags()
*/
#define JSON_TOKENER_STRICT 0x01
/**
* Given an error previously returned by json_tokener_get_error(),
* return a human readable description of the error.
*
* @return a generic error message is returned if an invalid error value is provided.
*/
const char *json_tokener_error_desc(enum json_tokener_error jerr);
/**
* Retrieve the error caused by the last call to json_tokener_parse_ex(),
* or json_tokener_success if there is no error.
*
* When parsing a JSON string in pieces, if the tokener is in the middle
* of parsing this will return json_tokener_continue.
*
* See also json_tokener_error_desc().
*/
enum json_tokener_error json_tokener_get_error(struct json_tokener *tok);
extern struct json_tokener* json_tokener_new(void);
extern struct json_tokener* json_tokener_new_ex(int depth);
extern void json_tokener_free(struct json_tokener *tok);
extern void json_tokener_reset(struct json_tokener *tok);
extern struct json_object* json_tokener_parse(const char *str);
extern struct json_object* json_tokener_parse_verbose(const char *str, enum json_tokener_error *error);
/**
* Set flags that control how parsing will be done.
*/
extern void json_tokener_set_flags(struct json_tokener *tok, int flags);
/**
* Parse a string and return a non-NULL json_object if a valid JSON value
* is found. The string does not need to be a JSON object or array;
* it can also be a string, number or boolean value.
*
* A partial JSON string can be parsed. If the parsing is incomplete,
* NULL will be returned and json_tokener_get_error() will be return
* json_tokener_continue.
* json_tokener_parse_ex() can then be called with additional bytes in str
* to continue the parsing.
*
* If json_tokener_parse_ex() returns NULL and the error anything other than
* json_tokener_continue, a fatal error has occurred and parsing must be
* halted. Then tok object must not be re-used until json_tokener_reset() is
* called.
*
* When a valid JSON value is parsed, a non-NULL json_object will be
* returned. Also, json_tokener_get_error() will return json_tokener_success.
* Be sure to check the type with json_object_is_type() or
* json_object_get_type() before using the object.
*
* @b XXX this shouldn't use internal fields:
* Trailing characters after the parsed value do not automatically cause an
* error. It is up to the caller to decide whether to treat this as an
* error or to handle the additional characters, perhaps by parsing another
* json value starting from that point.
*
* Extra characters can be detected by comparing the tok->char_offset against
* the length of the last len parameter passed in.
*
* The tokener does \b not maintain an internal buffer so the caller is
* responsible for calling json_tokener_parse_ex with an appropriate str
* parameter starting with the extra characters.
*
* This interface is presently not 64-bit clean due to the int len argument
* so the function limits the maximum string size to INT32_MAX (2GB).
* If the function is called with len == -1 then strlen is called to check
* the string length is less than INT32_MAX (2GB)
*
* Example:
* @code
json_object *jobj = NULL;
const char *mystring = NULL;
int stringlen = 0;
enum json_tokener_error jerr;
do {
mystring = ... // get JSON string, e.g. read from file, etc...
stringlen = strlen(mystring);
jobj = json_tokener_parse_ex(tok, mystring, stringlen);
} while ((jerr = json_tokener_get_error(tok)) == json_tokener_continue);
if (jerr != json_tokener_success)
{
fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr));
// Handle errors, as appropriate for your application.
}
if (tok->char_offset < stringlen) // XXX shouldn't access internal fields
{
// Handle extra characters after parsed object as desired.
// e.g. issue an error, parse another object from that point, etc...
}
// Success, use jobj here.
@endcode
*
* @param tok a json_tokener previously allocated with json_tokener_new()
* @param str an string with any valid JSON expression, or portion of. This does not need to be null terminated.
* @param len the length of str
*/
extern struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
const char *str, int len);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,299 +0,0 @@
/*
* $Id: json_util.c,v 1.4 2006/01/30 23:07:57 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#include "config.h"
#undef realloc
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <limits.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif /* HAVE_SYS_TYPES_H */
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif /* HAVE_SYS_STAT_H */
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif /* HAVE_FCNTL_H */
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif /* HAVE_UNISTD_H */
#ifdef WIN32
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# include <io.h>
#endif /* defined(WIN32) */
#if !defined(HAVE_OPEN) && defined(WIN32)
# define open _open
#endif
#if !defined(HAVE_SNPRINTF) && defined(_MSC_VER)
/* MSC has the version as _snprintf */
# define snprintf _snprintf
#elif !defined(HAVE_SNPRINTF)
# error You do not have snprintf on your system.
#endif /* HAVE_SNPRINTF */
#include "debug.h"
#include "printbuf.h"
#include "json_inttypes.h"
#include "json_object.h"
#include "json_tokener.h"
#include "json_util.h"
static int sscanf_is_broken = 0;
static int sscanf_is_broken_testdone = 0;
static void sscanf_is_broken_test(void);
struct json_object* json_object_from_file(const char *filename)
{
struct printbuf *pb;
struct json_object *obj;
char buf[JSON_FILE_BUF_SIZE];
int fd, ret;
if((fd = open(filename, O_RDONLY)) < 0) {
MC_ERROR("json_object_from_file: error opening file %s: %s\n",
filename, strerror(errno));
return NULL;
}
if(!(pb = printbuf_new())) {
close(fd);
MC_ERROR("json_object_from_file: printbuf_new failed\n");
return NULL;
}
while((ret = read(fd, buf, JSON_FILE_BUF_SIZE)) > 0) {
printbuf_memappend(pb, buf, ret);
}
close(fd);
if(ret < 0) {
MC_ERROR("json_object_from_file: error reading file %s: %s\n",
filename, strerror(errno));
printbuf_free(pb);
return NULL;
}
obj = json_tokener_parse(pb->buf);
printbuf_free(pb);
return obj;
}
/* extended "format and write to file" function */
int json_object_to_file_ext(const char *filename, struct json_object *obj, int flags)
{
const char *json_str;
int fd, ret;
unsigned int wpos, wsize;
if(!obj) {
MC_ERROR("json_object_to_file: object is null\n");
return -1;
}
if((fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0) {
MC_ERROR("json_object_to_file: error opening file %s: %s\n",
filename, strerror(errno));
return -1;
}
if(!(json_str = json_object_to_json_string_ext(obj,flags))) {
close(fd);
return -1;
}
wsize = (unsigned int)(strlen(json_str) & UINT_MAX); /* CAW: probably unnecessary, but the most 64bit safe */
wpos = 0;
while(wpos < wsize) {
if((ret = write(fd, json_str + wpos, wsize-wpos)) < 0) {
close(fd);
MC_ERROR("json_object_to_file: error writing file %s: %s\n",
filename, strerror(errno));
return -1;
}
/* because of the above check for ret < 0, we can safely cast and add */
wpos += (unsigned int)ret;
}
close(fd);
return 0;
}
// backwards compatible "format and write to file" function
int json_object_to_file(const char *filename, struct json_object *obj)
{
return json_object_to_file_ext(filename, obj, JSON_C_TO_STRING_PLAIN);
}
int json_parse_double(const char *buf, double *retval)
{
return (sscanf(buf, "%lf", retval)==1 ? 0 : 1);
}
/*
* Not all implementations of sscanf actually work properly.
* Check whether the one we're currently using does, and if
* it's broken, enable the workaround code.
*/
static void sscanf_is_broken_test()
{
int64_t num64;
int ret_errno, is_int64_min, ret_errno2, is_int64_max;
(void)sscanf(" -01234567890123456789012345", "%" SCNd64, &num64);
ret_errno = errno;
is_int64_min = (num64 == INT64_MIN);
(void)sscanf(" 01234567890123456789012345", "%" SCNd64, &num64);
ret_errno2 = errno;
is_int64_max = (num64 == INT64_MAX);
if (ret_errno != ERANGE || !is_int64_min ||
ret_errno2 != ERANGE || !is_int64_max)
{
MC_DEBUG("sscanf_is_broken_test failed, enabling workaround code\n");
sscanf_is_broken = 1;
}
}
int json_parse_int64(const char *buf, int64_t *retval)
{
int64_t num64;
const char *buf_sig_digits;
int orig_has_neg;
int saved_errno;
if (!sscanf_is_broken_testdone)
{
sscanf_is_broken_test();
sscanf_is_broken_testdone = 1;
}
// Skip leading spaces
while (isspace((int)*buf) && *buf)
buf++;
errno = 0; // sscanf won't always set errno, so initialize
if (sscanf(buf, "%" SCNd64, &num64) != 1)
{
MC_DEBUG("Failed to parse, sscanf != 1\n");
return 1;
}
saved_errno = errno;
buf_sig_digits = buf;
orig_has_neg = 0;
if (*buf_sig_digits == '-')
{
buf_sig_digits++;
orig_has_neg = 1;
}
// Not all sscanf implementations actually work
if (sscanf_is_broken && saved_errno != ERANGE)
{
char buf_cmp[100];
char *buf_cmp_start = buf_cmp;
int recheck_has_neg = 0;
int buf_cmp_len;
// Skip leading zeros, but keep at least one digit
while (buf_sig_digits[0] == '0' && buf_sig_digits[1] != '\0')
buf_sig_digits++;
if (num64 == 0) // assume all sscanf impl's will parse -0 to 0
orig_has_neg = 0; // "-0" is the same as just plain "0"
snprintf(buf_cmp_start, sizeof(buf_cmp), "%" PRId64, num64);
if (*buf_cmp_start == '-')
{
recheck_has_neg = 1;
buf_cmp_start++;
}
// No need to skip leading spaces or zeros here.
buf_cmp_len = strlen(buf_cmp_start);
/**
* If the sign is different, or
* some of the digits are different, or
* there is another digit present in the original string
* then we have NOT successfully parsed the value.
*/
if (orig_has_neg != recheck_has_neg ||
strncmp(buf_sig_digits, buf_cmp_start, strlen(buf_cmp_start)) != 0 ||
((int)strlen(buf_sig_digits) != buf_cmp_len &&
isdigit((int)buf_sig_digits[buf_cmp_len])
)
)
{
saved_errno = ERANGE;
}
}
// Not all sscanf impl's set the value properly when out of range.
// Always do this, even for properly functioning implementations,
// since it shouldn't slow things down much.
if (saved_errno == ERANGE)
{
if (orig_has_neg)
num64 = INT64_MIN;
else
num64 = INT64_MAX;
}
*retval = num64;
return 0;
}
#ifndef HAVE_REALLOC
void* rpl_realloc(void* p, size_t n)
{
if (n == 0)
n = 1;
if (p == 0)
return malloc(n);
return realloc(p, n);
}
#endif
#define NELEM(a) (sizeof(a) / sizeof(a[0]))
static const char* json_type_name[] = {
/* If you change this, be sure to update the enum json_type definition too */
"null",
"boolean",
"double",
"int",
"object",
"array",
"string",
};
const char *json_type_to_name(enum json_type o_type)
{
int o_type_int = (int)o_type;
if (o_type_int < 0 || o_type_int >= (int)NELEM(json_type_name))
{
MC_ERROR("json_type_to_name: type %d is out of range [0,%d]\n", o_type, NELEM(json_type_name));
return NULL;
}
return json_type_name[o_type];
}

View File

@@ -1,50 +0,0 @@
/*
* $Id: json_util.h,v 1.4 2006/01/30 23:07:57 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#ifndef _json_util_h_
#define _json_util_h_
#include "json_object.h"
#ifndef json_min
#define json_min(a,b) ((a) < (b) ? (a) : (b))
#endif
#ifndef json_max
#define json_max(a,b) ((a) > (b) ? (a) : (b))
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define JSON_FILE_BUF_SIZE 4096
/* utility functions */
extern struct json_object* json_object_from_file(const char *filename);
extern int json_object_to_file(const char *filename, struct json_object *obj);
extern int json_object_to_file_ext(const char *filename, struct json_object *obj, int flags);
extern int json_parse_int64(const char *buf, int64_t *retval);
extern int json_parse_double(const char *buf, double *retval);
/**
* Return a string describing the type of the object.
* e.g. "int", or "object", etc...
*/
extern const char *json_type_to_name(enum json_type o_type);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,26 +0,0 @@
/* dummy source file for compatibility purposes */
#if defined(HAVE_CDEFS_H)
#include <sys/cdefs.h>
#endif
#ifndef __warn_references
#if defined(__GNUC__) && defined (HAS_GNU_WARNING_LONG)
#define __warn_references(sym,msg) \
__asm__(".section .gnu" #sym ",\n\t.ascii \"" msg "\"\n\t.text");
#else
#define __warn_references(sym,msg) /* nothing */
#endif
#endif
#include "json_object.h"
__warn_references(json_object_get, "Warning: please link against libjson-c instead of libjson");
/* __asm__(".section .gnu.warning." __STRING(sym) \
" ; .ascii \"" msg "\" ; .text") */

View File

@@ -1,602 +0,0 @@
/*
* $Id: linkhash.c,v 1.4 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stddef.h>
#include <limits.h>
#ifdef HAVE_ENDIAN_H
# include <endian.h> /* attempt to define endianness */
#endif
#include "random_seed.h"
#include "linkhash.h"
void lh_abort(const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
vprintf(msg, ap);
va_end(ap);
exit(1);
}
unsigned long lh_ptr_hash(const void *k)
{
/* CAW: refactored to be 64bit nice */
return (unsigned long)((((ptrdiff_t)k * LH_PRIME) >> 4) & ULONG_MAX);
}
int lh_ptr_equal(const void *k1, const void *k2)
{
return (k1 == k2);
}
/*
* hashlittle from lookup3.c, by Bob Jenkins, May 2006, Public Domain.
* http://burtleburtle.net/bob/c/lookup3.c
* minor modifications to make functions static so no symbols are exported
* minor mofifications to compile with -Werror
*/
/*
-------------------------------------------------------------------------------
lookup3.c, by Bob Jenkins, May 2006, Public Domain.
These are functions for producing 32-bit hashes for hash table lookup.
hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final()
are externally useful functions. Routines to test the hash are included
if SELF_TEST is defined. You can use this free for any purpose. It's in
the public domain. It has no warranty.
You probably want to use hashlittle(). hashlittle() and hashbig()
hash byte arrays. hashlittle() is is faster than hashbig() on
little-endian machines. Intel and AMD are little-endian machines.
On second thought, you probably want hashlittle2(), which is identical to
hashlittle() except it returns two 32-bit hashes for the price of one.
You could implement hashbig2() if you wanted but I haven't bothered here.
If you want to find a hash of, say, exactly 7 integers, do
a = i1; b = i2; c = i3;
mix(a,b,c);
a += i4; b += i5; c += i6;
mix(a,b,c);
a += i7;
final(a,b,c);
then use c as the hash value. If you have a variable length array of
4-byte integers to hash, use hashword(). If you have a byte array (like
a character string), use hashlittle(). If you have several byte arrays, or
a mix of things, see the comments above hashlittle().
Why is this so big? I read 12 bytes at a time into 3 4-byte integers,
then mix those integers. This is fast (you can do a lot more thorough
mixing with 12*3 instructions on 3 integers than you can with 3 instructions
on 1 byte), but shoehorning those bytes into integers efficiently is messy.
-------------------------------------------------------------------------------
*/
/*
* My best guess at if you are big-endian or little-endian. This may
* need adjustment.
*/
#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
__BYTE_ORDER == __LITTLE_ENDIAN) || \
(defined(i386) || defined(__i386__) || defined(__i486__) || \
defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL))
# define HASH_LITTLE_ENDIAN 1
# define HASH_BIG_ENDIAN 0
#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \
__BYTE_ORDER == __BIG_ENDIAN) || \
(defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel))
# define HASH_LITTLE_ENDIAN 0
# define HASH_BIG_ENDIAN 1
#else
# define HASH_LITTLE_ENDIAN 0
# define HASH_BIG_ENDIAN 0
#endif
#define hashsize(n) ((uint32_t)1<<(n))
#define hashmask(n) (hashsize(n)-1)
#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
/*
-------------------------------------------------------------------------------
mix -- mix 3 32-bit values reversibly.
This is reversible, so any information in (a,b,c) before mix() is
still in (a,b,c) after mix().
If four pairs of (a,b,c) inputs are run through mix(), or through
mix() in reverse, there are at least 32 bits of the output that
are sometimes the same for one pair and different for another pair.
This was tested for:
* pairs that differed by one bit, by two bits, in any combination
of top bits of (a,b,c), or in any combination of bottom bits of
(a,b,c).
* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
is commonly produced by subtraction) look like a single 1-bit
difference.
* the base values were pseudorandom, all zero but one bit set, or
all zero plus a counter that starts at zero.
Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that
satisfy this are
4 6 8 16 19 4
9 15 3 18 27 15
14 9 3 7 17 3
Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing
for "differ" defined as + with a one-bit base and a two-bit delta. I
used http://burtleburtle.net/bob/hash/avalanche.html to choose
the operations, constants, and arrangements of the variables.
This does not achieve avalanche. There are input bits of (a,b,c)
that fail to affect some output bits of (a,b,c), especially of a. The
most thoroughly mixed value is c, but it doesn't really even achieve
avalanche in c.
This allows some parallelism. Read-after-writes are good at doubling
the number of bits affected, so the goal of mixing pulls in the opposite
direction as the goal of parallelism. I did what I could. Rotates
seem to cost as much as shifts on every machine I could lay my hands
on, and rotates are much kinder to the top and bottom bits, so I used
rotates.
-------------------------------------------------------------------------------
*/
#define mix(a,b,c) \
{ \
a -= c; a ^= rot(c, 4); c += b; \
b -= a; b ^= rot(a, 6); a += c; \
c -= b; c ^= rot(b, 8); b += a; \
a -= c; a ^= rot(c,16); c += b; \
b -= a; b ^= rot(a,19); a += c; \
c -= b; c ^= rot(b, 4); b += a; \
}
/*
-------------------------------------------------------------------------------
final -- final mixing of 3 32-bit values (a,b,c) into c
Pairs of (a,b,c) values differing in only a few bits will usually
produce values of c that look totally different. This was tested for
* pairs that differed by one bit, by two bits, in any combination
of top bits of (a,b,c), or in any combination of bottom bits of
(a,b,c).
* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
is commonly produced by subtraction) look like a single 1-bit
difference.
* the base values were pseudorandom, all zero but one bit set, or
all zero plus a counter that starts at zero.
These constants passed:
14 11 25 16 4 14 24
12 14 25 16 4 14 24
and these came close:
4 8 15 26 3 22 24
10 8 15 26 3 22 24
11 8 15 26 3 22 24
-------------------------------------------------------------------------------
*/
#define final(a,b,c) \
{ \
c ^= b; c -= rot(b,14); \
a ^= c; a -= rot(c,11); \
b ^= a; b -= rot(a,25); \
c ^= b; c -= rot(b,16); \
a ^= c; a -= rot(c,4); \
b ^= a; b -= rot(a,14); \
c ^= b; c -= rot(b,24); \
}
/*
-------------------------------------------------------------------------------
hashlittle() -- hash a variable-length key into a 32-bit value
k : the key (the unaligned variable-length array of bytes)
length : the length of the key, counting by bytes
initval : can be any 4-byte value
Returns a 32-bit value. Every bit of the key affects every bit of
the return value. Two keys differing by one or two bits will have
totally different hash values.
The best hash table sizes are powers of 2. There is no need to do
mod a prime (mod is sooo slow!). If you need less than 32 bits,
use a bitmask. For example, if you need only 10 bits, do
h = (h & hashmask(10));
In which case, the hash table should have hashsize(10) elements.
If you are hashing n strings (uint8_t **)k, do it like this:
for (i=0, h=0; i<n; ++i) h = hashlittle( k[i], len[i], h);
By Bob Jenkins, 2006. bob_jenkins@burtleburtle.net. You may use this
code any way you wish, private, educational, or commercial. It's free.
Use for hash table lookup, or anything where one collision in 2^^32 is
acceptable. Do NOT use for cryptographic purposes.
-------------------------------------------------------------------------------
*/
static uint32_t hashlittle( const void *key, size_t length, uint32_t initval)
{
uint32_t a,b,c; /* internal state */
union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */
/* Set up the internal state */
a = b = c = 0xdeadbeef + ((uint32_t)length) + initval;
u.ptr = key;
if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {
const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */
/*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
while (length > 12)
{
a += k[0];
b += k[1];
c += k[2];
mix(a,b,c);
length -= 12;
k += 3;
}
/*----------------------------- handle the last (probably partial) block */
/*
* "k[2]&0xffffff" actually reads beyond the end of the string, but
* then masks off the part it's not allowed to read. Because the
* string is aligned, the masked-off tail is in the same word as the
* rest of the string. Every machine with memory protection I've seen
* does it on word boundaries, so is OK with this. But VALGRIND will
* still catch it and complain. The masking trick does make the hash
* noticably faster for short strings (like English words).
*/
#ifndef VALGRIND
switch(length)
{
case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break;
case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break;
case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break;
case 8 : b+=k[1]; a+=k[0]; break;
case 7 : b+=k[1]&0xffffff; a+=k[0]; break;
case 6 : b+=k[1]&0xffff; a+=k[0]; break;
case 5 : b+=k[1]&0xff; a+=k[0]; break;
case 4 : a+=k[0]; break;
case 3 : a+=k[0]&0xffffff; break;
case 2 : a+=k[0]&0xffff; break;
case 1 : a+=k[0]&0xff; break;
case 0 : return c; /* zero length strings require no mixing */
}
#else /* make valgrind happy */
const uint8_t *k8 = (const uint8_t *)k;
switch(length)
{
case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
case 10: c+=((uint32_t)k8[9])<<8; /* fall through */
case 9 : c+=k8[8]; /* fall through */
case 8 : b+=k[1]; a+=k[0]; break;
case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */
case 5 : b+=k8[4]; /* fall through */
case 4 : a+=k[0]; break;
case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */
case 1 : a+=k8[0]; break;
case 0 : return c;
}
#endif /* !valgrind */
} else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) {
const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */
const uint8_t *k8;
/*--------------- all but last block: aligned reads and different mixing */
while (length > 12)
{
a += k[0] + (((uint32_t)k[1])<<16);
b += k[2] + (((uint32_t)k[3])<<16);
c += k[4] + (((uint32_t)k[5])<<16);
mix(a,b,c);
length -= 12;
k += 6;
}
/*----------------------------- handle the last (probably partial) block */
k8 = (const uint8_t *)k;
switch(length)
{
case 12: c+=k[4]+(((uint32_t)k[5])<<16);
b+=k[2]+(((uint32_t)k[3])<<16);
a+=k[0]+(((uint32_t)k[1])<<16);
break;
case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
case 10: c+=k[4];
b+=k[2]+(((uint32_t)k[3])<<16);
a+=k[0]+(((uint32_t)k[1])<<16);
break;
case 9 : c+=k8[8]; /* fall through */
case 8 : b+=k[2]+(((uint32_t)k[3])<<16);
a+=k[0]+(((uint32_t)k[1])<<16);
break;
case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
case 6 : b+=k[2];
a+=k[0]+(((uint32_t)k[1])<<16);
break;
case 5 : b+=k8[4]; /* fall through */
case 4 : a+=k[0]+(((uint32_t)k[1])<<16);
break;
case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
case 2 : a+=k[0];
break;
case 1 : a+=k8[0];
break;
case 0 : return c; /* zero length requires no mixing */
}
} else { /* need to read the key one byte at a time */
const uint8_t *k = (const uint8_t *)key;
/*--------------- all but the last block: affect some 32 bits of (a,b,c) */
while (length > 12)
{
a += k[0];
a += ((uint32_t)k[1])<<8;
a += ((uint32_t)k[2])<<16;
a += ((uint32_t)k[3])<<24;
b += k[4];
b += ((uint32_t)k[5])<<8;
b += ((uint32_t)k[6])<<16;
b += ((uint32_t)k[7])<<24;
c += k[8];
c += ((uint32_t)k[9])<<8;
c += ((uint32_t)k[10])<<16;
c += ((uint32_t)k[11])<<24;
mix(a,b,c);
length -= 12;
k += 12;
}
/*-------------------------------- last block: affect all 32 bits of (c) */
switch(length) /* all the case statements fall through */
{
case 12: c+=((uint32_t)k[11])<<24;
case 11: c+=((uint32_t)k[10])<<16;
case 10: c+=((uint32_t)k[9])<<8;
case 9 : c+=k[8];
case 8 : b+=((uint32_t)k[7])<<24;
case 7 : b+=((uint32_t)k[6])<<16;
case 6 : b+=((uint32_t)k[5])<<8;
case 5 : b+=k[4];
case 4 : a+=((uint32_t)k[3])<<24;
case 3 : a+=((uint32_t)k[2])<<16;
case 2 : a+=((uint32_t)k[1])<<8;
case 1 : a+=k[0];
break;
case 0 : return c;
}
}
final(a,b,c);
return c;
}
unsigned long lh_char_hash(const void *k)
{
static volatile int random_seed = -1;
if (random_seed == -1) {
int seed;
/* we can't use -1 as it is the unitialized sentinel */
while ((seed = json_c_get_random_seed()) == -1);
#if defined __GNUC__
__sync_val_compare_and_swap(&random_seed, -1, seed);
#elif defined _MSC_VER
InterlockedCompareExchange(&random_seed, seed, -1);
#else
#warning "racy random seed initializtion if used by multiple threads"
random_seed = seed; /* potentially racy */
#endif
}
return hashlittle((const char*)k, strlen((const char*)k), random_seed);
}
int lh_char_equal(const void *k1, const void *k2)
{
return (strcmp((const char*)k1, (const char*)k2) == 0);
}
struct lh_table* lh_table_new(int size, const char *name,
lh_entry_free_fn *free_fn,
lh_hash_fn *hash_fn,
lh_equal_fn *equal_fn)
{
int i;
struct lh_table *t;
t = (struct lh_table*)calloc(1, sizeof(struct lh_table));
if(!t) lh_abort("lh_table_new: calloc failed\n");
t->count = 0;
t->size = size;
t->name = name;
t->table = (struct lh_entry*)calloc(size, sizeof(struct lh_entry));
if(!t->table) lh_abort("lh_table_new: calloc failed\n");
t->free_fn = free_fn;
t->hash_fn = hash_fn;
t->equal_fn = equal_fn;
for(i = 0; i < size; i++) t->table[i].k = LH_EMPTY;
return t;
}
struct lh_table* lh_kchar_table_new(int size, const char *name,
lh_entry_free_fn *free_fn)
{
return lh_table_new(size, name, free_fn, lh_char_hash, lh_char_equal);
}
struct lh_table* lh_kptr_table_new(int size, const char *name,
lh_entry_free_fn *free_fn)
{
return lh_table_new(size, name, free_fn, lh_ptr_hash, lh_ptr_equal);
}
void lh_table_resize(struct lh_table *t, int new_size)
{
struct lh_table *new_t;
struct lh_entry *ent;
new_t = lh_table_new(new_size, t->name, NULL, t->hash_fn, t->equal_fn);
ent = t->head;
while(ent) {
lh_table_insert(new_t, ent->k, ent->v);
ent = ent->next;
}
free(t->table);
t->table = new_t->table;
t->size = new_size;
t->head = new_t->head;
t->tail = new_t->tail;
t->resizes++;
free(new_t);
}
void lh_table_free(struct lh_table *t)
{
struct lh_entry *c;
for(c = t->head; c != NULL; c = c->next) {
if(t->free_fn) {
t->free_fn(c);
}
}
free(t->table);
free(t);
}
int lh_table_insert(struct lh_table *t, void *k, const void *v)
{
unsigned long h, n;
t->inserts++;
if(t->count >= t->size * LH_LOAD_FACTOR) lh_table_resize(t, t->size * 2);
h = t->hash_fn(k);
n = h % t->size;
while( 1 ) {
if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) break;
t->collisions++;
if ((int)++n == t->size) n = 0;
}
t->table[n].k = k;
t->table[n].v = v;
t->count++;
if(t->head == NULL) {
t->head = t->tail = &t->table[n];
t->table[n].next = t->table[n].prev = NULL;
} else {
t->tail->next = &t->table[n];
t->table[n].prev = t->tail;
t->table[n].next = NULL;
t->tail = &t->table[n];
}
return 0;
}
struct lh_entry* lh_table_lookup_entry(struct lh_table *t, const void *k)
{
unsigned long h = t->hash_fn(k);
unsigned long n = h % t->size;
int count = 0;
t->lookups++;
while( count < t->size ) {
if(t->table[n].k == LH_EMPTY) return NULL;
if(t->table[n].k != LH_FREED &&
t->equal_fn(t->table[n].k, k)) return &t->table[n];
if ((int)++n == t->size) n = 0;
count++;
}
return NULL;
}
const void* lh_table_lookup(struct lh_table *t, const void *k)
{
void *result;
lh_table_lookup_ex(t, k, &result);
return result;
}
json_bool lh_table_lookup_ex(struct lh_table* t, const void* k, void **v)
{
struct lh_entry *e = lh_table_lookup_entry(t, k);
if (e != NULL) {
if (v != NULL) *v = (void *)e->v;
return TRUE; /* key found */
}
if (v != NULL) *v = NULL;
return FALSE; /* key not found */
}
int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e)
{
ptrdiff_t n = (ptrdiff_t)(e - t->table); /* CAW: fixed to be 64bit nice, still need the crazy negative case... */
/* CAW: this is bad, really bad, maybe stack goes other direction on this machine... */
if(n < 0) { return -2; }
if(t->table[n].k == LH_EMPTY || t->table[n].k == LH_FREED) return -1;
t->count--;
if(t->free_fn) t->free_fn(e);
t->table[n].v = NULL;
t->table[n].k = LH_FREED;
if(t->tail == &t->table[n] && t->head == &t->table[n]) {
t->head = t->tail = NULL;
} else if (t->head == &t->table[n]) {
t->head->next->prev = NULL;
t->head = t->head->next;
} else if (t->tail == &t->table[n]) {
t->tail->prev->next = NULL;
t->tail = t->tail->prev;
} else {
t->table[n].prev->next = t->table[n].next;
t->table[n].next->prev = t->table[n].prev;
}
t->table[n].next = t->table[n].prev = NULL;
return 0;
}
int lh_table_delete(struct lh_table *t, const void *k)
{
struct lh_entry *e = lh_table_lookup_entry(t, k);
if(!e) return -1;
return lh_table_delete_entry(t, e);
}
int lh_table_length(struct lh_table *t)
{
return t->count;
}

View File

@@ -1,292 +0,0 @@
/*
* $Id: linkhash.h,v 1.6 2006/01/30 23:07:57 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
* Copyright (c) 2009 Hewlett-Packard Development Company, L.P.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#ifndef _linkhash_h_
#define _linkhash_h_
#include "json_object.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* golden prime used in hash functions
*/
#define LH_PRIME 0x9e370001UL
/**
* The fraction of filled hash buckets until an insert will cause the table
* to be resized.
* This can range from just above 0 up to 1.0.
*/
#define LH_LOAD_FACTOR 0.66
/**
* sentinel pointer value for empty slots
*/
#define LH_EMPTY (void*)-1
/**
* sentinel pointer value for freed slots
*/
#define LH_FREED (void*)-2
struct lh_entry;
/**
* callback function prototypes
*/
typedef void (lh_entry_free_fn) (struct lh_entry *e);
/**
* callback function prototypes
*/
typedef unsigned long (lh_hash_fn) (const void *k);
/**
* callback function prototypes
*/
typedef int (lh_equal_fn) (const void *k1, const void *k2);
/**
* An entry in the hash table
*/
struct lh_entry {
/**
* The key.
*/
void *k;
/**
* The value.
*/
const void *v;
/**
* The next entry
*/
struct lh_entry *next;
/**
* The previous entry.
*/
struct lh_entry *prev;
};
/**
* The hash table structure.
*/
struct lh_table {
/**
* Size of our hash.
*/
int size;
/**
* Numbers of entries.
*/
int count;
/**
* Number of collisions.
*/
int collisions;
/**
* Number of resizes.
*/
int resizes;
/**
* Number of lookups.
*/
int lookups;
/**
* Number of inserts.
*/
int inserts;
/**
* Number of deletes.
*/
int deletes;
/**
* Name of the hash table.
*/
const char *name;
/**
* The first entry.
*/
struct lh_entry *head;
/**
* The last entry.
*/
struct lh_entry *tail;
struct lh_entry *table;
/**
* A pointer onto the function responsible for freeing an entry.
*/
lh_entry_free_fn *free_fn;
lh_hash_fn *hash_fn;
lh_equal_fn *equal_fn;
};
/**
* Pre-defined hash and equality functions
*/
extern unsigned long lh_ptr_hash(const void *k);
extern int lh_ptr_equal(const void *k1, const void *k2);
extern unsigned long lh_char_hash(const void *k);
extern int lh_char_equal(const void *k1, const void *k2);
/**
* Convenience list iterator.
*/
#define lh_foreach(table, entry) \
for(entry = table->head; entry; entry = entry->next)
/**
* lh_foreach_safe allows calling of deletion routine while iterating.
*/
#define lh_foreach_safe(table, entry, tmp) \
for(entry = table->head; entry && ((tmp = entry->next) || 1); entry = tmp)
/**
* Create a new linkhash table.
* @param size initial table size. The table is automatically resized
* although this incurs a performance penalty.
* @param name the table name.
* @param free_fn callback function used to free memory for entries
* when lh_table_free or lh_table_delete is called.
* If NULL is provided, then memory for keys and values
* must be freed by the caller.
* @param hash_fn function used to hash keys. 2 standard ones are defined:
* lh_ptr_hash and lh_char_hash for hashing pointer values
* and C strings respectively.
* @param equal_fn comparison function to compare keys. 2 standard ones defined:
* lh_ptr_hash and lh_char_hash for comparing pointer values
* and C strings respectively.
* @return a pointer onto the linkhash table.
*/
extern struct lh_table* lh_table_new(int size, const char *name,
lh_entry_free_fn *free_fn,
lh_hash_fn *hash_fn,
lh_equal_fn *equal_fn);
/**
* Convenience function to create a new linkhash
* table with char keys.
* @param size initial table size.
* @param name table name.
* @param free_fn callback function used to free memory for entries.
* @return a pointer onto the linkhash table.
*/
extern struct lh_table* lh_kchar_table_new(int size, const char *name,
lh_entry_free_fn *free_fn);
/**
* Convenience function to create a new linkhash
* table with ptr keys.
* @param size initial table size.
* @param name table name.
* @param free_fn callback function used to free memory for entries.
* @return a pointer onto the linkhash table.
*/
extern struct lh_table* lh_kptr_table_new(int size, const char *name,
lh_entry_free_fn *free_fn);
/**
* Free a linkhash table.
* If a callback free function is provided then it is called for all
* entries in the table.
* @param t table to free.
*/
extern void lh_table_free(struct lh_table *t);
/**
* Insert a record into the table.
* @param t the table to insert into.
* @param k a pointer to the key to insert.
* @param v a pointer to the value to insert.
*/
extern int lh_table_insert(struct lh_table *t, void *k, const void *v);
/**
* Lookup a record into the table.
* @param t the table to lookup
* @param k a pointer to the key to lookup
* @return a pointer to the record structure of the value or NULL if it does not exist.
*/
extern struct lh_entry* lh_table_lookup_entry(struct lh_table *t, const void *k);
/**
* Lookup a record into the table
* @param t the table to lookup
* @param k a pointer to the key to lookup
* @return a pointer to the found value or NULL if it does not exist.
* @deprecated Use lh_table_lookup_ex instead.
*/
THIS_FUNCTION_IS_DEPRECATED(extern const void* lh_table_lookup(struct lh_table *t, const void *k));
/**
* Lookup a record in the table
* @param t the table to lookup
* @param k a pointer to the key to lookup
* @param v a pointer to a where to store the found value (set to NULL if it doesn't exist).
* @return whether or not the key was found
*/
extern json_bool lh_table_lookup_ex(struct lh_table *t, const void *k, void **v);
/**
* Delete a record from the table.
* If a callback free function is provided then it is called for the
* for the item being deleted.
* @param t the table to delete from.
* @param e a pointer to the entry to delete.
* @return 0 if the item was deleted.
* @return -1 if it was not found.
*/
extern int lh_table_delete_entry(struct lh_table *t, struct lh_entry *e);
/**
* Delete a record from the table.
* If a callback free function is provided then it is called for the
* for the item being deleted.
* @param t the table to delete from.
* @param k a pointer to the key to delete.
* @return 0 if the item was deleted.
* @return -1 if it was not found.
*/
extern int lh_table_delete(struct lh_table *t, const void *k);
extern int lh_table_length(struct lh_table *t);
void lh_abort(const char *msg, ...);
void lh_table_resize(struct lh_table *t, int new_size);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,28 +0,0 @@
#ifndef __math_compat_h
#define __math_compat_h
/* Define isnan and isinf on Windows/MSVC */
#ifndef HAVE_DECL_ISNAN
# ifdef HAVE_DECL__ISNAN
#include <float.h>
#define isnan(x) _isnan(x)
# endif
#endif
#ifndef HAVE_DECL_ISINF
# ifdef HAVE_DECL__FINITE
#include <float.h>
#define isinf(x) (!_finite(x))
# endif
#endif
#ifndef HAVE_DECL_NAN
#error This platform does not have nan()
#endif
#ifndef HAVE_DECL_INFINITY
#error This platform does not have INFINITY
#endif
#endif

View File

@@ -1,193 +0,0 @@
/*
* $Id: printbuf.c,v 1.5 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*
* Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved.
* The copyrights to the contents of this file are licensed under the MIT License
* (http://www.opensource.org/licenses/mit-license.php)
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_STDARG_H
# include <stdarg.h>
#else /* !HAVE_STDARG_H */
# error Not enough var arg support!
#endif /* HAVE_STDARG_H */
#include "debug.h"
#include "printbuf.h"
static int printbuf_extend(struct printbuf *p, int min_size);
struct printbuf* printbuf_new(void)
{
struct printbuf *p;
p = (struct printbuf*)calloc(1, sizeof(struct printbuf));
if(!p) return NULL;
p->size = 32;
p->bpos = 0;
if(!(p->buf = (char*)malloc(p->size))) {
free(p);
return NULL;
}
return p;
}
/**
* Extend the buffer p so it has a size of at least min_size.
*
* If the current size is large enough, nothing is changed.
*
* Note: this does not check the available space! The caller
* is responsible for performing those calculations.
*/
static int printbuf_extend(struct printbuf *p, int min_size)
{
char *t;
int new_size;
if (p->size >= min_size)
return 0;
new_size = p->size * 2;
if (new_size < min_size + 8)
new_size = min_size + 8;
#ifdef PRINTBUF_DEBUG
MC_DEBUG("printbuf_memappend: realloc "
"bpos=%d min_size=%d old_size=%d new_size=%d\n",
p->bpos, min_size, p->size, new_size);
#endif /* PRINTBUF_DEBUG */
if(!(t = (char*)realloc(p->buf, new_size)))
return -1;
p->size = new_size;
p->buf = t;
return 0;
}
int printbuf_memappend(struct printbuf *p, const char *buf, int size)
{
if (p->size <= p->bpos + size + 1) {
if (printbuf_extend(p, p->bpos + size + 1) < 0)
return -1;
}
memcpy(p->buf + p->bpos, buf, size);
p->bpos += size;
p->buf[p->bpos]= '\0';
return size;
}
int printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len)
{
int size_needed;
if (offset == -1)
offset = pb->bpos;
size_needed = offset + len;
if (pb->size < size_needed)
{
if (printbuf_extend(pb, size_needed) < 0)
return -1;
}
memset(pb->buf + offset, charvalue, len);
if (pb->bpos < size_needed)
pb->bpos = size_needed;
return 0;
}
#if !defined(HAVE_VSNPRINTF) && defined(_MSC_VER)
# define vsnprintf _vsnprintf
#elif !defined(HAVE_VSNPRINTF) /* !HAVE_VSNPRINTF */
# error Need vsnprintf!
#endif /* !HAVE_VSNPRINTF && defined(WIN32) */
#if !defined(HAVE_VASPRINTF)
/* CAW: compliant version of vasprintf */
static int vasprintf(char **buf, const char *fmt, va_list ap)
{
#ifndef WIN32
static char _T_emptybuffer = '\0';
#endif /* !defined(WIN32) */
int chars;
char *b;
if(!buf) { return -1; }
#ifdef WIN32
chars = _vscprintf(fmt, ap)+1;
#else /* !defined(WIN32) */
/* CAW: RAWR! We have to hope to god here that vsnprintf doesn't overwrite
our buffer like on some 64bit sun systems.... but hey, its time to move on */
chars = vsnprintf(&_T_emptybuffer, 0, fmt, ap)+1;
if(chars < 0) { chars *= -1; } /* CAW: old glibc versions have this problem */
#endif /* defined(WIN32) */
b = (char*)malloc(sizeof(char)*chars);
if(!b) { return -1; }
if((chars = vsprintf(b, fmt, ap)) < 0)
{
free(b);
} else {
*buf = b;
}
return chars;
}
#endif /* !HAVE_VASPRINTF */
int sprintbuf(struct printbuf *p, const char *msg, ...)
{
va_list ap;
char *t;
int size;
char buf[128];
/* user stack buffer first */
va_start(ap, msg);
size = vsnprintf(buf, 128, msg, ap);
va_end(ap);
/* if string is greater than stack buffer, then use dynamic string
with vasprintf. Note: some implementation of vsnprintf return -1
if output is truncated whereas some return the number of bytes that
would have been written - this code handles both cases. */
if(size == -1 || size > 127) {
va_start(ap, msg);
if((size = vasprintf(&t, msg, ap)) < 0) { va_end(ap); return -1; }
va_end(ap);
printbuf_memappend(p, t, size);
free(t);
return size;
} else {
printbuf_memappend(p, buf, size);
return size;
}
}
void printbuf_reset(struct printbuf *p)
{
p->buf[0] = '\0';
p->bpos = 0;
}
void printbuf_free(struct printbuf *p)
{
if(p) {
free(p->buf);
free(p);
}
}

View File

@@ -1,77 +0,0 @@
/*
* $Id: printbuf.h,v 1.4 2006/01/26 02:16:28 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*
* Copyright (c) 2008-2009 Yahoo! Inc. All rights reserved.
* The copyrights to the contents of this file are licensed under the MIT License
* (http://www.opensource.org/licenses/mit-license.php)
*/
#ifndef _printbuf_h_
#define _printbuf_h_
#ifdef __cplusplus
extern "C" {
#endif
struct printbuf {
char *buf;
int bpos;
int size;
};
extern struct printbuf*
printbuf_new(void);
/* As an optimization, printbuf_memappend_fast is defined as a macro
* that handles copying data if the buffer is large enough; otherwise
* it invokes printbuf_memappend_real() which performs the heavy
* lifting of realloc()ing the buffer and copying data.
* Your code should not use printbuf_memappend directly--use
* printbuf_memappend_fast instead.
*/
extern int
printbuf_memappend(struct printbuf *p, const char *buf, int size);
#define printbuf_memappend_fast(p, bufptr, bufsize) \
do { \
if ((p->size - p->bpos) > bufsize) { \
memcpy(p->buf + p->bpos, (bufptr), bufsize); \
p->bpos += bufsize; \
p->buf[p->bpos]= '\0'; \
} else { printbuf_memappend(p, (bufptr), bufsize); } \
} while (0)
#define printbuf_length(p) ((p)->bpos)
/**
* Set len bytes of the buffer to charvalue, starting at offset offset.
* Similar to calling memset(x, charvalue, len);
*
* The memory allocated for the buffer is extended as necessary.
*
* If offset is -1, this starts at the end of the current data in the buffer.
*/
extern int
printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len);
extern int
sprintbuf(struct printbuf *p, const char *msg, ...);
extern void
printbuf_reset(struct printbuf *p);
extern void
printbuf_free(struct printbuf *p);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,237 +0,0 @@
/*
* random_seed.c
*
* Copyright (c) 2013 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#include <stdio.h>
#include "config.h"
#define DEBUG_SEED(s)
#if defined ENABLE_RDRAND
/* cpuid */
#if defined __GNUC__ && (defined __i386__ || defined __x86_64__)
#define HAS_X86_CPUID 1
static void do_cpuid(int regs[], int h)
{
__asm__ __volatile__(
#if defined __x86_64__
"pushq %%rbx;\n"
#else
"pushl %%ebx;\n"
#endif
"cpuid;\n"
#if defined __x86_64__
"popq %%rbx;\n"
#else
"popl %%ebx;\n"
#endif
: "=a"(regs[0]), [ebx] "=r"(regs[1]), "=c"(regs[2]), "=d"(regs[3])
: "a"(h));
}
#elif defined _MSC_VER
#define HAS_X86_CPUID 1
#define do_cpuid __cpuid
#endif
/* has_rdrand */
#if HAS_X86_CPUID
static int has_rdrand()
{
// CPUID.01H:ECX.RDRAND[bit 30] == 1
int regs[4];
do_cpuid(regs, 1);
return (regs[2] & (1 << 30)) != 0;
}
#endif
/* get_rdrand_seed - GCC x86 and X64 */
#if defined __GNUC__ && (defined __i386__ || defined __x86_64__)
#define HAVE_RDRAND 1
static int get_rdrand_seed()
{
DEBUG_SEED("get_rdrand_seed");
int _eax;
// rdrand eax
__asm__ __volatile__("1: .byte 0x0F\n"
" .byte 0xC7\n"
" .byte 0xF0\n"
" jnc 1b;\n"
: "=a" (_eax));
return _eax;
}
#endif
#if defined _MSC_VER
#if _MSC_VER >= 1700
#define HAVE_RDRAND 1
/* get_rdrand_seed - Visual Studio 2012 and above */
static int get_rdrand_seed()
{
DEBUG_SEED("get_rdrand_seed");
int r;
while (_rdrand32_step(&r) == 0);
return r;
}
#elif defined _M_IX86
#define HAVE_RDRAND 1
/* get_rdrand_seed - Visual Studio 2010 and below - x86 only */
static int get_rdrand_seed()
{
DEBUG_SEED("get_rdrand_seed");
int _eax;
retry:
// rdrand eax
__asm _emit 0x0F __asm _emit 0xC7 __asm _emit 0xF0
__asm jnc retry
__asm mov _eax, eax
return _eax;
}
#endif
#endif
#endif /* defined ENABLE_RDRAND */
/* has_dev_urandom */
#if defined (__APPLE__) || defined(__unix__) || defined(__linux__)
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/stat.h>
#define HAVE_DEV_RANDOM 1
static const char *dev_random_file = "/dev/urandom";
static int has_dev_urandom()
{
struct stat buf;
if (stat(dev_random_file, &buf)) {
return 0;
}
return ((buf.st_mode & S_IFCHR) != 0);
}
/* get_dev_random_seed */
static int get_dev_random_seed()
{
DEBUG_SEED("get_dev_random_seed");
int fd = open(dev_random_file, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "error opening %s: %s", dev_random_file, strerror(errno));
exit(1);
}
int r;
ssize_t nread = read(fd, &r, sizeof(r));
if (nread != sizeof(r)) {
fprintf(stderr, "error short read %s: %s", dev_random_file, strerror(errno));
exit(1);
}
close(fd);
return r;
}
#endif
/* get_cryptgenrandom_seed */
#ifdef WIN32
#define HAVE_CRYPTGENRANDOM 1
#include <windows.h>
#include <wincrypt.h>
#ifndef __GNUC__
#pragma comment(lib, "advapi32.lib")
#endif
static int get_cryptgenrandom_seed()
{
DEBUG_SEED("get_cryptgenrandom_seed");
HCRYPTPROV hProvider = 0;
int r;
if (!CryptAcquireContextW(&hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
fprintf(stderr, "error CryptAcquireContextW");
exit(1);
}
if (!CryptGenRandom(hProvider, sizeof(r), (BYTE*)&r)) {
fprintf(stderr, "error CryptGenRandom");
exit(1);
}
CryptReleaseContext(hProvider, 0);
return r;
}
#endif
/* get_time_seed */
#include <time.h>
static int get_time_seed()
{
DEBUG_SEED("get_time_seed");
return (int)time(NULL) * 433494437;
}
/* json_c_get_random_seed */
int json_c_get_random_seed()
{
#if HAVE_RDRAND
if (has_rdrand()) return get_rdrand_seed();
#endif
#if HAVE_DEV_RANDOM
if (has_dev_urandom()) return get_dev_random_seed();
#endif
#if HAVE_CRYPTGENRANDOM
return get_cryptgenrandom_seed();
#endif
return get_time_seed();
}

View File

@@ -1,25 +0,0 @@
/*
* random_seed.h
*
* Copyright (c) 2013 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/
#ifndef seed_h
#define seed_h
#ifdef __cplusplus
extern "C" {
#endif
extern int json_c_get_random_seed();
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,34 +0,0 @@
ifneq ($(BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE),)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libgnsspps
LOCAL_MODULE_TAGS := optional
LOCAL_SHARED_LIBRARIES := \
libutils \
libcutils \
libgps.utils \
liblog
LOCAL_SRC_FILES += \
gnsspps.c
LOCAL_CFLAGS += \
-fno-short-enums \
-D_ANDROID_
LOCAL_COPY_HEADERS_TO:= libgnsspps/
LOCAL_COPY_HEADERS:= \
gnsspps.h
## Includes
LOCAL_C_INCLUDES := \
$(TARGET_OUT_HEADERS)/gps.utils \
$(TARGET_OUT_HEADERS)/libloc_pla
include $(BUILD_SHARED_LIBRARY)
endif

View File

@@ -1,35 +0,0 @@
AM_CFLAGS = \
$(LOCPLA_CFLAGS) \
-I./
ACLOCAL_AMFLAGS = -I m4
libgnsspps_la_SOURCES = \
gnsspps.c
if USE_GLIB
libgnsspps_la_CFLAGS = -DUSE_GLIB $(AM_CFLAGS) @GLIB_CFLAGS@
libgnsspps_la_LDFLAGS = -lstdc++ -lpthread @GLIB_LIBS@ -shared -version-info 1:0:0
libgnsspps_la_CPPFLAGS = -DUSE_GLIB $(AM_CFLAGS) $(AM_CPPFLAGS) @GLIB_CFLAGS@
else
libgnsspps_la_CFLAGS = $(AM_CFLAGS)
libgnsspps_la_LDFLAGS = -lpthread -shared -version-info 1:0:0
libgnsspps_la_CPPFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS)
endif
libgnsspps_la_LIBADD = -lstdc++
library_include_HEADERS = \
gnsspps.h
#Create and Install libraries
lib_LTLIBRARIES = libgnsspps.la
library_includedir = $(pkgincludedir)
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = gnsspps.pc
EXTRA_DIST = $(pkgconfig_DATA)

View File

@@ -1,60 +0,0 @@
# configure.ac -- Autoconf script for gps lbs-core
#
# Process this file with autoconf to produce a configure script
# Requires autoconf tool later than 2.61
AC_PREREQ(2.61)
# Initialize the gps lbs-core package version 1.0.0
AC_INIT([gnsspps],1.0.0)
# Does not strictly follow GNU Coding standards
AM_INIT_AUTOMAKE([foreign])
# Disables auto rebuilding of configure, Makefile.ins
AM_MAINTAINER_MODE
# Verifies the --srcdir is correct by checking for the path
AC_CONFIG_SRCDIR([Makefile.am])
# defines some macros variable to be included by source
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])
# Checks for programs.
AC_PROG_LIBTOOL
AC_PROG_CXX
AC_PROG_CC
AM_PROG_CC_C_O
AC_PROG_AWK
AC_PROG_CPP
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_MAKE_SET
PKG_PROG_PKG_CONFIG
# Checks for libraries.
PKG_CHECK_MODULES([LOCPLA], [loc-pla])
AC_SUBST([LOCPLA_CFLAGS])
AC_SUBST([LOCPLA_LIBS])
AC_ARG_WITH([glib],
AC_HELP_STRING([--with-glib],
[enable glib, building HLOS systems which use glib]))
if (test "x${with_glib}" = "xyes"); then
AC_DEFINE(ENABLE_USEGLIB, 1, [Define if HLOS systems uses glib])
PKG_CHECK_MODULES(GTHREAD, gthread-2.0 >= 2.16, dummy=yes,
AC_MSG_ERROR(GThread >= 2.16 is required))
PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.16, dummy=yes,
AC_MSG_ERROR(GLib >= 2.16 is required))
GLIB_CFLAGS="$GLIB_CFLAGS $GTHREAD_CFLAGS"
GLIB_LIBS="$GLIB_LIBS $GTHREAD_LIBS"
AC_SUBST(GLIB_CFLAGS)
AC_SUBST(GLIB_LIBS)
fi
AM_CONDITIONAL(USE_GLIB, test "x${with_glib}" = "xyes")
AC_CONFIG_FILES([ \
Makefile \
gnsspps.pc
])
AC_OUTPUT

View File

@@ -1,194 +0,0 @@
/* Copyright (c) 2011-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 Foundatoin, 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 <platform_lib_log_util.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pthread.h>
#include <timepps.h>
#include <linux/types.h>
//DRsync kernel timestamp
static struct timespec drsyncKernelTs = {0,0};
//DRsync userspace timestamp
static struct timespec drsyncUserTs = {0,0};
//flag to stop fetching timestamp
static int isActive = 0;
static pps_handle handle;
static pthread_mutex_t ts_lock;
/* checks the PPS source and opens it */
int check_device(char *path, pps_handle *handle)
{
int ret;
/* Try to find the source by using the supplied "path" name */
ret = open(path, O_RDWR);
if (ret < 0)
{
LOC_LOGV("%s:%d unable to open device %s", __func__, __LINE__, path);
return ret;
}
/* Open the PPS source */
ret = pps_create(ret, handle);
if (ret < 0)
{
LOC_LOGV( "%s:%d cannot create a PPS source from device %s", __func__, __LINE__, path);
return -1;
}
return 0;
}
/* fetches the timestamp from the PPS source */
int read_pps(pps_handle *handle)
{
struct timespec timeout;
pps_info infobuf;
int ret;
// 3sec timeout
timeout.tv_sec = 3;
timeout.tv_nsec = 0;
ret = pps_fetch(*handle, PPS_TSFMT_TSPEC, &infobuf,&timeout);
if (ret < 0 && ret !=-EINTR)
{
LOC_LOGV("%s:%d pps_fetch() error %d", __func__, __LINE__, ret);
return -1;
}
pthread_mutex_lock(&ts_lock);
drsyncKernelTs.tv_sec = infobuf.tv_sec;
drsyncKernelTs.tv_nsec = infobuf.tv_nsec;
ret = clock_gettime(CLOCK_BOOTTIME,&drsyncUserTs);
pthread_mutex_unlock(&ts_lock);
if(ret != 0)
{
LOC_LOGV("%s:%d clock_gettime() error",__func__,__LINE__);
}
return 0;
}
#ifdef __cplusplus
extern "C" {
#endif
/* infinitely calls read_pps() */
void *thread_handle(void *input)
{
int ret;
if(input != NULL)
{
LOC_LOGV("%s:%d Thread Input is present", __func__, __LINE__);
}
while(isActive)
{
ret = read_pps(&handle);
if (ret == -1 && errno != ETIMEDOUT )
{
LOC_LOGV("%s:%d Could not fetch PPS source", __func__, __LINE__);
}
}
return NULL;
}
/* opens the device and fetches from PPS source */
int initPPS(char *devname)
{
int ret,pid;
pthread_t thread;
isActive = 1;
ret = check_device(devname, &handle);
if (ret < 0)
{
LOC_LOGV("%s:%d Could not find PPS source", __func__, __LINE__);
return 0;
}
pthread_mutex_init(&ts_lock,NULL);
pid = pthread_create(&thread,NULL,&thread_handle,NULL);
if(pid != 0)
{
LOC_LOGV("%s:%d Could not create thread in InitPPS", __func__, __LINE__);
return 0;
}
return 1;
}
/* stops fetching and closes the device */
void deInitPPS()
{
pthread_mutex_lock(&ts_lock);
isActive = 0;
pthread_mutex_unlock(&ts_lock);
pthread_mutex_destroy(&ts_lock);
pps_destroy(handle);
}
/* retrieves DRsync kernel timestamp,DRsync userspace timestamp
and updates current timestamp */
/* Returns:
* 1. @Param out DRsync kernel timestamp
* 2. @Param out DRsync userspace timestamp
* 3. @Param out current timestamp
*/
int getPPS(struct timespec *fineKernelTs ,struct timespec *currentTs,
struct timespec *fineUserTs)
{
int ret;
pthread_mutex_lock(&ts_lock);
fineKernelTs->tv_sec = drsyncKernelTs.tv_sec;
fineKernelTs->tv_nsec = drsyncKernelTs.tv_nsec;
fineUserTs->tv_sec = drsyncUserTs.tv_sec;
fineUserTs->tv_nsec = drsyncUserTs.tv_nsec;
ret = clock_gettime(CLOCK_BOOTTIME,currentTs);
pthread_mutex_unlock(&ts_lock);
if(ret != 0)
{
LOC_LOGV("%s:%d clock_gettime() error",__func__,__LINE__);
return 0;
}
return 1;
}
#ifdef __cplusplus
}
#endif

Some files were not shown because too many files have changed in this diff Show More