Linux Audio

Check our new training course

Loading...
v5.9
  1// SPDX-License-Identifier: MIT
  2/*
  3 * VirtualBox Guest Shared Folders support: Utility functions.
  4 * Mainly conversion from/to VirtualBox/Linux data structures.
  5 *
  6 * Copyright (C) 2006-2018 Oracle Corporation
  7 */
  8
  9#include <linux/namei.h>
 10#include <linux/nls.h>
 11#include <linux/sizes.h>
 
 12#include <linux/vfs.h>
 13#include "vfsmod.h"
 14
 15struct inode *vboxsf_new_inode(struct super_block *sb)
 16{
 17	struct vboxsf_sbi *sbi = VBOXSF_SBI(sb);
 18	struct inode *inode;
 19	unsigned long flags;
 20	int cursor, ret;
 21	u32 gen;
 22
 23	inode = new_inode(sb);
 24	if (!inode)
 25		return ERR_PTR(-ENOMEM);
 26
 27	idr_preload(GFP_KERNEL);
 28	spin_lock_irqsave(&sbi->ino_idr_lock, flags);
 29	cursor = idr_get_cursor(&sbi->ino_idr);
 30	ret = idr_alloc_cyclic(&sbi->ino_idr, inode, 1, 0, GFP_ATOMIC);
 31	if (ret >= 0 && ret < cursor)
 32		sbi->next_generation++;
 33	gen = sbi->next_generation;
 34	spin_unlock_irqrestore(&sbi->ino_idr_lock, flags);
 35	idr_preload_end();
 36
 37	if (ret < 0) {
 38		iput(inode);
 39		return ERR_PTR(ret);
 40	}
 41
 42	inode->i_ino = ret;
 43	inode->i_generation = gen;
 44	return inode;
 45}
 46
 47/* set [inode] attributes based on [info], uid/gid based on [sbi] */
 48void vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode,
 49		       const struct shfl_fsobjinfo *info)
 50{
 51	const struct shfl_fsobjattr *attr;
 52	s64 allocated;
 53	int mode;
 54
 55	attr = &info->attr;
 56
 57#define mode_set(r) ((attr->mode & (SHFL_UNIX_##r)) ? (S_##r) : 0)
 58
 59	mode = mode_set(IRUSR);
 60	mode |= mode_set(IWUSR);
 61	mode |= mode_set(IXUSR);
 62
 63	mode |= mode_set(IRGRP);
 64	mode |= mode_set(IWGRP);
 65	mode |= mode_set(IXGRP);
 66
 67	mode |= mode_set(IROTH);
 68	mode |= mode_set(IWOTH);
 69	mode |= mode_set(IXOTH);
 70
 71#undef mode_set
 72
 73	/* We use the host-side values for these */
 74	inode->i_flags |= S_NOATIME | S_NOCMTIME;
 75	inode->i_mapping->a_ops = &vboxsf_reg_aops;
 76
 77	if (SHFL_IS_DIRECTORY(attr->mode)) {
 78		inode->i_mode = sbi->o.dmode_set ? sbi->o.dmode : mode;
 79		inode->i_mode &= ~sbi->o.dmask;
 80		inode->i_mode |= S_IFDIR;
 81		inode->i_op = &vboxsf_dir_iops;
 82		inode->i_fop = &vboxsf_dir_fops;
 83		/*
 84		 * XXX: this probably should be set to the number of entries
 85		 * in the directory plus two (. ..)
 86		 */
 87		set_nlink(inode, 1);
 
 
 
 
 
 88	} else if (SHFL_IS_SYMLINK(attr->mode)) {
 89		inode->i_mode = sbi->o.fmode_set ? sbi->o.fmode : mode;
 90		inode->i_mode &= ~sbi->o.fmask;
 91		inode->i_mode |= S_IFLNK;
 92		inode->i_op = &vboxsf_lnk_iops;
 93		set_nlink(inode, 1);
 
 
 
 
 
 94	} else {
 95		inode->i_mode = sbi->o.fmode_set ? sbi->o.fmode : mode;
 96		inode->i_mode &= ~sbi->o.fmask;
 97		inode->i_mode |= S_IFREG;
 98		inode->i_op = &vboxsf_reg_iops;
 99		inode->i_fop = &vboxsf_reg_fops;
100		set_nlink(inode, 1);
 
 
 
 
 
101	}
102
103	inode->i_uid = sbi->o.uid;
104	inode->i_gid = sbi->o.gid;
105
106	inode->i_size = info->size;
107	inode->i_blkbits = 12;
108	/* i_blocks always in units of 512 bytes! */
109	allocated = info->allocated + 511;
110	do_div(allocated, 512);
111	inode->i_blocks = allocated;
112
113	inode->i_atime = ns_to_timespec64(
114				 info->access_time.ns_relative_to_unix_epoch);
115	inode->i_ctime = ns_to_timespec64(
116				 info->change_time.ns_relative_to_unix_epoch);
117	inode->i_mtime = ns_to_timespec64(
118			   info->modification_time.ns_relative_to_unix_epoch);
 
119}
120
121int vboxsf_create_at_dentry(struct dentry *dentry,
122			    struct shfl_createparms *params)
123{
124	struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb);
125	struct shfl_string *path;
126	int err;
127
128	path = vboxsf_path_from_dentry(sbi, dentry);
129	if (IS_ERR(path))
130		return PTR_ERR(path);
131
132	err = vboxsf_create(sbi->root, path, params);
133	__putname(path);
134
135	return err;
136}
137
138int vboxsf_stat(struct vboxsf_sbi *sbi, struct shfl_string *path,
139		struct shfl_fsobjinfo *info)
140{
141	struct shfl_createparms params = {};
142	int err;
143
144	params.handle = SHFL_HANDLE_NIL;
145	params.create_flags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW;
146
147	err = vboxsf_create(sbi->root, path, &params);
148	if (err)
149		return err;
150
151	if (params.result != SHFL_FILE_EXISTS)
152		return -ENOENT;
153
154	if (info)
155		*info = params.info;
156
157	return 0;
158}
159
160int vboxsf_stat_dentry(struct dentry *dentry, struct shfl_fsobjinfo *info)
161{
162	struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb);
163	struct shfl_string *path;
164	int err;
165
166	path = vboxsf_path_from_dentry(sbi, dentry);
167	if (IS_ERR(path))
168		return PTR_ERR(path);
169
170	err = vboxsf_stat(sbi, path, info);
171	__putname(path);
172	return err;
173}
174
175int vboxsf_inode_revalidate(struct dentry *dentry)
176{
177	struct vboxsf_sbi *sbi;
178	struct vboxsf_inode *sf_i;
179	struct shfl_fsobjinfo info;
180	struct timespec64 prev_mtime;
181	struct inode *inode;
182	int err;
183
184	if (!dentry || !d_really_is_positive(dentry))
185		return -EINVAL;
186
187	inode = d_inode(dentry);
188	prev_mtime = inode->i_mtime;
189	sf_i = VBOXSF_I(inode);
190	sbi = VBOXSF_SBI(dentry->d_sb);
191	if (!sf_i->force_restat) {
192		if (time_before(jiffies, dentry->d_time + sbi->o.ttl))
193			return 0;
194	}
195
196	err = vboxsf_stat_dentry(dentry, &info);
197	if (err)
198		return err;
199
200	dentry->d_time = jiffies;
201	sf_i->force_restat = 0;
202	vboxsf_init_inode(sbi, inode, &info);
 
 
203
204	/*
205	 * If the file was changed on the host side we need to invalidate the
206	 * page-cache for it.  Note this also gets triggered by our own writes,
207	 * this is unavoidable.
208	 */
209	if (timespec64_compare(&inode->i_mtime, &prev_mtime) > 0)
 
210		invalidate_inode_pages2(inode->i_mapping);
211
212	return 0;
213}
214
215int vboxsf_getattr(const struct path *path, struct kstat *kstat,
216		   u32 request_mask, unsigned int flags)
217{
218	int err;
219	struct dentry *dentry = path->dentry;
220	struct inode *inode = d_inode(dentry);
221	struct vboxsf_inode *sf_i = VBOXSF_I(inode);
222
223	switch (flags & AT_STATX_SYNC_TYPE) {
224	case AT_STATX_DONT_SYNC:
225		err = 0;
226		break;
227	case AT_STATX_FORCE_SYNC:
228		sf_i->force_restat = 1;
229		fallthrough;
230	default:
231		err = vboxsf_inode_revalidate(dentry);
232	}
233	if (err)
234		return err;
235
236	generic_fillattr(d_inode(dentry), kstat);
237	return 0;
238}
239
240int vboxsf_setattr(struct dentry *dentry, struct iattr *iattr)
 
241{
242	struct vboxsf_inode *sf_i = VBOXSF_I(d_inode(dentry));
243	struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb);
244	struct shfl_createparms params = {};
245	struct shfl_fsobjinfo info = {};
246	u32 buf_len;
247	int err;
248
249	params.handle = SHFL_HANDLE_NIL;
250	params.create_flags = SHFL_CF_ACT_OPEN_IF_EXISTS |
251			      SHFL_CF_ACT_FAIL_IF_NEW |
252			      SHFL_CF_ACCESS_ATTR_WRITE;
253
254	/* this is at least required for Posix hosts */
255	if (iattr->ia_valid & ATTR_SIZE)
256		params.create_flags |= SHFL_CF_ACCESS_WRITE;
257
258	err = vboxsf_create_at_dentry(dentry, &params);
259	if (err || params.result != SHFL_FILE_EXISTS)
260		return err ? err : -ENOENT;
261
262#define mode_set(r) ((iattr->ia_mode & (S_##r)) ? SHFL_UNIX_##r : 0)
263
264	/*
265	 * Setting the file size and setting the other attributes has to
266	 * be handled separately.
267	 */
268	if (iattr->ia_valid & (ATTR_MODE | ATTR_ATIME | ATTR_MTIME)) {
269		if (iattr->ia_valid & ATTR_MODE) {
270			info.attr.mode = mode_set(IRUSR);
271			info.attr.mode |= mode_set(IWUSR);
272			info.attr.mode |= mode_set(IXUSR);
273			info.attr.mode |= mode_set(IRGRP);
274			info.attr.mode |= mode_set(IWGRP);
275			info.attr.mode |= mode_set(IXGRP);
276			info.attr.mode |= mode_set(IROTH);
277			info.attr.mode |= mode_set(IWOTH);
278			info.attr.mode |= mode_set(IXOTH);
279
280			if (iattr->ia_mode & S_IFDIR)
281				info.attr.mode |= SHFL_TYPE_DIRECTORY;
282			else
283				info.attr.mode |= SHFL_TYPE_FILE;
284		}
285
286		if (iattr->ia_valid & ATTR_ATIME)
287			info.access_time.ns_relative_to_unix_epoch =
288					    timespec64_to_ns(&iattr->ia_atime);
289
290		if (iattr->ia_valid & ATTR_MTIME)
291			info.modification_time.ns_relative_to_unix_epoch =
292					    timespec64_to_ns(&iattr->ia_mtime);
293
294		/*
295		 * Ignore ctime (inode change time) as it can't be set
296		 * from userland anyway.
297		 */
298
299		buf_len = sizeof(info);
300		err = vboxsf_fsinfo(sbi->root, params.handle,
301				    SHFL_INFO_SET | SHFL_INFO_FILE, &buf_len,
302				    &info);
303		if (err) {
304			vboxsf_close(sbi->root, params.handle);
305			return err;
306		}
307
308		/* the host may have given us different attr then requested */
309		sf_i->force_restat = 1;
310	}
311
312#undef mode_set
313
314	if (iattr->ia_valid & ATTR_SIZE) {
315		memset(&info, 0, sizeof(info));
316		info.size = iattr->ia_size;
317		buf_len = sizeof(info);
318		err = vboxsf_fsinfo(sbi->root, params.handle,
319				    SHFL_INFO_SET | SHFL_INFO_SIZE, &buf_len,
320				    &info);
321		if (err) {
322			vboxsf_close(sbi->root, params.handle);
323			return err;
324		}
325
326		/* the host may have given us different attr then requested */
327		sf_i->force_restat = 1;
328	}
329
330	vboxsf_close(sbi->root, params.handle);
331
332	/* Update the inode with what the host has actually given us. */
333	if (sf_i->force_restat)
334		vboxsf_inode_revalidate(dentry);
335
336	return 0;
337}
338
339/*
340 * [dentry] contains string encoded in coding system that corresponds
341 * to [sbi]->nls, we must convert it to UTF8 here.
342 * Returns a shfl_string allocated through __getname (must be freed using
343 * __putname), or an ERR_PTR on error.
344 */
345struct shfl_string *vboxsf_path_from_dentry(struct vboxsf_sbi *sbi,
346					    struct dentry *dentry)
347{
348	struct shfl_string *shfl_path;
349	int path_len, out_len, nb;
350	char *buf, *path;
351	wchar_t uni;
352	u8 *out;
353
354	buf = __getname();
355	if (!buf)
356		return ERR_PTR(-ENOMEM);
357
358	path = dentry_path_raw(dentry, buf, PATH_MAX);
359	if (IS_ERR(path)) {
360		__putname(buf);
361		return ERR_CAST(path);
362	}
363	path_len = strlen(path);
364
365	if (sbi->nls) {
366		shfl_path = __getname();
367		if (!shfl_path) {
368			__putname(buf);
369			return ERR_PTR(-ENOMEM);
370		}
371
372		out = shfl_path->string.utf8;
373		out_len = PATH_MAX - SHFLSTRING_HEADER_SIZE - 1;
374
375		while (path_len) {
376			nb = sbi->nls->char2uni(path, path_len, &uni);
377			if (nb < 0) {
378				__putname(shfl_path);
379				__putname(buf);
380				return ERR_PTR(-EINVAL);
381			}
382			path += nb;
383			path_len -= nb;
384
385			nb = utf32_to_utf8(uni, out, out_len);
386			if (nb < 0) {
387				__putname(shfl_path);
388				__putname(buf);
389				return ERR_PTR(-ENAMETOOLONG);
390			}
391			out += nb;
392			out_len -= nb;
393		}
394		*out = 0;
395		shfl_path->length = out - shfl_path->string.utf8;
396		shfl_path->size = shfl_path->length + 1;
397		__putname(buf);
398	} else {
399		if ((SHFLSTRING_HEADER_SIZE + path_len + 1) > PATH_MAX) {
400			__putname(buf);
401			return ERR_PTR(-ENAMETOOLONG);
402		}
403		/*
404		 * dentry_path stores the name at the end of buf, but the
405		 * shfl_string string we return must be properly aligned.
406		 */
407		shfl_path = (struct shfl_string *)buf;
408		memmove(shfl_path->string.utf8, path, path_len);
409		shfl_path->string.utf8[path_len] = 0;
410		shfl_path->length = path_len;
411		shfl_path->size = path_len + 1;
412	}
413
414	return shfl_path;
415}
416
417int vboxsf_nlscpy(struct vboxsf_sbi *sbi, char *name, size_t name_bound_len,
418		  const unsigned char *utf8_name, size_t utf8_len)
419{
420	const char *in;
421	char *out;
422	size_t out_len;
423	size_t out_bound_len;
424	size_t in_bound_len;
425
426	in = utf8_name;
427	in_bound_len = utf8_len;
428
429	out = name;
430	out_len = 0;
431	/* Reserve space for terminating 0 */
432	out_bound_len = name_bound_len - 1;
433
434	while (in_bound_len) {
435		int nb;
436		unicode_t uni;
437
438		nb = utf8_to_utf32(in, in_bound_len, &uni);
439		if (nb < 0)
440			return -EINVAL;
441
442		in += nb;
443		in_bound_len -= nb;
444
445		nb = sbi->nls->uni2char(uni, out, out_bound_len);
446		if (nb < 0)
447			return nb;
448
449		out += nb;
450		out_bound_len -= nb;
451		out_len += nb;
452	}
453
454	*out = 0;
455
456	return 0;
457}
458
459static struct vboxsf_dir_buf *vboxsf_dir_buf_alloc(struct list_head *list)
460{
461	struct vboxsf_dir_buf *b;
462
463	b = kmalloc(sizeof(*b), GFP_KERNEL);
464	if (!b)
465		return NULL;
466
467	b->buf = kmalloc(DIR_BUFFER_SIZE, GFP_KERNEL);
468	if (!b->buf) {
469		kfree(b);
470		return NULL;
471	}
472
473	b->entries = 0;
474	b->used = 0;
475	b->free = DIR_BUFFER_SIZE;
476	list_add(&b->head, list);
477
478	return b;
479}
480
481static void vboxsf_dir_buf_free(struct vboxsf_dir_buf *b)
482{
483	list_del(&b->head);
484	kfree(b->buf);
485	kfree(b);
486}
487
488struct vboxsf_dir_info *vboxsf_dir_info_alloc(void)
489{
490	struct vboxsf_dir_info *p;
491
492	p = kmalloc(sizeof(*p), GFP_KERNEL);
493	if (!p)
494		return NULL;
495
496	INIT_LIST_HEAD(&p->info_list);
497	return p;
498}
499
500void vboxsf_dir_info_free(struct vboxsf_dir_info *p)
501{
502	struct list_head *list, *pos, *tmp;
503
504	list = &p->info_list;
505	list_for_each_safe(pos, tmp, list) {
506		struct vboxsf_dir_buf *b;
507
508		b = list_entry(pos, struct vboxsf_dir_buf, head);
509		vboxsf_dir_buf_free(b);
510	}
511	kfree(p);
512}
513
514int vboxsf_dir_read_all(struct vboxsf_sbi *sbi, struct vboxsf_dir_info *sf_d,
515			u64 handle)
516{
517	struct vboxsf_dir_buf *b;
518	u32 entries, size;
519	int err = 0;
520	void *buf;
521
522	/* vboxsf_dirinfo returns 1 on end of dir */
523	while (err == 0) {
524		b = vboxsf_dir_buf_alloc(&sf_d->info_list);
525		if (!b) {
526			err = -ENOMEM;
527			break;
528		}
529
530		buf = b->buf;
531		size = b->free;
532
533		err = vboxsf_dirinfo(sbi->root, handle, NULL, 0, 0,
534				     &size, buf, &entries);
535		if (err < 0)
536			break;
537
538		b->entries += entries;
539		b->free -= size;
540		b->used += size;
541	}
542
543	if (b && b->used == 0)
544		vboxsf_dir_buf_free(b);
545
546	/* -EILSEQ means the host could not translate a filename, ignore */
547	if (err > 0 || err == -EILSEQ)
548		err = 0;
549
550	return err;
551}
v6.8
  1// SPDX-License-Identifier: MIT
  2/*
  3 * VirtualBox Guest Shared Folders support: Utility functions.
  4 * Mainly conversion from/to VirtualBox/Linux data structures.
  5 *
  6 * Copyright (C) 2006-2018 Oracle Corporation
  7 */
  8
  9#include <linux/namei.h>
 10#include <linux/nls.h>
 11#include <linux/sizes.h>
 12#include <linux/pagemap.h>
 13#include <linux/vfs.h>
 14#include "vfsmod.h"
 15
 16struct inode *vboxsf_new_inode(struct super_block *sb)
 17{
 18	struct vboxsf_sbi *sbi = VBOXSF_SBI(sb);
 19	struct inode *inode;
 20	unsigned long flags;
 21	int cursor, ret;
 22	u32 gen;
 23
 24	inode = new_inode(sb);
 25	if (!inode)
 26		return ERR_PTR(-ENOMEM);
 27
 28	idr_preload(GFP_KERNEL);
 29	spin_lock_irqsave(&sbi->ino_idr_lock, flags);
 30	cursor = idr_get_cursor(&sbi->ino_idr);
 31	ret = idr_alloc_cyclic(&sbi->ino_idr, inode, 1, 0, GFP_ATOMIC);
 32	if (ret >= 0 && ret < cursor)
 33		sbi->next_generation++;
 34	gen = sbi->next_generation;
 35	spin_unlock_irqrestore(&sbi->ino_idr_lock, flags);
 36	idr_preload_end();
 37
 38	if (ret < 0) {
 39		iput(inode);
 40		return ERR_PTR(ret);
 41	}
 42
 43	inode->i_ino = ret;
 44	inode->i_generation = gen;
 45	return inode;
 46}
 47
 48/* set [inode] attributes based on [info], uid/gid based on [sbi] */
 49int vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode,
 50		       const struct shfl_fsobjinfo *info, bool reinit)
 51{
 52	const struct shfl_fsobjattr *attr;
 53	s64 allocated;
 54	umode_t mode;
 55
 56	attr = &info->attr;
 57
 58#define mode_set(r) ((attr->mode & (SHFL_UNIX_##r)) ? (S_##r) : 0)
 59
 60	mode = mode_set(IRUSR);
 61	mode |= mode_set(IWUSR);
 62	mode |= mode_set(IXUSR);
 63
 64	mode |= mode_set(IRGRP);
 65	mode |= mode_set(IWGRP);
 66	mode |= mode_set(IXGRP);
 67
 68	mode |= mode_set(IROTH);
 69	mode |= mode_set(IWOTH);
 70	mode |= mode_set(IXOTH);
 71
 72#undef mode_set
 73
 74	/* We use the host-side values for these */
 75	inode->i_flags |= S_NOATIME | S_NOCMTIME;
 76	inode->i_mapping->a_ops = &vboxsf_reg_aops;
 77
 78	if (SHFL_IS_DIRECTORY(attr->mode)) {
 79		if (sbi->o.dmode_set)
 80			mode = sbi->o.dmode;
 81		mode &= ~sbi->o.dmask;
 82		mode |= S_IFDIR;
 83		if (!reinit) {
 84			inode->i_op = &vboxsf_dir_iops;
 85			inode->i_fop = &vboxsf_dir_fops;
 86			/*
 87			 * XXX: this probably should be set to the number of entries
 88			 * in the directory plus two (. ..)
 89			 */
 90			set_nlink(inode, 1);
 91		} else if (!S_ISDIR(inode->i_mode))
 92			return -ESTALE;
 93		inode->i_mode = mode;
 94	} else if (SHFL_IS_SYMLINK(attr->mode)) {
 95		if (sbi->o.fmode_set)
 96			mode = sbi->o.fmode;
 97		mode &= ~sbi->o.fmask;
 98		mode |= S_IFLNK;
 99		if (!reinit) {
100			inode->i_op = &vboxsf_lnk_iops;
101			set_nlink(inode, 1);
102		} else if (!S_ISLNK(inode->i_mode))
103			return -ESTALE;
104		inode->i_mode = mode;
105	} else {
106		if (sbi->o.fmode_set)
107			mode = sbi->o.fmode;
108		mode &= ~sbi->o.fmask;
109		mode |= S_IFREG;
110		if (!reinit) {
111			inode->i_op = &vboxsf_reg_iops;
112			inode->i_fop = &vboxsf_reg_fops;
113			set_nlink(inode, 1);
114		} else if (!S_ISREG(inode->i_mode))
115			return -ESTALE;
116		inode->i_mode = mode;
117	}
118
119	inode->i_uid = sbi->o.uid;
120	inode->i_gid = sbi->o.gid;
121
122	inode->i_size = info->size;
123	inode->i_blkbits = 12;
124	/* i_blocks always in units of 512 bytes! */
125	allocated = info->allocated + 511;
126	do_div(allocated, 512);
127	inode->i_blocks = allocated;
128
129	inode_set_atime_to_ts(inode,
130			      ns_to_timespec64(info->access_time.ns_relative_to_unix_epoch));
131	inode_set_ctime_to_ts(inode,
132			      ns_to_timespec64(info->change_time.ns_relative_to_unix_epoch));
133	inode_set_mtime_to_ts(inode,
134			      ns_to_timespec64(info->modification_time.ns_relative_to_unix_epoch));
135	return 0;
136}
137
138int vboxsf_create_at_dentry(struct dentry *dentry,
139			    struct shfl_createparms *params)
140{
141	struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb);
142	struct shfl_string *path;
143	int err;
144
145	path = vboxsf_path_from_dentry(sbi, dentry);
146	if (IS_ERR(path))
147		return PTR_ERR(path);
148
149	err = vboxsf_create(sbi->root, path, params);
150	__putname(path);
151
152	return err;
153}
154
155int vboxsf_stat(struct vboxsf_sbi *sbi, struct shfl_string *path,
156		struct shfl_fsobjinfo *info)
157{
158	struct shfl_createparms params = {};
159	int err;
160
161	params.handle = SHFL_HANDLE_NIL;
162	params.create_flags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW;
163
164	err = vboxsf_create(sbi->root, path, &params);
165	if (err)
166		return err;
167
168	if (params.result != SHFL_FILE_EXISTS)
169		return -ENOENT;
170
171	if (info)
172		*info = params.info;
173
174	return 0;
175}
176
177int vboxsf_stat_dentry(struct dentry *dentry, struct shfl_fsobjinfo *info)
178{
179	struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb);
180	struct shfl_string *path;
181	int err;
182
183	path = vboxsf_path_from_dentry(sbi, dentry);
184	if (IS_ERR(path))
185		return PTR_ERR(path);
186
187	err = vboxsf_stat(sbi, path, info);
188	__putname(path);
189	return err;
190}
191
192int vboxsf_inode_revalidate(struct dentry *dentry)
193{
194	struct vboxsf_sbi *sbi;
195	struct vboxsf_inode *sf_i;
196	struct shfl_fsobjinfo info;
197	struct timespec64 mtime, prev_mtime;
198	struct inode *inode;
199	int err;
200
201	if (!dentry || !d_really_is_positive(dentry))
202		return -EINVAL;
203
204	inode = d_inode(dentry);
205	prev_mtime = inode_get_mtime(inode);
206	sf_i = VBOXSF_I(inode);
207	sbi = VBOXSF_SBI(dentry->d_sb);
208	if (!sf_i->force_restat) {
209		if (time_before(jiffies, dentry->d_time + sbi->o.ttl))
210			return 0;
211	}
212
213	err = vboxsf_stat_dentry(dentry, &info);
214	if (err)
215		return err;
216
217	dentry->d_time = jiffies;
218	sf_i->force_restat = 0;
219	err = vboxsf_init_inode(sbi, inode, &info, true);
220	if (err)
221		return err;
222
223	/*
224	 * If the file was changed on the host side we need to invalidate the
225	 * page-cache for it.  Note this also gets triggered by our own writes,
226	 * this is unavoidable.
227	 */
228	mtime = inode_get_mtime(inode);
229	if (timespec64_compare(&mtime, &prev_mtime) > 0)
230		invalidate_inode_pages2(inode->i_mapping);
231
232	return 0;
233}
234
235int vboxsf_getattr(struct mnt_idmap *idmap, const struct path *path,
236		   struct kstat *kstat, u32 request_mask, unsigned int flags)
237{
238	int err;
239	struct dentry *dentry = path->dentry;
240	struct inode *inode = d_inode(dentry);
241	struct vboxsf_inode *sf_i = VBOXSF_I(inode);
242
243	switch (flags & AT_STATX_SYNC_TYPE) {
244	case AT_STATX_DONT_SYNC:
245		err = 0;
246		break;
247	case AT_STATX_FORCE_SYNC:
248		sf_i->force_restat = 1;
249		fallthrough;
250	default:
251		err = vboxsf_inode_revalidate(dentry);
252	}
253	if (err)
254		return err;
255
256	generic_fillattr(&nop_mnt_idmap, request_mask, d_inode(dentry), kstat);
257	return 0;
258}
259
260int vboxsf_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
261		   struct iattr *iattr)
262{
263	struct vboxsf_inode *sf_i = VBOXSF_I(d_inode(dentry));
264	struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb);
265	struct shfl_createparms params = {};
266	struct shfl_fsobjinfo info = {};
267	u32 buf_len;
268	int err;
269
270	params.handle = SHFL_HANDLE_NIL;
271	params.create_flags = SHFL_CF_ACT_OPEN_IF_EXISTS |
272			      SHFL_CF_ACT_FAIL_IF_NEW |
273			      SHFL_CF_ACCESS_ATTR_WRITE;
274
275	/* this is at least required for Posix hosts */
276	if (iattr->ia_valid & ATTR_SIZE)
277		params.create_flags |= SHFL_CF_ACCESS_WRITE;
278
279	err = vboxsf_create_at_dentry(dentry, &params);
280	if (err || params.result != SHFL_FILE_EXISTS)
281		return err ? err : -ENOENT;
282
283#define mode_set(r) ((iattr->ia_mode & (S_##r)) ? SHFL_UNIX_##r : 0)
284
285	/*
286	 * Setting the file size and setting the other attributes has to
287	 * be handled separately.
288	 */
289	if (iattr->ia_valid & (ATTR_MODE | ATTR_ATIME | ATTR_MTIME)) {
290		if (iattr->ia_valid & ATTR_MODE) {
291			info.attr.mode = mode_set(IRUSR);
292			info.attr.mode |= mode_set(IWUSR);
293			info.attr.mode |= mode_set(IXUSR);
294			info.attr.mode |= mode_set(IRGRP);
295			info.attr.mode |= mode_set(IWGRP);
296			info.attr.mode |= mode_set(IXGRP);
297			info.attr.mode |= mode_set(IROTH);
298			info.attr.mode |= mode_set(IWOTH);
299			info.attr.mode |= mode_set(IXOTH);
300
301			if (iattr->ia_mode & S_IFDIR)
302				info.attr.mode |= SHFL_TYPE_DIRECTORY;
303			else
304				info.attr.mode |= SHFL_TYPE_FILE;
305		}
306
307		if (iattr->ia_valid & ATTR_ATIME)
308			info.access_time.ns_relative_to_unix_epoch =
309					    timespec64_to_ns(&iattr->ia_atime);
310
311		if (iattr->ia_valid & ATTR_MTIME)
312			info.modification_time.ns_relative_to_unix_epoch =
313					    timespec64_to_ns(&iattr->ia_mtime);
314
315		/*
316		 * Ignore ctime (inode change time) as it can't be set
317		 * from userland anyway.
318		 */
319
320		buf_len = sizeof(info);
321		err = vboxsf_fsinfo(sbi->root, params.handle,
322				    SHFL_INFO_SET | SHFL_INFO_FILE, &buf_len,
323				    &info);
324		if (err) {
325			vboxsf_close(sbi->root, params.handle);
326			return err;
327		}
328
329		/* the host may have given us different attr then requested */
330		sf_i->force_restat = 1;
331	}
332
333#undef mode_set
334
335	if (iattr->ia_valid & ATTR_SIZE) {
336		memset(&info, 0, sizeof(info));
337		info.size = iattr->ia_size;
338		buf_len = sizeof(info);
339		err = vboxsf_fsinfo(sbi->root, params.handle,
340				    SHFL_INFO_SET | SHFL_INFO_SIZE, &buf_len,
341				    &info);
342		if (err) {
343			vboxsf_close(sbi->root, params.handle);
344			return err;
345		}
346
347		/* the host may have given us different attr then requested */
348		sf_i->force_restat = 1;
349	}
350
351	vboxsf_close(sbi->root, params.handle);
352
353	/* Update the inode with what the host has actually given us. */
354	if (sf_i->force_restat)
355		vboxsf_inode_revalidate(dentry);
356
357	return 0;
358}
359
360/*
361 * [dentry] contains string encoded in coding system that corresponds
362 * to [sbi]->nls, we must convert it to UTF8 here.
363 * Returns a shfl_string allocated through __getname (must be freed using
364 * __putname), or an ERR_PTR on error.
365 */
366struct shfl_string *vboxsf_path_from_dentry(struct vboxsf_sbi *sbi,
367					    struct dentry *dentry)
368{
369	struct shfl_string *shfl_path;
370	int path_len, out_len, nb;
371	char *buf, *path;
372	wchar_t uni;
373	u8 *out;
374
375	buf = __getname();
376	if (!buf)
377		return ERR_PTR(-ENOMEM);
378
379	path = dentry_path_raw(dentry, buf, PATH_MAX);
380	if (IS_ERR(path)) {
381		__putname(buf);
382		return ERR_CAST(path);
383	}
384	path_len = strlen(path);
385
386	if (sbi->nls) {
387		shfl_path = __getname();
388		if (!shfl_path) {
389			__putname(buf);
390			return ERR_PTR(-ENOMEM);
391		}
392
393		out = shfl_path->string.utf8;
394		out_len = PATH_MAX - SHFLSTRING_HEADER_SIZE - 1;
395
396		while (path_len) {
397			nb = sbi->nls->char2uni(path, path_len, &uni);
398			if (nb < 0) {
399				__putname(shfl_path);
400				__putname(buf);
401				return ERR_PTR(-EINVAL);
402			}
403			path += nb;
404			path_len -= nb;
405
406			nb = utf32_to_utf8(uni, out, out_len);
407			if (nb < 0) {
408				__putname(shfl_path);
409				__putname(buf);
410				return ERR_PTR(-ENAMETOOLONG);
411			}
412			out += nb;
413			out_len -= nb;
414		}
415		*out = 0;
416		shfl_path->length = out - shfl_path->string.utf8;
417		shfl_path->size = shfl_path->length + 1;
418		__putname(buf);
419	} else {
420		if ((SHFLSTRING_HEADER_SIZE + path_len + 1) > PATH_MAX) {
421			__putname(buf);
422			return ERR_PTR(-ENAMETOOLONG);
423		}
424		/*
425		 * dentry_path stores the name at the end of buf, but the
426		 * shfl_string string we return must be properly aligned.
427		 */
428		shfl_path = (struct shfl_string *)buf;
429		memmove(shfl_path->string.utf8, path, path_len);
430		shfl_path->string.utf8[path_len] = 0;
431		shfl_path->length = path_len;
432		shfl_path->size = path_len + 1;
433	}
434
435	return shfl_path;
436}
437
438int vboxsf_nlscpy(struct vboxsf_sbi *sbi, char *name, size_t name_bound_len,
439		  const unsigned char *utf8_name, size_t utf8_len)
440{
441	const char *in;
442	char *out;
443	size_t out_len;
444	size_t out_bound_len;
445	size_t in_bound_len;
446
447	in = utf8_name;
448	in_bound_len = utf8_len;
449
450	out = name;
451	out_len = 0;
452	/* Reserve space for terminating 0 */
453	out_bound_len = name_bound_len - 1;
454
455	while (in_bound_len) {
456		int nb;
457		unicode_t uni;
458
459		nb = utf8_to_utf32(in, in_bound_len, &uni);
460		if (nb < 0)
461			return -EINVAL;
462
463		in += nb;
464		in_bound_len -= nb;
465
466		nb = sbi->nls->uni2char(uni, out, out_bound_len);
467		if (nb < 0)
468			return nb;
469
470		out += nb;
471		out_bound_len -= nb;
472		out_len += nb;
473	}
474
475	*out = 0;
476
477	return 0;
478}
479
480static struct vboxsf_dir_buf *vboxsf_dir_buf_alloc(struct list_head *list)
481{
482	struct vboxsf_dir_buf *b;
483
484	b = kmalloc(sizeof(*b), GFP_KERNEL);
485	if (!b)
486		return NULL;
487
488	b->buf = kmalloc(DIR_BUFFER_SIZE, GFP_KERNEL);
489	if (!b->buf) {
490		kfree(b);
491		return NULL;
492	}
493
494	b->entries = 0;
495	b->used = 0;
496	b->free = DIR_BUFFER_SIZE;
497	list_add(&b->head, list);
498
499	return b;
500}
501
502static void vboxsf_dir_buf_free(struct vboxsf_dir_buf *b)
503{
504	list_del(&b->head);
505	kfree(b->buf);
506	kfree(b);
507}
508
509struct vboxsf_dir_info *vboxsf_dir_info_alloc(void)
510{
511	struct vboxsf_dir_info *p;
512
513	p = kmalloc(sizeof(*p), GFP_KERNEL);
514	if (!p)
515		return NULL;
516
517	INIT_LIST_HEAD(&p->info_list);
518	return p;
519}
520
521void vboxsf_dir_info_free(struct vboxsf_dir_info *p)
522{
523	struct list_head *list, *pos, *tmp;
524
525	list = &p->info_list;
526	list_for_each_safe(pos, tmp, list) {
527		struct vboxsf_dir_buf *b;
528
529		b = list_entry(pos, struct vboxsf_dir_buf, head);
530		vboxsf_dir_buf_free(b);
531	}
532	kfree(p);
533}
534
535int vboxsf_dir_read_all(struct vboxsf_sbi *sbi, struct vboxsf_dir_info *sf_d,
536			u64 handle)
537{
538	struct vboxsf_dir_buf *b;
539	u32 entries, size;
540	int err = 0;
541	void *buf;
542
543	/* vboxsf_dirinfo returns 1 on end of dir */
544	while (err == 0) {
545		b = vboxsf_dir_buf_alloc(&sf_d->info_list);
546		if (!b) {
547			err = -ENOMEM;
548			break;
549		}
550
551		buf = b->buf;
552		size = b->free;
553
554		err = vboxsf_dirinfo(sbi->root, handle, NULL, 0, 0,
555				     &size, buf, &entries);
556		if (err < 0)
557			break;
558
559		b->entries += entries;
560		b->free -= size;
561		b->used += size;
562	}
563
564	if (b && b->used == 0)
565		vboxsf_dir_buf_free(b);
566
567	/* -EILSEQ means the host could not translate a filename, ignore */
568	if (err > 0 || err == -EILSEQ)
569		err = 0;
570
571	return err;
572}