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 59 inline const rtl::OUString FPH_PATH_SEPARATOR() 60 { return rtl::OUString::createFromAscii("/"); } 61 inline const rtl::OUString FPH_LOCAL_DIR_ENTRY() 62 { return rtl::OUString::createFromAscii("."); } 63 inline const rtl::OUString FPH_PARENT_DIR_ENTRY() 64 { return rtl::OUString::createFromAscii(".."); } 65 66 /******************************************* 67 * osl_systemPathRemoveSeparator 68 ******************************************/ 69 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 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 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 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 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 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 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 *****************************************/ 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 *****************************************/ 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 *****************************************/ 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 *****************************************/ 258 bool done() const 259 { 260 return (m_path_segment_end >= m_end); 261 } 262 263 /****************************************** 264 return the current item 265 *****************************************/ 266 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 *****************************************/ 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 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