LCOV - code coverage report
Current view: top level - sal/osl/unx - file_misc.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 256 350 73.1 %
Date: 2015-06-13 12:38:46 Functions: 29 34 85.3 %
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.hxx"
      30             : #include "file_impl.hxx"
      31             : #include "file_error_transl.hxx"
      32             : #include "file_path_helper.hxx"
      33             : #include "file_url.hxx"
      34             : #include "uunxapi.hxx"
      35             : #include "readwrite_helper.hxx"
      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      228990 : DirectoryItem_Impl::DirectoryItem_Impl(
      77             :     rtl_uString * ustrFilePath, unsigned char DType)
      78             :     : m_RefCount     (1),
      79             :       m_ustrFilePath (ustrFilePath),
      80      228990 :       m_DType        (DType)
      81             : {
      82      228990 :     if (m_ustrFilePath != 0)
      83      228990 :         rtl_uString_acquire(m_ustrFilePath);
      84      228990 : }
      85      228990 : DirectoryItem_Impl::~DirectoryItem_Impl()
      86             : {
      87      228990 :     if (m_ustrFilePath != 0)
      88      228990 :         rtl_uString_release(m_ustrFilePath);
      89      228990 : }
      90             : 
      91      228990 : void * DirectoryItem_Impl::operator new(size_t n)
      92             : {
      93      228990 :     return rtl_allocateMemory(n);
      94             : }
      95      228990 : void DirectoryItem_Impl::operator delete(void * p)
      96             : {
      97      228990 :     rtl_freeMemory(p);
      98      228990 : }
      99             : 
     100           0 : void DirectoryItem_Impl::acquire()
     101             : {
     102           0 :     ++m_RefCount;
     103           0 : }
     104      228990 : void DirectoryItem_Impl::release()
     105             : {
     106      228990 :     if (0 == --m_RefCount)
     107      228990 :         delete this;
     108      228990 : }
     109             : 
     110      311970 : oslFileType DirectoryItem_Impl::getFileType() const
     111             : {
     112      311970 :     switch (m_DType)
     113             :     {
     114             : #ifdef _DIRENT_HAVE_D_TYPE
     115             :         case DT_LNK:
     116           2 :             return osl_File_Type_Link;
     117             :         case DT_DIR:
     118       11155 :             return osl_File_Type_Directory;
     119             :         case DT_REG:
     120      179902 :             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      120911 :             break;
     131             :     }
     132      120911 :     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       98793 : oslFileError SAL_CALL osl_openDirectory(rtl_uString* ustrDirectoryURL, oslDirectory* pDirectory)
     140             : {
     141       98793 :     rtl_uString* ustrSystemPath = NULL;
     142             :     oslFileError eRet;
     143             : 
     144             :     char path[PATH_MAX];
     145             : 
     146       98793 :     if ((0 == ustrDirectoryURL) || (0 == ustrDirectoryURL->length) || (0 == pDirectory))
     147           0 :         return osl_File_E_INVAL;
     148             : 
     149             :     /* convert file URL to system path */
     150       98793 :     eRet = osl_getSystemPathFromFileURL_Ex(ustrDirectoryURL, &ustrSystemPath);
     151             : 
     152       98793 :     if( osl_File_E_None != eRet )
     153           2 :         return eRet;
     154             : 
     155       98791 :     osl_systemPathRemoveSeparator(ustrSystemPath);
     156             : 
     157             :     /* convert unicode path to text */
     158       98791 :     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       98791 :             DIR *pdir = opendir( path );
     194             : 
     195       98791 :             if( pdir )
     196             :             {
     197             :                 /* create and initialize impl structure */
     198       96729 :                 oslDirectoryImpl* pDirImpl = static_cast<oslDirectoryImpl*>(rtl_allocateMemory( sizeof(oslDirectoryImpl) ));
     199             : 
     200       96729 :                 if( pDirImpl )
     201             :                 {
     202       96729 :                     pDirImpl->pDirStruct = pdir;
     203       96729 :                     pDirImpl->ustrPath = ustrSystemPath;
     204             : #ifdef ANDROID
     205             :                     pDirImpl->eKind = oslDirectoryImpl::KIND_DIRENT;
     206             : #endif
     207       96729 :                     *pDirectory = static_cast<oslDirectory>(pDirImpl);
     208       96729 :                     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        2062 :     rtl_uString_release( ustrSystemPath );
     226             : 
     227        2062 :     return oslTranslateFileError(OSL_FET_ERROR, errno);
     228             : }
     229             : 
     230       96729 : oslFileError SAL_CALL osl_closeDirectory( oslDirectory Directory )
     231             : {
     232       96729 :     oslDirectoryImpl* pDirImpl = static_cast<oslDirectoryImpl*>(Directory);
     233       96729 :     oslFileError err = osl_File_E_None;
     234             : 
     235             :     OSL_ASSERT( Directory );
     236             : 
     237       96729 :     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       96729 :         if( closedir( pDirImpl->pDirStruct ) )
     250           0 :             err = oslTranslateFileError(OSL_FET_ERROR, errno);
     251             :     }
     252             : 
     253             :     /* cleanup members */
     254       96729 :     rtl_uString_release( pDirImpl->ustrPath );
     255             : 
     256       96729 :     rtl_freeMemory( pDirImpl );
     257             : 
     258       96729 :     return err;
     259             : }
     260             : 
     261             : /**********************************************
     262             :  * osl_readdir_impl_
     263             :  *
     264             :  * readdir wrapper, filters out "." and ".."
     265             :  * on request
     266             :  *********************************************/
     267             : 
     268      172118 : static struct dirent* osl_readdir_impl_(DIR* pdir, bool bFilterLocalAndParentDir)
     269             : {
     270             :     struct dirent* pdirent;
     271             : 
     272      475544 :     while ((pdirent = readdir(pdir)) != NULL)
     273             :     {
     274      475616 :         if (bFilterLocalAndParentDir &&
     275      409962 :             ((0 == strcmp(pdirent->d_name, ".")) || (0 == strcmp(pdirent->d_name, ".."))))
     276      131308 :             continue;
     277             :         else
     278             :             break;
     279             :     }
     280             : 
     281      172118 :     return pdirent;
     282             : }
     283             : 
     284      172119 : oslFileError SAL_CALL osl_getNextDirectoryItem(oslDirectory Directory, oslDirectoryItem* pItem, SAL_UNUSED_PARAMETER sal_uInt32 /*uHint*/)
     285             : {
     286      172119 :     oslDirectoryImpl* pDirImpl     = static_cast<oslDirectoryImpl*>(Directory);
     287      172119 :     rtl_uString*      ustrFileName = NULL;
     288      172119 :     rtl_uString*      ustrFilePath = NULL;
     289             :     struct dirent*    pEntry;
     290             : 
     291             :     OSL_ASSERT(Directory);
     292             :     OSL_ASSERT(pItem);
     293             : 
     294      172119 :     if ((NULL == Directory) || (NULL == pItem))
     295           1 :         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      172118 :         pEntry = osl_readdir_impl_(pDirImpl->pDirStruct, true);
     306             :     }
     307             : 
     308      172118 :     if (NULL == pEntry)
     309       65618 :         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      106500 :     rtl_string2UString( &ustrFileName, pEntry->d_name, strlen( pEntry->d_name ),
     326      213000 :         osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS );
     327             :     OSL_ASSERT(ustrFileName != 0);
     328             : 
     329             : #endif
     330             : 
     331      106500 :     osl_systemPathMakeAbsolutePath(pDirImpl->ustrPath, ustrFileName, &ustrFilePath);
     332      106500 :     rtl_uString_release( ustrFileName );
     333             : 
     334      106500 :     DirectoryItem_Impl * pImpl = static_cast< DirectoryItem_Impl* >(*pItem);
     335      106500 :     if (0 != pImpl)
     336             :     {
     337           0 :         pImpl->release(), pImpl = 0;
     338             :     }
     339             : #ifdef _DIRENT_HAVE_D_TYPE
     340      106500 :     pImpl = new DirectoryItem_Impl(ustrFilePath, pEntry->d_type);
     341             : #else
     342             :     pImpl = new DirectoryItem_Impl(ustrFilePath);
     343             : #endif /* _DIRENT_HAVE_D_TYPE */
     344      106500 :     *pItem = pImpl;
     345      106500 :     rtl_uString_release( ustrFilePath );
     346             : 
     347      106500 :     return osl_File_E_None;
     348             : }
     349             : 
     350      204244 : oslFileError SAL_CALL osl_getDirectoryItem( rtl_uString* ustrFileURL, oslDirectoryItem* pItem )
     351             : {
     352      204244 :     rtl_uString* ustrSystemPath = NULL;
     353      204244 :     oslFileError osl_error      = osl_File_E_INVAL;
     354             : 
     355             :     OSL_ASSERT((0 != ustrFileURL) && (0 != pItem));
     356      204244 :     if ((0 == ustrFileURL) || (0 == ustrFileURL->length) || (0 == pItem))
     357        7601 :         return osl_File_E_INVAL;
     358             : 
     359      196643 :     osl_error = osl_getSystemPathFromFileURL_Ex(ustrFileURL, &ustrSystemPath);
     360      196643 :     if (osl_File_E_None != osl_error)
     361        5808 :         return osl_error;
     362             : 
     363      190835 :     osl_systemPathRemoveSeparator(ustrSystemPath);
     364             : 
     365      190835 :     if (-1 == access_u(ustrSystemPath, F_OK))
     366             :     {
     367       68345 :         osl_error = oslTranslateFileError(OSL_FET_ERROR, errno);
     368             :     }
     369             :     else
     370             :     {
     371      122490 :         *pItem = new DirectoryItem_Impl(ustrSystemPath);
     372             :     }
     373      190835 :     rtl_uString_release(ustrSystemPath);
     374             : 
     375      190835 :     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      228990 : oslFileError SAL_CALL osl_releaseDirectoryItem( oslDirectoryItem Item )
     389             : {
     390      228990 :     DirectoryItem_Impl * pImpl = static_cast< DirectoryItem_Impl* >(Item);
     391      228990 :     if (0 == pImpl)
     392           0 :         return osl_File_E_INVAL;
     393             : 
     394      228990 :     pImpl->release();
     395      228990 :     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        4839 : 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        4839 :     eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL );
     414        4839 :     if( eRet != osl_File_E_None )
     415          25 :         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        4814 :     return osl_psz_createDirectory( path, flags );
     423             : }
     424             : 
     425         586 : 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         586 :     eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL );
     434         586 :     if( eRet != osl_File_E_None )
     435           1 :         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         585 :     return osl_psz_removeDirectory( path );
     443             : }
     444             : 
     445        4814 : oslFileError osl_psz_createDirectory(char const * pszPath, sal_uInt32 flags)
     446             : {
     447        4814 :     int nRet=0;
     448             :     int mode
     449        4814 :         = (((flags & osl_File_OpenFlag_Read) == 0
     450             :             ? 0
     451        4814 :             : ((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       14442 :            | ((flags & osl_File_OpenFlag_Write) == 0
     455             :               ? 0
     456        4814 :               : ((flags & osl_File_OpenFlag_Private) == 0
     457             :                  ? S_IWUSR | S_IWGRP | S_IWOTH
     458        4814 :                  : S_IWUSR)));
     459             : 
     460        4814 :     nRet = mkdir(pszPath,mode);
     461             : 
     462        4814 :     if ( nRet < 0 )
     463             :     {
     464        1354 :         nRet=errno;
     465        1354 :         return oslTranslateFileError(OSL_FET_ERROR, nRet);
     466             :     }
     467             : 
     468        3460 :     return osl_File_E_None;
     469             : }
     470             : 
     471         585 : static oslFileError osl_psz_removeDirectory( const sal_Char* pszPath )
     472             : {
     473         585 :     int nRet=0;
     474             : 
     475         585 :     nRet = rmdir(pszPath);
     476             : 
     477         585 :     if ( nRet < 0 )
     478             :     {
     479           7 :         nRet=errno;
     480           7 :         return oslTranslateFileError(OSL_FET_ERROR, nRet);
     481             :     }
     482             : 
     483         578 :     return osl_File_E_None;
     484             : }
     485             : 
     486          61 : static int path_make_parent(sal_Unicode* path)
     487             : {
     488          61 :     int i = rtl_ustr_lastIndexOfChar(path, '/');
     489             : 
     490          61 :     if (i > 0)
     491             :     {
     492          61 :         *(path + i) = 0;
     493          61 :         return i;
     494             :     }
     495             :     else
     496           0 :         return 0;
     497             : }
     498             : 
     499        1671 : static int create_dir_with_callback(
     500             :     sal_Unicode* directory_path,
     501             :     oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
     502             :     void* pData)
     503             : {
     504        1671 :     int mode = S_IRWXU | S_IRWXG | S_IRWXO;
     505             : 
     506        1671 :     if (osl::mkdir(directory_path, mode) == 0)
     507             :     {
     508         174 :         if (aDirectoryCreationCallbackFunc)
     509             :         {
     510           2 :             rtl::OUString url;
     511           2 :             osl::FileBase::getFileURLFromSystemPath(directory_path, url);
     512           2 :             aDirectoryCreationCallbackFunc(pData, url.pData);
     513             :         }
     514         174 :         return 0;
     515             :     }
     516        1497 :     return errno;
     517             : }
     518             : 
     519        1671 : 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        1671 :         dir_path, aDirectoryCreationCallbackFunc, pData);
     529             : 
     530        1671 :     if (native_err == 0)
     531         174 :         return osl_File_E_None;
     532             : 
     533        1497 :     if (native_err != ENOENT)
     534        1436 :         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          61 :     int pos = path_make_parent(dir_path);
     541             : 
     542             :     oslFileError osl_error = create_dir_recursively_(
     543          61 :         dir_path, aDirectoryCreationCallbackFunc, pData);
     544             : 
     545          61 :     if (osl_File_E_None != osl_error)
     546           0 :         return osl_error;
     547             : 
     548          61 :        dir_path[pos] = '/';
     549             : 
     550          61 :     return create_dir_recursively_(dir_path, aDirectoryCreationCallbackFunc, pData);
     551             : }
     552             : 
     553        1550 : oslFileError SAL_CALL osl_createDirectoryPath(
     554             :     rtl_uString* aDirectoryUrl,
     555             :     oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc,
     556             :     void* pData)
     557             : {
     558        1550 :     if (aDirectoryUrl == NULL)
     559           0 :         return osl_File_E_INVAL;
     560             : 
     561        1550 :     rtl::OUString sys_path;
     562        1550 :     oslFileError osl_error = osl_getSystemPathFromFileURL_Ex(aDirectoryUrl, &sys_path.pData);
     563             : 
     564        1550 :     if (osl_error != osl_File_E_None)
     565           1 :         return osl_error;
     566             : 
     567        1549 :     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        1549 :     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, bool preserveMetadata);
     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 void attemptChangeMetadata(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        1385 : 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        1385 :     eRet = FileURLToPath( srcPath, PATH_MAX, ustrFileURL );
     595        1385 :     if( eRet != osl_File_E_None )
     596           0 :         return eRet;
     597             : 
     598             :     /* convert destination url to system path */
     599        1385 :     eRet = FileURLToPath( destPath, PATH_MAX, ustrDestURL );
     600        1385 :     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        1385 :     return oslDoMoveFile( srcPath, destPath );
     609             : }
     610             : 
     611        4618 : 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        4618 :     eRet = FileURLToPath( srcPath, PATH_MAX, ustrFileURL );
     622        4618 :     if( eRet != osl_File_E_None )
     623           0 :         return eRet;
     624             : 
     625             :     /* convert destination url to system path */
     626        4618 :     eRet = FileURLToPath( destPath, PATH_MAX, ustrDestURL );
     627        4618 :     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        4618 :     return osl_psz_copyFile( srcPath, destPath, false );
     636             : }
     637             : 
     638       31690 : 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       31690 :     eRet = FileURLToPath( path, PATH_MAX, ustrFileURL );
     647       31690 :     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       31690 :     return osl_psz_removeFile( path );
     656             : }
     657             : 
     658        1385 : static oslFileError oslDoMoveFile( const sal_Char* pszPath, const sal_Char* pszDestPath)
     659             : {
     660        1385 :     oslFileError tErr = osl_psz_moveFile(pszPath,pszDestPath);
     661        1385 :     if ( tErr == osl_File_E_None )
     662             :     {
     663        1385 :         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, true);
     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       31690 : static oslFileError osl_psz_removeFile( const sal_Char* pszPath )
     685             : {
     686       31690 :     int nRet=0;
     687             :     struct stat aStat;
     688             : 
     689       31690 :     nRet = lstat_c(pszPath,&aStat);
     690       31690 :     if ( nRet < 0 )
     691             :     {
     692         555 :         nRet=errno;
     693         555 :         return oslTranslateFileError(OSL_FET_ERROR, nRet);
     694             :     }
     695             : 
     696       31135 :     if ( S_ISDIR(aStat.st_mode) )
     697             :     {
     698           0 :         return osl_File_E_ISDIR;
     699             :     }
     700             : 
     701       31135 :     nRet = unlink(pszPath);
     702       31135 :     if ( nRet < 0 )
     703             :     {
     704           0 :         nRet=errno;
     705           0 :         return oslTranslateFileError(OSL_FET_ERROR, nRet);
     706             :     }
     707             : 
     708       31135 :     return osl_File_E_None;
     709             : }
     710             : 
     711        1385 : static oslFileError osl_psz_moveFile(const sal_Char* pszPath, const sal_Char* pszDestPath)
     712             : {
     713        1385 :     int nRet = 0;
     714             : 
     715        1385 :     nRet = rename(pszPath,pszDestPath);
     716             : 
     717        1385 :     if ( nRet < 0 )
     718             :     {
     719           0 :         nRet=errno;
     720           0 :         return oslTranslateFileError(OSL_FET_ERROR, nRet);
     721             :     }
     722             : 
     723        1385 :     return osl_File_E_None;
     724             : }
     725             : 
     726        4618 : static oslFileError osl_psz_copyFile( const sal_Char* pszPath, const sal_Char* pszDestPath, bool preserveMetadata )
     727             : {
     728        4618 :     time_t nAcTime=0;
     729        4618 :     time_t nModTime=0;
     730        4618 :     uid_t nUID=0;
     731        4618 :     gid_t nGID=0;
     732        4618 :     int nRet=0;
     733        4618 :     mode_t nMode=0;
     734             :     struct stat aFileStat;
     735        4618 :     oslFileError tErr=osl_File_E_invalidError;
     736        4618 :     size_t nSourceSize=0;
     737        4618 :     int DestFileExists=1;
     738             : 
     739             :     /* mfe: does the source file really exists? */
     740        4618 :     nRet = lstat_c(pszPath,&aFileStat);
     741             : 
     742        4618 :     if ( nRet < 0 )
     743             :     {
     744           2 :         nRet=errno;
     745           2 :         return oslTranslateFileError(OSL_FET_ERROR, nRet);
     746             :     }
     747             : 
     748             :     /* mfe: we do only copy files here! */
     749        4616 :     if ( S_ISDIR(aFileStat.st_mode) )
     750             :     {
     751           0 :         return osl_File_E_ISDIR;
     752             :     }
     753             : 
     754        4616 :     nSourceSize=(size_t)aFileStat.st_size;
     755        4616 :     nMode=aFileStat.st_mode;
     756        4616 :     nAcTime=aFileStat.st_atime;
     757        4616 :     nModTime=aFileStat.st_mtime;
     758        4616 :     nUID=aFileStat.st_uid;
     759        4616 :     nGID=aFileStat.st_gid;
     760             : 
     761        4616 :     nRet = stat_c(pszDestPath,&aFileStat);
     762        4616 :     if ( nRet < 0 )
     763             :     {
     764        4255 :         nRet=errno;
     765             : 
     766        4255 :         if ( nRet == ENOENT )
     767             :         {
     768        4255 :             DestFileExists=0;
     769             :         }
     770             :     }
     771             : 
     772             :     /* mfe: the destination file must not be a directory! */
     773        4616 :     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        4616 :     tErr = oslDoCopy(pszPath,pszDestPath,nMode,nSourceSize,DestFileExists);
     783             : 
     784        4616 :     if ( tErr != osl_File_E_None )
     785             :     {
     786           0 :         return tErr;
     787             :     }
     788             : 
     789        4616 :     if (preserveMetadata)
     790             :     {
     791           0 :         attemptChangeMetadata(pszDestPath,nMode,nAcTime,nModTime,nUID,nGID);
     792             :     }
     793             : 
     794        4616 :     return tErr;
     795             : }
     796             : 
     797        4616 : static oslFileError oslDoCopy(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, mode_t nMode, size_t nSourceSize, int DestFileExists)
     798             : {
     799        4616 :     int      nRet=0;
     800             : 
     801        4616 :     rtl::OString tmpDestFile;
     802        4616 :     if ( DestFileExists )
     803             :     {
     804             :         //TODO: better pick a temp file name instead of adding .osl-tmp:
     805         361 :         tmpDestFile = rtl::OString(pszSourceFileName) + ".osl-tmp";
     806         361 :         if (rename(pszDestFileName, tmpDestFile.getStr()) != 0)
     807             :         {
     808           0 :             if (errno == ENOENT)
     809             :             {
     810           0 :                 DestFileExists = 0;
     811             :             }
     812             :             else
     813             :             {
     814           0 :                 int e = errno;
     815             :                 SAL_INFO(
     816             :                     "sal.osl",
     817             :                     "rename(" << pszDestFileName << ", " << tmpDestFile
     818             :                         << ") failed with errno " << e);
     819           0 :                 return osl_File_E_BUSY; // for want of a better error code
     820             :             }
     821             :         }
     822             :     }
     823             : 
     824             :     /* mfe: should be S_ISREG */
     825        4616 :     if ( !S_ISLNK(nMode) )
     826             :     {
     827             :         /* copy SourceFile to DestFile */
     828        4616 :         nRet = oslDoCopyFile(pszSourceFileName,pszDestFileName,nSourceSize, nMode);
     829             :     }
     830             :     /* mfe: OK redundant at the moment */
     831           0 :     else if ( S_ISLNK(nMode) )
     832             :     {
     833           0 :         nRet = oslDoCopyLink(pszSourceFileName,pszDestFileName);
     834             :     }
     835             :     else
     836             :     {
     837             :         /* mfe: what to do here? */
     838           0 :         nRet=ENOSYS;
     839             :     }
     840             : 
     841        4616 :     if ( nRet > 0 && DestFileExists == 1 )
     842             :     {
     843           0 :         unlink(pszDestFileName);
     844           0 :         if (rename(tmpDestFile.getStr(), pszDestFileName) != 0)
     845             :         {
     846           0 :             int e = errno;
     847             :             SAL_WARN(
     848             :                 "sal.osl",
     849             :                 "rename(" << tmpDestFile << ", " << pszDestFileName
     850             :                 << ") failed with errno " << e);
     851             :         }
     852             :     }
     853             : 
     854        4616 :     if ( nRet > 0 )
     855             :     {
     856           0 :         return oslTranslateFileError(OSL_FET_ERROR, nRet);
     857             :     }
     858             : 
     859        4616 :     if ( DestFileExists == 1 )
     860             :     {
     861         361 :         unlink(tmpDestFile.getStr());
     862             :     }
     863             : 
     864        4616 :     return osl_File_E_None;
     865             : }
     866             : 
     867           0 : void attemptChangeMetadata( const sal_Char* pszFileName, mode_t nMode, time_t nAcTime, time_t nModTime, uid_t nUID, gid_t nGID)
     868             : {
     869             :     struct utimbuf aTimeBuffer;
     870             : 
     871             : #if !defined AT_FDCWD
     872             :     if (!S_ISLNK(nMode) && chmod(pszFileName, nMode) < 0)
     873             : #else
     874           0 :     if ( fchmodat(AT_FDCWD, pszFileName, nMode, AT_SYMLINK_NOFOLLOW) < 0 )
     875             : #endif
     876             :     {
     877           0 :         int e = errno;
     878             :         SAL_INFO(
     879             :             "sal.osl", "chmod(" << pszFileName << ") failed with errno " << e);
     880             :     }
     881             : 
     882             :     // No way to change utime of a symlink itself:
     883           0 :     if (!S_ISLNK(nMode))
     884             :     {
     885           0 :         aTimeBuffer.actime=nAcTime;
     886           0 :         aTimeBuffer.modtime=nModTime;
     887           0 :         if ( utime(pszFileName,&aTimeBuffer) < 0 )
     888             :         {
     889           0 :             int e = errno;
     890             :             SAL_INFO(
     891             :                 "sal.osl",
     892             :                 "utime(" << pszFileName << ") failed with errno " << e);
     893             :         }
     894             :     }
     895             : 
     896           0 :     if ( nUID != getuid() )
     897             :     {
     898           0 :         nUID=getuid();
     899             :     }
     900           0 :     if ( lchown(pszFileName,nUID,nGID) < 0 )
     901             :     {
     902           0 :         int e = errno;
     903             :         SAL_INFO(
     904             :             "sal.osl", "lchown(" << pszFileName << ") failed with errno " << e);
     905             :     }
     906           0 : }
     907             : 
     908           0 : static int oslDoCopyLink(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName)
     909             : {
     910           0 :     int nRet=0;
     911             : 
     912             :     /* mfe: if dest file is symbolic link remove the link and place the file instead (hro says so) */
     913             :     /* mfe: if source is a link copy the link and not the file it points to (hro says so) */
     914             :     sal_Char pszLinkContent[PATH_MAX+1];
     915             : 
     916           0 :     pszLinkContent[0] = '\0';
     917             : 
     918           0 :     nRet = readlink(pszSourceFileName,pszLinkContent,PATH_MAX);
     919             : 
     920           0 :     if ( nRet < 0 )
     921             :     {
     922           0 :         nRet=errno;
     923           0 :         return nRet;
     924             :     }
     925             :     else
     926           0 :         pszLinkContent[ nRet ] = 0;
     927             : 
     928           0 :     nRet = symlink(pszLinkContent,pszDestFileName);
     929             : 
     930           0 :     if ( nRet < 0 )
     931             :     {
     932           0 :         nRet=errno;
     933           0 :         return nRet;
     934             :     }
     935             : 
     936           0 :     return 0;
     937             : }
     938             : 
     939        4616 : static int oslDoCopyFile(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, size_t nSourceSize, mode_t mode)
     940             : {
     941        4616 :     oslFileHandle SourceFileFH=0;
     942        4616 :     int DestFileFD=0;
     943        4616 :     int nRet=0;
     944             : 
     945        4616 :     if (openFilePath(pszSourceFileName,
     946             :                          &SourceFileFH,
     947        4616 :                          osl_File_OpenFlag_Read|osl_File_OpenFlag_NoLock|osl_File_OpenFlag_NoExcl, mode_t(-1)) != osl_File_E_None)
     948             :     {
     949             :         // Let's hope errno is still set relevantly after openFilePath...
     950           0 :         nRet=errno;
     951           0 :         return nRet;
     952             :     }
     953             : 
     954        4616 :     DestFileFD=open(pszDestFileName, O_WRONLY | O_CREAT, mode);
     955             : 
     956        4616 :     if ( DestFileFD < 0 )
     957             :     {
     958           0 :         nRet=errno;
     959           0 :         osl_closeFile(SourceFileFH);
     960           0 :         return nRet;
     961             :     }
     962             : 
     963        4616 :     size_t nRemains = nSourceSize;
     964             : 
     965        4616 :     if ( nRemains )
     966             :     {
     967             :         /* mmap has problems, try the direct streaming */
     968             :         char pBuffer[0x7FFF];
     969             : 
     970        7522 :         do
     971             :         {
     972        7522 :             size_t nToRead = std::min( sizeof(pBuffer), nRemains );
     973             :             sal_uInt64 nRead;
     974             :             bool succeeded;
     975        7522 :             if ( osl_readFile( SourceFileFH, pBuffer, nToRead, &nRead ) != osl_File_E_None || nRead > nToRead || nRead == 0 )
     976           0 :                 break;
     977             : 
     978        7522 :             succeeded = safeWrite( DestFileFD, pBuffer, nRead );
     979        7522 :             if ( !succeeded )
     980           0 :                 break;
     981             : 
     982             :             // We know nRead <= nToRead, so it must fit in a size_t
     983        7522 :             nRemains -= (size_t) nRead;
     984             :         }
     985             :         while( nRemains );
     986             :     }
     987             : 
     988        4616 :     if ( nRemains )
     989             :     {
     990           0 :         if ( errno )
     991           0 :             nRet = errno;
     992             :         else
     993           0 :             nRet = ENOSPC;
     994             :     }
     995             : 
     996        4616 :     osl_closeFile( SourceFileFH );
     997        4616 :     if ( close( DestFileFD ) == -1 && nRet == 0 )
     998           0 :         nRet = errno;
     999             : 
    1000        4616 :     return nRet;
    1001             : }
    1002             : 
    1003             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11