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

Generated by: LCOV version 1.10