VirtualBox

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

Last change on this file since 76066 was 75506, checked in by vboxsync, 6 years ago

Make scm happy.

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