Loading...
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, ¶ms);
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, ¶ms);
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}
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, ¶ms);
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, ¶ms);
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_bound_len;
444 size_t in_bound_len;
445
446 in = utf8_name;
447 in_bound_len = utf8_len;
448
449 out = name;
450 /* Reserve space for terminating 0 */
451 out_bound_len = name_bound_len - 1;
452
453 while (in_bound_len) {
454 int nb;
455 unicode_t uni;
456
457 nb = utf8_to_utf32(in, in_bound_len, &uni);
458 if (nb < 0)
459 return -EINVAL;
460
461 in += nb;
462 in_bound_len -= nb;
463
464 nb = sbi->nls->uni2char(uni, out, out_bound_len);
465 if (nb < 0)
466 return nb;
467
468 out += nb;
469 out_bound_len -= nb;
470 }
471
472 *out = 0;
473
474 return 0;
475}
476
477static struct vboxsf_dir_buf *vboxsf_dir_buf_alloc(struct list_head *list)
478{
479 struct vboxsf_dir_buf *b;
480
481 b = kmalloc(sizeof(*b), GFP_KERNEL);
482 if (!b)
483 return NULL;
484
485 b->buf = kmalloc(DIR_BUFFER_SIZE, GFP_KERNEL);
486 if (!b->buf) {
487 kfree(b);
488 return NULL;
489 }
490
491 b->entries = 0;
492 b->used = 0;
493 b->free = DIR_BUFFER_SIZE;
494 list_add(&b->head, list);
495
496 return b;
497}
498
499static void vboxsf_dir_buf_free(struct vboxsf_dir_buf *b)
500{
501 list_del(&b->head);
502 kfree(b->buf);
503 kfree(b);
504}
505
506struct vboxsf_dir_info *vboxsf_dir_info_alloc(void)
507{
508 struct vboxsf_dir_info *p;
509
510 p = kmalloc(sizeof(*p), GFP_KERNEL);
511 if (!p)
512 return NULL;
513
514 INIT_LIST_HEAD(&p->info_list);
515 return p;
516}
517
518void vboxsf_dir_info_free(struct vboxsf_dir_info *p)
519{
520 struct list_head *list, *pos, *tmp;
521
522 list = &p->info_list;
523 list_for_each_safe(pos, tmp, list) {
524 struct vboxsf_dir_buf *b;
525
526 b = list_entry(pos, struct vboxsf_dir_buf, head);
527 vboxsf_dir_buf_free(b);
528 }
529 kfree(p);
530}
531
532int vboxsf_dir_read_all(struct vboxsf_sbi *sbi, struct vboxsf_dir_info *sf_d,
533 u64 handle)
534{
535 struct vboxsf_dir_buf *b;
536 u32 entries, size;
537 int err = 0;
538 void *buf;
539
540 /* vboxsf_dirinfo returns 1 on end of dir */
541 while (err == 0) {
542 b = vboxsf_dir_buf_alloc(&sf_d->info_list);
543 if (!b) {
544 err = -ENOMEM;
545 break;
546 }
547
548 buf = b->buf;
549 size = b->free;
550
551 err = vboxsf_dirinfo(sbi->root, handle, NULL, 0, 0,
552 &size, buf, &entries);
553 if (err < 0)
554 break;
555
556 b->entries += entries;
557 b->free -= size;
558 b->used += size;
559 }
560
561 if (b && b->used == 0)
562 vboxsf_dir_buf_free(b);
563
564 /* -EILSEQ means the host could not translate a filename, ignore */
565 if (err > 0 || err == -EILSEQ)
566 err = 0;
567
568 return err;
569}