VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/path/RTPathParse.cpp.h

Last change on this file was 98103, checked in by vboxsync, 16 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: 8.1 KB
Line 
1/* $Id: RTPathParse.cpp.h 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * IPRT - RTPathParse - Code Template.
4 *
5 * This file included multiple times with different path style macros.
6 */
7
8/*
9 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
10 *
11 * This file is part of VirtualBox base platform packages, as
12 * available from https://www.virtualbox.org.
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation, in version 3 of the
17 * License.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, see <https://www.gnu.org/licenses>.
26 *
27 * The contents of this file may alternatively be used under the terms
28 * of the Common Development and Distribution License Version 1.0
29 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
30 * in the VirtualBox distribution, in which case the provisions of the
31 * CDDL are applicable instead of those of the GPL.
32 *
33 * You may elect to license modified versions of this file under the
34 * terms and conditions of either the GPL or the CDDL or both.
35 *
36 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
37 */
38
39
40
41/**
42 * @copydoc RTPathParse
43 */
44static int RTPATH_STYLE_FN(rtPathParse)(const char *pszPath, PRTPATHPARSED pParsed, size_t cbParsed, uint32_t fFlags)
45{
46 /*
47 * Parse the root specification if present and initialize the parser state
48 * (keep it on the stack for speed).
49 */
50 uint32_t const cMaxComps = cbParsed < RT_UOFFSETOF(RTPATHPARSED, aComps[0xfff0])
51 ? (uint32_t)((cbParsed - RT_UOFFSETOF(RTPATHPARSED, aComps)) / sizeof(pParsed->aComps[0]))
52 : 0xfff0;
53 uint32_t idxComp = 0;
54 uint32_t cchPath;
55 uint32_t offCur;
56 uint16_t fProps;
57
58 if (RTPATH_IS_SLASH(pszPath[0]))
59 {
60 if (fFlags & RTPATH_STR_F_NO_START)
61 {
62 offCur = 1;
63 while (RTPATH_IS_SLASH(pszPath[offCur]))
64 offCur++;
65 if (!pszPath[offCur])
66 return VERR_PATH_ZERO_LENGTH;
67 fProps = RTPATH_PROP_RELATIVE | RTPATH_PROP_EXTRA_SLASHES;
68 cchPath = 0;
69 }
70#if RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS
71 else if (RTPATH_IS_SLASH(pszPath[1]))
72 {
73 /* UNC - there are exactly two prefix slashes followed by a namespace
74 or computer name, which can be empty on windows. */
75 offCur = 2;
76 while (!RTPATH_IS_SLASH(pszPath[offCur]) && pszPath[offCur])
77 offCur++;
78
79 /* Special fun for windows. */
80 fProps = RTPATH_PROP_UNC | RTPATH_PROP_ABSOLUTE;
81 if ( offCur == 3
82 && (pszPath[2] == '.' || pszPath[2] == '?'))
83 fProps |= RTPATH_PROP_SPECIAL_UNC;
84
85 if (RTPATH_IS_SLASH(pszPath[offCur]))
86 {
87 fProps |= RTPATH_PROP_ROOT_SLASH;
88 offCur++;
89 }
90 cchPath = offCur;
91 }
92#endif
93 else
94 {
95#if RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS
96 fProps = RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_RELATIVE;
97#else
98 fProps = RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE;
99#endif
100 offCur = 1;
101 cchPath = 1;
102 }
103 }
104#if RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS
105 else if (RT_C_IS_ALPHA(pszPath[0]) && pszPath[1] == ':')
106 {
107 if (!RTPATH_IS_SLASH(pszPath[2]))
108 {
109 fProps = RTPATH_PROP_VOLUME | RTPATH_PROP_RELATIVE;
110 offCur = 2;
111 }
112 else
113 {
114 fProps = RTPATH_PROP_VOLUME | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE;
115 offCur = 3;
116 }
117 cchPath = offCur;
118 }
119#endif
120 else
121 {
122 fProps = RTPATH_PROP_RELATIVE;
123 offCur = 0;
124 cchPath = 0;
125 }
126
127 /* Add it to the component array . */
128 if (offCur && !(fFlags & RTPATH_STR_F_NO_START))
129 {
130 cchPath = offCur;
131 if (idxComp < cMaxComps)
132 {
133 pParsed->aComps[idxComp].off = 0;
134 pParsed->aComps[idxComp].cch = offCur;
135 }
136 idxComp++;
137
138 /* Skip unnecessary slashes following the root-spec. */
139 if (RTPATH_IS_SLASH(pszPath[offCur]))
140 {
141 fProps |= RTPATH_PROP_EXTRA_SLASHES;
142 do
143 offCur++;
144 while (RTPATH_IS_SLASH(pszPath[offCur]));
145 }
146 }
147
148 /*
149 * Parse the rest.
150 */
151 if (pszPath[offCur])
152 {
153 for (;;)
154 {
155 Assert(!RTPATH_IS_SLASH(pszPath[offCur]));
156
157 /* Find the end of the component. */
158 uint32_t offStart = offCur;
159 char ch;
160 while ((ch = pszPath[offCur]) != '\0' && !RTPATH_IS_SLASH(ch))
161 offCur++;
162 if (offCur >= _64K)
163 return VERR_FILENAME_TOO_LONG;
164
165 /* Add it. */
166 uint32_t cchComp = offCur - offStart;
167 if (idxComp < cMaxComps)
168 {
169 pParsed->aComps[idxComp].off = offStart;
170 pParsed->aComps[idxComp].cch = cchComp;
171 }
172 idxComp++;
173 cchPath += cchComp;
174
175 /* Look for '.' and '..' references. */
176 if (cchComp == 1 && pszPath[offCur - 1] == '.')
177 fProps |= RTPATH_PROP_DOT_REFS;
178 else if (cchComp == 2 && pszPath[offCur - 1] == '.' && pszPath[offCur - 2] == '.')
179 {
180 fProps &= ~RTPATH_PROP_ABSOLUTE;
181 fProps |= RTPATH_PROP_DOTDOT_REFS | RTPATH_PROP_RELATIVE;
182 }
183
184 /* Skip unnecessary slashes. Leave ch unchanged! */
185 char ch2 = ch;
186 if (ch2)
187 {
188 ch2 = pszPath[++offCur];
189 if (RTPATH_IS_SLASH(ch2))
190 {
191 fProps |= RTPATH_PROP_EXTRA_SLASHES;
192 do
193 ch2 = pszPath[++offCur];
194 while (RTPATH_IS_SLASH(ch2));
195 }
196 }
197
198 /* The end? */
199 if (ch2 == '\0')
200 {
201 pParsed->offSuffix = offCur;
202 pParsed->cchSuffix = 0;
203 if (ch)
204 {
205 if (!(fFlags & RTPATH_STR_F_NO_END))
206 {
207 fProps |= RTPATH_PROP_DIR_SLASH; /* (not counted in component, but in cchPath) */
208 cchPath++;
209 }
210 else
211 fProps |= RTPATH_PROP_EXTRA_SLASHES;
212 }
213 else if (!(fFlags & RTPATH_STR_F_NO_END))
214 {
215 fProps |= RTPATH_PROP_FILENAME;
216
217 /* Look for a suffix: */
218 uint32_t offSuffix = offStart + cchComp;
219 while (--offSuffix > offStart)
220 if (pszPath[offSuffix] == '.')
221 {
222 uint32_t cchSuffix = offStart + cchComp - offSuffix;
223 if (cchSuffix > 1)
224 {
225 pParsed->cchSuffix = cchSuffix;
226 pParsed->offSuffix = offSuffix;
227 fProps |= RTPATH_PROP_SUFFIX;
228 }
229 break;
230 }
231 }
232 break;
233 }
234
235 /* No, not the end. Account for an separator before we restart the loop. */
236 cchPath += sizeof(RTPATH_SLASH_STR) - 1;
237 }
238 }
239 else
240 {
241 pParsed->offSuffix = offCur;
242 pParsed->cchSuffix = 0;
243 }
244 if (offCur >= _64K)
245 return VERR_FILENAME_TOO_LONG;
246
247 /*
248 * Store the remainder of the state and we're done.
249 */
250 pParsed->fProps = fProps;
251 pParsed->cchPath = cchPath;
252 pParsed->cComps = idxComp;
253
254 return idxComp <= cMaxComps ? VINF_SUCCESS : VERR_BUFFER_OVERFLOW;
255}
256
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use