<commit_before>/*
 * lxc: linux Container library
 *
 * (C) Copyright IBM Corp. 2007, 2008
 *
 * Authors:
 * <NAME> <daniel.lezcano at free.fr>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#define _GNU_SOURCE
#include <libgen.h>
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>

#include <lxc/lxccontainer.h>

#include "arguments.h"
#include "tool_utils.h"

static bool ips;
static bool state;
static bool pid;
static bool stats;
static bool humanize = true;
static char **key = NULL;
static int keys = 0;
static int filter_count = 0;

static int my_parser(struct lxc_arguments* args, int c, char* arg)
{
	char **newk;
	switch (c) {
	case 'c':
		newk = realloc(key, (keys + 1) * sizeof(key[0]));
		if (!newk)
			return -1;
		key = newk;
		key[keys] = arg;
		keys++;
		break;
	case 'i': ips = true; filter_count += 1; break;
	case 's': state = true; filter_count += 1; break;
	case 'p': pid = true; filter_count += 1; break;
	case 'S': stats = true; filter_count += 5; break;
	case 'H': humanize = false; break;
	}
	return 0;
}

static const struct option my_longopts[] = {
	{"config", required_argument, 0, 'c'},
	{"ips", no_argument, 0, 'i'},
	{"state", no_argument, 0, 's'},
	{"pid", no_argument, 0, 'p'},
	{"stats", no_argument, 0, 'S'},
	{"no-humanize", no_argument, 0, 'H'},
	LXC_COMMON_OPTIONS,
};

static struct lxc_arguments my_args = {
	.progname = "lxc-info",
	.help     = "\
--name=NAME\n\
\n\
lxc-info display some information about a container with the identifier NAME\n\
\n\
Options :\n\
  -n, --name=NAME       NAME of the container\n\
  -c, --config=KEY      show configuration variable KEY from running container\n\
  -i, --ips             shows the IP addresses\n\
  -p, --pid             shows the process id of the init container\n\
  -S, --stats           shows usage stats\n\
  -H, --no-humanize     shows stats as raw numbers, not humanized\n\
  -s, --state           shows the state of the container\n\
  --rcfile=FILE         Load configuration file FILE\n",
	.name     = NULL,
	.options  = my_longopts,
	.parser   = my_parser,
	.checker  = NULL,
};

static void str_chomp(char *buf)
{
	char *ch;

	/* remove trailing whitespace from buf */
	for(ch = &buf[strlen(buf)-1];
	    ch >= buf && (*ch == '\t' || *ch == '\n' || *ch == ' ');
	    ch--)
		*ch = '\0';
}

static void size_humanize(unsigned long long val, char *buf, size_t bufsz)
{
	if (val > 1 << 30) {
		(void)snprintf(buf, bufsz, "%u.%2.2u GiB",
			       (unsigned int)(val >> 30),
			       (unsigned int)(val & ((1 << 30) - 1)) / 10737419);
	} else if (val > 1 << 20) {
		unsigned int x = val + 5243;  /* for rounding */
		(void)snprintf(buf, bufsz, "%u.%2.2u MiB", x >> 20,
			       ((x & ((1 << 20) - 1)) * 100) >> 20);
	} else if (val > 1 << 10) {
		unsigned int x = val + 5;  /* for rounding */
		(void)snprintf(buf, bufsz, "%u.%2.2u KiB", x >> 10,
			       ((x & ((1 << 10) - 1)) * 100) >> 10);
	} else {
		(void)snprintf(buf, bufsz, "%u bytes", (unsigned int)val);
	}
}

static unsigned long long str_size_humanize(char *iobuf, size_t iobufsz)
{
	unsigned long long val;
	char *end = NULL;

	val = strtoull(iobuf, &end, 0);
	if (humanize) {
		if (*end == '\0' || *end == '\n')
			size_humanize(val, iobuf, iobufsz);
		else
			*iobuf = '\0';
	}
	return val;
}

static void print_net_stats(struct lxc_container *c)
{
	int rc,netnr;
	unsigned long long rx_bytes = 0, tx_bytes = 0;
	char *ifname, *type;
	char path[PATH_MAX];
	char buf[256];

	for(netnr = 0; ;netnr++) {
		sprintf(buf, "lxc.net.%d.type", netnr);
		type = c->get_running_config_item(c, buf);
		if (!type)
			break;

		if (!strcmp(type, "veth")) {
			sprintf(buf, "lxc.net.%d.veth.pair", netnr);
		} else {
			sprintf(buf, "lxc.net.%d.link", netnr);
		}
		free(type);
		ifname = c->get_running_config_item(c, buf);
		if (!ifname)
			return;
		printf("%-15s %s\n", "Link:", ifname);
		fflush(stdout);

		/* XXX: tx and rx are reversed from the host vs container
		 * perspective, print them from the container perspective
		 */
		rc = snprintf(path, sizeof(path), "/sys/class/net/%s/statistics/rx_bytes", ifname);
		if (rc < 0 || (size_t)rc >= sizeof(path))
			return;

		rc = lxc_read_from_file(path, buf, sizeof(buf));
		if (rc > 0) {
			str_chomp(buf);
			rx_bytes = str_size_humanize(buf, sizeof(buf));
			printf("%-15s %s\n", " TX bytes:", buf);
			fflush(stdout);
		}

		rc = snprintf(path, sizeof(path), "/sys/class/net/%s/statistics/tx_bytes", ifname);
		if (rc < 0 || (size_t)rc >= sizeof(path))
			return;

		rc = lxc_read_from_file(path, buf, sizeof(buf));
		if (rc > 0) {
			str_chomp(buf);<commit_msg>coverity: #1425855<commit_after>/*
 * lxc: linux Container library
 *
 * (C) Copyright IBM Corp. 2007, 2008
 *
 * Authors:
 * <NAME> <daniel.lezcano at free.fr>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#define _GNU_SOURCE
#include <libgen.h>
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>

#include <lxc/lxccontainer.h>

#include "arguments.h"
#include "tool_utils.h"

static bool ips;
static bool state;
static bool pid;
static bool stats;
static bool humanize = true;
static char **key = NULL;
static int keys = 0;
static int filter_count = 0;

static int my_parser(struct lxc_arguments* args, int c, char* arg)
{
	char **newk;
	switch (c) {
	case 'c':
		newk = realloc(key, (keys + 1) * sizeof(key[0]));
		if (!newk)
			return -1;
		key = newk;
		key[keys] = arg;
		keys++;
		break;
	case 'i': ips = true; filter_count += 1; break;
	case 's': state = true; filter_count += 1; break;
	case 'p': pid = true; filter_count += 1; break;
	case 'S': stats = true; filter_count += 5; break;
	case 'H': humanize = false; break;
	}
	return 0;
}

static const struct option my_longopts[] = {
	{"config", required_argument, 0, 'c'},
	{"ips", no_argument, 0, 'i'},
	{"state", no_argument, 0, 's'},
	{"pid", no_argument, 0, 'p'},
	{"stats", no_argument, 0, 'S'},
	{"no-humanize", no_argument, 0, 'H'},
	LXC_COMMON_OPTIONS,
};

static struct lxc_arguments my_args = {
	.progname = "lxc-info",
	.help     = "\
--name=NAME\n\
\n\
lxc-info display some information about a container with the identifier NAME\n\
\n\
Options :\n\
  -n, --name=NAME       NAME of the container\n\
  -c, --config=KEY      show configuration variable KEY from running container\n\
  -i, --ips             shows the IP addresses\n\
  -p, --pid             shows the process id of the init container\n\
  -S, --stats           shows usage stats\n\
  -H, --no-humanize     shows stats as raw numbers, not humanized\n\
  -s, --state           shows the state of the container\n\
  --rcfile=FILE         Load configuration file FILE\n",
	.name     = NULL,
	.options  = my_longopts,
	.parser   = my_parser,
	.checker  = NULL,
};

static void str_chomp(char *buf)
{
	char *ch;

	/* remove trailing whitespace from buf */
	for(ch = &buf[strlen(buf)-1];
	    ch >= buf && (*ch == '\t' || *ch == '\n' || *ch == ' ');
	    ch--)
		*ch = '\0';
}

static void size_humanize(unsigned long long val, char *buf, size_t bufsz)
{
	if (val > 1 << 30) {
		(void)snprintf(buf, bufsz, "%u.%2.2u GiB",
			       (unsigned int)(val >> 30),
			       (unsigned int)(val & ((1 << 30) - 1)) / 10737419);
	} else if (val > 1 << 20) {
		unsigned int x = val + 5243;  /* for rounding */
		(void)snprintf(buf, bufsz, "%u.%2.2u MiB", x >> 20,
			       ((x & ((1 << 20) - 1)) * 100) >> 20);
	} else if (val > 1 << 10) {
		unsigned int x = val + 5;  /* for rounding */
		(void)snprintf(buf, bufsz, "%u.%2.2u KiB", x >> 10,
			       ((x & ((1 << 10) - 1)) * 100) >> 10);
	} else {
		(void)snprintf(buf, bufsz, "%u bytes", (unsigned int)val);
	}
}

static unsigned long long str_size_humanize(char *iobuf, size_t iobufsz)
{
	unsigned long long val;
	char *end = NULL;

	val = strtoull(iobuf, &end, 0);
	if (humanize) {
		if (*end == '\0' || *end == '\n')
			size_humanize(val, iobuf, iobufsz);
		else
			*iobuf = '\0';
	}
	return val;
}

static void print_net_stats(struct lxc_container *c)
{
	int rc,netnr;
	unsigned long long rx_bytes = 0, tx_bytes = 0;
	char *ifname, *type;
	char path[PATH_MAX];
	char buf[256];

	for(netnr = 0; ;netnr++) {
		sprintf(buf, "lxc.net.%d.type", netnr);
		type = c->get_running_config_item(c, buf);
		if (!type)
			break;

		if (!strcmp(type, "veth")) {
			sprintf(buf, "lxc.net.%d.veth.pair", netnr);
		} else {
			sprintf(buf, "lxc.net.%d.link", netnr);
		}
		free(type);
		ifname = c->get_running_config_item(c, buf);
		if (!ifname)
			return;
		printf("%-15s %s\n", "Link:", ifname);
		fflush(stdout);

		/* XXX: tx and rx are reversed from the host vs container
		 * perspective, print them from the container perspective
		 */
		rc = snprintf(path, sizeof(path), "/sys/class/net/%s/statistics/rx_bytes", ifname);
		if (rc < 0 || (size_t)rc >= sizeof(path))
			return;

		rc = lxc_read_from_file(path, buf, sizeof(buf));
		if (rc > 0) {
			buf[rc - 1] = '\0';
			str_chomp(buf);
			rx_bytes = str_size_humanize(buf, sizeof(buf));
			printf("%-15s %s\n", " TX bytes:", buf);
			fflush(stdout);
		}

		rc = snprintf(path, sizeof(path), "/sys/class/net/%s/statistics/tx_bytes", ifname);
		if (rc < 0 || (size_t)rc >= sizeof(path))
			return;

		rc = lxc_read_from_file(path, buf, sizeof(buf));
		if (rc > 0) {
			buf[rc - 1] = '\0';
			str_chomp(buf);
{'fraction_non_alphanumeric': 0.16303440600945934, 'fraction_numerical': 0.021793563943243995, 'mean_word_length': 3.202650038971161, 'pattern_counts': {'":': 0, '<': 53, '<?xml version=': 0, '>': 65, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4520070', 'n_tokens_mistral': 4365, 'n_tokens_neox': 3970, 'n_words': 1260}