VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedFolders/vbsfpathabs.cpp@ 67954

Last change on this file since 67954 was 66090, checked in by vboxsync, 8 years ago

SharedFolders: helper function for Windows extended-length paths.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 5.5 KB
Line 
1/* $Id: vbsfpathabs.cpp 66090 2017-03-14 14:02:22Z vboxsync $ */
2/** @file
3 * Shared Folders - guest/host path convertion and verification.
4 */
5
6/*
7 * Copyright (C) 2017 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
18#include <iprt/path.h>
19#include <iprt/string.h>
20
21#if defined(RT_OS_WINDOWS)
22static void vbsfPathResolveRelative(char *pszPathBegin)
23{
24 char *pszCur = pszPathBegin;
25 char * const pszTop = pszCur;
26
27 /*
28 * Get rid of double dot path components by evaluating them.
29 */
30 for (;;)
31 {
32 char const chFirst = pszCur[0];
33 if ( chFirst == '.'
34 && pszCur[1] == '.'
35 && (!pszCur[2] || pszCur[2] == RTPATH_SLASH))
36 {
37 /* rewind to the previous component if any */
38 char *pszPrev = pszCur;
39 if ((uintptr_t)pszPrev > (uintptr_t)pszTop)
40 {
41 pszPrev--;
42 while ( (uintptr_t)pszPrev > (uintptr_t)pszTop
43 && pszPrev[-1] != RTPATH_SLASH)
44 pszPrev--;
45 }
46 if (!pszCur[2])
47 {
48 if (pszPrev != pszTop)
49 pszPrev[-1] = '\0';
50 else
51 *pszPrev = '\0';
52 break;
53 }
54 Assert(pszPrev[-1] == RTPATH_SLASH);
55 memmove(pszPrev, pszCur + 3, strlen(pszCur + 3) + 1);
56 pszCur = pszPrev - 1;
57 }
58 else if ( chFirst == '.'
59 && (!pszCur[1] || pszCur[1] == RTPATH_SLASH))
60 {
61 /* remove unnecessary '.' */
62 if (!pszCur[1])
63 {
64 if (pszCur != pszTop)
65 pszCur[-1] = '\0';
66 else
67 *pszCur = '\0';
68 break;
69 }
70 memmove(pszCur, pszCur + 2, strlen(pszCur + 2) + 1);
71 continue;
72 }
73 else
74 {
75 /* advance to end of component. */
76 while (*pszCur && *pszCur != RTPATH_SLASH)
77 pszCur++;
78 }
79
80 if (!*pszCur)
81 break;
82
83 /* skip the slash */
84 ++pszCur;
85 }
86}
87#endif /* RT_OS_WINDOWS */
88
89int vbsfPathAbs(const char *pszRoot, const char *pszPath, char *pszAbsPath, size_t cbAbsPath)
90{
91#if defined(RT_OS_WINDOWS)
92 const char *pszPathStart = pszRoot? pszRoot: pszPath;
93
94 /* Windows extended-length paths. */
95 if ( RTPATH_IS_SLASH(pszPathStart[0])
96 && RTPATH_IS_SLASH(pszPathStart[1])
97 && pszPathStart[2] == '?'
98 && RTPATH_IS_SLASH(pszPathStart[3])
99 )
100 {
101 /* Maximum total path length of 32,767 characters. */
102 if (cbAbsPath > _32K)
103 cbAbsPath = _32K;
104
105 /* Copy the root to pszAbsPath buffer. */
106 size_t cchRoot = pszRoot? strlen(pszRoot): 0;
107 if (cchRoot >= cbAbsPath)
108 return VERR_FILENAME_TOO_LONG;
109
110 if (pszRoot)
111 {
112 /* Caller must ensure that the path is relative, without the leading path separator. */
113 if (RTPATH_IS_SLASH(pszPath[0]))
114 return VERR_INVALID_PARAMETER;
115
116 if (cchRoot)
117 memcpy(pszAbsPath, pszRoot, cchRoot);
118
119 if (cchRoot == 0 || !RTPATH_IS_SLASH(pszAbsPath[cchRoot - 1]))
120 {
121 /* Append path separator after the root. */
122 ++cchRoot;
123 if (cchRoot >= cbAbsPath)
124 return VERR_FILENAME_TOO_LONG;
125
126 pszAbsPath[cchRoot - 1] = RTPATH_SLASH;
127 }
128 }
129
130 /* Append the path to the pszAbsPath buffer. */
131 const size_t cchPath = strlen(pszPath);
132 if (cchRoot + cchPath >= cbAbsPath)
133 return VERR_FILENAME_TOO_LONG;
134
135 memcpy(&pszAbsPath[cchRoot], pszPath, cchPath + 1); /* Including trailing 0. */
136
137 /* Find out where the actual path begins, i.e. skip the root spec. */
138 char *pszPathBegin = &pszAbsPath[4]; /* Skip the extended-length path prefix "\\?\" */
139 if ( pszPathBegin[0]
140 && RTPATH_IS_VOLSEP(pszPathBegin[1])
141 && pszPathBegin[2] == RTPATH_SLASH)
142 {
143 /* "\\?\C:\" */
144 pszPathBegin += 3;
145 }
146 else if ( pszPathBegin[0] == 'U'
147 && pszPathBegin[1] == 'N'
148 && pszPathBegin[2] == 'C'
149 && pszPathBegin[3] == RTPATH_SLASH)
150 {
151 /* "\\?\UNC\server\share" */
152 pszPathBegin += 4;
153
154 /* Skip "server\share" too. */
155 while (*pszPathBegin != RTPATH_SLASH && *pszPathBegin)
156 ++pszPathBegin;
157 if (*pszPathBegin == RTPATH_SLASH)
158 {
159 ++pszPathBegin;
160 while (*pszPathBegin != RTPATH_SLASH && *pszPathBegin)
161 ++pszPathBegin;
162 if (*pszPathBegin == RTPATH_SLASH)
163 ++pszPathBegin;
164 }
165 }
166 else
167 return VERR_INVALID_NAME;
168
169 /* Process pszAbsPath in place. */
170 vbsfPathResolveRelative(pszPathBegin);
171
172 return VINF_SUCCESS;
173 }
174#endif /* RT_OS_WINDOWS */
175
176 /* Fallback for the common paths. */
177 return RTPathAbsEx(pszRoot, pszPath, pszAbsPath, cbAbsPath);
178}
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