VirtualBox

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

Last change on this file since 34869 was 33994, checked in by vboxsync, 14 years ago

shfl: Replaced RTFSOBJINFO and RTFSPROPERTIES with shared folder specific versions. IPRT structures like this should never have been exposed to the guest.

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