VirtualBox

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

Last change on this file since 34575 was 31055, checked in by vboxsync, 14 years ago

Warning.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.6 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 PMAPPING 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
333/**
334 * Note: If pMappings / *pcMappings is smaller than the actual amount of mappings
335 * that *could* have been returned *pcMappings contains the required buffer size
336 * so that the caller can retry the operation if wanted.
337 */
338int vbsfMappingsQuery(PSHFLCLIENTDATA pClient, PSHFLMAPPING pMappings, uint32_t *pcMappings)
339{
340 int rc = VINF_SUCCESS;
341
342 uint32_t cMappings = 0; /* Will contain actual valid mappings. */
343 uint32_t idx = 0; /* Current index in mappings buffer. */
344
345 LogFlow(("vbsfMappingsQuery: pClient = %p, pMappings = %p, pcMappings = %p, *pcMappings = %d\n",
346 pClient, pMappings, pcMappings, *pcMappings));
347
348 for (uint32_t i = 0; i < SHFL_MAX_MAPPINGS; i++)
349 {
350 MAPPING *pFolderMapping = vbsfMappingGetByRoot(i);
351 if ( pFolderMapping != NULL
352 && pFolderMapping->fValid == true)
353 {
354 if (idx < *pcMappings)
355 {
356 /* Skip mappings which are not marked for auto-mounting if
357 * the SHFL_MF_AUTOMOUNT flag ist set. */
358 if ( (pClient->fu32Flags & SHFL_MF_AUTOMOUNT)
359 && !pFolderMapping->fAutoMount)
360 continue;
361
362 pMappings[idx].u32Status = SHFL_MS_NEW;
363 pMappings[idx].root = i;
364 idx++;
365 }
366 cMappings++;
367 }
368 }
369
370 /* Return actual number of mappings, regardless whether the handed in
371 * mapping buffer was big enough. */
372 *pcMappings = cMappings;
373
374 LogFlow(("vbsfMappingsQuery: return rc = %Rrc\n", rc));
375 return rc;
376}
377
378int vbsfMappingsQueryName(PSHFLCLIENTDATA pClient, SHFLROOT root, SHFLSTRING *pString)
379{
380 int rc = VINF_SUCCESS;
381
382 LogFlow(("vbsfMappingsQuery: pClient = %p, root = %d, *pString = %p\n",
383 pClient, root, pString));
384
385 MAPPING *pFolderMapping = vbsfMappingGetByRoot(root);
386 if (pFolderMapping == NULL)
387 {
388 return VERR_INVALID_PARAMETER;
389 }
390
391 if (BIT_FLAG(pClient->fu32Flags, SHFL_CF_UTF8))
392 {
393 /* Not implemented. */
394 AssertFailed();
395 return VERR_INVALID_PARAMETER;
396 }
397
398 if (pFolderMapping->fValid == true)
399 {
400 pString->u16Length = pFolderMapping->pMapName->u16Length;
401 memcpy(pString->String.ucs2, pFolderMapping->pMapName->String.ucs2, pString->u16Size);
402 }
403 else
404 rc = VERR_FILE_NOT_FOUND;
405
406 LogFlow(("vbsfMappingsQuery:Name return rc = %Rrc\n", rc));
407
408 return rc;
409}
410
411int vbsfMappingsQueryWritable(PSHFLCLIENTDATA pClient, SHFLROOT root, bool *fWritable)
412{
413 int rc = VINF_SUCCESS;
414
415 LogFlow(("vbsfMappingsQueryWritable: pClient = %p, root = %d\n",
416 pClient, root));
417
418 MAPPING *pFolderMapping = vbsfMappingGetByRoot(root);
419 if (pFolderMapping == NULL)
420 {
421 return VERR_INVALID_PARAMETER;
422 }
423
424 if (pFolderMapping->fValid == true)
425 *fWritable = pFolderMapping->fWritable;
426 else
427 rc = VERR_FILE_NOT_FOUND;
428
429 LogFlow(("vbsfMappingsQuery:Writable return rc = %Rrc\n", rc));
430
431 return rc;
432}
433
434int vbsfMappingsQueryAutoMount(PSHFLCLIENTDATA pClient, SHFLROOT root, bool *fAutoMount)
435{
436 int rc = VINF_SUCCESS;
437
438 LogFlow(("vbsfMappingsQueryAutoMount: pClient = %p, root = %d\n",
439 pClient, root));
440
441 MAPPING *pFolderMapping = vbsfMappingGetByRoot(root);
442 if (pFolderMapping == NULL)
443 {
444 return VERR_INVALID_PARAMETER;
445 }
446
447 if (pFolderMapping->fValid == true)
448 *fAutoMount = pFolderMapping->fAutoMount;
449 else
450 rc = VERR_FILE_NOT_FOUND;
451
452 LogFlow(("vbsfMappingsQueryAutoMount:Writable return rc = %Rrc\n", rc));
453
454 return rc;
455}
456
457int vbsfMapFolder(PSHFLCLIENTDATA pClient, PSHFLSTRING pszMapName,
458 RTUTF16 delimiter, bool fCaseSensitive, SHFLROOT *pRoot)
459{
460 MAPPING *pFolderMapping = NULL;
461
462 if (BIT_FLAG(pClient->fu32Flags, SHFL_CF_UTF8))
463 {
464 Log(("vbsfMapFolder %s\n", pszMapName->String.utf8));
465 }
466 else
467 {
468 Log(("vbsfMapFolder %ls\n", pszMapName->String.ucs2));
469 }
470
471 if (pClient->PathDelimiter == 0)
472 {
473 pClient->PathDelimiter = delimiter;
474 }
475 else
476 {
477 Assert(delimiter == pClient->PathDelimiter);
478 }
479
480 if (BIT_FLAG(pClient->fu32Flags, SHFL_CF_UTF8))
481 {
482 int rc;
483 PRTUTF16 utf16Name;
484
485 rc = RTStrToUtf16 ((const char *) pszMapName->String.utf8, &utf16Name);
486 if (RT_FAILURE (rc))
487 return rc;
488
489 pFolderMapping = vbsfMappingGetByName(utf16Name, pRoot);
490 RTUtf16Free (utf16Name);
491 }
492 else
493 {
494 pFolderMapping = vbsfMappingGetByName(pszMapName->String.ucs2, pRoot);
495 }
496
497 if (!pFolderMapping)
498 {
499 return VERR_FILE_NOT_FOUND;
500 }
501
502 pFolderMapping->cMappings++;
503 Assert(pFolderMapping->cMappings == 1 || pFolderMapping->fGuestCaseSensitive == fCaseSensitive);
504 pFolderMapping->fGuestCaseSensitive = fCaseSensitive;
505 return VINF_SUCCESS;
506}
507
508int vbsfUnmapFolder(PSHFLCLIENTDATA pClient, SHFLROOT root)
509{
510 int rc = VINF_SUCCESS;
511
512 MAPPING *pFolderMapping = vbsfMappingGetByRoot(root);
513 if (pFolderMapping == NULL)
514 {
515 AssertFailed();
516 return VERR_FILE_NOT_FOUND;
517 }
518
519 Assert(pFolderMapping->fValid == true && pFolderMapping->cMappings > 0);
520 if (pFolderMapping->cMappings > 0)
521 pFolderMapping->cMappings--;
522
523 Log(("vbsfUnmapFolder\n"));
524 return rc;
525}
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