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

Generated by: LCOV version 1.10