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