LCOV - code coverage report
Current view: top level - sal/osl/unx - file_stat.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 128 188 68.1 %
Date: 2015-06-13 12:38:46 Functions: 13 17 76.5 %
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.h"
      21             : 
      22             : #include "system.hxx"
      23             : #include <sys/types.h>
      24             : #include <dirent.h>
      25             : #include <errno.h>
      26             : #include <limits.h>
      27             : #include <unistd.h>
      28             : 
      29             : #include <osl/diagnose.h>
      30             : 
      31             : #include "file_impl.hxx"
      32             : #include "file_error_transl.hxx"
      33             : #include "file_path_helper.hxx"
      34             : #include "file_url.hxx"
      35             : #include "uunxapi.hxx"
      36             : 
      37             : namespace
      38             : {
      39       83014 :     inline void set_file_type(const struct stat& file_stat, oslFileStatus* pStat)
      40             :     {
      41             :         /* links to directories state also to be a directory */
      42       83014 :        if (S_ISLNK(file_stat.st_mode))
      43           0 :            pStat->eType = osl_File_Type_Link;
      44       83014 :        else if (S_ISDIR(file_stat.st_mode))
      45       22987 :            pStat->eType = osl_File_Type_Directory;
      46       60027 :        else if (S_ISREG(file_stat.st_mode))
      47       60027 :            pStat->eType = osl_File_Type_Regular;
      48           0 :        else if (S_ISFIFO(file_stat.st_mode))
      49           0 :            pStat->eType = osl_File_Type_Fifo;
      50           0 :        else if (S_ISSOCK(file_stat.st_mode))
      51           0 :            pStat->eType = osl_File_Type_Socket;
      52           0 :        else if (S_ISCHR(file_stat.st_mode) || S_ISBLK(file_stat.st_mode))
      53           0 :            pStat->eType = osl_File_Type_Special;
      54             :        else
      55           0 :            pStat->eType = osl_File_Type_Unknown;
      56             : 
      57       83014 :        pStat->uValidFields |= osl_FileStatus_Mask_Type;
      58       83014 :     }
      59             : 
      60       83014 :     inline void set_file_access_mask(const struct stat& file_stat, oslFileStatus* pStat)
      61             :     {
      62             :         // user permissions
      63       83014 :         if (S_IRUSR & file_stat.st_mode)
      64       83014 :             pStat->uAttributes |= osl_File_Attribute_OwnRead;
      65             : 
      66       83014 :         if (S_IWUSR & file_stat.st_mode)
      67       83014 :             pStat->uAttributes |= osl_File_Attribute_OwnWrite;
      68             : 
      69       83014 :         if (S_IXUSR & file_stat.st_mode)
      70       25082 :             pStat->uAttributes |= osl_File_Attribute_OwnExe;
      71             : 
      72             :         // group permissions
      73       83014 :         if (S_IRGRP & file_stat.st_mode)
      74       63565 :             pStat->uAttributes |= osl_File_Attribute_GrpRead;
      75             : 
      76       83014 :         if (S_IWGRP & file_stat.st_mode)
      77        2703 :             pStat->uAttributes |= osl_File_Attribute_GrpWrite;
      78             : 
      79       83014 :         if (S_IXGRP & file_stat.st_mode)
      80       24916 :             pStat->uAttributes |= osl_File_Attribute_GrpExe;
      81             : 
      82             :         // others permissions
      83       83014 :         if (S_IROTH & file_stat.st_mode)
      84       63565 :             pStat->uAttributes |= osl_File_Attribute_OthRead;
      85             : 
      86       83014 :         if (S_IWOTH & file_stat.st_mode)
      87        2701 :             pStat->uAttributes |= osl_File_Attribute_OthWrite;
      88             : 
      89       83014 :         if (S_IXOTH & file_stat.st_mode)
      90       22924 :             pStat->uAttributes |= osl_File_Attribute_OthExe;
      91             : 
      92       83014 :         pStat->uValidFields |= osl_FileStatus_Mask_Attributes;
      93       83014 :     }
      94             : 
      95             :     /* This code used not to use access(...) because access follows links which
      96             :        may cause performance problems see #97133.  (That apparently references a
      97             :        no-longer accessible Hamburg-internal bug-tracking system.)
      98             :        However, contrary to what is stated above the use of access calls is
      99             :        required on network file systems not using unix semantics (AFS, see
     100             :        fdo#43095).
     101             :     */
     102       10420 :     inline void set_file_access_rights(const rtl::OUString& file_path, oslFileStatus* pStat)
     103             :     {
     104       10420 :         pStat->uValidFields |= osl_FileStatus_Mask_Attributes;
     105             : 
     106       10420 :         if (access_u(file_path.pData, W_OK) < 0)
     107           0 :             pStat->uAttributes |= osl_File_Attribute_ReadOnly;
     108             : 
     109       10420 :         if (access_u(file_path.pData, X_OK) == 0)
     110          18 :             pStat->uAttributes |= osl_File_Attribute_Executable;
     111       10420 :     }
     112             : 
     113       83014 :     inline void set_file_hidden_status(const rtl::OUString& file_path, oslFileStatus* pStat)
     114             :     {
     115       83014 :         pStat->uAttributes   = osl::systemPathIsHiddenFileOrDirectoryEntry(file_path) ? osl_File_Attribute_Hidden : 0;
     116       83014 :         pStat->uValidFields |= osl_FileStatus_Mask_Attributes;
     117       83014 :     }
     118             : 
     119             :     /* the set_file_access_rights must be called after set_file_hidden_status(...) and
     120             :        set_file_access_mask(...) because of the hack in set_file_access_rights(...) */
     121       83014 :     inline void set_file_attributes(
     122             :         const rtl::OUString& file_path, const struct stat& file_stat, const sal_uInt32 uFieldMask, oslFileStatus* pStat)
     123             :     {
     124       83014 :         set_file_hidden_status(file_path, pStat);
     125       83014 :         set_file_access_mask(file_stat, pStat);
     126             : 
     127             :         // we set the file access rights only on demand
     128             :         // because it's potentially expensive
     129       83014 :         if (uFieldMask & osl_FileStatus_Mask_Attributes)
     130       10420 :             set_file_access_rights(file_path, pStat);
     131       83014 :     }
     132             : 
     133       83014 :     inline void set_file_access_time(const struct stat& file_stat, oslFileStatus* pStat)
     134             :     {
     135       83014 :         pStat->aAccessTime.Seconds  = file_stat.st_atime;
     136       83014 :         pStat->aAccessTime.Nanosec  = 0;
     137       83014 :            pStat->uValidFields        |= osl_FileStatus_Mask_AccessTime;
     138       83014 :     }
     139             : 
     140       83014 :     inline void set_file_modify_time(const struct stat& file_stat, oslFileStatus* pStat)
     141             :     {
     142       83014 :         pStat->aModifyTime.Seconds  = file_stat.st_mtime;
     143       83014 :         pStat->aModifyTime.Nanosec  = 0;
     144       83014 :         pStat->uValidFields        |= osl_FileStatus_Mask_ModifyTime;
     145       83014 :     }
     146             : 
     147       83014 :     inline void set_file_size(const struct stat& file_stat, oslFileStatus* pStat)
     148             :     {
     149       83014 :         if (S_ISREG(file_stat.st_mode))
     150             :            {
     151       60027 :             pStat->uFileSize     = file_stat.st_size;
     152       60027 :                pStat->uValidFields |= osl_FileStatus_Mask_FileSize;
     153             :            }
     154       83014 :     }
     155             : 
     156             :     /* we only need to call stat or lstat if one of the
     157             :        following flags is set */
     158      227408 :     inline bool is_stat_call_necessary(sal_uInt32 field_mask, oslFileType file_type = osl_File_Type_Unknown)
     159             :     {
     160             :         return (
     161      545494 :                 ((field_mask & osl_FileStatus_Mask_Type) && (file_type == osl_File_Type_Unknown)) ||
     162      314942 :                 (field_mask & osl_FileStatus_Mask_Attributes) ||
     163      304522 :                 (field_mask & osl_FileStatus_Mask_CreationTime) ||
     164      304522 :                 (field_mask & osl_FileStatus_Mask_AccessTime) ||
     165      302999 :                 (field_mask & osl_FileStatus_Mask_ModifyTime) ||
     166      301416 :                 (field_mask & osl_FileStatus_Mask_FileSize) ||
     167      522648 :                 (field_mask & osl_FileStatus_Mask_LinkTargetURL) ||
     168      227408 :                 (field_mask & osl_FileStatus_Mask_Validate));
     169             :     }
     170             : 
     171           0 :     inline oslFileError set_link_target_url(const rtl::OUString& file_path, oslFileStatus* pStat)
     172             :     {
     173           0 :         rtl::OUString link_target;
     174           0 :         if (!osl::realpath(file_path, link_target))
     175           0 :             return oslTranslateFileError(OSL_FET_ERROR, errno);
     176             : 
     177           0 :         oslFileError osl_error = osl_getFileURLFromSystemPath(link_target.pData, &pStat->ustrLinkTargetURL);
     178           0 :         if (osl_error != osl_File_E_None)
     179           0 :             return osl_error;
     180             : 
     181           0 :         pStat->uValidFields |= osl_FileStatus_Mask_LinkTargetURL;
     182           0 :         return osl_File_E_None;
     183             :     }
     184             : 
     185      246392 :     inline oslFileError setup_osl_getFileStatus(
     186             :         DirectoryItem_Impl * pImpl, oslFileStatus* pStat, rtl::OUString& file_path)
     187             :     {
     188      246392 :         if ((NULL == pImpl) || (NULL == pStat))
     189       18984 :             return osl_File_E_INVAL;
     190             : 
     191      227408 :         file_path = rtl::OUString(pImpl->m_ustrFilePath);
     192             :         OSL_ASSERT(!file_path.isEmpty());
     193      227408 :         if (file_path.isEmpty())
     194           0 :             return osl_File_E_INVAL;
     195             : 
     196      227408 :         pStat->uValidFields = 0;
     197      227408 :         return osl_File_E_None;
     198             :     }
     199             : 
     200             : }
     201             : 
     202      246392 : oslFileError SAL_CALL osl_getFileStatus(oslDirectoryItem Item, oslFileStatus* pStat, sal_uInt32 uFieldMask)
     203             : {
     204      246392 :     DirectoryItem_Impl * pImpl = static_cast< DirectoryItem_Impl* >(Item);
     205             : 
     206      246392 :     rtl::OUString file_path;
     207      246392 :     oslFileError  osl_error = setup_osl_getFileStatus(pImpl, pStat, file_path);
     208      246392 :     if (osl_File_E_None != osl_error)
     209       18984 :         return osl_error;
     210             : 
     211             :     struct stat file_stat;
     212             : 
     213      227408 :     bool bStatNeeded = is_stat_call_necessary(uFieldMask, pImpl->getFileType());
     214      227408 :     if (bStatNeeded && (0 != osl::lstat(file_path, file_stat)))
     215           0 :         return oslTranslateFileError(OSL_FET_ERROR, errno);
     216             : 
     217      227408 :     if (bStatNeeded)
     218             :     {
     219             :         // we set all these attributes because it's cheap
     220       83014 :         set_file_type(file_stat, pStat);
     221       83014 :         set_file_access_time(file_stat, pStat);
     222       83014 :         set_file_modify_time(file_stat, pStat);
     223       83014 :         set_file_size(file_stat, pStat);
     224       83014 :         set_file_attributes(file_path, file_stat, uFieldMask, pStat);
     225             : 
     226             :         // file exists semantic of osl_FileStatus_Mask_Validate
     227       83014 :         if ((uFieldMask & osl_FileStatus_Mask_LinkTargetURL) && S_ISLNK(file_stat.st_mode))
     228             :         {
     229           0 :             osl_error = set_link_target_url(file_path, pStat);
     230           0 :             if (osl_error != osl_File_E_None)
     231           0 :                 return osl_error;
     232             :         }
     233             :     }
     234             : #ifdef _DIRENT_HAVE_D_TYPE
     235      144394 :     else if (uFieldMask & osl_FileStatus_Mask_Type)
     236             :     {
     237       84562 :         pStat->eType = pImpl->getFileType();
     238       84562 :         pStat->uValidFields |= osl_FileStatus_Mask_Type;
     239             :     }
     240             : #endif /* _DIRENT_HAVE_D_TYPE */
     241             : 
     242      227408 :     if (uFieldMask & osl_FileStatus_Mask_FileURL)
     243             :     {
     244      132561 :         if ((osl_error = osl_getFileURLFromSystemPath(file_path.pData, &pStat->ustrFileURL)) != osl_File_E_None)
     245           0 :             return osl_error;
     246             : 
     247      132561 :         pStat->uValidFields |= osl_FileStatus_Mask_FileURL;
     248             :     }
     249             : 
     250      227408 :     if (uFieldMask & osl_FileStatus_Mask_FileName)
     251             :     {
     252      105121 :         osl_systemPathGetFileNameOrLastDirectoryPart(file_path.pData, &pStat->ustrFileName);
     253      105121 :         pStat->uValidFields |= osl_FileStatus_Mask_FileName;
     254             :        }
     255      227408 :     return osl_File_E_None;
     256             : }
     257             : 
     258       21746 : static oslFileError osl_psz_setFileAttributes( const sal_Char* pszFilePath, sal_uInt64 uAttributes )
     259             : {
     260       21746 :     oslFileError osl_error = osl_File_E_None;
     261       21746 :     mode_t       nNewMode  = 0;
     262             : 
     263             :      OSL_ENSURE(!(osl_File_Attribute_Hidden & uAttributes), "osl_File_Attribute_Hidden doesn't work under Unix");
     264             : 
     265       21746 :     if (uAttributes & osl_File_Attribute_OwnRead)
     266       21711 :         nNewMode |= S_IRUSR;
     267             : 
     268       21746 :     if (uAttributes & osl_File_Attribute_OwnWrite)
     269       21745 :         nNewMode|=S_IWUSR;
     270             : 
     271       21746 :     if  (uAttributes & osl_File_Attribute_OwnExe)
     272          57 :         nNewMode|=S_IXUSR;
     273             : 
     274       21746 :     if (uAttributes & osl_File_Attribute_GrpRead)
     275       20916 :         nNewMode|=S_IRGRP;
     276             : 
     277       21746 :     if (uAttributes & osl_File_Attribute_GrpWrite)
     278       18960 :         nNewMode|=S_IWGRP;
     279             : 
     280       21746 :     if (uAttributes & osl_File_Attribute_GrpExe)
     281           3 :         nNewMode|=S_IXGRP;
     282             : 
     283       21746 :     if (uAttributes & osl_File_Attribute_OthRead)
     284       20916 :         nNewMode|=S_IROTH;
     285             : 
     286       21746 :     if (uAttributes & osl_File_Attribute_OthWrite)
     287          34 :         nNewMode|=S_IWOTH;
     288             : 
     289       21746 :     if (uAttributes & osl_File_Attribute_OthExe)
     290           3 :         nNewMode|=S_IXOTH;
     291             : 
     292       21746 :     if (chmod(pszFilePath, nNewMode) < 0)
     293           0 :         osl_error = oslTranslateFileError(OSL_FET_ERROR, errno);
     294             : 
     295       21746 :     return osl_error;
     296             : }
     297             : 
     298       21746 : oslFileError SAL_CALL osl_setFileAttributes( rtl_uString* ustrFileURL, sal_uInt64 uAttributes )
     299             : {
     300             :     char path[PATH_MAX];
     301             :     oslFileError eRet;
     302             : 
     303             :     OSL_ASSERT( ustrFileURL );
     304             : 
     305             :     /* convert file url to system path */
     306       21746 :     eRet = FileURLToPath( path, PATH_MAX, ustrFileURL );
     307       21746 :     if( eRet != osl_File_E_None )
     308           0 :         return eRet;
     309             : 
     310             : #ifdef MACOSX
     311             :     if ( macxp_resolveAlias( path, PATH_MAX ) != 0 )
     312             :       return oslTranslateFileError( OSL_FET_ERROR, errno );
     313             : #endif/* MACOSX */
     314             : 
     315       21746 :     return osl_psz_setFileAttributes( path, uAttributes );
     316             : }
     317             : 
     318           0 : static oslFileError osl_psz_setFileTime (
     319             :     const sal_Char* pszFilePath,
     320             :     const TimeValue* pLastAccessTime,
     321             :     const TimeValue* pLastWriteTime )
     322             : {
     323           0 :     int nRet=0;
     324             :     struct utimbuf aTimeBuffer;
     325             :     struct stat aFileStat;
     326             : #ifdef DEBUG_OSL_FILE
     327             :     struct tm* pTM=0;
     328             : #endif
     329             : 
     330           0 :     nRet = lstat_c(pszFilePath,&aFileStat);
     331             : 
     332           0 :     if ( nRet < 0 )
     333             :     {
     334           0 :         nRet=errno;
     335           0 :         return oslTranslateFileError(OSL_FET_ERROR, nRet);
     336             :     }
     337             : 
     338             : #ifdef DEBUG_OSL_FILE
     339             :     fprintf(stderr,"File Times are (in localtime):\n");
     340             :     pTM=localtime(&aFileStat.st_ctime);
     341             :     fprintf(stderr,"CreationTime is '%s'\n",asctime(pTM));
     342             :     pTM=localtime(&aFileStat.st_atime);
     343             :     fprintf(stderr,"AccessTime   is '%s'\n",asctime(pTM));
     344             :     pTM=localtime(&aFileStat.st_mtime);
     345             :     fprintf(stderr,"Modification is '%s'\n",asctime(pTM));
     346             : 
     347             :     fprintf(stderr,"File Times are (in UTC):\n");
     348             :     fprintf(stderr,"CreationTime is '%s'\n",ctime(&aFileStat.st_ctime));
     349             :     fprintf(stderr,"AccessTime   is '%s'\n",ctime(&aTimeBuffer.actime));
     350             :     fprintf(stderr,"Modification is '%s'\n",ctime(&aTimeBuffer.modtime));
     351             : #endif
     352             : 
     353           0 :     if ( pLastAccessTime != 0 )
     354             :     {
     355           0 :         aTimeBuffer.actime=pLastAccessTime->Seconds;
     356             :     }
     357             :     else
     358             :     {
     359           0 :         aTimeBuffer.actime=aFileStat.st_atime;
     360             :     }
     361             : 
     362           0 :     if ( pLastWriteTime != 0 )
     363             :     {
     364           0 :         aTimeBuffer.modtime=pLastWriteTime->Seconds;
     365             :     }
     366             :     else
     367             :     {
     368           0 :         aTimeBuffer.modtime=aFileStat.st_mtime;
     369             :     }
     370             : 
     371             :     /* mfe: Creation time not used here! */
     372             : 
     373             : #ifdef DEBUG_OSL_FILE
     374             :     fprintf(stderr,"File Times are (in localtime):\n");
     375             :     pTM=localtime(&aFileStat.st_ctime);
     376             :     fprintf(stderr,"CreationTime now '%s'\n",asctime(pTM));
     377             :     pTM=localtime(&aTimeBuffer.actime);
     378             :     fprintf(stderr,"AccessTime   now '%s'\n",asctime(pTM));
     379             :     pTM=localtime(&aTimeBuffer.modtime);
     380             :     fprintf(stderr,"Modification now '%s'\n",asctime(pTM));
     381             : 
     382             :     fprintf(stderr,"File Times are (in UTC):\n");
     383             :     fprintf(stderr,"CreationTime now '%s'\n",ctime(&aFileStat.st_ctime));
     384             :     fprintf(stderr,"AccessTime   now '%s'\n",ctime(&aTimeBuffer.actime));
     385             :     fprintf(stderr,"Modification now '%s'\n",ctime(&aTimeBuffer.modtime));
     386             : #endif
     387             : 
     388           0 :     nRet = utime_c(pszFilePath,&aTimeBuffer);
     389           0 :     if ( nRet < 0 )
     390             :     {
     391           0 :         nRet=errno;
     392           0 :         return oslTranslateFileError(OSL_FET_ERROR, nRet);
     393             :     }
     394             : 
     395           0 :     return osl_File_E_None;
     396             : }
     397             : 
     398           0 : oslFileError SAL_CALL osl_setFileTime (
     399             :     rtl_uString* ustrFileURL,
     400             :     SAL_UNUSED_PARAMETER const TimeValue* /* pCreationTime */,
     401             :     const TimeValue* pLastAccessTime,
     402             :     const TimeValue* pLastWriteTime )
     403             : {
     404             :     char path[PATH_MAX];
     405             :     oslFileError eRet;
     406             : 
     407             :     OSL_ASSERT( ustrFileURL );
     408             : 
     409             :     /* convert file url to system path */
     410           0 :     eRet = FileURLToPath( path, PATH_MAX, ustrFileURL );
     411           0 :     if( eRet != osl_File_E_None )
     412           0 :         return eRet;
     413             : 
     414             : #ifdef MACOSX
     415             :     if ( macxp_resolveAlias( path, PATH_MAX ) != 0 )
     416             :       return oslTranslateFileError( OSL_FET_ERROR, errno );
     417             : #endif/* MACOSX */
     418             : 
     419           0 :     return osl_psz_setFileTime( path, pLastAccessTime, pLastWriteTime );
     420             : }
     421             : 
     422             : sal_Bool
     423           0 : SAL_CALL osl_identicalDirectoryItem( oslDirectoryItem a, oslDirectoryItem b)
     424             : {
     425           0 :     DirectoryItem_Impl *pA = static_cast<DirectoryItem_Impl *>(a);
     426           0 :     DirectoryItem_Impl *pB = static_cast<DirectoryItem_Impl *>(b);
     427           0 :     if (a == b)
     428           0 :         return sal_True;
     429             :     /* same name => same item, unless renaming / moving madness has occurred */
     430           0 :     if (rtl_ustr_compare_WithLength(
     431             :                 pA->m_ustrFilePath->buffer, pA->m_ustrFilePath->length,
     432           0 :                 pB->m_ustrFilePath->buffer, pB->m_ustrFilePath->length ) == 0)
     433           0 :         return sal_True;
     434             : 
     435             :     struct stat a_stat, b_stat;
     436             : 
     437           0 :     if (osl::lstat(rtl::OUString(pA->m_ustrFilePath), a_stat) != 0 ||
     438           0 :         osl::lstat(rtl::OUString(pB->m_ustrFilePath), b_stat) != 0)
     439           0 :         return sal_False;
     440             : 
     441           0 :     return (a_stat.st_ino == b_stat.st_ino);
     442             : }
     443             : 
     444             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11