VirtualBox

source: vbox/trunk/src/VBox/Additions/solaris/SharedFolders/vboxfs_prov.c@ 76553

Last change on this file since 76553 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 23.4 KB
Line 
1/* $Id: vboxfs_prov.c 76553 2019-01-01 01:45:53Z vboxsync $ */
2/** @file
3 * VirtualBox File System for Solaris Guests, provider implementation.
4 * Portions contributed by: Ronald.
5 */
6
7/*
8 * Copyright (C) 2008-2019 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 *
18 * The contents of this file may alternatively be used under the terms
19 * of the Common Development and Distribution License Version 1.0
20 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
21 * VirtualBox OSE distribution, in which case the provisions of the
22 * CDDL are applicable instead of those of the GPL.
23 *
24 * You may elect to license modified versions of this file under the
25 * terms and conditions of either the GPL or the CDDL or both.
26 */
27
28/*
29 * Provider interfaces for shared folder file system.
30 */
31
32#include <sys/types.h>
33#include <sys/stat.h>
34#include <sys/mntent.h>
35#include <sys/param.h>
36#include <sys/modctl.h>
37#include <sys/mount.h>
38#include <sys/policy.h>
39#include <sys/atomic.h>
40#include <sys/sysmacros.h>
41#include <sys/ddi.h>
42#include <sys/sunddi.h>
43#include <sys/dirent.h>
44#include <sys/file.h>
45#undef u /* /usr/include/sys/user.h:249:1 is where this is defined to (curproc->p_user). very cool. */
46
47#include "vboxfs_prov.h"
48#include <iprt/err.h>
49
50#define SFPROV_VERSION 1
51
52static VBGLSFCLIENT vbox_client;
53
54static int sfprov_vbox2errno(int rc)
55{
56 if (rc == VERR_ACCESS_DENIED)
57 return (EACCES);
58 if (rc == VERR_INVALID_NAME)
59 return (ENOENT);
60 return (RTErrConvertToErrno(rc));
61}
62
63/*
64 * utility to create strings
65 */
66static SHFLSTRING *
67sfprov_string(char *path, int *sz)
68{
69 SHFLSTRING *str;
70 int len = strlen(path);
71
72 *sz = len + 1 + sizeof (*str) - sizeof (str->String);
73 str = kmem_zalloc(*sz, KM_SLEEP);
74 str->u16Size = len + 1;
75 str->u16Length = len;
76 strcpy(str->String.utf8, path);
77 return (str);
78}
79
80sfp_connection_t *
81sfprov_connect(int version)
82{
83 /*
84 * only one version for now, so must match
85 */
86 int rc = -1;
87 if (version != SFPROV_VERSION)
88 {
89 cmn_err(CE_WARN, "sfprov_connect: wrong version. version=%d expected=%d\n", version, SFPROV_VERSION);
90 return NULL;
91 }
92 rc = VbglR0SfInit();
93 if (RT_SUCCESS(rc))
94 {
95 rc = VbglR0SfConnect(&vbox_client);
96 if (RT_SUCCESS(rc))
97 {
98 rc = VbglR0SfSetUtf8(&vbox_client);
99 if (RT_SUCCESS(rc))
100 {
101 return ((sfp_connection_t *)&vbox_client);
102 }
103 else
104 cmn_err(CE_WARN, "sfprov_connect: VbglR0SfSetUtf8() failed\n");
105
106 VbglR0SfDisconnect(&vbox_client);
107 }
108 else
109 cmn_err(CE_WARN, "sfprov_connect: VbglR0SfConnect() failed rc=%d\n", rc);
110 VbglR0SfTerm();
111 }
112 else
113 cmn_err(CE_WARN, "sfprov_connect: VbglR0SfInit() failed rc=%d\n", rc);
114 return (NULL);
115}
116
117void
118sfprov_disconnect(sfp_connection_t *conn)
119{
120 if (conn != (sfp_connection_t *)&vbox_client)
121 cmn_err(CE_WARN, "sfprov_disconnect: bad argument\n");
122 VbglR0SfDisconnect(&vbox_client);
123 VbglR0SfTerm();
124}
125
126
127int
128sfprov_mount(sfp_connection_t *conn, char *path, sfp_mount_t **mnt)
129{
130 sfp_mount_t *m;
131 SHFLSTRING *str;
132 int size;
133 int rc;
134
135 m = kmem_zalloc(sizeof (*m), KM_SLEEP);
136 str = sfprov_string(path, &size);
137 rc = VbglR0SfMapFolder(&vbox_client, str, &m->map);
138 if (RT_FAILURE(rc)) {
139 cmn_err(CE_WARN, "sfprov_mount: VbglR0SfMapFolder() failed. path=%s rc=%d\n", path, rc);
140 kmem_free(m, sizeof (*m));
141 *mnt = NULL;
142 rc = EINVAL;
143 } else {
144 *mnt = m;
145 rc = 0;
146 }
147 kmem_free(str, size);
148 return (rc);
149}
150
151int
152sfprov_unmount(sfp_mount_t *mnt)
153{
154 int rc;
155
156 rc = VbglR0SfUnmapFolder(&vbox_client, &mnt->map);
157 if (RT_FAILURE(rc)) {
158 cmn_err(CE_WARN, "sfprov_mount: VbglR0SfUnmapFolder() failed rc=%d\n", rc);
159 rc = EINVAL;
160 } else {
161 rc = 0;
162 }
163 kmem_free(mnt, sizeof (*mnt));
164 return (rc);
165}
166
167/*
168 * query information about a mounted file system
169 */
170int
171sfprov_get_fsinfo(sfp_mount_t *mnt, sffs_fsinfo_t *fsinfo)
172{
173 int rc;
174 SHFLVOLINFO info;
175 uint32_t bytes = sizeof(SHFLVOLINFO);
176
177 rc = VbglR0SfFsInfo(&vbox_client, &mnt->map, 0, SHFL_INFO_GET | SHFL_INFO_VOLUME,
178 &bytes, (SHFLDIRINFO *)&info);
179 if (RT_FAILURE(rc))
180 return (EINVAL);
181
182 fsinfo->blksize = info.ulBytesPerAllocationUnit;
183 fsinfo->blksused = (info.ullTotalAllocationBytes - info.ullAvailableAllocationBytes) / info.ulBytesPerAllocationUnit;
184 fsinfo->blksavail = info.ullAvailableAllocationBytes / info.ulBytesPerAllocationUnit;
185 fsinfo->maxnamesize = info.fsProperties.cbMaxComponent;
186 fsinfo->readonly = info.fsProperties.fReadOnly;
187 return (0);
188}
189
190/*
191 * file/directory information conversions.
192 */
193static void
194sfprov_fmode_from_mode(RTFMODE *fMode, mode_t mode)
195{
196 RTFMODE m = 0;
197
198#define mode_set(r) ((mode) & (S_##r)) ? RTFS_UNIX_##r : 0
199 m = mode_set (ISUID);
200 m |= mode_set (ISGID);
201 m |= (mode & S_ISVTX) ? RTFS_UNIX_ISTXT : 0;
202
203 m |= mode_set (IRUSR);
204 m |= mode_set (IWUSR);
205 m |= mode_set (IXUSR);
206
207 m |= mode_set (IRGRP);
208 m |= mode_set (IWGRP);
209 m |= mode_set (IXGRP);
210
211 m |= mode_set (IROTH);
212 m |= mode_set (IWOTH);
213 m |= mode_set (IXOTH);
214#undef mode_set
215
216 if (S_ISDIR(mode))
217 m |= RTFS_TYPE_DIRECTORY;
218 else if (S_ISREG(mode))
219 m |= RTFS_TYPE_FILE;
220 else if (S_ISFIFO(mode))
221 m |= RTFS_TYPE_FIFO;
222 else if (S_ISCHR(mode))
223 m |= RTFS_TYPE_DEV_CHAR;
224 else if (S_ISBLK(mode))
225 m |= RTFS_TYPE_DEV_BLOCK;
226 else if (S_ISLNK(mode))
227 m |= RTFS_TYPE_SYMLINK;
228 else if (S_ISSOCK(mode))
229 m |= RTFS_TYPE_SOCKET;
230 else
231 m |= RTFS_TYPE_FILE;
232
233 *fMode = m;
234}
235
236static void
237sfprov_mode_from_fmode(sfp_mount_t *mnt, mode_t *mode, RTFMODE fMode)
238{
239 mode_t m = 0;
240
241#define mode_set_from_rt(r) ((fMode) & (RTFS_UNIX_##r)) ? (S_##r) : 0;
242 m = mode_set_from_rt(ISUID);
243 m |= mode_set_from_rt(ISGID);
244 m |= (fMode & RTFS_UNIX_ISTXT) ? S_ISVTX : 0;
245
246 m |= mode_set_from_rt(IRUSR);
247 m |= mode_set_from_rt(IWUSR);
248 m |= mode_set_from_rt(IXUSR);
249
250 m |= mode_set_from_rt(IRGRP);
251 m |= mode_set_from_rt(IWGRP);
252 m |= mode_set_from_rt(IXGRP);
253
254 m |= mode_set_from_rt(IROTH);
255 m |= mode_set_from_rt(IWOTH);
256 m |= mode_set_from_rt(IXOTH);
257#undef mode_set_from_rt
258
259 if (RTFS_IS_DIRECTORY(fMode))
260 {
261 m = mnt->sf_dmode != ~0U ? (mnt->sf_dmode & PERMMASK) : m;
262 m &= ~mnt->sf_dmask;
263 m |= S_IFDIR;
264 }
265 else
266 {
267 m = mnt->sf_fmode != ~0U ? (mnt->sf_fmode & PERMMASK) : m;
268 m &= ~mnt->sf_fmask;
269
270 if (RTFS_IS_FILE(fMode))
271 m |= S_IFREG;
272 else if (RTFS_IS_SYMLINK(fMode))
273 m |= S_IFLNK;
274 else if (RTFS_IS_FIFO(fMode))
275 m |= S_IFIFO;
276 else if (RTFS_IS_DEV_CHAR(fMode))
277 m |= S_IFCHR;
278 else if (RTFS_IS_DEV_BLOCK(fMode))
279 m |= S_IFBLK;
280 else if (RTFS_IS_SOCKET(fMode))
281 m |= S_IFSOCK;
282 }
283
284 *mode = m;
285}
286
287static void
288sfprov_ftime_from_timespec(timestruc_t *time, RTTIMESPEC *ts)
289{
290 uint64_t nanosec = RTTimeSpecGetNano(ts);
291 time->tv_sec = nanosec / UINT64_C(1000000000);
292 time->tv_nsec = nanosec % UINT64_C(1000000000);
293}
294
295static void
296sfprov_stat_from_info(sfp_mount_t *mnt, sffs_stat_t *stat, SHFLFSOBJINFO *info)
297{
298 sfprov_mode_from_fmode(mnt, &stat->sf_mode, info->Attr.fMode);
299 stat->sf_size = info->cbObject;
300 stat->sf_alloc = info->cbAllocated;
301 sfprov_ftime_from_timespec(&stat->sf_atime, &info->AccessTime);
302 sfprov_ftime_from_timespec(&stat->sf_mtime, &info->ModificationTime);
303 sfprov_ftime_from_timespec(&stat->sf_ctime, &info->ChangeTime);
304}
305
306/*
307 * File operations: open/close/read/write/etc.
308 *
309 * open/create can return any relevant errno, however ENOENT
310 * generally means that the host file didn't exist.
311 */
312struct sfp_file {
313 SHFLHANDLE handle;
314 VBGLSFMAP map; /**< need this again for the close operation */
315};
316
317int
318sfprov_create(
319 sfp_mount_t *mnt,
320 char *path,
321 mode_t mode,
322 sfp_file_t **fp,
323 sffs_stat_t *stat)
324{
325
326 int rc;
327 SHFLCREATEPARMS parms;
328 SHFLSTRING *str;
329 int size;
330 sfp_file_t *newfp;
331
332 str = sfprov_string(path, &size);
333 parms.Handle = SHFL_HANDLE_NIL;
334 parms.Info.cbObject = 0;
335 sfprov_fmode_from_mode(&parms.Info.Attr.fMode, mode);
336 parms.CreateFlags = SHFL_CF_ACT_CREATE_IF_NEW |
337 SHFL_CF_ACT_REPLACE_IF_EXISTS | SHFL_CF_ACCESS_READWRITE;
338 rc = VbglR0SfCreate(&vbox_client, &mnt->map, str, &parms);
339 kmem_free(str, size);
340
341 if (RT_FAILURE(rc))
342 {
343 if (rc != VERR_ACCESS_DENIED && rc != VERR_WRITE_PROTECT)
344 cmn_err(CE_WARN, "sfprov_create: VbglR0SfCreate failed! path=%s rc=%d\n", path, rc);
345 return (sfprov_vbox2errno(rc));
346 }
347 if (parms.Handle == SHFL_HANDLE_NIL) {
348 if (parms.Result == SHFL_FILE_EXISTS)
349 return (EEXIST);
350 return (ENOENT);
351 }
352 newfp = kmem_alloc(sizeof(sfp_file_t), KM_SLEEP);
353 newfp->handle = parms.Handle;
354 newfp->map = mnt->map;
355 *fp = newfp;
356 sfprov_stat_from_info(mnt, stat, &parms.Info);
357 return (0);
358}
359
360int
361sfprov_diropen(sfp_mount_t *mnt, char *path, sfp_file_t **fp)
362{
363 int rc;
364 SHFLCREATEPARMS parms;
365 SHFLSTRING *str;
366 int size;
367 sfp_file_t *newfp;
368
369 bzero(&parms, sizeof(parms));
370 str = sfprov_string(path, &size);
371 parms.Handle = SHFL_HANDLE_NIL;
372 parms.Info.cbObject = 0;
373 parms.CreateFlags = SHFL_CF_DIRECTORY
374 | SHFL_CF_ACCESS_READ
375 | SHFL_CF_ACT_OPEN_IF_EXISTS
376 | SHFL_CF_ACT_FAIL_IF_NEW;
377
378 /*
379 * Open the host directory.
380 */
381 rc = VbglR0SfCreate(&vbox_client, &mnt->map, str, &parms);
382
383 /*
384 * Our VBoxFS interface here isn't very clear regarding failure and informational status.
385 * Check the file-handle as well as the return code to make sure the operation succeeded.
386 */
387 if (RT_FAILURE(rc)) {
388 kmem_free(str, size);
389 return (sfprov_vbox2errno(rc));
390 }
391
392 if (parms.Handle == SHFL_HANDLE_NIL) {
393 kmem_free(str, size);
394 return (ENOENT);
395 }
396
397 newfp = kmem_alloc(sizeof(sfp_file_t), KM_SLEEP);
398 newfp->handle = parms.Handle;
399 newfp->map = mnt->map;
400 *fp = newfp;
401 return (0);
402}
403
404int
405sfprov_open(sfp_mount_t *mnt, char *path, sfp_file_t **fp, int flag)
406{
407 int rc;
408 SHFLCREATEPARMS parms;
409 SHFLSTRING *str;
410 int size;
411 sfp_file_t *newfp;
412
413 bzero(&parms, sizeof(parms));
414 str = sfprov_string(path, &size);
415 parms.Handle = SHFL_HANDLE_NIL;
416 parms.Info.cbObject = 0;
417
418 /*
419 * Translate file modes.
420 */
421 if (flag & FCREAT) {
422 parms.CreateFlags |= SHFL_CF_ACT_CREATE_IF_NEW;
423 if (!(flag & FTRUNC))
424 parms.CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS;
425 }
426 else
427 parms.CreateFlags |= SHFL_CF_ACT_FAIL_IF_NEW;
428
429 if (flag & FTRUNC)
430 parms.CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS | SHFL_CF_ACCESS_WRITE;
431 if (flag & FWRITE)
432 parms.CreateFlags |= SHFL_CF_ACCESS_WRITE;
433 if (flag & FREAD)
434 parms.CreateFlags |= SHFL_CF_ACCESS_READ;
435 if (flag & FAPPEND)
436 parms.CreateFlags |= SHFL_CF_ACCESS_APPEND;
437
438 /*
439 * Open/create the host file.
440 */
441 rc = VbglR0SfCreate(&vbox_client, &mnt->map, str, &parms);
442
443 /*
444 * Our VBoxFS interface here isn't very clear regarding failure and informational status.
445 * Check the file-handle as well as the return code to make sure the operation succeeded.
446 */
447 if (RT_FAILURE(rc)) {
448 kmem_free(str, size);
449 return (sfprov_vbox2errno(rc));
450 }
451
452 if (parms.Handle == SHFL_HANDLE_NIL) {
453 kmem_free(str, size);
454 return (ENOENT);
455 }
456
457 newfp = kmem_alloc(sizeof(sfp_file_t), KM_SLEEP);
458 newfp->handle = parms.Handle;
459 newfp->map = mnt->map;
460 *fp = newfp;
461 return (0);
462}
463
464int
465sfprov_close(sfp_file_t *fp)
466{
467 int rc;
468
469 rc = VbglR0SfClose(&vbox_client, &fp->map, fp->handle);
470 kmem_free(fp, sizeof(sfp_file_t));
471 return (0);
472}
473
474int
475sfprov_read(sfp_file_t *fp, char *buffer, uint64_t offset, uint32_t *numbytes)
476{
477 int rc;
478
479 rc = VbglR0SfRead(&vbox_client, &fp->map, fp->handle, offset,
480 numbytes, (uint8_t *)buffer, 0 /*fLocked*/);
481 if (RT_FAILURE(rc))
482 return (EINVAL);
483 return (0);
484}
485
486int
487sfprov_write(sfp_file_t *fp, char *buffer, uint64_t offset, uint32_t *numbytes)
488{
489 int rc;
490
491 rc = VbglR0SfWrite(&vbox_client, &fp->map, fp->handle, offset,
492 numbytes, (uint8_t *)buffer, 0 /*fLocked*/);
493 if (RT_FAILURE(rc))
494 return (EINVAL);
495 return (0);
496}
497
498int
499sfprov_fsync(sfp_file_t *fp)
500{
501 int rc;
502
503 rc = VbglR0SfFlush(&vbox_client, &fp->map, fp->handle);
504 if (RT_FAILURE(rc))
505 return (EIO);
506 return (0);
507}
508
509
510static int
511sfprov_getinfo(sfp_mount_t *mnt, char *path, PSHFLFSOBJINFO info)
512{
513 int rc;
514 SHFLCREATEPARMS parms;
515 SHFLSTRING *str;
516 int size;
517
518 str = sfprov_string(path, &size);
519 parms.Handle = 0;
520 parms.Info.cbObject = 0;
521 parms.CreateFlags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW;
522 rc = VbglR0SfCreate(&vbox_client, &mnt->map, str, &parms);
523 kmem_free(str, size);
524
525 if (RT_FAILURE(rc))
526 return (EINVAL);
527 if (parms.Result != SHFL_FILE_EXISTS)
528 return (ENOENT);
529 *info = parms.Info;
530 return (0);
531}
532
533/*
534 * get information about a file (or directory)
535 */
536int
537sfprov_get_mode(sfp_mount_t *mnt, char *path, mode_t *mode)
538{
539 int rc;
540 SHFLFSOBJINFO info;
541
542 rc = sfprov_getinfo(mnt, path, &info);
543 if (rc)
544 return (rc);
545 sfprov_mode_from_fmode(mnt, mode, info.Attr.fMode);
546 return (0);
547}
548
549int
550sfprov_get_size(sfp_mount_t *mnt, char *path, uint64_t *size)
551{
552 int rc;
553 SHFLFSOBJINFO info;
554
555 rc = sfprov_getinfo(mnt, path, &info);
556 if (rc)
557 return (rc);
558 *size = info.cbObject;
559 return (0);
560}
561
562
563int
564sfprov_get_atime(sfp_mount_t *mnt, char *path, timestruc_t *time)
565{
566 int rc;
567 SHFLFSOBJINFO info;
568
569 rc = sfprov_getinfo(mnt, path, &info);
570 if (rc)
571 return (rc);
572 sfprov_ftime_from_timespec(time, &info.AccessTime);
573 return (0);
574}
575
576int
577sfprov_get_mtime(sfp_mount_t *mnt, char *path, timestruc_t *time)
578{
579 int rc;
580 SHFLFSOBJINFO info;
581
582 rc = sfprov_getinfo(mnt, path, &info);
583 if (rc)
584 return (rc);
585 sfprov_ftime_from_timespec(time, &info.ModificationTime);
586 return (0);
587}
588
589int
590sfprov_get_ctime(sfp_mount_t *mnt, char *path, timestruc_t *time)
591{
592 int rc;
593 SHFLFSOBJINFO info;
594
595 rc = sfprov_getinfo(mnt, path, &info);
596 if (rc)
597 return (rc);
598 sfprov_ftime_from_timespec(time, &info.ChangeTime);
599 return (0);
600}
601
602int
603sfprov_get_attr(sfp_mount_t *mnt, char *path, sffs_stat_t *attr)
604{
605 int rc;
606 SHFLFSOBJINFO info;
607
608 rc = sfprov_getinfo(mnt, path, &info);
609 if (rc)
610 return (rc);
611 sfprov_stat_from_info(mnt, attr, &info);
612 return (0);
613}
614
615static void
616sfprov_timespec_from_ftime(RTTIMESPEC *ts, timestruc_t time)
617{
618 uint64_t nanosec = UINT64_C(1000000000) * time.tv_sec + time.tv_nsec;
619 RTTimeSpecSetNano(ts, nanosec);
620}
621
622int
623sfprov_set_attr(
624 sfp_mount_t *mnt,
625 char *path,
626 uint_t mask,
627 mode_t mode,
628 timestruc_t atime,
629 timestruc_t mtime,
630 timestruc_t ctime)
631{
632 int rc, err;
633 SHFLCREATEPARMS parms;
634 SHFLSTRING *str;
635 SHFLFSOBJINFO info;
636 uint32_t bytes;
637 int str_size;
638
639 str = sfprov_string(path, &str_size);
640 parms.Handle = 0;
641 parms.Info.cbObject = 0;
642 parms.CreateFlags = SHFL_CF_ACT_OPEN_IF_EXISTS
643 | SHFL_CF_ACT_FAIL_IF_NEW
644 | SHFL_CF_ACCESS_ATTR_WRITE;
645
646 rc = VbglR0SfCreate(&vbox_client, &mnt->map, str, &parms);
647
648 if (RT_FAILURE(rc)) {
649 cmn_err(CE_WARN, "sfprov_set_attr: VbglR0SfCreate(%s) failed rc=%d\n",
650 path, rc);
651 err = EINVAL;
652 goto fail2;
653 }
654 if (parms.Result != SHFL_FILE_EXISTS) {
655 err = ENOENT;
656 goto fail1;
657 }
658
659 RT_ZERO(info);
660 if (mask & AT_MODE)
661 sfprov_fmode_from_mode(&info.Attr.fMode, mode);
662 if (mask & AT_ATIME)
663 sfprov_timespec_from_ftime(&info.AccessTime, atime);
664 if (mask & AT_MTIME)
665 sfprov_timespec_from_ftime(&info.ModificationTime, mtime);
666 if (mask & AT_CTIME)
667 sfprov_timespec_from_ftime(&info.ChangeTime, ctime);
668
669 bytes = sizeof(info);
670 rc = VbglR0SfFsInfo(&vbox_client, &mnt->map, parms.Handle, SHFL_INFO_SET | SHFL_INFO_FILE,
671 &bytes, (SHFLDIRINFO *)&info);
672 if (RT_FAILURE(rc)) {
673 if (rc != VERR_ACCESS_DENIED && rc != VERR_WRITE_PROTECT)
674 {
675 cmn_err(CE_WARN, "sfprov_set_attr: VbglR0SfFsInfo(%s, FILE) failed rc=%d\n",
676 path, rc);
677 }
678 err = sfprov_vbox2errno(rc);
679 goto fail1;
680 }
681
682 err = 0;
683
684fail1:
685 rc = VbglR0SfClose(&vbox_client, &mnt->map, parms.Handle);
686 if (RT_FAILURE(rc)) {
687 cmn_err(CE_WARN, "sfprov_set_attr: VbglR0SfClose(%s) failed rc=%d\n",
688 path, rc);
689 }
690fail2:
691 kmem_free(str, str_size);
692 return err;
693}
694
695int
696sfprov_set_size(sfp_mount_t *mnt, char *path, uint64_t size)
697{
698 int rc, err;
699 SHFLCREATEPARMS parms;
700 SHFLSTRING *str;
701 SHFLFSOBJINFO info;
702 uint32_t bytes;
703 int str_size;
704
705 str = sfprov_string(path, &str_size);
706 parms.Handle = 0;
707 parms.Info.cbObject = 0;
708 parms.CreateFlags = SHFL_CF_ACT_OPEN_IF_EXISTS
709 | SHFL_CF_ACT_FAIL_IF_NEW
710 | SHFL_CF_ACCESS_WRITE;
711
712 rc = VbglR0SfCreate(&vbox_client, &mnt->map, str, &parms);
713
714 if (RT_FAILURE(rc)) {
715 cmn_err(CE_WARN, "sfprov_set_size: VbglR0SfCreate(%s) failed rc=%d\n",
716 path, rc);
717 err = EINVAL;
718 goto fail2;
719 }
720 if (parms.Result != SHFL_FILE_EXISTS) {
721 err = ENOENT;
722 goto fail1;
723 }
724
725 RT_ZERO(info);
726 info.cbObject = size;
727 bytes = sizeof(info);
728 rc = VbglR0SfFsInfo(&vbox_client, &mnt->map, parms.Handle, SHFL_INFO_SET | SHFL_INFO_SIZE,
729 &bytes, (SHFLDIRINFO *)&info);
730 if (RT_FAILURE(rc)) {
731 cmn_err(CE_WARN, "sfprov_set_size: VbglR0SfFsInfo(%s, SIZE) failed rc=%d\n",
732 path, rc);
733 err = sfprov_vbox2errno(rc);
734 goto fail1;
735 }
736
737 err = 0;
738
739fail1:
740 rc = VbglR0SfClose(&vbox_client, &mnt->map, parms.Handle);
741 if (RT_FAILURE(rc)) {
742 cmn_err(CE_WARN, "sfprov_set_size: VbglR0SfClose(%s) failed rc=%d\n",
743 path, rc);
744 }
745fail2:
746 kmem_free(str, str_size);
747 return err;
748}
749
750/*
751 * Directory operations
752 */
753int
754sfprov_mkdir(
755 sfp_mount_t *mnt,
756 char *path,
757 mode_t mode,
758 sfp_file_t **fp,
759 sffs_stat_t *stat)
760{
761 int rc;
762 SHFLCREATEPARMS parms;
763 SHFLSTRING *str;
764 int size;
765 sfp_file_t *newfp;
766
767 str = sfprov_string(path, &size);
768 parms.Handle = SHFL_HANDLE_NIL;
769 parms.Info.cbObject = 0;
770 sfprov_fmode_from_mode(&parms.Info.Attr.fMode, mode);
771 parms.CreateFlags = SHFL_CF_DIRECTORY | SHFL_CF_ACT_CREATE_IF_NEW |
772 SHFL_CF_ACT_FAIL_IF_EXISTS | SHFL_CF_ACCESS_READ;
773 rc = VbglR0SfCreate(&vbox_client, &mnt->map, str, &parms);
774 kmem_free(str, size);
775
776 if (RT_FAILURE(rc))
777 return (sfprov_vbox2errno(rc));
778 if (parms.Handle == SHFL_HANDLE_NIL) {
779 if (parms.Result == SHFL_FILE_EXISTS)
780 return (EEXIST);
781 return (ENOENT);
782 }
783 newfp = kmem_alloc(sizeof(sfp_file_t), KM_SLEEP);
784 newfp->handle = parms.Handle;
785 newfp->map = mnt->map;
786 *fp = newfp;
787 sfprov_stat_from_info(mnt, stat, &parms.Info);
788 return (0);
789}
790
791int
792sfprov_set_show_symlinks(void)
793{
794 int rc;
795
796 rc = VbglR0SfSetSymlinks(&vbox_client);
797 if (RT_FAILURE(rc))
798 return (sfprov_vbox2errno(rc));
799
800 return (0);
801}
802
803int
804sfprov_remove(sfp_mount_t *mnt, char *path, uint_t is_link)
805{
806 int rc;
807 SHFLSTRING *str;
808 int size;
809
810 str = sfprov_string(path, &size);
811 rc = VbglR0SfRemove(&vbox_client, &mnt->map, str,
812 SHFL_REMOVE_FILE | (is_link ? SHFL_REMOVE_SYMLINK : 0));
813 kmem_free(str, size);
814 if (RT_FAILURE(rc))
815 return (sfprov_vbox2errno(rc));
816 return (0);
817}
818
819int
820sfprov_readlink(
821 sfp_mount_t *mnt,
822 char *path,
823 char *target,
824 size_t tgt_size)
825{
826 int rc;
827 SHFLSTRING *str;
828 int size;
829
830 str = sfprov_string(path, &size);
831
832 rc = VbglR0SfReadLink(&vbox_client, &mnt->map, str, (uint32_t) tgt_size,
833 target);
834 if (RT_FAILURE(rc))
835 rc = sfprov_vbox2errno(rc);
836
837 kmem_free(str, size);
838 return (rc);
839}
840
841int
842sfprov_symlink(
843 sfp_mount_t *mnt,
844 char *linkname,
845 char *target,
846 sffs_stat_t *stat)
847{
848 int rc;
849 SHFLSTRING *lnk, *tgt;
850 int lnk_size, tgt_size;
851 SHFLFSOBJINFO info;
852
853 lnk = sfprov_string(linkname, &lnk_size);
854 tgt = sfprov_string(target, &tgt_size);
855
856 rc = VbglR0SfSymlink(&vbox_client, &mnt->map, lnk, tgt, &info);
857 if (RT_FAILURE(rc)) {
858 rc = sfprov_vbox2errno(rc);
859 goto done;
860 }
861
862 if (stat != NULL)
863 sfprov_stat_from_info(mnt, stat, &info);
864
865done:
866 kmem_free(lnk, lnk_size);
867 kmem_free(tgt, tgt_size);
868
869 return (rc);
870}
871
872int
873sfprov_rmdir(sfp_mount_t *mnt, char *path)
874{
875 int rc;
876 SHFLSTRING *str;
877 int size;
878
879 str = sfprov_string(path, &size);
880 rc = VbglR0SfRemove(&vbox_client, &mnt->map, str, SHFL_REMOVE_DIR);
881 kmem_free(str, size);
882 if (RT_FAILURE(rc))
883 return (sfprov_vbox2errno(rc));
884 return (0);
885}
886
887int
888sfprov_rename(sfp_mount_t *mnt, char *from, char *to, uint_t is_dir)
889{
890 int rc;
891 SHFLSTRING *old, *new;
892 int old_size, new_size;
893
894 old = sfprov_string(from, &old_size);
895 new = sfprov_string(to, &new_size);
896 rc = VbglR0SfRename(&vbox_client, &mnt->map, old, new,
897 (is_dir ? SHFL_RENAME_DIR : SHFL_RENAME_FILE) | SHFL_RENAME_REPLACE_IF_EXISTS);
898 kmem_free(old, old_size);
899 kmem_free(new, new_size);
900 if (RT_FAILURE(rc))
901 return (sfprov_vbox2errno(rc));
902 return (0);
903}
904
905
906/*
907 * Read all filenames in a directory.
908 *
909 * - success - all entries read and returned
910 * - ENOENT - Couldn't open the directory for reading
911 * - EINVAL - Internal error of some kind
912 *
913 * On successful return, *dirents points to a list of sffs_dirents_t;
914 * for each dirent, all fields except the d_ino will be set appropriately.
915 * The caller is responsible for freeing the dirents buffer.
916 */
917int
918sfprov_readdir(
919 sfp_mount_t *mnt,
920 char *path,
921 sffs_dirents_t **dirents,
922 int flag)
923{
924 int error;
925 char *cp;
926 int len;
927 SHFLSTRING *mask_str = NULL; /* must be path with "/ *" appended */
928 int mask_size;
929 sfp_file_t *fp;
930 uint32_t infobuff_alloc = 16384;
931 SHFLDIRINFO *infobuff = NULL, *info;
932 uint32_t numbytes;
933 uint32_t nents;
934 uint32_t size;
935 off_t offset;
936 sffs_dirents_t *cur_buf;
937 struct sffs_dirent *dirent;
938 unsigned short reclen;
939 unsigned short entlen;
940
941 *dirents = NULL;
942
943 error = sfprov_diropen(mnt, path, &fp);
944 if (error != 0)
945 return (ENOENT);
946
947 /*
948 * Allocate the first dirents buffers.
949 */
950 *dirents = kmem_alloc(SFFS_DIRENTS_SIZE, KM_SLEEP);
951 if (*dirents == NULL) {
952 error = (ENOSPC);
953 goto done;
954 }
955 cur_buf = *dirents;
956 cur_buf->sf_next = NULL;
957 cur_buf->sf_len = 0;
958
959 /*
960 * Create mask that VBox expects. This needs to be the directory path,
961 * plus a "*" wildcard to get all files.
962 */
963 len = strlen(path) + 3;
964 cp = kmem_alloc(len, KM_SLEEP);
965 if (cp == NULL) {
966 error = (ENOSPC);
967 goto done;
968 }
969 strcpy(cp, path);
970 strcat(cp, "/*");
971 mask_str = sfprov_string(cp, &mask_size);
972 kmem_free(cp, len);
973
974 /*
975 * Now loop using VbglR0SfDirInfo
976 */
977 infobuff = kmem_alloc(infobuff_alloc, KM_SLEEP);
978 if (infobuff == NULL) {
979 error = (ENOSPC);
980 goto done;
981 }
982
983 offset = 0;
984 for (;;) {
985 numbytes = infobuff_alloc;
986 error = VbglR0SfDirInfo(&vbox_client, &fp->map, fp->handle,
987 mask_str, 0, 0, &numbytes, infobuff, &nents);
988 switch (error) {
989
990 case VINF_SUCCESS:
991 /* fallthrough */
992 case VERR_NO_MORE_FILES:
993 break;
994
995 case VERR_NO_TRANSLATION:
996 /* XXX ??? */
997 break;
998
999 default:
1000 error = sfprov_vbox2errno(error);
1001 goto done;
1002 }
1003
1004 /*
1005 * Create the dirent_t's and save the stats for each name
1006 */
1007 for (info = infobuff; (char *) info < (char *) infobuff + numbytes; nents--) {
1008 /* expand buffers if we need more space */
1009 reclen = DIRENT64_RECLEN(strlen(info->name.String.utf8));
1010 entlen = sizeof(sffs_stat_t) + reclen;
1011 if (SFFS_DIRENTS_OFF + cur_buf->sf_len + entlen > SFFS_DIRENTS_SIZE) {
1012 cur_buf->sf_next = kmem_alloc(SFFS_DIRENTS_SIZE, KM_SLEEP);
1013 if (cur_buf->sf_next == NULL) {
1014 error = ENOSPC;
1015 goto done;
1016 }
1017 cur_buf = cur_buf->sf_next;
1018 cur_buf->sf_next = NULL;
1019 cur_buf->sf_len = 0;
1020 }
1021
1022 /* create the dirent with the name, offset, and len */
1023 dirent = (struct sffs_dirent *)
1024 (((char *) &cur_buf->sf_entries[0]) + cur_buf->sf_len);
1025 strncpy(&dirent->sf_entry.d_name[0], info->name.String.utf8, DIRENT64_NAMELEN(reclen));
1026 dirent->sf_entry.d_reclen = reclen;
1027 offset += entlen;
1028 dirent->sf_entry.d_off = offset;
1029
1030 /* save the stats */
1031 sfprov_stat_from_info(mnt, &dirent->sf_stat, &info->Info);
1032
1033 /* next info */
1034 cur_buf->sf_len += entlen;
1035 size = offsetof (SHFLDIRINFO, name.String) + info->name.u16Size;
1036 info = (SHFLDIRINFO *) ((uintptr_t) info + size);
1037 }
1038 ASSERT(nents == 0);
1039 ASSERT((char *) info == (char *) infobuff + numbytes);
1040
1041 if (error == VERR_NO_MORE_FILES)
1042 break;
1043 }
1044 error = 0;
1045
1046done:
1047 if (error != 0) {
1048 while (*dirents) {
1049 cur_buf = (*dirents)->sf_next;
1050 kmem_free(*dirents, SFFS_DIRENTS_SIZE);
1051 *dirents = cur_buf;
1052 }
1053 }
1054 if (infobuff != NULL)
1055 kmem_free(infobuff, infobuff_alloc);
1056 if (mask_str != NULL)
1057 kmem_free(mask_str, mask_size);
1058 sfprov_close(fp);
1059 return (error);
1060}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette