VirtualBox

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

最後變更 在這個檔案從21673是 21673,由 vboxsync 提交於 16 年 前

IPRT: Split up r3/path.cpp.

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette