VirtualBox

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

Last change on this file since 26761 was 26476, checked in by vboxsync, 15 years ago

iprt: Added RTPathCountComponents, RTPathCopyComponents, RTGetOptArgvFromString and RTGetOptArgvFree.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 5.7 KB
Line 
1/* $Id: RTPathAppend.cpp 26476 2010-02-13 02:06:41Z 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
38#include <iprt/assert.h>
39#include <iprt/ctype.h>
40#include <iprt/err.h>
41#include <iprt/string.h>
42
43
44/**
45 * Figures the length of the root part of the path.
46 *
47 * @returns length of the root specifier.
48 * @retval 0 if none.
49 *
50 * @param pszPath The path to investigate.
51 *
52 * @remarks Unnecessary root slashes will not be counted. The caller will have
53 * to deal with it where it matters. (Unlike rtPathRootSpecLen which
54 * counts them.)
55 */
56static size_t rtPathRootSpecLen2(const char *pszPath)
57{
58 /* fend of wildlife. */
59 if (!pszPath)
60 return 0;
61
62 /* Root slash? */
63 if (RTPATH_IS_SLASH(pszPath[0]))
64 {
65#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
66 /* UNC? */
67 if ( RTPATH_IS_SLASH(pszPath[1])
68 && pszPath[2] != '\0'
69 && !RTPATH_IS_SLASH(pszPath[2]))
70 {
71 /* Find the end of the server name. */
72 const char *pszEnd = pszPath + 2;
73 pszEnd += 2;
74 while ( *pszEnd != '\0'
75 && !RTPATH_IS_SLASH(*pszEnd))
76 pszEnd++;
77 if (RTPATH_IS_SLASH(*pszEnd))
78 {
79 pszEnd++;
80 while (RTPATH_IS_SLASH(*pszEnd))
81 pszEnd++;
82
83 /* Find the end of the share name */
84 while ( *pszEnd != '\0'
85 && !RTPATH_IS_SLASH(*pszEnd))
86 pszEnd++;
87 if (RTPATH_IS_SLASH(*pszEnd))
88 pszEnd++;
89 return pszPath - pszEnd;
90 }
91 }
92#endif
93 return 1;
94 }
95
96#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
97 /* Drive specifier? */
98 if ( pszPath[0] != '\0'
99 && pszPath[1] == ':'
100 && RT_C_IS_ALPHA(pszPath[0]))
101 {
102 if (RTPATH_IS_SLASH(pszPath[2]))
103 return 3;
104 return 2;
105 }
106#endif
107 return 0;
108}
109
110
111RTDECL(int) RTPathAppend(char *pszPath, size_t cbPathDst, const char *pszAppend)
112{
113 char *pszPathEnd = (char *)memchr(pszPath, '\0', cbPathDst);
114 AssertReturn(pszPathEnd, VERR_INVALID_PARAMETER);
115
116 /*
117 * Special cases.
118 */
119 if (!pszAppend)
120 return VINF_SUCCESS;
121 size_t cchAppend = strlen(pszAppend);
122 if (!cchAppend)
123 return VINF_SUCCESS;
124 if (pszPathEnd == pszPath)
125 {
126 if (cchAppend >= cbPathDst)
127 return VERR_BUFFER_OVERFLOW;
128 memcpy(pszPath, pszAppend, cchAppend + 1);
129 return VINF_SUCCESS;
130 }
131
132 /*
133 * Balance slashes and check for buffer overflow.
134 */
135 bool fAddSlash = false;
136 if (!RTPATH_IS_SLASH(pszPathEnd[-1]))
137 {
138 if (!RTPATH_IS_SLASH(pszAppend[0]))
139 {
140#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
141 if ( (size_t)(pszPathEnd - pszPath) == 2
142 && pszPath[1] == ':'
143 && RT_C_IS_ALPHA(pszPath[0]))
144 {
145 if ((size_t)(pszPathEnd - pszPath) + cchAppend >= cbPathDst)
146 return VERR_BUFFER_OVERFLOW;
147 }
148 else
149#endif
150 {
151 if ((size_t)(pszPathEnd - pszPath) + 1 + cchAppend >= cbPathDst)
152 return VERR_BUFFER_OVERFLOW;
153 *pszPathEnd++ = '/';
154 }
155 }
156 else
157 {
158 /* One slash is sufficient at this point. */
159 while (RTPATH_IS_SLASH(pszAppend[1]))
160 pszAppend++, cchAppend--;
161
162 if ((size_t)(pszPathEnd - pszPath) + cchAppend >= cbPathDst)
163 return VERR_BUFFER_OVERFLOW;
164 }
165 }
166 else
167 {
168 /* No slashes needed in the appended bit. */
169 while (RTPATH_IS_SLASH(*pszAppend))
170 pszAppend++, cchAppend--;
171
172 /* In the leading path we can skip unnecessary trailing slashes, but
173 be sure to leave one. */
174 size_t const cchRoot = rtPathRootSpecLen2(pszPath);
175 while ( (size_t)(pszPathEnd - pszPath) > RT_MAX(1, cchRoot)
176 && RTPATH_IS_SLASH(pszPathEnd[-2]))
177 pszPathEnd--;
178
179 if ((size_t)(pszPathEnd - pszPath) + cchAppend >= cbPathDst)
180 return VERR_BUFFER_OVERFLOW;
181 }
182
183 /*
184 * What remains now is the just the copying.
185 */
186 memcpy(pszPathEnd, pszAppend, cchAppend + 1);
187 return VINF_SUCCESS;
188}
189
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