LCOV - code coverage report
Current view: top level - sal/osl/unx - file_misc.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 268 347 77.2 %
Date: 2014-04-11 Functions: 30 33 90.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : #include "osl/file.hxx"
      21             : #include "osl/detail/file.h"
      22             : 
      23             : #include "osl/diagnose.h"
      24             : #include "osl/thread.h"
      25             : #include <osl/signal.h>
      26             : #include "rtl/alloc.h"
      27             : 
      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"
      35             : 
      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>
      45             : 
      46             : #include <algorithm>
      47             : 
      48             : #ifdef ANDROID
      49             : #include <osl/detail/android-bootstrap.h>
      50             : #endif
      51             : 
      52             : /************************************************************************
      53             :  *   TODO
      54             :  *
      55             :  *   - Fix: check for corresponding struct sizes in exported functions
      56             :  *   - check size/use of oslDirectory
      57             :  *   - check size/use of oslDirectoryItem
      58             :  ***********************************************************************/
      59             : 
      60             : typedef struct
      61             : {
      62             :     rtl_uString* ustrPath;           /* holds native directory path */
      63             :     DIR*         pDirStruct;
      64             : #ifdef ANDROID
      65             :     enum Kind
      66             :     {
      67             :         KIND_DIRENT = 1,
      68             :         KIND_ASSETS = 2
      69             :     };
      70             :     int eKind;
      71             :     lo_apk_dir*  pApkDirStruct;
      72             : #endif
      73             : } oslDirectoryImpl;
      74             : 
      75       94392 : DirectoryItem_Impl::DirectoryItem_Impl(
      76             :     rtl_uString * ustrFilePath, unsigned char DType)
      77             :     : m_RefCount     (1),
      78             :       m_ustrFilePath (ustrFilePath),
      79       94392 :       m_DType        (DType)
      80             : {
      81       94392 :     if (m_ustrFilePath != 0)
      82       94392 :         rtl_uString_acquire(m_ustrFilePath);
      83       94392 : }
      84       94392 : DirectoryItem_Impl::~DirectoryItem_Impl()
      85             : {
      86       94392 :     if (m_ustrFilePath != 0)
      87       94392 :         rtl_uString_release(m_ustrFilePath);
      88       94392 : }
      89             : 
      90       94392 : void * DirectoryItem_Impl::operator new(size_t n)
      91             : {
      92       94392 :     return rtl_allocateMemory(n);
      93             : }
      94       94392 : void DirectoryItem_Impl::operator delete(void * p)
      95             : {
      96       94392 :     rtl_freeMemory(p);
      97       94392 : }
      98             : 
      99           0 : void DirectoryItem_Impl::acquire()
     100             : {
     101           0 :     ++m_RefCount;
     102           0 : }
     103       94392 : void DirectoryItem_Impl::release()
     104             : {
     105       94392 :     if (0 == --m_RefCount)
     106       94392 :         delete this;
     107       94392 : }
     108             : 
     109      102076 : oslFileType DirectoryItem_Impl::getFileType() const
     110             : {
     111      102076 :     switch (m_DType)
     112             :     {
     113             : #ifdef _DIRENT_HAVE_D_TYPE
     114             :         case DT_LNK:
     115         536 :             return osl_File_Type_Link;
     116             :         case DT_DIR:
     117        2866 :             return osl_File_Type_Directory;
     118             :         case DT_REG:
     119       30347 :             return osl_File_Type_Regular;
     120             :         case DT_FIFO:
     121           0 :             return osl_File_Type_Fifo;
     122             :         case DT_SOCK:
     123           0 :             return osl_File_Type_Socket;
     124             :         case DT_CHR:
     125             :         case DT_BLK:
     126           0 :             return osl_File_Type_Special;
     127             : #endif /* _DIRENT_HAVE_D_TYPE */
     128             :         default:
     129       68327 :             break;
     130             :     }
     131       68327 :     return osl_File_Type_Unknown;
     132             : }
     133             : 
     134             : static oslFileError osl_psz_createDirectory(const sal_Char* pszPath);
     135             : static oslFileError osl_psz_removeDirectory(const sal_Char* pszPath);
     136             : 
     137       57732 : oslFileError SAL_CALL osl_openDirectory(rtl_uString* ustrDirectoryURL, oslDirectory* pDirectory)
     138             : {
     139       57732 :     rtl_uString* ustrSystemPath = NULL;
     140             :     oslFileError eRet;
     141             : 
     142             :     char path[PATH_MAX];
     143             : 
     144       57732 :     if ((0 == ustrDirectoryURL) || (0 == ustrDirectoryURL->length) || (0 == pDirectory))
     145           0 :         return osl_File_E_INVAL;
     146             : 
     147             :     /* convert file URL to system path */
     148       57732 :     eRet = osl_getSystemPathFromFileURL_Ex(ustrDirectoryURL, &ustrSystemPath);
     149             : 
     150       57732 :     if( osl_File_E_None != eRet )
     151           2 :         return eRet;
     152             : 
     153       57730 :     osl_systemPathRemoveSeparator(ustrSystemPath);
     154             : 
     155             :     /* convert unicode path to text */
     156       57730 :     if ( UnicodeToText( path, PATH_MAX, ustrSystemPath->buffer, ustrSystemPath->length )
     157             : #ifdef MACOSX
     158             :      && macxp_resolveAlias( path, PATH_MAX ) == 0
     159             : #endif /* MACOSX */
     160             :      )
     161             :     {
     162             : #ifdef ANDROID
     163             :         if( strncmp( path, "/assets/", sizeof( "/assets/" ) - 1) == 0 )
     164             :         {
     165             :             lo_apk_dir *pdir = lo_apk_opendir( path );
     166             : 
     167             :             if( pdir )
     168             :             {
     169             :                 oslDirectoryImpl* pDirImpl = (oslDirectoryImpl*) rtl_allocateMemory( sizeof(oslDirectoryImpl) );
     170             : 
     171             :                 if( pDirImpl )
     172             :                     {
     173             :                         pDirImpl->eKind = oslDirectoryImpl::KIND_ASSETS;
     174             :                         pDirImpl->pApkDirStruct = pdir;
     175             :                         pDirImpl->ustrPath = ustrSystemPath;
     176             : 
     177             :                         *pDirectory = (oslDirectory) pDirImpl;
     178             :                         return osl_File_E_None;
     179             :                     }
     180             :                 else
     181             :                     {
     182             :                         errno = ENOMEM;
     183             :                         lo_apk_closedir( pdir );
     184             :                     }
     185             :             }
     186             :         }
     187             :         else
     188             : #endif
     189             :         {
     190             :             /* open directory */
     191       57730 :             DIR *pdir = opendir( path );
     192             : 
     193       57730 :             if( pdir )
     194             :             {
     195             :                 /* create and initialize impl structure */
     196       56335 :                 oslDirectoryImpl* pDirImpl = (oslDirectoryImpl*) rtl_allocateMemory( sizeof(oslDirectoryImpl) );
     197             : 
     198       56335 :                 if( pDirImpl )
     199             :                 {
     200       56335 :                     pDirImpl->pDirStruct = pdir;
     201       56335 :                     pDirImpl->ustrPath = ustrSystemPath;
     202             : #ifdef ANDROID
     203             :                     pDirImpl->eKind = oslDirectoryImpl::KIND_DIRENT;
     204             : #endif
     205       56335 :                     *pDirectory = (oslDirectory) pDirImpl;
     206       56335 :                     return osl_File_E_None;
     207             :                 }
     208             :                 else
     209             :                 {
     210           0 :                     errno = ENOMEM;
     211           0 :                     closedir( pdir );
     212             :                 }
     213             :             }
     214             :             else
     215             :             {
     216             : #ifdef DEBUG_OSL_FILE
     217             :                 perror ("osl_openDirectory"); fprintf (stderr, path);
     218             : #endif
     219             :             }
     220             :         }
     221             :     }
     222             : 
     223        1395 :     rtl_uString_release( ustrSystemPath );
     224             : 
     225        1395 :     return oslTranslateFileError(OSL_FET_ERROR, errno);
     226             : }
     227             : 
     228       56335 : oslFileError SAL_CALL osl_closeDirectory( oslDirectory Directory )
     229             : {
     230       56335 :     oslDirectoryImpl* pDirImpl = (oslDirectoryImpl*) Directory;
     231       56335 :     oslFileError err = osl_File_E_None;
     232             : 
     233             :     OSL_ASSERT( Directory );
     234             : 
     235       56335 :     if( NULL == pDirImpl )
     236           0 :         return osl_File_E_INVAL;
     237             : 
     238             : #ifdef ANDROID
     239             :     if( pDirImpl->eKind == oslDirectoryImpl::KIND_ASSETS )
     240             :     {
     241             :         if (lo_apk_closedir( pDirImpl->pApkDirStruct ))
     242             :             err = osl_File_E_IO;
     243             :     }
     244             :     else
     245             : #endif
     246             :     {
     247       56335 :         if( closedir( pDirImpl->pDirStruct ) )
     248           0 :             err = oslTranslateFileError(OSL_FET_ERROR, errno);
     249             :     }
     250             : 
     251             :     /* cleanup members */
     252       56335 :     rtl_uString_release( pDirImpl->ustrPath );
     253             : 
     254       56335 :     rtl_freeMemory( pDirImpl );
     255             : 
     256       56335 :     return err;
     257             : }
     258             : 
     259             : /**********************************************
     260             :  * osl_readdir_impl_
     261             :  *
     262             :  * readdir wrapper, filters out "." and ".."
     263             :  * on request
     264             :  *********************************************/
     265             : 
     266       54684 : static struct dirent* osl_readdir_impl_(DIR* pdir, bool bFilterLocalAndParentDir)
     267             : {
     268             :     struct dirent* pdirent;
     269             : 
     270      168852 :     while ((pdirent = readdir(pdir)) != NULL)
     271             :     {
     272      168878 :         if (bFilterLocalAndParentDir &&
     273      139131 :             ((0 == strcmp(pdirent->d_name, ".")) || (0 == strcmp(pdirent->d_name, ".."))))
     274       59484 :             continue;
     275             :         else
     276             :             break;
     277             :     }
     278             : 
     279       54684 :     return pdirent;
     280             : }
     281             : 
     282       54685 : oslFileError SAL_CALL osl_getNextDirectoryItem(oslDirectory Directory, oslDirectoryItem* pItem, SAL_UNUSED_PARAMETER sal_uInt32 /*uHint*/)
     283             : {
     284       54685 :     oslDirectoryImpl* pDirImpl     = (oslDirectoryImpl*)Directory;
     285       54685 :     rtl_uString*      ustrFileName = NULL;
     286       54685 :     rtl_uString*      ustrFilePath = NULL;
     287             :     struct dirent*    pEntry;
     288             : 
     289             :     OSL_ASSERT(Directory);
     290             :     OSL_ASSERT(pItem);
     291             : 
     292       54685 :     if ((NULL == Directory) || (NULL == pItem))
     293           1 :         return osl_File_E_INVAL;
     294             : 
     295             : #ifdef ANDROID
     296             :     if( pDirImpl->eKind == oslDirectoryImpl::KIND_ASSETS )
     297             :     {
     298             :         pEntry = lo_apk_readdir(pDirImpl->pApkDirStruct);
     299             :     }
     300             :     else
     301             : #endif
     302             :     {
     303       54684 :         pEntry = osl_readdir_impl_(pDirImpl->pDirStruct, true);
     304             :     }
     305             : 
     306       54684 :     if (NULL == pEntry)
     307       29729 :         return osl_File_E_NOENT;
     308             : 
     309             : #if defined(MACOSX)
     310             : 
     311             :     // convert decomposed filename to precomposed unicode
     312             :     char composed_name[BUFSIZ];
     313             :     CFMutableStringRef strRef = CFStringCreateMutable (NULL, 0 );
     314             :     CFStringAppendCString( strRef, pEntry->d_name, kCFStringEncodingUTF8 );  //UTF8 is default on Mac OSX
     315             :     CFStringNormalize( strRef, kCFStringNormalizationFormC );
     316             :     CFStringGetCString( strRef, composed_name, BUFSIZ, kCFStringEncodingUTF8 );
     317             :     CFRelease( strRef );
     318             :     rtl_string2UString( &ustrFileName, composed_name, strlen( composed_name),
     319             :     osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
     320             : 
     321             : #else  // not MACOSX
     322             :     /* convert file name to unicode */
     323       24955 :     rtl_string2UString( &ustrFileName, pEntry->d_name, strlen( pEntry->d_name ),
     324       49910 :         osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
     325             :     OSL_ASSERT(ustrFileName != 0);
     326             : 
     327             : #endif
     328             : 
     329       24955 :     osl_systemPathMakeAbsolutePath(pDirImpl->ustrPath, ustrFileName, &ustrFilePath);
     330       24955 :     rtl_uString_release( ustrFileName );
     331             : 
     332       24955 :     DirectoryItem_Impl * pImpl = static_cast< DirectoryItem_Impl* >(*pItem);
     333       24955 :     if (0 != pImpl)
     334             :     {
     335           0 :         pImpl->release(), pImpl = 0;
     336             :     }
     337             : #ifdef _DIRENT_HAVE_D_TYPE
     338       24955 :     pImpl = new DirectoryItem_Impl(ustrFilePath, pEntry->d_type);
     339             : #else
     340             :     pImpl = new DirectoryItem_Impl(ustrFilePath);
     341             : #endif /* _DIRENT_HAVE_D_TYPE */
     342       24955 :     *pItem = pImpl;
     343       24955 :     rtl_uString_release( ustrFilePath );
     344             : 
     345       24955 :     return osl_File_E_None;
     346             : }
     347             : 
     348      127619 : oslFileError SAL_CALL osl_getDirectoryItem( rtl_uString* ustrFileURL, oslDirectoryItem* pItem )
     349             : {
     350      127619 :     rtl_uString* ustrSystemPath = NULL;
     351      127619 :     oslFileError osl_error      = osl_File_E_INVAL;
     352             : 
     353             :     OSL_ASSERT((0 != ustrFileURL) && (0 != pItem));
     354      127619 :     if ((0 == ustrFileURL) || (0 == ustrFileURL->length) || (0 == pItem))
     355          15 :         return osl_File_E_INVAL;
     356             : 
     357      127604 :     osl_error = osl_getSystemPathFromFileURL_Ex(ustrFileURL, &ustrSystemPath);
     358      127604 :     if (osl_File_E_None != osl_error)
     359         739 :         return osl_error;
     360             : 
     361      126865 :     osl_systemPathRemoveSeparator(ustrSystemPath);
     362             : 
     363      126865 :     if (-1 == access_u(ustrSystemPath, F_OK))
     364             :     {
     365       57428 :         osl_error = oslTranslateFileError(OSL_FET_ERROR, errno);
     366             :     }
     367             :     else
     368             :     {
     369       69437 :         *pItem = new DirectoryItem_Impl(ustrSystemPath);
     370             :     }
     371      126865 :     rtl_uString_release(ustrSystemPath);
     372             : 
     373      126865 :     return osl_error;
     374             : }
     375             : 
     376           0 : oslFileError SAL_CALL osl_acquireDirectoryItem( oslDirectoryItem Item )
     377             : {
     378           0 :     DirectoryItem_Impl * pImpl = static_cast< DirectoryItem_Impl* >(Item);
     379           0 :     if (0 == pImpl)
     380           0 :         return osl_File_E_INVAL;
     381             : 
     382           0 :     pImpl->acquire();
     383           0 :     return osl_File_E_None;
     384             : }
     385             : 
     386       94392 : oslFileError SAL_CALL osl_releaseDirectoryItem( oslDirectoryItem Item )
     387             : {
     388       94392 :     DirectoryItem_Impl * pImpl = static_cast< DirectoryItem_Impl* >(Item);
     389       94392 :     if (0 == pImpl)
     390           0 :         return osl_File_E_INVAL;
     391             : 
     392       94392 :     pImpl->release();
     393       94392 :     return osl_File_E_None;
     394             : }
     395             : 
     396        2886 : oslFileError SAL_CALL osl_createDirectory( rtl_uString* ustrDirectoryURL )
     397             : {
     398             :     char path[PATH_MAX];
     399             :     oslFileError eRet;
     400             : 
     401             :     OSL_ASSERT( ustrDirectoryURL );
     402             : 
     403             :     /* convert directory url to system path */
     404        2886 :     eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL );
     405        2886 :     if( eRet != osl_File_E_None )
     406          11 :         return eRet;
     407             : 
     408             : #ifdef MACOSX
     409             :     if ( macxp_resolveAlias( path, PATH_MAX ) != 0 )
     410             :       return oslTranslateFileError( OSL_FET_ERROR, errno );
     411             : #endif/* MACOSX */
     412             : 
     413        2875 :     return osl_psz_createDirectory( path );
     414             : }
     415             : 
     416         379 : oslFileError SAL_CALL osl_removeDirectory( rtl_uString* ustrDirectoryURL )
     417             : {
     418             :     char path[PATH_MAX];
     419             :     oslFileError eRet;
     420             : 
     421             :     OSL_ASSERT( ustrDirectoryURL );
     422             : 
     423             :     /* convert directory url to system path */
     424         379 :     eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL );
     425         379 :     if( eRet != osl_File_E_None )
     426           1 :         return eRet;
     427             : 
     428             : #ifdef MACOSX
     429             :     if ( macxp_resolveAlias( path, PATH_MAX ) != 0 )
     430             :       return oslTranslateFileError( OSL_FET_ERROR, errno );
     431             : #endif/* MACOSX */
     432             : 
     433         378 :     return osl_psz_removeDirectory( path );
     434             : }
     435             : 
     436        2875 : static oslFileError osl_psz_createDirectory( const sal_Char* pszPath )
     437             : {
     438        2875 :     int nRet=0;
     439        2875 :     int mode = S_IRWXU | S_IRWXG | S_IRWXO;
     440             : 
     441        2875 :     nRet = mkdir(pszPath,mode);
     442             : 
     443        2875 :     if ( nRet < 0 )
     444             :     {
     445         733 :         nRet=errno;
     446         733 :         return oslTranslateFileError(OSL_FET_ERROR, nRet);
     447             :     }
     448             : 
     449        2142 :     return osl_File_E_None;
     450             : }
     451             : 
     452         378 : static oslFileError osl_psz_removeDirectory( const sal_Char* pszPath )
     453             : {
     454         378 :     int nRet=0;
     455             : 
     456         378 :     nRet = rmdir(pszPath);
     457             : 
     458         378 :     if ( nRet < 0 )
     459             :     {
     460           7 :         nRet=errno;
     461           7 :         return oslTranslateFileError(OSL_FET_ERROR, nRet);
     462             :     }
     463             : 
     464         371 :     return osl_File_E_None;
     465             : }
     466             : 
     467          37 : static int path_make_parent(sal_Unicode* path)
     468             : {
     469          37 :     int i = rtl_ustr_lastIndexOfChar(path, '/');
     470             : 
     471          37 :     if (i > 0)
     472             :     {
     473          37 :         *(path + i) = 0;
     474          37 :         return i;
     475             :     }
     476             :     else
     477           0 :         return 0;
     478             : }
     479             : 
     480        1635 : static int create_dir_with_callback(
     481             :     sal_Unicode* directory_path,
     482             :     oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
     483             :     void* pData)
     484             : {
     485        1635 :     int mode = S_IRWXU | S_IRWXG | S_IRWXO;
     486             : 
     487        1635 :     if (osl::mkdir(directory_path, mode) == 0)
     488             :     {
     489         106 :         if (aDirectoryCreationCallbackFunc)
     490             :         {
     491           2 :             rtl::OUString url;
     492           2 :             osl::FileBase::getFileURLFromSystemPath(directory_path, url);
     493           2 :             aDirectoryCreationCallbackFunc(pData, url.pData);
     494             :         }
     495         106 :         return 0;
     496             :     }
     497        1529 :     return errno;
     498             : }
     499             : 
     500        1635 : static oslFileError create_dir_recursively_(
     501             :     sal_Unicode* dir_path,
     502             :     oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
     503             :     void* pData)
     504             : {
     505             :     OSL_PRECOND((rtl_ustr_getLength(dir_path) > 0) && ((dir_path + (rtl_ustr_getLength(dir_path) - 1)) != (dir_path + rtl_ustr_lastIndexOfChar(dir_path, '/'))), \
     506             :     "Path must not end with a slash");
     507             : 
     508             :     int native_err = create_dir_with_callback(
     509        1635 :         dir_path, aDirectoryCreationCallbackFunc, pData);
     510             : 
     511        1635 :     if (native_err == 0)
     512         106 :         return osl_File_E_None;
     513             : 
     514        1529 :     if (native_err != ENOENT)
     515        1492 :         return oslTranslateFileError(OSL_FET_ERROR, native_err);
     516             : 
     517             :     // we step back until '/a_dir' at maximum because
     518             :     // we should get an error unequal ENOENT when
     519             :     // we try to create 'a_dir' at '/' and would so
     520             :     // return before
     521          37 :     int pos = path_make_parent(dir_path);
     522             : 
     523             :     oslFileError osl_error = create_dir_recursively_(
     524          37 :         dir_path, aDirectoryCreationCallbackFunc, pData);
     525             : 
     526          37 :     if (osl_File_E_None != osl_error)
     527           0 :         return osl_error;
     528             : 
     529          37 :        dir_path[pos] = '/';
     530             : 
     531          37 :     return create_dir_recursively_(dir_path, aDirectoryCreationCallbackFunc, pData);
     532             : }
     533             : 
     534        1562 : oslFileError SAL_CALL osl_createDirectoryPath(
     535             :     rtl_uString* aDirectoryUrl,
     536             :     oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
     537             :     void* pData)
     538             : {
     539        1562 :     if (aDirectoryUrl == NULL)
     540           0 :         return osl_File_E_INVAL;
     541             : 
     542        1562 :     rtl::OUString sys_path;
     543        1562 :     oslFileError osl_error = osl_getSystemPathFromFileURL_Ex(aDirectoryUrl, &sys_path.pData);
     544             : 
     545        1562 :     if (osl_error != osl_File_E_None)
     546           1 :         return osl_error;
     547             : 
     548        1561 :     osl::systemPathRemoveSeparator(sys_path);
     549             : 
     550             :     // const_cast because sys_path is a local copy which we want to modify inplace instead of
     551             :     // coyp it into another buffer on the heap again
     552        1561 :     return create_dir_recursively_(sys_path.pData->buffer, aDirectoryCreationCallbackFunc, pData);
     553             : }
     554             : 
     555             : static oslFileError osl_psz_removeFile(const sal_Char* pszPath);
     556             : static oslFileError osl_psz_copyFile(const sal_Char* pszPath, const sal_Char* pszDestPath);
     557             : static oslFileError osl_psz_moveFile(const sal_Char* pszPath, const sal_Char* pszDestPath);
     558             : 
     559             : static oslFileError  oslDoCopy(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, mode_t nMode, size_t nSourceSize, int DestFileExists);
     560             : static oslFileError  oslChangeFileModes(const sal_Char* pszFileName, mode_t nMode, time_t nAcTime, time_t nModTime, uid_t nUID, gid_t nGID);
     561             : static int           oslDoCopyLink(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName);
     562             : static int           oslDoCopyFile(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, size_t nSourceSize, mode_t mode);
     563             : static oslFileError  oslDoMoveFile(const sal_Char* pszPath, const sal_Char* pszDestPath);
     564             : 
     565        1545 : oslFileError SAL_CALL osl_moveFile( rtl_uString* ustrFileURL, rtl_uString* ustrDestURL )
     566             : {
     567             :     char srcPath[PATH_MAX];
     568             :     char destPath[PATH_MAX];
     569             :     oslFileError eRet;
     570             : 
     571             :     OSL_ASSERT( ustrFileURL );
     572             :     OSL_ASSERT( ustrDestURL );
     573             : 
     574             :     /* convert source url to system path */
     575        1545 :     eRet = FileURLToPath( srcPath, PATH_MAX, ustrFileURL );
     576        1545 :     if( eRet != osl_File_E_None )
     577           0 :         return eRet;
     578             : 
     579             :     /* convert destination url to system path */
     580        1545 :     eRet = FileURLToPath( destPath, PATH_MAX, ustrDestURL );
     581        1545 :     if( eRet != osl_File_E_None )
     582           0 :         return eRet;
     583             : 
     584             : #ifdef MACOSX
     585             :     if ( macxp_resolveAlias( srcPath, PATH_MAX ) != 0 || macxp_resolveAlias( destPath, PATH_MAX ) != 0 )
     586             :       return oslTranslateFileError( OSL_FET_ERROR, errno );
     587             : #endif/* MACOSX */
     588             : 
     589        1545 :     return oslDoMoveFile( srcPath, destPath );
     590             : }
     591             : 
     592        3347 : oslFileError SAL_CALL osl_copyFile( rtl_uString* ustrFileURL, rtl_uString* ustrDestURL )
     593             : {
     594             :     char srcPath[PATH_MAX];
     595             :     char destPath[PATH_MAX];
     596             :     oslFileError eRet;
     597             : 
     598             :     OSL_ASSERT( ustrFileURL );
     599             :     OSL_ASSERT( ustrDestURL );
     600             : 
     601             :     /* convert source url to system path */
     602        3347 :     eRet = FileURLToPath( srcPath, PATH_MAX, ustrFileURL );
     603        3347 :     if( eRet != osl_File_E_None )
     604           0 :         return eRet;
     605             : 
     606             :     /* convert destination url to system path */
     607        3347 :     eRet = FileURLToPath( destPath, PATH_MAX, ustrDestURL );
     608        3347 :     if( eRet != osl_File_E_None )
     609           0 :         return eRet;
     610             : 
     611             : #ifdef MACOSX
     612             :     if ( macxp_resolveAlias( srcPath, PATH_MAX ) != 0 || macxp_resolveAlias( destPath, PATH_MAX ) != 0 )
     613             :       return oslTranslateFileError( OSL_FET_ERROR, errno );
     614             : #endif/* MACOSX */
     615             : 
     616        3347 :     return osl_psz_copyFile( srcPath, destPath );
     617             : }
     618             : 
     619       21170 : oslFileError SAL_CALL osl_removeFile( rtl_uString* ustrFileURL )
     620             : {
     621             :     char path[PATH_MAX];
     622             :     oslFileError eRet;
     623             : 
     624             :     OSL_ASSERT( ustrFileURL );
     625             : 
     626             :     /* convert file url to system path */
     627       21170 :     eRet = FileURLToPath( path, PATH_MAX, ustrFileURL );
     628       21170 :     if( eRet != osl_File_E_None )
     629           9 :         return eRet;
     630             : 
     631             : #ifdef MACOSX
     632             :     if ( macxp_resolveAlias( path, PATH_MAX ) != 0 )
     633             :       return oslTranslateFileError( OSL_FET_ERROR, errno );
     634             : #endif/* MACOSX */
     635             : 
     636       21161 :     return osl_psz_removeFile( path );
     637             : }
     638             : 
     639        1545 : static oslFileError oslDoMoveFile( const sal_Char* pszPath, const sal_Char* pszDestPath)
     640             : {
     641        1545 :     oslFileError tErr = osl_psz_moveFile(pszPath,pszDestPath);
     642        1545 :     if ( tErr == osl_File_E_None )
     643             :     {
     644        1545 :         return tErr;
     645             :     }
     646             : 
     647           0 :     if ( tErr != osl_File_E_XDEV )
     648             :     {
     649           0 :         return tErr;
     650             :     }
     651             : 
     652           0 :     tErr=osl_psz_copyFile(pszPath,pszDestPath);
     653             : 
     654           0 :     if ( tErr != osl_File_E_None )
     655             :     {
     656           0 :         osl_psz_removeFile(pszDestPath);
     657           0 :         return tErr;
     658             :     }
     659             : 
     660           0 :     tErr=osl_psz_removeFile(pszPath);
     661             : 
     662           0 :     return tErr;
     663             : }
     664             : 
     665       21161 : static oslFileError osl_psz_removeFile( const sal_Char* pszPath )
     666             : {
     667       21161 :     int nRet=0;
     668             :     struct stat aStat;
     669             : 
     670       21161 :     nRet = lstat_c(pszPath,&aStat);
     671       21161 :     if ( nRet < 0 )
     672             :     {
     673         524 :         nRet=errno;
     674         524 :         return oslTranslateFileError(OSL_FET_ERROR, nRet);
     675             :     }
     676             : 
     677       20637 :     if ( S_ISDIR(aStat.st_mode) )
     678             :     {
     679           0 :         return osl_File_E_ISDIR;
     680             :     }
     681             : 
     682       20637 :     nRet = unlink(pszPath);
     683       20637 :     if ( nRet < 0 )
     684             :     {
     685           0 :         nRet=errno;
     686           0 :         return oslTranslateFileError(OSL_FET_ERROR, nRet);
     687             :     }
     688             : 
     689       20637 :     return osl_File_E_None;
     690             : }
     691             : 
     692        1545 : static oslFileError osl_psz_moveFile(const sal_Char* pszPath, const sal_Char* pszDestPath)
     693             : {
     694        1545 :     int nRet = 0;
     695             : 
     696        1545 :     nRet = rename(pszPath,pszDestPath);
     697             : 
     698        1545 :     if ( nRet < 0 )
     699             :     {
     700           0 :         nRet=errno;
     701           0 :         return oslTranslateFileError(OSL_FET_ERROR, nRet);
     702             :     }
     703             : 
     704        1545 :     return osl_File_E_None;
     705             : }
     706             : 
     707        3347 : static oslFileError osl_psz_copyFile( const sal_Char* pszPath, const sal_Char* pszDestPath )
     708             : {
     709        3347 :     time_t nAcTime=0;
     710        3347 :     time_t nModTime=0;
     711        3347 :     uid_t nUID=0;
     712        3347 :     gid_t nGID=0;
     713        3347 :     int nRet=0;
     714        3347 :     mode_t nMode=0;
     715             :     struct stat aFileStat;
     716        3347 :     oslFileError tErr=osl_File_E_invalidError;
     717        3347 :     size_t nSourceSize=0;
     718        3347 :     int DestFileExists=1;
     719             : 
     720             :     /* mfe: does the source file really exists? */
     721        3347 :     nRet = lstat_c(pszPath,&aFileStat);
     722             : 
     723        3347 :     if ( nRet < 0 )
     724             :     {
     725           2 :         nRet=errno;
     726           2 :         return oslTranslateFileError(OSL_FET_ERROR, nRet);
     727             :     }
     728             : 
     729             :     /* mfe: we do only copy files here! */
     730        3345 :     if ( S_ISDIR(aFileStat.st_mode) )
     731             :     {
     732           0 :         return osl_File_E_ISDIR;
     733             :     }
     734             : 
     735        3345 :     nSourceSize=(size_t)aFileStat.st_size;
     736        3345 :     nMode=aFileStat.st_mode;
     737        3345 :     nAcTime=aFileStat.st_atime;
     738        3345 :     nModTime=aFileStat.st_mtime;
     739        3345 :     nUID=aFileStat.st_uid;
     740        3345 :     nGID=aFileStat.st_gid;
     741             : 
     742        3345 :     nRet = stat_c(pszDestPath,&aFileStat);
     743        3345 :     if ( nRet < 0 )
     744             :     {
     745        2950 :         nRet=errno;
     746             : 
     747        2950 :         if ( nRet == ENOENT )
     748             :         {
     749        2950 :             DestFileExists=0;
     750             :         }
     751             :     }
     752             : 
     753             :     /* mfe: the destination file must not be a directory! */
     754        3345 :     if ( nRet == 0 && S_ISDIR(aFileStat.st_mode) )
     755             :     {
     756           0 :         return osl_File_E_ISDIR;
     757             :     }
     758             :     else
     759             :     {
     760             :         /* mfe: file does not exists or is no dir */
     761             :     }
     762             : 
     763        3345 :     tErr = oslDoCopy(pszPath,pszDestPath,nMode,nSourceSize,DestFileExists);
     764             : 
     765        3345 :     if ( tErr != osl_File_E_None )
     766             :     {
     767           0 :         return tErr;
     768             :     }
     769             : 
     770             :     /*
     771             :      *   mfe: ignore return code
     772             :      *        since only  the success of the copy is
     773             :      *        important
     774             :      */
     775        3345 :     oslChangeFileModes(pszDestPath,nMode,nAcTime,nModTime,nUID,nGID);
     776             : 
     777        3345 :     return tErr;
     778             : }
     779             : 
     780             : #define TMP_DEST_FILE_EXTENSION ".osl-tmp"
     781             : 
     782        3345 : static oslFileError oslDoCopy(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, mode_t nMode, size_t nSourceSize, int DestFileExists)
     783             : {
     784        3345 :     int      nRet=0;
     785             :     sal_Char pszTmpDestFile[PATH_MAX];
     786        3345 :     size_t   size_tmp_dest_buff = sizeof(pszTmpDestFile);
     787             : 
     788             :     /* Quick fix for #106048, the whole copy file function seems
     789             :        to be erroneous anyway and needs to be rewritten.
     790             :     */
     791        3345 :     memset(pszTmpDestFile, 0, size_tmp_dest_buff);
     792             : 
     793        3345 :     if ( DestFileExists )
     794             :     {
     795         395 :         strncpy(pszTmpDestFile, pszDestFileName, size_tmp_dest_buff - 1);
     796             : 
     797         395 :         if ((strlen(pszTmpDestFile) + strlen(TMP_DEST_FILE_EXTENSION)) >= size_tmp_dest_buff)
     798           0 :             return osl_File_E_NAMETOOLONG;
     799             : 
     800         395 :         strncat(pszTmpDestFile, TMP_DEST_FILE_EXTENSION, strlen(TMP_DEST_FILE_EXTENSION));
     801             : 
     802             :         /* FIXME: what if pszTmpDestFile already exists? */
     803             :         /*        with getcanonical??? */
     804         395 :         nRet=rename(pszDestFileName,pszTmpDestFile);
     805             :     }
     806             : 
     807             :     /* mfe: should be S_ISREG */
     808        3345 :     if ( !S_ISLNK(nMode) )
     809             :     {
     810             :         /* copy SourceFile to DestFile */
     811        3345 :         nRet = oslDoCopyFile(pszSourceFileName,pszDestFileName,nSourceSize, nMode);
     812             :     }
     813             :     /* mfe: OK redundant at the moment */
     814           0 :     else if ( S_ISLNK(nMode) )
     815             :     {
     816           0 :         nRet = oslDoCopyLink(pszSourceFileName,pszDestFileName);
     817             :     }
     818             :     else
     819             :     {
     820             :         /* mfe: what to do here? */
     821           0 :         nRet=ENOSYS;
     822             :     }
     823             : 
     824        3345 :     if ( nRet > 0 && DestFileExists == 1 )
     825             :     {
     826           0 :         unlink(pszDestFileName);
     827           0 :         rename(pszTmpDestFile,pszDestFileName);
     828             :     }
     829             : 
     830        3345 :     if ( nRet > 0 )
     831             :     {
     832           0 :         return oslTranslateFileError(OSL_FET_ERROR, nRet);
     833             :     }
     834             : 
     835        3345 :     if ( DestFileExists == 1 )
     836             :     {
     837         395 :         unlink(pszTmpDestFile);
     838             :     }
     839             : 
     840        3345 :     return osl_File_E_None;
     841             : }
     842             : 
     843        3345 : static oslFileError oslChangeFileModes( const sal_Char* pszFileName, mode_t nMode, time_t nAcTime, time_t nModTime, uid_t nUID, gid_t nGID)
     844             : {
     845        3345 :     int nRet=0;
     846             :     struct utimbuf aTimeBuffer;
     847             : 
     848        3345 :     nRet = chmod(pszFileName,nMode);
     849        3345 :     if ( nRet < 0 )
     850             :     {
     851           0 :         nRet=errno;
     852           0 :         return oslTranslateFileError(OSL_FET_ERROR, nRet);
     853             :     }
     854             : 
     855        3345 :     aTimeBuffer.actime=nAcTime;
     856        3345 :     aTimeBuffer.modtime=nModTime;
     857        3345 :     nRet=utime(pszFileName,&aTimeBuffer);
     858        3345 :     if ( nRet < 0 )
     859             :     {
     860           0 :         nRet=errno;
     861           0 :         return oslTranslateFileError(OSL_FET_ERROR, nRet);
     862             :     }
     863             : 
     864        3345 :     if ( nUID != getuid() )
     865             :     {
     866           0 :         nUID=getuid();
     867             :     }
     868             : 
     869        3345 :     nRet=chown(pszFileName,nUID,nGID);
     870        3345 :     if ( nRet < 0 )
     871             :     {
     872           0 :         nRet=errno;
     873             : 
     874             :         /* mfe: do not return an error here! */
     875             :         /* return oslTranslateFileError(nRet);*/
     876             :     }
     877             : 
     878        3345 :     return osl_File_E_None;
     879             : }
     880             : 
     881           0 : static int oslDoCopyLink(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName)
     882             : {
     883           0 :     int nRet=0;
     884             : 
     885             :     /* mfe: if dest file is symbolic link remove the link and place the file instead (hro says so) */
     886             :     /* mfe: if source is a link copy the link and not the file it points to (hro says so) */
     887             :     sal_Char pszLinkContent[PATH_MAX+1];
     888             : 
     889           0 :     pszLinkContent[0] = '\0';
     890             : 
     891           0 :     nRet = readlink(pszSourceFileName,pszLinkContent,PATH_MAX);
     892             : 
     893           0 :     if ( nRet < 0 )
     894             :     {
     895           0 :         nRet=errno;
     896           0 :         return nRet;
     897             :     }
     898             :     else
     899           0 :         pszLinkContent[ nRet ] = 0;
     900             : 
     901           0 :     nRet = symlink(pszLinkContent,pszDestFileName);
     902             : 
     903           0 :     if ( nRet < 0 )
     904             :     {
     905           0 :         nRet=errno;
     906           0 :         return nRet;
     907             :     }
     908             : 
     909           0 :     return 0;
     910             : }
     911             : 
     912        3345 : static int oslDoCopyFile(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, size_t nSourceSize, mode_t mode)
     913             : {
     914        3345 :     oslFileHandle SourceFileFH=0;
     915        3345 :     int DestFileFD=0;
     916        3345 :     int nRet=0;
     917             : 
     918        3345 :     if (osl_openFilePath(pszSourceFileName,
     919             :                          &SourceFileFH,
     920        3345 :                          osl_File_OpenFlag_Read|osl_File_OpenFlag_NoLock|osl_File_OpenFlag_NoExcl) != osl_File_E_None)
     921             :     {
     922             :         // Let's hope errno is still set relevantly after osl_openFilePath...
     923           0 :         nRet=errno;
     924           0 :         return nRet;
     925             :     }
     926             : 
     927        3345 :     DestFileFD=open(pszDestFileName, O_WRONLY | O_CREAT, mode);
     928             : 
     929        3345 :     if ( DestFileFD < 0 )
     930             :     {
     931           0 :         nRet=errno;
     932           0 :         osl_closeFile(SourceFileFH);
     933           0 :         return nRet;
     934             :     }
     935             : 
     936        3345 :     size_t nRemains = nSourceSize;
     937             : 
     938        3345 :     if ( nRemains )
     939             :     {
     940             :         /* mmap has problems, try the direct streaming */
     941             :         char pBuffer[0x7FFF];
     942             : 
     943        4947 :         do
     944             :         {
     945        4947 :             size_t nToRead = std::min( sizeof(pBuffer), nRemains );
     946             :             sal_uInt64 nRead;
     947             :             bool succeeded;
     948        4947 :             if ( osl_readFile( SourceFileFH, pBuffer, nToRead, &nRead ) != osl_File_E_None || nRead > nToRead || nRead == 0 )
     949           0 :                 break;
     950             : 
     951        4947 :             succeeded = safeWrite( DestFileFD, pBuffer, nRead );
     952        4947 :             if ( !succeeded )
     953           0 :                 break;
     954             : 
     955             :             // We know nRead <= nToRead, so it must fit in a size_t
     956        4947 :             nRemains -= (size_t) nRead;
     957             :         }
     958             :         while( nRemains );
     959             :     }
     960             : 
     961        3345 :     if ( nRemains )
     962             :     {
     963           0 :         if ( errno )
     964           0 :             nRet = errno;
     965             :         else
     966           0 :             nRet = ENOSPC;
     967             :     }
     968             : 
     969        3345 :     osl_closeFile( SourceFileFH );
     970        3345 :     if ( close( DestFileFD ) == -1 && nRet == 0 )
     971           0 :         nRet = errno;
     972             : 
     973        3345 :     return nRet;
     974             : }
     975             : 
     976             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10