xref: /trunk/main/sal/osl/os2/file_path_helper.cxx (revision 87d2adbc)
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  /*******************************************
25  	Includes
26   ******************************************/
27 
28  #ifndef _OSL_THREAD_H_
29  #include "osl/thread.h"
30  #endif
31 
32  #ifndef _OSL_FILE_PATH_HELPER_H_
33  #include "file_path_helper.h"
34  #endif
35 
36  #ifndef _OSL_FILE_PATH_HELPER_HXX_
37  #include "file_path_helper.hxx"
38  #endif
39 
40  #ifndef _OSL_UUNXAPI_HXX_
41  #include "uunxapi.hxx"
42  #endif
43 
44  #ifndef _OSL_DIAGNOSE_H_
45  #include <osl/diagnose.h>
46  #endif
47 
48  #ifndef _RTL_USTRING_HXX_
49  #include <rtl/ustring.hxx>
50  #endif
51 
52  /*******************************************
53  	Constants
54   ******************************************/
55 
56   const sal_Unicode FPH_CHAR_PATH_SEPARATOR = (sal_Unicode)'\\';
57   const sal_Unicode FPH_CHAR_DOT            = (sal_Unicode)'.';
58   const sal_Unicode FPH_CHAR_COLON          = (sal_Unicode)':';
59 
FPH_PATH_SEPARATOR()60   inline const rtl::OUString FPH_PATH_SEPARATOR()
61       { return rtl::OUString::createFromAscii("\\"); }
FPH_LOCAL_DIR_ENTRY()62   inline const rtl::OUString FPH_LOCAL_DIR_ENTRY()
63       { return rtl::OUString::createFromAscii("."); }
FPH_PARENT_DIR_ENTRY()64   inline const rtl::OUString FPH_PARENT_DIR_ENTRY()
65       { return rtl::OUString::createFromAscii(".."); }
66 
67  /*******************************************
68   *  osl_systemPathRemoveSeparator
69   ******************************************/
70 
osl_systemPathRemoveSeparator(rtl_uString * pustrPath)71  void SAL_CALL osl_systemPathRemoveSeparator(rtl_uString* pustrPath)
72  {
73  	OSL_PRECOND(pustrPath, "osl_systemPathRemoveSeparator: Invalid parameter");
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     osl_systemPathEnsureSeparator
90   ******************************************/
91 
osl_systemPathEnsureSeparator(rtl_uString ** ppustrPath)92  void SAL_CALL osl_systemPathEnsureSeparator(rtl_uString** ppustrPath)
93  {
94  	OSL_PRECOND(ppustrPath && (NULL != *ppustrPath), \
95 				"osl_systemPathEnsureSeparator: Invalid parameter");
96 
97  	rtl::OUString path(*ppustrPath);
98 	sal_Int32	  lp = path.getLength();
99 	sal_Int32     i  = path.lastIndexOf(FPH_CHAR_PATH_SEPARATOR);
100 
101 	if ((lp > 1 && i != (lp - 1)) || ((lp < 2) && i < 0))
102 	{
103 		path += FPH_PATH_SEPARATOR();
104 		rtl_uString_assign(ppustrPath, path.pData);
105 	}
106 
107 	OSL_POSTCOND(path.lastIndexOf(FPH_CHAR_PATH_SEPARATOR) == (path.getLength() - 1), \
108 				 "osl_systemPathEnsureSeparator: Post condition failed");
109  }
110 
111  /*******************************************
112   *  osl_systemPathIsRelativePath
113   ******************************************/
114 
osl_systemPathIsRelativePath(const rtl_uString * pustrPath)115  sal_Bool SAL_CALL osl_systemPathIsRelativePath(const rtl_uString* pustrPath)
116  {
117  	OSL_PRECOND(pustrPath, "osl_systemPathIsRelativePath: Invalid parameter");
118  	return (!osl_systemPathIsAbsolutePath(pustrPath));
119  }
120 
121  /******************************************
122   *  osl_systemPathIsAbsolutePath
123   *****************************************/
124 
osl_systemPathIsAbsolutePath(const rtl_uString * pustrPath)125  sal_Bool SAL_CALL osl_systemPathIsAbsolutePath(const rtl_uString* pustrPath)
126  {
127  	OSL_PRECOND(pustrPath, "osl_systemPathIsAbsolutePath: Invalid parameter");
128 	if (pustrPath->length == 0)
129 		return sal_False;
130 	if (pustrPath->buffer[0] == FPH_CHAR_PATH_SEPARATOR)
131 		return sal_True;
132 	if (pustrPath->buffer[1] == FPH_CHAR_COLON
133 		    && pustrPath->buffer[2] == FPH_CHAR_PATH_SEPARATOR)
134 		return sal_True;
135 	return sal_False;
136  }
137 
138  /******************************************
139     osl_systemPathMakeAbsolutePath
140   *****************************************/
141 
osl_systemPathMakeAbsolutePath(const rtl_uString * pustrBasePath,const rtl_uString * pustrRelPath,rtl_uString ** ppustrAbsolutePath)142  void SAL_CALL osl_systemPathMakeAbsolutePath(
143  	const rtl_uString* pustrBasePath,
144 	const rtl_uString* pustrRelPath,
145 	rtl_uString** 	   ppustrAbsolutePath)
146 {
147 	rtl::OUString base(rtl_uString_getStr(const_cast<rtl_uString*>(pustrBasePath)));
148 	rtl::OUString rel(const_cast<rtl_uString*>(pustrRelPath));
149 
150 	if (base.getLength() > 0)
151 		osl_systemPathEnsureSeparator(&base.pData);
152 
153 	base += rel;
154 
155 	rtl_uString_acquire(base.pData);
156 	*ppustrAbsolutePath = base.pData;
157 }
158 
159 
160  /*****************************************
161 	osl_systemPathGetParent
162   ****************************************/
163 
osl_systemPathGetParent(rtl_uString * pustrPath)164  sal_Int32 SAL_CALL osl_systemPathGetParent(rtl_uString* pustrPath)
165  {
166  	return 0;
167  }
168 
169  /*******************************************
170  	osl_systemPathGetFileOrLastDirectoryPart
171   ******************************************/
172 
osl_systemPathGetFileNameOrLastDirectoryPart(const rtl_uString * pustrPath,rtl_uString ** ppustrFileNameOrLastDirPart)173  void SAL_CALL osl_systemPathGetFileNameOrLastDirectoryPart(
174  	const rtl_uString* 	pustrPath,
175 	rtl_uString** 		ppustrFileNameOrLastDirPart)
176 {
177 	OSL_PRECOND(pustrPath && ppustrFileNameOrLastDirPart, \
178 			    "osl_systemPathGetFileNameOrLastDirectoryPart: Invalid parameter");
179 
180 	rtl::OUString path(const_cast<rtl_uString*>(pustrPath));
181 
182 	osl_systemPathRemoveSeparator(path.pData);
183 
184 	rtl::OUString last_part;
185 
186 	if (path.getLength() > 1 || (1 == path.getLength() && *path.getStr() != FPH_CHAR_PATH_SEPARATOR))
187 	{
188 		sal_Int32 idx_ps = path.lastIndexOf(FPH_CHAR_PATH_SEPARATOR);
189 		idx_ps++; // always right to increment by one even if idx_ps == -1!
190 		last_part = rtl::OUString(path.getStr() + idx_ps);
191 	}
192 	rtl_uString_assign(ppustrFileNameOrLastDirPart, last_part.pData);
193 }
194 
195 
196  /********************************************
197  	osl_systemPathIsHiddenFileOrDirectoryEntry
198  *********************************************/
199 
osl_systemPathIsHiddenFileOrDirectoryEntry(const rtl_uString * pustrPath)200  sal_Bool SAL_CALL osl_systemPathIsHiddenFileOrDirectoryEntry(
201  	const rtl_uString* pustrPath)
202 {
203 	OSL_PRECOND(pustrPath, "osl_systemPathIsHiddenFileOrDirectoryEntry: Invalid parameter");
204 
205 	sal_Bool is_hidden = sal_False;
206 
207 	if (pustrPath->length > 0)
208 	{
209 		rtl::OUString fdp;
210 
211 		osl_systemPathGetFileNameOrLastDirectoryPart(pustrPath, &fdp.pData);
212 
213 		is_hidden = ((fdp.pData->length > 0) && (fdp.pData->buffer[0] == FPH_CHAR_DOT) &&
214 					 !osl_systemPathIsLocalOrParentDirectoryEntry(fdp.pData));
215  	}
216 
217 	return is_hidden;
218 }
219 
220 
221  /************************************************
222  	osl_systemPathIsLocalOrParentDirectoryEntry
223  ************************************************/
224 
osl_systemPathIsLocalOrParentDirectoryEntry(const rtl_uString * pustrPath)225 sal_Bool SAL_CALL osl_systemPathIsLocalOrParentDirectoryEntry(
226 	const rtl_uString* pustrPath)
227 {
228 	OSL_PRECOND(pustrPath, "osl_systemPathIsLocalOrParentDirectoryEntry: Invalid parameter");
229 
230 	rtl::OUString dirent;
231 
232 	osl_systemPathGetFileNameOrLastDirectoryPart(pustrPath, &dirent.pData);
233 
234 	return (
235 	        (dirent == FPH_LOCAL_DIR_ENTRY()) ||
236 	        (dirent == FPH_PARENT_DIR_ENTRY())
237 	       );
238 }
239 
240 /***********************************************
241  Simple iterator for a path list separated by
242  the specified character
243  **********************************************/
244 
245 class path_list_iterator
246 {
247 public:
248 
249 	/******************************************
250  	 constructor
251 
252 	 after construction get_current_item
253 	 returns the first path in list, no need
254 	 to call reset first
255 	 *****************************************/
path_list_iterator(const rtl::OUString & path_list,sal_Unicode list_separator=FPH_CHAR_COLON)256 	path_list_iterator(const rtl::OUString& path_list, sal_Unicode list_separator = FPH_CHAR_COLON) :
257 		m_path_list(path_list),
258 		m_end(m_path_list.getStr() + m_path_list.getLength() + 1),
259 		m_separator(list_separator)
260 	{
261 		reset();
262 	}
263 
264 	/******************************************
265 	 reset the iterator
266 	 *****************************************/
reset()267 	void reset()
268 	{
269 		m_path_segment_begin = m_path_segment_end = m_path_list.getStr();
270 		advance();
271 	}
272 
273 	/******************************************
274 	 move the iterator to the next position
275 	 *****************************************/
next()276 	void next()
277 	{
278 		OSL_PRECOND(!done(), "path_list_iterator: Already done!");
279 
280 		m_path_segment_begin = ++m_path_segment_end;
281 		advance();
282 	}
283 
284 	/******************************************
285 	 check if done
286 	 *****************************************/
done() const287 	bool done() const
288 	{
289 		return (m_path_segment_end >= m_end);
290 	}
291 
292 	/******************************************
293 	 return the current item
294 	 *****************************************/
get_current_item() const295 	rtl::OUString get_current_item() const
296 	{
297 		return rtl::OUString(
298 			m_path_segment_begin,
299 			(m_path_segment_end - m_path_segment_begin));
300 	}
301 
302 private:
303 
304 	/******************************************
305 	 move m_path_end to the next separator or
306 	 to the edn of the string
307 	 *****************************************/
advance()308 	void advance()
309 	{
310 		while (!done() && *m_path_segment_end && (*m_path_segment_end != m_separator))
311 			++m_path_segment_end;
312 
313 		OSL_ASSERT(m_path_segment_end <= m_end);
314 	}
315 
316 private:
317 	rtl::OUString 		m_path_list;
318 	const sal_Unicode*  m_end;
319 	const sal_Unicode 	m_separator;
320 	const sal_Unicode*  m_path_segment_begin;
321 	const sal_Unicode*  m_path_segment_end;
322 
323 // prevent copy and assignment
324 private:
325 	/******************************************
326 	 copy constructor
327 	 remember: do not simply copy m_path_begin
328 	 and m_path_end because they point to
329 	 the memory of other.m_path_list!
330 	 *****************************************/
331 	path_list_iterator(const path_list_iterator& other);
332 
333 	/******************************************
334 	 assignment operator
335  	 remember: do not simply copy m_path_begin
336 	 and m_path_end because they point to
337 	 the memory of other.m_path_list!
338 	 *****************************************/
339 	path_list_iterator& operator=(const path_list_iterator& other);
340 };
341 
342  /************************************************
343   	osl_searchPath
344   ***********************************************/
345 
osl_searchPath(const rtl_uString * pustrFilePath,const rtl_uString * pustrSearchPathList,rtl_uString ** ppustrPathFound)346 sal_Bool SAL_CALL osl_searchPath(
347  	const rtl_uString* pustrFilePath,
348 	const rtl_uString* pustrSearchPathList,
349 	rtl_uString**      ppustrPathFound)
350 {
351 	OSL_PRECOND(pustrFilePath && pustrSearchPathList && ppustrPathFound, "osl_searchPath: Invalid parameter");
352 
353 	bool               bfound = false;
354 	rtl::OUString      fp(const_cast<rtl_uString*>(pustrFilePath));
355 	rtl::OUString      pl = rtl::OUString(const_cast<rtl_uString*>(pustrSearchPathList));
356 	path_list_iterator pli(pl);
357 
358 	while (!pli.done())
359 	{
360 		rtl::OUString p = pli.get_current_item();
361 		osl::systemPathEnsureSeparator(p);
362 		p += fp;
363 
364 		if (osl::access(p, F_OK) > -1)
365 		{
366 			bfound = true;
367 			rtl_uString_assign(ppustrPathFound, p.pData);
368 			break;
369 		}
370 		pli.next();
371 	}
372 	return bfound;
373 }
374