merge the formfield patch from ooo-build
[ooovba.git] / sal / osl / unx / file_misc.cxx
bloba04d4b4c9223380139087ab86aeefb6d1d74af15
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 * 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 #include "osl/file.hxx"
30 #include "osl/diagnose.h"
31 #include "osl/thread.h"
32 #include "rtl/alloc.h"
34 #include "system.h"
35 #include "file_impl.hxx"
36 #include "file_error_transl.h"
37 #include "file_path_helper.hxx"
38 #include "file_url.h"
39 #include "uunxapi.hxx"
41 #include <sys/types.h>
42 #include <errno.h>
43 #include <dirent.h>
44 #include <limits.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <unistd.h>
48 #include <sys/stat.h>
49 #include <sys/mman.h>
51 /************************************************************************
52 * ToDo
54 * - Fix: check for corresponding struct sizes in exported functions
55 * - check size/use of oslDirectory
56 * - check size/use of oslDirectoryItem
57 ***********************************************************************/
58 /******************************************************************************
60 * Data Type Definition
62 ******************************************************************************/
64 typedef struct
66 rtl_uString* ustrPath; /* holds native directory path */
67 DIR* pDirStruct;
68 } oslDirectoryImpl;
70 #if 0
71 /* FIXME: reintroducing this may save some extra bytes per Item */
72 typedef struct
74 rtl_uString* ustrFileName; /* holds native file name */
75 rtl_uString* ustrDirPath; /* holds native dir path */
76 sal_uInt32 RefCount;
77 } oslDirectoryItemImpl;
78 #endif
80 DirectoryItem_Impl::DirectoryItem_Impl(
81 rtl_uString * ustrFilePath, unsigned char DType)
82 : m_RefCount (1),
83 m_ustrFilePath (ustrFilePath),
84 m_DType (DType)
86 if (m_ustrFilePath != 0)
87 rtl_uString_acquire(m_ustrFilePath);
89 DirectoryItem_Impl::~DirectoryItem_Impl()
91 if (m_ustrFilePath != 0)
92 rtl_uString_release(m_ustrFilePath);
95 void * DirectoryItem_Impl::operator new(size_t n)
97 return rtl_allocateMemory(n);
99 void DirectoryItem_Impl::operator delete(void * p, size_t)
101 rtl_freeMemory(p);
104 void DirectoryItem_Impl::acquire()
106 ++m_RefCount;
108 void DirectoryItem_Impl::release()
110 if (0 == --m_RefCount)
111 delete this;
114 oslFileType DirectoryItem_Impl::getFileType() const
116 switch (m_DType)
118 #ifdef _DIRENT_HAVE_D_TYPE
119 case DT_LNK:
120 return osl_File_Type_Link;
121 case DT_DIR:
122 return osl_File_Type_Directory;
123 case DT_REG:
124 return osl_File_Type_Regular;
125 case DT_FIFO:
126 return osl_File_Type_Fifo;
127 case DT_SOCK:
128 return osl_File_Type_Socket;
129 case DT_CHR:
130 case DT_BLK:
131 return osl_File_Type_Special;
132 #endif /* _DIRENT_HAVE_D_TYPE */
133 default:
134 break;
136 return osl_File_Type_Unknown;
139 /******************************************************************************
141 * C-String Function Declarations
143 *****************************************************************************/
145 static oslFileError osl_psz_createDirectory(const sal_Char* pszPath);
146 static oslFileError osl_psz_removeDirectory(const sal_Char* pszPath);
148 /*******************************************************************
149 * osl_openDirectory
150 ******************************************************************/
152 oslFileError SAL_CALL osl_openDirectory(rtl_uString* ustrDirectoryURL, oslDirectory* pDirectory)
154 rtl_uString* ustrSystemPath = NULL;
155 oslFileError eRet;
157 char path[PATH_MAX];
159 if ((0 == ustrDirectoryURL) || (0 == ustrDirectoryURL->length) || (0 == pDirectory))
160 return osl_File_E_INVAL;
162 /* convert file URL to system path */
163 eRet = osl_getSystemPathFromFileURL_Ex(ustrDirectoryURL, &ustrSystemPath, sal_False);
165 if( osl_File_E_None != eRet )
166 return eRet;
168 osl_systemPathRemoveSeparator(ustrSystemPath);
170 /* convert unicode path to text */
171 if ( UnicodeToText( path, PATH_MAX, ustrSystemPath->buffer, ustrSystemPath->length )
172 #ifdef MACOSX
173 && macxp_resolveAlias( path, PATH_MAX ) == 0
174 #endif /* MACOSX */
177 /* open directory */
178 DIR *pdir = opendir( path );
180 if( pdir )
182 /* create and initialize impl structure */
183 oslDirectoryImpl* pDirImpl = (oslDirectoryImpl*) rtl_allocateMemory( sizeof(oslDirectoryImpl) );
185 if( pDirImpl )
187 pDirImpl->pDirStruct = pdir;
188 pDirImpl->ustrPath = ustrSystemPath;
190 *pDirectory = (oslDirectory) pDirImpl;
191 return osl_File_E_None;
193 else
195 errno = ENOMEM;
196 closedir( pdir );
199 else
201 #ifdef DEBUG_OSL_FILE
202 perror ("osl_openDirectory"); fprintf (stderr, path);
203 #endif
207 rtl_uString_release( ustrSystemPath );
209 return oslTranslateFileError(OSL_FET_ERROR, errno);
212 /****************************************************************************/
213 /* osl_closeDirectory */
214 /****************************************************************************/
216 oslFileError SAL_CALL osl_closeDirectory( oslDirectory Directory )
218 oslDirectoryImpl* pDirImpl = (oslDirectoryImpl*) Directory;
219 oslFileError err = osl_File_E_None;
221 OSL_ASSERT( Directory );
223 if( NULL == pDirImpl )
224 return osl_File_E_INVAL;
226 /* close directory */
227 if( closedir( pDirImpl->pDirStruct ) )
229 err = oslTranslateFileError(OSL_FET_ERROR, errno);
232 /* cleanup members */
233 rtl_uString_release( pDirImpl->ustrPath );
235 rtl_freeMemory( pDirImpl );
237 return err;
240 /**********************************************
241 * osl_readdir_impl_
243 * readdir wrapper, filters out "." and ".."
244 * on request
245 *********************************************/
247 static struct dirent* osl_readdir_impl_(DIR* pdir, sal_Bool bFilterLocalAndParentDir)
249 struct dirent* pdirent;
251 while ((pdirent = readdir(pdir)) != NULL)
253 if (bFilterLocalAndParentDir &&
254 ((0 == strcmp(pdirent->d_name, ".")) || (0 == strcmp(pdirent->d_name, ".."))))
255 continue;
256 else
257 break;
260 return pdirent;
263 /****************************************************************************
264 * osl_getNextDirectoryItem
265 ***************************************************************************/
267 oslFileError SAL_CALL osl_getNextDirectoryItem(oslDirectory Directory, oslDirectoryItem* pItem, sal_uInt32 /*uHint*/)
269 oslDirectoryImpl* pDirImpl = (oslDirectoryImpl*)Directory;
270 rtl_uString* ustrFileName = NULL;
271 rtl_uString* ustrFilePath = NULL;
272 struct dirent* pEntry;
274 OSL_ASSERT(Directory);
275 OSL_ASSERT(pItem);
277 if ((NULL == Directory) || (NULL == pItem))
278 return osl_File_E_INVAL;
280 pEntry = osl_readdir_impl_(pDirImpl->pDirStruct, sal_True);
282 if (NULL == pEntry)
283 return osl_File_E_NOENT;
286 #if defined(MACOSX)
288 // convert decomposed filename to precomposed unicode
289 char composed_name[BUFSIZ];
290 CFMutableStringRef strRef = CFStringCreateMutable (NULL, 0 );
291 CFStringAppendCString( strRef, pEntry->d_name, kCFStringEncodingUTF8 ); //UTF8 is default on Mac OSX
292 CFStringNormalize( strRef, kCFStringNormalizationFormC );
293 CFStringGetCString( strRef, composed_name, BUFSIZ, kCFStringEncodingUTF8 );
294 CFRelease( strRef );
295 rtl_string2UString( &ustrFileName, composed_name, strlen( composed_name),
296 osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
298 #else // not MACOSX
299 /* convert file name to unicode */
300 rtl_string2UString( &ustrFileName, pEntry->d_name, strlen( pEntry->d_name ),
301 osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
302 OSL_ASSERT(ustrFileName != 0);
304 #endif
306 osl_systemPathMakeAbsolutePath(pDirImpl->ustrPath, ustrFileName, &ustrFilePath);
307 rtl_uString_release( ustrFileName );
309 DirectoryItem_Impl * pImpl = static_cast< DirectoryItem_Impl* >(*pItem);
310 if (0 != pImpl)
312 pImpl->release(), pImpl = 0;
314 #ifdef _DIRENT_HAVE_D_TYPE
315 pImpl = new DirectoryItem_Impl(ustrFilePath, pEntry->d_type);
316 #else
317 pImpl = new DirectoryItem_Impl(ustrFilePath);
318 #endif /* _DIRENT_HAVE_D_TYPE */
319 *pItem = pImpl;
320 rtl_uString_release( ustrFilePath );
322 return osl_File_E_None;
325 /****************************************************************************/
326 /* osl_getDirectoryItem */
327 /****************************************************************************/
329 oslFileError SAL_CALL osl_getDirectoryItem( rtl_uString* ustrFileURL, oslDirectoryItem* pItem )
331 rtl_uString* ustrSystemPath = NULL;
332 oslFileError osl_error = osl_File_E_INVAL;
334 OSL_ASSERT(ustrFileURL);
335 OSL_ASSERT(pItem);
337 if (0 == ustrFileURL->length || NULL == pItem)
338 return osl_File_E_INVAL;
340 osl_error = osl_getSystemPathFromFileURL_Ex(ustrFileURL, &ustrSystemPath, sal_False);
341 if (osl_File_E_None != osl_error)
342 return osl_error;
344 osl_systemPathRemoveSeparator(ustrSystemPath);
346 if (-1 == access_u(ustrSystemPath, F_OK))
348 osl_error = oslTranslateFileError(OSL_FET_ERROR, errno);
350 else
352 *pItem = new DirectoryItem_Impl(ustrSystemPath);
354 rtl_uString_release(ustrSystemPath);
356 return osl_error;
360 /****************************************************************************/
361 /* osl_acquireDirectoryItem */
362 /****************************************************************************/
364 oslFileError SAL_CALL osl_acquireDirectoryItem( oslDirectoryItem Item )
366 DirectoryItem_Impl * pImpl = static_cast< DirectoryItem_Impl* >(Item);
367 if (0 == pImpl)
368 return osl_File_E_INVAL;
370 pImpl->acquire();
371 return osl_File_E_None;
374 /****************************************************************************/
375 /* osl_releaseDirectoryItem */
376 /****************************************************************************/
378 oslFileError SAL_CALL osl_releaseDirectoryItem( oslDirectoryItem Item )
380 DirectoryItem_Impl * pImpl = static_cast< DirectoryItem_Impl* >(Item);
381 if (0 == pImpl)
382 return osl_File_E_INVAL;
384 pImpl->release();
385 return osl_File_E_None;
388 /****************************************************************************/
389 /* osl_createDirectory */
390 /****************************************************************************/
392 oslFileError SAL_CALL osl_createDirectory( rtl_uString* ustrDirectoryURL )
394 char path[PATH_MAX];
395 oslFileError eRet;
397 OSL_ASSERT( ustrDirectoryURL );
399 /* convert directory url to system path */
400 eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL );
401 if( eRet != osl_File_E_None )
402 return eRet;
404 #ifdef MACOSX
405 if ( macxp_resolveAlias( path, PATH_MAX ) != 0 )
406 return oslTranslateFileError( OSL_FET_ERROR, errno );
407 #endif/* MACOSX */
409 return osl_psz_createDirectory( path );
412 /****************************************************************************/
413 /* osl_removeDirectory */
414 /****************************************************************************/
416 oslFileError SAL_CALL osl_removeDirectory( rtl_uString* ustrDirectoryURL )
418 char path[PATH_MAX];
419 oslFileError eRet;
421 OSL_ASSERT( ustrDirectoryURL );
423 /* convert directory url to system path */
424 eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL );
425 if( eRet != osl_File_E_None )
426 return eRet;
428 #ifdef MACOSX
429 if ( macxp_resolveAlias( path, PATH_MAX ) != 0 )
430 return oslTranslateFileError( OSL_FET_ERROR, errno );
431 #endif/* MACOSX */
433 return osl_psz_removeDirectory( path );
436 /*****************************************
437 * osl_psz_createDirectory
438 ****************************************/
440 static oslFileError osl_psz_createDirectory( const sal_Char* pszPath )
442 int nRet=0;
443 int mode = S_IRWXU | S_IRWXG | S_IRWXO;
445 nRet = mkdir(pszPath,mode);
447 if ( nRet < 0 )
449 nRet=errno;
450 return oslTranslateFileError(OSL_FET_ERROR, nRet);
453 return osl_File_E_None;
456 /*****************************************
457 * osl_psz_removeDirectory
458 ****************************************/
460 static oslFileError osl_psz_removeDirectory( const sal_Char* pszPath )
462 int nRet=0;
464 nRet = rmdir(pszPath);
466 if ( nRet < 0 )
468 nRet=errno;
469 return oslTranslateFileError(OSL_FET_ERROR, nRet);
472 return osl_File_E_None;
475 /****************************************************************************/
476 /* osl_createDirectoryPath */
477 /****************************************************************************/
479 static int path_make_parent(sal_Unicode* path)
481 int i = rtl_ustr_lastIndexOfChar(path, '/');
483 if (i > 0)
485 *(path + i) = 0;
486 return i;
488 else
489 return 0;
492 static int create_dir_with_callback(
493 sal_Unicode* directory_path,
494 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
495 void* pData)
497 int mode = S_IRWXU | S_IRWXG | S_IRWXO;
499 if (osl::mkdir(directory_path, mode) == 0)
501 if (aDirectoryCreationCallbackFunc)
503 rtl::OUString url;
504 osl::FileBase::getFileURLFromSystemPath(directory_path, url);
505 aDirectoryCreationCallbackFunc(pData, url.pData);
507 return 0;
509 return errno;
512 static oslFileError create_dir_recursively_(
513 sal_Unicode* dir_path,
514 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
515 void* pData)
517 OSL_PRECOND((rtl_ustr_getLength(dir_path) > 0) && ((dir_path + (rtl_ustr_getLength(dir_path) - 1)) != (dir_path + rtl_ustr_lastIndexOfChar(dir_path, '/'))), \
518 "Path must not end with a slash");
520 int native_err = create_dir_with_callback(
521 dir_path, aDirectoryCreationCallbackFunc, pData);
523 if (native_err == 0)
524 return osl_File_E_None;
526 if (native_err != ENOENT)
527 return oslTranslateFileError(OSL_FET_ERROR, native_err);
529 // we step back until '/a_dir' at maximum because
530 // we should get an error unequal ENOENT when
531 // we try to create 'a_dir' at '/' and would so
532 // return before
533 int pos = path_make_parent(dir_path);
535 oslFileError osl_error = create_dir_recursively_(
536 dir_path, aDirectoryCreationCallbackFunc, pData);
538 if (osl_File_E_None != osl_error)
539 return osl_error;
541 dir_path[pos] = '/';
543 return create_dir_recursively_(dir_path, aDirectoryCreationCallbackFunc, pData);
546 oslFileError SAL_CALL osl_createDirectoryPath(
547 rtl_uString* aDirectoryUrl,
548 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
549 void* pData)
551 if (aDirectoryUrl == NULL)
552 return osl_File_E_INVAL;
554 rtl::OUString sys_path;
555 oslFileError osl_error = osl_getSystemPathFromFileURL_Ex(
556 aDirectoryUrl, &sys_path.pData, sal_False);
558 if (osl_error != osl_File_E_None)
559 return osl_error;
561 osl::systemPathRemoveSeparator(sys_path);
563 // const_cast because sys_path is a local copy which we want to modify inplace instead of
564 // coyp it into another buffer on the heap again
565 return create_dir_recursively_(sys_path.pData->buffer, aDirectoryCreationCallbackFunc, pData);
568 /******************************************************************************
570 * C-String Function Declarations
572 *****************************************************************************/
574 static oslFileError osl_psz_removeFile(const sal_Char* pszPath);
575 static oslFileError osl_psz_copyFile(const sal_Char* pszPath, const sal_Char* pszDestPath);
576 static oslFileError osl_psz_moveFile(const sal_Char* pszPath, const sal_Char* pszDestPath);
579 /******************************************************************************
581 * Static Module Utility Function Declarations
583 *****************************************************************************/
585 static oslFileError oslDoCopy(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, mode_t nMode, size_t nSourceSize, int DestFileExists);
586 static oslFileError oslChangeFileModes(const sal_Char* pszFileName, mode_t nMode, time_t nAcTime, time_t nModTime, uid_t nUID, gid_t nGID);
587 static int oslDoCopyLink(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName);
588 static int oslDoCopyFile(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, size_t nSourceSize, mode_t mode);
589 static oslFileError oslDoMoveFile(const sal_Char* pszPath, const sal_Char* pszDestPath);
591 /****************************************************************************/
592 /* osl_moveFile */
593 /****************************************************************************/
595 oslFileError SAL_CALL osl_moveFile( rtl_uString* ustrFileURL, rtl_uString* ustrDestURL )
597 char srcPath[PATH_MAX];
598 char destPath[PATH_MAX];
599 oslFileError eRet;
601 OSL_ASSERT( ustrFileURL );
602 OSL_ASSERT( ustrDestURL );
604 /* convert source url to system path */
605 eRet = FileURLToPath( srcPath, PATH_MAX, ustrFileURL );
606 if( eRet != osl_File_E_None )
607 return eRet;
609 /* convert destination url to system path */
610 eRet = FileURLToPath( destPath, PATH_MAX, ustrDestURL );
611 if( eRet != osl_File_E_None )
612 return eRet;
614 #ifdef MACOSX
615 if ( macxp_resolveAlias( srcPath, PATH_MAX ) != 0 || macxp_resolveAlias( destPath, PATH_MAX ) != 0 )
616 return oslTranslateFileError( OSL_FET_ERROR, errno );
617 #endif/* MACOSX */
619 return oslDoMoveFile( srcPath, destPath );
622 /****************************************************************************/
623 /* osl_copyFile */
624 /****************************************************************************/
626 oslFileError SAL_CALL osl_copyFile( rtl_uString* ustrFileURL, rtl_uString* ustrDestURL )
628 char srcPath[PATH_MAX];
629 char destPath[PATH_MAX];
630 oslFileError eRet;
632 OSL_ASSERT( ustrFileURL );
633 OSL_ASSERT( ustrDestURL );
635 /* convert source url to system path */
636 eRet = FileURLToPath( srcPath, PATH_MAX, ustrFileURL );
637 if( eRet != osl_File_E_None )
638 return eRet;
640 /* convert destination url to system path */
641 eRet = FileURLToPath( destPath, PATH_MAX, ustrDestURL );
642 if( eRet != osl_File_E_None )
643 return eRet;
645 #ifdef MACOSX
646 if ( macxp_resolveAlias( srcPath, PATH_MAX ) != 0 || macxp_resolveAlias( destPath, PATH_MAX ) != 0 )
647 return oslTranslateFileError( OSL_FET_ERROR, errno );
648 #endif/* MACOSX */
650 return osl_psz_copyFile( srcPath, destPath );
653 /****************************************************************************/
654 /* osl_removeFile */
655 /****************************************************************************/
657 oslFileError SAL_CALL osl_removeFile( rtl_uString* ustrFileURL )
659 char path[PATH_MAX];
660 oslFileError eRet;
662 OSL_ASSERT( ustrFileURL );
664 /* convert file url to system path */
665 eRet = FileURLToPath( path, PATH_MAX, ustrFileURL );
666 if( eRet != osl_File_E_None )
667 return eRet;
669 #ifdef MACOSX
670 if ( macxp_resolveAlias( path, PATH_MAX ) != 0 )
671 return oslTranslateFileError( OSL_FET_ERROR, errno );
672 #endif/* MACOSX */
674 return osl_psz_removeFile( path );
677 /******************************************************************************
679 * Utility Functions
681 *****************************************************************************/
683 /*****************************************
684 * oslDoMoveFile
685 ****************************************/
687 static oslFileError oslDoMoveFile( const sal_Char* pszPath, const sal_Char* pszDestPath)
689 oslFileError tErr=osl_File_E_invalidError;
691 tErr = osl_psz_moveFile(pszPath,pszDestPath);
692 if ( tErr == osl_File_E_None )
694 return tErr;
697 if ( tErr != osl_File_E_XDEV )
699 return tErr;
702 tErr=osl_psz_copyFile(pszPath,pszDestPath);
704 if ( tErr != osl_File_E_None )
706 oslFileError tErrRemove;
707 tErrRemove=osl_psz_removeFile(pszDestPath);
708 return tErr;
711 tErr=osl_psz_removeFile(pszPath);
713 return tErr;
716 /*****************************************
717 * osl_psz_removeFile
718 ****************************************/
719 static oslFileError osl_psz_removeFile( const sal_Char* pszPath )
721 int nRet=0;
722 struct stat aStat;
724 nRet = lstat(pszPath,&aStat);
725 if ( nRet < 0 )
727 nRet=errno;
728 return oslTranslateFileError(OSL_FET_ERROR, nRet);
731 if ( S_ISDIR(aStat.st_mode) )
733 return osl_File_E_ISDIR;
736 nRet = unlink(pszPath);
737 if ( nRet < 0 )
739 nRet=errno;
740 return oslTranslateFileError(OSL_FET_ERROR, nRet);
743 return osl_File_E_None;
746 /*****************************************
747 * osl_psz_moveFile
748 ****************************************/
750 static oslFileError osl_psz_moveFile(const sal_Char* pszPath, const sal_Char* pszDestPath)
753 int nRet = 0;
755 nRet = rename(pszPath,pszDestPath);
757 if ( nRet < 0 )
759 nRet=errno;
760 return oslTranslateFileError(OSL_FET_ERROR, nRet);
763 return osl_File_E_None;
766 /*****************************************
767 * osl_psz_copyFile
768 ****************************************/
770 static oslFileError osl_psz_copyFile( const sal_Char* pszPath, const sal_Char* pszDestPath )
772 time_t nAcTime=0;
773 time_t nModTime=0;
774 uid_t nUID=0;
775 gid_t nGID=0;
776 int nRet=0;
777 mode_t nMode=0;
778 struct stat aFileStat;
779 oslFileError tErr=osl_File_E_invalidError;
780 size_t nSourceSize=0;
781 int DestFileExists=1;
783 /* mfe: does the source file really exists? */
784 nRet = lstat(pszPath,&aFileStat);
786 if ( nRet < 0 )
788 nRet=errno;
789 return oslTranslateFileError(OSL_FET_ERROR, nRet);
792 /* mfe: we do only copy files here! */
793 if ( S_ISDIR(aFileStat.st_mode) )
795 return osl_File_E_ISDIR;
798 nSourceSize=(size_t)aFileStat.st_size;
799 nMode=aFileStat.st_mode;
800 nAcTime=aFileStat.st_atime;
801 nModTime=aFileStat.st_mtime;
802 nUID=aFileStat.st_uid;
803 nGID=aFileStat.st_gid;
805 nRet = stat(pszDestPath,&aFileStat);
806 if ( nRet < 0 )
808 nRet=errno;
810 if ( nRet == ENOENT )
812 DestFileExists=0;
814 /* return oslTranslateFileError(nRet);*/
817 /* mfe: the destination file must not be a directory! */
818 if ( nRet == 0 && S_ISDIR(aFileStat.st_mode) )
820 return osl_File_E_ISDIR;
822 else
824 /* mfe: file does not exists or is no dir */
827 tErr = oslDoCopy(pszPath,pszDestPath,nMode,nSourceSize,DestFileExists);
829 if ( tErr != osl_File_E_None )
831 return tErr;
835 * mfe: ignore return code
836 * since only the success of the copy is
837 * important
839 oslChangeFileModes(pszDestPath,nMode,nAcTime,nModTime,nUID,nGID);
841 return tErr;
845 /******************************************************************************
847 * Utility Functions
849 *****************************************************************************/
851 /*****************************************
852 * oslDoCopy
853 ****************************************/
855 #define TMP_DEST_FILE_EXTENSION ".osl-tmp"
857 static oslFileError oslDoCopy(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, mode_t nMode, size_t nSourceSize, int DestFileExists)
859 int nRet=0;
860 sal_Char pszTmpDestFile[PATH_MAX];
861 size_t size_tmp_dest_buff = sizeof(pszTmpDestFile);
863 /* Quick fix for #106048, the whole copy file function seems
864 to be erroneous anyway and needs to be rewritten.
865 Besides osl_copyFile is currently not used from OO/SO code.
867 memset(pszTmpDestFile, 0, size_tmp_dest_buff);
869 if ( DestFileExists )
871 strncpy(pszTmpDestFile, pszDestFileName, size_tmp_dest_buff - 1);
873 if ((strlen(pszTmpDestFile) + strlen(TMP_DEST_FILE_EXTENSION)) >= size_tmp_dest_buff)
874 return osl_File_E_NAMETOOLONG;
876 strncat(pszTmpDestFile, TMP_DEST_FILE_EXTENSION, strlen(TMP_DEST_FILE_EXTENSION));
878 /* FIXME: what if pszTmpDestFile already exists? */
879 /* with getcanonical??? */
880 nRet=rename(pszDestFileName,pszTmpDestFile);
883 /* mfe: should be S_ISREG */
884 if ( !S_ISLNK(nMode) )
886 /* copy SourceFile to DestFile */
887 nRet = oslDoCopyFile(pszSourceFileName,pszDestFileName,nSourceSize, nMode);
889 /* mfe: OK redundant at the moment */
890 else if ( S_ISLNK(nMode) )
892 nRet = oslDoCopyLink(pszSourceFileName,pszDestFileName);
894 else
896 /* mfe: what to do here? */
897 nRet=ENOSYS;
900 if ( nRet > 0 && DestFileExists == 1 )
902 unlink(pszDestFileName);
903 rename(pszTmpDestFile,pszDestFileName);
906 if ( nRet > 0 )
908 return oslTranslateFileError(OSL_FET_ERROR, nRet);
911 if ( DestFileExists == 1 )
913 unlink(pszTmpDestFile);
916 return osl_File_E_None;
919 /*****************************************
920 * oslChangeFileModes
921 ****************************************/
923 static oslFileError oslChangeFileModes( const sal_Char* pszFileName, mode_t nMode, time_t nAcTime, time_t nModTime, uid_t nUID, gid_t nGID)
925 int nRet=0;
926 struct utimbuf aTimeBuffer;
928 nRet = chmod(pszFileName,nMode);
929 if ( nRet < 0 )
931 nRet=errno;
932 return oslTranslateFileError(OSL_FET_ERROR, nRet);
935 aTimeBuffer.actime=nAcTime;
936 aTimeBuffer.modtime=nModTime;
937 nRet=utime(pszFileName,&aTimeBuffer);
938 if ( nRet < 0 )
940 nRet=errno;
941 return oslTranslateFileError(OSL_FET_ERROR, nRet);
944 if ( nUID != getuid() )
946 nUID=getuid();
949 nRet=chown(pszFileName,nUID,nGID);
950 if ( nRet < 0 )
952 nRet=errno;
954 /* mfe: do not return an error here! */
955 /* return oslTranslateFileError(nRet);*/
958 return osl_File_E_None;
961 /*****************************************
962 * oslDoCopyLink
963 ****************************************/
965 static int oslDoCopyLink(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName)
967 int nRet=0;
969 /* mfe: if dest file is symbolic link remove the link and place the file instead (hro says so) */
970 /* mfe: if source is a link copy the link and not the file it points to (hro says so) */
971 sal_Char pszLinkContent[PATH_MAX];
973 pszLinkContent[0] = '\0';
975 nRet = readlink(pszSourceFileName,pszLinkContent,PATH_MAX);
977 if ( nRet < 0 )
979 nRet=errno;
980 return nRet;
982 else
983 pszLinkContent[ nRet ] = 0;
985 nRet = symlink(pszLinkContent,pszDestFileName);
987 if ( nRet < 0 )
989 nRet=errno;
990 return nRet;
993 return 0;
996 /*****************************************
997 * oslDoCopyFile
998 ****************************************/
1000 static int oslDoCopyFile(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, size_t nSourceSize, mode_t mode)
1002 int SourceFileFD=0;
1003 int DestFileFD=0;
1004 int nRet=0;
1005 void* pSourceFile=0;
1007 SourceFileFD=open(pszSourceFileName,O_RDONLY);
1008 if ( SourceFileFD < 0 )
1010 nRet=errno;
1011 return nRet;
1014 DestFileFD=open(pszDestFileName, O_WRONLY | O_CREAT, mode);
1016 if ( DestFileFD < 0 )
1018 nRet=errno;
1019 close(SourceFileFD);
1020 return nRet;
1023 /* HACK: because memory mapping fails on various
1024 platforms if the size of the source file is 0 byte */
1025 if (0 == nSourceSize)
1027 close(SourceFileFD);
1028 close(DestFileFD);
1029 return 0;
1032 /* FIXME doCopy: fall back code for systems not having mmap */
1033 /* mmap file -- open dest file -- write once -- fsync it */
1034 pSourceFile=mmap(0,nSourceSize,PROT_READ,MAP_PRIVATE,SourceFileFD,0);
1036 if ( pSourceFile == MAP_FAILED )
1038 /* it's important to set nRet before the hack
1039 otherwise errno may be changed by lstat */
1040 nRet = errno;
1041 close(SourceFileFD);
1042 close(DestFileFD);
1044 return nRet;
1047 nRet = write(DestFileFD,pSourceFile,nSourceSize);
1049 /* #112584# if 'write' could not write the requested number of bytes
1050 we have to fail of course; because it's not exactly specified if 'write'
1051 sets errno if less than requested byte could be written we set nRet
1052 explicitly to ENOSPC */
1053 if ((nRet < 0) || (nRet != sal::static_int_cast< int >(nSourceSize)))
1055 if (nRet < 0)
1056 nRet = errno;
1057 else
1058 nRet = ENOSPC;
1060 close(SourceFileFD);
1061 close(DestFileFD);
1062 munmap((char*)pSourceFile,nSourceSize);
1063 return nRet;
1066 nRet = munmap((char*)pSourceFile,nSourceSize);
1067 if ( nRet < 0 )
1069 nRet=errno;
1070 close(SourceFileFD);
1071 close(DestFileFD);
1072 return nRet;
1075 close(SourceFileFD);
1077 // Removed call to 'fsync' again (#112584#) and instead
1078 // evaluate the return value of 'close' in order to detect
1079 // and report ENOSPC and other erronous conditions on close
1080 if (close(DestFileFD) == -1)
1081 return errno;
1082 else
1083 return 0;