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

#include "lib.h"
#include "buffer.h"
#include "hex-binary.h"
#include "randgen.h"
#include "write-full.h"
#include "istream-internal.h"
#include "istream-concat.h"
#include "istream-seekable.h"

#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>

#define BUF_INITIAL_SIZE (1024*32)

struct seekable_istream {
	struct istream_private istream;

	char *temp_prefix;
	uoff_t write_peak;

	buffer_t *buffer;
	struct istream **input, *cur_input;
	struct istream *fd_input;
	unsigned int cur_idx;
	int fd;
};

static void i_stream_seekable_close(struct iostream_private *stream)
{
	struct seekable_istream *sstream = (struct seekable_istream *)stream;
	unsigned int i;

	sstream->fd = -1;
	if (sstream->fd_input != NULL)
		i_stream_close(sstream->fd_input);
	for (i = 0; sstream->input[i] != NULL; i++)
		i_stream_close(sstream->input[i]);
}

static void i_stream_seekable_destroy(struct iostream_private *stream)
{
	struct seekable_istream *sstream = (struct seekable_istream *)stream;
	unsigned int i;

	if (sstream->buffer != NULL)
		buffer_free(&sstream->buffer);
	if (sstream->fd_input != NULL)
		i_stream_unref(&sstream->fd_input);
	for (i = 0; sstream->input[i] != NULL; i++)
		i_stream_unref(&sstream->input[i]);

	i_free(sstream->temp_prefix);
}

static void
i_stream_seekable_set_max_buffer_size(struct iostream_private *stream,
				      size_t max_size)
{
	struct seekable_istream *sstream = (struct seekable_istream *)stream;
	unsigned int i;

	sstream->istream.max_buffer_size = max_size;
	if (sstream->fd_input != NULL)
		i_stream_set_max_buffer_size(sstream->fd_input, max_size);
	for (i = 0; sstream->input[i] != NULL; i++)
		i_stream_set_max_buffer_size(sstream->input[i], max_size);
}

static int copy_to_temp_file(struct seekable_istream *sstream)
{
	unsigned char randbuf[8];
	const char *path;
	struct stat st;
	int fd;

	/* create a temporary file */
	for (;;) {
		random_fill_weak(randbuf, sizeof(randbuf));
		path = t_strconcat(sstream->temp_prefix, ".",
				   dec2str(time(NULL)), ".",
				   dec2str(getpid()), ".",
				   binary_to_hex(randbuf, sizeof(randbuf)),
				   NULL);
		if (stat(path, &st) == 0)
			continue;

		if (errno != ENOENT) {
			i_error("stat(%s) failed: %m", path);
			return -1;
		}

		fd = open(path, O_RDWR | O_EXCL | O_CREAT, 0600);
		if (fd != -1)
			break;

		if (errno != EEXIST) {
			i_error("open(%s) failed: %m", path);
			return -1;
		}
	}<commit_msg>istream-seekable: Log file creation error as creat() failure, not open().<commit_after>/* Copyright (c) 2005-2008 Dovecot authors, see the included COPYING file */

#include "lib.h"
#include "buffer.h"
#include "hex-binary.h"
#include "randgen.h"
#include "write-full.h"
#include "istream-internal.h"
#include "istream-concat.h"
#include "istream-seekable.h"

#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>

#define BUF_INITIAL_SIZE (1024*32)

struct seekable_istream {
	struct istream_private istream;

	char *temp_prefix;
	uoff_t write_peak;

	buffer_t *buffer;
	struct istream **input, *cur_input;
	struct istream *fd_input;
	unsigned int cur_idx;
	int fd;
};

static void i_stream_seekable_close(struct iostream_private *stream)
{
	struct seekable_istream *sstream = (struct seekable_istream *)stream;
	unsigned int i;

	sstream->fd = -1;
	if (sstream->fd_input != NULL)
		i_stream_close(sstream->fd_input);
	for (i = 0; sstream->input[i] != NULL; i++)
		i_stream_close(sstream->input[i]);
}

static void i_stream_seekable_destroy(struct iostream_private *stream)
{
	struct seekable_istream *sstream = (struct seekable_istream *)stream;
	unsigned int i;

	if (sstream->buffer != NULL)
		buffer_free(&sstream->buffer);
	if (sstream->fd_input != NULL)
		i_stream_unref(&sstream->fd_input);
	for (i = 0; sstream->input[i] != NULL; i++)
		i_stream_unref(&sstream->input[i]);

	i_free(sstream->temp_prefix);
}

static void
i_stream_seekable_set_max_buffer_size(struct iostream_private *stream,
				      size_t max_size)
{
	struct seekable_istream *sstream = (struct seekable_istream *)stream;
	unsigned int i;

	sstream->istream.max_buffer_size = max_size;
	if (sstream->fd_input != NULL)
		i_stream_set_max_buffer_size(sstream->fd_input, max_size);
	for (i = 0; sstream->input[i] != NULL; i++)
		i_stream_set_max_buffer_size(sstream->input[i], max_size);
}

static int copy_to_temp_file(struct seekable_istream *sstream)
{
	unsigned char randbuf[8];
	const char *path;
	struct stat st;
	int fd;

	/* create a temporary file */
	for (;;) {
		random_fill_weak(randbuf, sizeof(randbuf));
		path = t_strconcat(sstream->temp_prefix, ".",
				   dec2str(time(NULL)), ".",
				   dec2str(getpid()), ".",
				   binary_to_hex(randbuf, sizeof(randbuf)),
				   NULL);
		if (stat(path, &st) == 0)
			continue;

		if (errno != ENOENT) {
			i_error("stat(%s) failed: %m", path);
			return -1;
		}

		fd = open(path, O_RDWR | O_EXCL | O_CREAT, 0600);
		if (fd != -1)
			break;

		if (errno != EEXIST) {
			i_error("creat(%s) failed: %m", path);
			return -1;
		}
	}
{'fraction_non_alphanumeric': 0.14679976512037582, 'fraction_numerical': 0.011352515169309062, 'mean_word_length': 4.703125, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 47, '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': '2854322', 'n_tokens_mistral': 2118, 'n_tokens_neox': 1960, 'n_words': 433}