xref: /AOO41X/main/sal/osl/unx/file_path_helper.cxx (revision 87d2adbc9cadf14644c3679b041b9226f7630199)
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