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

Generated by: LCOV version 1.10