VirtualBox

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

Last change on this file since 61888 was 58203, checked in by vboxsync, 9 years ago

VBoxGuestR0LibSharedFolders.h: Moved from VBoxGuestLib to include/VBox/VBoxGuestLibSharedFolders.h where it belongs (not merging it into VBoxGuestLib.h because it includes VBox/shflsvc.h.

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