VirtualBox

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

Last change on this file was 99775, checked in by vboxsync, 13 months ago

*: Mark functions as static if not used outside of a given compilation unit. Enables the compiler to optimize inlining, reduces the symbol tables, exposes unused functions and in some rare cases exposes mismtaches between function declarations and definitions, but most importantly reduces the number of parfait reports for the extern-function-no-forward-declaration category. This should not result in any functional changes, bugref:3409

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.6 KB
Line 
1/* $Id: vbsfpathabs.cpp 99775 2023-05-12 12:21:58Z vboxsync $ */
2/** @file
3 * Shared Folders Service - guest/host path convertion and verification.
4 */
5
6/*
7 * Copyright (C) 2017-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#define LOG_GROUP LOG_GROUP_SHARED_FOLDERS
33#include <iprt/err.h>
34#include <iprt/path.h>
35#include <iprt/string.h>
36
37#include "vbsfpath.h"
38
39#if defined(RT_OS_WINDOWS)
40static void vbsfPathResolveRelative(char *pszPathBegin)
41{
42 char *pszCur = pszPathBegin;
43 char * const pszTop = pszCur;
44
45 /*
46 * Get rid of double dot path components by evaluating them.
47 */
48 for (;;)
49 {
50 char const chFirst = pszCur[0];
51 if ( chFirst == '.'
52 && pszCur[1] == '.'
53 && (!pszCur[2] || pszCur[2] == RTPATH_SLASH))
54 {
55 /* rewind to the previous component if any */
56 char *pszPrev = pszCur;
57 if ((uintptr_t)pszPrev > (uintptr_t)pszTop)
58 {
59 pszPrev--;
60 while ( (uintptr_t)pszPrev > (uintptr_t)pszTop
61 && pszPrev[-1] != RTPATH_SLASH)
62 pszPrev--;
63 }
64 if (!pszCur[2])
65 {
66 if (pszPrev != pszTop)
67 pszPrev[-1] = '\0';
68 else
69 *pszPrev = '\0';
70 break;
71 }
72 Assert(pszPrev[-1] == RTPATH_SLASH);
73 memmove(pszPrev, pszCur + 3, strlen(pszCur + 3) + 1);
74 pszCur = pszPrev - 1;
75 }
76 else if ( chFirst == '.'
77 && (!pszCur[1] || pszCur[1] == RTPATH_SLASH))
78 {
79 /* remove unnecessary '.' */
80 if (!pszCur[1])
81 {
82 if (pszCur != pszTop)
83 pszCur[-1] = '\0';
84 else
85 *pszCur = '\0';
86 break;
87 }
88 memmove(pszCur, pszCur + 2, strlen(pszCur + 2) + 1);
89 continue;
90 }
91 else
92 {
93 /* advance to end of component. */
94 while (*pszCur && *pszCur != RTPATH_SLASH)
95 pszCur++;
96 }
97
98 if (!*pszCur)
99 break;
100
101 /* skip the slash */
102 ++pszCur;
103 }
104}
105#endif /* RT_OS_WINDOWS */
106
107int vbsfPathAbs(const char *pszRoot, const char *pszPath, char *pszAbsPath, size_t cbAbsPath)
108{
109#if defined(RT_OS_WINDOWS)
110 /** @todo This code is not needed in 6.0 and later as IPRT translates paths
111 * to //./ (inverted slashes for doxygen) format if they're too long. */
112 const char *pszPathStart = pszRoot? pszRoot: pszPath;
113
114 /* Windows extended-length paths. */
115 if ( RTPATH_IS_SLASH(pszPathStart[0])
116 && RTPATH_IS_SLASH(pszPathStart[1])
117 && pszPathStart[2] == '?'
118 && RTPATH_IS_SLASH(pszPathStart[3])
119 )
120 {
121 /* Maximum total path length of 32,767 characters. */
122 if (cbAbsPath > _32K)
123 cbAbsPath = _32K;
124
125 /* Copy the root to pszAbsPath buffer. */
126 size_t cchRoot = pszRoot? strlen(pszRoot): 0;
127 if (cchRoot >= cbAbsPath)
128 return VERR_FILENAME_TOO_LONG;
129
130 if (pszRoot)
131 {
132 /* Caller must ensure that the path is relative, without the leading path separator. */
133 if (RTPATH_IS_SLASH(pszPath[0]))
134 return VERR_INVALID_PARAMETER;
135
136 if (cchRoot)
137 memcpy(pszAbsPath, pszRoot, cchRoot);
138
139 if (cchRoot == 0 || !RTPATH_IS_SLASH(pszAbsPath[cchRoot - 1]))
140 {
141 /* Append path separator after the root. */
142 ++cchRoot;
143 if (cchRoot >= cbAbsPath)
144 return VERR_FILENAME_TOO_LONG;
145
146 pszAbsPath[cchRoot - 1] = RTPATH_SLASH;
147 }
148 }
149
150 /* Append the path to the pszAbsPath buffer. */
151 const size_t cchPath = strlen(pszPath);
152 if (cchRoot + cchPath >= cbAbsPath)
153 return VERR_FILENAME_TOO_LONG;
154
155 memcpy(&pszAbsPath[cchRoot], pszPath, cchPath + 1); /* Including trailing 0. */
156
157 /* Find out where the actual path begins, i.e. skip the root spec. */
158 char *pszPathBegin = &pszAbsPath[4]; /* Skip the extended-length path prefix "\\?\" */
159 if ( pszPathBegin[0]
160 && RTPATH_IS_VOLSEP(pszPathBegin[1])
161 && pszPathBegin[2] == RTPATH_SLASH)
162 {
163 /* "\\?\C:\" */
164 pszPathBegin += 3;
165 }
166 else if ( pszPathBegin[0] == 'U'
167 && pszPathBegin[1] == 'N'
168 && pszPathBegin[2] == 'C'
169 && pszPathBegin[3] == RTPATH_SLASH)
170 {
171 /* "\\?\UNC\server\share" */
172 pszPathBegin += 4;
173
174 /* Skip "server\share" too. */
175 while (*pszPathBegin != RTPATH_SLASH && *pszPathBegin)
176 ++pszPathBegin;
177 if (*pszPathBegin == RTPATH_SLASH)
178 {
179 ++pszPathBegin;
180 while (*pszPathBegin != RTPATH_SLASH && *pszPathBegin)
181 ++pszPathBegin;
182 if (*pszPathBegin == RTPATH_SLASH)
183 ++pszPathBegin;
184 }
185 }
186 else
187 return VERR_INVALID_NAME;
188
189 /* Process pszAbsPath in place. */
190 vbsfPathResolveRelative(pszPathBegin);
191
192 return VINF_SUCCESS;
193 }
194#endif /* RT_OS_WINDOWS */
195
196 /* Fallback for the common paths. */
197
198 if (*pszPath != '\0')
199 return RTPathAbsEx(pszRoot, pszPath, RTPATH_STR_F_STYLE_HOST, pszAbsPath, &cbAbsPath);
200 return RTPathAbsEx(NULL, pszRoot, RTPATH_STR_F_STYLE_HOST, pszAbsPath, &cbAbsPath);
201}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use