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
24 #include "file_path_helper.hxx"
25 #include "uunxapi.hxx"
26
27 #include <osl/diagnose.h>
28 #include <rtl/ustring.hxx>
29 #include <sal/log.hxx>
30
31 const sal_Unicode FPH_CHAR_PATH_SEPARATOR = '/';
32 const sal_Unicode FPH_CHAR_DOT = '.';
33 const sal_Unicode FPH_CHAR_COLON = ':';
34
osl_systemPathRemoveSeparator(rtl_String * pstrPath)35 void osl_systemPathRemoveSeparator(rtl_String* pstrPath)
36 {
37 OSL_PRECOND(nullptr != pstrPath, "osl_systemPathRemoveSeparator: Invalid parameter");
38 if (pstrPath != nullptr)
39 {
40 // maybe there are more than one separator at end
41 // so we run in a loop
42 while ((pstrPath->length > 1) && (pstrPath->buffer[pstrPath->length - 1] == FPH_CHAR_PATH_SEPARATOR))
43 {
44 pstrPath->length--;
45 pstrPath->buffer[pstrPath->length] = '\0';
46 }
47
48 SAL_WARN_IF( !((0 == pstrPath->length) || (1 == pstrPath->length) ||
49 (pstrPath->length > 1 && pstrPath->buffer[pstrPath->length - 1] != FPH_CHAR_PATH_SEPARATOR)),
50 "sal.osl",
51 "osl_systemPathRemoveSeparator: Post condition failed");
52 }
53 }
54
55 namespace {
56
systemPathEnsureSeparator(T * ppstrPath)57 template<typename T> void systemPathEnsureSeparator(T* ppstrPath)
58 {
59 assert(nullptr != ppstrPath);
60 sal_Int32 lp = ppstrPath->getLength();
61 sal_Int32 i = ppstrPath->lastIndexOf(FPH_CHAR_PATH_SEPARATOR);
62
63 if ((lp > 1 && i != (lp - 1)) || ((lp < 2) && i < 0))
64 {
65 *ppstrPath += "/";
66 }
67
68 SAL_WARN_IF( !ppstrPath->endsWith("/"),
69 "sal.osl",
70 "systemPathEnsureSeparator: Post condition failed");
71 }
72
73 }
74
osl_systemPathIsRelativePath(const rtl_uString * pustrPath)75 bool osl_systemPathIsRelativePath(const rtl_uString* pustrPath)
76 {
77 OSL_PRECOND(nullptr != pustrPath, "osl_systemPathIsRelativePath: Invalid parameter");
78 return ((pustrPath == nullptr) || (pustrPath->length == 0) || (pustrPath->buffer[0] != FPH_CHAR_PATH_SEPARATOR));
79 }
80
81 namespace {
82
systemPathMakeAbsolutePath_(const T & BasePath,const T & RelPath)83 template<typename T> T systemPathMakeAbsolutePath_(
84 const T& BasePath,
85 const T& RelPath)
86 {
87 T base(BasePath);
88
89 if (!base.isEmpty())
90 systemPathEnsureSeparator(&base);
91
92 return base + RelPath;
93 }
94
95 }
96
systemPathMakeAbsolutePath(const OString & BasePath,const OString & RelPath)97 OString osl::systemPathMakeAbsolutePath(
98 const OString& BasePath,
99 const OString& RelPath)
100 {
101 return systemPathMakeAbsolutePath_(BasePath, RelPath);
102 }
103
systemPathMakeAbsolutePath(const OUString & BasePath,const OUString & RelPath)104 OUString osl::systemPathMakeAbsolutePath(
105 const OUString& BasePath,
106 const OUString& RelPath)
107 {
108 return systemPathMakeAbsolutePath_(BasePath, RelPath);
109 }
110
osl_systemPathGetFileNameOrLastDirectoryPart(const rtl_String * pstrPath,rtl_String ** ppstrFileNameOrLastDirPart)111 void osl_systemPathGetFileNameOrLastDirectoryPart(
112 const rtl_String* pstrPath,
113 rtl_String** ppstrFileNameOrLastDirPart)
114 {
115 OSL_PRECOND(pstrPath && ppstrFileNameOrLastDirPart,
116 "osl_systemPathGetFileNameOrLastDirectoryPart: Invalid parameter");
117
118 OString path(const_cast<rtl_String*>(pstrPath));
119
120 osl_systemPathRemoveSeparator(path.pData);
121
122 OString last_part;
123
124 if (path.getLength() > 1 || (path.getLength() == 1 && path[0] != FPH_CHAR_PATH_SEPARATOR))
125 {
126 sal_Int32 idx_ps = path.lastIndexOf(FPH_CHAR_PATH_SEPARATOR);
127 idx_ps++; // always right to increment by one even if idx_ps == -1!
128 last_part = path.copy(idx_ps);
129 }
130 rtl_string_assign(ppstrFileNameOrLastDirPart, last_part.pData);
131 }
132
osl_systemPathIsHiddenFileOrDirectoryEntry(const rtl_String * pstrPath)133 bool osl_systemPathIsHiddenFileOrDirectoryEntry(
134 const rtl_String* pstrPath)
135 {
136 OSL_PRECOND(nullptr != pstrPath, "osl_systemPathIsHiddenFileOrDirectoryEntry: Invalid parameter");
137 if ((pstrPath == nullptr) || (pstrPath->length == 0))
138 return false;
139
140 OString fdp;
141 osl_systemPathGetFileNameOrLastDirectoryPart(pstrPath, &fdp.pData);
142
143 return ((fdp.pData->length > 0) &&
144 (fdp.pData->buffer[0] == FPH_CHAR_DOT) &&
145 !osl_systemPathIsLocalOrParentDirectoryEntry(fdp.pData));
146 }
147
osl_systemPathIsLocalOrParentDirectoryEntry(const rtl_String * pstrPath)148 bool osl_systemPathIsLocalOrParentDirectoryEntry(
149 const rtl_String* pstrPath)
150 {
151 OSL_PRECOND(pstrPath, "osl_systemPathIsLocalOrParentDirectoryEntry: Invalid parameter");
152
153 OString dirent;
154
155 osl_systemPathGetFileNameOrLastDirectoryPart(pstrPath, &dirent.pData);
156
157 return (dirent == "." ||
158 dirent == "..");
159 }
160
161 /** Simple iterator for a path list separated by the specified character
162 */
163 class path_list_iterator
164 {
165 public:
166
167 /* after construction get_current_item
168 returns the first path in list, no need
169 to call reset first
170 */
path_list_iterator(const OUString & path_list,sal_Unicode list_separator=FPH_CHAR_COLON)171 path_list_iterator(const OUString& path_list, sal_Unicode list_separator = FPH_CHAR_COLON) :
172 m_path_list(path_list),
173 m_end(m_path_list.getStr() + m_path_list.getLength() + 1),
174 m_separator(list_separator)
175 {
176 reset();
177 }
178
179 path_list_iterator(const path_list_iterator&) = delete;
180 path_list_iterator& operator=(const path_list_iterator&) = delete;
181
reset()182 void reset()
183 {
184 m_path_segment_begin = m_path_segment_end = m_path_list.getStr();
185 advance();
186 }
187
next()188 void next()
189 {
190 OSL_PRECOND(!done(), "path_list_iterator: Already done!");
191
192 m_path_segment_begin = ++m_path_segment_end;
193 advance();
194 }
195
done() const196 bool done() const
197 {
198 return (m_path_segment_end >= m_end);
199 }
200
get_current_item() const201 OUString get_current_item() const
202 {
203 return OUString(
204 m_path_segment_begin,
205 (m_path_segment_end - m_path_segment_begin));
206 }
207
208 private:
209 /* move m_path_end to the next separator or
210 to the end of the string
211 */
advance()212 void advance()
213 {
214 while (!done() && *m_path_segment_end && (*m_path_segment_end != m_separator))
215 ++m_path_segment_end;
216
217 OSL_ASSERT(m_path_segment_end <= m_end);
218 }
219
220 private:
221 OUString const m_path_list;
222 const sal_Unicode* m_end;
223 const sal_Unicode m_separator;
224 const sal_Unicode* m_path_segment_begin;
225 const sal_Unicode* m_path_segment_end;
226 };
227
osl_searchPath(const rtl_uString * pustrFilePath,const rtl_uString * pustrSearchPathList,rtl_uString ** ppustrPathFound)228 bool osl_searchPath(
229 const rtl_uString* pustrFilePath,
230 const rtl_uString* pustrSearchPathList,
231 rtl_uString** ppustrPathFound)
232 {
233 OSL_PRECOND(pustrFilePath && pustrSearchPathList && ppustrPathFound, "osl_searchPath: Invalid parameter");
234
235 bool bfound = false;
236 OUString fp(const_cast<rtl_uString*>(pustrFilePath));
237 OUString pl(const_cast<rtl_uString*>(pustrSearchPathList));
238 path_list_iterator pli(pl);
239
240 while (!pli.done())
241 {
242 OUString p = pli.get_current_item();
243 systemPathEnsureSeparator(&p);
244 p += fp;
245
246 if (osl::access(osl::OUStringToOString(p), F_OK) > -1)
247 {
248 bfound = true;
249 rtl_uString_assign(ppustrPathFound, p.pData);
250 break;
251 }
252 pli.next();
253 }
254 return bfound;
255 }
256
257 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
258