1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
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.
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).
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.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sal.hxx"
40 #include "osl/file.hxx"
41 #include <osl/security.h>
42 #include <osl/diagnose.h>
43 #include <osl/thread.h>
44 #include <osl/process.h>
47 #include <rtl/ustring.hxx>
48 #include <rtl/ustrbuf.h>
49 #include "rtl/textcvt.h"
51 #include "file_error_transl.h"
52 #include "file_path_helper.hxx"
54 #include "uunxapi.hxx"
56 /***************************************************
60 This file contains the part that handles File URLs.
62 File URLs as scheme specific notion of URIs
63 (RFC2396) may be handled platform independend, but
64 will not in osl which is considered wrong.
65 Future version of osl should handle File URLs this
66 way. In rtl/uri there is already an URI parser etc.
67 so this code should be consolidated.
69 **************************************************/
70 /************************************************************************
73 * Fix osl_getCanonicalName
75 ***********************************************************************/
78 /***************************************************
79 * namespace directives
80 **************************************************/
84 /***************************************************
86 **************************************************/
88 const sal_Unicode UNICHAR_SLASH
= ((sal_Unicode
)'/');
89 const sal_Unicode UNICHAR_COLON
= ((sal_Unicode
)':');
90 const sal_Unicode UNICHAR_DOT
= ((sal_Unicode
)'.');
92 /******************************************************************************
94 * Exported Module Functions
96 *****************************************************************************/
98 /* a slightly modified version of Pchar in rtl/source/uri.c */
99 const sal_Bool uriCharClass
[128] =
101 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Pchar but without encoding slashes */
102 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
103 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* !"#$%&'()*+,-./ */
104 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, /* 0123456789:;<=>? */
105 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ABCDEFGHIJKLMNO */
106 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* PQRSTUVWXYZ[\]^_ */
107 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* `abcdefghijklmno */
108 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0 /* pqrstuvwxyz{|}~ */
112 /* check for top wrong usage strings */
114 static sal_Bool findWrongUsage( const sal_Unicode *path, sal_Int32 len )
116 rtl_uString *pTmp = NULL;
119 rtl_uString_newFromStr_WithLength( &pTmp, path, len );
121 rtl_ustr_toAsciiLowerCase_WithLength( pTmp->buffer, pTmp->length );
123 bRet = ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "ftp://", 6 ) ) ||
124 ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "http://", 7 ) ) ||
125 ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "vnd.sun.star", 12 ) ) ||
126 ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "private:", 8 ) ) ||
127 ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "slot:", 5) );
129 rtl_uString_release( pTmp );
134 /****************************************************************************/
135 /* osl_getCanonicalName */
136 /****************************************************************************/
138 oslFileError SAL_CALL
osl_getCanonicalName( rtl_uString
* ustrFileURL
, rtl_uString
** pustrValidURL
)
140 OSL_ENSURE(0, "osl_getCanonicalName not implemented");
142 rtl_uString_newFromString(pustrValidURL
, ustrFileURL
);
143 return osl_File_E_None
;
146 /****************************************************************************/
147 /* osl_getSystemPathFromFileURL */
148 /****************************************************************************/
150 oslFileError SAL_CALL
osl_getSystemPathFromFileURL( rtl_uString
*ustrFileURL
, rtl_uString
**pustrSystemPath
)
153 rtl_uString
* pTmp
= NULL
;
155 sal_Unicode encodedSlash
[3] = { '%', '2', 'F' };
156 sal_Unicode protocolDelimiter
[3] = { ':', '/', '/' };
158 /* temporary hack: if already system path, return ustrFileURL */
160 if( (sal_Unicode) '/' == ustrFileURL->buffer[0] )
162 OSL_ENSURE( 0, "osl_getSystemPathFromFileURL: input is already system path" );
163 rtl_uString_assign( pustrSystemPath, ustrFileURL );
164 return osl_File_E_None;
168 /* a valid file url may not start with '/' */
169 if( ( 0 == ustrFileURL
->length
) || ( (sal_Unicode
) '/' == ustrFileURL
->buffer
[0] ) )
171 return osl_File_E_INVAL
;
174 /* Check for non file:// protocols */
176 nIndex
= rtl_ustr_indexOfStr_WithLength( ustrFileURL
->buffer
, ustrFileURL
->length
, protocolDelimiter
, 3 );
177 if ( -1 != nIndex
&& (4 != nIndex
|| 0 != rtl_ustr_ascii_shortenedCompare_WithLength( ustrFileURL
->buffer
, ustrFileURL
->length
,"file", 4 ) ) )
179 return osl_File_E_INVAL
;
182 /* search for encoded slashes (%2F) and decode every single token if we find one */
186 if( -1 != rtl_ustr_indexOfStr_WithLength( ustrFileURL
->buffer
, ustrFileURL
->length
, encodedSlash
, 3 ) )
188 rtl_uString
* ustrPathToken
= NULL
;
189 sal_Int32 nOffset
= 7;
195 /* break url down in '/' devided tokens tokens */
196 nIndex
= rtl_ustr_indexOfChar_WithLength( ustrFileURL
->buffer
+ nOffset
, ustrFileURL
->length
- nOffset
, (sal_Unicode
) '/' );
198 /* copy token to new string */
199 rtl_uString_newFromStr_WithLength( &ustrPathToken
, ustrFileURL
->buffer
+ nOffset
,
200 -1 == nIndex
? ustrFileURL
->length
- nOffset
: nIndex
++ );
203 rtl_uriDecode( ustrPathToken
, rtl_UriDecodeWithCharset
, RTL_TEXTENCODING_UTF8
, &pTmp
);
205 /* the result should not contain any '/' */
206 if( -1 != rtl_ustr_indexOfChar_WithLength( pTmp
->buffer
, pTmp
->length
, (sal_Unicode
) '/' ) )
208 rtl_uString_release( pTmp
);
209 rtl_uString_release( ustrPathToken
);
211 return osl_File_E_INVAL
;
214 } while( -1 != nIndex
);
216 /* release temporary string and restore index variable */
217 rtl_uString_release( ustrPathToken
);
221 /* protocol and server should not be encoded, so decode the whole string */
222 rtl_uriDecode( ustrFileURL
, rtl_UriDecodeWithCharset
, RTL_TEXTENCODING_UTF8
, &pTmp
);
224 /* check if file protocol specified */
225 /* FIXME: use rtl_ustr_ascii_shortenedCompareIgnoreCase_WithLength when available */
226 if( 7 <= pTmp
->length
)
228 rtl_uString
* pProtocol
= NULL
;
229 rtl_uString_newFromStr_WithLength( &pProtocol
, pTmp
->buffer
, 7 );
231 /* protocol is case insensitive */
232 rtl_ustr_toAsciiLowerCase_WithLength( pProtocol
->buffer
, pProtocol
->length
);
234 if( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pProtocol
->buffer
, pProtocol
->length
,"file://", 7 ) )
237 rtl_uString_release( pProtocol
);
240 /* skip "localhost" or "127.0.0.1" if "file://" is specified */
241 /* FIXME: use rtl_ustr_ascii_shortenedCompareIgnoreCase_WithLength when available */
242 if( nIndex
&& ( 10 <= pTmp
->length
- nIndex
) )
244 rtl_uString
* pServer
= NULL
;
245 rtl_uString_newFromStr_WithLength( &pServer
, pTmp
->buffer
+ nIndex
, 10 );
247 /* server is case insensitive */
248 rtl_ustr_toAsciiLowerCase_WithLength( pServer
->buffer
, pServer
->length
);
250 if( ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pServer
->buffer
, pServer
->length
,"localhost/", 10 ) ) ||
251 ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pServer
->buffer
, pServer
->length
,"127.0.0.1/", 10 ) ) )
253 /* don't exclude the '/' */
257 rtl_uString_release( pServer
);
261 rtl_uString_newFromStr_WithLength( &pTmp
, pTmp
->buffer
+ nIndex
, pTmp
->length
- nIndex
);
263 /* check if system path starts with ~ or ~user and replace it with the appropriate home dir */
264 if( (sal_Unicode
) '~' == pTmp
->buffer
[0] )
266 /* check if another user is specified */
267 if( ( 1 == pTmp
->length
) || ( (sal_Unicode
)'/' == pTmp
->buffer
[1] ) )
269 rtl_uString
*pTmp2
= NULL
;
271 /* osl_getHomeDir returns file URL */
272 osl_getHomeDir( osl_getCurrentSecurity(), &pTmp2
);
274 /* remove "file://" prefix */
275 rtl_uString_newFromStr_WithLength( &pTmp2
, pTmp2
->buffer
+ 7, pTmp2
->length
- 7 );
277 /* replace '~' in original string */
278 rtl_uString_newReplaceStrAt( &pTmp
, pTmp
, 0, 1, pTmp2
);
279 rtl_uString_release( pTmp2
);
284 /* FIXME: replace ~user with users home directory */
285 return osl_File_E_INVAL
;
289 /* temporary check for top 5 wrong usage strings (which are valid but unlikly filenames) */
291 OSL_ASSERT( !findWrongUsage( pTmp->buffer, pTmp->length ) );
294 *pustrSystemPath
= pTmp
;
295 return osl_File_E_None
;
298 /****************************************************************************/
299 /* osl_getFileURLFromSystemPath */
300 /****************************************************************************/
302 oslFileError SAL_CALL
osl_getFileURLFromSystemPath( rtl_uString
*ustrSystemPath
, rtl_uString
**pustrFileURL
)
304 static const sal_Unicode pDoubleSlash
[2] = { '/', '/' };
306 rtl_uString
*pTmp
= NULL
;
309 if( 0 == ustrSystemPath
->length
)
310 return osl_File_E_INVAL
;
312 /* temporary hack: if already file url, return ustrSystemPath */
314 if( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( ustrSystemPath
->buffer
, ustrSystemPath
->length
,"file:", 5 ) )
317 if( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( ustrSystemPath->buffer, ustrSystemPath->length,"file://", 7 ) )
319 OSL_ENSURE( 0, "osl_getFileURLFromSystemPath: input is already file URL" );
320 rtl_uString_assign( pustrFileURL, ustrSystemPath );
324 rtl_uString *pTmp2 = NULL;
326 OSL_ENSURE( 0, "osl_getFileURLFromSystemPath: input is wrong file URL" );
327 rtl_uString_newFromStr_WithLength( pustrFileURL, ustrSystemPath->buffer + 5, ustrSystemPath->length - 5 );
328 rtl_uString_newFromAscii( &pTmp2, "file://" );
329 rtl_uString_newConcat( pustrFileURL, *pustrFileURL, pTmp2 );
330 rtl_uString_release( pTmp2 );
332 return osl_File_E_None;
334 return osl_File_E_INVAL
;
338 /* check if system path starts with ~ or ~user and replace it with the appropriate home dir */
339 if( (sal_Unicode
) '~' == ustrSystemPath
->buffer
[0] )
341 /* check if another user is specified */
342 if( ( 1 == ustrSystemPath
->length
) || ( (sal_Unicode
)'/' == ustrSystemPath
->buffer
[1] ) )
344 /* osl_getHomeDir returns file URL */
345 osl_getHomeDir( osl_getCurrentSecurity(), &pTmp
);
347 /* remove "file://" prefix */
348 rtl_uString_newFromStr_WithLength( &pTmp
, pTmp
->buffer
+ 7, pTmp
->length
- 7 );
350 /* replace '~' in original string */
351 rtl_uString_newReplaceStrAt( &pTmp
, ustrSystemPath
, 0, 1, pTmp
);
356 /* FIXME: replace ~user with users home directory */
357 return osl_File_E_INVAL
;
361 /* check if initial string contains double instances of '/' */
362 nIndex
= rtl_ustr_indexOfStr_WithLength( ustrSystemPath
->buffer
, ustrSystemPath
->length
, pDoubleSlash
, 2 );
366 sal_Int32 nDeleted
= 0;
368 /* if pTmp is not already allocated, copy ustrSystemPath for modification */
370 rtl_uString_newFromString( &pTmp
, ustrSystemPath
);
372 /* adapt index to pTmp */
373 nIndex
+= pTmp
->length
- ustrSystemPath
->length
;
375 /* remove all occurances of '//' */
376 for( nSrcIndex
= nIndex
+ 1; nSrcIndex
< pTmp
->length
; nSrcIndex
++ )
378 if( ((sal_Unicode
) '/' == pTmp
->buffer
[nSrcIndex
]) && ((sal_Unicode
) '/' == pTmp
->buffer
[nIndex
]) )
381 pTmp
->buffer
[++nIndex
] = pTmp
->buffer
[nSrcIndex
];
384 /* adjust length member */
385 pTmp
->length
-= nDeleted
;
389 rtl_uString_assign( &pTmp
, ustrSystemPath
);
391 /* temporary check for top 5 wrong usage strings (which are valid but unlikly filenames) */
393 OSL_ASSERT( !findWrongUsage( pTmp->buffer, pTmp->length ) );
396 /* file URLs must be URI encoded */
397 rtl_uriEncode( pTmp
, uriCharClass
, rtl_UriEncodeIgnoreEscapes
, RTL_TEXTENCODING_UTF8
, pustrFileURL
);
399 rtl_uString_release( pTmp
);
401 /* absolute urls should start with 'file://' */
402 if( (sal_Unicode
)'/' == (*pustrFileURL
)->buffer
[0] )
404 rtl_uString
*pProtocol
= NULL
;
406 rtl_uString_newFromAscii( &pProtocol
, "file://" );
407 rtl_uString_newConcat( pustrFileURL
, pProtocol
, *pustrFileURL
);
408 rtl_uString_release( pProtocol
);
411 return osl_File_E_None
;
414 /****************************************************************************
415 * osl_getSystemPathFromFileURL_Ex - helper function
416 * clients may specify if they want to accept relative
418 ****************************************************************************/
420 oslFileError
osl_getSystemPathFromFileURL_Ex(
421 rtl_uString
*ustrFileURL
, rtl_uString
**pustrSystemPath
, sal_Bool bAllowRelative
)
423 rtl_uString
* temp
= 0;
424 oslFileError osl_error
= osl_getSystemPathFromFileURL(ustrFileURL
, &temp
);
426 if (osl_File_E_None
== osl_error
)
428 if (bAllowRelative
|| (UNICHAR_SLASH
== temp
->buffer
[0]))
430 *pustrSystemPath
= temp
;
434 rtl_uString_release(temp
);
435 osl_error
= osl_File_E_INVAL
;
442 namespace /* private */
445 /******************************************************
446 * Helper function, return a pinter to the final '\0'
448 ******************************************************/
450 sal_Unicode
* ustrtoend(sal_Unicode
* pStr
)
452 return (pStr
+ rtl_ustr_getLength(pStr
));
455 /*********************************************
457 ********************************************/
459 sal_Unicode
* ustrchrcat(const sal_Unicode chr
, sal_Unicode
* d
)
461 sal_Unicode
* p
= ustrtoend(d
);
467 /******************************************************
469 ******************************************************/
471 bool _islastchr(sal_Unicode
* pStr
, sal_Unicode Chr
)
473 sal_Unicode
* p
= ustrtoend(pStr
);
479 /******************************************************
480 * Remove the last part of a path, a path that has
481 * only a '/' or no '/' at all will be returned
483 ******************************************************/
485 sal_Unicode
* _rmlastpathtoken(sal_Unicode
* aPath
)
487 /* we always may skip -2 because we
488 may at least stand on a '/' but
489 either there is no other character
490 before this '/' or it's another
491 character than the '/'
493 sal_Unicode
* p
= ustrtoend(aPath
) - 2;
495 // move back to the next path separator
496 // or to the start of the string
497 while ((p
> aPath
) && (*p
!= UNICHAR_SLASH
))
502 if (UNICHAR_SLASH
== *p
)
516 /******************************************************
518 ******************************************************/
520 oslFileError
_osl_resolvepath(
521 /*inout*/ sal_Unicode
* path
,
522 /*inout*/ sal_Unicode
* current_pos
,
523 /*inout*/ bool* failed
)
525 oslFileError ferr
= osl_File_E_None
;
529 char unresolved_path
[PATH_MAX
];
530 if (!UnicodeToText(unresolved_path
, sizeof(unresolved_path
), path
, rtl_ustr_getLength(path
)))
531 return oslTranslateFileError(OSL_FET_ERROR
, ENAMETOOLONG
);
533 char resolved_path
[PATH_MAX
];
534 if (realpath(unresolved_path
, resolved_path
))
536 if (!TextToUnicode(resolved_path
, strlen(resolved_path
), path
, PATH_MAX
))
537 return oslTranslateFileError(OSL_FET_ERROR
, ENAMETOOLONG
);
539 current_pos
= ustrtoend(path
) - 1;
543 if (EACCES
== errno
|| ENOTDIR
== errno
|| ENOENT
== errno
)
546 ferr
= oslTranslateFileError(OSL_FET_ERROR
, errno
);
553 /******************************************************
554 * Works even with non existing paths. The resulting
555 * path must not exceed PATH_MAX else
556 * osl_File_E_NAMETOOLONG is the result
557 ******************************************************/
559 oslFileError
osl_getAbsoluteFileURL_impl_(const rtl::OUString
& unresolved_path
, rtl::OUString
& resolved_path
)
561 // the given unresolved path must not exceed PATH_MAX
562 if (unresolved_path
.getLength() >= (PATH_MAX
- 2))
563 return oslTranslateFileError(OSL_FET_ERROR
, ENAMETOOLONG
);
565 sal_Unicode path_resolved_so_far
[PATH_MAX
];
566 const sal_Unicode
* punresolved
= unresolved_path
.getStr();
567 sal_Unicode
* presolvedsf
= path_resolved_so_far
;
569 // reserve space for leading '/' and trailing '\0'
570 // do not exceed this limit
571 sal_Unicode
* sentinel
= path_resolved_so_far
+ PATH_MAX
- 2;
573 // if realpath fails with error ENOTDIR, EACCES or ENOENT
574 // we will not call it again, because _osl_realpath should also
575 // work with non existing directories etc.
576 bool realpath_failed
= false;
579 path_resolved_so_far
[0] = '\0';
581 while (*punresolved
!= '\0')
583 // ignore '/.' , skip one part back when '/..'
585 if ((UNICHAR_DOT
== *punresolved
) && (UNICHAR_SLASH
== *presolvedsf
))
587 if ('\0' == *(punresolved
+ 1))
592 else if (UNICHAR_SLASH
== *(punresolved
+ 1))
597 else if ((UNICHAR_DOT
== *(punresolved
+ 1)) && ('\0' == *(punresolved
+ 2) || (UNICHAR_SLASH
== *(punresolved
+ 2))))
599 _rmlastpathtoken(path_resolved_so_far
);
601 presolvedsf
= ustrtoend(path_resolved_so_far
) - 1;
603 if (UNICHAR_SLASH
== *(punresolved
+ 2))
610 else // a file or directory name may start with '.'
612 if ((presolvedsf
= ustrtoend(path_resolved_so_far
)) > sentinel
)
613 return oslTranslateFileError(OSL_FET_ERROR
, ENAMETOOLONG
);
615 ustrchrcat(*punresolved
++, path_resolved_so_far
);
617 if ('\0' == *punresolved
&& !realpath_failed
)
619 ferr
= _osl_resolvepath(
620 path_resolved_so_far
,
624 if (osl_File_E_None
!= ferr
)
629 else if (UNICHAR_SLASH
== *punresolved
)
631 if ((presolvedsf
= ustrtoend(path_resolved_so_far
)) > sentinel
)
632 return oslTranslateFileError(OSL_FET_ERROR
, ENAMETOOLONG
);
634 ustrchrcat(*punresolved
++, path_resolved_so_far
);
636 if (!realpath_failed
)
638 ferr
= _osl_resolvepath(
639 path_resolved_so_far
,
643 if (osl_File_E_None
!= ferr
)
646 if (!_islastchr(path_resolved_so_far
, UNICHAR_SLASH
))
648 if ((presolvedsf
= ustrtoend(path_resolved_so_far
)) > sentinel
)
649 return oslTranslateFileError(OSL_FET_ERROR
, ENAMETOOLONG
);
651 ustrchrcat(UNICHAR_SLASH
, path_resolved_so_far
);
655 else // any other character
657 if ((presolvedsf
= ustrtoend(path_resolved_so_far
)) > sentinel
)
658 return oslTranslateFileError(OSL_FET_ERROR
, ENAMETOOLONG
);
660 ustrchrcat(*punresolved
++, path_resolved_so_far
);
662 if ('\0' == *punresolved
&& !realpath_failed
)
664 ferr
= _osl_resolvepath(
665 path_resolved_so_far
,
669 if (osl_File_E_None
!= ferr
)
675 sal_Int32 len
= rtl_ustr_getLength(path_resolved_so_far
);
677 OSL_ASSERT(len
< PATH_MAX
);
679 resolved_path
= rtl::OUString(path_resolved_so_far
, len
);
681 return osl_File_E_None
;
684 } // end namespace private
687 /******************************************************
688 * osl_getAbsoluteFileURL
689 ******************************************************/
691 oslFileError
osl_getAbsoluteFileURL(rtl_uString
* ustrBaseDirURL
, rtl_uString
* ustrRelativeURL
, rtl_uString
** pustrAbsoluteURL
)
694 rtl::OUString unresolved_path
;
696 rc
= FileBase::getSystemPathFromFileURL(rtl::OUString(ustrRelativeURL
), unresolved_path
);
698 if(FileBase::E_None
!= rc
)
699 return oslFileError(rc
);
701 if (systemPathIsRelativePath(unresolved_path
))
703 rtl::OUString base_path
;
704 rc
= (FileBase::RC
) osl_getSystemPathFromFileURL_Ex(ustrBaseDirURL
, &base_path
.pData
, sal_False
);
706 if (FileBase::E_None
!= rc
)
707 return oslFileError(rc
);
709 rtl::OUString abs_path
;
710 systemPathMakeAbsolutePath(base_path
, unresolved_path
, abs_path
);
712 unresolved_path
= abs_path
;
715 rtl::OUString resolved_path
;
716 rc
= (FileBase::RC
) osl_getAbsoluteFileURL_impl_(unresolved_path
, resolved_path
);
718 if (FileBase::E_None
== rc
)
720 rc
= (FileBase::RC
) osl_getFileURLFromSystemPath(resolved_path
.pData
, pustrAbsoluteURL
);
721 OSL_ASSERT(FileBase::E_None
== rc
);
724 return oslFileError(rc
);
728 namespace /* private */
731 /*********************************************
732 No separate error code if unicode to text
733 conversion or getenv fails because for the
734 caller there is no difference why a file
735 could not be found in $PATH
736 ********************************************/
738 bool find_in_PATH(const rtl::OUString
& file_path
, rtl::OUString
& result
)
741 rtl::OUString path
= rtl::OUString::createFromAscii("PATH");
742 rtl::OUString env_path
;
744 if (osl_Process_E_None
== osl_getEnvironment(path
.pData
, &env_path
.pData
))
745 bfound
= osl::searchPath(file_path
, env_path
, result
);
750 /*********************************************
751 No separate error code if unicode to text
752 conversion or getcwd fails because for the
753 caller there is no difference why a file
754 could not be found in CDW
755 ********************************************/
757 bool find_in_CWD(const rtl::OUString
& file_path
, rtl::OUString
& result
)
760 rtl::OUString cwd_url
;
762 if (osl_Process_E_None
== osl_getProcessWorkingDir(&cwd_url
.pData
))
765 FileBase::getSystemPathFromFileURL(cwd_url
, cwd
);
766 bfound
= osl::searchPath(file_path
, cwd
, result
);
771 /*********************************************
773 ********************************************/
775 bool find_in_searchPath(const rtl::OUString
& file_path
, rtl_uString
* search_path
, rtl::OUString
& result
)
777 return (search_path
&& osl::searchPath(file_path
, rtl::OUString(search_path
), result
));
780 } // end namespace private
783 /****************************************************************************
785 ***************************************************************************/
787 oslFileError
osl_searchFileURL(rtl_uString
* ustrFilePath
, rtl_uString
* ustrSearchPath
, rtl_uString
** pustrURL
)
789 OSL_PRECOND(ustrFilePath
&& pustrURL
, "osl_searchFileURL: invalid parameter");
792 rtl::OUString file_path
;
794 // try to interpret search path as file url else assume it's a system path list
795 rc
= FileBase::getSystemPathFromFileURL(rtl::OUString(ustrFilePath
), file_path
);
796 if ((FileBase::E_None
!= rc
) && (FileBase::E_INVAL
== rc
))
797 file_path
= ustrFilePath
;
798 else if (FileBase::E_None
!= rc
)
799 return oslFileError(rc
);
802 rtl::OUString result
;
804 if (find_in_searchPath(file_path
, ustrSearchPath
, result
) ||
805 find_in_PATH(file_path
, result
) ||
806 find_in_CWD(file_path
, result
))
808 rtl::OUString resolved
;
810 if (osl::realpath(result
, resolved
))
812 #if OSL_DEBUG_LEVEL > 0
813 oslFileError osl_error
=
815 osl_getFileURLFromSystemPath(resolved
.pData
, pustrURL
);
816 OSL_ASSERT(osl_File_E_None
== osl_error
);
820 return bfound
? osl_File_E_None
: osl_File_E_NOENT
;
824 /****************************************************************************
826 ***************************************************************************/
828 oslFileError
FileURLToPath(char * buffer
, size_t bufLen
, rtl_uString
* ustrFileURL
)
830 rtl_uString
* ustrSystemPath
= NULL
;
831 oslFileError osl_error
= osl_getSystemPathFromFileURL(ustrFileURL
, &ustrSystemPath
);
833 if(osl_File_E_None
!= osl_error
)
836 osl_systemPathRemoveSeparator(ustrSystemPath
);
838 /* convert unicode path to text */
839 if(!UnicodeToText( buffer
, bufLen
, ustrSystemPath
->buffer
, ustrSystemPath
->length
))
840 osl_error
= oslTranslateFileError(OSL_FET_ERROR
, errno
);
842 rtl_uString_release(ustrSystemPath
);
847 /*****************************************************************************
849 ****************************************************************************/
851 namespace /* private */
853 class UnicodeToTextConverter_Impl
855 rtl_UnicodeToTextConverter m_converter
;
857 UnicodeToTextConverter_Impl()
858 : m_converter (rtl_createUnicodeToTextConverter (osl_getThreadTextEncoding()))
861 ~UnicodeToTextConverter_Impl()
863 rtl_destroyUnicodeToTextConverter (m_converter
);
866 static UnicodeToTextConverter_Impl
& getInstance()
868 static UnicodeToTextConverter_Impl g_theConverter
;
869 return g_theConverter
;
873 sal_Unicode
const * pSrcBuf
, sal_Size nSrcChars
, sal_Char
* pDstBuf
, sal_Size nDstBytes
,
874 sal_uInt32 nFlags
, sal_uInt32
* pInfo
, sal_Size
* pSrcCvtChars
)
876 OSL_ASSERT(m_converter
!= 0);
877 return rtl_convertUnicodeToText (
878 m_converter
, 0, pSrcBuf
, nSrcChars
, pDstBuf
, nDstBytes
, nFlags
, pInfo
, pSrcCvtChars
);
881 } // end namespace private
883 int UnicodeToText( char * buffer
, size_t bufLen
, const sal_Unicode
* uniText
, sal_Int32 uniTextLen
)
885 sal_uInt32 nInfo
= 0;
886 sal_Size nSrcChars
= 0;
888 sal_Size nDestBytes
= UnicodeToTextConverter_Impl::getInstance().convert (
889 uniText
, uniTextLen
, buffer
, bufLen
,
890 OUSTRING_TO_OSTRING_CVTFLAGS
| RTL_UNICODETOTEXT_FLAGS_FLUSH
, &nInfo
, &nSrcChars
);
892 if( nInfo
& RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL
)
898 /* ensure trailing '\0' */
899 buffer
[nDestBytes
] = '\0';
903 /*****************************************************************************
905 ****************************************************************************/
907 namespace /* private */
909 class TextToUnicodeConverter_Impl
911 rtl_TextToUnicodeConverter m_converter
;
913 TextToUnicodeConverter_Impl()
914 : m_converter (rtl_createTextToUnicodeConverter (osl_getThreadTextEncoding()))
917 ~TextToUnicodeConverter_Impl()
919 rtl_destroyTextToUnicodeConverter (m_converter
);
923 static TextToUnicodeConverter_Impl
& getInstance()
925 static TextToUnicodeConverter_Impl g_theConverter
;
926 return g_theConverter
;
930 sal_Char
const * pSrcBuf
, sal_Size nSrcBytes
, sal_Unicode
* pDstBuf
, sal_Size nDstChars
,
931 sal_uInt32 nFlags
, sal_uInt32
* pInfo
, sal_Size
* pSrcCvtBytes
)
933 OSL_ASSERT(m_converter
!= 0);
934 return rtl_convertTextToUnicode (
935 m_converter
, 0, pSrcBuf
, nSrcBytes
, pDstBuf
, nDstChars
, nFlags
, pInfo
, pSrcCvtBytes
);
938 } // end namespace private
942 size_t text_buffer_size
,
943 sal_Unicode
* unic_text
,
944 sal_Int32 unic_text_buffer_size
)
946 sal_uInt32 nInfo
= 0;
947 sal_Size nSrcChars
= 0;
949 sal_Size nDestBytes
= TextToUnicodeConverter_Impl::getInstance().convert(
950 text
, text_buffer_size
, unic_text
, unic_text_buffer_size
,
951 OSTRING_TO_OUSTRING_CVTFLAGS
| RTL_TEXTTOUNICODE_FLAGS_FLUSH
, &nInfo
, &nSrcChars
);
953 if (nInfo
& RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL
)
959 /* ensure trailing '\0' */
960 unic_text
[nDestBytes
] = '\0';