update dev300-m57
[ooovba.git] / sal / osl / unx / file_url.cxx
blob2e7c8151275adc68b8d07207ed9a44774a58b321
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: file_url.cxx,v $
10 * $Revision: 1.13 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sal.hxx"
33 #include "system.h"
35 #ifndef _LIMITS_H
36 #include <limits.h>
37 #endif
39 #ifndef _ERRNO_H
40 #include <errno.h>
41 #endif
43 #ifndef _STRINGS_H
44 #include <strings.h>
45 #endif
47 #ifndef _UNISTD_H
48 #include <unistd.h>
49 #endif
50 #include <osl/file.h>
51 #include <osl/security.h>
52 #include <rtl/uri.h>
53 #include <osl/diagnose.h>
54 #include <rtl/ustring.hxx>
55 #include <rtl/ustrbuf.h>
57 #ifndef _OSL_TREAD_H_
58 #include <osl/thread.h>
59 #endif
60 #include <osl/file.hxx>
61 #include <osl/process.h>
62 #include "file_error_transl.h"
64 #ifndef _FILE_URL_H_
65 #include "file_url.h"
66 #endif
67 #include "file_path_helper.hxx"
69 #ifndef _OSL_UUNXAPI_HXX_
70 #include "uunxapi.hxx"
71 #endif
73 /***************************************************
75 General note
77 This file contains the part that handles File URLs.
79 File URLs as scheme specific notion of URIs
80 (RFC2396) may be handled platform independend, but
81 will not in osl which is considered wrong.
82 Future version of osl should handle File URLs this
83 way. In rtl/uri there is already an URI parser etc.
84 so this code should be consolidated.
86 **************************************************/
90 /***************************************************
91 * forward
92 **************************************************/
94 extern "C" int UnicodeToText(char *, size_t, const sal_Unicode *, sal_Int32);
95 extern "C" int TextToUnicode(const char* text, size_t text_buffer_size, sal_Unicode* unic_text, sal_Int32 unic_text_buffer_size);
97 /***************************************************
98 * namespace directives
99 **************************************************/
101 using namespace osl;
103 /***************************************************
104 * constants
105 **************************************************/
107 const sal_Unicode UNICHAR_SLASH = ((sal_Unicode)'/');
108 const sal_Unicode UNICHAR_COLON = ((sal_Unicode)':');
109 const sal_Unicode UNICHAR_DOT = ((sal_Unicode)'.');
111 /******************************************************************************
113 * Exported Module Functions
115 *****************************************************************************/
117 /* a slightly modified version of Pchar in rtl/source/uri.c */
118 const sal_Bool uriCharClass[128] =
120 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Pchar but without encoding slashes */
121 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
122 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* !"#$%&'()*+,-./ */
123 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, /* 0123456789:;<=>? */
124 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ABCDEFGHIJKLMNO */
125 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* PQRSTUVWXYZ[\]^_ */
126 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* `abcdefghijklmno */
127 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0 /* pqrstuvwxyz{|}~ */
131 /* check for top wrong usage strings */
133 static sal_Bool findWrongUsage( const sal_Unicode *path, sal_Int32 len )
135 rtl_uString *pTmp = NULL;
136 sal_Bool bRet;
138 rtl_uString_newFromStr_WithLength( &pTmp, path, len );
140 rtl_ustr_toAsciiLowerCase_WithLength( pTmp->buffer, pTmp->length );
142 bRet = ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "ftp://", 6 ) ) ||
143 ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "http://", 7 ) ) ||
144 ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "vnd.sun.star", 12 ) ) ||
145 ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "private:", 8 ) ) ||
146 ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pTmp->buffer, pTmp->length, "slot:", 5) );
148 rtl_uString_release( pTmp );
149 return bRet;
153 /****************************************************************************/
154 /* osl_getSystemPathFromFileURL */
155 /****************************************************************************/
157 oslFileError SAL_CALL osl_getSystemPathFromFileURL( rtl_uString *ustrFileURL, rtl_uString **pustrSystemPath )
159 sal_Int32 nIndex;
160 rtl_uString * pTmp = NULL;
162 sal_Unicode encodedSlash[3] = { '%', '2', 'F' };
163 sal_Unicode protocolDelimiter[3] = { ':', '/', '/' };
165 /* temporary hack: if already system path, return ustrFileURL */
167 if( (sal_Unicode) '/' == ustrFileURL->buffer[0] )
169 OSL_ENSURE( 0, "osl_getSystemPathFromFileURL: input is already system path" );
170 rtl_uString_assign( pustrSystemPath, ustrFileURL );
171 return osl_File_E_None;
175 /* a valid file url may not start with '/' */
176 if( ( 0 == ustrFileURL->length ) || ( (sal_Unicode) '/' == ustrFileURL->buffer[0] ) )
178 return osl_File_E_INVAL;
181 /* Check for non file:// protocols */
183 nIndex = rtl_ustr_indexOfStr_WithLength( ustrFileURL->buffer, ustrFileURL->length, protocolDelimiter, 3 );
184 if ( -1 != nIndex && (4 != nIndex || 0 != rtl_ustr_ascii_shortenedCompare_WithLength( ustrFileURL->buffer, ustrFileURL->length,"file", 4 ) ) )
186 return osl_File_E_INVAL;
189 /* search for encoded slashes (%2F) and decode every single token if we find one */
191 nIndex = 0;
193 if( -1 != rtl_ustr_indexOfStr_WithLength( ustrFileURL->buffer, ustrFileURL->length, encodedSlash, 3 ) )
195 rtl_uString * ustrPathToken = NULL;
196 sal_Int32 nOffset = 7;
200 nOffset += nIndex;
202 /* break url down in '/' devided tokens tokens */
203 nIndex = rtl_ustr_indexOfChar_WithLength( ustrFileURL->buffer + nOffset, ustrFileURL->length - nOffset, (sal_Unicode) '/' );
205 /* copy token to new string */
206 rtl_uString_newFromStr_WithLength( &ustrPathToken, ustrFileURL->buffer + nOffset,
207 -1 == nIndex ? ustrFileURL->length - nOffset : nIndex++ );
209 /* decode token */
210 rtl_uriDecode( ustrPathToken, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8, &pTmp );
212 /* the result should not contain any '/' */
213 if( -1 != rtl_ustr_indexOfChar_WithLength( pTmp->buffer, pTmp->length, (sal_Unicode) '/' ) )
215 rtl_uString_release( pTmp );
216 rtl_uString_release( ustrPathToken );
218 return osl_File_E_INVAL;
221 } while( -1 != nIndex );
223 /* release temporary string and restore index variable */
224 rtl_uString_release( ustrPathToken );
225 nIndex = 0;
228 /* protocol and server should not be encoded, so decode the whole string */
229 rtl_uriDecode( ustrFileURL, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8, &pTmp );
231 /* check if file protocol specified */
232 /* FIXME: use rtl_ustr_ascii_shortenedCompareIgnoreCase_WithLength when available */
233 if( 7 <= pTmp->length )
235 rtl_uString * pProtocol = NULL;
236 rtl_uString_newFromStr_WithLength( &pProtocol, pTmp->buffer, 7 );
238 /* protocol is case insensitive */
239 rtl_ustr_toAsciiLowerCase_WithLength( pProtocol->buffer, pProtocol->length );
241 if( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pProtocol->buffer, pProtocol->length,"file://", 7 ) )
242 nIndex = 7;
244 rtl_uString_release( pProtocol );
247 /* skip "localhost" or "127.0.0.1" if "file://" is specified */
248 /* FIXME: use rtl_ustr_ascii_shortenedCompareIgnoreCase_WithLength when available */
249 if( nIndex && ( 10 <= pTmp->length - nIndex ) )
251 rtl_uString * pServer = NULL;
252 rtl_uString_newFromStr_WithLength( &pServer, pTmp->buffer + nIndex, 10 );
254 /* server is case insensitive */
255 rtl_ustr_toAsciiLowerCase_WithLength( pServer->buffer, pServer->length );
257 if( ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pServer->buffer, pServer->length,"localhost/", 10 ) ) ||
258 ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( pServer->buffer, pServer->length,"127.0.0.1/", 10 ) ) )
260 /* don't exclude the '/' */
261 nIndex += 9;
264 rtl_uString_release( pServer );
267 if( nIndex )
268 rtl_uString_newFromStr_WithLength( &pTmp, pTmp->buffer + nIndex, pTmp->length - nIndex );
270 /* check if system path starts with ~ or ~user and replace it with the appropriate home dir */
271 if( (sal_Unicode) '~' == pTmp->buffer[0] )
273 /* check if another user is specified */
274 if( ( 1 == pTmp->length ) || ( (sal_Unicode)'/' == pTmp->buffer[1] ) )
276 rtl_uString *pTmp2 = NULL;
278 /* osl_getHomeDir returns file URL */
279 osl_getHomeDir( osl_getCurrentSecurity(), &pTmp2 );
281 /* remove "file://" prefix */
282 rtl_uString_newFromStr_WithLength( &pTmp2, pTmp2->buffer + 7, pTmp2->length - 7 );
284 /* replace '~' in original string */
285 rtl_uString_newReplaceStrAt( &pTmp, pTmp, 0, 1, pTmp2 );
286 rtl_uString_release( pTmp2 );
289 else
291 /* FIXME: replace ~user with users home directory */
292 return osl_File_E_INVAL;
296 /* temporary check for top 5 wrong usage strings (which are valid but unlikly filenames) */
298 OSL_ASSERT( !findWrongUsage( pTmp->buffer, pTmp->length ) );
301 *pustrSystemPath = pTmp;
302 return osl_File_E_None;
305 /****************************************************************************/
306 /* osl_getFileURLFromSystemPath */
307 /****************************************************************************/
309 oslFileError SAL_CALL osl_getFileURLFromSystemPath( rtl_uString *ustrSystemPath, rtl_uString **pustrFileURL )
311 static const sal_Unicode pDoubleSlash[2] = { '/', '/' };
313 rtl_uString *pTmp = NULL;
314 sal_Int32 nIndex;
316 if( 0 == ustrSystemPath->length )
317 return osl_File_E_INVAL;
319 /* temporary hack: if already file url, return ustrSystemPath */
321 if( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( ustrSystemPath->buffer, ustrSystemPath->length,"file:", 5 ) )
324 if( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( ustrSystemPath->buffer, ustrSystemPath->length,"file://", 7 ) )
326 OSL_ENSURE( 0, "osl_getFileURLFromSystemPath: input is already file URL" );
327 rtl_uString_assign( pustrFileURL, ustrSystemPath );
329 else
331 rtl_uString *pTmp2 = NULL;
333 OSL_ENSURE( 0, "osl_getFileURLFromSystemPath: input is wrong file URL" );
334 rtl_uString_newFromStr_WithLength( pustrFileURL, ustrSystemPath->buffer + 5, ustrSystemPath->length - 5 );
335 rtl_uString_newFromAscii( &pTmp2, "file://" );
336 rtl_uString_newConcat( pustrFileURL, *pustrFileURL, pTmp2 );
337 rtl_uString_release( pTmp2 );
339 return osl_File_E_None;
341 return osl_File_E_INVAL;
345 /* check if system path starts with ~ or ~user and replace it with the appropriate home dir */
346 if( (sal_Unicode) '~' == ustrSystemPath->buffer[0] )
348 /* check if another user is specified */
349 if( ( 1 == ustrSystemPath->length ) || ( (sal_Unicode)'/' == ustrSystemPath->buffer[1] ) )
351 /* osl_getHomeDir returns file URL */
352 osl_getHomeDir( osl_getCurrentSecurity(), &pTmp );
354 /* remove "file://" prefix */
355 rtl_uString_newFromStr_WithLength( &pTmp, pTmp->buffer + 7, pTmp->length - 7 );
357 /* replace '~' in original string */
358 rtl_uString_newReplaceStrAt( &pTmp, ustrSystemPath, 0, 1, pTmp );
361 else
363 /* FIXME: replace ~user with users home directory */
364 return osl_File_E_INVAL;
368 /* check if initial string contains double instances of '/' */
369 nIndex = rtl_ustr_indexOfStr_WithLength( ustrSystemPath->buffer, ustrSystemPath->length, pDoubleSlash, 2 );
370 if( -1 != nIndex )
372 sal_Int32 nSrcIndex;
373 sal_Int32 nDeleted = 0;
375 /* if pTmp is not already allocated, copy ustrSystemPath for modification */
376 if( NULL == pTmp )
377 rtl_uString_newFromString( &pTmp, ustrSystemPath );
379 /* adapt index to pTmp */
380 nIndex += pTmp->length - ustrSystemPath->length;
382 /* remove all occurances of '//' */
383 for( nSrcIndex = nIndex + 1; nSrcIndex < pTmp->length; nSrcIndex++ )
385 if( ((sal_Unicode) '/' == pTmp->buffer[nSrcIndex]) && ((sal_Unicode) '/' == pTmp->buffer[nIndex]) )
386 nDeleted++;
387 else
388 pTmp->buffer[++nIndex] = pTmp->buffer[nSrcIndex];
391 /* adjust length member */
392 pTmp->length -= nDeleted;
395 if( NULL == pTmp )
396 rtl_uString_assign( &pTmp, ustrSystemPath );
398 /* temporary check for top 5 wrong usage strings (which are valid but unlikly filenames) */
400 OSL_ASSERT( !findWrongUsage( pTmp->buffer, pTmp->length ) );
403 /* file URLs must be URI encoded */
404 rtl_uriEncode( pTmp, uriCharClass, rtl_UriEncodeIgnoreEscapes, RTL_TEXTENCODING_UTF8, pustrFileURL );
406 rtl_uString_release( pTmp );
408 /* absolute urls should start with 'file://' */
409 if( (sal_Unicode)'/' == (*pustrFileURL)->buffer[0] )
411 rtl_uString *pProtocol = NULL;
413 rtl_uString_newFromAscii( &pProtocol, "file://" );
414 rtl_uString_newConcat( pustrFileURL, pProtocol, *pustrFileURL );
415 rtl_uString_release( pProtocol );
418 return osl_File_E_None;
421 /****************************************************************************
422 * osl_getSystemPathFromFileURL_Ex - helper function
423 * clients may specify if they want to accept relative
424 * URLs or not
425 ****************************************************************************/
427 oslFileError osl_getSystemPathFromFileURL_Ex(
428 rtl_uString *ustrFileURL, rtl_uString **pustrSystemPath, sal_Bool bAllowRelative)
430 rtl_uString* temp = 0;
431 oslFileError osl_error = osl_getSystemPathFromFileURL(ustrFileURL, &temp);
433 if (osl_File_E_None == osl_error)
435 if (bAllowRelative || (UNICHAR_SLASH == temp->buffer[0]))
437 *pustrSystemPath = temp;
439 else
441 rtl_uString_release(temp);
442 osl_error = osl_File_E_INVAL;
446 return osl_error;
449 /******************************************************
450 * Resolve the paths if they exist. The resulting
451 * path must not exceed PATH_MAX else
452 * osl_File_E_NAMETOOLONG is the result
453 ******************************************************/
455 static oslFileError osl_getAbsoluteFileURL_impl_(const rtl::OUString& unresolved, rtl::OUString& resolved)
457 char unresolved_path[PATH_MAX];
458 char resolved_path[PATH_MAX];
460 if (!UnicodeToText(unresolved_path, sizeof(unresolved_path), unresolved.getStr(), unresolved.getLength()))
461 return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
463 if (realpath(unresolved_path, resolved_path))
465 sal_Unicode path[PATH_MAX];
466 if (!TextToUnicode(resolved_path, strlen(resolved_path), path, PATH_MAX))
467 return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
468 resolved = rtl::OUString(path, rtl_ustr_getLength(path));
469 return osl_File_E_None;
471 else
473 if (EACCES != errno && ENOTDIR != errno && ENOENT != errno)
474 return oslTranslateFileError(OSL_FET_ERROR, errno);
477 // the 'unresolved' does not exist, let's just copy it to 'resolved'
478 resolved = unresolved;
479 return osl_File_E_None;
482 /******************************************************
483 * osl_getAbsoluteFileURL
484 ******************************************************/
486 oslFileError osl_getAbsoluteFileURL(rtl_uString* ustrBaseDirURL, rtl_uString* ustrRelativeURL, rtl_uString** pustrAbsoluteURL)
488 FileBase::RC rc;
489 rtl::OUString unresolved_path;
490 static char *allow_symlinks = getenv( "SAL_ALLOW_LINKOO_SYMLINKS" );
492 rc = FileBase::getSystemPathFromFileURL(rtl::OUString(ustrRelativeURL), unresolved_path);
494 if(FileBase::E_None != rc)
495 return oslFileError(rc);
497 if (systemPathIsRelativePath(unresolved_path))
499 rtl::OUString base_path;
500 rc = (FileBase::RC) osl_getSystemPathFromFileURL_Ex(ustrBaseDirURL, &base_path.pData, sal_False);
502 if (FileBase::E_None != rc)
503 return oslFileError(rc);
505 rtl::OUString abs_path;
506 systemPathMakeAbsolutePath(base_path, unresolved_path, abs_path);
508 unresolved_path = abs_path;
511 rtl::OUString resolved_path;
513 if (!allow_symlinks)
515 rc = (FileBase::RC) osl_getAbsoluteFileURL_impl_(unresolved_path, resolved_path);
517 else
519 // SAL_ALLOW_LINKOO_SYMLINKS environment variable:
520 // for linkoo to work, we need to let the symlinks to the libraries untouched
521 rtl::OUString base;
522 sal_Int32 last_slash = unresolved_path.lastIndexOf( UNICHAR_SLASH );
524 if (last_slash >= 0 && last_slash + 1 < unresolved_path.getLength())
526 base = unresolved_path.copy(last_slash+1);
527 unresolved_path = unresolved_path.copy(0, last_slash);
530 rc = (FileBase::RC) osl_getAbsoluteFileURL_impl_(unresolved_path, resolved_path);
532 if (base.getLength() > 0)
534 resolved_path += rtl::OUString( UNICHAR_SLASH );
535 resolved_path += base;
539 if (FileBase::E_None == rc)
541 rc = (FileBase::RC) osl_getFileURLFromSystemPath(resolved_path.pData, pustrAbsoluteURL);
542 OSL_ASSERT(FileBase::E_None == rc);
545 return oslFileError(rc);
549 namespace /* private */
552 /*********************************************
553 No separate error code if unicode to text
554 conversion or getenv fails because for the
555 caller there is no difference why a file
556 could not be found in $PATH
557 ********************************************/
559 bool find_in_PATH(const rtl::OUString& file_path, rtl::OUString& result)
561 bool bfound = false;
562 rtl::OUString path = rtl::OUString::createFromAscii("PATH");
563 rtl::OUString env_path;
565 if (osl_Process_E_None == osl_getEnvironment(path.pData, &env_path.pData))
566 bfound = osl::searchPath(file_path, env_path, result);
568 return bfound;
571 /*********************************************
572 No separate error code if unicode to text
573 conversion or getcwd fails because for the
574 caller there is no difference why a file
575 could not be found in CDW
576 ********************************************/
578 bool find_in_CWD(const rtl::OUString& file_path, rtl::OUString& result)
580 bool bfound = false;
581 rtl::OUString cwd_url;
583 if (osl_Process_E_None == osl_getProcessWorkingDir(&cwd_url.pData))
585 rtl::OUString cwd;
586 FileBase::getSystemPathFromFileURL(cwd_url, cwd);
587 bfound = osl::searchPath(file_path, cwd, result);
589 return bfound;
592 /*********************************************
594 ********************************************/
596 bool find_in_searchPath(const rtl::OUString& file_path, rtl_uString* search_path, rtl::OUString& result)
598 return (search_path && osl::searchPath(file_path, rtl::OUString(search_path), result));
601 } // end namespace private
604 /****************************************************************************
605 * osl_searchFileURL
606 ***************************************************************************/
608 oslFileError osl_searchFileURL(rtl_uString* ustrFilePath, rtl_uString* ustrSearchPath, rtl_uString** pustrURL)
610 OSL_PRECOND(ustrFilePath && pustrURL, "osl_searchFileURL: invalid parameter");
612 FileBase::RC rc;
613 rtl::OUString file_path;
615 // try to interpret search path as file url else assume it's a system path list
616 rc = FileBase::getSystemPathFromFileURL(rtl::OUString(ustrFilePath), file_path);
617 if ((FileBase::E_None != rc) && (FileBase::E_INVAL == rc))
618 file_path = ustrFilePath;
619 else if (FileBase::E_None != rc)
620 return oslFileError(rc);
622 bool bfound = false;
623 rtl::OUString result;
625 if (find_in_searchPath(file_path, ustrSearchPath, result) ||
626 find_in_PATH(file_path, result) ||
627 find_in_CWD(file_path, result))
629 rtl::OUString resolved;
631 if (osl::realpath(result, resolved))
633 #if OSL_DEBUG_LEVEL > 0
634 oslFileError osl_error =
635 #endif
636 osl_getFileURLFromSystemPath(resolved.pData, pustrURL);
637 OSL_ASSERT(osl_File_E_None == osl_error);
638 bfound = true;
641 return bfound ? osl_File_E_None : osl_File_E_NOENT;
645 /****************************************************************************
646 * FileURLToPath
647 ***************************************************************************/
649 oslFileError FileURLToPath(char * buffer, size_t bufLen, rtl_uString* ustrFileURL)
651 rtl_uString* ustrSystemPath = NULL;
652 oslFileError osl_error = osl_getSystemPathFromFileURL(ustrFileURL, &ustrSystemPath);
654 if(osl_File_E_None != osl_error)
655 return osl_error;
657 osl_systemPathRemoveSeparator(ustrSystemPath);
659 /* convert unicode path to text */
660 if(!UnicodeToText( buffer, bufLen, ustrSystemPath->buffer, ustrSystemPath->length))
661 osl_error = oslTranslateFileError(OSL_FET_ERROR, errno);
663 rtl_uString_release(ustrSystemPath);
665 return osl_error;