/src/libreoffice/sal/osl/unx/file_path_helper.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
5 | | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
11 | | * Licensed to the Apache Software Foundation (ASF) under one or more |
12 | | * contributor license agreements. See the NOTICE file distributed |
13 | | * with this work for additional information regarding copyright |
14 | | * ownership. The ASF licenses this file to you under the Apache |
15 | | * License, Version 2.0 (the "License"); you may not use this file |
16 | | * except in compliance with the License. You may obtain a copy of |
17 | | * the License at http://www.apache.org/licenses/LICENSE-2.0 . |
18 | | */ |
19 | | |
20 | | #include <sal/config.h> |
21 | | |
22 | | #include <cassert> |
23 | | #include <utility> |
24 | | #include <unistd.h> |
25 | | |
26 | | #include "file_path_helper.hxx" |
27 | | #include "uunxapi.hxx" |
28 | | |
29 | | #include <osl/diagnose.h> |
30 | | #include <rtl/ustring.hxx> |
31 | | #include <sal/log.hxx> |
32 | | |
33 | | const sal_Unicode FPH_CHAR_PATH_SEPARATOR = '/'; |
34 | | const sal_Unicode FPH_CHAR_DOT = '.'; |
35 | | const sal_Unicode FPH_CHAR_COLON = ':'; |
36 | | |
37 | | void osl_systemPathRemoveSeparator(rtl_String* pstrPath) |
38 | 2.17M | { |
39 | 2.17M | OSL_PRECOND(nullptr != pstrPath, "osl_systemPathRemoveSeparator: Invalid parameter"); |
40 | 2.17M | if (pstrPath == nullptr) |
41 | 0 | return; |
42 | | |
43 | | // maybe there are more than one separator at end |
44 | | // so we run in a loop |
45 | 2.49M | while ((pstrPath->length > 1) && (pstrPath->buffer[pstrPath->length - 1] == FPH_CHAR_PATH_SEPARATOR)) |
46 | 324k | { |
47 | 324k | pstrPath->length--; |
48 | 324k | pstrPath->buffer[pstrPath->length] = '\0'; |
49 | 324k | } |
50 | | |
51 | 2.17M | SAL_WARN_IF( !((0 == pstrPath->length) || (1 == pstrPath->length) || |
52 | 2.17M | (pstrPath->length > 1 && pstrPath->buffer[pstrPath->length - 1] != FPH_CHAR_PATH_SEPARATOR)), |
53 | 2.17M | "sal.osl", |
54 | 2.17M | "osl_systemPathRemoveSeparator: Post condition failed"); |
55 | 2.17M | } |
56 | | |
57 | | namespace { |
58 | | |
59 | | template<typename T> void systemPathEnsureSeparator(T* ppstrPath) |
60 | 102k | { |
61 | 102k | assert(nullptr != ppstrPath); |
62 | 102k | sal_Int32 lp = ppstrPath->getLength(); |
63 | 102k | sal_Int32 i = ppstrPath->lastIndexOf(FPH_CHAR_PATH_SEPARATOR); |
64 | | |
65 | 102k | if ((lp > 1 && i != (lp - 1)) || ((lp < 2) && i < 0)) |
66 | 102k | { |
67 | 102k | *ppstrPath += "/"; |
68 | 102k | } |
69 | | |
70 | 102k | SAL_WARN_IF( !ppstrPath->endsWith("/"), |
71 | 102k | "sal.osl", |
72 | 102k | "systemPathEnsureSeparator: Post condition failed"); |
73 | 102k | } file_path_helper.cxx:void (anonymous namespace)::systemPathEnsureSeparator<rtl::OString>(rtl::OString*) Line | Count | Source | 60 | 102k | { | 61 | 102k | assert(nullptr != ppstrPath); | 62 | 102k | sal_Int32 lp = ppstrPath->getLength(); | 63 | 102k | sal_Int32 i = ppstrPath->lastIndexOf(FPH_CHAR_PATH_SEPARATOR); | 64 | | | 65 | 102k | if ((lp > 1 && i != (lp - 1)) || ((lp < 2) && i < 0)) | 66 | 102k | { | 67 | 102k | *ppstrPath += "/"; | 68 | 102k | } | 69 | | | 70 | 102k | SAL_WARN_IF( !ppstrPath->endsWith("/"), | 71 | 102k | "sal.osl", | 72 | 102k | "systemPathEnsureSeparator: Post condition failed"); | 73 | 102k | } |
file_path_helper.cxx:void (anonymous namespace)::systemPathEnsureSeparator<rtl::OUString>(rtl::OUString*) Line | Count | Source | 60 | 87 | { | 61 | 87 | assert(nullptr != ppstrPath); | 62 | 87 | sal_Int32 lp = ppstrPath->getLength(); | 63 | 87 | sal_Int32 i = ppstrPath->lastIndexOf(FPH_CHAR_PATH_SEPARATOR); | 64 | | | 65 | 87 | if ((lp > 1 && i != (lp - 1)) || ((lp < 2) && i < 0)) | 66 | 87 | { | 67 | 87 | *ppstrPath += "/"; | 68 | 87 | } | 69 | | | 70 | 87 | SAL_WARN_IF( !ppstrPath->endsWith("/"), | 71 | 87 | "sal.osl", | 72 | 87 | "systemPathEnsureSeparator: Post condition failed"); | 73 | 87 | } |
|
74 | | |
75 | | } |
76 | | |
77 | | bool osl_systemPathIsRelativePath(const rtl_uString* pustrPath) |
78 | 281 | { |
79 | 281 | OSL_PRECOND(nullptr != pustrPath, "osl_systemPathIsRelativePath: Invalid parameter"); |
80 | 281 | return ((pustrPath == nullptr) || (pustrPath->length == 0) || (pustrPath->buffer[0] != FPH_CHAR_PATH_SEPARATOR)); |
81 | 281 | } |
82 | | |
83 | | namespace { |
84 | | |
85 | | template<typename T> T systemPathMakeAbsolutePath_( |
86 | | const T& BasePath, |
87 | | const T& RelPath) |
88 | 102k | { |
89 | 102k | T base(BasePath); |
90 | | |
91 | 102k | if (!base.isEmpty()) |
92 | 102k | systemPathEnsureSeparator(&base); |
93 | | |
94 | 102k | return base + RelPath; |
95 | 102k | } file_path_helper.cxx:rtl::OString (anonymous namespace)::systemPathMakeAbsolutePath_<rtl::OString>(rtl::OString const&, rtl::OString const&) Line | Count | Source | 88 | 102k | { | 89 | 102k | T base(BasePath); | 90 | | | 91 | 102k | if (!base.isEmpty()) | 92 | 102k | systemPathEnsureSeparator(&base); | 93 | | | 94 | 102k | return base + RelPath; | 95 | 102k | } |
file_path_helper.cxx:rtl::OUString (anonymous namespace)::systemPathMakeAbsolutePath_<rtl::OUString>(rtl::OUString const&, rtl::OUString const&) Line | Count | Source | 88 | 87 | { | 89 | 87 | T base(BasePath); | 90 | | | 91 | 87 | if (!base.isEmpty()) | 92 | 87 | systemPathEnsureSeparator(&base); | 93 | | | 94 | 87 | return base + RelPath; | 95 | 87 | } |
|
96 | | |
97 | | } |
98 | | |
99 | | OString osl::systemPathMakeAbsolutePath( |
100 | | const OString& BasePath, |
101 | | const OString& RelPath) |
102 | 102k | { |
103 | 102k | return systemPathMakeAbsolutePath_(BasePath, RelPath); |
104 | 102k | } |
105 | | |
106 | | OUString osl::systemPathMakeAbsolutePath( |
107 | | const OUString& BasePath, |
108 | | const OUString& RelPath) |
109 | 87 | { |
110 | 87 | return systemPathMakeAbsolutePath_(BasePath, RelPath); |
111 | 87 | } |
112 | | |
113 | | void osl_systemPathGetFileNameOrLastDirectoryPart( |
114 | | const rtl_String* pstrPath, |
115 | | rtl_String** ppstrFileNameOrLastDirPart) |
116 | 236k | { |
117 | 236k | OSL_PRECOND(pstrPath && ppstrFileNameOrLastDirPart, |
118 | 236k | "osl_systemPathGetFileNameOrLastDirectoryPart: Invalid parameter"); |
119 | | |
120 | 236k | OString path(const_cast<rtl_String*>(pstrPath)); |
121 | | |
122 | 236k | osl_systemPathRemoveSeparator(path.pData); |
123 | | |
124 | 236k | OString last_part; |
125 | | |
126 | 236k | if (path.getLength() > 1 || (path.getLength() == 1 && path[0] != FPH_CHAR_PATH_SEPARATOR)) |
127 | 236k | { |
128 | 236k | sal_Int32 idx_ps = path.lastIndexOf(FPH_CHAR_PATH_SEPARATOR); |
129 | 236k | idx_ps++; // always right to increment by one even if idx_ps == -1! |
130 | 236k | last_part = path.copy(idx_ps); |
131 | 236k | } |
132 | 236k | rtl_string_assign(ppstrFileNameOrLastDirPart, last_part.pData); |
133 | 236k | } |
134 | | |
135 | | bool osl_systemPathIsHiddenFileOrDirectoryEntry( |
136 | | const rtl_String* pstrPath) |
137 | 133k | { |
138 | 133k | OSL_PRECOND(nullptr != pstrPath, "osl_systemPathIsHiddenFileOrDirectoryEntry: Invalid parameter"); |
139 | 133k | if ((pstrPath == nullptr) || (pstrPath->length == 0)) |
140 | 0 | return false; |
141 | | |
142 | 133k | OString fdp; |
143 | 133k | osl_systemPathGetFileNameOrLastDirectoryPart(pstrPath, &fdp.pData); |
144 | | |
145 | 133k | return ((fdp.pData->length > 0) && |
146 | 133k | (fdp.pData->buffer[0] == FPH_CHAR_DOT) && |
147 | 0 | !osl_systemPathIsLocalOrParentDirectoryEntry(fdp.pData)); |
148 | 133k | } |
149 | | |
150 | | bool osl_systemPathIsLocalOrParentDirectoryEntry( |
151 | | const rtl_String* pstrPath) |
152 | 0 | { |
153 | 0 | OSL_PRECOND(pstrPath, "osl_systemPathIsLocalOrParentDirectoryEntry: Invalid parameter"); |
154 | |
|
155 | 0 | OString dirent; |
156 | |
|
157 | 0 | osl_systemPathGetFileNameOrLastDirectoryPart(pstrPath, &dirent.pData); |
158 | |
|
159 | 0 | return (dirent == "." || |
160 | 0 | dirent == ".."); |
161 | 0 | } |
162 | | |
163 | | namespace { |
164 | | |
165 | | /** Simple iterator for a path list separated by the specified character |
166 | | */ |
167 | | class path_list_iterator |
168 | | { |
169 | | public: |
170 | | |
171 | | /* after construction get_current_item |
172 | | returns the first path in list, no need |
173 | | to call reset first |
174 | | */ |
175 | | path_list_iterator(OUString path_list, sal_Unicode list_separator = FPH_CHAR_COLON) : |
176 | 0 | m_path_list(std::move(path_list)), |
177 | 0 | m_end(m_path_list.getStr() + m_path_list.getLength() + 1), |
178 | 0 | m_separator(list_separator) |
179 | 0 | { |
180 | 0 | reset(); |
181 | 0 | } |
182 | | |
183 | | path_list_iterator(const path_list_iterator&) = delete; |
184 | | path_list_iterator& operator=(const path_list_iterator&) = delete; |
185 | | |
186 | | void reset() |
187 | 0 | { |
188 | 0 | m_path_segment_begin = m_path_segment_end = m_path_list.getStr(); |
189 | 0 | advance(); |
190 | 0 | } |
191 | | |
192 | | void next() |
193 | 0 | { |
194 | 0 | OSL_PRECOND(!done(), "path_list_iterator: Already done!"); |
195 | |
|
196 | 0 | m_path_segment_begin = ++m_path_segment_end; |
197 | 0 | advance(); |
198 | 0 | } |
199 | | |
200 | | bool done() const |
201 | 0 | { |
202 | 0 | return (m_path_segment_end >= m_end); |
203 | 0 | } |
204 | | |
205 | | OUString get_current_item() const |
206 | 0 | { |
207 | 0 | return OUString( |
208 | 0 | m_path_segment_begin, |
209 | 0 | (m_path_segment_end - m_path_segment_begin)); |
210 | 0 | } |
211 | | |
212 | | private: |
213 | | /* move m_path_end to the next separator or |
214 | | to the end of the string |
215 | | */ |
216 | | void advance() |
217 | 0 | { |
218 | 0 | while (!done() && *m_path_segment_end && (*m_path_segment_end != m_separator)) |
219 | 0 | ++m_path_segment_end; |
220 | |
|
221 | 0 | OSL_ASSERT(m_path_segment_end <= m_end); |
222 | 0 | } |
223 | | |
224 | | private: |
225 | | OUString m_path_list; |
226 | | const sal_Unicode* m_end; |
227 | | const sal_Unicode m_separator; |
228 | | const sal_Unicode* m_path_segment_begin; |
229 | | const sal_Unicode* m_path_segment_end; |
230 | | }; |
231 | | |
232 | | } |
233 | | |
234 | | bool osl_searchPath( |
235 | | const rtl_uString* pustrFilePath, |
236 | | const rtl_uString* pustrSearchPathList, |
237 | | rtl_uString** ppustrPathFound) |
238 | 0 | { |
239 | 0 | OSL_PRECOND(pustrFilePath && pustrSearchPathList && ppustrPathFound, "osl_searchPath: Invalid parameter"); |
240 | |
|
241 | 0 | bool bfound = false; |
242 | 0 | OUString fp(const_cast<rtl_uString*>(pustrFilePath)); |
243 | 0 | OUString pl(const_cast<rtl_uString*>(pustrSearchPathList)); |
244 | 0 | path_list_iterator pli(pl); |
245 | |
|
246 | 0 | while (!pli.done()) |
247 | 0 | { |
248 | 0 | OUString p = pli.get_current_item(); |
249 | 0 | systemPathEnsureSeparator(&p); |
250 | 0 | p += fp; |
251 | |
|
252 | 0 | if (osl::access(osl::OUStringToOString(p), F_OK) > -1) |
253 | 0 | { |
254 | 0 | bfound = true; |
255 | 0 | rtl_uString_assign(ppustrPathFound, p.pData); |
256 | 0 | break; |
257 | 0 | } |
258 | 0 | pli.next(); |
259 | 0 | } |
260 | 0 | return bfound; |
261 | 0 | } |
262 | | |
263 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |