Updated core
[LibreOffice.git] / sal / osl / unx / file_misc.cxx
blobcbfc52ff315214e0b58b6c8ee1afb38d7b79e610
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "osl/file.hxx"
21 #include "osl/detail/file.h"
23 #include "osl/diagnose.h"
24 #include "osl/thread.h"
25 #include <osl/signal.h>
26 #include "rtl/alloc.h"
28 #include "system.h"
29 #include "file_impl.hxx"
30 #include "file_error_transl.h"
31 #include "file_path_helper.hxx"
32 #include "file_url.h"
33 #include "uunxapi.hxx"
34 #include "readwrite_helper.h"
36 #include <sys/types.h>
37 #include <errno.h>
38 #include <dirent.h>
39 #include <limits.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <unistd.h>
43 #include <sys/stat.h>
44 #include <sys/mman.h>
46 #include <algorithm>
48 #ifdef ANDROID
49 #include <osl/detail/android-bootstrap.h>
50 #endif
52 /************************************************************************
53 * ToDo
55 * - Fix: check for corresponding struct sizes in exported functions
56 * - check size/use of oslDirectory
57 * - check size/use of oslDirectoryItem
58 ***********************************************************************/
59 /******************************************************************************
61 * Data Type Definition
63 ******************************************************************************/
65 typedef struct
67 rtl_uString* ustrPath; /* holds native directory path */
68 DIR* pDirStruct;
69 #ifdef ANDROID
70 enum Kind
72 KIND_DIRENT = 1,
73 KIND_ASSETS = 2
75 int eKind;
76 lo_apk_dir* pApkDirStruct;
77 #endif
78 } oslDirectoryImpl;
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)
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 #ifdef ANDROID
178 if( strncmp( path, "/assets/", sizeof( "/assets/" ) - 1) == 0 )
180 lo_apk_dir *pdir = lo_apk_opendir( path );
182 if( pdir )
184 oslDirectoryImpl* pDirImpl = (oslDirectoryImpl*) rtl_allocateMemory( sizeof(oslDirectoryImpl) );
186 if( pDirImpl )
188 pDirImpl->eKind = oslDirectoryImpl::KIND_ASSETS;
189 pDirImpl->pApkDirStruct = pdir;
190 pDirImpl->ustrPath = ustrSystemPath;
192 *pDirectory = (oslDirectory) pDirImpl;
193 return osl_File_E_None;
195 else
197 errno = ENOMEM;
198 lo_apk_closedir( pdir );
202 else
203 #endif
205 /* open directory */
206 DIR *pdir = opendir( path );
208 if( pdir )
210 /* create and initialize impl structure */
211 oslDirectoryImpl* pDirImpl = (oslDirectoryImpl*) rtl_allocateMemory( sizeof(oslDirectoryImpl) );
213 if( pDirImpl )
215 pDirImpl->pDirStruct = pdir;
216 pDirImpl->ustrPath = ustrSystemPath;
217 #ifdef ANDROID
218 pDirImpl->eKind = oslDirectoryImpl::KIND_DIRENT;
219 #endif
220 *pDirectory = (oslDirectory) pDirImpl;
221 return osl_File_E_None;
223 else
225 errno = ENOMEM;
226 closedir( pdir );
229 else
231 #ifdef DEBUG_OSL_FILE
232 perror ("osl_openDirectory"); fprintf (stderr, path);
233 #endif
238 rtl_uString_release( ustrSystemPath );
240 return oslTranslateFileError(OSL_FET_ERROR, errno);
243 /****************************************************************************/
244 /* osl_closeDirectory */
245 /****************************************************************************/
247 oslFileError SAL_CALL osl_closeDirectory( oslDirectory Directory )
249 oslDirectoryImpl* pDirImpl = (oslDirectoryImpl*) Directory;
250 oslFileError err = osl_File_E_None;
252 OSL_ASSERT( Directory );
254 if( NULL == pDirImpl )
255 return osl_File_E_INVAL;
257 #ifdef ANDROID
258 if( pDirImpl->eKind == oslDirectoryImpl::KIND_ASSETS )
260 if (lo_apk_closedir( pDirImpl->pApkDirStruct ))
261 err = osl_File_E_IO;
263 else
264 #endif
266 if( closedir( pDirImpl->pDirStruct ) )
267 err = oslTranslateFileError(OSL_FET_ERROR, errno);
270 /* cleanup members */
271 rtl_uString_release( pDirImpl->ustrPath );
273 rtl_freeMemory( pDirImpl );
275 return err;
278 /**********************************************
279 * osl_readdir_impl_
281 * readdir wrapper, filters out "." and ".."
282 * on request
283 *********************************************/
285 static struct dirent* osl_readdir_impl_(DIR* pdir, sal_Bool bFilterLocalAndParentDir)
287 struct dirent* pdirent;
289 while ((pdirent = readdir(pdir)) != NULL)
291 if (bFilterLocalAndParentDir &&
292 ((0 == strcmp(pdirent->d_name, ".")) || (0 == strcmp(pdirent->d_name, ".."))))
293 continue;
294 else
295 break;
298 return pdirent;
301 /****************************************************************************
302 * osl_getNextDirectoryItem
303 ***************************************************************************/
305 oslFileError SAL_CALL osl_getNextDirectoryItem(oslDirectory Directory, oslDirectoryItem* pItem, SAL_UNUSED_PARAMETER sal_uInt32 /*uHint*/)
307 oslDirectoryImpl* pDirImpl = (oslDirectoryImpl*)Directory;
308 rtl_uString* ustrFileName = NULL;
309 rtl_uString* ustrFilePath = NULL;
310 struct dirent* pEntry;
312 OSL_ASSERT(Directory);
313 OSL_ASSERT(pItem);
315 if ((NULL == Directory) || (NULL == pItem))
316 return osl_File_E_INVAL;
318 #ifdef ANDROID
319 if( pDirImpl->eKind == oslDirectoryImpl::KIND_ASSETS )
321 pEntry = lo_apk_readdir(pDirImpl->pApkDirStruct);
323 else
324 #endif
326 pEntry = osl_readdir_impl_(pDirImpl->pDirStruct, sal_True);
329 if (NULL == pEntry)
330 return osl_File_E_NOENT;
333 #if defined(MACOSX)
335 // convert decomposed filename to precomposed unicode
336 char composed_name[BUFSIZ];
337 CFMutableStringRef strRef = CFStringCreateMutable (NULL, 0 );
338 CFStringAppendCString( strRef, pEntry->d_name, kCFStringEncodingUTF8 ); //UTF8 is default on Mac OSX
339 CFStringNormalize( strRef, kCFStringNormalizationFormC );
340 CFStringGetCString( strRef, composed_name, BUFSIZ, kCFStringEncodingUTF8 );
341 CFRelease( strRef );
342 rtl_string2UString( &ustrFileName, composed_name, strlen( composed_name),
343 osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
345 #else // not MACOSX
346 /* convert file name to unicode */
347 rtl_string2UString( &ustrFileName, pEntry->d_name, strlen( pEntry->d_name ),
348 osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
349 OSL_ASSERT(ustrFileName != 0);
351 #endif
353 osl_systemPathMakeAbsolutePath(pDirImpl->ustrPath, ustrFileName, &ustrFilePath);
354 rtl_uString_release( ustrFileName );
356 DirectoryItem_Impl * pImpl = static_cast< DirectoryItem_Impl* >(*pItem);
357 if (0 != pImpl)
359 pImpl->release(), pImpl = 0;
361 #ifdef _DIRENT_HAVE_D_TYPE
362 pImpl = new DirectoryItem_Impl(ustrFilePath, pEntry->d_type);
363 #else
364 pImpl = new DirectoryItem_Impl(ustrFilePath);
365 #endif /* _DIRENT_HAVE_D_TYPE */
366 *pItem = pImpl;
367 rtl_uString_release( ustrFilePath );
369 return osl_File_E_None;
372 /****************************************************************************/
373 /* osl_getDirectoryItem */
374 /****************************************************************************/
376 oslFileError SAL_CALL osl_getDirectoryItem( rtl_uString* ustrFileURL, oslDirectoryItem* pItem )
378 rtl_uString* ustrSystemPath = NULL;
379 oslFileError osl_error = osl_File_E_INVAL;
381 OSL_ASSERT((0 != ustrFileURL) && (0 != pItem));
382 if ((0 == ustrFileURL) || (0 == ustrFileURL->length) || (0 == pItem))
383 return osl_File_E_INVAL;
385 osl_error = osl_getSystemPathFromFileURL_Ex(ustrFileURL, &ustrSystemPath, sal_False);
386 if (osl_File_E_None != osl_error)
387 return osl_error;
389 osl_systemPathRemoveSeparator(ustrSystemPath);
391 if (-1 == access_u(ustrSystemPath, F_OK))
393 osl_error = oslTranslateFileError(OSL_FET_ERROR, errno);
395 else
397 *pItem = new DirectoryItem_Impl(ustrSystemPath);
399 rtl_uString_release(ustrSystemPath);
401 return osl_error;
405 /****************************************************************************/
406 /* osl_acquireDirectoryItem */
407 /****************************************************************************/
409 oslFileError SAL_CALL osl_acquireDirectoryItem( oslDirectoryItem Item )
411 DirectoryItem_Impl * pImpl = static_cast< DirectoryItem_Impl* >(Item);
412 if (0 == pImpl)
413 return osl_File_E_INVAL;
415 pImpl->acquire();
416 return osl_File_E_None;
419 /****************************************************************************/
420 /* osl_releaseDirectoryItem */
421 /****************************************************************************/
423 oslFileError SAL_CALL osl_releaseDirectoryItem( oslDirectoryItem Item )
425 DirectoryItem_Impl * pImpl = static_cast< DirectoryItem_Impl* >(Item);
426 if (0 == pImpl)
427 return osl_File_E_INVAL;
429 pImpl->release();
430 return osl_File_E_None;
433 /****************************************************************************/
434 /* osl_createDirectory */
435 /****************************************************************************/
437 oslFileError SAL_CALL osl_createDirectory( rtl_uString* ustrDirectoryURL )
439 char path[PATH_MAX];
440 oslFileError eRet;
442 OSL_ASSERT( ustrDirectoryURL );
444 /* convert directory url to system path */
445 eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL );
446 if( eRet != osl_File_E_None )
447 return eRet;
449 #ifdef MACOSX
450 if ( macxp_resolveAlias( path, PATH_MAX ) != 0 )
451 return oslTranslateFileError( OSL_FET_ERROR, errno );
452 #endif/* MACOSX */
454 return osl_psz_createDirectory( path );
457 /****************************************************************************/
458 /* osl_removeDirectory */
459 /****************************************************************************/
461 oslFileError SAL_CALL osl_removeDirectory( rtl_uString* ustrDirectoryURL )
463 char path[PATH_MAX];
464 oslFileError eRet;
466 OSL_ASSERT( ustrDirectoryURL );
468 /* convert directory url to system path */
469 eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL );
470 if( eRet != osl_File_E_None )
471 return eRet;
473 #ifdef MACOSX
474 if ( macxp_resolveAlias( path, PATH_MAX ) != 0 )
475 return oslTranslateFileError( OSL_FET_ERROR, errno );
476 #endif/* MACOSX */
478 return osl_psz_removeDirectory( path );
481 /*****************************************
482 * osl_psz_createDirectory
483 ****************************************/
485 static oslFileError osl_psz_createDirectory( const sal_Char* pszPath )
487 int nRet=0;
488 int mode = S_IRWXU | S_IRWXG | S_IRWXO;
490 nRet = mkdir(pszPath,mode);
492 if ( nRet < 0 )
494 nRet=errno;
495 return oslTranslateFileError(OSL_FET_ERROR, nRet);
498 return osl_File_E_None;
501 /*****************************************
502 * osl_psz_removeDirectory
503 ****************************************/
505 static oslFileError osl_psz_removeDirectory( const sal_Char* pszPath )
507 int nRet=0;
509 nRet = rmdir(pszPath);
511 if ( nRet < 0 )
513 nRet=errno;
514 return oslTranslateFileError(OSL_FET_ERROR, nRet);
517 return osl_File_E_None;
520 /****************************************************************************/
521 /* osl_createDirectoryPath */
522 /****************************************************************************/
524 static int path_make_parent(sal_Unicode* path)
526 int i = rtl_ustr_lastIndexOfChar(path, '/');
528 if (i > 0)
530 *(path + i) = 0;
531 return i;
533 else
534 return 0;
537 static int create_dir_with_callback(
538 sal_Unicode* directory_path,
539 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
540 void* pData)
542 int mode = S_IRWXU | S_IRWXG | S_IRWXO;
544 if (osl::mkdir(directory_path, mode) == 0)
546 if (aDirectoryCreationCallbackFunc)
548 rtl::OUString url;
549 osl::FileBase::getFileURLFromSystemPath(directory_path, url);
550 aDirectoryCreationCallbackFunc(pData, url.pData);
552 return 0;
554 return errno;
557 static oslFileError create_dir_recursively_(
558 sal_Unicode* dir_path,
559 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
560 void* pData)
562 OSL_PRECOND((rtl_ustr_getLength(dir_path) > 0) && ((dir_path + (rtl_ustr_getLength(dir_path) - 1)) != (dir_path + rtl_ustr_lastIndexOfChar(dir_path, '/'))), \
563 "Path must not end with a slash");
565 int native_err = create_dir_with_callback(
566 dir_path, aDirectoryCreationCallbackFunc, pData);
568 if (native_err == 0)
569 return osl_File_E_None;
571 if (native_err != ENOENT)
572 return oslTranslateFileError(OSL_FET_ERROR, native_err);
574 // we step back until '/a_dir' at maximum because
575 // we should get an error unequal ENOENT when
576 // we try to create 'a_dir' at '/' and would so
577 // return before
578 int pos = path_make_parent(dir_path);
580 oslFileError osl_error = create_dir_recursively_(
581 dir_path, aDirectoryCreationCallbackFunc, pData);
583 if (osl_File_E_None != osl_error)
584 return osl_error;
586 dir_path[pos] = '/';
588 return create_dir_recursively_(dir_path, aDirectoryCreationCallbackFunc, pData);
591 oslFileError SAL_CALL osl_createDirectoryPath(
592 rtl_uString* aDirectoryUrl,
593 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
594 void* pData)
596 if (aDirectoryUrl == NULL)
597 return osl_File_E_INVAL;
599 rtl::OUString sys_path;
600 oslFileError osl_error = osl_getSystemPathFromFileURL_Ex(
601 aDirectoryUrl, &sys_path.pData, sal_False);
603 if (osl_error != osl_File_E_None)
604 return osl_error;
606 osl::systemPathRemoveSeparator(sys_path);
608 // const_cast because sys_path is a local copy which we want to modify inplace instead of
609 // coyp it into another buffer on the heap again
610 return create_dir_recursively_(sys_path.pData->buffer, aDirectoryCreationCallbackFunc, pData);
613 /******************************************************************************
615 * C-String Function Declarations
617 *****************************************************************************/
619 static oslFileError osl_psz_removeFile(const sal_Char* pszPath);
620 static oslFileError osl_psz_copyFile(const sal_Char* pszPath, const sal_Char* pszDestPath);
621 static oslFileError osl_psz_moveFile(const sal_Char* pszPath, const sal_Char* pszDestPath);
624 /******************************************************************************
626 * Static Module Utility Function Declarations
628 *****************************************************************************/
630 static oslFileError oslDoCopy(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, mode_t nMode, size_t nSourceSize, int DestFileExists);
631 static oslFileError oslChangeFileModes(const sal_Char* pszFileName, mode_t nMode, time_t nAcTime, time_t nModTime, uid_t nUID, gid_t nGID);
632 static int oslDoCopyLink(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName);
633 static int oslDoCopyFile(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, size_t nSourceSize, mode_t mode);
634 static oslFileError oslDoMoveFile(const sal_Char* pszPath, const sal_Char* pszDestPath);
636 /****************************************************************************/
637 /* osl_moveFile */
638 /****************************************************************************/
640 oslFileError SAL_CALL osl_moveFile( rtl_uString* ustrFileURL, rtl_uString* ustrDestURL )
642 char srcPath[PATH_MAX];
643 char destPath[PATH_MAX];
644 oslFileError eRet;
646 OSL_ASSERT( ustrFileURL );
647 OSL_ASSERT( ustrDestURL );
649 /* convert source url to system path */
650 eRet = FileURLToPath( srcPath, PATH_MAX, ustrFileURL );
651 if( eRet != osl_File_E_None )
652 return eRet;
654 /* convert destination url to system path */
655 eRet = FileURLToPath( destPath, PATH_MAX, ustrDestURL );
656 if( eRet != osl_File_E_None )
657 return eRet;
659 #ifdef MACOSX
660 if ( macxp_resolveAlias( srcPath, PATH_MAX ) != 0 || macxp_resolveAlias( destPath, PATH_MAX ) != 0 )
661 return oslTranslateFileError( OSL_FET_ERROR, errno );
662 #endif/* MACOSX */
664 return oslDoMoveFile( srcPath, destPath );
667 /****************************************************************************/
668 /* osl_copyFile */
669 /****************************************************************************/
671 oslFileError SAL_CALL osl_copyFile( rtl_uString* ustrFileURL, rtl_uString* ustrDestURL )
673 char srcPath[PATH_MAX];
674 char destPath[PATH_MAX];
675 oslFileError eRet;
677 OSL_ASSERT( ustrFileURL );
678 OSL_ASSERT( ustrDestURL );
680 /* convert source url to system path */
681 eRet = FileURLToPath( srcPath, PATH_MAX, ustrFileURL );
682 if( eRet != osl_File_E_None )
683 return eRet;
685 /* convert destination url to system path */
686 eRet = FileURLToPath( destPath, PATH_MAX, ustrDestURL );
687 if( eRet != osl_File_E_None )
688 return eRet;
690 #ifdef MACOSX
691 if ( macxp_resolveAlias( srcPath, PATH_MAX ) != 0 || macxp_resolveAlias( destPath, PATH_MAX ) != 0 )
692 return oslTranslateFileError( OSL_FET_ERROR, errno );
693 #endif/* MACOSX */
695 return osl_psz_copyFile( srcPath, destPath );
698 /****************************************************************************/
699 /* osl_removeFile */
700 /****************************************************************************/
702 oslFileError SAL_CALL osl_removeFile( rtl_uString* ustrFileURL )
704 char path[PATH_MAX];
705 oslFileError eRet;
707 OSL_ASSERT( ustrFileURL );
709 /* convert file url to system path */
710 eRet = FileURLToPath( path, PATH_MAX, ustrFileURL );
711 if( eRet != osl_File_E_None )
712 return eRet;
714 #ifdef MACOSX
715 if ( macxp_resolveAlias( path, PATH_MAX ) != 0 )
716 return oslTranslateFileError( OSL_FET_ERROR, errno );
717 #endif/* MACOSX */
719 return osl_psz_removeFile( path );
722 /******************************************************************************
724 * Utility Functions
726 *****************************************************************************/
728 /*****************************************
729 * oslDoMoveFile
730 ****************************************/
732 static oslFileError oslDoMoveFile( const sal_Char* pszPath, const sal_Char* pszDestPath)
734 oslFileError tErr = osl_psz_moveFile(pszPath,pszDestPath);
735 if ( tErr == osl_File_E_None )
737 return tErr;
740 if ( tErr != osl_File_E_XDEV )
742 return tErr;
745 tErr=osl_psz_copyFile(pszPath,pszDestPath);
747 if ( tErr != osl_File_E_None )
749 osl_psz_removeFile(pszDestPath);
750 return tErr;
753 tErr=osl_psz_removeFile(pszPath);
755 return tErr;
758 /*****************************************
759 * osl_psz_removeFile
760 ****************************************/
761 static oslFileError osl_psz_removeFile( const sal_Char* pszPath )
763 int nRet=0;
764 struct stat aStat;
766 nRet = lstat_c(pszPath,&aStat);
767 if ( nRet < 0 )
769 nRet=errno;
770 return oslTranslateFileError(OSL_FET_ERROR, nRet);
773 if ( S_ISDIR(aStat.st_mode) )
775 return osl_File_E_ISDIR;
778 nRet = unlink(pszPath);
779 if ( nRet < 0 )
781 nRet=errno;
782 return oslTranslateFileError(OSL_FET_ERROR, nRet);
785 return osl_File_E_None;
788 /*****************************************
789 * osl_psz_moveFile
790 ****************************************/
792 static oslFileError osl_psz_moveFile(const sal_Char* pszPath, const sal_Char* pszDestPath)
795 int nRet = 0;
797 nRet = rename(pszPath,pszDestPath);
799 if ( nRet < 0 )
801 nRet=errno;
802 return oslTranslateFileError(OSL_FET_ERROR, nRet);
805 return osl_File_E_None;
808 /*****************************************
809 * osl_psz_copyFile
810 ****************************************/
812 static oslFileError osl_psz_copyFile( const sal_Char* pszPath, const sal_Char* pszDestPath )
814 time_t nAcTime=0;
815 time_t nModTime=0;
816 uid_t nUID=0;
817 gid_t nGID=0;
818 int nRet=0;
819 mode_t nMode=0;
820 struct stat aFileStat;
821 oslFileError tErr=osl_File_E_invalidError;
822 size_t nSourceSize=0;
823 int DestFileExists=1;
825 /* mfe: does the source file really exists? */
826 nRet = lstat_c(pszPath,&aFileStat);
828 if ( nRet < 0 )
830 nRet=errno;
831 return oslTranslateFileError(OSL_FET_ERROR, nRet);
834 /* mfe: we do only copy files here! */
835 if ( S_ISDIR(aFileStat.st_mode) )
837 return osl_File_E_ISDIR;
840 nSourceSize=(size_t)aFileStat.st_size;
841 nMode=aFileStat.st_mode;
842 nAcTime=aFileStat.st_atime;
843 nModTime=aFileStat.st_mtime;
844 nUID=aFileStat.st_uid;
845 nGID=aFileStat.st_gid;
847 nRet = stat(pszDestPath,&aFileStat);
848 if ( nRet < 0 )
850 nRet=errno;
852 if ( nRet == ENOENT )
854 DestFileExists=0;
856 /* return oslTranslateFileError(nRet);*/
859 /* mfe: the destination file must not be a directory! */
860 if ( nRet == 0 && S_ISDIR(aFileStat.st_mode) )
862 return osl_File_E_ISDIR;
864 else
866 /* mfe: file does not exists or is no dir */
869 tErr = oslDoCopy(pszPath,pszDestPath,nMode,nSourceSize,DestFileExists);
871 if ( tErr != osl_File_E_None )
873 return tErr;
877 * mfe: ignore return code
878 * since only the success of the copy is
879 * important
881 oslChangeFileModes(pszDestPath,nMode,nAcTime,nModTime,nUID,nGID);
883 return tErr;
887 /******************************************************************************
889 * Utility Functions
891 *****************************************************************************/
893 /*****************************************
894 * oslDoCopy
895 ****************************************/
897 #define TMP_DEST_FILE_EXTENSION ".osl-tmp"
899 static oslFileError oslDoCopy(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, mode_t nMode, size_t nSourceSize, int DestFileExists)
901 int nRet=0;
902 sal_Char pszTmpDestFile[PATH_MAX];
903 size_t size_tmp_dest_buff = sizeof(pszTmpDestFile);
905 /* Quick fix for #106048, the whole copy file function seems
906 to be erroneous anyway and needs to be rewritten.
908 memset(pszTmpDestFile, 0, size_tmp_dest_buff);
910 if ( DestFileExists )
912 strncpy(pszTmpDestFile, pszDestFileName, size_tmp_dest_buff - 1);
914 if ((strlen(pszTmpDestFile) + strlen(TMP_DEST_FILE_EXTENSION)) >= size_tmp_dest_buff)
915 return osl_File_E_NAMETOOLONG;
917 strncat(pszTmpDestFile, TMP_DEST_FILE_EXTENSION, strlen(TMP_DEST_FILE_EXTENSION));
919 /* FIXME: what if pszTmpDestFile already exists? */
920 /* with getcanonical??? */
921 nRet=rename(pszDestFileName,pszTmpDestFile);
924 /* mfe: should be S_ISREG */
925 if ( !S_ISLNK(nMode) )
927 /* copy SourceFile to DestFile */
928 nRet = oslDoCopyFile(pszSourceFileName,pszDestFileName,nSourceSize, nMode);
930 /* mfe: OK redundant at the moment */
931 else if ( S_ISLNK(nMode) )
933 nRet = oslDoCopyLink(pszSourceFileName,pszDestFileName);
935 else
937 /* mfe: what to do here? */
938 nRet=ENOSYS;
941 if ( nRet > 0 && DestFileExists == 1 )
943 unlink(pszDestFileName);
944 rename(pszTmpDestFile,pszDestFileName);
947 if ( nRet > 0 )
949 return oslTranslateFileError(OSL_FET_ERROR, nRet);
952 if ( DestFileExists == 1 )
954 unlink(pszTmpDestFile);
957 return osl_File_E_None;
960 /*****************************************
961 * oslChangeFileModes
962 ****************************************/
964 static oslFileError oslChangeFileModes( const sal_Char* pszFileName, mode_t nMode, time_t nAcTime, time_t nModTime, uid_t nUID, gid_t nGID)
966 int nRet=0;
967 struct utimbuf aTimeBuffer;
969 nRet = chmod(pszFileName,nMode);
970 if ( nRet < 0 )
972 nRet=errno;
973 return oslTranslateFileError(OSL_FET_ERROR, nRet);
976 aTimeBuffer.actime=nAcTime;
977 aTimeBuffer.modtime=nModTime;
978 nRet=utime(pszFileName,&aTimeBuffer);
979 if ( nRet < 0 )
981 nRet=errno;
982 return oslTranslateFileError(OSL_FET_ERROR, nRet);
985 if ( nUID != getuid() )
987 nUID=getuid();
990 nRet=chown(pszFileName,nUID,nGID);
991 if ( nRet < 0 )
993 nRet=errno;
995 /* mfe: do not return an error here! */
996 /* return oslTranslateFileError(nRet);*/
999 return osl_File_E_None;
1002 /*****************************************
1003 * oslDoCopyLink
1004 ****************************************/
1006 static int oslDoCopyLink(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName)
1008 int nRet=0;
1010 /* mfe: if dest file is symbolic link remove the link and place the file instead (hro says so) */
1011 /* mfe: if source is a link copy the link and not the file it points to (hro says so) */
1012 sal_Char pszLinkContent[PATH_MAX+1];
1014 pszLinkContent[0] = '\0';
1016 nRet = readlink(pszSourceFileName,pszLinkContent,PATH_MAX);
1018 if ( nRet < 0 )
1020 nRet=errno;
1021 return nRet;
1023 else
1024 pszLinkContent[ nRet ] = 0;
1026 nRet = symlink(pszLinkContent,pszDestFileName);
1028 if ( nRet < 0 )
1030 nRet=errno;
1031 return nRet;
1034 return 0;
1037 /*****************************************
1038 * oslDoCopyFile
1039 ****************************************/
1041 static int oslDoCopyFile(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, size_t nSourceSize, mode_t mode)
1043 oslFileHandle SourceFileFH=0;
1044 int DestFileFD=0;
1045 int nRet=0;
1047 if (osl_openFilePath(pszSourceFileName,
1048 &SourceFileFH,
1049 osl_File_OpenFlag_Read|osl_File_OpenFlag_NoLock|osl_File_OpenFlag_NoExcl) != osl_File_E_None)
1051 // Let's hope errno is still set relevantly after osl_openFilePath...
1052 nRet=errno;
1053 return nRet;
1056 DestFileFD=open(pszDestFileName, O_WRONLY | O_CREAT, mode);
1058 if ( DestFileFD < 0 )
1060 nRet=errno;
1061 osl_closeFile(SourceFileFH);
1062 return nRet;
1065 size_t nRemains = nSourceSize;
1067 if ( nRemains )
1069 /* mmap has problems, try the direct streaming */
1070 char pBuffer[0x7FFF];
1074 size_t nToRead = std::min( sizeof(pBuffer), nRemains );
1075 sal_uInt64 nRead;
1076 sal_Bool succeeded;
1077 if ( osl_readFile( SourceFileFH, pBuffer, nToRead, &nRead ) != osl_File_E_None || nRead > nToRead || nRead == 0 )
1078 break;
1080 succeeded = safeWrite( DestFileFD, pBuffer, nRead );
1081 if ( !succeeded )
1082 break;
1084 // We know nRead <= nToRead, so it must fit in a size_t
1085 nRemains -= (size_t) nRead;
1087 while( nRemains );
1090 if ( nRemains )
1092 if ( errno )
1093 nRet = errno;
1094 else
1095 nRet = ENOSPC;
1098 osl_closeFile( SourceFileFH );
1099 if ( close( DestFileFD ) == -1 && nRet == 0 )
1100 nRet = errno;
1102 return nRet;
1105 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */