VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/path/RTPathAppend.cpp@ 25659

Last change on this file since 25659 was 21676, checked in by vboxsync, 16 years ago

common/path: build fix.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 5.6 KB
Line 
1/* $Id: RTPathAppend.cpp 21676 2009-07-17 12:21:49Z vboxsync $ */
2/** @file
3 * IPRT - RTPathAppend
4 */
5
6/*
7 * Copyright (C) 2009 Sun Microsystems, Inc.
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 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 *
26 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31
32/*******************************************************************************
33* Header Files *
34*******************************************************************************/
35#include "internal/iprt.h"
36#include <iprt/path.h>
37#include <iprt/assert.h>
38#include <iprt/ctype.h>
39#include <iprt/err.h>
40#include <iprt/string.h>
41
42
43/**
44 * Figures the length of the root part of the path.
45 *
46 * @returns length of the root specifier.
47 * @retval 0 if none.
48 *
49 * @param pszPath The path to investigate.
50 *
51 * @remarks Unnecessary root slashes will not be counted. The caller will have
52 * to deal with it where it matters.
53 */
54static size_t rtPathRootSpecLen(const char *pszPath)
55{
56 /* fend of wildlife. */
57 if (!pszPath)
58 return 0;
59
60 /* Root slash? */
61 if (RTPATH_IS_SLASH(pszPath[0]))
62 {
63#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
64 /* UNC? */
65 if ( RTPATH_IS_SLASH(pszPath[1])
66 && pszPath[2] != '\0'
67 && !RTPATH_IS_SLASH(pszPath[2]))
68 {
69 /* Find the end of the server name. */
70 const char *pszEnd = pszPath + 2;
71 pszEnd += 2;
72 while ( *pszEnd != '\0'
73 && !RTPATH_IS_SLASH(*pszEnd))
74 pszEnd++;
75 if (RTPATH_IS_SLASH(*pszEnd))
76 {
77 pszEnd++;
78 while (RTPATH_IS_SLASH(*pszEnd))
79 pszEnd++;
80
81 /* Find the end of the share name */
82 while ( *pszEnd != '\0'
83 && !RTPATH_IS_SLASH(*pszEnd))
84 pszEnd++;
85 if (RTPATH_IS_SLASH(*pszEnd))
86 pszEnd++;
87 return pszPath - pszEnd;
88 }
89 }
90#endif
91 return 1;
92 }
93
94#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
95 /* Drive specifier? */
96 if ( pszPath[0] != '\0'
97 && pszPath[1] == ':'
98 && RT_C_IS_ALPHA(pszPath[0]))
99 {
100 if (RTPATH_IS_SLASH(pszPath[2]))
101 return 3;
102 return 2;
103 }
104#endif
105 return 0;
106}
107
108
109RTDECL(int) RTPathAppend(char *pszPath, size_t cbPathDst, const char *pszAppend)
110{
111 char *pszPathEnd = (char *)memchr(pszPath, '\0', cbPathDst);
112 AssertReturn(pszPathEnd, VERR_INVALID_PARAMETER);
113
114 /*
115 * Special cases.
116 */
117 if (!pszAppend)
118 return VINF_SUCCESS;
119 size_t cchAppend = strlen(pszAppend);
120 if (!cchAppend)
121 return VINF_SUCCESS;
122 if (pszPathEnd == pszPath)
123 {
124 if (cchAppend >= cbPathDst)
125 return VERR_BUFFER_OVERFLOW;
126 memcpy(pszPath, pszAppend, cchAppend + 1);
127 return VINF_SUCCESS;
128 }
129
130 /*
131 * Balance slashes and check for buffer overflow.
132 */
133 bool fAddSlash = false;
134 if (!RTPATH_IS_SLASH(pszPathEnd[-1]))
135 {
136 if (!RTPATH_IS_SLASH(pszAppend[0]))
137 {
138#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
139 if ( (size_t)(pszPathEnd - pszPath) == 2
140 && pszPath[1] == ':'
141 && RT_C_IS_ALPHA(pszPath[0]))
142 {
143 if ((size_t)(pszPathEnd - pszPath) + cchAppend >= cbPathDst)
144 return VERR_BUFFER_OVERFLOW;
145 }
146 else
147#endif
148 {
149 if ((size_t)(pszPathEnd - pszPath) + 1 + cchAppend >= cbPathDst)
150 return VERR_BUFFER_OVERFLOW;
151 *pszPathEnd++ = '/';
152 }
153 }
154 else
155 {
156 /* One slash is sufficient at this point. */
157 while (RTPATH_IS_SLASH(pszAppend[1]))
158 pszAppend++, cchAppend--;
159
160 if ((size_t)(pszPathEnd - pszPath) + cchAppend >= cbPathDst)
161 return VERR_BUFFER_OVERFLOW;
162 }
163 }
164 else
165 {
166 /* No slashes needed in the appended bit. */
167 while (RTPATH_IS_SLASH(*pszAppend))
168 pszAppend++, cchAppend--;
169
170 /* In the leading path we can skip unnecessary trailing slashes, but
171 be sure to leave one. */
172 size_t const cchRoot = rtPathRootSpecLen(pszPath);
173 while ( (size_t)(pszPathEnd - pszPath) > RT_MAX(1, cchRoot)
174 && RTPATH_IS_SLASH(pszPathEnd[-2]))
175 pszPathEnd--;
176
177 if ((size_t)(pszPathEnd - pszPath) + cchAppend >= cbPathDst)
178 return VERR_BUFFER_OVERFLOW;
179 }
180
181 /*
182 * What remains now is the just the copying.
183 */
184 memcpy(pszPathEnd, pszAppend, cchAppend + 1);
185 return VINF_SUCCESS;
186}
187
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