<commit_before>#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

#include "opts.h"
#include "stats.h"
#include "version.h"


uopt_t uopt;


void uopt_init() {
	uopt.doexit = 0;
	uopt.retval = 0;
	uopt.nroots = 0;
	uopt.stats_enabled = false;
	uopt.cow_enabled = false; // copy-on-write
	uopt.initgroups = true;
}

/**
 * Take a relative path as argument and return the absolute path by using the 
 * current working directory. The return string is malloc'ed with this function.
 */
static char *make_absolute(char *relpath) {
	// Already an absolute path
	if (*relpath == '/') return relpath;

	char cwd[PATHLEN_MAX];
	if (!getcwd(cwd, PATHLEN_MAX)) {
		perror("Unable to get current working directory");
		return NULL;
	}

	size_t cwdlen = strlen(cwd);
	if (!cwdlen) {
		fprintf(stderr, "Zero-sized length of CWD!\n");
		return NULL;
	}

	// 2 due to: +1 for '/' between cwd and relpath
	//           +1 for terminating '\0'
	int abslen = cwdlen + strlen(relpath) + 2;
	if (abslen > PATHLEN_MAX) {
		fprintf(stderr, "Absolute path too long!\n");
		return NULL;
	}

	char *abspath = malloc(abslen);
	// the terminating '/' is important so that we are sure later on the
	// diroctory components are properly seperated
	sprintf(abspath, "%s/%s/", cwd, relpath);

	return abspath;
}

/**
 * Add a trailing slash at the end of a branch (root). So functions using this
 * path don't have to care about this slash themselves.
 **/
static char *add_trailing_slash(char *path)
{
	int len = strlen(path);
	if (path[len - 1] == '/')
		return path; // no need to add a slash, already there
	
	path = realloc(path, len + 2); // +1 for '/' and +1 for '\0'
	if (!path) // still very early stage, we can abort here
		fprintf(stderr, "%s: realloc() failed, aborting\n", __func__);
	
	strcat (path, "/");
	return (path);
}

/**
 * Add a given root and its options to the array of available roots.
 * example root string "root1=RO" or "/path/path2=RW"
 */
static void add_root(char *root) {
	uopt.roots = realloc(uopt.roots, (uopt.nroots+1) * sizeof(root_entry_t));

	char *res;
	char **ptr = (char **)&root;

	res = strsep(ptr, "=");
	if (!res) return;

	// for string manipulations it is important to copy the string, otherwise
	// make_absolute() and add_trailing_slash() will corrupt our input (parse string)
	uopt.roots[uopt.nroots].path = strdup(res);
	uopt.roots[uopt.nroots].path = make_absolute(uopt.roots[uopt.nroots].path);
	uopt.roots[uopt.nroots].path = add_trailing_slash(uopt.roots[uopt.nroots].path);
	uopt.roots[uopt.nroots].rw = 0;<commit_msg>Check malloc and realloc calls in opts.c and abort if it fails.<commit_after>#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

#include "opts.h"
#include "stats.h"
#include "version.h"


uopt_t uopt;


void uopt_init() {
	uopt.doexit = 0;
	uopt.retval = 0;
	uopt.nroots = 0;
	uopt.stats_enabled = false;
	uopt.cow_enabled = false; // copy-on-write
	uopt.initgroups = true;
}

/**
 * Take a relative path as argument and return the absolute path by using the 
 * current working directory. The return string is malloc'ed with this function.
 */
static char *make_absolute(char *relpath) {
	// Already an absolute path
	if (*relpath == '/') return relpath;

	char cwd[PATHLEN_MAX];
	if (!getcwd(cwd, PATHLEN_MAX)) {
		perror("Unable to get current working directory");
		return NULL;
	}

	size_t cwdlen = strlen(cwd);
	if (!cwdlen) {
		fprintf(stderr, "Zero-sized length of CWD!\n");
		return NULL;
	}

	// 2 due to: +1 for '/' between cwd and relpath
	//           +1 for terminating '\0'
	int abslen = cwdlen + strlen(relpath) + 2;
	if (abslen > PATHLEN_MAX) {
		fprintf(stderr, "Absolute path too long!\n");
		return NULL;
	}

	char *abspath = malloc(abslen);
	if (abspath == NULL) {
		fprintf(stderr, "%s: malloc failed\n", __func__);
		exit (1); // still at early stage, we can't abort
	}
	// the terminating '/' is important so that we are sure later on the
	// diroctory components are properly seperated
	sprintf(abspath, "%s/%s/", cwd, relpath);

	return abspath;
}

/**
 * Add a trailing slash at the end of a branch (root). So functions using this
 * path don't have to care about this slash themselves.
 **/
static char *add_trailing_slash(char *path)
{
	int len = strlen(path);
	if (path[len - 1] == '/')
		return path; // no need to add a slash, already there
	
	path = realloc(path, len + 2); // +1 for '/' and +1 for '\0'
	if (!path) {
		fprintf(stderr, "%s: realloc() failed, aborting\n", __func__);
		exit (1); // still very early stage, we can abort here
	}
	
	strcat (path, "/");
	return (path);
}

/**
 * Add a given root and its options to the array of available roots.
 * example root string "root1=RO" or "/path/path2=RW"
 */
static void add_root(char *root) {
	uopt.roots = realloc(uopt.roots, (uopt.nroots+1) * sizeof(root_entry_t));
	if (uopt.roots == NULL) {
		fprintf(stderr, "%s: realloc failed\n", __func__);
		exit (1); // still at early stage, we can't abort
	}


	char *res;
	char **ptr = (char **)&root;

	res = strsep(ptr, "=");
	if (!res) return;

	// for string manipulations it is important to copy the string, otherwise
	// make_absolute() and add_trailing_slash() will corrupt our input (parse string)
	uopt.roots[uopt.nroots].path = strdup(res);
	uopt.roots[uopt.nroots].path = make_absolute(uopt.roots[uopt.nroots].path);
	uopt.roots[uopt.nroots].path = add_trailing_slash(uopt.roots[uopt.nroots].path);
	uopt.roots[uopt.nroots].rw = 0;
{'fraction_non_alphanumeric': 0.145985401459854, 'fraction_numerical': 0.006751824817518248, 'mean_word_length': 3.729076790336497, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 13, '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': '3410153', 'n_tokens_mistral': 2082, 'n_tokens_neox': 1967, 'n_words': 620}