VirtualBox

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

Last change on this file since 93622 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

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