<commit_before>/* Copyright (c) 2010 Dovecot authors, see the included COPYING file */

#include "lib.h"
#include "str.h"
#include "istream.h"
#include "ostream-cmp.h"
#include "fs-sis-common.h"

struct sis_fs {
	struct fs fs;
	struct fs *super;
};

struct sis_fs_file {
	struct fs_file file;
	struct fs_file *super;
	enum fs_open_mode open_mode;

	struct fs_file *hash_file;
	struct istream *hash_input;
	struct ostream *fs_output;

	char *hash, *hash_path;
};

static void fs_sis_copy_error(struct sis_fs *fs)
{
	fs_set_error(&fs->fs, "%s", fs_last_error(fs->super));
}

static void fs_sis_file_copy_error(struct sis_fs_file *file)
{
	struct sis_fs *fs = (struct sis_fs *)file->file.fs;

	fs_sis_copy_error(fs);
}

static struct fs *
fs_sis_init(const char *args, const struct fs_settings *set)
{
	struct sis_fs *fs;
	const char *p;

	fs = i_new(struct sis_fs, 1);
	fs->fs = fs_class_sis;

	if (*args == '\0')
		i_fatal("fs-sis: Parent filesystem not given as parameter");

	p = strchr(args, ':');
	if (p == NULL)
		fs->super = fs_init(args, "", set);
	else
		fs->super = fs_init(t_strdup_until(args, p), p+1, set);
	return &fs->fs;
}

static void fs_sis_deinit(struct fs *_fs)
{
	struct sis_fs *fs = (struct sis_fs *)_fs;

	fs_deinit(&fs->super);
	i_free(fs);
}

static int
fs_sis_open(struct fs *_fs, const char *path, enum fs_open_mode mode,
	    enum fs_open_flags flags, struct fs_file **file_r)
{
	struct sis_fs *fs = (struct sis_fs *)_fs;
	struct sis_fs_file *file;
	struct fs_file *super;
	const char *dir, *hash;

	if (mode == FS_OPEN_MODE_APPEND) {
		fs_set_error(_fs, "APPEND mode not supported");
		return -1;
	}

	if (fs_open(fs->super, path, mode | flags, &super) < 0) {
		fs_sis_copy_error(fs);
		return -1;
	}

	switch (mode) {
	case FS_OPEN_MODE_RDONLY:
		*file_r = super;
		return 0;
	case FS_OPEN_MODE_CREATE:
	case FS_OPEN_MODE_REPLACE:
		break;
	case FS_OPEN_MODE_APPEND:
		i_unreached();
	}

	if (fs_sis_path_parse(_fs, path, &dir, &hash) < 0)
		return -1;

	file = i_new(struct sis_fs_file, 1);
	file->file.fs = _fs;
	file->file.path = i_strdup(fs_file_path(super));
	file->super = super;
	file->open_mode = mode;
	file->hash = i_strdup(hash);

	/* if hashes/<hash> already exists, open it */
	file->hash_path = i_strdup_printf("%s/"HASH_DIR_NAME"/%s", dir, hash);
	if (fs_open(fs->super, file->hash_path, FS_OPEN_MODE_RDONLY,
		    &file->hash_file) < 0 && errno != ENOENT) {
		i_error("fs-sis: Couldn't open hash file: %s",
			fs_last_error(fs->super));
	}
	if (file->hash_file != NULL) {
		file->hash_input =
			fs_read_stream(file->hash_file, IO_BLOCK_SIZE);
	}

	*file_r = &file->file;
	return 0;
}

static void fs_sis_close(struct fs_file *_file)
{
	struct sis_fs_file *file = (struct sis_fs_file *)_file;

	if (file->hash_file != NULL) {
		i_stream_unref(&file->hash_input);
		fs_close(&file->hash_file);
	}
	fs_close(&file->super);
	i_free(file->hash);
	i_free(file->file.path);
	i_free(file);
}

static ssize_t fs_sis_read(struct fs_file *_file, void *buf, size_t size)
{
	struct sis_fs_file *file = (struct sis_fs_file *)_file;
	ssize_t ret;

	if ((ret = fs_read(file->super, buf, size)) < 0)
		fs_sis_file_copy_error(file);
	return ret;
}

static struct istream *
fs_sis_read_stream(struct fs_file *_file, size_t max_buffer_size)
{
	struct sis_fs_file *file = (struct sis_fs_file *)_file;

	return fs_read_stream(file->super, max_buffer_size);
}
<commit_msg>fs-sis: Memory leak fix.<commit_after>/* Copyright (c) 2010 Dovecot authors, see the included COPYING file */

#include "lib.h"
#include "str.h"
#include "istream.h"
#include "ostream-cmp.h"
#include "fs-sis-common.h"

struct sis_fs {
	struct fs fs;
	struct fs *super;
};

struct sis_fs_file {
	struct fs_file file;
	struct fs_file *super;
	enum fs_open_mode open_mode;

	struct fs_file *hash_file;
	struct istream *hash_input;
	struct ostream *fs_output;

	char *hash, *hash_path;
};

static void fs_sis_copy_error(struct sis_fs *fs)
{
	fs_set_error(&fs->fs, "%s", fs_last_error(fs->super));
}

static void fs_sis_file_copy_error(struct sis_fs_file *file)
{
	struct sis_fs *fs = (struct sis_fs *)file->file.fs;

	fs_sis_copy_error(fs);
}

static struct fs *
fs_sis_init(const char *args, const struct fs_settings *set)
{
	struct sis_fs *fs;
	const char *p;

	fs = i_new(struct sis_fs, 1);
	fs->fs = fs_class_sis;

	if (*args == '\0')
		i_fatal("fs-sis: Parent filesystem not given as parameter");

	p = strchr(args, ':');
	if (p == NULL)
		fs->super = fs_init(args, "", set);
	else
		fs->super = fs_init(t_strdup_until(args, p), p+1, set);
	return &fs->fs;
}

static void fs_sis_deinit(struct fs *_fs)
{
	struct sis_fs *fs = (struct sis_fs *)_fs;

	fs_deinit(&fs->super);
	i_free(fs);
}

static int
fs_sis_open(struct fs *_fs, const char *path, enum fs_open_mode mode,
	    enum fs_open_flags flags, struct fs_file **file_r)
{
	struct sis_fs *fs = (struct sis_fs *)_fs;
	struct sis_fs_file *file;
	struct fs_file *super;
	const char *dir, *hash;

	if (mode == FS_OPEN_MODE_APPEND) {
		fs_set_error(_fs, "APPEND mode not supported");
		return -1;
	}

	if (fs_open(fs->super, path, mode | flags, &super) < 0) {
		fs_sis_copy_error(fs);
		return -1;
	}

	switch (mode) {
	case FS_OPEN_MODE_RDONLY:
		*file_r = super;
		return 0;
	case FS_OPEN_MODE_CREATE:
	case FS_OPEN_MODE_REPLACE:
		break;
	case FS_OPEN_MODE_APPEND:
		i_unreached();
	}

	if (fs_sis_path_parse(_fs, path, &dir, &hash) < 0)
		return -1;

	file = i_new(struct sis_fs_file, 1);
	file->file.fs = _fs;
	file->file.path = i_strdup(fs_file_path(super));
	file->super = super;
	file->open_mode = mode;
	file->hash = i_strdup(hash);

	/* if hashes/<hash> already exists, open it */
	file->hash_path = i_strdup_printf("%s/"HASH_DIR_NAME"/%s", dir, hash);
	if (fs_open(fs->super, file->hash_path, FS_OPEN_MODE_RDONLY,
		    &file->hash_file) < 0 && errno != ENOENT) {
		i_error("fs-sis: Couldn't open hash file: %s",
			fs_last_error(fs->super));
	}
	if (file->hash_file != NULL) {
		file->hash_input =
			fs_read_stream(file->hash_file, IO_BLOCK_SIZE);
	}

	*file_r = &file->file;
	return 0;
}

static void fs_sis_close(struct fs_file *_file)
{
	struct sis_fs_file *file = (struct sis_fs_file *)_file;

	if (file->hash_file != NULL) {
		i_stream_unref(&file->hash_input);
		fs_close(&file->hash_file);
	}
	fs_close(&file->super);
	i_free(file->hash);
	i_free(file->hash_path);
	i_free(file->file.path);
	i_free(file);
}

static ssize_t fs_sis_read(struct fs_file *_file, void *buf, size_t size)
{
	struct sis_fs_file *file = (struct sis_fs_file *)_file;
	ssize_t ret;

	if ((ret = fs_read(file->super, buf, size)) < 0)
		fs_sis_file_copy_error(file);
	return ret;
}

static struct istream *
fs_sis_read_stream(struct fs_file *_file, size_t max_buffer_size)
{
	struct sis_fs_file *file = (struct sis_fs_file *)_file;

	return fs_read_stream(file->super, max_buffer_size);
}

{'fraction_non_alphanumeric': 0.14534798534798535, 'fraction_numerical': 0.004981684981684982, 'mean_word_length': 4.683597002497918, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 68, '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': '1636238', 'n_tokens_mistral': 2985, 'n_tokens_neox': 2804, 'n_words': 648}