merged tag ooo/DEV300_m102
[LibreOffice.git] / sal / osl / unx / file_misc.cxx
blob2ed57b01a2c4f6e74f2dad2cc6d96ba39f3b293e
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 #include "osl/file.hxx"
30 #include "osl/diagnose.h"
31 #include "osl/thread.h"
32 #include <osl/signal.h>
33 #include "rtl/alloc.h"
35 #include "system.h"
36 #include "file_impl.hxx"
37 #include "file_error_transl.h"
38 #include "file_path_helper.hxx"
39 #include "file_url.h"
40 #include "uunxapi.hxx"
42 #include <sys/types.h>
43 #include <errno.h>
44 #include <dirent.h>
45 #include <limits.h>
46 #include <stdio.h>
47 #include <string.h>
48 #include <unistd.h>
49 #include <sys/stat.h>
50 #include <sys/mman.h>
52 #include <algorithm>
54 /************************************************************************
55 * ToDo
57 * - Fix: check for corresponding struct sizes in exported functions
58 * - check size/use of oslDirectory
59 * - check size/use of oslDirectoryItem
60 ***********************************************************************/
61 /******************************************************************************
63 * Data Type Definition
65 ******************************************************************************/
67 typedef struct
69 rtl_uString* ustrPath; /* holds native directory path */
70 DIR* pDirStruct;
71 } oslDirectoryImpl;
73 #if 0
74 /* FIXME: reintroducing this may save some extra bytes per Item */
75 typedef struct
77 rtl_uString* ustrFileName; /* holds native file name */
78 rtl_uString* ustrDirPath; /* holds native dir path */
79 sal_uInt32 RefCount;
80 } oslDirectoryItemImpl;
81 #endif
83 DirectoryItem_Impl::DirectoryItem_Impl(
84 rtl_uString * ustrFilePath, unsigned char DType)
85 : m_RefCount (1),
86 m_ustrFilePath (ustrFilePath),
87 m_DType (DType)
89 if (m_ustrFilePath != 0)
90 rtl_uString_acquire(m_ustrFilePath);
92 DirectoryItem_Impl::~DirectoryItem_Impl()
94 if (m_ustrFilePath != 0)
95 rtl_uString_release(m_ustrFilePath);
98 void * DirectoryItem_Impl::operator new(size_t n)
100 return rtl_allocateMemory(n);
102 void DirectoryItem_Impl::operator delete(void * p, size_t)
104 rtl_freeMemory(p);
107 void DirectoryItem_Impl::acquire()
109 ++m_RefCount;
111 void DirectoryItem_Impl::release()
113 if (0 == --m_RefCount)
114 delete this;
117 oslFileType DirectoryItem_Impl::getFileType() const
119 switch (m_DType)
121 #ifdef _DIRENT_HAVE_D_TYPE
122 case DT_LNK:
123 return osl_File_Type_Link;
124 case DT_DIR:
125 return osl_File_Type_Directory;
126 case DT_REG:
127 return osl_File_Type_Regular;
128 case DT_FIFO:
129 return osl_File_Type_Fifo;
130 case DT_SOCK:
131 return osl_File_Type_Socket;
132 case DT_CHR:
133 case DT_BLK:
134 return osl_File_Type_Special;
135 #endif /* _DIRENT_HAVE_D_TYPE */
136 default:
137 break;
139 return osl_File_Type_Unknown;
142 /******************************************************************************
144 * C-String Function Declarations
146 *****************************************************************************/
148 static oslFileError osl_psz_createDirectory(const sal_Char* pszPath);
149 static oslFileError osl_psz_removeDirectory(const sal_Char* pszPath);
151 /*******************************************************************
152 * osl_openDirectory
153 ******************************************************************/
155 oslFileError SAL_CALL osl_openDirectory(rtl_uString* ustrDirectoryURL, oslDirectory* pDirectory)
157 rtl_uString* ustrSystemPath = NULL;
158 oslFileError eRet;
160 char path[PATH_MAX];
162 if ((0 == ustrDirectoryURL) || (0 == ustrDirectoryURL->length) || (0 == pDirectory))
163 return osl_File_E_INVAL;
165 /* convert file URL to system path */
166 eRet = osl_getSystemPathFromFileURL_Ex(ustrDirectoryURL, &ustrSystemPath, sal_False);
168 if( osl_File_E_None != eRet )
169 return eRet;
171 osl_systemPathRemoveSeparator(ustrSystemPath);
173 /* convert unicode path to text */
174 if ( UnicodeToText( path, PATH_MAX, ustrSystemPath->buffer, ustrSystemPath->length )
175 #ifdef MACOSX
176 && macxp_resolveAlias( path, PATH_MAX ) == 0
177 #endif /* MACOSX */
180 /* open directory */
181 DIR *pdir = opendir( path );
183 if( pdir )
185 /* create and initialize impl structure */
186 oslDirectoryImpl* pDirImpl = (oslDirectoryImpl*) rtl_allocateMemory( sizeof(oslDirectoryImpl) );
188 if( pDirImpl )
190 pDirImpl->pDirStruct = pdir;
191 pDirImpl->ustrPath = ustrSystemPath;
193 *pDirectory = (oslDirectory) pDirImpl;
194 return osl_File_E_None;
196 else
198 errno = ENOMEM;
199 closedir( pdir );
202 else
204 #ifdef DEBUG_OSL_FILE
205 perror ("osl_openDirectory"); fprintf (stderr, path);
206 #endif
210 rtl_uString_release( ustrSystemPath );
212 return oslTranslateFileError(OSL_FET_ERROR, errno);
215 /****************************************************************************/
216 /* osl_closeDirectory */
217 /****************************************************************************/
219 oslFileError SAL_CALL osl_closeDirectory( oslDirectory Directory )
221 oslDirectoryImpl* pDirImpl = (oslDirectoryImpl*) Directory;
222 oslFileError err = osl_File_E_None;
224 OSL_ASSERT( Directory );
226 if( NULL == pDirImpl )
227 return osl_File_E_INVAL;
229 /* close directory */
230 if( closedir( pDirImpl->pDirStruct ) )
232 err = oslTranslateFileError(OSL_FET_ERROR, errno);
235 /* cleanup members */
236 rtl_uString_release( pDirImpl->ustrPath );
238 rtl_freeMemory( pDirImpl );
240 return err;
243 /**********************************************
244 * osl_readdir_impl_
246 * readdir wrapper, filters out "." and ".."
247 * on request
248 *********************************************/
250 static struct dirent* osl_readdir_impl_(DIR* pdir, sal_Bool bFilterLocalAndParentDir)
252 struct dirent* pdirent;
254 while ((pdirent = readdir(pdir)) != NULL)
256 if (bFilterLocalAndParentDir &&
257 ((0 == strcmp(pdirent->d_name, ".")) || (0 == strcmp(pdirent->d_name, ".."))))
258 continue;
259 else
260 break;
263 return pdirent;
266 /****************************************************************************
267 * osl_getNextDirectoryItem
268 ***************************************************************************/
270 oslFileError SAL_CALL osl_getNextDirectoryItem(oslDirectory Directory, oslDirectoryItem* pItem, sal_uInt32 /*uHint*/)
272 oslDirectoryImpl* pDirImpl = (oslDirectoryImpl*)Directory;
273 rtl_uString* ustrFileName = NULL;
274 rtl_uString* ustrFilePath = NULL;
275 struct dirent* pEntry;
277 OSL_ASSERT(Directory);
278 OSL_ASSERT(pItem);
280 if ((NULL == Directory) || (NULL == pItem))
281 return osl_File_E_INVAL;
283 pEntry = osl_readdir_impl_(pDirImpl->pDirStruct, sal_True);
285 if (NULL == pEntry)
286 return osl_File_E_NOENT;
289 #if defined(MACOSX)
291 // convert decomposed filename to precomposed unicode
292 char composed_name[BUFSIZ];
293 CFMutableStringRef strRef = CFStringCreateMutable (NULL, 0 );
294 CFStringAppendCString( strRef, pEntry->d_name, kCFStringEncodingUTF8 ); //UTF8 is default on Mac OSX
295 CFStringNormalize( strRef, kCFStringNormalizationFormC );
296 CFStringGetCString( strRef, composed_name, BUFSIZ, kCFStringEncodingUTF8 );
297 CFRelease( strRef );
298 rtl_string2UString( &ustrFileName, composed_name, strlen( composed_name),
299 osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
301 #else // not MACOSX
302 /* convert file name to unicode */
303 rtl_string2UString( &ustrFileName, pEntry->d_name, strlen( pEntry->d_name ),
304 osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
305 OSL_ASSERT(ustrFileName != 0);
307 #endif
309 osl_systemPathMakeAbsolutePath(pDirImpl->ustrPath, ustrFileName, &ustrFilePath);
310 rtl_uString_release( ustrFileName );
312 DirectoryItem_Impl * pImpl = static_cast< DirectoryItem_Impl* >(*pItem);
313 if (0 != pImpl)
315 pImpl->release(), pImpl = 0;
317 #ifdef _DIRENT_HAVE_D_TYPE
318 pImpl = new DirectoryItem_Impl(ustrFilePath, pEntry->d_type);
319 #else
320 pImpl = new DirectoryItem_Impl(ustrFilePath);
321 #endif /* _DIRENT_HAVE_D_TYPE */
322 *pItem = pImpl;
323 rtl_uString_release( ustrFilePath );
325 return osl_File_E_None;
328 /****************************************************************************/
329 /* osl_getDirectoryItem */
330 /****************************************************************************/
332 oslFileError SAL_CALL osl_getDirectoryItem( rtl_uString* ustrFileURL, oslDirectoryItem* pItem )
334 rtl_uString* ustrSystemPath = NULL;
335 oslFileError osl_error = osl_File_E_INVAL;
337 OSL_ASSERT((0 != ustrFileURL) && (0 != pItem));
338 if ((0 == ustrFileURL) || (0 == ustrFileURL->length) || (0 == pItem))
339 return osl_File_E_INVAL;
341 osl_error = osl_getSystemPathFromFileURL_Ex(ustrFileURL, &ustrSystemPath, sal_False);
342 if (osl_File_E_None != osl_error)
343 return osl_error;
345 osl_systemPathRemoveSeparator(ustrSystemPath);
347 if (-1 == access_u(ustrSystemPath, F_OK))
349 osl_error = oslTranslateFileError(OSL_FET_ERROR, errno);
351 else
353 *pItem = new DirectoryItem_Impl(ustrSystemPath);
355 rtl_uString_release(ustrSystemPath);
357 return osl_error;
361 /****************************************************************************/
362 /* osl_acquireDirectoryItem */
363 /****************************************************************************/
365 oslFileError SAL_CALL osl_acquireDirectoryItem( oslDirectoryItem Item )
367 DirectoryItem_Impl * pImpl = static_cast< DirectoryItem_Impl* >(Item);
368 if (0 == pImpl)
369 return osl_File_E_INVAL;
371 pImpl->acquire();
372 return osl_File_E_None;
375 /****************************************************************************/
376 /* osl_releaseDirectoryItem */
377 /****************************************************************************/
379 oslFileError SAL_CALL osl_releaseDirectoryItem( oslDirectoryItem Item )
381 DirectoryItem_Impl * pImpl = static_cast< DirectoryItem_Impl* >(Item);
382 if (0 == pImpl)
383 return osl_File_E_INVAL;
385 pImpl->release();
386 return osl_File_E_None;
389 /****************************************************************************/
390 /* osl_createDirectory */
391 /****************************************************************************/
393 oslFileError SAL_CALL osl_createDirectory( rtl_uString* ustrDirectoryURL )
395 char path[PATH_MAX];
396 oslFileError eRet;
398 OSL_ASSERT( ustrDirectoryURL );
400 /* convert directory url to system path */
401 eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL );
402 if( eRet != osl_File_E_None )
403 return eRet;
405 #ifdef MACOSX
406 if ( macxp_resolveAlias( path, PATH_MAX ) != 0 )
407 return oslTranslateFileError( OSL_FET_ERROR, errno );
408 #endif/* MACOSX */
410 return osl_psz_createDirectory( path );
413 /****************************************************************************/
414 /* osl_removeDirectory */
415 /****************************************************************************/
417 oslFileError SAL_CALL osl_removeDirectory( rtl_uString* ustrDirectoryURL )
419 char path[PATH_MAX];
420 oslFileError eRet;
422 OSL_ASSERT( ustrDirectoryURL );
424 /* convert directory url to system path */
425 eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL );
426 if( eRet != osl_File_E_None )
427 return eRet;
429 #ifdef MACOSX
430 if ( macxp_resolveAlias( path, PATH_MAX ) != 0 )
431 return oslTranslateFileError( OSL_FET_ERROR, errno );
432 #endif/* MACOSX */
434 return osl_psz_removeDirectory( path );
437 /*****************************************
438 * osl_psz_createDirectory
439 ****************************************/
441 static oslFileError osl_psz_createDirectory( const sal_Char* pszPath )
443 int nRet=0;
444 int mode = S_IRWXU | S_IRWXG | S_IRWXO;
446 nRet = mkdir(pszPath,mode);
448 if ( nRet < 0 )
450 nRet=errno;
451 return oslTranslateFileError(OSL_FET_ERROR, nRet);
454 return osl_File_E_None;
457 /*****************************************
458 * osl_psz_removeDirectory
459 ****************************************/
461 static oslFileError osl_psz_removeDirectory( const sal_Char* pszPath )
463 int nRet=0;
465 nRet = rmdir(pszPath);
467 if ( nRet < 0 )
469 nRet=errno;
470 return oslTranslateFileError(OSL_FET_ERROR, nRet);
473 return osl_File_E_None;
476 /****************************************************************************/
477 /* osl_createDirectoryPath */
478 /****************************************************************************/
480 static int path_make_parent(sal_Unicode* path)
482 int i = rtl_ustr_lastIndexOfChar(path, '/');
484 if (i > 0)
486 *(path + i) = 0;
487 return i;
489 else
490 return 0;
493 static int create_dir_with_callback(
494 sal_Unicode* directory_path,
495 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
496 void* pData)
498 int mode = S_IRWXU | S_IRWXG | S_IRWXO;
500 if (osl::mkdir(directory_path, mode) == 0)
502 if (aDirectoryCreationCallbackFunc)
504 rtl::OUString url;
505 osl::FileBase::getFileURLFromSystemPath(directory_path, url);
506 aDirectoryCreationCallbackFunc(pData, url.pData);
508 return 0;
510 return errno;
513 static oslFileError create_dir_recursively_(
514 sal_Unicode* dir_path,
515 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
516 void* pData)
518 OSL_PRECOND((rtl_ustr_getLength(dir_path) > 0) && ((dir_path + (rtl_ustr_getLength(dir_path) - 1)) != (dir_path + rtl_ustr_lastIndexOfChar(dir_path, '/'))), \
519 "Path must not end with a slash");
521 int native_err = create_dir_with_callback(
522 dir_path, aDirectoryCreationCallbackFunc, pData);
524 if (native_err == 0)
525 return osl_File_E_None;
527 if (native_err != ENOENT)
528 return oslTranslateFileError(OSL_FET_ERROR, native_err);
530 // we step back until '/a_dir' at maximum because
531 // we should get an error unequal ENOENT when
532 // we try to create 'a_dir' at '/' and would so
533 // return before
534 int pos = path_make_parent(dir_path);
536 oslFileError osl_error = create_dir_recursively_(
537 dir_path, aDirectoryCreationCallbackFunc, pData);
539 if (osl_File_E_None != osl_error)
540 return osl_error;
542 dir_path[pos] = '/';
544 return create_dir_recursively_(dir_path, aDirectoryCreationCallbackFunc, pData);
547 oslFileError SAL_CALL osl_createDirectoryPath(
548 rtl_uString* aDirectoryUrl,
549 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
550 void* pData)
552 if (aDirectoryUrl == NULL)
553 return osl_File_E_INVAL;
555 rtl::OUString sys_path;
556 oslFileError osl_error = osl_getSystemPathFromFileURL_Ex(
557 aDirectoryUrl, &sys_path.pData, sal_False);
559 if (osl_error != osl_File_E_None)
560 return osl_error;
562 osl::systemPathRemoveSeparator(sys_path);
564 // const_cast because sys_path is a local copy which we want to modify inplace instead of
565 // coyp it into another buffer on the heap again
566 return create_dir_recursively_(sys_path.pData->buffer, aDirectoryCreationCallbackFunc, pData);
569 /******************************************************************************
571 * C-String Function Declarations
573 *****************************************************************************/
575 static oslFileError osl_psz_removeFile(const sal_Char* pszPath);
576 static oslFileError osl_psz_copyFile(const sal_Char* pszPath, const sal_Char* pszDestPath);
577 static oslFileError osl_psz_moveFile(const sal_Char* pszPath, const sal_Char* pszDestPath);
580 /******************************************************************************
582 * Static Module Utility Function Declarations
584 *****************************************************************************/
586 static oslFileError oslDoCopy(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, mode_t nMode, size_t nSourceSize, int DestFileExists);
587 static oslFileError oslChangeFileModes(const sal_Char* pszFileName, mode_t nMode, time_t nAcTime, time_t nModTime, uid_t nUID, gid_t nGID);
588 static int oslDoCopyLink(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName);
589 static int oslDoCopyFile(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, size_t nSourceSize, mode_t mode);
590 static oslFileError oslDoMoveFile(const sal_Char* pszPath, const sal_Char* pszDestPath);
592 /****************************************************************************/
593 /* osl_moveFile */
594 /****************************************************************************/
596 oslFileError SAL_CALL osl_moveFile( rtl_uString* ustrFileURL, rtl_uString* ustrDestURL )
598 char srcPath[PATH_MAX];
599 char destPath[PATH_MAX];
600 oslFileError eRet;
602 OSL_ASSERT( ustrFileURL );
603 OSL_ASSERT( ustrDestURL );
605 /* convert source url to system path */
606 eRet = FileURLToPath( srcPath, PATH_MAX, ustrFileURL );
607 if( eRet != osl_File_E_None )
608 return eRet;
610 /* convert destination url to system path */
611 eRet = FileURLToPath( destPath, PATH_MAX, ustrDestURL );
612 if( eRet != osl_File_E_None )
613 return eRet;
615 #ifdef MACOSX
616 if ( macxp_resolveAlias( srcPath, PATH_MAX ) != 0 || macxp_resolveAlias( destPath, PATH_MAX ) != 0 )
617 return oslTranslateFileError( OSL_FET_ERROR, errno );
618 #endif/* MACOSX */
620 return oslDoMoveFile( srcPath, destPath );
623 /****************************************************************************/
624 /* osl_copyFile */
625 /****************************************************************************/
627 oslFileError SAL_CALL osl_copyFile( rtl_uString* ustrFileURL, rtl_uString* ustrDestURL )
629 char srcPath[PATH_MAX];
630 char destPath[PATH_MAX];
631 oslFileError eRet;
633 OSL_ASSERT( ustrFileURL );
634 OSL_ASSERT( ustrDestURL );
636 /* convert source url to system path */
637 eRet = FileURLToPath( srcPath, PATH_MAX, ustrFileURL );
638 if( eRet != osl_File_E_None )
639 return eRet;
641 /* convert destination url to system path */
642 eRet = FileURLToPath( destPath, PATH_MAX, ustrDestURL );
643 if( eRet != osl_File_E_None )
644 return eRet;
646 #ifdef MACOSX
647 if ( macxp_resolveAlias( srcPath, PATH_MAX ) != 0 || macxp_resolveAlias( destPath, PATH_MAX ) != 0 )
648 return oslTranslateFileError( OSL_FET_ERROR, errno );
649 #endif/* MACOSX */
651 return osl_psz_copyFile( srcPath, destPath );
654 /****************************************************************************/
655 /* osl_removeFile */
656 /****************************************************************************/
658 oslFileError SAL_CALL osl_removeFile( rtl_uString* ustrFileURL )
660 char path[PATH_MAX];
661 oslFileError eRet;
663 OSL_ASSERT( ustrFileURL );
665 /* convert file url to system path */
666 eRet = FileURLToPath( path, PATH_MAX, ustrFileURL );
667 if( eRet != osl_File_E_None )
668 return eRet;
670 #ifdef MACOSX
671 if ( macxp_resolveAlias( path, PATH_MAX ) != 0 )
672 return oslTranslateFileError( OSL_FET_ERROR, errno );
673 #endif/* MACOSX */
675 return osl_psz_removeFile( path );
678 /******************************************************************************
680 * Utility Functions
682 *****************************************************************************/
684 /*****************************************
685 * oslDoMoveFile
686 ****************************************/
688 static oslFileError oslDoMoveFile( const sal_Char* pszPath, const sal_Char* pszDestPath)
690 oslFileError tErr=osl_File_E_invalidError;
692 tErr = osl_psz_moveFile(pszPath,pszDestPath);
693 if ( tErr == osl_File_E_None )
695 return tErr;
698 if ( tErr != osl_File_E_XDEV )
700 return tErr;
703 tErr=osl_psz_copyFile(pszPath,pszDestPath);
705 if ( tErr != osl_File_E_None )
707 oslFileError tErrRemove;
708 tErrRemove=osl_psz_removeFile(pszDestPath);
709 return tErr;
712 tErr=osl_psz_removeFile(pszPath);
714 return tErr;
717 /*****************************************
718 * osl_psz_removeFile
719 ****************************************/
720 static oslFileError osl_psz_removeFile( const sal_Char* pszPath )
722 int nRet=0;
723 struct stat aStat;
725 nRet = lstat(pszPath,&aStat);
726 if ( nRet < 0 )
728 nRet=errno;
729 return oslTranslateFileError(OSL_FET_ERROR, nRet);
732 if ( S_ISDIR(aStat.st_mode) )
734 return osl_File_E_ISDIR;
737 nRet = unlink(pszPath);
738 if ( nRet < 0 )
740 nRet=errno;
741 return oslTranslateFileError(OSL_FET_ERROR, nRet);
744 return osl_File_E_None;
747 /*****************************************
748 * osl_psz_moveFile
749 ****************************************/
751 static oslFileError osl_psz_moveFile(const sal_Char* pszPath, const sal_Char* pszDestPath)
754 int nRet = 0;
756 nRet = rename(pszPath,pszDestPath);
758 if ( nRet < 0 )
760 nRet=errno;
761 return oslTranslateFileError(OSL_FET_ERROR, nRet);
764 return osl_File_E_None;
767 /*****************************************
768 * osl_psz_copyFile
769 ****************************************/
771 static oslFileError osl_psz_copyFile( const sal_Char* pszPath, const sal_Char* pszDestPath )
773 time_t nAcTime=0;
774 time_t nModTime=0;
775 uid_t nUID=0;
776 gid_t nGID=0;
777 int nRet=0;
778 mode_t nMode=0;
779 struct stat aFileStat;
780 oslFileError tErr=osl_File_E_invalidError;
781 size_t nSourceSize=0;
782 int DestFileExists=1;
784 /* mfe: does the source file really exists? */
785 nRet = lstat(pszPath,&aFileStat);
787 if ( nRet < 0 )
789 nRet=errno;
790 return oslTranslateFileError(OSL_FET_ERROR, nRet);
793 /* mfe: we do only copy files here! */
794 if ( S_ISDIR(aFileStat.st_mode) )
796 return osl_File_E_ISDIR;
799 nSourceSize=(size_t)aFileStat.st_size;
800 nMode=aFileStat.st_mode;
801 nAcTime=aFileStat.st_atime;
802 nModTime=aFileStat.st_mtime;
803 nUID=aFileStat.st_uid;
804 nGID=aFileStat.st_gid;
806 nRet = stat(pszDestPath,&aFileStat);
807 if ( nRet < 0 )
809 nRet=errno;
811 if ( nRet == ENOENT )
813 DestFileExists=0;
815 /* return oslTranslateFileError(nRet);*/
818 /* mfe: the destination file must not be a directory! */
819 if ( nRet == 0 && S_ISDIR(aFileStat.st_mode) )
821 return osl_File_E_ISDIR;
823 else
825 /* mfe: file does not exists or is no dir */
828 tErr = oslDoCopy(pszPath,pszDestPath,nMode,nSourceSize,DestFileExists);
830 if ( tErr != osl_File_E_None )
832 return tErr;
836 * mfe: ignore return code
837 * since only the success of the copy is
838 * important
840 oslChangeFileModes(pszDestPath,nMode,nAcTime,nModTime,nUID,nGID);
842 return tErr;
846 /******************************************************************************
848 * Utility Functions
850 *****************************************************************************/
852 /*****************************************
853 * oslDoCopy
854 ****************************************/
856 #define TMP_DEST_FILE_EXTENSION ".osl-tmp"
858 static oslFileError oslDoCopy(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, mode_t nMode, size_t nSourceSize, int DestFileExists)
860 int nRet=0;
861 sal_Char pszTmpDestFile[PATH_MAX];
862 size_t size_tmp_dest_buff = sizeof(pszTmpDestFile);
864 /* Quick fix for #106048, the whole copy file function seems
865 to be erroneous anyway and needs to be rewritten.
866 Besides osl_copyFile is currently not used from OO/SO code.
868 memset(pszTmpDestFile, 0, size_tmp_dest_buff);
870 if ( DestFileExists )
872 strncpy(pszTmpDestFile, pszDestFileName, size_tmp_dest_buff - 1);
874 if ((strlen(pszTmpDestFile) + strlen(TMP_DEST_FILE_EXTENSION)) >= size_tmp_dest_buff)
875 return osl_File_E_NAMETOOLONG;
877 strncat(pszTmpDestFile, TMP_DEST_FILE_EXTENSION, strlen(TMP_DEST_FILE_EXTENSION));
879 /* FIXME: what if pszTmpDestFile already exists? */
880 /* with getcanonical??? */
881 nRet=rename(pszDestFileName,pszTmpDestFile);
884 /* mfe: should be S_ISREG */
885 if ( !S_ISLNK(nMode) )
887 /* copy SourceFile to DestFile */
888 nRet = oslDoCopyFile(pszSourceFileName,pszDestFileName,nSourceSize, nMode);
890 /* mfe: OK redundant at the moment */
891 else if ( S_ISLNK(nMode) )
893 nRet = oslDoCopyLink(pszSourceFileName,pszDestFileName);
895 else
897 /* mfe: what to do here? */
898 nRet=ENOSYS;
901 if ( nRet > 0 && DestFileExists == 1 )
903 unlink(pszDestFileName);
904 rename(pszTmpDestFile,pszDestFileName);
907 if ( nRet > 0 )
909 return oslTranslateFileError(OSL_FET_ERROR, nRet);
912 if ( DestFileExists == 1 )
914 unlink(pszTmpDestFile);
917 return osl_File_E_None;
920 /*****************************************
921 * oslChangeFileModes
922 ****************************************/
924 static oslFileError oslChangeFileModes( const sal_Char* pszFileName, mode_t nMode, time_t nAcTime, time_t nModTime, uid_t nUID, gid_t nGID)
926 int nRet=0;
927 struct utimbuf aTimeBuffer;
929 nRet = chmod(pszFileName,nMode);
930 if ( nRet < 0 )
932 nRet=errno;
933 return oslTranslateFileError(OSL_FET_ERROR, nRet);
936 aTimeBuffer.actime=nAcTime;
937 aTimeBuffer.modtime=nModTime;
938 nRet=utime(pszFileName,&aTimeBuffer);
939 if ( nRet < 0 )
941 nRet=errno;
942 return oslTranslateFileError(OSL_FET_ERROR, nRet);
945 if ( nUID != getuid() )
947 nUID=getuid();
950 nRet=chown(pszFileName,nUID,nGID);
951 if ( nRet < 0 )
953 nRet=errno;
955 /* mfe: do not return an error here! */
956 /* return oslTranslateFileError(nRet);*/
959 return osl_File_E_None;
962 /*****************************************
963 * oslDoCopyLink
964 ****************************************/
966 static int oslDoCopyLink(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName)
968 int nRet=0;
970 /* mfe: if dest file is symbolic link remove the link and place the file instead (hro says so) */
971 /* mfe: if source is a link copy the link and not the file it points to (hro says so) */
972 sal_Char pszLinkContent[PATH_MAX];
974 pszLinkContent[0] = '\0';
976 nRet = readlink(pszSourceFileName,pszLinkContent,PATH_MAX);
978 if ( nRet < 0 )
980 nRet=errno;
981 return nRet;
983 else
984 pszLinkContent[ nRet ] = 0;
986 nRet = symlink(pszLinkContent,pszDestFileName);
988 if ( nRet < 0 )
990 nRet=errno;
991 return nRet;
994 return 0;
997 /*****************************************
998 * oslDoCopyFile
999 ****************************************/
1001 static int oslDoCopyFile(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, size_t nSourceSize, mode_t mode)
1003 int SourceFileFD=0;
1004 int DestFileFD=0;
1005 int nRet=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 size_t nWritten = 0;
1024 size_t nRemains = nSourceSize;
1026 if ( nRemains )
1028 /* mmap has problems, try the direct streaming */
1029 char pBuffer[0x8000];
1030 size_t nRead = 0;
1032 nRemains = nSourceSize;
1036 nRead = 0;
1037 nWritten = 0;
1039 size_t nToRead = std::min( (size_t)0x8000, nRemains );
1040 nRead = read( SourceFileFD, pBuffer, nToRead );
1041 if ( (size_t)-1 != nRead )
1042 nWritten = write( DestFileFD, pBuffer, nRead );
1044 if ( (size_t)-1 != nWritten )
1045 nRemains -= nWritten;
1047 while( nRemains && (size_t)-1 != nRead && nRead == nWritten );
1050 if ( nRemains )
1052 if ( errno )
1053 nRet = errno;
1054 else
1055 nRet = ENOSPC;
1058 close( SourceFileFD );
1059 if ( close( DestFileFD ) == -1 && nRet == 0 )
1060 nRet = errno;
1062 return nRet;