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), ¶ms);
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, ¶ms);
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, ¶ms.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