<commit_before>#include <sys/mount.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <limits.h>
#include <errno.h>
#include "mosaic.h"
#include "volume.h"
#include "util.h"

static int open_fsimg(struct mosaic *m, int flags)
{
	if (!m->default_fs)
		m->default_fs = strdup("ext4");

	return open_mosaic_subdir(m);
}


static int open_fsimg_vol(struct mosaic *m, struct volume *t,
		int open_flags)
{
	struct mosaic_subdir_priv *fp = m->priv;
	struct stat b;

	return fstatat(fp->m_loc_dir, t->t_name, &b, 0);
}

static int new_fsimg_vol(struct mosaic *m, const char *name,
		unsigned long size_in_blocks, int make_flags)
{
	struct mosaic_subdir_priv *fp = m->priv;
	char dir[PATH_MAX];
	int imgf;

	/*
	 * FIXME -- add separate subdir for images and separate for
	 * regular fs mount?
	 */
	snprintf(dir, sizeof(dir), "%s/%s", m->m_loc, name);
	if (mkdir_p(dir, 0, 0700) < 0) {
		// error is printed by mkdir_p()
		return -1;
	}
	imgf = openat(fp->m_loc_dir, name, O_WRONLY | O_CREAT | O_EXCL, 0600);
	if (imgf < 0)
		return -1;

	if (ftruncate(imgf, size_in_blocks << MOSAIC_BLOCK_SHIFT) < 0) {
		close(imgf);
		return -1;
	}

	if (make_flags & NEW_VOL_WITH_FS) {
		char path[PATH_MAX];
		char *argv[8];
		int i = 0;

		snprintf(path, sizeof(path), "%s/%s", m->m_loc, name);

		argv[i++] = "mkfs";
		argv[i++] = "-t";
		argv[i++] = m->default_fs;
		argv[i++] = "-F";
		argv[i++] = path;
		argv[i++] = NULL;
		if (run_prg(argv)) {
			close(imgf);
			return -1;
		}
	}

	close(imgf);
	return 0;
}

static int drop_fsimg_vol(struct mosaic *m, struct volume *t,
		int drop_flags)
{
	const char *base = m->m_loc;
	struct mosaic_subdir_priv *fp = m->priv;
	int base_fd = fp->m_loc_dir;

	/*
	 * FIXME -- what if mounted?
	 */
	if (unlinkat(base_fd, t->t_name, 0))
		return -1;
	// Remove all the non-empty parent directories up to base
	return rmdirat_r(base_fd, base, t->t_name);
}

/* Figure out device name that corresponds to given volume.
 * Returns device string length, 0 if no device, or -1 on error.
 */
static int get_dev(struct mosaic *m, struct volume *t, char *dev, int size)
{
	struct mosaic_subdir_priv *pdata = m->priv;<commit_msg>drop_fsimg_vol(): report error<commit_after>#include <sys/mount.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <limits.h>
#include <errno.h>
#include "mosaic.h"
#include "volume.h"
#include "util.h"

static int open_fsimg(struct mosaic *m, int flags)
{
	if (!m->default_fs)
		m->default_fs = strdup("ext4");

	return open_mosaic_subdir(m);
}


static int open_fsimg_vol(struct mosaic *m, struct volume *t,
		int open_flags)
{
	struct mosaic_subdir_priv *fp = m->priv;
	struct stat b;

	return fstatat(fp->m_loc_dir, t->t_name, &b, 0);
}

static int new_fsimg_vol(struct mosaic *m, const char *name,
		unsigned long size_in_blocks, int make_flags)
{
	struct mosaic_subdir_priv *fp = m->priv;
	char dir[PATH_MAX];
	int imgf;

	/*
	 * FIXME -- add separate subdir for images and separate for
	 * regular fs mount?
	 */
	snprintf(dir, sizeof(dir), "%s/%s", m->m_loc, name);
	if (mkdir_p(dir, 0, 0700) < 0) {
		// error is printed by mkdir_p()
		return -1;
	}
	imgf = openat(fp->m_loc_dir, name, O_WRONLY | O_CREAT | O_EXCL, 0600);
	if (imgf < 0)
		return -1;

	if (ftruncate(imgf, size_in_blocks << MOSAIC_BLOCK_SHIFT) < 0) {
		close(imgf);
		return -1;
	}

	if (make_flags & NEW_VOL_WITH_FS) {
		char path[PATH_MAX];
		char *argv[8];
		int i = 0;

		snprintf(path, sizeof(path), "%s/%s", m->m_loc, name);

		argv[i++] = "mkfs";
		argv[i++] = "-t";
		argv[i++] = m->default_fs;
		argv[i++] = "-F";
		argv[i++] = path;
		argv[i++] = NULL;
		if (run_prg(argv)) {
			close(imgf);
			return -1;
		}
	}

	close(imgf);
	return 0;
}

static int drop_fsimg_vol(struct mosaic *m, struct volume *t,
		int drop_flags)
{
	const char *base = m->m_loc;
	struct mosaic_subdir_priv *fp = m->priv;
	int base_fd = fp->m_loc_dir;

	/*
	 * FIXME -- what if mounted?
	 */
	if (unlinkat(base_fd, t->t_name, 0)) {
		fprintf(stderr, "%s: can't rm %s: %m\n", __func__, t->t_name);
		return -1;
	}
	// Remove all the non-empty parent directories up to base
	return rmdirat_r(base_fd, base, t->t_name);
}

/* Figure out device name that corresponds to given volume.
 * Returns device string length, 0 if no device, or -1 on error.
 */
static int get_dev(struct mosaic *m, struct volume *t, char *dev, int size)
{
	struct mosaic_subdir_priv *pdata = m->priv;
{'fraction_non_alphanumeric': 0.1609702315325248, 'fraction_numerical': 0.011025358324145534, 'mean_word_length': 3.8461538461538463, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 54, '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': '4955463', 'n_tokens_mistral': 2008, 'n_tokens_neox': 1860, 'n_words': 499}