xref: /linux/fs/vboxsf/dir.c (revision a1c613ae4c322ddd58d5a8539dbfba2a0380a8c0)
10fd16957SHans de Goede // SPDX-License-Identifier: MIT
20fd16957SHans de Goede /*
30fd16957SHans de Goede  * VirtualBox Guest Shared Folders support: Directory inode and file operations
40fd16957SHans de Goede  *
50fd16957SHans de Goede  * Copyright (C) 2006-2018 Oracle Corporation
60fd16957SHans de Goede  */
70fd16957SHans de Goede 
80fd16957SHans de Goede #include <linux/namei.h>
90fd16957SHans de Goede #include <linux/vbox_utils.h>
100fd16957SHans de Goede #include "vfsmod.h"
110fd16957SHans de Goede 
vboxsf_dir_open(struct inode * inode,struct file * file)120fd16957SHans de Goede static int vboxsf_dir_open(struct inode *inode, struct file *file)
130fd16957SHans de Goede {
140fd16957SHans de Goede 	struct vboxsf_sbi *sbi = VBOXSF_SBI(inode->i_sb);
150fd16957SHans de Goede 	struct shfl_createparms params = {};
160fd16957SHans de Goede 	struct vboxsf_dir_info *sf_d;
170fd16957SHans de Goede 	int err;
180fd16957SHans de Goede 
190fd16957SHans de Goede 	sf_d = vboxsf_dir_info_alloc();
200fd16957SHans de Goede 	if (!sf_d)
210fd16957SHans de Goede 		return -ENOMEM;
220fd16957SHans de Goede 
230fd16957SHans de Goede 	params.handle = SHFL_HANDLE_NIL;
240fd16957SHans de Goede 	params.create_flags = SHFL_CF_DIRECTORY | SHFL_CF_ACT_OPEN_IF_EXISTS |
250fd16957SHans de Goede 			      SHFL_CF_ACT_FAIL_IF_NEW | SHFL_CF_ACCESS_READ;
260fd16957SHans de Goede 
270fd16957SHans de Goede 	err = vboxsf_create_at_dentry(file_dentry(file), &params);
280fd16957SHans de Goede 	if (err)
290fd16957SHans de Goede 		goto err_free_dir_info;
300fd16957SHans de Goede 
310fd16957SHans de Goede 	if (params.result != SHFL_FILE_EXISTS) {
320fd16957SHans de Goede 		err = -ENOENT;
330fd16957SHans de Goede 		goto err_close;
340fd16957SHans de Goede 	}
350fd16957SHans de Goede 
360fd16957SHans de Goede 	err = vboxsf_dir_read_all(sbi, sf_d, params.handle);
370fd16957SHans de Goede 	if (err)
380fd16957SHans de Goede 		goto err_close;
390fd16957SHans de Goede 
400fd16957SHans de Goede 	vboxsf_close(sbi->root, params.handle);
410fd16957SHans de Goede 	file->private_data = sf_d;
420fd16957SHans de Goede 	return 0;
430fd16957SHans de Goede 
440fd16957SHans de Goede err_close:
450fd16957SHans de Goede 	vboxsf_close(sbi->root, params.handle);
460fd16957SHans de Goede err_free_dir_info:
470fd16957SHans de Goede 	vboxsf_dir_info_free(sf_d);
480fd16957SHans de Goede 	return err;
490fd16957SHans de Goede }
500fd16957SHans de Goede 
vboxsf_dir_release(struct inode * inode,struct file * file)510fd16957SHans de Goede static int vboxsf_dir_release(struct inode *inode, struct file *file)
520fd16957SHans de Goede {
530fd16957SHans de Goede 	if (file->private_data)
540fd16957SHans de Goede 		vboxsf_dir_info_free(file->private_data);
550fd16957SHans de Goede 
560fd16957SHans de Goede 	return 0;
570fd16957SHans de Goede }
580fd16957SHans de Goede 
vboxsf_get_d_type(u32 mode)590fd16957SHans de Goede static unsigned int vboxsf_get_d_type(u32 mode)
600fd16957SHans de Goede {
610fd16957SHans de Goede 	unsigned int d_type;
620fd16957SHans de Goede 
630fd16957SHans de Goede 	switch (mode & SHFL_TYPE_MASK) {
640fd16957SHans de Goede 	case SHFL_TYPE_FIFO:
650fd16957SHans de Goede 		d_type = DT_FIFO;
660fd16957SHans de Goede 		break;
670fd16957SHans de Goede 	case SHFL_TYPE_DEV_CHAR:
680fd16957SHans de Goede 		d_type = DT_CHR;
690fd16957SHans de Goede 		break;
700fd16957SHans de Goede 	case SHFL_TYPE_DIRECTORY:
710fd16957SHans de Goede 		d_type = DT_DIR;
720fd16957SHans de Goede 		break;
730fd16957SHans de Goede 	case SHFL_TYPE_DEV_BLOCK:
740fd16957SHans de Goede 		d_type = DT_BLK;
750fd16957SHans de Goede 		break;
760fd16957SHans de Goede 	case SHFL_TYPE_FILE:
770fd16957SHans de Goede 		d_type = DT_REG;
780fd16957SHans de Goede 		break;
790fd16957SHans de Goede 	case SHFL_TYPE_SYMLINK:
800fd16957SHans de Goede 		d_type = DT_LNK;
810fd16957SHans de Goede 		break;
820fd16957SHans de Goede 	case SHFL_TYPE_SOCKET:
830fd16957SHans de Goede 		d_type = DT_SOCK;
840fd16957SHans de Goede 		break;
850fd16957SHans de Goede 	case SHFL_TYPE_WHITEOUT:
860fd16957SHans de Goede 		d_type = DT_WHT;
870fd16957SHans de Goede 		break;
880fd16957SHans de Goede 	default:
890fd16957SHans de Goede 		d_type = DT_UNKNOWN;
900fd16957SHans de Goede 		break;
910fd16957SHans de Goede 	}
920fd16957SHans de Goede 	return d_type;
930fd16957SHans de Goede }
940fd16957SHans de Goede 
vboxsf_dir_emit(struct file * dir,struct dir_context * ctx)950fd16957SHans de Goede static bool vboxsf_dir_emit(struct file *dir, struct dir_context *ctx)
960fd16957SHans de Goede {
970fd16957SHans de Goede 	struct vboxsf_sbi *sbi = VBOXSF_SBI(file_inode(dir)->i_sb);
980fd16957SHans de Goede 	struct vboxsf_dir_info *sf_d = dir->private_data;
990fd16957SHans de Goede 	struct shfl_dirinfo *info;
1000fd16957SHans de Goede 	struct vboxsf_dir_buf *b;
1010fd16957SHans de Goede 	unsigned int d_type;
1020fd16957SHans de Goede 	loff_t i, cur = 0;
1030fd16957SHans de Goede 	ino_t fake_ino;
1040fd16957SHans de Goede 	void *end;
1050fd16957SHans de Goede 	int err;
1060fd16957SHans de Goede 
1070fd16957SHans de Goede 	list_for_each_entry(b, &sf_d->info_list, head) {
1080fd16957SHans de Goede try_next_entry:
1090fd16957SHans de Goede 		if (ctx->pos >= cur + b->entries) {
1100fd16957SHans de Goede 			cur += b->entries;
1110fd16957SHans de Goede 			continue;
1120fd16957SHans de Goede 		}
1130fd16957SHans de Goede 
1140fd16957SHans de Goede 		/*
1150fd16957SHans de Goede 		 * Note the vboxsf_dir_info objects we are iterating over here
1160fd16957SHans de Goede 		 * are variable sized, so the info pointer may end up being
1170fd16957SHans de Goede 		 * unaligned. This is how we get the data from the host.
1180fd16957SHans de Goede 		 * Since vboxsf is only supported on x86 machines this is not
1190fd16957SHans de Goede 		 * a problem.
1200fd16957SHans de Goede 		 */
1210fd16957SHans de Goede 		for (i = 0, info = b->buf; i < ctx->pos - cur; i++) {
1220fd16957SHans de Goede 			end = &info->name.string.utf8[info->name.size];
1230fd16957SHans de Goede 			/* Only happens if the host gives us corrupt data */
1240fd16957SHans de Goede 			if (WARN_ON(end > (b->buf + b->used)))
1250fd16957SHans de Goede 				return false;
1260fd16957SHans de Goede 			info = end;
1270fd16957SHans de Goede 		}
1280fd16957SHans de Goede 
1290fd16957SHans de Goede 		end = &info->name.string.utf8[info->name.size];
1300fd16957SHans de Goede 		if (WARN_ON(end > (b->buf + b->used)))
1310fd16957SHans de Goede 			return false;
1320fd16957SHans de Goede 
1330fd16957SHans de Goede 		/* Info now points to the right entry, emit it. */
1340fd16957SHans de Goede 		d_type = vboxsf_get_d_type(info->info.attr.mode);
1350fd16957SHans de Goede 
1360fd16957SHans de Goede 		/*
13715f9f63fSChucheng Luo 		 * On 32-bit systems pos is 64-bit signed, while ino is 32-bit
1380fd16957SHans de Goede 		 * unsigned so fake_ino may overflow, check for this.
1390fd16957SHans de Goede 		 */
1400fd16957SHans de Goede 		if ((ino_t)(ctx->pos + 1) != (u64)(ctx->pos + 1)) {
1410fd16957SHans de Goede 			vbg_err("vboxsf: fake ino overflow, truncating dir\n");
1420fd16957SHans de Goede 			return false;
1430fd16957SHans de Goede 		}
1440fd16957SHans de Goede 		fake_ino = ctx->pos + 1;
1450fd16957SHans de Goede 
1460fd16957SHans de Goede 		if (sbi->nls) {
1470fd16957SHans de Goede 			char d_name[NAME_MAX];
1480fd16957SHans de Goede 
1490fd16957SHans de Goede 			err = vboxsf_nlscpy(sbi, d_name, NAME_MAX,
1500fd16957SHans de Goede 					    info->name.string.utf8,
1510fd16957SHans de Goede 					    info->name.length);
1520fd16957SHans de Goede 			if (err) {
1530fd16957SHans de Goede 				/* skip erroneous entry and proceed */
1540fd16957SHans de Goede 				ctx->pos += 1;
1550fd16957SHans de Goede 				goto try_next_entry;
1560fd16957SHans de Goede 			}
1570fd16957SHans de Goede 
1580fd16957SHans de Goede 			return dir_emit(ctx, d_name, strlen(d_name),
1590fd16957SHans de Goede 					fake_ino, d_type);
1600fd16957SHans de Goede 		}
1610fd16957SHans de Goede 
1620fd16957SHans de Goede 		return dir_emit(ctx, info->name.string.utf8, info->name.length,
1630fd16957SHans de Goede 				fake_ino, d_type);
1640fd16957SHans de Goede 	}
1650fd16957SHans de Goede 
1660fd16957SHans de Goede 	return false;
1670fd16957SHans de Goede }
1680fd16957SHans de Goede 
vboxsf_dir_iterate(struct file * dir,struct dir_context * ctx)1690fd16957SHans de Goede static int vboxsf_dir_iterate(struct file *dir, struct dir_context *ctx)
1700fd16957SHans de Goede {
1710fd16957SHans de Goede 	bool emitted;
1720fd16957SHans de Goede 
1730fd16957SHans de Goede 	do {
1740fd16957SHans de Goede 		emitted = vboxsf_dir_emit(dir, ctx);
1750fd16957SHans de Goede 		if (emitted)
1760fd16957SHans de Goede 			ctx->pos += 1;
1770fd16957SHans de Goede 	} while (emitted);
1780fd16957SHans de Goede 
1790fd16957SHans de Goede 	return 0;
1800fd16957SHans de Goede }
1810fd16957SHans de Goede 
182*3e327154SLinus Torvalds WRAP_DIR_ITER(vboxsf_dir_iterate) // FIXME!
1830fd16957SHans de Goede const struct file_operations vboxsf_dir_fops = {
1840fd16957SHans de Goede 	.open = vboxsf_dir_open,
185*3e327154SLinus Torvalds 	.iterate_shared = shared_vboxsf_dir_iterate,
1860fd16957SHans de Goede 	.release = vboxsf_dir_release,
1870fd16957SHans de Goede 	.read = generic_read_dir,
1880fd16957SHans de Goede 	.llseek = generic_file_llseek,
1890fd16957SHans de Goede };
1900fd16957SHans de Goede 
1910fd16957SHans de Goede /*
1920fd16957SHans de Goede  * This is called during name resolution/lookup to check if the @dentry in
1930fd16957SHans de Goede  * the cache is still valid. the job is handled by vboxsf_inode_revalidate.
1940fd16957SHans de Goede  */
vboxsf_dentry_revalidate(struct dentry * dentry,unsigned int flags)1950fd16957SHans de Goede static int vboxsf_dentry_revalidate(struct dentry *dentry, unsigned int flags)
1960fd16957SHans de Goede {
1970fd16957SHans de Goede 	if (flags & LOOKUP_RCU)
1980fd16957SHans de Goede 		return -ECHILD;
1990fd16957SHans de Goede 
2000fd16957SHans de Goede 	if (d_really_is_positive(dentry))
2010fd16957SHans de Goede 		return vboxsf_inode_revalidate(dentry) == 0;
2020fd16957SHans de Goede 	else
2030fd16957SHans de Goede 		return vboxsf_stat_dentry(dentry, NULL) == -ENOENT;
2040fd16957SHans de Goede }
2050fd16957SHans de Goede 
2060fd16957SHans de Goede const struct dentry_operations vboxsf_dentry_ops = {
2070fd16957SHans de Goede 	.d_revalidate = vboxsf_dentry_revalidate
2080fd16957SHans de Goede };
2090fd16957SHans de Goede 
2100fd16957SHans de Goede /* iops */
2110fd16957SHans de Goede 
vboxsf_dir_lookup(struct inode * parent,struct dentry * dentry,unsigned int flags)2120fd16957SHans de Goede static struct dentry *vboxsf_dir_lookup(struct inode *parent,
2130fd16957SHans de Goede 					struct dentry *dentry,
2140fd16957SHans de Goede 					unsigned int flags)
2150fd16957SHans de Goede {
2160fd16957SHans de Goede 	struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb);
2170fd16957SHans de Goede 	struct shfl_fsobjinfo fsinfo;
2180fd16957SHans de Goede 	struct inode *inode;
2190fd16957SHans de Goede 	int err;
2200fd16957SHans de Goede 
2210fd16957SHans de Goede 	dentry->d_time = jiffies;
2220fd16957SHans de Goede 
2230fd16957SHans de Goede 	err = vboxsf_stat_dentry(dentry, &fsinfo);
2240fd16957SHans de Goede 	if (err) {
2250fd16957SHans de Goede 		inode = (err == -ENOENT) ? NULL : ERR_PTR(err);
2260fd16957SHans de Goede 	} else {
2270fd16957SHans de Goede 		inode = vboxsf_new_inode(parent->i_sb);
2280fd16957SHans de Goede 		if (!IS_ERR(inode))
229e98f93e7SAl Viro 			vboxsf_init_inode(sbi, inode, &fsinfo, false);
2300fd16957SHans de Goede 	}
2310fd16957SHans de Goede 
2320fd16957SHans de Goede 	return d_splice_alias(inode, dentry);
2330fd16957SHans de Goede }
2340fd16957SHans de Goede 
vboxsf_dir_instantiate(struct inode * parent,struct dentry * dentry,struct shfl_fsobjinfo * info)2350fd16957SHans de Goede static int vboxsf_dir_instantiate(struct inode *parent, struct dentry *dentry,
2360fd16957SHans de Goede 				  struct shfl_fsobjinfo *info)
2370fd16957SHans de Goede {
2380fd16957SHans de Goede 	struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb);
2390fd16957SHans de Goede 	struct vboxsf_inode *sf_i;
2400fd16957SHans de Goede 	struct inode *inode;
2410fd16957SHans de Goede 
2420fd16957SHans de Goede 	inode = vboxsf_new_inode(parent->i_sb);
2430fd16957SHans de Goede 	if (IS_ERR(inode))
2440fd16957SHans de Goede 		return PTR_ERR(inode);
2450fd16957SHans de Goede 
2460fd16957SHans de Goede 	sf_i = VBOXSF_I(inode);
2470fd16957SHans de Goede 	/* The host may have given us different attr then requested */
2480fd16957SHans de Goede 	sf_i->force_restat = 1;
249e98f93e7SAl Viro 	vboxsf_init_inode(sbi, inode, info, false);
2500fd16957SHans de Goede 
2510fd16957SHans de Goede 	d_instantiate(dentry, inode);
2520fd16957SHans de Goede 
2530fd16957SHans de Goede 	return 0;
2540fd16957SHans de Goede }
2550fd16957SHans de Goede 
vboxsf_dir_create(struct inode * parent,struct dentry * dentry,umode_t mode,bool is_dir,bool excl,u64 * handle_ret)2560fd16957SHans de Goede static int vboxsf_dir_create(struct inode *parent, struct dentry *dentry,
257ab0c2968SHans de Goede 			     umode_t mode, bool is_dir, bool excl, u64 *handle_ret)
2580fd16957SHans de Goede {
2590fd16957SHans de Goede 	struct vboxsf_inode *sf_parent_i = VBOXSF_I(parent);
2600fd16957SHans de Goede 	struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb);
2610fd16957SHans de Goede 	struct shfl_createparms params = {};
2620fd16957SHans de Goede 	int err;
2630fd16957SHans de Goede 
2640fd16957SHans de Goede 	params.handle = SHFL_HANDLE_NIL;
265cc3ddee9SHans de Goede 	params.create_flags = SHFL_CF_ACT_CREATE_IF_NEW | SHFL_CF_ACCESS_READWRITE;
266cc3ddee9SHans de Goede 	if (is_dir)
267cc3ddee9SHans de Goede 		params.create_flags |= SHFL_CF_DIRECTORY;
268cc3ddee9SHans de Goede 	if (excl)
269cc3ddee9SHans de Goede 		params.create_flags |= SHFL_CF_ACT_FAIL_IF_EXISTS;
270cc3ddee9SHans de Goede 
2710fd16957SHans de Goede 	params.info.attr.mode = (mode & 0777) |
2720fd16957SHans de Goede 				(is_dir ? SHFL_TYPE_DIRECTORY : SHFL_TYPE_FILE);
2730fd16957SHans de Goede 	params.info.attr.additional = SHFLFSOBJATTRADD_NOTHING;
2740fd16957SHans de Goede 
2750fd16957SHans de Goede 	err = vboxsf_create_at_dentry(dentry, &params);
2760fd16957SHans de Goede 	if (err)
2770fd16957SHans de Goede 		return err;
2780fd16957SHans de Goede 
2790fd16957SHans de Goede 	if (params.result != SHFL_FILE_CREATED)
2800fd16957SHans de Goede 		return -EPERM;
2810fd16957SHans de Goede 
2820fd16957SHans de Goede 	err = vboxsf_dir_instantiate(parent, dentry, &params.info);
2830fd16957SHans de Goede 	if (err)
284ab0c2968SHans de Goede 		goto out;
2850fd16957SHans de Goede 
2860fd16957SHans de Goede 	/* parent directory access/change time changed */
2870fd16957SHans de Goede 	sf_parent_i->force_restat = 1;
2880fd16957SHans de Goede 
289ab0c2968SHans de Goede out:
290ab0c2968SHans de Goede 	if (err == 0 && handle_ret)
291ab0c2968SHans de Goede 		*handle_ret = params.handle;
292ab0c2968SHans de Goede 	else
293ab0c2968SHans de Goede 		vboxsf_close(sbi->root, params.handle);
294ab0c2968SHans de Goede 
295ab0c2968SHans de Goede 	return err;
2960fd16957SHans de Goede }
2970fd16957SHans de Goede 
vboxsf_dir_mkfile(struct mnt_idmap * idmap,struct inode * parent,struct dentry * dentry,umode_t mode,bool excl)2986c960e68SChristian Brauner static int vboxsf_dir_mkfile(struct mnt_idmap *idmap,
299549c7297SChristian Brauner 			     struct inode *parent, struct dentry *dentry,
3000fd16957SHans de Goede 			     umode_t mode, bool excl)
3010fd16957SHans de Goede {
302ab0c2968SHans de Goede 	return vboxsf_dir_create(parent, dentry, mode, false, excl, NULL);
3030fd16957SHans de Goede }
3040fd16957SHans de Goede 
vboxsf_dir_mkdir(struct mnt_idmap * idmap,struct inode * parent,struct dentry * dentry,umode_t mode)305c54bd91eSChristian Brauner static int vboxsf_dir_mkdir(struct mnt_idmap *idmap,
306549c7297SChristian Brauner 			    struct inode *parent, struct dentry *dentry,
3070fd16957SHans de Goede 			    umode_t mode)
3080fd16957SHans de Goede {
309ab0c2968SHans de Goede 	return vboxsf_dir_create(parent, dentry, mode, true, true, NULL);
3100fd16957SHans de Goede }
3110fd16957SHans de Goede 
vboxsf_dir_atomic_open(struct inode * parent,struct dentry * dentry,struct file * file,unsigned int flags,umode_t mode)31252dfd86aSHans de Goede static int vboxsf_dir_atomic_open(struct inode *parent, struct dentry *dentry,
31352dfd86aSHans de Goede 				  struct file *file, unsigned int flags, umode_t mode)
31452dfd86aSHans de Goede {
31552dfd86aSHans de Goede 	struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb);
31652dfd86aSHans de Goede 	struct vboxsf_handle *sf_handle;
31752dfd86aSHans de Goede 	struct dentry *res = NULL;
31852dfd86aSHans de Goede 	u64 handle;
31952dfd86aSHans de Goede 	int err;
32052dfd86aSHans de Goede 
32152dfd86aSHans de Goede 	if (d_in_lookup(dentry)) {
32252dfd86aSHans de Goede 		res = vboxsf_dir_lookup(parent, dentry, 0);
32352dfd86aSHans de Goede 		if (IS_ERR(res))
32452dfd86aSHans de Goede 			return PTR_ERR(res);
32552dfd86aSHans de Goede 
32652dfd86aSHans de Goede 		if (res)
32752dfd86aSHans de Goede 			dentry = res;
32852dfd86aSHans de Goede 	}
32952dfd86aSHans de Goede 
33052dfd86aSHans de Goede 	/* Only creates */
33152dfd86aSHans de Goede 	if (!(flags & O_CREAT) || d_really_is_positive(dentry))
33252dfd86aSHans de Goede 		return finish_no_open(file, res);
33352dfd86aSHans de Goede 
33452dfd86aSHans de Goede 	err = vboxsf_dir_create(parent, dentry, mode, false, flags & O_EXCL, &handle);
33552dfd86aSHans de Goede 	if (err)
33652dfd86aSHans de Goede 		goto out;
33752dfd86aSHans de Goede 
33852dfd86aSHans de Goede 	sf_handle = vboxsf_create_sf_handle(d_inode(dentry), handle, SHFL_CF_ACCESS_READWRITE);
33952dfd86aSHans de Goede 	if (IS_ERR(sf_handle)) {
34052dfd86aSHans de Goede 		vboxsf_close(sbi->root, handle);
34152dfd86aSHans de Goede 		err = PTR_ERR(sf_handle);
34252dfd86aSHans de Goede 		goto out;
34352dfd86aSHans de Goede 	}
34452dfd86aSHans de Goede 
34552dfd86aSHans de Goede 	err = finish_open(file, dentry, generic_file_open);
34652dfd86aSHans de Goede 	if (err) {
34752dfd86aSHans de Goede 		/* This also closes the handle passed to vboxsf_create_sf_handle() */
34852dfd86aSHans de Goede 		vboxsf_release_sf_handle(d_inode(dentry), sf_handle);
34952dfd86aSHans de Goede 		goto out;
35052dfd86aSHans de Goede 	}
35152dfd86aSHans de Goede 
35252dfd86aSHans de Goede 	file->private_data = sf_handle;
35352dfd86aSHans de Goede 	file->f_mode |= FMODE_CREATED;
35452dfd86aSHans de Goede out:
35552dfd86aSHans de Goede 	dput(res);
35652dfd86aSHans de Goede 	return err;
35752dfd86aSHans de Goede }
35852dfd86aSHans de Goede 
vboxsf_dir_unlink(struct inode * parent,struct dentry * dentry)3590fd16957SHans de Goede static int vboxsf_dir_unlink(struct inode *parent, struct dentry *dentry)
3600fd16957SHans de Goede {
3610fd16957SHans de Goede 	struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb);
3620fd16957SHans de Goede 	struct vboxsf_inode *sf_parent_i = VBOXSF_I(parent);
3630fd16957SHans de Goede 	struct inode *inode = d_inode(dentry);
3640fd16957SHans de Goede 	struct shfl_string *path;
3650fd16957SHans de Goede 	u32 flags;
3660fd16957SHans de Goede 	int err;
3670fd16957SHans de Goede 
3680fd16957SHans de Goede 	if (S_ISDIR(inode->i_mode))
3690fd16957SHans de Goede 		flags = SHFL_REMOVE_DIR;
3700fd16957SHans de Goede 	else
3710fd16957SHans de Goede 		flags = SHFL_REMOVE_FILE;
3720fd16957SHans de Goede 
3730fd16957SHans de Goede 	if (S_ISLNK(inode->i_mode))
3740fd16957SHans de Goede 		flags |= SHFL_REMOVE_SYMLINK;
3750fd16957SHans de Goede 
3760fd16957SHans de Goede 	path = vboxsf_path_from_dentry(sbi, dentry);
3770fd16957SHans de Goede 	if (IS_ERR(path))
3780fd16957SHans de Goede 		return PTR_ERR(path);
3790fd16957SHans de Goede 
3800fd16957SHans de Goede 	err = vboxsf_remove(sbi->root, path, flags);
3810fd16957SHans de Goede 	__putname(path);
3820fd16957SHans de Goede 	if (err)
3830fd16957SHans de Goede 		return err;
3840fd16957SHans de Goede 
3850fd16957SHans de Goede 	/* parent directory access/change time changed */
3860fd16957SHans de Goede 	sf_parent_i->force_restat = 1;
3870fd16957SHans de Goede 
3880fd16957SHans de Goede 	return 0;
3890fd16957SHans de Goede }
3900fd16957SHans de Goede 
vboxsf_dir_rename(struct mnt_idmap * idmap,struct inode * old_parent,struct dentry * old_dentry,struct inode * new_parent,struct dentry * new_dentry,unsigned int flags)391e18275aeSChristian Brauner static int vboxsf_dir_rename(struct mnt_idmap *idmap,
392549c7297SChristian Brauner 			     struct inode *old_parent,
3930fd16957SHans de Goede 			     struct dentry *old_dentry,
3940fd16957SHans de Goede 			     struct inode *new_parent,
3950fd16957SHans de Goede 			     struct dentry *new_dentry,
3960fd16957SHans de Goede 			     unsigned int flags)
3970fd16957SHans de Goede {
3980fd16957SHans de Goede 	struct vboxsf_sbi *sbi = VBOXSF_SBI(old_parent->i_sb);
3990fd16957SHans de Goede 	struct vboxsf_inode *sf_old_parent_i = VBOXSF_I(old_parent);
4000fd16957SHans de Goede 	struct vboxsf_inode *sf_new_parent_i = VBOXSF_I(new_parent);
4010fd16957SHans de Goede 	u32 shfl_flags = SHFL_RENAME_FILE | SHFL_RENAME_REPLACE_IF_EXISTS;
4020fd16957SHans de Goede 	struct shfl_string *old_path, *new_path;
4030fd16957SHans de Goede 	int err;
4040fd16957SHans de Goede 
4050fd16957SHans de Goede 	if (flags)
4060fd16957SHans de Goede 		return -EINVAL;
4070fd16957SHans de Goede 
4080fd16957SHans de Goede 	old_path = vboxsf_path_from_dentry(sbi, old_dentry);
4090fd16957SHans de Goede 	if (IS_ERR(old_path))
4100fd16957SHans de Goede 		return PTR_ERR(old_path);
4110fd16957SHans de Goede 
4120fd16957SHans de Goede 	new_path = vboxsf_path_from_dentry(sbi, new_dentry);
4130fd16957SHans de Goede 	if (IS_ERR(new_path)) {
4140fd16957SHans de Goede 		err = PTR_ERR(new_path);
4150fd16957SHans de Goede 		goto err_put_old_path;
4160fd16957SHans de Goede 	}
4170fd16957SHans de Goede 
4180fd16957SHans de Goede 	if (d_inode(old_dentry)->i_mode & S_IFDIR)
4190fd16957SHans de Goede 		shfl_flags = 0;
4200fd16957SHans de Goede 
4210fd16957SHans de Goede 	err = vboxsf_rename(sbi->root, old_path, new_path, shfl_flags);
4220fd16957SHans de Goede 	if (err == 0) {
4230fd16957SHans de Goede 		/* parent directories access/change time changed */
4240fd16957SHans de Goede 		sf_new_parent_i->force_restat = 1;
4250fd16957SHans de Goede 		sf_old_parent_i->force_restat = 1;
4260fd16957SHans de Goede 	}
4270fd16957SHans de Goede 
4280fd16957SHans de Goede 	__putname(new_path);
4290fd16957SHans de Goede err_put_old_path:
4300fd16957SHans de Goede 	__putname(old_path);
4310fd16957SHans de Goede 	return err;
4320fd16957SHans de Goede }
4330fd16957SHans de Goede 
vboxsf_dir_symlink(struct mnt_idmap * idmap,struct inode * parent,struct dentry * dentry,const char * symname)4347a77db95SChristian Brauner static int vboxsf_dir_symlink(struct mnt_idmap *idmap,
435549c7297SChristian Brauner 			      struct inode *parent, struct dentry *dentry,
4360fd16957SHans de Goede 			      const char *symname)
4370fd16957SHans de Goede {
4380fd16957SHans de Goede 	struct vboxsf_inode *sf_parent_i = VBOXSF_I(parent);
4390fd16957SHans de Goede 	struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb);
4400fd16957SHans de Goede 	int symname_size = strlen(symname) + 1;
4410fd16957SHans de Goede 	struct shfl_string *path, *ssymname;
4420fd16957SHans de Goede 	struct shfl_fsobjinfo info;
4430fd16957SHans de Goede 	int err;
4440fd16957SHans de Goede 
4450fd16957SHans de Goede 	path = vboxsf_path_from_dentry(sbi, dentry);
4460fd16957SHans de Goede 	if (IS_ERR(path))
4470fd16957SHans de Goede 		return PTR_ERR(path);
4480fd16957SHans de Goede 
4490fd16957SHans de Goede 	ssymname = kmalloc(SHFLSTRING_HEADER_SIZE + symname_size, GFP_KERNEL);
4500fd16957SHans de Goede 	if (!ssymname) {
4510fd16957SHans de Goede 		__putname(path);
4520fd16957SHans de Goede 		return -ENOMEM;
4530fd16957SHans de Goede 	}
4540fd16957SHans de Goede 	ssymname->length = symname_size - 1;
4550fd16957SHans de Goede 	ssymname->size = symname_size;
4560fd16957SHans de Goede 	memcpy(ssymname->string.utf8, symname, symname_size);
4570fd16957SHans de Goede 
4580fd16957SHans de Goede 	err = vboxsf_symlink(sbi->root, path, ssymname, &info);
4590fd16957SHans de Goede 	kfree(ssymname);
4600fd16957SHans de Goede 	__putname(path);
4610fd16957SHans de Goede 	if (err) {
4620fd16957SHans de Goede 		/* -EROFS means symlinks are note support -> -EPERM */
4630fd16957SHans de Goede 		return (err == -EROFS) ? -EPERM : err;
4640fd16957SHans de Goede 	}
4650fd16957SHans de Goede 
4660fd16957SHans de Goede 	err = vboxsf_dir_instantiate(parent, dentry, &info);
4670fd16957SHans de Goede 	if (err)
4680fd16957SHans de Goede 		return err;
4690fd16957SHans de Goede 
4700fd16957SHans de Goede 	/* parent directory access/change time changed */
4710fd16957SHans de Goede 	sf_parent_i->force_restat = 1;
4720fd16957SHans de Goede 	return 0;
4730fd16957SHans de Goede }
4740fd16957SHans de Goede 
4750fd16957SHans de Goede const struct inode_operations vboxsf_dir_iops = {
4760fd16957SHans de Goede 	.lookup  = vboxsf_dir_lookup,
4770fd16957SHans de Goede 	.create  = vboxsf_dir_mkfile,
4780fd16957SHans de Goede 	.mkdir   = vboxsf_dir_mkdir,
47952dfd86aSHans de Goede 	.atomic_open = vboxsf_dir_atomic_open,
4800fd16957SHans de Goede 	.rmdir   = vboxsf_dir_unlink,
4810fd16957SHans de Goede 	.unlink  = vboxsf_dir_unlink,
4820fd16957SHans de Goede 	.rename  = vboxsf_dir_rename,
4830fd16957SHans de Goede 	.symlink = vboxsf_dir_symlink,
4840fd16957SHans de Goede 	.getattr = vboxsf_getattr,
4850fd16957SHans de Goede 	.setattr = vboxsf_setattr,
4860fd16957SHans de Goede };
487