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

Generated by: LCOV version 1.10