xref: /linux/fs/vboxsf/utils.c (revision 0200ceed)
10fd16957SHans de Goede // SPDX-License-Identifier: MIT
20fd16957SHans de Goede /*
30fd16957SHans de Goede  * VirtualBox Guest Shared Folders support: Utility functions.
40fd16957SHans de Goede  * Mainly conversion from/to VirtualBox/Linux data structures.
50fd16957SHans de Goede  *
60fd16957SHans de Goede  * Copyright (C) 2006-2018 Oracle Corporation
70fd16957SHans de Goede  */
80fd16957SHans de Goede 
90fd16957SHans de Goede #include <linux/namei.h>
100fd16957SHans de Goede #include <linux/nls.h>
110fd16957SHans de Goede #include <linux/sizes.h>
12cbcc268bSMatthew Wilcox (Oracle) #include <linux/pagemap.h>
130fd16957SHans de Goede #include <linux/vfs.h>
140fd16957SHans de Goede #include "vfsmod.h"
150fd16957SHans de Goede 
vboxsf_new_inode(struct super_block * sb)160fd16957SHans de Goede struct inode *vboxsf_new_inode(struct super_block *sb)
170fd16957SHans de Goede {
180fd16957SHans de Goede 	struct vboxsf_sbi *sbi = VBOXSF_SBI(sb);
190fd16957SHans de Goede 	struct inode *inode;
200fd16957SHans de Goede 	unsigned long flags;
210fd16957SHans de Goede 	int cursor, ret;
220fd16957SHans de Goede 	u32 gen;
230fd16957SHans de Goede 
240fd16957SHans de Goede 	inode = new_inode(sb);
250fd16957SHans de Goede 	if (!inode)
260fd16957SHans de Goede 		return ERR_PTR(-ENOMEM);
270fd16957SHans de Goede 
280fd16957SHans de Goede 	idr_preload(GFP_KERNEL);
290fd16957SHans de Goede 	spin_lock_irqsave(&sbi->ino_idr_lock, flags);
300fd16957SHans de Goede 	cursor = idr_get_cursor(&sbi->ino_idr);
310fd16957SHans de Goede 	ret = idr_alloc_cyclic(&sbi->ino_idr, inode, 1, 0, GFP_ATOMIC);
320fd16957SHans de Goede 	if (ret >= 0 && ret < cursor)
330fd16957SHans de Goede 		sbi->next_generation++;
340fd16957SHans de Goede 	gen = sbi->next_generation;
350fd16957SHans de Goede 	spin_unlock_irqrestore(&sbi->ino_idr_lock, flags);
360fd16957SHans de Goede 	idr_preload_end();
370fd16957SHans de Goede 
380fd16957SHans de Goede 	if (ret < 0) {
390fd16957SHans de Goede 		iput(inode);
400fd16957SHans de Goede 		return ERR_PTR(ret);
410fd16957SHans de Goede 	}
420fd16957SHans de Goede 
430fd16957SHans de Goede 	inode->i_ino = ret;
440fd16957SHans de Goede 	inode->i_generation = gen;
450fd16957SHans de Goede 	return inode;
460fd16957SHans de Goede }
470fd16957SHans de Goede 
480fd16957SHans de Goede /* set [inode] attributes based on [info], uid/gid based on [sbi] */
vboxsf_init_inode(struct vboxsf_sbi * sbi,struct inode * inode,const struct shfl_fsobjinfo * info,bool reinit)49e98f93e7SAl Viro int vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode,
50e98f93e7SAl Viro 		       const struct shfl_fsobjinfo *info, bool reinit)
510fd16957SHans de Goede {
520fd16957SHans de Goede 	const struct shfl_fsobjattr *attr;
530fd16957SHans de Goede 	s64 allocated;
54e98f93e7SAl Viro 	umode_t mode;
550fd16957SHans de Goede 
560fd16957SHans de Goede 	attr = &info->attr;
570fd16957SHans de Goede 
580fd16957SHans de Goede #define mode_set(r) ((attr->mode & (SHFL_UNIX_##r)) ? (S_##r) : 0)
590fd16957SHans de Goede 
600fd16957SHans de Goede 	mode = mode_set(IRUSR);
610fd16957SHans de Goede 	mode |= mode_set(IWUSR);
620fd16957SHans de Goede 	mode |= mode_set(IXUSR);
630fd16957SHans de Goede 
640fd16957SHans de Goede 	mode |= mode_set(IRGRP);
650fd16957SHans de Goede 	mode |= mode_set(IWGRP);
660fd16957SHans de Goede 	mode |= mode_set(IXGRP);
670fd16957SHans de Goede 
680fd16957SHans de Goede 	mode |= mode_set(IROTH);
690fd16957SHans de Goede 	mode |= mode_set(IWOTH);
700fd16957SHans de Goede 	mode |= mode_set(IXOTH);
710fd16957SHans de Goede 
720fd16957SHans de Goede #undef mode_set
730fd16957SHans de Goede 
740fd16957SHans de Goede 	/* We use the host-side values for these */
750fd16957SHans de Goede 	inode->i_flags |= S_NOATIME | S_NOCMTIME;
760fd16957SHans de Goede 	inode->i_mapping->a_ops = &vboxsf_reg_aops;
770fd16957SHans de Goede 
780fd16957SHans de Goede 	if (SHFL_IS_DIRECTORY(attr->mode)) {
79e98f93e7SAl Viro 		if (sbi->o.dmode_set)
80e98f93e7SAl Viro 			mode = sbi->o.dmode;
81e98f93e7SAl Viro 		mode &= ~sbi->o.dmask;
82e98f93e7SAl Viro 		mode |= S_IFDIR;
83e98f93e7SAl Viro 		if (!reinit) {
840fd16957SHans de Goede 			inode->i_op = &vboxsf_dir_iops;
850fd16957SHans de Goede 			inode->i_fop = &vboxsf_dir_fops;
860fd16957SHans de Goede 			/*
870fd16957SHans de Goede 			 * XXX: this probably should be set to the number of entries
880fd16957SHans de Goede 			 * in the directory plus two (. ..)
890fd16957SHans de Goede 			 */
900fd16957SHans de Goede 			set_nlink(inode, 1);
91e98f93e7SAl Viro 		} else if (!S_ISDIR(inode->i_mode))
92e98f93e7SAl Viro 			return -ESTALE;
93e98f93e7SAl Viro 		inode->i_mode = mode;
940fd16957SHans de Goede 	} else if (SHFL_IS_SYMLINK(attr->mode)) {
95e98f93e7SAl Viro 		if (sbi->o.fmode_set)
96e98f93e7SAl Viro 			mode = sbi->o.fmode;
97e98f93e7SAl Viro 		mode &= ~sbi->o.fmask;
98e98f93e7SAl Viro 		mode |= S_IFLNK;
99e98f93e7SAl Viro 		if (!reinit) {
1000fd16957SHans de Goede 			inode->i_op = &vboxsf_lnk_iops;
1010fd16957SHans de Goede 			set_nlink(inode, 1);
102e98f93e7SAl Viro 		} else if (!S_ISLNK(inode->i_mode))
103e98f93e7SAl Viro 			return -ESTALE;
104e98f93e7SAl Viro 		inode->i_mode = mode;
1050fd16957SHans de Goede 	} else {
106e98f93e7SAl Viro 		if (sbi->o.fmode_set)
107e98f93e7SAl Viro 			mode = sbi->o.fmode;
108e98f93e7SAl Viro 		mode &= ~sbi->o.fmask;
109e98f93e7SAl Viro 		mode |= S_IFREG;
110e98f93e7SAl Viro 		if (!reinit) {
1110fd16957SHans de Goede 			inode->i_op = &vboxsf_reg_iops;
1120fd16957SHans de Goede 			inode->i_fop = &vboxsf_reg_fops;
1130fd16957SHans de Goede 			set_nlink(inode, 1);
114e98f93e7SAl Viro 		} else if (!S_ISREG(inode->i_mode))
115e98f93e7SAl Viro 			return -ESTALE;
116e98f93e7SAl Viro 		inode->i_mode = mode;
1170fd16957SHans de Goede 	}
1180fd16957SHans de Goede 
1190fd16957SHans de Goede 	inode->i_uid = sbi->o.uid;
1200fd16957SHans de Goede 	inode->i_gid = sbi->o.gid;
1210fd16957SHans de Goede 
1220fd16957SHans de Goede 	inode->i_size = info->size;
1230fd16957SHans de Goede 	inode->i_blkbits = 12;
1240fd16957SHans de Goede 	/* i_blocks always in units of 512 bytes! */
1250fd16957SHans de Goede 	allocated = info->allocated + 511;
1260fd16957SHans de Goede 	do_div(allocated, 512);
1270fd16957SHans de Goede 	inode->i_blocks = allocated;
1280fd16957SHans de Goede 
129*9caef040SJeff Layton 	inode_set_atime_to_ts(inode,
130*9caef040SJeff Layton 			      ns_to_timespec64(info->access_time.ns_relative_to_unix_epoch));
1310593be0cSJeff Layton 	inode_set_ctime_to_ts(inode,
1320593be0cSJeff Layton 			      ns_to_timespec64(info->change_time.ns_relative_to_unix_epoch));
133*9caef040SJeff Layton 	inode_set_mtime_to_ts(inode,
134*9caef040SJeff Layton 			      ns_to_timespec64(info->modification_time.ns_relative_to_unix_epoch));
135e98f93e7SAl Viro 	return 0;
1360fd16957SHans de Goede }
1370fd16957SHans de Goede 
vboxsf_create_at_dentry(struct dentry * dentry,struct shfl_createparms * params)1380fd16957SHans de Goede int vboxsf_create_at_dentry(struct dentry *dentry,
1390fd16957SHans de Goede 			    struct shfl_createparms *params)
1400fd16957SHans de Goede {
1410fd16957SHans de Goede 	struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb);
1420fd16957SHans de Goede 	struct shfl_string *path;
1430fd16957SHans de Goede 	int err;
1440fd16957SHans de Goede 
1450fd16957SHans de Goede 	path = vboxsf_path_from_dentry(sbi, dentry);
1460fd16957SHans de Goede 	if (IS_ERR(path))
1470fd16957SHans de Goede 		return PTR_ERR(path);
1480fd16957SHans de Goede 
1490fd16957SHans de Goede 	err = vboxsf_create(sbi->root, path, params);
1500fd16957SHans de Goede 	__putname(path);
1510fd16957SHans de Goede 
1520fd16957SHans de Goede 	return err;
1530fd16957SHans de Goede }
1540fd16957SHans de Goede 
vboxsf_stat(struct vboxsf_sbi * sbi,struct shfl_string * path,struct shfl_fsobjinfo * info)1550fd16957SHans de Goede int vboxsf_stat(struct vboxsf_sbi *sbi, struct shfl_string *path,
1560fd16957SHans de Goede 		struct shfl_fsobjinfo *info)
1570fd16957SHans de Goede {
1580fd16957SHans de Goede 	struct shfl_createparms params = {};
1590fd16957SHans de Goede 	int err;
1600fd16957SHans de Goede 
1610fd16957SHans de Goede 	params.handle = SHFL_HANDLE_NIL;
1620fd16957SHans de Goede 	params.create_flags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW;
1630fd16957SHans de Goede 
1640fd16957SHans de Goede 	err = vboxsf_create(sbi->root, path, &params);
1650fd16957SHans de Goede 	if (err)
1660fd16957SHans de Goede 		return err;
1670fd16957SHans de Goede 
1680fd16957SHans de Goede 	if (params.result != SHFL_FILE_EXISTS)
1690fd16957SHans de Goede 		return -ENOENT;
1700fd16957SHans de Goede 
1710fd16957SHans de Goede 	if (info)
1720fd16957SHans de Goede 		*info = params.info;
1730fd16957SHans de Goede 
1740fd16957SHans de Goede 	return 0;
1750fd16957SHans de Goede }
1760fd16957SHans de Goede 
vboxsf_stat_dentry(struct dentry * dentry,struct shfl_fsobjinfo * info)1770fd16957SHans de Goede int vboxsf_stat_dentry(struct dentry *dentry, struct shfl_fsobjinfo *info)
1780fd16957SHans de Goede {
1790fd16957SHans de Goede 	struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb);
1800fd16957SHans de Goede 	struct shfl_string *path;
1810fd16957SHans de Goede 	int err;
1820fd16957SHans de Goede 
1830fd16957SHans de Goede 	path = vboxsf_path_from_dentry(sbi, dentry);
1840fd16957SHans de Goede 	if (IS_ERR(path))
1850fd16957SHans de Goede 		return PTR_ERR(path);
1860fd16957SHans de Goede 
1870fd16957SHans de Goede 	err = vboxsf_stat(sbi, path, info);
1880fd16957SHans de Goede 	__putname(path);
1890fd16957SHans de Goede 	return err;
1900fd16957SHans de Goede }
1910fd16957SHans de Goede 
vboxsf_inode_revalidate(struct dentry * dentry)1920fd16957SHans de Goede int vboxsf_inode_revalidate(struct dentry *dentry)
1930fd16957SHans de Goede {
1940fd16957SHans de Goede 	struct vboxsf_sbi *sbi;
1950fd16957SHans de Goede 	struct vboxsf_inode *sf_i;
1960fd16957SHans de Goede 	struct shfl_fsobjinfo info;
197*9caef040SJeff Layton 	struct timespec64 mtime, prev_mtime;
1980fd16957SHans de Goede 	struct inode *inode;
1990fd16957SHans de Goede 	int err;
2000fd16957SHans de Goede 
2010fd16957SHans de Goede 	if (!dentry || !d_really_is_positive(dentry))
2020fd16957SHans de Goede 		return -EINVAL;
2030fd16957SHans de Goede 
2040fd16957SHans de Goede 	inode = d_inode(dentry);
205*9caef040SJeff Layton 	prev_mtime = inode_get_mtime(inode);
2060fd16957SHans de Goede 	sf_i = VBOXSF_I(inode);
2070fd16957SHans de Goede 	sbi = VBOXSF_SBI(dentry->d_sb);
2080fd16957SHans de Goede 	if (!sf_i->force_restat) {
2090fd16957SHans de Goede 		if (time_before(jiffies, dentry->d_time + sbi->o.ttl))
2100fd16957SHans de Goede 			return 0;
2110fd16957SHans de Goede 	}
2120fd16957SHans de Goede 
2130fd16957SHans de Goede 	err = vboxsf_stat_dentry(dentry, &info);
2140fd16957SHans de Goede 	if (err)
2150fd16957SHans de Goede 		return err;
2160fd16957SHans de Goede 
2170fd16957SHans de Goede 	dentry->d_time = jiffies;
2180fd16957SHans de Goede 	sf_i->force_restat = 0;
219e98f93e7SAl Viro 	err = vboxsf_init_inode(sbi, inode, &info, true);
220e98f93e7SAl Viro 	if (err)
221e98f93e7SAl Viro 		return err;
2220fd16957SHans de Goede 
2230fd16957SHans de Goede 	/*
2240fd16957SHans de Goede 	 * If the file was changed on the host side we need to invalidate the
2250fd16957SHans de Goede 	 * page-cache for it.  Note this also gets triggered by our own writes,
2260fd16957SHans de Goede 	 * this is unavoidable.
2270fd16957SHans de Goede 	 */
228*9caef040SJeff Layton 	mtime = inode_get_mtime(inode);
229*9caef040SJeff Layton 	if (timespec64_compare(&mtime, &prev_mtime) > 0)
2300fd16957SHans de Goede 		invalidate_inode_pages2(inode->i_mapping);
2310fd16957SHans de Goede 
2320fd16957SHans de Goede 	return 0;
2330fd16957SHans de Goede }
2340fd16957SHans de Goede 
vboxsf_getattr(struct mnt_idmap * idmap,const struct path * path,struct kstat * kstat,u32 request_mask,unsigned int flags)235b74d24f7SChristian Brauner int vboxsf_getattr(struct mnt_idmap *idmap, const struct path *path,
236549c7297SChristian Brauner 		   struct kstat *kstat, u32 request_mask, unsigned int flags)
2370fd16957SHans de Goede {
2380fd16957SHans de Goede 	int err;
2390fd16957SHans de Goede 	struct dentry *dentry = path->dentry;
2400fd16957SHans de Goede 	struct inode *inode = d_inode(dentry);
2410fd16957SHans de Goede 	struct vboxsf_inode *sf_i = VBOXSF_I(inode);
2420fd16957SHans de Goede 
2430fd16957SHans de Goede 	switch (flags & AT_STATX_SYNC_TYPE) {
2440fd16957SHans de Goede 	case AT_STATX_DONT_SYNC:
2450fd16957SHans de Goede 		err = 0;
2460fd16957SHans de Goede 		break;
2470fd16957SHans de Goede 	case AT_STATX_FORCE_SYNC:
2480fd16957SHans de Goede 		sf_i->force_restat = 1;
249df561f66SGustavo A. R. Silva 		fallthrough;
2500fd16957SHans de Goede 	default:
2510fd16957SHans de Goede 		err = vboxsf_inode_revalidate(dentry);
2520fd16957SHans de Goede 	}
2530fd16957SHans de Goede 	if (err)
2540fd16957SHans de Goede 		return err;
2550fd16957SHans de Goede 
2560d72b928SJeff Layton 	generic_fillattr(&nop_mnt_idmap, request_mask, d_inode(dentry), kstat);
2570fd16957SHans de Goede 	return 0;
2580fd16957SHans de Goede }
2590fd16957SHans de Goede 
vboxsf_setattr(struct mnt_idmap * idmap,struct dentry * dentry,struct iattr * iattr)260c1632a0fSChristian Brauner int vboxsf_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
261549c7297SChristian Brauner 		   struct iattr *iattr)
2620fd16957SHans de Goede {
2630fd16957SHans de Goede 	struct vboxsf_inode *sf_i = VBOXSF_I(d_inode(dentry));
2640fd16957SHans de Goede 	struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb);
2650fd16957SHans de Goede 	struct shfl_createparms params = {};
2660fd16957SHans de Goede 	struct shfl_fsobjinfo info = {};
2670fd16957SHans de Goede 	u32 buf_len;
2680fd16957SHans de Goede 	int err;
2690fd16957SHans de Goede 
2700fd16957SHans de Goede 	params.handle = SHFL_HANDLE_NIL;
2710fd16957SHans de Goede 	params.create_flags = SHFL_CF_ACT_OPEN_IF_EXISTS |
2720fd16957SHans de Goede 			      SHFL_CF_ACT_FAIL_IF_NEW |
2730fd16957SHans de Goede 			      SHFL_CF_ACCESS_ATTR_WRITE;
2740fd16957SHans de Goede 
2750fd16957SHans de Goede 	/* this is at least required for Posix hosts */
2760fd16957SHans de Goede 	if (iattr->ia_valid & ATTR_SIZE)
2770fd16957SHans de Goede 		params.create_flags |= SHFL_CF_ACCESS_WRITE;
2780fd16957SHans de Goede 
2790fd16957SHans de Goede 	err = vboxsf_create_at_dentry(dentry, &params);
2800fd16957SHans de Goede 	if (err || params.result != SHFL_FILE_EXISTS)
2810fd16957SHans de Goede 		return err ? err : -ENOENT;
2820fd16957SHans de Goede 
2830fd16957SHans de Goede #define mode_set(r) ((iattr->ia_mode & (S_##r)) ? SHFL_UNIX_##r : 0)
2840fd16957SHans de Goede 
2850fd16957SHans de Goede 	/*
2860fd16957SHans de Goede 	 * Setting the file size and setting the other attributes has to
2870fd16957SHans de Goede 	 * be handled separately.
2880fd16957SHans de Goede 	 */
2890fd16957SHans de Goede 	if (iattr->ia_valid & (ATTR_MODE | ATTR_ATIME | ATTR_MTIME)) {
2900fd16957SHans de Goede 		if (iattr->ia_valid & ATTR_MODE) {
2910fd16957SHans de Goede 			info.attr.mode = mode_set(IRUSR);
2920fd16957SHans de Goede 			info.attr.mode |= mode_set(IWUSR);
2930fd16957SHans de Goede 			info.attr.mode |= mode_set(IXUSR);
2940fd16957SHans de Goede 			info.attr.mode |= mode_set(IRGRP);
2950fd16957SHans de Goede 			info.attr.mode |= mode_set(IWGRP);
2960fd16957SHans de Goede 			info.attr.mode |= mode_set(IXGRP);
2970fd16957SHans de Goede 			info.attr.mode |= mode_set(IROTH);
2980fd16957SHans de Goede 			info.attr.mode |= mode_set(IWOTH);
2990fd16957SHans de Goede 			info.attr.mode |= mode_set(IXOTH);
3000fd16957SHans de Goede 
3010fd16957SHans de Goede 			if (iattr->ia_mode & S_IFDIR)
3020fd16957SHans de Goede 				info.attr.mode |= SHFL_TYPE_DIRECTORY;
3030fd16957SHans de Goede 			else
3040fd16957SHans de Goede 				info.attr.mode |= SHFL_TYPE_FILE;
3050fd16957SHans de Goede 		}
3060fd16957SHans de Goede 
3070fd16957SHans de Goede 		if (iattr->ia_valid & ATTR_ATIME)
3080fd16957SHans de Goede 			info.access_time.ns_relative_to_unix_epoch =
3090fd16957SHans de Goede 					    timespec64_to_ns(&iattr->ia_atime);
3100fd16957SHans de Goede 
3110fd16957SHans de Goede 		if (iattr->ia_valid & ATTR_MTIME)
3120fd16957SHans de Goede 			info.modification_time.ns_relative_to_unix_epoch =
3130fd16957SHans de Goede 					    timespec64_to_ns(&iattr->ia_mtime);
3140fd16957SHans de Goede 
3150fd16957SHans de Goede 		/*
3160fd16957SHans de Goede 		 * Ignore ctime (inode change time) as it can't be set
3170fd16957SHans de Goede 		 * from userland anyway.
3180fd16957SHans de Goede 		 */
3190fd16957SHans de Goede 
3200fd16957SHans de Goede 		buf_len = sizeof(info);
3210fd16957SHans de Goede 		err = vboxsf_fsinfo(sbi->root, params.handle,
3220fd16957SHans de Goede 				    SHFL_INFO_SET | SHFL_INFO_FILE, &buf_len,
3230fd16957SHans de Goede 				    &info);
3240fd16957SHans de Goede 		if (err) {
3250fd16957SHans de Goede 			vboxsf_close(sbi->root, params.handle);
3260fd16957SHans de Goede 			return err;
3270fd16957SHans de Goede 		}
3280fd16957SHans de Goede 
3290fd16957SHans de Goede 		/* the host may have given us different attr then requested */
3300fd16957SHans de Goede 		sf_i->force_restat = 1;
3310fd16957SHans de Goede 	}
3320fd16957SHans de Goede 
3330fd16957SHans de Goede #undef mode_set
3340fd16957SHans de Goede 
3350fd16957SHans de Goede 	if (iattr->ia_valid & ATTR_SIZE) {
3360fd16957SHans de Goede 		memset(&info, 0, sizeof(info));
3370fd16957SHans de Goede 		info.size = iattr->ia_size;
3380fd16957SHans de Goede 		buf_len = sizeof(info);
3390fd16957SHans de Goede 		err = vboxsf_fsinfo(sbi->root, params.handle,
3400fd16957SHans de Goede 				    SHFL_INFO_SET | SHFL_INFO_SIZE, &buf_len,
3410fd16957SHans de Goede 				    &info);
3420fd16957SHans de Goede 		if (err) {
3430fd16957SHans de Goede 			vboxsf_close(sbi->root, params.handle);
3440fd16957SHans de Goede 			return err;
3450fd16957SHans de Goede 		}
3460fd16957SHans de Goede 
3470fd16957SHans de Goede 		/* the host may have given us different attr then requested */
3480fd16957SHans de Goede 		sf_i->force_restat = 1;
3490fd16957SHans de Goede 	}
3500fd16957SHans de Goede 
3510fd16957SHans de Goede 	vboxsf_close(sbi->root, params.handle);
3520fd16957SHans de Goede 
3530fd16957SHans de Goede 	/* Update the inode with what the host has actually given us. */
3540fd16957SHans de Goede 	if (sf_i->force_restat)
3550fd16957SHans de Goede 		vboxsf_inode_revalidate(dentry);
3560fd16957SHans de Goede 
3570fd16957SHans de Goede 	return 0;
3580fd16957SHans de Goede }
3590fd16957SHans de Goede 
3600fd16957SHans de Goede /*
3610fd16957SHans de Goede  * [dentry] contains string encoded in coding system that corresponds
3620fd16957SHans de Goede  * to [sbi]->nls, we must convert it to UTF8 here.
3630fd16957SHans de Goede  * Returns a shfl_string allocated through __getname (must be freed using
3640fd16957SHans de Goede  * __putname), or an ERR_PTR on error.
3650fd16957SHans de Goede  */
vboxsf_path_from_dentry(struct vboxsf_sbi * sbi,struct dentry * dentry)3660fd16957SHans de Goede struct shfl_string *vboxsf_path_from_dentry(struct vboxsf_sbi *sbi,
3670fd16957SHans de Goede 					    struct dentry *dentry)
3680fd16957SHans de Goede {
3690fd16957SHans de Goede 	struct shfl_string *shfl_path;
3700fd16957SHans de Goede 	int path_len, out_len, nb;
3710fd16957SHans de Goede 	char *buf, *path;
3720fd16957SHans de Goede 	wchar_t uni;
3730fd16957SHans de Goede 	u8 *out;
3740fd16957SHans de Goede 
3750fd16957SHans de Goede 	buf = __getname();
3760fd16957SHans de Goede 	if (!buf)
3770fd16957SHans de Goede 		return ERR_PTR(-ENOMEM);
3780fd16957SHans de Goede 
3790fd16957SHans de Goede 	path = dentry_path_raw(dentry, buf, PATH_MAX);
3800fd16957SHans de Goede 	if (IS_ERR(path)) {
3810fd16957SHans de Goede 		__putname(buf);
3820fd16957SHans de Goede 		return ERR_CAST(path);
3830fd16957SHans de Goede 	}
3840fd16957SHans de Goede 	path_len = strlen(path);
3850fd16957SHans de Goede 
3860fd16957SHans de Goede 	if (sbi->nls) {
3870fd16957SHans de Goede 		shfl_path = __getname();
3880fd16957SHans de Goede 		if (!shfl_path) {
3890fd16957SHans de Goede 			__putname(buf);
3900fd16957SHans de Goede 			return ERR_PTR(-ENOMEM);
3910fd16957SHans de Goede 		}
3920fd16957SHans de Goede 
3930fd16957SHans de Goede 		out = shfl_path->string.utf8;
3940fd16957SHans de Goede 		out_len = PATH_MAX - SHFLSTRING_HEADER_SIZE - 1;
3950fd16957SHans de Goede 
3960fd16957SHans de Goede 		while (path_len) {
3970fd16957SHans de Goede 			nb = sbi->nls->char2uni(path, path_len, &uni);
3980fd16957SHans de Goede 			if (nb < 0) {
3990fd16957SHans de Goede 				__putname(shfl_path);
4000fd16957SHans de Goede 				__putname(buf);
4010fd16957SHans de Goede 				return ERR_PTR(-EINVAL);
4020fd16957SHans de Goede 			}
4030fd16957SHans de Goede 			path += nb;
4040fd16957SHans de Goede 			path_len -= nb;
4050fd16957SHans de Goede 
4060fd16957SHans de Goede 			nb = utf32_to_utf8(uni, out, out_len);
4070fd16957SHans de Goede 			if (nb < 0) {
4080fd16957SHans de Goede 				__putname(shfl_path);
4090fd16957SHans de Goede 				__putname(buf);
4100fd16957SHans de Goede 				return ERR_PTR(-ENAMETOOLONG);
4110fd16957SHans de Goede 			}
4120fd16957SHans de Goede 			out += nb;
4130fd16957SHans de Goede 			out_len -= nb;
4140fd16957SHans de Goede 		}
4150fd16957SHans de Goede 		*out = 0;
4160fd16957SHans de Goede 		shfl_path->length = out - shfl_path->string.utf8;
4170fd16957SHans de Goede 		shfl_path->size = shfl_path->length + 1;
4180fd16957SHans de Goede 		__putname(buf);
4190fd16957SHans de Goede 	} else {
4200fd16957SHans de Goede 		if ((SHFLSTRING_HEADER_SIZE + path_len + 1) > PATH_MAX) {
4210fd16957SHans de Goede 			__putname(buf);
4220fd16957SHans de Goede 			return ERR_PTR(-ENAMETOOLONG);
4230fd16957SHans de Goede 		}
4240fd16957SHans de Goede 		/*
4250fd16957SHans de Goede 		 * dentry_path stores the name at the end of buf, but the
4260fd16957SHans de Goede 		 * shfl_string string we return must be properly aligned.
4270fd16957SHans de Goede 		 */
4280fd16957SHans de Goede 		shfl_path = (struct shfl_string *)buf;
4290fd16957SHans de Goede 		memmove(shfl_path->string.utf8, path, path_len);
4300fd16957SHans de Goede 		shfl_path->string.utf8[path_len] = 0;
4310fd16957SHans de Goede 		shfl_path->length = path_len;
4320fd16957SHans de Goede 		shfl_path->size = path_len + 1;
4330fd16957SHans de Goede 	}
4340fd16957SHans de Goede 
4350fd16957SHans de Goede 	return shfl_path;
4360fd16957SHans de Goede }
4370fd16957SHans de Goede 
vboxsf_nlscpy(struct vboxsf_sbi * sbi,char * name,size_t name_bound_len,const unsigned char * utf8_name,size_t utf8_len)4380fd16957SHans de Goede int vboxsf_nlscpy(struct vboxsf_sbi *sbi, char *name, size_t name_bound_len,
4390fd16957SHans de Goede 		  const unsigned char *utf8_name, size_t utf8_len)
4400fd16957SHans de Goede {
4410fd16957SHans de Goede 	const char *in;
4420fd16957SHans de Goede 	char *out;
4430fd16957SHans de Goede 	size_t out_bound_len;
4440fd16957SHans de Goede 	size_t in_bound_len;
4450fd16957SHans de Goede 
4460fd16957SHans de Goede 	in = utf8_name;
4470fd16957SHans de Goede 	in_bound_len = utf8_len;
4480fd16957SHans de Goede 
4490fd16957SHans de Goede 	out = name;
4500fd16957SHans de Goede 	/* Reserve space for terminating 0 */
4510fd16957SHans de Goede 	out_bound_len = name_bound_len - 1;
4520fd16957SHans de Goede 
4530fd16957SHans de Goede 	while (in_bound_len) {
4540fd16957SHans de Goede 		int nb;
4550fd16957SHans de Goede 		unicode_t uni;
4560fd16957SHans de Goede 
4570fd16957SHans de Goede 		nb = utf8_to_utf32(in, in_bound_len, &uni);
4580fd16957SHans de Goede 		if (nb < 0)
4590fd16957SHans de Goede 			return -EINVAL;
4600fd16957SHans de Goede 
4610fd16957SHans de Goede 		in += nb;
4620fd16957SHans de Goede 		in_bound_len -= nb;
4630fd16957SHans de Goede 
4640fd16957SHans de Goede 		nb = sbi->nls->uni2char(uni, out, out_bound_len);
4650fd16957SHans de Goede 		if (nb < 0)
4660fd16957SHans de Goede 			return nb;
4670fd16957SHans de Goede 
4680fd16957SHans de Goede 		out += nb;
4690fd16957SHans de Goede 		out_bound_len -= nb;
4700fd16957SHans de Goede 	}
4710fd16957SHans de Goede 
4720fd16957SHans de Goede 	*out = 0;
4730fd16957SHans de Goede 
4740fd16957SHans de Goede 	return 0;
4750fd16957SHans de Goede }
4760fd16957SHans de Goede 
vboxsf_dir_buf_alloc(struct list_head * list)4770fd16957SHans de Goede static struct vboxsf_dir_buf *vboxsf_dir_buf_alloc(struct list_head *list)
4780fd16957SHans de Goede {
4790fd16957SHans de Goede 	struct vboxsf_dir_buf *b;
4800fd16957SHans de Goede 
4810fd16957SHans de Goede 	b = kmalloc(sizeof(*b), GFP_KERNEL);
4820fd16957SHans de Goede 	if (!b)
4830fd16957SHans de Goede 		return NULL;
4840fd16957SHans de Goede 
4850fd16957SHans de Goede 	b->buf = kmalloc(DIR_BUFFER_SIZE, GFP_KERNEL);
4860fd16957SHans de Goede 	if (!b->buf) {
4870fd16957SHans de Goede 		kfree(b);
4880fd16957SHans de Goede 		return NULL;
4890fd16957SHans de Goede 	}
4900fd16957SHans de Goede 
4910fd16957SHans de Goede 	b->entries = 0;
4920fd16957SHans de Goede 	b->used = 0;
4930fd16957SHans de Goede 	b->free = DIR_BUFFER_SIZE;
4940fd16957SHans de Goede 	list_add(&b->head, list);
4950fd16957SHans de Goede 
4960fd16957SHans de Goede 	return b;
4970fd16957SHans de Goede }
4980fd16957SHans de Goede 
vboxsf_dir_buf_free(struct vboxsf_dir_buf * b)4990fd16957SHans de Goede static void vboxsf_dir_buf_free(struct vboxsf_dir_buf *b)
5000fd16957SHans de Goede {
5010fd16957SHans de Goede 	list_del(&b->head);
5020fd16957SHans de Goede 	kfree(b->buf);
5030fd16957SHans de Goede 	kfree(b);
5040fd16957SHans de Goede }
5050fd16957SHans de Goede 
vboxsf_dir_info_alloc(void)5060fd16957SHans de Goede struct vboxsf_dir_info *vboxsf_dir_info_alloc(void)
5070fd16957SHans de Goede {
5080fd16957SHans de Goede 	struct vboxsf_dir_info *p;
5090fd16957SHans de Goede 
5100fd16957SHans de Goede 	p = kmalloc(sizeof(*p), GFP_KERNEL);
5110fd16957SHans de Goede 	if (!p)
5120fd16957SHans de Goede 		return NULL;
5130fd16957SHans de Goede 
5140fd16957SHans de Goede 	INIT_LIST_HEAD(&p->info_list);
5150fd16957SHans de Goede 	return p;
5160fd16957SHans de Goede }
5170fd16957SHans de Goede 
vboxsf_dir_info_free(struct vboxsf_dir_info * p)5180fd16957SHans de Goede void vboxsf_dir_info_free(struct vboxsf_dir_info *p)
5190fd16957SHans de Goede {
5200fd16957SHans de Goede 	struct list_head *list, *pos, *tmp;
5210fd16957SHans de Goede 
5220fd16957SHans de Goede 	list = &p->info_list;
5230fd16957SHans de Goede 	list_for_each_safe(pos, tmp, list) {
5240fd16957SHans de Goede 		struct vboxsf_dir_buf *b;
5250fd16957SHans de Goede 
5260fd16957SHans de Goede 		b = list_entry(pos, struct vboxsf_dir_buf, head);
5270fd16957SHans de Goede 		vboxsf_dir_buf_free(b);
5280fd16957SHans de Goede 	}
5290fd16957SHans de Goede 	kfree(p);
5300fd16957SHans de Goede }
5310fd16957SHans de Goede 
vboxsf_dir_read_all(struct vboxsf_sbi * sbi,struct vboxsf_dir_info * sf_d,u64 handle)5320fd16957SHans de Goede int vboxsf_dir_read_all(struct vboxsf_sbi *sbi, struct vboxsf_dir_info *sf_d,
5330fd16957SHans de Goede 			u64 handle)
5340fd16957SHans de Goede {
5350fd16957SHans de Goede 	struct vboxsf_dir_buf *b;
5360fd16957SHans de Goede 	u32 entries, size;
5370fd16957SHans de Goede 	int err = 0;
5380fd16957SHans de Goede 	void *buf;
5390fd16957SHans de Goede 
5400fd16957SHans de Goede 	/* vboxsf_dirinfo returns 1 on end of dir */
5410fd16957SHans de Goede 	while (err == 0) {
5420fd16957SHans de Goede 		b = vboxsf_dir_buf_alloc(&sf_d->info_list);
5430fd16957SHans de Goede 		if (!b) {
5440fd16957SHans de Goede 			err = -ENOMEM;
5450fd16957SHans de Goede 			break;
5460fd16957SHans de Goede 		}
5470fd16957SHans de Goede 
5480fd16957SHans de Goede 		buf = b->buf;
5490fd16957SHans de Goede 		size = b->free;
5500fd16957SHans de Goede 
5510fd16957SHans de Goede 		err = vboxsf_dirinfo(sbi->root, handle, NULL, 0, 0,
5520fd16957SHans de Goede 				     &size, buf, &entries);
5530fd16957SHans de Goede 		if (err < 0)
5540fd16957SHans de Goede 			break;
5550fd16957SHans de Goede 
5560fd16957SHans de Goede 		b->entries += entries;
5570fd16957SHans de Goede 		b->free -= size;
5580fd16957SHans de Goede 		b->used += size;
5590fd16957SHans de Goede 	}
5600fd16957SHans de Goede 
5610fd16957SHans de Goede 	if (b && b->used == 0)
5620fd16957SHans de Goede 		vboxsf_dir_buf_free(b);
5630fd16957SHans de Goede 
5640fd16957SHans de Goede 	/* -EILSEQ means the host could not translate a filename, ignore */
5650fd16957SHans de Goede 	if (err > 0 || err == -EILSEQ)
5660fd16957SHans de Goede 		err = 0;
5670fd16957SHans de Goede 
5680fd16957SHans de Goede 	return err;
5690fd16957SHans de Goede }
570