Bump for 3.6-28
[LibreOffice.git] / sal / osl / unx / file_misc.cxx
blobedd4eecbead6817cb8e2b34d64a775886b7b26d6
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 ************************************************************************/
29 #include "osl/file.hxx"
30 #include "osl/detail/file.h"
32 #include "osl/diagnose.h"
33 #include "osl/thread.h"
34 #include <osl/signal.h>
35 #include "rtl/alloc.h"
37 #include "system.h"
38 #include "file_impl.hxx"
39 #include "file_error_transl.h"
40 #include "file_path_helper.hxx"
41 #include "file_url.h"
42 #include "uunxapi.hxx"
43 #include "readwrite_helper.h"
45 #include <sys/types.h>
46 #include <errno.h>
47 #include <dirent.h>
48 #include <limits.h>
49 #include <stdio.h>
50 #include <string.h>
51 #include <unistd.h>
52 #include <sys/stat.h>
53 #include <sys/mman.h>
55 #include <algorithm>
57 #ifdef ANDROID
58 #include <osl/detail/android-bootstrap.h>
59 #endif
61 /************************************************************************
62 * ToDo
64 * - Fix: check for corresponding struct sizes in exported functions
65 * - check size/use of oslDirectory
66 * - check size/use of oslDirectoryItem
67 ***********************************************************************/
68 /******************************************************************************
70 * Data Type Definition
72 ******************************************************************************/
74 typedef struct
76 rtl_uString* ustrPath; /* holds native directory path */
77 DIR* pDirStruct;
78 #ifdef ANDROID
79 enum Kind
81 KIND_DIRENT = 1,
82 KIND_ASSETS = 2
84 int eKind;
85 lo_apk_dir* pApkDirStruct;
86 #endif
87 } oslDirectoryImpl;
89 DirectoryItem_Impl::DirectoryItem_Impl(
90 rtl_uString * ustrFilePath, unsigned char DType)
91 : m_RefCount (1),
92 m_ustrFilePath (ustrFilePath),
93 m_DType (DType)
95 if (m_ustrFilePath != 0)
96 rtl_uString_acquire(m_ustrFilePath);
98 DirectoryItem_Impl::~DirectoryItem_Impl()
100 if (m_ustrFilePath != 0)
101 rtl_uString_release(m_ustrFilePath);
104 void * DirectoryItem_Impl::operator new(size_t n)
106 return rtl_allocateMemory(n);
108 void DirectoryItem_Impl::operator delete(void * p)
110 rtl_freeMemory(p);
113 void DirectoryItem_Impl::acquire()
115 ++m_RefCount;
117 void DirectoryItem_Impl::release()
119 if (0 == --m_RefCount)
120 delete this;
123 oslFileType DirectoryItem_Impl::getFileType() const
125 switch (m_DType)
127 #ifdef _DIRENT_HAVE_D_TYPE
128 case DT_LNK:
129 return osl_File_Type_Link;
130 case DT_DIR:
131 return osl_File_Type_Directory;
132 case DT_REG:
133 return osl_File_Type_Regular;
134 case DT_FIFO:
135 return osl_File_Type_Fifo;
136 case DT_SOCK:
137 return osl_File_Type_Socket;
138 case DT_CHR:
139 case DT_BLK:
140 return osl_File_Type_Special;
141 #endif /* _DIRENT_HAVE_D_TYPE */
142 default:
143 break;
145 return osl_File_Type_Unknown;
148 /******************************************************************************
150 * C-String Function Declarations
152 *****************************************************************************/
154 static oslFileError osl_psz_createDirectory(const sal_Char* pszPath);
155 static oslFileError osl_psz_removeDirectory(const sal_Char* pszPath);
157 /*******************************************************************
158 * osl_openDirectory
159 ******************************************************************/
161 oslFileError SAL_CALL osl_openDirectory(rtl_uString* ustrDirectoryURL, oslDirectory* pDirectory)
163 rtl_uString* ustrSystemPath = NULL;
164 oslFileError eRet;
166 char path[PATH_MAX];
168 if ((0 == ustrDirectoryURL) || (0 == ustrDirectoryURL->length) || (0 == pDirectory))
169 return osl_File_E_INVAL;
171 /* convert file URL to system path */
172 eRet = osl_getSystemPathFromFileURL_Ex(ustrDirectoryURL, &ustrSystemPath, sal_False);
174 if( osl_File_E_None != eRet )
175 return eRet;
177 osl_systemPathRemoveSeparator(ustrSystemPath);
179 /* convert unicode path to text */
180 if ( UnicodeToText( path, PATH_MAX, ustrSystemPath->buffer, ustrSystemPath->length )
181 #ifdef MACOSX
182 && macxp_resolveAlias( path, PATH_MAX ) == 0
183 #endif /* MACOSX */
186 #ifdef ANDROID
187 if( strncmp( path, "/assets/", sizeof( "/assets/" ) - 1) == 0 )
189 lo_apk_dir *pdir = lo_apk_opendir( path );
191 if( pdir )
193 oslDirectoryImpl* pDirImpl = (oslDirectoryImpl*) rtl_allocateMemory( sizeof(oslDirectoryImpl) );
195 if( pDirImpl )
197 pDirImpl->eKind = oslDirectoryImpl::KIND_ASSETS;
198 pDirImpl->pApkDirStruct = pdir;
199 pDirImpl->ustrPath = ustrSystemPath;
201 *pDirectory = (oslDirectory) pDirImpl;
202 return osl_File_E_None;
204 else
206 errno = ENOMEM;
207 lo_apk_closedir( pdir );
211 else
212 #endif
214 /* open directory */
215 DIR *pdir = opendir( path );
217 if( pdir )
219 /* create and initialize impl structure */
220 oslDirectoryImpl* pDirImpl = (oslDirectoryImpl*) rtl_allocateMemory( sizeof(oslDirectoryImpl) );
222 if( pDirImpl )
224 pDirImpl->pDirStruct = pdir;
225 pDirImpl->ustrPath = ustrSystemPath;
226 #ifdef ANDROID
227 pDirImpl->eKind = oslDirectoryImpl::KIND_DIRENT;
228 #endif
229 *pDirectory = (oslDirectory) pDirImpl;
230 return osl_File_E_None;
232 else
234 errno = ENOMEM;
235 closedir( pdir );
238 else
240 #ifdef DEBUG_OSL_FILE
241 perror ("osl_openDirectory"); fprintf (stderr, path);
242 #endif
247 rtl_uString_release( ustrSystemPath );
249 return oslTranslateFileError(OSL_FET_ERROR, errno);
252 /****************************************************************************/
253 /* osl_closeDirectory */
254 /****************************************************************************/
256 oslFileError SAL_CALL osl_closeDirectory( oslDirectory Directory )
258 oslDirectoryImpl* pDirImpl = (oslDirectoryImpl*) Directory;
259 oslFileError err = osl_File_E_None;
261 OSL_ASSERT( Directory );
263 if( NULL == pDirImpl )
264 return osl_File_E_INVAL;
266 #ifdef ANDROID
267 if( pDirImpl->eKind == oslDirectoryImpl::KIND_ASSETS )
269 if (lo_apk_closedir( pDirImpl->pApkDirStruct ))
270 err = osl_File_E_IO;
272 else
273 #endif
275 if( closedir( pDirImpl->pDirStruct ) )
276 err = oslTranslateFileError(OSL_FET_ERROR, errno);
279 /* cleanup members */
280 rtl_uString_release( pDirImpl->ustrPath );
282 rtl_freeMemory( pDirImpl );
284 return err;
287 /**********************************************
288 * osl_readdir_impl_
290 * readdir wrapper, filters out "." and ".."
291 * on request
292 *********************************************/
294 static struct dirent* osl_readdir_impl_(DIR* pdir, sal_Bool bFilterLocalAndParentDir)
296 struct dirent* pdirent;
298 while ((pdirent = readdir(pdir)) != NULL)
300 if (bFilterLocalAndParentDir &&
301 ((0 == strcmp(pdirent->d_name, ".")) || (0 == strcmp(pdirent->d_name, ".."))))
302 continue;
303 else
304 break;
307 return pdirent;
310 /****************************************************************************
311 * osl_getNextDirectoryItem
312 ***************************************************************************/
314 oslFileError SAL_CALL osl_getNextDirectoryItem(oslDirectory Directory, oslDirectoryItem* pItem, SAL_UNUSED_PARAMETER sal_uInt32 /*uHint*/)
316 oslDirectoryImpl* pDirImpl = (oslDirectoryImpl*)Directory;
317 rtl_uString* ustrFileName = NULL;
318 rtl_uString* ustrFilePath = NULL;
319 struct dirent* pEntry;
321 OSL_ASSERT(Directory);
322 OSL_ASSERT(pItem);
324 if ((NULL == Directory) || (NULL == pItem))
325 return osl_File_E_INVAL;
327 #ifdef ANDROID
328 if( pDirImpl->eKind == oslDirectoryImpl::KIND_ASSETS )
330 pEntry = lo_apk_readdir(pDirImpl->pApkDirStruct);
332 else
333 #endif
335 pEntry = osl_readdir_impl_(pDirImpl->pDirStruct, sal_True);
338 if (NULL == pEntry)
339 return osl_File_E_NOENT;
342 #if defined(MACOSX)
344 // convert decomposed filename to precomposed unicode
345 char composed_name[BUFSIZ];
346 CFMutableStringRef strRef = CFStringCreateMutable (NULL, 0 );
347 CFStringAppendCString( strRef, pEntry->d_name, kCFStringEncodingUTF8 ); //UTF8 is default on Mac OSX
348 CFStringNormalize( strRef, kCFStringNormalizationFormC );
349 CFStringGetCString( strRef, composed_name, BUFSIZ, kCFStringEncodingUTF8 );
350 CFRelease( strRef );
351 rtl_string2UString( &ustrFileName, composed_name, strlen( composed_name),
352 osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
354 #else // not MACOSX
355 /* convert file name to unicode */
356 rtl_string2UString( &ustrFileName, pEntry->d_name, strlen( pEntry->d_name ),
357 osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
358 OSL_ASSERT(ustrFileName != 0);
360 #endif
362 osl_systemPathMakeAbsolutePath(pDirImpl->ustrPath, ustrFileName, &ustrFilePath);
363 rtl_uString_release( ustrFileName );
365 DirectoryItem_Impl * pImpl = static_cast< DirectoryItem_Impl* >(*pItem);
366 if (0 != pImpl)
368 pImpl->release(), pImpl = 0;
370 #ifdef _DIRENT_HAVE_D_TYPE
371 pImpl = new DirectoryItem_Impl(ustrFilePath, pEntry->d_type);
372 #else
373 pImpl = new DirectoryItem_Impl(ustrFilePath);
374 #endif /* _DIRENT_HAVE_D_TYPE */
375 *pItem = pImpl;
376 rtl_uString_release( ustrFilePath );
378 return osl_File_E_None;
381 /****************************************************************************/
382 /* osl_getDirectoryItem */
383 /****************************************************************************/
385 oslFileError SAL_CALL osl_getDirectoryItem( rtl_uString* ustrFileURL, oslDirectoryItem* pItem )
387 rtl_uString* ustrSystemPath = NULL;
388 oslFileError osl_error = osl_File_E_INVAL;
390 OSL_ASSERT((0 != ustrFileURL) && (0 != pItem));
391 if ((0 == ustrFileURL) || (0 == ustrFileURL->length) || (0 == pItem))
392 return osl_File_E_INVAL;
394 osl_error = osl_getSystemPathFromFileURL_Ex(ustrFileURL, &ustrSystemPath, sal_False);
395 if (osl_File_E_None != osl_error)
396 return osl_error;
398 osl_systemPathRemoveSeparator(ustrSystemPath);
400 if (-1 == access_u(ustrSystemPath, F_OK))
402 osl_error = oslTranslateFileError(OSL_FET_ERROR, errno);
404 else
406 *pItem = new DirectoryItem_Impl(ustrSystemPath);
408 rtl_uString_release(ustrSystemPath);
410 return osl_error;
414 /****************************************************************************/
415 /* osl_acquireDirectoryItem */
416 /****************************************************************************/
418 oslFileError SAL_CALL osl_acquireDirectoryItem( oslDirectoryItem Item )
420 DirectoryItem_Impl * pImpl = static_cast< DirectoryItem_Impl* >(Item);
421 if (0 == pImpl)
422 return osl_File_E_INVAL;
424 pImpl->acquire();
425 return osl_File_E_None;
428 /****************************************************************************/
429 /* osl_releaseDirectoryItem */
430 /****************************************************************************/
432 oslFileError SAL_CALL osl_releaseDirectoryItem( oslDirectoryItem Item )
434 DirectoryItem_Impl * pImpl = static_cast< DirectoryItem_Impl* >(Item);
435 if (0 == pImpl)
436 return osl_File_E_INVAL;
438 pImpl->release();
439 return osl_File_E_None;
442 /****************************************************************************/
443 /* osl_createDirectory */
444 /****************************************************************************/
446 oslFileError SAL_CALL osl_createDirectory( rtl_uString* ustrDirectoryURL )
448 char path[PATH_MAX];
449 oslFileError eRet;
451 OSL_ASSERT( ustrDirectoryURL );
453 /* convert directory url to system path */
454 eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL );
455 if( eRet != osl_File_E_None )
456 return eRet;
458 #ifdef MACOSX
459 if ( macxp_resolveAlias( path, PATH_MAX ) != 0 )
460 return oslTranslateFileError( OSL_FET_ERROR, errno );
461 #endif/* MACOSX */
463 return osl_psz_createDirectory( path );
466 /****************************************************************************/
467 /* osl_removeDirectory */
468 /****************************************************************************/
470 oslFileError SAL_CALL osl_removeDirectory( rtl_uString* ustrDirectoryURL )
472 char path[PATH_MAX];
473 oslFileError eRet;
475 OSL_ASSERT( ustrDirectoryURL );
477 /* convert directory url to system path */
478 eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL );
479 if( eRet != osl_File_E_None )
480 return eRet;
482 #ifdef MACOSX
483 if ( macxp_resolveAlias( path, PATH_MAX ) != 0 )
484 return oslTranslateFileError( OSL_FET_ERROR, errno );
485 #endif/* MACOSX */
487 return osl_psz_removeDirectory( path );
490 /*****************************************
491 * osl_psz_createDirectory
492 ****************************************/
494 static oslFileError osl_psz_createDirectory( const sal_Char* pszPath )
496 int nRet=0;
497 int mode = S_IRWXU | S_IRWXG | S_IRWXO;
499 nRet = mkdir(pszPath,mode);
501 if ( nRet < 0 )
503 nRet=errno;
504 return oslTranslateFileError(OSL_FET_ERROR, nRet);
507 return osl_File_E_None;
510 /*****************************************
511 * osl_psz_removeDirectory
512 ****************************************/
514 static oslFileError osl_psz_removeDirectory( const sal_Char* pszPath )
516 int nRet=0;
518 nRet = rmdir(pszPath);
520 if ( nRet < 0 )
522 nRet=errno;
523 return oslTranslateFileError(OSL_FET_ERROR, nRet);
526 return osl_File_E_None;
529 /****************************************************************************/
530 /* osl_createDirectoryPath */
531 /****************************************************************************/
533 static int path_make_parent(sal_Unicode* path)
535 int i = rtl_ustr_lastIndexOfChar(path, '/');
537 if (i > 0)
539 *(path + i) = 0;
540 return i;
542 else
543 return 0;
546 static int create_dir_with_callback(
547 sal_Unicode* directory_path,
548 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
549 void* pData)
551 int mode = S_IRWXU | S_IRWXG | S_IRWXO;
553 if (osl::mkdir(directory_path, mode) == 0)
555 if (aDirectoryCreationCallbackFunc)
557 rtl::OUString url;
558 osl::FileBase::getFileURLFromSystemPath(directory_path, url);
559 aDirectoryCreationCallbackFunc(pData, url.pData);
561 return 0;
563 return errno;
566 static oslFileError create_dir_recursively_(
567 sal_Unicode* dir_path,
568 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
569 void* pData)
571 OSL_PRECOND((rtl_ustr_getLength(dir_path) > 0) && ((dir_path + (rtl_ustr_getLength(dir_path) - 1)) != (dir_path + rtl_ustr_lastIndexOfChar(dir_path, '/'))), \
572 "Path must not end with a slash");
574 int native_err = create_dir_with_callback(
575 dir_path, aDirectoryCreationCallbackFunc, pData);
577 if (native_err == 0)
578 return osl_File_E_None;
580 if (native_err != ENOENT)
581 return oslTranslateFileError(OSL_FET_ERROR, native_err);
583 // we step back until '/a_dir' at maximum because
584 // we should get an error unequal ENOENT when
585 // we try to create 'a_dir' at '/' and would so
586 // return before
587 int pos = path_make_parent(dir_path);
589 oslFileError osl_error = create_dir_recursively_(
590 dir_path, aDirectoryCreationCallbackFunc, pData);
592 if (osl_File_E_None != osl_error)
593 return osl_error;
595 dir_path[pos] = '/';
597 return create_dir_recursively_(dir_path, aDirectoryCreationCallbackFunc, pData);
600 oslFileError SAL_CALL osl_createDirectoryPath(
601 rtl_uString* aDirectoryUrl,
602 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
603 void* pData)
605 if (aDirectoryUrl == NULL)
606 return osl_File_E_INVAL;
608 rtl::OUString sys_path;
609 oslFileError osl_error = osl_getSystemPathFromFileURL_Ex(
610 aDirectoryUrl, &sys_path.pData, sal_False);
612 if (osl_error != osl_File_E_None)
613 return osl_error;
615 osl::systemPathRemoveSeparator(sys_path);
617 // const_cast because sys_path is a local copy which we want to modify inplace instead of
618 // coyp it into another buffer on the heap again
619 return create_dir_recursively_(sys_path.pData->buffer, aDirectoryCreationCallbackFunc, pData);
622 /******************************************************************************
624 * C-String Function Declarations
626 *****************************************************************************/
628 static oslFileError osl_psz_removeFile(const sal_Char* pszPath);
629 static oslFileError osl_psz_copyFile(const sal_Char* pszPath, const sal_Char* pszDestPath);
630 static oslFileError osl_psz_moveFile(const sal_Char* pszPath, const sal_Char* pszDestPath);
633 /******************************************************************************
635 * Static Module Utility Function Declarations
637 *****************************************************************************/
639 static oslFileError oslDoCopy(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, mode_t nMode, size_t nSourceSize, int DestFileExists);
640 static oslFileError oslChangeFileModes(const sal_Char* pszFileName, mode_t nMode, time_t nAcTime, time_t nModTime, uid_t nUID, gid_t nGID);
641 static int oslDoCopyLink(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName);
642 static int oslDoCopyFile(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, size_t nSourceSize, mode_t mode);
643 static oslFileError oslDoMoveFile(const sal_Char* pszPath, const sal_Char* pszDestPath);
645 /****************************************************************************/
646 /* osl_moveFile */
647 /****************************************************************************/
649 oslFileError SAL_CALL osl_moveFile( rtl_uString* ustrFileURL, rtl_uString* ustrDestURL )
651 char srcPath[PATH_MAX];
652 char destPath[PATH_MAX];
653 oslFileError eRet;
655 OSL_ASSERT( ustrFileURL );
656 OSL_ASSERT( ustrDestURL );
658 /* convert source url to system path */
659 eRet = FileURLToPath( srcPath, PATH_MAX, ustrFileURL );
660 if( eRet != osl_File_E_None )
661 return eRet;
663 /* convert destination url to system path */
664 eRet = FileURLToPath( destPath, PATH_MAX, ustrDestURL );
665 if( eRet != osl_File_E_None )
666 return eRet;
668 #ifdef MACOSX
669 if ( macxp_resolveAlias( srcPath, PATH_MAX ) != 0 || macxp_resolveAlias( destPath, PATH_MAX ) != 0 )
670 return oslTranslateFileError( OSL_FET_ERROR, errno );
671 #endif/* MACOSX */
673 return oslDoMoveFile( srcPath, destPath );
676 /****************************************************************************/
677 /* osl_copyFile */
678 /****************************************************************************/
680 oslFileError SAL_CALL osl_copyFile( rtl_uString* ustrFileURL, rtl_uString* ustrDestURL )
682 char srcPath[PATH_MAX];
683 char destPath[PATH_MAX];
684 oslFileError eRet;
686 OSL_ASSERT( ustrFileURL );
687 OSL_ASSERT( ustrDestURL );
689 /* convert source url to system path */
690 eRet = FileURLToPath( srcPath, PATH_MAX, ustrFileURL );
691 if( eRet != osl_File_E_None )
692 return eRet;
694 /* convert destination url to system path */
695 eRet = FileURLToPath( destPath, PATH_MAX, ustrDestURL );
696 if( eRet != osl_File_E_None )
697 return eRet;
699 #ifdef MACOSX
700 if ( macxp_resolveAlias( srcPath, PATH_MAX ) != 0 || macxp_resolveAlias( destPath, PATH_MAX ) != 0 )
701 return oslTranslateFileError( OSL_FET_ERROR, errno );
702 #endif/* MACOSX */
704 return osl_psz_copyFile( srcPath, destPath );
707 /****************************************************************************/
708 /* osl_removeFile */
709 /****************************************************************************/
711 oslFileError SAL_CALL osl_removeFile( rtl_uString* ustrFileURL )
713 char path[PATH_MAX];
714 oslFileError eRet;
716 OSL_ASSERT( ustrFileURL );
718 /* convert file url to system path */
719 eRet = FileURLToPath( path, PATH_MAX, ustrFileURL );
720 if( eRet != osl_File_E_None )
721 return eRet;
723 #ifdef MACOSX
724 if ( macxp_resolveAlias( path, PATH_MAX ) != 0 )
725 return oslTranslateFileError( OSL_FET_ERROR, errno );
726 #endif/* MACOSX */
728 return osl_psz_removeFile( path );
731 /******************************************************************************
733 * Utility Functions
735 *****************************************************************************/
737 /*****************************************
738 * oslDoMoveFile
739 ****************************************/
741 static oslFileError oslDoMoveFile( const sal_Char* pszPath, const sal_Char* pszDestPath)
743 oslFileError tErr=osl_File_E_invalidError;
745 tErr = osl_psz_moveFile(pszPath,pszDestPath);
746 if ( tErr == osl_File_E_None )
748 return tErr;
751 if ( tErr != osl_File_E_XDEV )
753 return tErr;
756 tErr=osl_psz_copyFile(pszPath,pszDestPath);
758 if ( tErr != osl_File_E_None )
760 osl_psz_removeFile(pszDestPath);
761 return tErr;
764 tErr=osl_psz_removeFile(pszPath);
766 return tErr;
769 /*****************************************
770 * osl_psz_removeFile
771 ****************************************/
772 static oslFileError osl_psz_removeFile( const sal_Char* pszPath )
774 int nRet=0;
775 struct stat aStat;
777 nRet = lstat_c(pszPath,&aStat);
778 if ( nRet < 0 )
780 nRet=errno;
781 return oslTranslateFileError(OSL_FET_ERROR, nRet);
784 if ( S_ISDIR(aStat.st_mode) )
786 return osl_File_E_ISDIR;
789 nRet = unlink(pszPath);
790 if ( nRet < 0 )
792 nRet=errno;
793 return oslTranslateFileError(OSL_FET_ERROR, nRet);
796 return osl_File_E_None;
799 /*****************************************
800 * osl_psz_moveFile
801 ****************************************/
803 static oslFileError osl_psz_moveFile(const sal_Char* pszPath, const sal_Char* pszDestPath)
806 int nRet = 0;
808 nRet = rename(pszPath,pszDestPath);
810 if ( nRet < 0 )
812 nRet=errno;
813 return oslTranslateFileError(OSL_FET_ERROR, nRet);
816 return osl_File_E_None;
819 /*****************************************
820 * osl_psz_copyFile
821 ****************************************/
823 static oslFileError osl_psz_copyFile( const sal_Char* pszPath, const sal_Char* pszDestPath )
825 time_t nAcTime=0;
826 time_t nModTime=0;
827 uid_t nUID=0;
828 gid_t nGID=0;
829 int nRet=0;
830 mode_t nMode=0;
831 struct stat aFileStat;
832 oslFileError tErr=osl_File_E_invalidError;
833 size_t nSourceSize=0;
834 int DestFileExists=1;
836 /* mfe: does the source file really exists? */
837 nRet = lstat_c(pszPath,&aFileStat);
839 if ( nRet < 0 )
841 nRet=errno;
842 return oslTranslateFileError(OSL_FET_ERROR, nRet);
845 /* mfe: we do only copy files here! */
846 if ( S_ISDIR(aFileStat.st_mode) )
848 return osl_File_E_ISDIR;
851 nSourceSize=(size_t)aFileStat.st_size;
852 nMode=aFileStat.st_mode;
853 nAcTime=aFileStat.st_atime;
854 nModTime=aFileStat.st_mtime;
855 nUID=aFileStat.st_uid;
856 nGID=aFileStat.st_gid;
858 nRet = stat(pszDestPath,&aFileStat);
859 if ( nRet < 0 )
861 nRet=errno;
863 if ( nRet == ENOENT )
865 DestFileExists=0;
867 /* return oslTranslateFileError(nRet);*/
870 /* mfe: the destination file must not be a directory! */
871 if ( nRet == 0 && S_ISDIR(aFileStat.st_mode) )
873 return osl_File_E_ISDIR;
875 else
877 /* mfe: file does not exists or is no dir */
880 tErr = oslDoCopy(pszPath,pszDestPath,nMode,nSourceSize,DestFileExists);
882 if ( tErr != osl_File_E_None )
884 return tErr;
888 * mfe: ignore return code
889 * since only the success of the copy is
890 * important
892 oslChangeFileModes(pszDestPath,nMode,nAcTime,nModTime,nUID,nGID);
894 return tErr;
898 /******************************************************************************
900 * Utility Functions
902 *****************************************************************************/
904 /*****************************************
905 * oslDoCopy
906 ****************************************/
908 #define TMP_DEST_FILE_EXTENSION ".osl-tmp"
910 static oslFileError oslDoCopy(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, mode_t nMode, size_t nSourceSize, int DestFileExists)
912 int nRet=0;
913 sal_Char pszTmpDestFile[PATH_MAX];
914 size_t size_tmp_dest_buff = sizeof(pszTmpDestFile);
916 /* Quick fix for #106048, the whole copy file function seems
917 to be erroneous anyway and needs to be rewritten.
919 memset(pszTmpDestFile, 0, size_tmp_dest_buff);
921 if ( DestFileExists )
923 strncpy(pszTmpDestFile, pszDestFileName, size_tmp_dest_buff - 1);
925 if ((strlen(pszTmpDestFile) + strlen(TMP_DEST_FILE_EXTENSION)) >= size_tmp_dest_buff)
926 return osl_File_E_NAMETOOLONG;
928 strncat(pszTmpDestFile, TMP_DEST_FILE_EXTENSION, strlen(TMP_DEST_FILE_EXTENSION));
930 /* FIXME: what if pszTmpDestFile already exists? */
931 /* with getcanonical??? */
932 nRet=rename(pszDestFileName,pszTmpDestFile);
935 /* mfe: should be S_ISREG */
936 if ( !S_ISLNK(nMode) )
938 /* copy SourceFile to DestFile */
939 nRet = oslDoCopyFile(pszSourceFileName,pszDestFileName,nSourceSize, nMode);
941 /* mfe: OK redundant at the moment */
942 else if ( S_ISLNK(nMode) )
944 nRet = oslDoCopyLink(pszSourceFileName,pszDestFileName);
946 else
948 /* mfe: what to do here? */
949 nRet=ENOSYS;
952 if ( nRet > 0 && DestFileExists == 1 )
954 unlink(pszDestFileName);
955 rename(pszTmpDestFile,pszDestFileName);
958 if ( nRet > 0 )
960 return oslTranslateFileError(OSL_FET_ERROR, nRet);
963 if ( DestFileExists == 1 )
965 unlink(pszTmpDestFile);
968 return osl_File_E_None;
971 /*****************************************
972 * oslChangeFileModes
973 ****************************************/
975 static oslFileError oslChangeFileModes( const sal_Char* pszFileName, mode_t nMode, time_t nAcTime, time_t nModTime, uid_t nUID, gid_t nGID)
977 int nRet=0;
978 struct utimbuf aTimeBuffer;
980 nRet = chmod(pszFileName,nMode);
981 if ( nRet < 0 )
983 nRet=errno;
984 return oslTranslateFileError(OSL_FET_ERROR, nRet);
987 aTimeBuffer.actime=nAcTime;
988 aTimeBuffer.modtime=nModTime;
989 nRet=utime(pszFileName,&aTimeBuffer);
990 if ( nRet < 0 )
992 nRet=errno;
993 return oslTranslateFileError(OSL_FET_ERROR, nRet);
996 if ( nUID != getuid() )
998 nUID=getuid();
1001 nRet=chown(pszFileName,nUID,nGID);
1002 if ( nRet < 0 )
1004 nRet=errno;
1006 /* mfe: do not return an error here! */
1007 /* return oslTranslateFileError(nRet);*/
1010 return osl_File_E_None;
1013 /*****************************************
1014 * oslDoCopyLink
1015 ****************************************/
1017 static int oslDoCopyLink(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName)
1019 int nRet=0;
1021 /* mfe: if dest file is symbolic link remove the link and place the file instead (hro says so) */
1022 /* mfe: if source is a link copy the link and not the file it points to (hro says so) */
1023 sal_Char pszLinkContent[PATH_MAX];
1025 pszLinkContent[0] = '\0';
1027 nRet = readlink(pszSourceFileName,pszLinkContent,PATH_MAX);
1029 if ( nRet < 0 )
1031 nRet=errno;
1032 return nRet;
1034 else
1035 pszLinkContent[ nRet ] = 0;
1037 nRet = symlink(pszLinkContent,pszDestFileName);
1039 if ( nRet < 0 )
1041 nRet=errno;
1042 return nRet;
1045 return 0;
1048 /*****************************************
1049 * oslDoCopyFile
1050 ****************************************/
1052 static int oslDoCopyFile(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, size_t nSourceSize, mode_t mode)
1054 oslFileHandle SourceFileFH=0;
1055 int DestFileFD=0;
1056 int nRet=0;
1058 if (osl_openFilePath(pszSourceFileName,
1059 &SourceFileFH,
1060 osl_File_OpenFlag_Read|osl_File_OpenFlag_NoLock|osl_File_OpenFlag_NoExcl) != osl_File_E_None)
1062 // Let's hope errno is still set relevantly after osl_openFilePath...
1063 nRet=errno;
1064 return nRet;
1067 DestFileFD=open(pszDestFileName, O_WRONLY | O_CREAT, mode);
1069 if ( DestFileFD < 0 )
1071 nRet=errno;
1072 osl_closeFile(SourceFileFH);
1073 return nRet;
1076 size_t nRemains = nSourceSize;
1078 if ( nRemains )
1080 /* mmap has problems, try the direct streaming */
1081 char pBuffer[0x7FFF];
1085 size_t nToRead = std::min( sizeof(pBuffer), nRemains );
1086 sal_uInt64 nRead;
1087 sal_Bool succeeded;
1088 if ( osl_readFile( SourceFileFH, pBuffer, nToRead, &nRead ) != osl_File_E_None || nRead > nToRead || nRead == 0 )
1089 break;
1091 succeeded = safeWrite( DestFileFD, pBuffer, nRead );
1092 if ( !succeeded )
1093 break;
1095 // We know nRead <= nToRead, so it must fit in a size_t
1096 nRemains -= (size_t) nRead;
1098 while( nRemains );
1101 if ( nRemains )
1103 if ( errno )
1104 nRet = errno;
1105 else
1106 nRet = ENOSPC;
1109 osl_closeFile( SourceFileFH );
1110 if ( close( DestFileFD ) == -1 && nRet == 0 )
1111 nRet = errno;
1113 return nRet;
1116 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */