VirtualBox

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

Last change on this file since 106579 was 106061, checked in by vboxsync, 2 months ago

Copyright year updates by scm.

  • 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 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * Shared Folders Service - guest/host path convertion and verification.
4 */
5
6/*
7 * Copyright (C) 2017-2024 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.

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