1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
39 #include "osl/file.hxx"
40 #include <osl/security.hxx>
41 #include <osl/diagnose.h>
42 #include <osl/thread.h>
43 #include <osl/process.h>
45 #include <rtl/uri.hxx>
46 #include <rtl/ustring.hxx>
47 #include <rtl/ustrbuf.h>
48 #include "rtl/textcvt.h"
50 #include "file_error_transl.h"
51 #include "file_path_helper.hxx"
53 #include "uunxapi.hxx"
55 /***************************************************
59 This file contains the part that handles File URLs.
61 File URLs as scheme specific notion of URIs
62 (RFC2396) may be handled platform independend, but
63 will not in osl which is considered wrong.
64 Future version of osl should handle File URLs this
65 way. In rtl/uri there is already an URI parser etc.
66 so this code should be consolidated.
68 **************************************************/
69 /************************************************************************
72 * Fix osl_getCanonicalName
74 ***********************************************************************/
77 /***************************************************
78 * namespace directives
79 **************************************************/
83 /***************************************************
85 **************************************************/
87 const sal_Unicode UNICHAR_SLASH
= ((sal_Unicode
)'/');
88 const sal_Unicode UNICHAR_COLON
= ((sal_Unicode
)':');
89 const sal_Unicode UNICHAR_DOT
= ((sal_Unicode
)'.');
91 /******************************************************************************
93 * Exported Module Functions
95 *****************************************************************************/
97 /* a slightly modified version of Pchar in rtl/source/uri.c */
98 const sal_Bool uriCharClass
[128] =
100 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Pchar but without encoding slashes */
101 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
102 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* !"#$%&'()*+,-./ */
103 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, /* 0123456789:;<=>? */
104 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ABCDEFGHIJKLMNO */
105 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* PQRSTUVWXYZ[\]^_ */
106 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* `abcdefghijklmno */
107 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0 /* pqrstuvwxyz{|}~ */
111 /* check for top wrong usage strings */
113 static sal_Bool findWrongUsage( const sal_Unicode *path, sal_Int32 len )
115 rtl_uString *pTmp = NULL;
118 rtl_uString_newFromStr_WithLength( &pTmp, path, len );
120 rtl_ustr_toAsciiLowerCase_WithLength( pTmp->buffer, pTmp->length );
122 bRet = ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "ftp://", 6 ) ) ||
123 ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "http://", 7 ) ) ||
124 ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "vnd.sun.star", 12 ) ) ||
125 ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "private:", 8 ) ) ||
126 ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "slot:", 5) );
128 rtl_uString_release( pTmp );
133 /****************************************************************************/
134 /* osl_getCanonicalName */
135 /****************************************************************************/
137 oslFileError SAL_CALL
osl_getCanonicalName( rtl_uString
* ustrFileURL
, rtl_uString
** pustrValidURL
)
139 OSL_FAIL("osl_getCanonicalName not implemented");
141 rtl_uString_newFromString(pustrValidURL
, ustrFileURL
);
142 return osl_File_E_None
;
145 /****************************************************************************/
146 /* osl_getSystemPathFromFileURL */
147 /****************************************************************************/
151 oslFileError
getSystemPathFromFileUrl(
152 rtl::OUString
const & url
, rtl::OUString
* path
, bool homeAbbreviation
)
154 OSL_ASSERT(path
!= 0 && path
->isEmpty());
156 sal_Unicode
const * p
= url
.getStr();
157 sal_Unicode
const * end
= p
+ url
.getLength();
159 /* a valid file url may not start with '/' */
160 if ((p
== end
) || (*p
== UNICHAR_SLASH
))
161 return osl_File_E_INVAL
;
163 for (sal_Unicode
const * p1
= p
; p1
!= end
; ++p1
) {
164 if (*p1
== '?' || *p1
== '#' ||
165 (*p1
== '%' && end
- p1
>= 3 && p1
[1] == '2' &&
166 (p1
[2] == 'F' || p1
[2] == 'f')))
168 return osl_File_E_INVAL
;
171 sal_Unicode
const * p1
= p
;
172 while (p1
!= end
&& *p1
!= ':' && *p1
!= '/') {
175 if (p1
!= end
&& *p1
== ':') {
176 if (rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths(
177 p
, p1
- p
, RTL_CONSTASCII_STRINGPARAM("file")) !=
180 return osl_File_E_INVAL
;
184 if (end
- p
>= 2 && p
[0] == '/' && p
[1] == '/') {
186 sal_Int32 i
= rtl_ustr_indexOfChar_WithLength(p
, end
- p
, '/');
187 p1
= i
< 0 ? end
: p
+ i
;
189 (rtl_ustr_ascii_compareIgnoreAsciiCase_WithLengths(
190 p
, p1
- p
, RTL_CONSTASCII_STRINGPARAM("localhost")) !=
192 rtl_ustr_ascii_compare_WithLength(p
, p1
- p
, "127.0.0.1") != 0)
194 return osl_File_E_INVAL
;
198 *path
= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/"));
199 return osl_File_E_None
;
202 if (homeAbbreviation
&& end
- p
>= 2 && p
[0] == '/' && p
[1] == '~') {
204 sal_Int32 i
= rtl_ustr_indexOfChar_WithLength(p
, end
- p
, '/');
205 p1
= i
< 0 ? end
: p
+ i
;
208 if (!osl::Security().getHomeDir(home
)) {
209 return osl_File_E_INVAL
;
211 oslFileError e
= getSystemPathFromFileUrl(home
, path
, false);
212 if (e
!= osl_File_E_None
) {
216 return osl_File_E_INVAL
; //TODO
222 rtl::OUString(p
, end
- p
), rtl_UriDecodeWithCharset
,
223 RTL_TEXTENCODING_UTF8
));
224 if (d
.indexOf(0) >=0) {
225 return osl_File_E_INVAL
;
228 return osl_File_E_None
;
232 oslFileError
osl_getSystemPathFromFileURL(
233 rtl_uString
* pustrFileURL
, rtl_uString
** ppustrSystemPath
)
236 oslFileError e
= getSystemPathFromFileUrl(
237 rtl::OUString(pustrFileURL
), &p
, true);
238 if (e
== osl_File_E_None
) {
239 rtl_uString_assign(ppustrSystemPath
, p
.pData
);
244 /****************************************************************************/
245 /* osl_getFileURLFromSystemPath */
246 /****************************************************************************/
248 oslFileError SAL_CALL
osl_getFileURLFromSystemPath( rtl_uString
*ustrSystemPath
, rtl_uString
**pustrFileURL
)
250 static const sal_Unicode pDoubleSlash
[2] = { '/', '/' };
252 rtl_uString
*pTmp
= NULL
;
255 if( 0 == ustrSystemPath
->length
)
256 return osl_File_E_INVAL
;
258 /* temporary hack: if already file url, return ustrSystemPath */
260 if( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( ustrSystemPath
->buffer
, ustrSystemPath
->length
,"file:", 5 ) )
263 if( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( ustrSystemPath->buffer, ustrSystemPath->length,"file://", 7 ) )
265 OSL_FAIL( "osl_getFileURLFromSystemPath: input is already file URL" );
266 rtl_uString_assign( pustrFileURL, ustrSystemPath );
270 rtl_uString *pTmp2 = NULL;
272 OSL_FAIL( "osl_getFileURLFromSystemPath: input is wrong file URL" );
273 rtl_uString_newFromStr_WithLength( pustrFileURL, ustrSystemPath->buffer + 5, ustrSystemPath->length - 5 );
274 rtl_uString_newFromAscii( &pTmp2, "file://" );
275 rtl_uString_newConcat( pustrFileURL, *pustrFileURL, pTmp2 );
276 rtl_uString_release( pTmp2 );
278 return osl_File_E_None;
280 return osl_File_E_INVAL
;
284 /* check if system path starts with ~ or ~user and replace it with the appropriate home dir */
285 if( (sal_Unicode
) '~' == ustrSystemPath
->buffer
[0] )
287 /* check if another user is specified */
288 if( ( 1 == ustrSystemPath
->length
) || ( (sal_Unicode
)'/' == ustrSystemPath
->buffer
[1] ) )
290 /* osl_getHomeDir returns file URL */
291 osl_getHomeDir( osl_getCurrentSecurity(), &pTmp
);
293 /* remove "file://" prefix */
294 rtl_uString_newFromStr_WithLength( &pTmp
, pTmp
->buffer
+ 7, pTmp
->length
- 7 );
296 /* replace '~' in original string */
297 rtl_uString_newReplaceStrAt( &pTmp
, ustrSystemPath
, 0, 1, pTmp
);
302 /* FIXME: replace ~user with users home directory */
303 return osl_File_E_INVAL
;
307 /* check if initial string contains double instances of '/' */
308 nIndex
= rtl_ustr_indexOfStr_WithLength( ustrSystemPath
->buffer
, ustrSystemPath
->length
, pDoubleSlash
, 2 );
312 sal_Int32 nDeleted
= 0;
314 /* if pTmp is not already allocated, copy ustrSystemPath for modification */
316 rtl_uString_newFromString( &pTmp
, ustrSystemPath
);
318 /* adapt index to pTmp */
319 nIndex
+= pTmp
->length
- ustrSystemPath
->length
;
321 /* remove all occurrences of '//' */
322 for( nSrcIndex
= nIndex
+ 1; nSrcIndex
< pTmp
->length
; nSrcIndex
++ )
324 if( ((sal_Unicode
) '/' == pTmp
->buffer
[nSrcIndex
]) && ((sal_Unicode
) '/' == pTmp
->buffer
[nIndex
]) )
327 pTmp
->buffer
[++nIndex
] = pTmp
->buffer
[nSrcIndex
];
330 /* adjust length member */
331 pTmp
->length
-= nDeleted
;
335 rtl_uString_assign( &pTmp
, ustrSystemPath
);
337 /* temporary check for top 5 wrong usage strings (which are valid but unlikly filenames) */
339 OSL_ASSERT( !findWrongUsage( pTmp->buffer, pTmp->length ) );
342 /* file URLs must be URI encoded */
343 rtl_uriEncode( pTmp
, uriCharClass
, rtl_UriEncodeIgnoreEscapes
, RTL_TEXTENCODING_UTF8
, pustrFileURL
);
345 rtl_uString_release( pTmp
);
347 /* absolute urls should start with 'file://' */
348 if( (sal_Unicode
)'/' == (*pustrFileURL
)->buffer
[0] )
350 rtl_uString
*pProtocol
= NULL
;
352 rtl_uString_newFromAscii( &pProtocol
, "file://" );
353 rtl_uString_newConcat( pustrFileURL
, pProtocol
, *pustrFileURL
);
354 rtl_uString_release( pProtocol
);
357 return osl_File_E_None
;
360 /****************************************************************************
361 * osl_getSystemPathFromFileURL_Ex - helper function
362 * clients may specify if they want to accept relative
364 ****************************************************************************/
366 oslFileError
osl_getSystemPathFromFileURL_Ex(
367 rtl_uString
*ustrFileURL
, rtl_uString
**pustrSystemPath
, sal_Bool bAllowRelative
)
369 rtl_uString
* temp
= 0;
370 oslFileError osl_error
= osl_getSystemPathFromFileURL(ustrFileURL
, &temp
);
372 if (osl_File_E_None
== osl_error
)
374 if (bAllowRelative
|| (UNICHAR_SLASH
== temp
->buffer
[0]))
376 *pustrSystemPath
= temp
;
380 rtl_uString_release(temp
);
381 osl_error
= osl_File_E_INVAL
;
388 namespace /* private */
391 /******************************************************
392 * Helper function, return a pinter to the final '\0'
394 ******************************************************/
396 sal_Unicode
* ustrtoend(sal_Unicode
* pStr
)
398 return (pStr
+ rtl_ustr_getLength(pStr
));
401 /*********************************************
403 ********************************************/
405 sal_Unicode
* ustrchrcat(const sal_Unicode chr
, sal_Unicode
* d
)
407 sal_Unicode
* p
= ustrtoend(d
);
413 /******************************************************
415 ******************************************************/
417 bool _islastchr(sal_Unicode
* pStr
, sal_Unicode Chr
)
419 sal_Unicode
* p
= ustrtoend(pStr
);
425 /******************************************************
426 * Remove the last part of a path, a path that has
427 * only a '/' or no '/' at all will be returned
429 ******************************************************/
431 sal_Unicode
* _rmlastpathtoken(sal_Unicode
* aPath
)
433 /* we always may skip -2 because we
434 may at least stand on a '/' but
435 either there is no other character
436 before this '/' or it's another
437 character than the '/'
439 sal_Unicode
* p
= ustrtoend(aPath
) - 2;
441 // move back to the next path separator
442 // or to the start of the string
443 while ((p
> aPath
) && (*p
!= UNICHAR_SLASH
))
448 if (UNICHAR_SLASH
== *p
)
462 /******************************************************
464 ******************************************************/
466 oslFileError
_osl_resolvepath(
467 /*inout*/ sal_Unicode
* path
,
468 /*inout*/ bool* failed
)
470 oslFileError ferr
= osl_File_E_None
;
474 char unresolved_path
[PATH_MAX
];
475 if (!UnicodeToText(unresolved_path
, sizeof(unresolved_path
), path
, rtl_ustr_getLength(path
)))
476 return oslTranslateFileError(OSL_FET_ERROR
, ENAMETOOLONG
);
478 char resolved_path
[PATH_MAX
];
479 if (realpath(unresolved_path
, resolved_path
))
481 if (!TextToUnicode(resolved_path
, strlen(resolved_path
), path
, PATH_MAX
))
482 return oslTranslateFileError(OSL_FET_ERROR
, ENAMETOOLONG
);
487 if (EACCES
== errno
|| ENOTDIR
== errno
|| ENOENT
== errno
)
490 ferr
= oslTranslateFileError(OSL_FET_ERROR
, errno
);
497 /******************************************************
498 * Works even with non existing paths. The resulting
499 * path must not exceed PATH_MAX else
500 * osl_File_E_NAMETOOLONG is the result
501 ******************************************************/
503 oslFileError
osl_getAbsoluteFileURL_impl_(const rtl::OUString
& unresolved_path
, rtl::OUString
& resolved_path
)
505 // the given unresolved path must not exceed PATH_MAX
506 if (unresolved_path
.getLength() >= (PATH_MAX
- 2))
507 return oslTranslateFileError(OSL_FET_ERROR
, ENAMETOOLONG
);
509 sal_Unicode path_resolved_so_far
[PATH_MAX
];
510 const sal_Unicode
* punresolved
= unresolved_path
.getStr();
511 sal_Unicode
* presolvedsf
= path_resolved_so_far
;
513 // reserve space for leading '/' and trailing '\0'
514 // do not exceed this limit
515 sal_Unicode
* sentinel
= path_resolved_so_far
+ PATH_MAX
- 2;
517 // if realpath fails with error ENOTDIR, EACCES or ENOENT
518 // we will not call it again, because _osl_realpath should also
519 // work with non existing directories etc.
520 bool realpath_failed
= false;
523 path_resolved_so_far
[0] = '\0';
525 while (*punresolved
!= '\0')
527 // ignore '/.' , skip one part back when '/..'
529 if ((UNICHAR_DOT
== *punresolved
) && (UNICHAR_SLASH
== *presolvedsf
))
531 if ('\0' == *(punresolved
+ 1))
536 else if (UNICHAR_SLASH
== *(punresolved
+ 1))
541 else if ((UNICHAR_DOT
== *(punresolved
+ 1)) && ('\0' == *(punresolved
+ 2) || (UNICHAR_SLASH
== *(punresolved
+ 2))))
543 _rmlastpathtoken(path_resolved_so_far
);
545 presolvedsf
= ustrtoend(path_resolved_so_far
) - 1;
547 if (UNICHAR_SLASH
== *(punresolved
+ 2))
554 else // a file or directory name may start with '.'
556 if ((presolvedsf
= ustrtoend(path_resolved_so_far
)) > sentinel
)
557 return oslTranslateFileError(OSL_FET_ERROR
, ENAMETOOLONG
);
559 ustrchrcat(*punresolved
++, path_resolved_so_far
);
561 if ('\0' == *punresolved
&& !realpath_failed
)
563 ferr
= _osl_resolvepath(
564 path_resolved_so_far
,
567 if (osl_File_E_None
!= ferr
)
572 else if (UNICHAR_SLASH
== *punresolved
)
574 if ((presolvedsf
= ustrtoend(path_resolved_so_far
)) > sentinel
)
575 return oslTranslateFileError(OSL_FET_ERROR
, ENAMETOOLONG
);
577 ustrchrcat(*punresolved
++, path_resolved_so_far
);
579 if (!realpath_failed
)
581 ferr
= _osl_resolvepath(
582 path_resolved_so_far
,
585 if (osl_File_E_None
!= ferr
)
588 if (!_islastchr(path_resolved_so_far
, UNICHAR_SLASH
))
590 if ((presolvedsf
= ustrtoend(path_resolved_so_far
)) > sentinel
)
591 return oslTranslateFileError(OSL_FET_ERROR
, ENAMETOOLONG
);
593 ustrchrcat(UNICHAR_SLASH
, path_resolved_so_far
);
597 else // any other character
599 if ((presolvedsf
= ustrtoend(path_resolved_so_far
)) > sentinel
)
600 return oslTranslateFileError(OSL_FET_ERROR
, ENAMETOOLONG
);
602 ustrchrcat(*punresolved
++, path_resolved_so_far
);
604 if ('\0' == *punresolved
&& !realpath_failed
)
606 ferr
= _osl_resolvepath(
607 path_resolved_so_far
,
610 if (osl_File_E_None
!= ferr
)
616 sal_Int32 len
= rtl_ustr_getLength(path_resolved_so_far
);
618 OSL_ASSERT(len
< PATH_MAX
);
620 resolved_path
= rtl::OUString(path_resolved_so_far
, len
);
622 return osl_File_E_None
;
625 } // end namespace private
628 /******************************************************
629 * osl_getAbsoluteFileURL
630 ******************************************************/
632 oslFileError
osl_getAbsoluteFileURL(rtl_uString
* ustrBaseDirURL
, rtl_uString
* ustrRelativeURL
, rtl_uString
** pustrAbsoluteURL
)
635 rtl::OUString unresolved_path
;
636 static char *allow_symlinks
= getenv( "SAL_ALLOW_LINKOO_SYMLINKS" );
638 rc
= FileBase::getSystemPathFromFileURL(rtl::OUString(ustrRelativeURL
), unresolved_path
);
640 if(FileBase::E_None
!= rc
)
641 return oslFileError(rc
);
643 if (systemPathIsRelativePath(unresolved_path
))
645 rtl::OUString base_path
;
646 rc
= (FileBase::RC
) osl_getSystemPathFromFileURL_Ex(ustrBaseDirURL
, &base_path
.pData
, sal_False
);
648 if (FileBase::E_None
!= rc
)
649 return oslFileError(rc
);
651 rtl::OUString abs_path
;
652 systemPathMakeAbsolutePath(base_path
, unresolved_path
, abs_path
);
654 unresolved_path
= abs_path
;
657 rtl::OUString resolved_path
;
661 rc
= (FileBase::RC
) osl_getAbsoluteFileURL_impl_(unresolved_path
, resolved_path
);
665 // SAL_ALLOW_LINKOO_SYMLINKS environment variable:
666 // for linkoo to work, we need to let the symlinks to the libraries untouched
668 sal_Int32 last_slash
= unresolved_path
.lastIndexOf( UNICHAR_SLASH
);
670 if (last_slash
>= 0 && last_slash
+ 1 < unresolved_path
.getLength()
671 && ! ( last_slash
+ 2 == unresolved_path
.getLength() && unresolved_path
.matchAsciiL(RTL_CONSTASCII_STRINGPARAM("."), last_slash
+ 1) )
672 && ! ( last_slash
+ 3 == unresolved_path
.getLength() && unresolved_path
.matchAsciiL(RTL_CONSTASCII_STRINGPARAM(".."), last_slash
+ 1) ))
674 base
= unresolved_path
.copy(last_slash
+1);
675 unresolved_path
= unresolved_path
.copy(0, last_slash
);
678 rc
= (FileBase::RC
) osl_getAbsoluteFileURL_impl_(unresolved_path
, resolved_path
);
682 resolved_path
+= rtl::OUString( UNICHAR_SLASH
);
683 resolved_path
+= base
;
687 if (FileBase::E_None
== rc
)
689 rc
= (FileBase::RC
) osl_getFileURLFromSystemPath(resolved_path
.pData
, pustrAbsoluteURL
);
690 OSL_ASSERT(FileBase::E_None
== rc
);
693 return oslFileError(rc
);
697 namespace /* private */
700 /*********************************************
701 No separate error code if unicode to text
702 conversion or getenv fails because for the
703 caller there is no difference why a file
704 could not be found in $PATH
705 ********************************************/
707 bool find_in_PATH(const rtl::OUString
& file_path
, rtl::OUString
& result
)
710 rtl::OUString
path(RTL_CONSTASCII_USTRINGPARAM("PATH"));
711 rtl::OUString env_path
;
713 if (osl_Process_E_None
== osl_getEnvironment(path
.pData
, &env_path
.pData
))
714 bfound
= osl::searchPath(file_path
, env_path
, result
);
719 /*********************************************
720 No separate error code if unicode to text
721 conversion or getcwd fails because for the
722 caller there is no difference why a file
723 could not be found in CDW
724 ********************************************/
726 bool find_in_CWD(const rtl::OUString
& file_path
, rtl::OUString
& result
)
729 rtl::OUString cwd_url
;
731 if (osl_Process_E_None
== osl_getProcessWorkingDir(&cwd_url
.pData
))
734 FileBase::getSystemPathFromFileURL(cwd_url
, cwd
);
735 bfound
= osl::searchPath(file_path
, cwd
, result
);
740 /*********************************************
742 ********************************************/
744 bool find_in_searchPath(const rtl::OUString
& file_path
, rtl_uString
* search_path
, rtl::OUString
& result
)
746 return (search_path
&& osl::searchPath(file_path
, rtl::OUString(search_path
), result
));
749 } // end namespace private
752 /****************************************************************************
754 ***************************************************************************/
756 oslFileError
osl_searchFileURL(rtl_uString
* ustrFilePath
, rtl_uString
* ustrSearchPath
, rtl_uString
** pustrURL
)
758 OSL_PRECOND(ustrFilePath
&& pustrURL
, "osl_searchFileURL: invalid parameter");
761 rtl::OUString file_path
;
763 // try to interpret search path as file url else assume it's a system path list
764 rc
= FileBase::getSystemPathFromFileURL(rtl::OUString(ustrFilePath
), file_path
);
765 if (FileBase::E_INVAL
== rc
)
766 file_path
= ustrFilePath
;
767 else if (FileBase::E_None
!= rc
)
768 return oslFileError(rc
);
771 rtl::OUString result
;
773 if (find_in_searchPath(file_path
, ustrSearchPath
, result
) ||
774 find_in_PATH(file_path
, result
) ||
775 find_in_CWD(file_path
, result
))
777 rtl::OUString resolved
;
779 if (osl::realpath(result
, resolved
))
781 #if OSL_DEBUG_LEVEL > 0
782 oslFileError osl_error
=
784 osl_getFileURLFromSystemPath(resolved
.pData
, pustrURL
);
785 OSL_ASSERT(osl_File_E_None
== osl_error
);
789 return bfound
? osl_File_E_None
: osl_File_E_NOENT
;
793 /****************************************************************************
795 ***************************************************************************/
797 oslFileError
FileURLToPath(char * buffer
, size_t bufLen
, rtl_uString
* ustrFileURL
)
799 rtl_uString
* ustrSystemPath
= NULL
;
800 oslFileError osl_error
= osl_getSystemPathFromFileURL(ustrFileURL
, &ustrSystemPath
);
802 if(osl_File_E_None
!= osl_error
)
805 osl_systemPathRemoveSeparator(ustrSystemPath
);
807 /* convert unicode path to text */
808 if(!UnicodeToText( buffer
, bufLen
, ustrSystemPath
->buffer
, ustrSystemPath
->length
))
809 osl_error
= oslTranslateFileError(OSL_FET_ERROR
, errno
);
811 rtl_uString_release(ustrSystemPath
);
816 /*****************************************************************************
818 ****************************************************************************/
820 namespace /* private */
822 class UnicodeToTextConverter_Impl
824 rtl_UnicodeToTextConverter m_converter
;
826 UnicodeToTextConverter_Impl()
827 : m_converter (rtl_createUnicodeToTextConverter (osl_getThreadTextEncoding()))
830 ~UnicodeToTextConverter_Impl()
832 rtl_destroyUnicodeToTextConverter (m_converter
);
835 static UnicodeToTextConverter_Impl
& getInstance()
837 static UnicodeToTextConverter_Impl g_theConverter
;
838 return g_theConverter
;
842 sal_Unicode
const * pSrcBuf
, sal_Size nSrcChars
, sal_Char
* pDstBuf
, sal_Size nDstBytes
,
843 sal_uInt32 nFlags
, sal_uInt32
* pInfo
, sal_Size
* pSrcCvtChars
)
845 OSL_ASSERT(m_converter
!= 0);
846 return rtl_convertUnicodeToText (
847 m_converter
, 0, pSrcBuf
, nSrcChars
, pDstBuf
, nDstBytes
, nFlags
, pInfo
, pSrcCvtChars
);
850 } // end namespace private
852 int UnicodeToText( char * buffer
, size_t bufLen
, const sal_Unicode
* uniText
, sal_Int32 uniTextLen
)
854 sal_uInt32 nInfo
= 0;
855 sal_Size nSrcChars
= 0;
857 sal_Size nDestBytes
= UnicodeToTextConverter_Impl::getInstance().convert (
858 uniText
, uniTextLen
, buffer
, bufLen
,
859 OUSTRING_TO_OSTRING_CVTFLAGS
| RTL_UNICODETOTEXT_FLAGS_FLUSH
, &nInfo
, &nSrcChars
);
861 if( nInfo
& RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL
)
867 /* ensure trailing '\0' */
868 buffer
[nDestBytes
] = '\0';
872 /*****************************************************************************
874 ****************************************************************************/
876 namespace /* private */
878 class TextToUnicodeConverter_Impl
880 rtl_TextToUnicodeConverter m_converter
;
882 TextToUnicodeConverter_Impl()
883 : m_converter (rtl_createTextToUnicodeConverter (osl_getThreadTextEncoding()))
886 ~TextToUnicodeConverter_Impl()
888 rtl_destroyTextToUnicodeConverter (m_converter
);
892 static TextToUnicodeConverter_Impl
& getInstance()
894 static TextToUnicodeConverter_Impl g_theConverter
;
895 return g_theConverter
;
899 sal_Char
const * pSrcBuf
, sal_Size nSrcBytes
, sal_Unicode
* pDstBuf
, sal_Size nDstChars
,
900 sal_uInt32 nFlags
, sal_uInt32
* pInfo
, sal_Size
* pSrcCvtBytes
)
902 OSL_ASSERT(m_converter
!= 0);
903 return rtl_convertTextToUnicode (
904 m_converter
, 0, pSrcBuf
, nSrcBytes
, pDstBuf
, nDstChars
, nFlags
, pInfo
, pSrcCvtBytes
);
907 } // end namespace private
911 size_t text_buffer_size
,
912 sal_Unicode
* unic_text
,
913 sal_Int32 unic_text_buffer_size
)
915 sal_uInt32 nInfo
= 0;
916 sal_Size nSrcChars
= 0;
918 sal_Size nDestBytes
= TextToUnicodeConverter_Impl::getInstance().convert(
919 text
, text_buffer_size
, unic_text
, unic_text_buffer_size
,
920 OSTRING_TO_OUSTRING_CVTFLAGS
| RTL_TEXTTOUNICODE_FLAGS_FLUSH
, &nInfo
, &nSrcChars
);
922 if (nInfo
& RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL
)
928 /* ensure trailing '\0' */
929 unic_text
[nDestBytes
] = '\0';
933 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */