<commit_before>/*
 * @file
 *
 * @date Nov 29, 2012
 * @author: <NAME>
 */

#include <unistd.h>
#include <fcntl.h>
#include <limits.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>

#include <sys/file.h>

#include <fs/vfs.h>
#include <fs/mount.h>
#include <fs/hlpr_path.h>
#include <fs/fs_driver.h>
#include <fs/kfsop.h>
#include <fs/perm.h>
#include <fs/flags.h>
#include <fs/file_desc.h>
//#include <fs/file_operation.h>

#include <security/security.h>


#include <kernel/spinlock.h>
#include <kernel/thread.h>

#include <mem/misc/pool.h>

#define MAX_FLOCK_QUANTITY OPTION_GET(NUMBER, flock_quantity)
POOL_DEF(flock_pool, flock_shared_t, MAX_FLOCK_QUANTITY);

static int create_new_node(struct path *parent, const char *name, mode_t mode) {
	struct path node;
	struct fs_driver *drv;
	int retval = 0;

	if(NULL == parent->node->nas->fs) {
		return -EINVAL;
	}

	if (0 != vfs_create(parent, name, mode, &node)) {
		return -ENOMEM;
	}

	/* check drv of parents */
	drv = parent->node->nas->fs->drv;
	if (!drv || !drv->fsop->create_node) {
		retval = -ENOSYS;
		goto out;
	}

	retval = drv->fsop->create_node(parent->node, node.node);
	if (retval) {
		goto out;
	}

	return 0;

out:
	vfs_del_leaf(node.node);
	return retval;
}

int kmkdir(struct path *root_node, const char *pathname, mode_t mode) {
	struct path node;
	const char *lastpath, *ch;
	int res;

	if (-ENOENT != (res = fs_perm_lookup(root_node, pathname, &lastpath, &node))) {
		errno = -res;
		return -1;
	}

	if (NULL != (ch = strchr(lastpath, '/'))
			&& NULL != path_next(ch, NULL)) {
		errno = ENOENT;
		return -1;
	}

	if_mounted_follow_down(&node);

	if (0 != fs_perm_check(node.node, FS_MAY_WRITE)) {
		errno = EACCES;
		return -1;
	}

	if (0 != (res = security_node_create(node.node, S_IFDIR | mode))) {
		errno = -res;
		return -1;
	}

	if (0 != create_new_node(&node, lastpath, S_IFDIR | mode)) {
		errno = -res;
		return -1;
	}

	return 0;
}

int kremove(const char *pathname) {
	struct path node, leaf;
	struct nas *nas;
	struct fs_driver *drv;
	int res;

	vfs_get_leaf_path(&leaf);
	if (0 != (res = fs_perm_lookup(&leaf, pathname, NULL, &node))) {
		errno = -res;
		return -1;
	}

	nas = node.node->nas;
	drv = nas->fs->drv;
	if (NULL == drv->fsop->delete_node) {
		errno = EPERM;
		return -1;
	}

	if (node_is_directory(node.node)) {
		return krmdir(pathname);
	}
	else {
		return kunlink(pathname);
	}
}

int kunlink(const char *pathname) {
	struct path node, leaf, parent;
	struct fs_driver *drv;
	int res;

	vfs_get_leaf_path(&leaf);
	if (0 != (res = fs_perm_lookup(&leaf, pathname, NULL, &node))) {
		errno = -res;
		return -1;
	}

	vfs_get_parent(&node, &parent);
	if (0 != fs_perm_check(parent.node, FS_MAY_WRITE)) {
		errno = EACCES;
		return -1;
	}

	if (0 != (res = security_node_delete(parent.node, node.node))) {
		errno = -res;
		return -1;
	}

	drv = node.node->nas->fs->drv;

	if (NULL == drv->fsop->delete_node) {
		errno = EPERM;
		return -1;
	}

	if (0 != (res = drv->fsop->delete_node(node.node))) {
		errno = -res;
		return -1;
	}

	/*vfs_del_leaf(node);*/

	return 0;

}

int krmdir(const char *pathname) {
	struct path node, leaf, parent;
	struct fs_driver *drv;
	int res;

	vfs_get_leaf_path(&leaf);
	if (0 != (res = fs_perm_lookup(&leaf, pathname, NULL, &node))) {
		errno = -res;
		return -1;
	}

	if (0 != (res = fs_perm_check(node.node, FS_MAY_WRITE))) {
		errno = EACCES;
		return -1;
	}

	vfs_get_parent(&node, &parent);
	if (0 != (res = security_node_delete(parent.node, node.node))) {
		return res;
	}

	drv = node.node->nas->fs->drv;

	if (NULL == drv->fsop->delete_node) {
		errno = EPERM;
		return -1;
	}

	if (0 != (res = drv->fsop->delete_node(node.node))) {
		errno = -res;
		return -1;
	}

	/*vfs_del_leaf(node);*/

	return 0;

}

int klstat(const char *path, struct stat *buf) {
	struct path node, leaf;
	int res;

	vfs_get_leaf_path(&leaf);
	if (0 != (res = fs_perm_lookup(&leaf, path, NULL, &node))) {
		errno = -res;
		return -1;
	}

	kfile_fill_stat(node.node, buf);

	return 0;
}

int kformat(const char *pathname, const char *fs_type) {
	struct path node, leaf;
	struct fs_driver *drv;
	int res;

	if (0 != fs_type) {
		drv = fs_driver_find_drv((const char *) fs_type);
		if (NULL == drv) {
			return -EINVAL;
		}
		if (NULL == drv->fsop->format) {
			return  -ENOSYS;
		}
	}
	else {
		return -EINVAL;
	}

	vfs_get_leaf_path(&leaf);
	if (0 != (res = fs_perm_lookup(&leaf, pathname, NULL, &node))) {
		errno = res == -ENOENT ? ENODEV : -res;
		return -1;
	}

	if (0 != (res = fs_perm_check(node.node, FS_MAY_WRITE))) {
		errno = EACCES;
		return -1;
	}

	if (0 != (res = drv->fsop->format(&node))) {
		errno = -res;
		return -1;
	}

	return 0;
}

int kmount(const char *dev, const char *dir, const char *fs_type) {
	struct path leaf, dev_node, dir_node, root_path;
	struct fs_driver *drv;
	const char *lastpath;
	int res;

	if (!fs_type) {
		errno = EINVAL;
		return -1;
	}

	drv = fs_driver_find_drv(fs_type);
	if (!drv) {
		errno = EINVAL;
		return -1;
	}
	if (!drv->fsop->mount) {
		errno = ENOSYS;
		return -1;
	}

	if ((0 == strcmp(fs_type, "nfs")) || (0 == strcmp(fs_type, "cifs"))) {
		//todo xxx
		dev_node.node = (node_t *) dev;
		goto skip_dev_lookup;
	}

	vfs_get_leaf_path(&leaf);
	if (ENOERR != (res = fs_perm_lookup(&leaf, dev, &lastpath, &dev_node))) {
		errno = res == -ENOENT ? ENODEV : -res;
		return -1;
	}

	if (ENOERR != (res = fs_perm_check(dev_node.node, FS_MAY_READ | FS_MAY_EXEC))) {
		errno = EACCES;<commit_msg>fs: kmount fix (NFS fixed)<commit_after>/*
 * @file
 *
 * @date Nov 29, 2012
 * @author: <NAME>
 */

#include <unistd.h>
#include <fcntl.h>
#include <limits.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>

#include <sys/file.h>

#include <fs/vfs.h>
#include <fs/mount.h>
#include <fs/hlpr_path.h>
#include <fs/fs_driver.h>
#include <fs/kfsop.h>
#include <fs/perm.h>
#include <fs/flags.h>
#include <fs/file_desc.h>
//#include <fs/file_operation.h>

#include <security/security.h>


#include <kernel/spinlock.h>
#include <kernel/thread.h>

#include <mem/misc/pool.h>

#define MAX_FLOCK_QUANTITY OPTION_GET(NUMBER, flock_quantity)
POOL_DEF(flock_pool, flock_shared_t, MAX_FLOCK_QUANTITY);

static int create_new_node(struct path *parent, const char *name, mode_t mode) {
	struct path node;
	struct fs_driver *drv;
	int retval = 0;

	if(NULL == parent->node->nas->fs) {
		return -EINVAL;
	}

	if (0 != vfs_create(parent, name, mode, &node)) {
		return -ENOMEM;
	}

	/* check drv of parents */
	drv = parent->node->nas->fs->drv;
	if (!drv || !drv->fsop->create_node) {
		retval = -ENOSYS;
		goto out;
	}

	retval = drv->fsop->create_node(parent->node, node.node);
	if (retval) {
		goto out;
	}

	return 0;

out:
	vfs_del_leaf(node.node);
	return retval;
}

int kmkdir(struct path *root_node, const char *pathname, mode_t mode) {
	struct path node;
	const char *lastpath, *ch;
	int res;

	if (-ENOENT != (res = fs_perm_lookup(root_node, pathname, &lastpath, &node))) {
		errno = -res;
		return -1;
	}

	if (NULL != (ch = strchr(lastpath, '/'))
			&& NULL != path_next(ch, NULL)) {
		errno = ENOENT;
		return -1;
	}

	if_mounted_follow_down(&node);

	if (0 != fs_perm_check(node.node, FS_MAY_WRITE)) {
		errno = EACCES;
		return -1;
	}

	if (0 != (res = security_node_create(node.node, S_IFDIR | mode))) {
		errno = -res;
		return -1;
	}

	if (0 != create_new_node(&node, lastpath, S_IFDIR | mode)) {
		errno = -res;
		return -1;
	}

	return 0;
}

int kremove(const char *pathname) {
	struct path node, leaf;
	struct nas *nas;
	struct fs_driver *drv;
	int res;

	vfs_get_leaf_path(&leaf);
	if (0 != (res = fs_perm_lookup(&leaf, pathname, NULL, &node))) {
		errno = -res;
		return -1;
	}

	nas = node.node->nas;
	drv = nas->fs->drv;
	if (NULL == drv->fsop->delete_node) {
		errno = EPERM;
		return -1;
	}

	if (node_is_directory(node.node)) {
		return krmdir(pathname);
	}
	else {
		return kunlink(pathname);
	}
}

int kunlink(const char *pathname) {
	struct path node, leaf, parent;
	struct fs_driver *drv;
	int res;

	vfs_get_leaf_path(&leaf);
	if (0 != (res = fs_perm_lookup(&leaf, pathname, NULL, &node))) {
		errno = -res;
		return -1;
	}

	vfs_get_parent(&node, &parent);
	if (0 != fs_perm_check(parent.node, FS_MAY_WRITE)) {
		errno = EACCES;
		return -1;
	}

	if (0 != (res = security_node_delete(parent.node, node.node))) {
		errno = -res;
		return -1;
	}

	drv = node.node->nas->fs->drv;

	if (NULL == drv->fsop->delete_node) {
		errno = EPERM;
		return -1;
	}

	if (0 != (res = drv->fsop->delete_node(node.node))) {
		errno = -res;
		return -1;
	}

	/*vfs_del_leaf(node);*/

	return 0;

}

int krmdir(const char *pathname) {
	struct path node, leaf, parent;
	struct fs_driver *drv;
	int res;

	vfs_get_leaf_path(&leaf);
	if (0 != (res = fs_perm_lookup(&leaf, pathname, NULL, &node))) {
		errno = -res;
		return -1;
	}

	if (0 != (res = fs_perm_check(node.node, FS_MAY_WRITE))) {
		errno = EACCES;
		return -1;
	}

	vfs_get_parent(&node, &parent);
	if (0 != (res = security_node_delete(parent.node, node.node))) {
		return res;
	}

	drv = node.node->nas->fs->drv;

	if (NULL == drv->fsop->delete_node) {
		errno = EPERM;
		return -1;
	}

	if (0 != (res = drv->fsop->delete_node(node.node))) {
		errno = -res;
		return -1;
	}

	/*vfs_del_leaf(node);*/

	return 0;

}

int klstat(const char *path, struct stat *buf) {
	struct path node, leaf;
	int res;

	vfs_get_leaf_path(&leaf);
	if (0 != (res = fs_perm_lookup(&leaf, path, NULL, &node))) {
		errno = -res;
		return -1;
	}

	kfile_fill_stat(node.node, buf);

	return 0;
}

int kformat(const char *pathname, const char *fs_type) {
	struct path node, leaf;
	struct fs_driver *drv;
	int res;

	if (0 != fs_type) {
		drv = fs_driver_find_drv((const char *) fs_type);
		if (NULL == drv) {
			return -EINVAL;
		}
		if (NULL == drv->fsop->format) {
			return  -ENOSYS;
		}
	}
	else {
		return -EINVAL;
	}

	vfs_get_leaf_path(&leaf);
	if (0 != (res = fs_perm_lookup(&leaf, pathname, NULL, &node))) {
		errno = res == -ENOENT ? ENODEV : -res;
		return -1;
	}

	if (0 != (res = fs_perm_check(node.node, FS_MAY_WRITE))) {
		errno = EACCES;
		return -1;
	}

	if (0 != (res = drv->fsop->format(&node))) {
		errno = -res;
		return -1;
	}

	return 0;
}

int kmount(const char *dev, const char *dir, const char *fs_type) {
	struct path leaf, dev_node, dir_node, root_path;
	struct fs_driver *drv;
	const char *lastpath;
	int res;

	if (!fs_type) {
		errno = EINVAL;
		return -1;
	}

	drv = fs_driver_find_drv(fs_type);
	if (!drv) {
		errno = EINVAL;
		return -1;
	}
	if (!drv->fsop->mount) {
		errno = ENOSYS;
		return -1;
	}

	vfs_get_leaf_path(&leaf);

	if ((0 == strcmp(fs_type, "nfs")) || (0 == strcmp(fs_type, "cifs"))) {
		//todo xxx
		dev_node.node = (node_t *) dev;
		goto skip_dev_lookup;
	}

	if (ENOERR != (res = fs_perm_lookup(&leaf, dev, &lastpath, &dev_node))) {
		errno = res == -ENOENT ? ENODEV : -res;
		return -1;
	}

	if (ENOERR != (res = fs_perm_check(dev_node.node, FS_MAY_READ | FS_MAY_EXEC))) {
		errno = EACCES;
{'fraction_non_alphanumeric': 0.17509057971014494, 'fraction_numerical': 0.010326086956521738, 'mean_word_length': 3.510212418300654, 'pattern_counts': {'":': 0, '<': 49, '<?xml version=': 0, '>': 123, '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': '1511324', 'n_tokens_mistral': 4987, 'n_tokens_neox': 4695, 'n_words': 1087}