VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedFolders/mappings.cpp@ 31002

Last change on this file since 31002 was 31002, checked in by vboxsync, 15 years ago

First support for auto-mounted Shared Folders (Windows only yet).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.1 KB
Line 
1/** @file
2 * Shared Folders: Mappings support.
3 */
4
5/*
6 * Copyright (C) 2006-2007 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 */
16
17#include "mappings.h"
18#include <iprt/alloc.h>
19#include <iprt/assert.h>
20#include <iprt/string.h>
21
22/* Shared folders order in the saved state and in the FolderMapping can differ.
23 * So a translation array of root handle is needed.
24 */
25
26static MAPPING FolderMapping[SHFL_MAX_MAPPINGS];
27static SHFLROOT aIndexFromRoot[SHFL_MAX_MAPPINGS];
28
29void vbsfMappingInit(void)
30{
31 unsigned root;
32
33 for (root = 0; root < RT_ELEMENTS(aIndexFromRoot); root++)
34 {
35 aIndexFromRoot[root] = SHFL_ROOT_NIL;
36 }
37}
38
39int vbsfMappingLoaded (const MAPPING *pLoadedMapping, SHFLROOT root)
40{
41 /* Mapping loaded from the saved state with the index. Which means
42 * the guest uses the iMapping as root handle for this folder.
43 * Check whether there is the same mapping in FolderMapping and
44 * update the aIndexFromRoot.
45 *
46 * Also update the mapping properties, which were lost: cMappings.
47 */
48 if (root >= SHFL_MAX_MAPPINGS)
49 {
50 return VERR_INVALID_PARAMETER;
51 }
52
53 SHFLROOT i;
54 for (i = 0; i < RT_ELEMENTS(FolderMapping); i++)
55 {
56 MAPPING *pMapping = &FolderMapping[i];
57
58 /* Equal? */
59 if ( pLoadedMapping->fValid == pMapping->fValid
60 && ShflStringSizeOfBuffer(pLoadedMapping->pMapName) == ShflStringSizeOfBuffer(pMapping->pMapName)
61 && memcmp(pLoadedMapping->pMapName, pMapping->pMapName, ShflStringSizeOfBuffer(pMapping->pMapName)) == 0)
62 {
63 /* Actual index is i. */
64 aIndexFromRoot[root] = i;
65
66 /* Update the mapping properties. */
67 pMapping->cMappings = pLoadedMapping->cMappings;
68
69 return VINF_SUCCESS;
70 }
71 }
72
73 return VERR_INVALID_PARAMETER;
74}
75
76MAPPING *vbsfMappingGetByRoot(SHFLROOT root)
77{
78 if (root < RT_ELEMENTS(aIndexFromRoot))
79 {
80 SHFLROOT iMapping = aIndexFromRoot[root];
81
82 if ( iMapping != SHFL_ROOT_NIL
83 && iMapping < RT_ELEMENTS(FolderMapping))
84 {
85 return &FolderMapping[iMapping];
86 }
87 }
88
89 return NULL;
90}
91
92static SHFLROOT vbsfMappingGetRootFromIndex(SHFLROOT iMapping)
93{
94 unsigned root;
95
96 for (root = 0; root < RT_ELEMENTS(aIndexFromRoot); root++)
97 {
98 if (iMapping == aIndexFromRoot[root])
99 {
100 return root;
101 }
102 }
103
104 return SHFL_ROOT_NIL;
105}
106
107static MAPPING *vbsfMappingGetByName (PRTUTF16 utf16Name, SHFLROOT *pRoot)
108{
109 unsigned i;
110
111 for (i=0; i<SHFL_MAX_MAPPINGS; i++)
112 {
113 if (FolderMapping[i].fValid == true)
114 {
115 if (!RTUtf16LocaleICmp(FolderMapping[i].pMapName->String.ucs2, utf16Name))
116 {
117 SHFLROOT root = vbsfMappingGetRootFromIndex(i);
118
119 if (root != SHFL_ROOT_NIL)
120 {
121 if (pRoot)
122 {
123 *pRoot = root;
124 }
125 return &FolderMapping[i];
126 }
127 else
128 {
129 AssertFailed();
130 }
131 }
132 }
133 }
134
135 return NULL;
136}
137
138static void vbsfRootHandleAdd(SHFLROOT iMapping)
139{
140 unsigned root;
141
142 for (root = 0; root < RT_ELEMENTS(aIndexFromRoot); root++)
143 {
144 if (aIndexFromRoot[root] == SHFL_ROOT_NIL)
145 {
146 aIndexFromRoot[root] = iMapping;
147 return;
148 }
149 }
150
151 AssertFailed();
152}
153
154static void vbsfRootHandleRemove(SHFLROOT iMapping)
155{
156 unsigned root;
157
158 for (root = 0; root < RT_ELEMENTS(aIndexFromRoot); root++)
159 {
160 if (aIndexFromRoot[root] == iMapping)
161 {
162 aIndexFromRoot[root] = SHFL_ROOT_NIL;
163 return;
164 }
165 }
166
167 AssertFailed();
168}
169
170
171
172/*
173 * We are always executed from one specific HGCM thread. So thread safe.
174 */
175int vbsfMappingsAdd (PSHFLSTRING pFolderName, PSHFLSTRING pMapName,
176 uint32_t fWritable, uint32_t fAutoMount)
177{
178 unsigned i;
179
180 Assert(pFolderName && pMapName);
181
182 Log(("vbsfMappingsAdd %ls\n", pMapName->String.ucs2));
183
184 /* check for duplicates */
185 for (i=0; i<SHFL_MAX_MAPPINGS; i++)
186 {
187 if (FolderMapping[i].fValid == true)
188 {
189 if (!RTUtf16LocaleICmp(FolderMapping[i].pMapName->String.ucs2, pMapName->String.ucs2))
190 {
191 AssertMsgFailed(("vbsfMappingsAdd: %ls mapping already exists!!\n", pMapName->String.ucs2));
192 return VERR_ALREADY_EXISTS;
193 }
194 }
195 }
196
197 for (i=0; i<SHFL_MAX_MAPPINGS; i++)
198 {
199 if (FolderMapping[i].fValid == false)
200 {
201 FolderMapping[i].pFolderName = (PSHFLSTRING)RTMemAlloc(ShflStringSizeOfBuffer(pFolderName));
202 Assert(FolderMapping[i].pFolderName);
203 if (FolderMapping[i].pFolderName == NULL)
204 return VERR_NO_MEMORY;
205
206 FolderMapping[i].pFolderName->u16Length = pFolderName->u16Length;
207 FolderMapping[i].pFolderName->u16Size = pFolderName->u16Size;
208 memcpy(FolderMapping[i].pFolderName->String.ucs2, pFolderName->String.ucs2, pFolderName->u16Size);
209
210 FolderMapping[i].pMapName = (PSHFLSTRING)RTMemAlloc(ShflStringSizeOfBuffer(pMapName));
211 Assert(FolderMapping[i].pMapName);
212 if (FolderMapping[i].pMapName == NULL)
213 return VERR_NO_MEMORY;
214
215 FolderMapping[i].pMapName->u16Length = pMapName->u16Length;
216 FolderMapping[i].pMapName->u16Size = pMapName->u16Size;
217 memcpy(FolderMapping[i].pMapName->String.ucs2, pMapName->String.ucs2, pMapName->u16Size);
218
219 FolderMapping[i].fValid = true;
220 FolderMapping[i].cMappings = 0;
221 FolderMapping[i].fWritable = !!fWritable;
222 FolderMapping[i].fAutoMount = !!fAutoMount;
223
224 /* Check if the host file system is case sensitive */
225 RTFSPROPERTIES prop;
226 char *utf8Root, *asciiroot;
227
228 int rc = RTUtf16ToUtf8(FolderMapping[i].pFolderName->String.ucs2, &utf8Root);
229 AssertRC(rc);
230
231 if (RT_SUCCESS(rc))
232 {
233 rc = RTStrUtf8ToCurrentCP(&asciiroot, utf8Root);
234 if (RT_SUCCESS(rc))
235 {
236 rc = RTFsQueryProperties(asciiroot, &prop);
237 AssertRC(rc);
238 RTStrFree(asciiroot);
239 }
240 RTStrFree(utf8Root);
241 }
242 FolderMapping[i].fHostCaseSensitive = RT_SUCCESS(rc) ? prop.fCaseSensitive : false;
243 vbsfRootHandleAdd(i);
244 break;
245 }
246 }
247 if (i == SHFL_MAX_MAPPINGS)
248 {
249 AssertMsgFailed(("vbsfMappingsAdd: no more room to add mapping %ls to %ls!!\n", pFolderName->String.ucs2, pMapName->String.ucs2));
250 return VERR_TOO_MUCH_DATA;
251 }
252
253 Log(("vbsfMappingsAdd: added mapping %ls to %ls\n", pFolderName->String.ucs2, pMapName->String.ucs2));
254 return VINF_SUCCESS;
255}
256
257int vbsfMappingsRemove (PSHFLSTRING pMapName)
258{
259 unsigned i;
260
261 Assert(pMapName);
262
263 Log(("vbsfMappingsRemove %ls\n", pMapName->String.ucs2));
264 for (i=0; i<SHFL_MAX_MAPPINGS; i++)
265 {
266 if (FolderMapping[i].fValid == true)
267 {
268 if (!RTUtf16LocaleICmp(FolderMapping[i].pMapName->String.ucs2, pMapName->String.ucs2))
269 {
270 if (FolderMapping[i].cMappings != 0)
271 {
272 Log(("vbsfMappingsRemove: trying to remove active share %ls\n", pMapName->String.ucs2));
273 return VERR_PERMISSION_DENIED;
274 }
275
276 RTMemFree(FolderMapping[i].pFolderName);
277 RTMemFree(FolderMapping[i].pMapName);
278 FolderMapping[i].pFolderName = NULL;
279 FolderMapping[i].pMapName = NULL;
280 FolderMapping[i].fValid = false;
281 vbsfRootHandleRemove(i);
282 break;
283 }
284 }
285 }
286
287 if (i == SHFL_MAX_MAPPINGS)
288 {
289 AssertMsgFailed(("vbsfMappingsRemove: mapping %ls not found!!!!\n", pMapName->String.ucs2));
290 return VERR_FILE_NOT_FOUND;
291 }
292 Log(("vbsfMappingsRemove: mapping %ls removed\n", pMapName->String.ucs2));
293 return VINF_SUCCESS;
294}
295
296PCRTUTF16 vbsfMappingsQueryHostRoot (SHFLROOT root, uint32_t *pcbRoot)
297{
298 MAPPING *pFolderMapping = vbsfMappingGetByRoot(root);
299 if (pFolderMapping == NULL)
300 {
301 AssertFailed();
302 return NULL;
303 }
304
305 *pcbRoot = pFolderMapping->pFolderName->u16Size;
306 return &pFolderMapping->pFolderName->String.ucs2[0];
307}
308
309bool vbsfIsGuestMappingCaseSensitive (SHFLROOT root)
310{
311 MAPPING *pFolderMapping = vbsfMappingGetByRoot(root);
312 if (pFolderMapping == NULL)
313 {
314 AssertFailed();
315 return false;
316 }
317
318 return pFolderMapping->fGuestCaseSensitive;
319}
320
321bool vbsfIsHostMappingCaseSensitive (SHFLROOT root)
322{
323 MAPPING *pFolderMapping = vbsfMappingGetByRoot(root);
324 if (pFolderMapping == NULL)
325 {
326 AssertFailed();
327 return false;
328 }
329
330 return pFolderMapping->fHostCaseSensitive;
331}
332
333int vbsfMappingsQuery (SHFLCLIENTDATA *pClient, SHFLMAPPING *pMappings, uint32_t *pcMappings)
334{
335 int rc = VINF_SUCCESS;
336 uint32_t cMaxMappings = RT_MIN(*pcMappings, SHFL_MAX_MAPPINGS);
337
338 LogFlow(("vbsfMappingsQuery: pClient = %p, pMappings = %p, pcMappings = %p, *pcMappings = %d\n",
339 pClient, pMappings, pcMappings, *pcMappings));
340
341 *pcMappings = 0;
342 for (uint32_t i=0;i<cMaxMappings;i++)
343 {
344 MAPPING *pFolderMapping = vbsfMappingGetByRoot(i);
345 if ( pFolderMapping != NULL
346 && pFolderMapping->fValid == true)
347 {
348 /* Skip mappings which are not marked for auto-mounting if
349 * the SHFL_MF_AUTOMOUNT flag ist set. */
350 if ( (pClient->fu32Flags & SHFL_MF_AUTOMOUNT)
351 && !pFolderMapping->fAutoMount)
352 continue;
353
354 pMappings[*pcMappings].u32Status = SHFL_MS_NEW;
355 pMappings[*pcMappings].root = i;
356 *pcMappings = *pcMappings + 1;
357 }
358 }
359 LogFlow(("vbsfMappingsQuery: return rc = %Rrc\n", rc));
360 return rc;
361}
362
363int vbsfMappingsQueryName (SHFLCLIENTDATA *pClient, SHFLROOT root, SHFLSTRING *pString)
364{
365 int rc = VINF_SUCCESS;
366
367 LogFlow(("vbsfMappingsQuery: pClient = %p, root = %d, *pString = %p\n",
368 pClient, root, pString));
369
370 MAPPING *pFolderMapping = vbsfMappingGetByRoot(root);
371 if (pFolderMapping == NULL)
372 {
373 return VERR_INVALID_PARAMETER;
374 }
375
376 if (BIT_FLAG(pClient->fu32Flags, SHFL_CF_UTF8))
377 {
378 /* Not implemented. */
379 AssertFailed();
380 return VERR_INVALID_PARAMETER;
381 }
382
383 if (pFolderMapping->fValid == true)
384 {
385 pString->u16Length = pFolderMapping->pMapName->u16Length;
386 memcpy(pString->String.ucs2, pFolderMapping->pMapName->String.ucs2, pString->u16Size);
387 }
388 else
389 rc = VERR_FILE_NOT_FOUND;
390
391 LogFlow(("vbsfMappingsQuery:Name return rc = %Rrc\n", rc));
392
393 return rc;
394}
395
396int vbsfMappingsQueryWritable (SHFLCLIENTDATA *pClient, SHFLROOT root, bool *fWritable)
397{
398 int rc = VINF_SUCCESS;
399
400 LogFlow(("vbsfMappingsQueryWritable: pClient = %p, root = %d\n",
401 pClient, root));
402
403 MAPPING *pFolderMapping = vbsfMappingGetByRoot(root);
404 if (pFolderMapping == NULL)
405 {
406 return VERR_INVALID_PARAMETER;
407 }
408
409 if (pFolderMapping->fValid == true)
410 *fWritable = pFolderMapping->fWritable;
411 else
412 rc = VERR_FILE_NOT_FOUND;
413
414 LogFlow(("vbsfMappingsQuery:Writable return rc = %Rrc\n", rc));
415
416 return rc;
417}
418
419int vbsfMappingsQueryAutoMount (SHFLCLIENTDATA *pClient, SHFLROOT root, bool *fAutoMount)
420{
421 int rc = VINF_SUCCESS;
422
423 LogFlow(("vbsfMappingsQueryAutoMount: pClient = %p, root = %d\n",
424 pClient, root));
425
426 MAPPING *pFolderMapping = vbsfMappingGetByRoot(root);
427 if (pFolderMapping == NULL)
428 {
429 return VERR_INVALID_PARAMETER;
430 }
431
432 if (pFolderMapping->fValid == true)
433 *fAutoMount = pFolderMapping->fAutoMount;
434 else
435 rc = VERR_FILE_NOT_FOUND;
436
437 LogFlow(("vbsfMappingsQueryAutoMount:Writable return rc = %Rrc\n", rc));
438
439 return rc;
440}
441
442int vbsfMapFolder (SHFLCLIENTDATA *pClient, PSHFLSTRING pszMapName, RTUTF16 delimiter, bool fCaseSensitive, SHFLROOT *pRoot)
443{
444 MAPPING *pFolderMapping = NULL;
445
446 if (BIT_FLAG(pClient->fu32Flags, SHFL_CF_UTF8))
447 {
448 Log(("vbsfMapFolder %s\n", pszMapName->String.utf8));
449 }
450 else
451 {
452 Log(("vbsfMapFolder %ls\n", pszMapName->String.ucs2));
453 }
454
455 if (pClient->PathDelimiter == 0)
456 {
457 pClient->PathDelimiter = delimiter;
458 }
459 else
460 {
461 Assert(delimiter == pClient->PathDelimiter);
462 }
463
464 if (BIT_FLAG(pClient->fu32Flags, SHFL_CF_UTF8))
465 {
466 int rc;
467 PRTUTF16 utf16Name;
468
469 rc = RTStrToUtf16 ((const char *) pszMapName->String.utf8, &utf16Name);
470 if (RT_FAILURE (rc))
471 return rc;
472
473 pFolderMapping = vbsfMappingGetByName(utf16Name, pRoot);
474 RTUtf16Free (utf16Name);
475 }
476 else
477 {
478 pFolderMapping = vbsfMappingGetByName(pszMapName->String.ucs2, pRoot);
479 }
480
481 if (!pFolderMapping)
482 {
483 return VERR_FILE_NOT_FOUND;
484 }
485
486 pFolderMapping->cMappings++;
487 Assert(pFolderMapping->cMappings == 1 || pFolderMapping->fGuestCaseSensitive == fCaseSensitive);
488 pFolderMapping->fGuestCaseSensitive = fCaseSensitive;
489 return VINF_SUCCESS;
490}
491
492int vbsfUnmapFolder (SHFLCLIENTDATA *pClient, SHFLROOT root)
493{
494 int rc = VINF_SUCCESS;
495
496 MAPPING *pFolderMapping = vbsfMappingGetByRoot(root);
497 if (pFolderMapping == NULL)
498 {
499 AssertFailed();
500 return VERR_FILE_NOT_FOUND;
501 }
502
503 Assert(pFolderMapping->fValid == true && pFolderMapping->cMappings > 0);
504 if (pFolderMapping->cMappings > 0)
505 pFolderMapping->cMappings--;
506
507 Log(("vbsfUnmapFolder\n"));
508 return rc;
509}
Note: See TracBrowser for help on using the repository browser.

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