summaryrefslogtreecommitdiff
path: root/sal/osl/unx/file_stat.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sal/osl/unx/file_stat.cxx')
-rw-r--r--sal/osl/unx/file_stat.cxx361
1 files changed, 361 insertions, 0 deletions
diff --git a/sal/osl/unx/file_stat.cxx b/sal/osl/unx/file_stat.cxx
new file mode 100644
index 000000000000..430670d3db41
--- /dev/null
+++ b/sal/osl/unx/file_stat.cxx
@@ -0,0 +1,361 @@
+/*************************************************************************
+ *
+ * $RCSfile: file_stat.cxx,v $
+ *
+ * $Revision: 1.2 $
+ *
+ * last change: $Author: hr $ $Date: 2003-03-26 16:46:03 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifndef _LIMITS_H
+#include <limits.h>
+#endif
+
+#ifndef _UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifndef _OSL_FILE_H_
+#include <osl/file.h>
+#endif
+
+#ifndef _ERRNO_H
+#include <errno.h>
+#endif
+
+#ifndef _RTL_STRING_HXX_
+#include <rtl/string.hxx>
+#endif
+
+#ifndef _OSL_UUNXAPI_H_
+#include "uunxapi.hxx"
+#endif
+
+#ifndef _OSL_FILE_PATH_HELPER_HXX_
+#include "file_path_helper.hxx"
+#endif
+
+#ifndef _FILE_ERROR_TRANSL_H_
+#include "file_error_transl.h"
+#endif
+
+
+namespace /* private */
+{
+
+ inline void set_file_type(const struct stat& file_stat, oslFileStatus* pStat)
+ {
+ /* links to directories state also to be a directory */
+ if (S_ISLNK(file_stat.st_mode))
+ pStat->eType = osl_File_Type_Link;
+ else if (S_ISDIR(file_stat.st_mode))
+ pStat->eType = osl_File_Type_Directory;
+ else if (S_ISREG(file_stat.st_mode))
+ pStat->eType = osl_File_Type_Regular;
+ else if (S_ISFIFO(file_stat.st_mode))
+ pStat->eType = osl_File_Type_Fifo;
+ else if (S_ISSOCK(file_stat.st_mode))
+ pStat->eType = osl_File_Type_Socket;
+ else if (S_ISCHR(file_stat.st_mode) || S_ISBLK(file_stat.st_mode))
+ pStat->eType = osl_File_Type_Special;
+ else
+ pStat->eType = osl_File_Type_Unknown;
+
+ pStat->uValidFields |= osl_FileStatus_Mask_Type;
+ }
+
+ inline void set_file_access_mask(const struct stat& file_stat, oslFileStatus* pStat)
+ {
+ // user permissions
+ if (S_IRUSR & file_stat.st_mode)
+ pStat->uAttributes |= osl_File_Attribute_OwnRead;
+
+ if (S_IWUSR & file_stat.st_mode)
+ pStat->uAttributes |= osl_File_Attribute_OwnWrite;
+
+ if (S_IXUSR & file_stat.st_mode)
+ pStat->uAttributes |= osl_File_Attribute_OwnExe;
+
+ // group permissions
+ if (S_IRGRP & file_stat.st_mode)
+ pStat->uAttributes |= osl_File_Attribute_GrpRead;
+
+ if (S_IWGRP & file_stat.st_mode)
+ pStat->uAttributes |= osl_File_Attribute_GrpWrite;
+
+ if (S_IXGRP & file_stat.st_mode)
+ pStat->uAttributes |= osl_File_Attribute_GrpExe;
+
+ // others permissions
+ if (S_IROTH & file_stat.st_mode)
+ pStat->uAttributes |= osl_File_Attribute_OthRead;
+
+ if (S_IWOTH & file_stat.st_mode)
+ pStat->uAttributes |= osl_File_Attribute_OthWrite;
+
+ if (S_IXOTH & file_stat.st_mode)
+ pStat->uAttributes |= osl_File_Attribute_OthExe;
+
+ pStat->uValidFields |= osl_FileStatus_Mask_Attributes;
+ }
+
+ inline void set_file_access_rights(const struct stat& file_stat, int S_IR, int S_IW, int S_IX, oslFileStatus* pStat)
+ {
+ /* we cannot really map osl_File_Attribute_ReadOnly to
+ the Unix access rights, it's a Windows only flag
+ that's why the following hack. We set osl_FileStatus_Mask_Attributes
+ but if there is no read access for a file we clear the flag
+ again to signal to the caller that there are no file attributes
+ to read because that's better than to give them incorrect one.
+ */
+ pStat->uValidFields |= osl_FileStatus_Mask_Attributes;
+
+ if (0 == (S_IR & file_stat.st_mode))
+ pStat->uValidFields &= ~osl_FileStatus_Mask_Attributes;
+
+ if (0 == (S_IW & file_stat.st_mode))
+ pStat->uAttributes |= osl_File_Attribute_ReadOnly;
+
+ if (S_IX & file_stat.st_mode)
+ pStat->uAttributes |= osl_File_Attribute_Executable;
+ }
+
+ /* a process may belong to up to NGROUPS_MAX groups, so when
+ checking group access rights, we have to check all belonging
+ groups */
+ inline bool is_in_process_grouplist(const gid_t file_group)
+ {
+ // check primary process group
+
+ if (getgid() == file_group)
+ return true;
+
+ // check supplementary process groups
+
+ gid_t grplist[NGROUPS_MAX];
+ int grp_number = getgroups(NGROUPS_MAX, grplist);
+
+ for (int i = 0; i < grp_number; i++)
+ {
+ if (grplist[i] == file_group)
+ return true;
+ }
+ return false;
+ }
+
+ /* Currently we are determining the file access right based
+ on the real user ID not the effective user ID!
+ We don't use access(...) because access follows links which
+ may cause performance problems see #97133.
+ */
+ inline void set_file_access_rights(const struct stat& file_stat, oslFileStatus* pStat)
+ {
+ if (getuid() == file_stat.st_uid)
+ {
+ set_file_access_rights(file_stat, S_IRUSR, S_IWUSR, S_IXUSR, pStat);
+ }
+ else if (is_in_process_grouplist(file_stat.st_gid))
+ {
+ set_file_access_rights(file_stat, S_IRGRP, S_IWGRP, S_IXGRP, pStat);
+ }
+ else
+ {
+ set_file_access_rights(file_stat, S_IROTH, S_IWOTH, S_IXOTH, pStat);
+ }
+ }
+
+ inline void set_file_hidden_status(const rtl::OUString& file_path, oslFileStatus* pStat)
+ {
+ pStat->uAttributes = osl::systemPathIsHiddenFileOrDirectoryEntry(file_path) ? osl_File_Attribute_Hidden : 0;
+ pStat->uValidFields |= osl_FileStatus_Mask_Attributes;
+ }
+
+ /* the set_file_access_rights must be called after set_file_hidden_status(...) and
+ set_file_access_mask(...) because of the hack in set_file_access_rights(...) */
+ inline void set_file_attributes(
+ const rtl::OUString& file_path, const struct stat& file_stat, const sal_uInt32 uFieldMask, oslFileStatus* pStat)
+ {
+ set_file_hidden_status(file_path, pStat);
+ set_file_access_mask(file_stat, pStat);
+
+ // we set the file access rights only on demand
+ // because it's potentially expensive
+ if (uFieldMask & osl_FileStatus_Mask_Attributes)
+ set_file_access_rights(file_stat, pStat);
+ }
+
+ inline void set_file_access_time(const struct stat& file_stat, oslFileStatus* pStat)
+ {
+ pStat->aAccessTime.Seconds = file_stat.st_atime;
+ pStat->aAccessTime.Nanosec = 0;
+ pStat->uValidFields |= osl_FileStatus_Mask_AccessTime;
+ }
+
+ inline void set_file_modify_time(const struct stat& file_stat, oslFileStatus* pStat)
+ {
+ pStat->aModifyTime.Seconds = file_stat.st_mtime;
+ pStat->aModifyTime.Nanosec = 0;
+ pStat->uValidFields |= osl_FileStatus_Mask_ModifyTime;
+ }
+
+ inline void set_file_size(const struct stat& file_stat, oslFileStatus* pStat)
+ {
+ if (S_ISREG(file_stat.st_mode))
+ {
+ pStat->uFileSize = file_stat.st_size;
+ pStat->uValidFields |= osl_FileStatus_Mask_FileSize;
+ }
+ }
+
+ /* we only need to call stat or lstat if one of the
+ following flags is set */
+ inline bool is_stat_call_necessary(sal_uInt32 field_mask)
+ {
+ return ((field_mask & osl_FileStatus_Mask_Type) ||
+ (field_mask & osl_FileStatus_Mask_Attributes) ||
+ (field_mask & osl_FileStatus_Mask_CreationTime) ||
+ (field_mask & osl_FileStatus_Mask_AccessTime) ||
+ (field_mask & osl_FileStatus_Mask_ModifyTime) ||
+ (field_mask & osl_FileStatus_Mask_FileSize) ||
+ (field_mask & osl_FileStatus_Mask_LinkTargetURL) ||
+ (field_mask & osl_FileStatus_Mask_Validate));
+ }
+
+ inline oslFileError set_link_target_url(const rtl::OUString& file_path, oslFileStatus* pStat)
+ {
+ rtl::OUString link_target;
+ if (!osl::realpath(file_path, link_target))
+ return oslTranslateFileError(OSL_FET_ERROR, errno);
+
+ oslFileError osl_error = osl_getFileURLFromSystemPath(link_target.pData, &pStat->ustrLinkTargetURL);
+ if (osl_error != osl_File_E_None)
+ return osl_error;
+
+ pStat->uValidFields |= osl_FileStatus_Mask_LinkTargetURL;
+ return osl_File_E_None;
+ }
+
+ inline oslFileError setup_osl_getFileStatus(oslDirectoryItem Item, oslFileStatus* pStat, rtl::OUString& file_path)
+ {
+ if ((NULL == Item) || (NULL == pStat))
+ return osl_File_E_INVAL;
+
+ file_path = rtl::OUString(reinterpret_cast<rtl_uString*>(Item));
+
+ OSL_ASSERT(file_path.getLength() > 0);
+
+ if (file_path.getLength() <= 0)
+ return osl_File_E_INVAL;
+
+ pStat->uValidFields = 0;
+
+ return osl_File_E_None;
+ }
+
+} // end namespace private
+
+
+/****************************************************************************
+ * osl_getFileStatus
+ ****************************************************************************/
+
+oslFileError SAL_CALL osl_getFileStatus(oslDirectoryItem Item, oslFileStatus* pStat, sal_uInt32 uFieldMask)
+{
+ rtl::OUString file_path;
+ oslFileError osl_error = setup_osl_getFileStatus(Item, pStat, file_path);
+ if (osl_File_E_None != osl_error)
+ return osl_error;
+
+ struct stat file_stat;
+ if (is_stat_call_necessary(uFieldMask) && (0 != osl::lstat(file_path, file_stat)))
+ return oslTranslateFileError(OSL_FET_ERROR, errno);
+
+ if (is_stat_call_necessary(uFieldMask))
+ {
+ // we set all these attributes because it's cheap
+ set_file_type(file_stat, pStat);
+ set_file_access_time(file_stat, pStat);
+ set_file_modify_time(file_stat, pStat);
+ set_file_size(file_stat, pStat);
+ set_file_attributes(file_path, file_stat, uFieldMask, pStat);
+
+ // file exists semantic of osl_FileStatus_Mask_Validate
+ if ((uFieldMask & osl_FileStatus_Mask_LinkTargetURL) && S_ISLNK(file_stat.st_mode))
+ {
+ osl_error = set_link_target_url(file_path, pStat);
+ if (osl_error != osl_File_E_None)
+ return osl_error;
+ }
+ }
+
+ if (uFieldMask & osl_FileStatus_Mask_FileURL)
+ {
+ if ((osl_error = osl_getFileURLFromSystemPath(file_path.pData, &pStat->ustrFileURL)) != osl_File_E_None)
+ return osl_error;
+
+ pStat->uValidFields |= osl_FileStatus_Mask_FileURL;
+ }
+
+ if (uFieldMask & osl_FileStatus_Mask_FileName)
+ {
+ osl_systemPathGetFileNameOrLastDirectoryPart(file_path.pData, &pStat->ustrFileName);
+ pStat->uValidFields |= osl_FileStatus_Mask_FileName;
+ }
+ return osl_File_E_None;
+}