xref: /aoo4110/main/sal/osl/unx/file_path_helper.cxx (revision b1cdbd2c)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sal.hxx"
26 
27  /*******************************************
28  	Includes
29   ******************************************/
30 
31  #ifndef _OSL_FILE_PATH_HELPER_H_
32  #include "file_path_helper.h"
33  #endif
34 
35  #ifndef _OSL_FILE_PATH_HELPER_HXX_
36  #include "file_path_helper.hxx"
37  #endif
38 
39  #ifndef _OSL_UUNXAPI_HXX_
40  #include "uunxapi.hxx"
41  #endif
42 
43  #ifndef _OSL_DIAGNOSE_H_
44  #include <osl/diagnose.h>
45  #endif
46 
47  #ifndef _RTL_USTRING_HXX_
48  #include <rtl/ustring.hxx>
49  #endif
50 
51  /*******************************************
52  	Constants
53   ******************************************/
54 
55   const sal_Unicode FPH_CHAR_PATH_SEPARATOR = (sal_Unicode)'/';
56   const sal_Unicode FPH_CHAR_DOT            = (sal_Unicode)'.';
57   const sal_Unicode FPH_CHAR_COLON          = (sal_Unicode)':';
58 
FPH_PATH_SEPARATOR()59   inline const rtl::OUString FPH_PATH_SEPARATOR()
60       { return rtl::OUString::createFromAscii("/"); }
FPH_LOCAL_DIR_ENTRY()61   inline const rtl::OUString FPH_LOCAL_DIR_ENTRY()
62       { return rtl::OUString::createFromAscii("."); }
FPH_PARENT_DIR_ENTRY()63   inline const rtl::OUString FPH_PARENT_DIR_ENTRY()
64       { return rtl::OUString::createFromAscii(".."); }
65 
66  /*******************************************
67   *  osl_systemPathRemoveSeparator
68   ******************************************/
69 
osl_systemPathRemoveSeparator(rtl_uString * pustrPath)70  void SAL_CALL osl_systemPathRemoveSeparator(rtl_uString* pustrPath)
71  {
72  	OSL_PRECOND(0 != pustrPath, "osl_systemPathRemoveSeparator: Invalid parameter");
73     if (0 != pustrPath)
74     {
75         // maybe there are more than one separator at end
76         // so we run in a loop
77         while ((pustrPath->length > 1) && (FPH_CHAR_PATH_SEPARATOR == pustrPath->buffer[pustrPath->length - 1]))
78         {
79             pustrPath->length--;
80             pustrPath->buffer[pustrPath->length] = (sal_Unicode)'\0';
81         }
82 
83         OSL_POSTCOND((0 == pustrPath->length) || (1 == pustrPath->length) || \
84                      (pustrPath->length > 1 && pustrPath->buffer[pustrPath->length - 1] != FPH_CHAR_PATH_SEPARATOR), \
85                      "osl_systemPathRemoveSeparator: Post condition failed");
86     }
87  }
88 
89  /*******************************************
90     osl_systemPathEnsureSeparator
91   ******************************************/
92 
osl_systemPathEnsureSeparator(rtl_uString ** ppustrPath)93  void SAL_CALL osl_systemPathEnsureSeparator(rtl_uString** ppustrPath)
94  {
95      OSL_PRECOND((0 != ppustrPath) && (0 != *ppustrPath), "osl_systemPathEnsureSeparator: Invalid parameter");
96      if ((0 != ppustrPath) && (0 != *ppustrPath))
97      {
98          rtl::OUString path(*ppustrPath);
99          sal_Int32	  lp = path.getLength();
100          sal_Int32    i  = path.lastIndexOf(FPH_CHAR_PATH_SEPARATOR);
101 
102          if ((lp > 1 && i != (lp - 1)) || ((lp < 2) && i < 0))
103          {
104              path += FPH_PATH_SEPARATOR();
105              rtl_uString_assign(ppustrPath, path.pData);
106          }
107 
108          OSL_POSTCOND(path.lastIndexOf(FPH_CHAR_PATH_SEPARATOR) == (path.getLength() - 1), \
109                       "osl_systemPathEnsureSeparator: Post condition failed");
110      }
111  }
112 
113  /*******************************************
114   *  osl_systemPathIsRelativePath
115   ******************************************/
116 
osl_systemPathIsRelativePath(const rtl_uString * pustrPath)117  sal_Bool SAL_CALL osl_systemPathIsRelativePath(const rtl_uString* pustrPath)
118  {
119      OSL_PRECOND(0 != pustrPath, "osl_systemPathIsRelativePath: Invalid parameter");
120      return ((0 == pustrPath) || (0 == pustrPath->length) || (pustrPath->buffer[0] != FPH_CHAR_PATH_SEPARATOR));
121  }
122 
123  /******************************************
124     osl_systemPathMakeAbsolutePath
125   *****************************************/
126 
osl_systemPathMakeAbsolutePath(const rtl_uString * pustrBasePath,const rtl_uString * pustrRelPath,rtl_uString ** ppustrAbsolutePath)127  void SAL_CALL osl_systemPathMakeAbsolutePath(
128  	const rtl_uString* pustrBasePath,
129 	const rtl_uString* pustrRelPath,
130 	rtl_uString** 	   ppustrAbsolutePath)
131 {
132 	rtl::OUString base(rtl_uString_getStr(const_cast<rtl_uString*>(pustrBasePath)));
133 	rtl::OUString rel(const_cast<rtl_uString*>(pustrRelPath));
134 
135 	if (base.getLength() > 0)
136 		osl_systemPathEnsureSeparator(&base.pData);
137 
138 	base += rel;
139 
140 	rtl_uString_acquire(base.pData);
141 	*ppustrAbsolutePath = base.pData;
142 }
143 
144 
145  /*******************************************
146  	osl_systemPathGetFileOrLastDirectoryPart
147   ******************************************/
148 
osl_systemPathGetFileNameOrLastDirectoryPart(const rtl_uString * pustrPath,rtl_uString ** ppustrFileNameOrLastDirPart)149  void SAL_CALL osl_systemPathGetFileNameOrLastDirectoryPart(
150  	const rtl_uString* 	pustrPath,
151 	rtl_uString** 		ppustrFileNameOrLastDirPart)
152 {
153 	OSL_PRECOND(pustrPath && ppustrFileNameOrLastDirPart, \
154 			    "osl_systemPathGetFileNameOrLastDirectoryPart: Invalid parameter");
155 
156 	rtl::OUString path(const_cast<rtl_uString*>(pustrPath));
157 
158 	osl_systemPathRemoveSeparator(path.pData);
159 
160 	rtl::OUString last_part;
161 
162 	if (path.getLength() > 1 || (1 == path.getLength() && *path.getStr() != FPH_CHAR_PATH_SEPARATOR))
163 	{
164 		sal_Int32 idx_ps = path.lastIndexOf(FPH_CHAR_PATH_SEPARATOR);
165 		idx_ps++; // always right to increment by one even if idx_ps == -1!
166 		last_part = rtl::OUString(path.getStr() + idx_ps);
167 	}
168 	rtl_uString_assign(ppustrFileNameOrLastDirPart, last_part.pData);
169 }
170 
171 
172  /********************************************
173  	osl_systemPathIsHiddenFileOrDirectoryEntry
174  *********************************************/
175 
osl_systemPathIsHiddenFileOrDirectoryEntry(const rtl_uString * pustrPath)176  sal_Bool SAL_CALL osl_systemPathIsHiddenFileOrDirectoryEntry(
177  	const rtl_uString* pustrPath)
178 {
179 	OSL_PRECOND(0 != pustrPath, "osl_systemPathIsHiddenFileOrDirectoryEntry: Invalid parameter");
180     if ((0 == pustrPath) || (0 == pustrPath->length))
181         return sal_False;
182 
183     rtl::OUString fdp;
184     osl_systemPathGetFileNameOrLastDirectoryPart(pustrPath, &fdp.pData);
185 
186     return ((fdp.pData->length > 0) &&
187             (fdp.pData->buffer[0] == FPH_CHAR_DOT) &&
188             !osl_systemPathIsLocalOrParentDirectoryEntry(fdp.pData));
189 }
190 
191 
192  /************************************************
193  	osl_systemPathIsLocalOrParentDirectoryEntry
194  ************************************************/
195 
osl_systemPathIsLocalOrParentDirectoryEntry(const rtl_uString * pustrPath)196 sal_Bool SAL_CALL osl_systemPathIsLocalOrParentDirectoryEntry(
197 	const rtl_uString* pustrPath)
198 {
199 	OSL_PRECOND(pustrPath, "osl_systemPathIsLocalOrParentDirectoryEntry: Invalid parameter");
200 
201 	rtl::OUString dirent;
202 
203 	osl_systemPathGetFileNameOrLastDirectoryPart(pustrPath, &dirent.pData);
204 
205 	return (
206 	        (dirent == FPH_LOCAL_DIR_ENTRY()) ||
207 	        (dirent == FPH_PARENT_DIR_ENTRY())
208 	       );
209 }
210 
211 /***********************************************
212  Simple iterator for a path list separated by
213  the specified character
214  **********************************************/
215 
216 class path_list_iterator
217 {
218 public:
219 
220 	/******************************************
221  	 constructor
222 
223 	 after construction get_current_item
224 	 returns the first path in list, no need
225 	 to call reset first
226 	 *****************************************/
path_list_iterator(const rtl::OUString & path_list,sal_Unicode list_separator=FPH_CHAR_COLON)227 	path_list_iterator(const rtl::OUString& path_list, sal_Unicode list_separator = FPH_CHAR_COLON) :
228 		m_path_list(path_list),
229 		m_end(m_path_list.getStr() + m_path_list.getLength() + 1),
230 		m_separator(list_separator)
231 	{
232 		reset();
233 	}
234 
235 	/******************************************
236 	 reset the iterator
237 	 *****************************************/
reset()238 	void reset()
239 	{
240 		m_path_segment_begin = m_path_segment_end = m_path_list.getStr();
241 		advance();
242 	}
243 
244 	/******************************************
245 	 move the iterator to the next position
246 	 *****************************************/
next()247 	void next()
248 	{
249 		OSL_PRECOND(!done(), "path_list_iterator: Already done!");
250 
251 		m_path_segment_begin = ++m_path_segment_end;
252 		advance();
253 	}
254 
255 	/******************************************
256 	 check if done
257 	 *****************************************/
done() const258 	bool done() const
259 	{
260 		return (m_path_segment_end >= m_end);
261 	}
262 
263 	/******************************************
264 	 return the current item
265 	 *****************************************/
get_current_item() const266 	rtl::OUString get_current_item() const
267 	{
268 		return rtl::OUString(
269 			m_path_segment_begin,
270 			(m_path_segment_end - m_path_segment_begin));
271 	}
272 
273 private:
274 
275 	/******************************************
276 	 move m_path_end to the next separator or
277 	 to the edn of the string
278 	 *****************************************/
advance()279 	void advance()
280 	{
281 		while (!done() && *m_path_segment_end && (*m_path_segment_end != m_separator))
282 			++m_path_segment_end;
283 
284 		OSL_ASSERT(m_path_segment_end <= m_end);
285 	}
286 
287 private:
288 	rtl::OUString 		m_path_list;
289 	const sal_Unicode*  m_end;
290 	const sal_Unicode 	m_separator;
291 	const sal_Unicode*  m_path_segment_begin;
292 	const sal_Unicode*  m_path_segment_end;
293 
294 // prevent copy and assignment
295 private:
296 	/******************************************
297 	 copy constructor
298 	 remember: do not simply copy m_path_begin
299 	 and m_path_end because they point to
300 	 the memory of other.m_path_list!
301 	 *****************************************/
302 	path_list_iterator(const path_list_iterator& other);
303 
304 	/******************************************
305 	 assignment operator
306  	 remember: do not simply copy m_path_begin
307 	 and m_path_end because they point to
308 	 the memory of other.m_path_list!
309 	 *****************************************/
310 	path_list_iterator& operator=(const path_list_iterator& other);
311 };
312 
313  /************************************************
314   	osl_searchPath
315   ***********************************************/
316 
osl_searchPath(const rtl_uString * pustrFilePath,const rtl_uString * pustrSearchPathList,rtl_uString ** ppustrPathFound)317 sal_Bool SAL_CALL osl_searchPath(
318  	const rtl_uString* pustrFilePath,
319 	const rtl_uString* pustrSearchPathList,
320 	rtl_uString**      ppustrPathFound)
321 {
322 	OSL_PRECOND(pustrFilePath && pustrSearchPathList && ppustrPathFound, "osl_searchPath: Invalid parameter");
323 
324 	bool               bfound = false;
325 	rtl::OUString      fp(const_cast<rtl_uString*>(pustrFilePath));
326 	rtl::OUString      pl = rtl::OUString(const_cast<rtl_uString*>(pustrSearchPathList));
327 	path_list_iterator pli(pl);
328 
329 	while (!pli.done())
330 	{
331 		rtl::OUString p = pli.get_current_item();
332 		osl::systemPathEnsureSeparator(p);
333 		p += fp;
334 
335 		if (osl::access(p, F_OK) > -1)
336 		{
337 			bfound = true;
338 			rtl_uString_assign(ppustrPathFound, p.pData);
339 			break;
340 		}
341 		pli.next();
342 	}
343 	return bfound;
344 }
345