<commit_before>#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/mount.h>
#include <regex.h>
#include <limits.h>
#include <libgen.h>

#include "mosaic.h"
#include "volume.h"
#include "log.h"
#include "util.h"
#include "uapi/mosaic.h"

#ifndef MOSAIC_CONFIG_DIR
#define MOSAIC_CONFIG_DIR	"/etc/mosaic.d"
#endif

const struct mosaic_ops *mosaic_find_ops(char *type)
{
	if (!strcmp(type, "fsimg"))
		return &mosaic_fsimg;
	if (!strcmp(type, "btrfs"))
		return &mosaic_btrfs;
	if (!strcmp(type, "plain"))
		return &mosaic_plain;
	if (!strcmp(type, "ploop"))
		return &mosaic_ploop;
	if (!strcmp(type, "thin"))
		return &mosaic_thin;

	return NULL;
}

static const char *name_to_config(const char *name, char *buf, int blen)
{
	if (name[0] == '.' || name[0] == '/')
		return name;

	snprintf(buf, blen, MOSAIC_CONFIG_DIR "/%s.mos", name);
	return buf;
}

static char *name_to_name(const char *name, char *buf, int blen)
{
	int len;
	char *tail;

	/*
	 * We will have so called compound mosaics -- the ones that
	 * chose some other one upon opening. So to keep the constant
	 * reference on it we need to provide some fixed name for
	 * exact handler.
	 */
	if (name[0] != '.' && name[0] != '/')
		return xstrdup(name);

	len = readlink(name, buf, blen);
	if (len < sizeof("/x.mos")) { /* Minimal config name */
		loge("Path %s doesn't look like mosaic config\n", buf);
		return NULL;
	}

	if (strcmp(buf + len - 4, ".mos")) {
		loge("Path %s doesn't look like mosaic config\n", buf);
		return NULL;
	}

	/* Trim the path: /foo/bar/some_name.mos -> some_name */
	buf[len - 4] = '\0';
	tail = basename(buf);
	return xstrdup(tail);
}

mosaic_t mosaic_open(const char *name, int open_flags)
{
	const char *cfg;
	char aux[PATH_MAX];<commit_msg>mosaic_open(): fix<commit_after>#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/mount.h>
#include <regex.h>
#include <limits.h>
#include <libgen.h>

#include "mosaic.h"
#include "volume.h"
#include "log.h"
#include "util.h"
#include "uapi/mosaic.h"

#ifndef MOSAIC_CONFIG_DIR
#define MOSAIC_CONFIG_DIR	"/etc/mosaic.d"
#endif

const struct mosaic_ops *mosaic_find_ops(char *type)
{
	if (!strcmp(type, "fsimg"))
		return &mosaic_fsimg;
	if (!strcmp(type, "btrfs"))
		return &mosaic_btrfs;
	if (!strcmp(type, "plain"))
		return &mosaic_plain;
	if (!strcmp(type, "ploop"))
		return &mosaic_ploop;
	if (!strcmp(type, "thin"))
		return &mosaic_thin;

	return NULL;
}

static const char *name_to_config(const char *name, char *buf, int blen)
{
	if (name[0] == '.' || name[0] == '/')
		return name;

	snprintf(buf, blen, MOSAIC_CONFIG_DIR "/%s.mos", name);
	return buf;
}

static char *name_to_name(const char *name, char *buf, int blen)
{
	int len;
	char *tail;

	/*
	 * We will have so called compound mosaics -- the ones that
	 * chose some other one upon opening. So to keep the constant
	 * reference on it we need to provide some fixed name for
	 * exact handler.
	 */
	if (name[0] != '.' && name[0] != '/')
		return xstrdup(name);

	// assuming blen >= PATH_MAX
	if (realpath(name, buf) == NULL) {
		loge("Error in realpath(%s): %m\n", name);
		return NULL;
	}
	len = strlen(buf);

	if (len < sizeof("/x.mos")) { /* Minimal config name */
		loge("Path %s doesn't look like mosaic config\n", buf);
		return NULL;
	}

	if (strcmp(buf + len - 4, ".mos")) {
		loge("Path %s doesn't look like mosaic config\n", buf);
		return NULL;
	}

	/* Trim the path: /foo/bar/some_name.mos -> some_name */
	buf[len - 4] = '\0';
	tail = basename(buf);
	return xstrdup(tail);
}

mosaic_t mosaic_open(const char *name, int open_flags)
{
	const char *cfg;
	char aux[PATH_MAX];
{'fraction_non_alphanumeric': 0.16936984844456263, 'fraction_numerical': 0.003722414251528849, 'mean_word_length': 4.056451612903226, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 26, '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': '5847422', 'n_tokens_mistral': 1571, 'n_tokens_neox': 1481, 'n_words': 412}