<commit_before>#include "spfs_fuse_entity.h"
#include "spfs_path.h"
#include <string.h>
#include <unistd.h>

spfs_entity * spfs_entity_find_path(spfs_entity *root, const gchar *path) {
	g_return_val_if_fail(root != NULL, NULL);
	g_return_val_if_fail(root->name == NULL, NULL);
	g_return_val_if_fail(path != NULL, NULL);

	if (strlen(path) <= 0) {
		return NULL;
	}
	if (g_strcmp0(path, "/") == 0) {
		return root;
	}

	gchar **elems = g_strsplit(path, "/", 0);
	gchar *cur_el = NULL;
	spfs_entity *found = root;

	size_t i = 0;
	while ((elems[i] != NULL) && found != NULL) {
		/*Skip leading empty elements*/
		while (elems[i+1] != NULL && strlen(elems[i]) == 0) {
			++i;
			continue;
		}
		cur_el = elems[i];

		/*Skip trailing empty elements*/
		while (elems[i+1] != NULL && strlen(elems[i+1]) == 0) {
			++i;
		}

		if (elems[i+1] == NULL && (g_strcmp0(cur_el, found->name) == 0)) {
			break;
		}
		else if (found->type == SPFS_DIR) {
			GHashTable *children = found->e.dir->children;
			found = g_hash_table_lookup(children, cur_el);
		}
		else {
			/* Where do we go now, but nowhere? */
			found = NULL;
		}
		++i;
	}
	g_strfreev(elems);
	return found;
}

gchar *spfs_entity_get_full_path(spfs_entity *e) {
	g_return_val_if_fail(e != NULL, NULL);
	if (e->name == NULL) {
		return g_strdup("/");
	}

	gchar *p = g_malloc0(PATH_MAX);
	GArray *elems = g_array_new(FALSE, FALSE, sizeof(gpointer));

	while (e != NULL) {
		if (e->name != NULL) {
			gchar *s = g_strdup(e->name);
			g_array_append_val(elems, s);
		}
		e = e->parent;
	}

	size_t i;
	for (i = elems->len; i > 0; i--) {
		gchar *el = g_array_index(elems, gchar*, i-1);
		g_strlcat(p, "/", PATH_MAX);
		g_strlcat(p, el, PATH_MAX);
		g_free(el);
	}
	g_array_free(elems, TRUE);
	return p;
}

gchar *relpath(spfs_entity *from, spfs_entity *to) {
	gchar *frompath = spfs_entity_get_full_path(from);
	gchar *topath = spfs_entity_get_full_path(to);

	gchar * relpath = spfs_path_get_relative_path(frompath, topath);
	if (!relpath)
		g_warn_if_reached();

	g_free(frompath);
	g_free(topath);
	return relpath;
}

unsigned int spfs_entity_get_direct_io(spfs_entity *e) {
	g_return_val_if_fail(e != NULL, 0);
	if (e->type != SPFS_FILE || e->e.file->size > 0)
		return 0;

	return 1;

}

void spfs_entity_stat(spfs_entity *e, struct stat *statbuf) {
	switch (e->type) {
		case SPFS_DIR:
			statbuf->st_mode = S_IFDIR | S_IRUSR | S_IXUSR;
			break;
		case SPFS_FILE:
			statbuf->st_mode = S_IFREG | S_IRUSR | S_IRGRP;
			statbuf->st_size = e->e.file->size;
			break;
		case SPFS_LINK:
			statbuf->st_mode = S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO;
			if (e->e.link->target)
				statbuf->st_size = strlen(e->e.link->target);
			break;
	}

	statbuf->st_uid = getuid();
	if (e->ctime)
		statbuf->st_ctime = e->ctime;
	if (e->mtime)
		statbuf->st_mtime = e->mtime;
	if (e->atime)
		statbuf->st_atime = e->atime;

}
void spfs_entity_dir_add_child(spfs_entity *parent, spfs_entity *child) {
	g_return_if_fail(parent != NULL);
	g_return_if_fail(child != NULL);
	g_return_if_fail(parent->type == S_IFDIR);

	child->parent = parent;
	g_hash_table_insert(parent->e.dir->children, child->name, child);
	g_debug("added %s to dir %s", child->name, parent->name ? parent->name : "root");
}

void spfs_entity_link_set_target(spfs_entity *link, const gchar *target) {
	g_return_if_fail(link != NULL);
	g_return_if_fail(target != NULL);
	g_return_if_fail(link->type == S_IFLNK);<commit_msg>dirs: Disallow adding zero-length children<commit_after>#include "spfs_fuse_entity.h"
#include "spfs_path.h"
#include <string.h>
#include <unistd.h>

spfs_entity * spfs_entity_find_path(spfs_entity *root, const gchar *path) {
	g_return_val_if_fail(root != NULL, NULL);
	g_return_val_if_fail(root->name == NULL, NULL);
	g_return_val_if_fail(path != NULL, NULL);

	if (strlen(path) <= 0) {
		return NULL;
	}
	if (g_strcmp0(path, "/") == 0) {
		return root;
	}

	gchar **elems = g_strsplit(path, "/", 0);
	gchar *cur_el = NULL;
	spfs_entity *found = root;

	size_t i = 0;
	while ((elems[i] != NULL) && found != NULL) {
		/*Skip leading empty elements*/
		while (elems[i+1] != NULL && strlen(elems[i]) == 0) {
			++i;
			continue;
		}
		cur_el = elems[i];

		/*Skip trailing empty elements*/
		while (elems[i+1] != NULL && strlen(elems[i+1]) == 0) {
			++i;
		}

		if (elems[i+1] == NULL && (g_strcmp0(cur_el, found->name) == 0)) {
			break;
		}
		else if (found->type == SPFS_DIR) {
			GHashTable *children = found->e.dir->children;
			found = g_hash_table_lookup(children, cur_el);
		}
		else {
			/* Where do we go now, but nowhere? */
			found = NULL;
		}
		++i;
	}
	g_strfreev(elems);
	return found;
}

gchar *spfs_entity_get_full_path(spfs_entity *e) {
	g_return_val_if_fail(e != NULL, NULL);
	if (e->name == NULL) {
		return g_strdup("/");
	}

	gchar *p = g_malloc0(PATH_MAX);
	GArray *elems = g_array_new(FALSE, FALSE, sizeof(gpointer));

	while (e != NULL) {
		if (e->name != NULL) {
			gchar *s = g_strdup(e->name);
			g_array_append_val(elems, s);
		}
		e = e->parent;
	}

	size_t i;
	for (i = elems->len; i > 0; i--) {
		gchar *el = g_array_index(elems, gchar*, i-1);
		g_strlcat(p, "/", PATH_MAX);
		g_strlcat(p, el, PATH_MAX);
		g_free(el);
	}
	g_array_free(elems, TRUE);
	return p;
}

gchar *relpath(spfs_entity *from, spfs_entity *to) {
	gchar *frompath = spfs_entity_get_full_path(from);
	gchar *topath = spfs_entity_get_full_path(to);

	gchar * relpath = spfs_path_get_relative_path(frompath, topath);
	if (!relpath)
		g_warn_if_reached();

	g_free(frompath);
	g_free(topath);
	return relpath;
}

unsigned int spfs_entity_get_direct_io(spfs_entity *e) {
	g_return_val_if_fail(e != NULL, 0);
	if (e->type != SPFS_FILE || e->e.file->size > 0)
		return 0;

	return 1;

}

void spfs_entity_stat(spfs_entity *e, struct stat *statbuf) {
	switch (e->type) {
		case SPFS_DIR:
			statbuf->st_mode = S_IFDIR | S_IRUSR | S_IXUSR;
			break;
		case SPFS_FILE:
			statbuf->st_mode = S_IFREG | S_IRUSR | S_IRGRP;
			statbuf->st_size = e->e.file->size;
			break;
		case SPFS_LINK:
			statbuf->st_mode = S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO;
			if (e->e.link->target)
				statbuf->st_size = strlen(e->e.link->target);
			break;
	}

	statbuf->st_uid = getuid();
	if (e->ctime)
		statbuf->st_ctime = e->ctime;
	if (e->mtime)
		statbuf->st_mtime = e->mtime;
	if (e->atime)
		statbuf->st_atime = e->atime;

}
void spfs_entity_dir_add_child(spfs_entity *parent, spfs_entity *child) {
	g_return_if_fail(parent != NULL);
	g_return_if_fail(child != NULL);
	g_return_if_fail(parent->type == S_IFDIR);
	g_return_if_fail(strlen(child->name) > 0);

	child->parent = parent;
	g_hash_table_insert(parent->e.dir->children, child->name, child);
	g_debug("added %s to dir %s", child->name, parent->name ? parent->name : "root");
}

void spfs_entity_link_set_target(spfs_entity *link, const gchar *target) {
	g_return_if_fail(link != NULL);
	g_return_if_fail(target != NULL);
	g_return_if_fail(link->type == S_IFLNK);
{'fraction_non_alphanumeric': 0.16731686172518423, 'fraction_numerical': 0.005923999422048837, 'mean_word_length': 4.1927981995498875, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 101, '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': '2813018', 'n_tokens_mistral': 3212, 'n_tokens_neox': 3017, 'n_words': 575}