diff options
Diffstat (limited to 'sal/osl/unx/file_volume.cxx')
-rw-r--r-- | sal/osl/unx/file_volume.cxx | 336 |
1 files changed, 336 insertions, 0 deletions
diff --git a/sal/osl/unx/file_volume.cxx b/sal/osl/unx/file_volume.cxx new file mode 100644 index 000000000..5e661bd65 --- /dev/null +++ b/sal/osl/unx/file_volume.cxx @@ -0,0 +1,336 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <osl/file.h> + +#include <osl/diagnose.h> +#include <osl/thread.h> +#include <rtl/alloc.h> + +#include "file_error_transl.hxx" +#include "file_url.hxx" +#include "system.hxx" + +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <sys/wait.h> +#include <sal/macros.h> + +#ifdef HAVE_STATFS_H +#undef HAVE_STATFS_H +#endif + +#if defined(LINUX) && defined(__FreeBSD_kernel__) +#undef LINUX +#define FREEBSD 1 +#endif + +#if defined(__sun) + +#include <sys/mnttab.h> +#include <sys/statvfs.h> +#define HAVE_STATFS_H + +#elif defined(LINUX) + +#include <mntent.h> +#include <sys/vfs.h> +#define HAVE_STATFS_H + +#elif defined(NETBSD) || defined(FREEBSD) || defined(OPENBSD) || defined(DRAGONFLY) + +#include <sys/param.h> +#include <sys/ucred.h> +#include <sys/mount.h> +#define HAVE_STATFS_H + +#elif defined(MACOSX) + +#include <sys/param.h> +#include <sys/mount.h> +#define HAVE_STATFS_H + +#endif /* HAVE_STATFS_H */ + +/************************************************************************ + * ToDo + * + * - Fix: check for corresponding struct sizes in exported functions + * - check size/use of oslVolumeInfo + ***********************************************************************/ + +/****************************************************************************** + * + * C-String Function Declarations + * + *****************************************************************************/ + +static oslFileError osl_psz_getVolumeInformation(const char* , oslVolumeInfo* pInfo, sal_uInt32 uFieldMask); + +/****************************************************************************/ +/* osl_getVolumeInformation */ +/****************************************************************************/ + +oslFileError osl_getVolumeInformation( rtl_uString* ustrDirectoryURL, oslVolumeInfo* pInfo, sal_uInt32 uFieldMask ) +{ + char path[PATH_MAX]; + oslFileError eRet; + + OSL_ASSERT( ustrDirectoryURL ); + OSL_ASSERT( pInfo ); + + /* convert directory url to system path */ + eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL ); + if( eRet != osl_File_E_None ) + return eRet; + +#ifdef MACOSX + if ( macxp_resolveAlias( path, PATH_MAX ) != 0 ) + return oslTranslateFileError( errno ); +#endif/* MACOSX */ + + return osl_psz_getVolumeInformation( path, pInfo, uFieldMask); +} + +/****************************************************************************** + * + * C-String Versions of Exported Module Functions + * + *****************************************************************************/ + +#ifdef HAVE_STATFS_H + +#if defined(FREEBSD) || defined(MACOSX) || defined(OPENBSD) || defined(DRAGONFLY) +# define OSL_detail_STATFS_STRUCT struct statfs +# define OSL_detail_STATFS(dir, sfs) statfs((dir), (sfs)) +# define OSL_detail_STATFS_BLKSIZ(a) (static_cast<sal_uInt64>((a).f_bsize)) +# define OSL_detail_STATFS_TYPENAME(a) ((a).f_fstypename) +#if defined(OPENBSD) +# define OSL_detail_STATFS_ISREMOTE(a) (rtl_str_compare((a).f_fstypename, "nfs") == 0) +#else +# define OSL_detail_STATFS_ISREMOTE(a) (((a).f_type & MNT_LOCAL) == 0) +#endif + +/* always return true if queried for the properties of + the file system. If you think this is wrong under any + of the target platforms fix it!!!! */ +# define OSL_detail_STATFS_IS_CASE_SENSITIVE_FS(a) (true) +# define OSL_detail_STATFS_IS_CASE_PRESERVING_FS(a) (true) +#endif /* FREEBSD || MACOSX || OPENBSD */ + +#if defined(NETBSD) + +# define OSL_detail_STATFS_STRUCT struct statvfs +# define OSL_detail_STATFS(dir, sfs) statvfs((dir), (sfs)) +# define OSL_detail_STATFS_ISREMOTE(a) (((a).f_flag & ST_LOCAL) == 0) + +# define OSL_detail_STATFS_BLKSIZ(a) ((sal_uInt64)((a).f_bsize)) +# define OSL_detail_STATFS_TYPENAME(a) ((a).f_fstypename) + +# define OSL_detail_STATFS_IS_CASE_SENSITIVE_FS(a) (strcmp((a).f_fstypename, "msdos") != 0 && strcmp((a).f_fstypename, "ntfs") != 0 && strcmp((a).f_fstypename, "smbfs") != 0) +# define OSL_detail_STATFS_IS_CASE_PRESERVING_FS(a) (strcmp((a).f_fstypename, "msdos") != 0) +#endif /* NETBSD */ + +#if defined(LINUX) +# define OSL_detail_NFS_SUPER_MAGIC 0x6969 +# define OSL_detail_SMB_SUPER_MAGIC 0x517B +# define OSL_detail_MSDOS_SUPER_MAGIC 0x4d44 +# define OSL_detail_NTFS_SUPER_MAGIC 0x5346544e +# define OSL_detail_STATFS_STRUCT struct statfs +# define OSL_detail_STATFS(dir, sfs) statfs((dir), (sfs)) +# define OSL_detail_STATFS_BLKSIZ(a) (static_cast<sal_uInt64>((a).f_bsize)) +# define OSL_detail_STATFS_IS_NFS(a) (OSL_detail_NFS_SUPER_MAGIC == (a).f_type) +# define OSL_detail_STATFS_IS_SMB(a) (OSL_detail_SMB_SUPER_MAGIC == (a).f_type) +# define OSL_detail_STATFS_ISREMOTE(a) (OSL_detail_STATFS_IS_NFS((a)) || OSL_detail_STATFS_IS_SMB((a))) +# define OSL_detail_STATFS_IS_CASE_SENSITIVE_FS(a) ((OSL_detail_MSDOS_SUPER_MAGIC != (a).f_type) && (OSL_detail_NTFS_SUPER_MAGIC != (a).f_type)) +# define OSL_detail_STATFS_IS_CASE_PRESERVING_FS(a) ((OSL_detail_MSDOS_SUPER_MAGIC != (a).f_type)) +#endif /* LINUX */ + +#if defined(__sun) +# define OSL_detail_STATFS_STRUCT struct statvfs +# define OSL_detail_STATFS(dir, sfs) statvfs((dir), (sfs)) +# define OSL_detail_STATFS_BLKSIZ(a) ((sal_uInt64)((a).f_frsize)) +# define OSL_detail_STATFS_TYPENAME(a) ((a).f_basetype) +# define OSL_detail_STATFS_ISREMOTE(a) (rtl_str_compare((a).f_basetype, "nfs") == 0) + +/* always return true if queried for the properties of + the file system. If you think this is wrong under any + of the target platforms fix it!!!! */ +# define OSL_detail_STATFS_IS_CASE_SENSITIVE_FS(a) (true) +# define OSL_detail_STATFS_IS_CASE_PRESERVING_FS(a) (true) +#endif /* __sun */ + +# define OSL_detail_STATFS_INIT(a) (memset(&(a), 0, sizeof(OSL_detail_STATFS_STRUCT))) + +#else /* no statfs available */ + +# define OSL_detail_STATFS_STRUCT struct dummy {int i;} +# define OSL_detail_STATFS_INIT(a) ((void)a) +# define OSL_detail_STATFS(dir, sfs) (1) +# define OSL_detail_STATFS_ISREMOTE(sfs) (false) +# define OSL_detail_STATFS_IS_CASE_SENSITIVE_FS(a) (true) +# define OSL_detail_STATFS_IS_CASE_PRESERVING_FS(a) (true) +#endif /* HAVE_STATFS_H */ + +static oslFileError osl_psz_getVolumeInformation ( + const char* pszDirectory, oslVolumeInfo* pInfo, sal_uInt32 uFieldMask) +{ + if (!pInfo) + return osl_File_E_INVAL; + + pInfo->uValidFields = 0; + pInfo->uAttributes = 0; + pInfo->uTotalSpace = 0; + pInfo->uFreeSpace = 0; + pInfo->uUsedSpace = 0; + + if ((uFieldMask + & (osl_VolumeInfo_Mask_Attributes | osl_VolumeInfo_Mask_TotalSpace + | osl_VolumeInfo_Mask_UsedSpace | osl_VolumeInfo_Mask_FreeSpace + | osl_VolumeInfo_Mask_FileSystemName + | osl_VolumeInfo_Mask_FileSystemCaseHandling)) + != 0) + { + OSL_detail_STATFS_STRUCT sfs; + OSL_detail_STATFS_INIT(sfs); + // coverity[fs_check_call : FALSE] + if ((OSL_detail_STATFS(pszDirectory, &sfs)) < (0)) + { + oslFileError result = oslTranslateFileError(errno); + return result; + } + + /* FIXME: how to detect the kind of storage (fixed, cdrom, ...) */ + if (uFieldMask & osl_VolumeInfo_Mask_Attributes) + { + bool const remote = OSL_detail_STATFS_ISREMOTE(sfs); + // extracted from the 'if' to avoid Clang -Wunreachable-code + if (remote) + pInfo->uAttributes |= osl_Volume_Attribute_Remote; + + pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes; + } + + if (uFieldMask & osl_VolumeInfo_Mask_FileSystemCaseHandling) + { + if (OSL_detail_STATFS_IS_CASE_SENSITIVE_FS(sfs)) + pInfo->uAttributes |= osl_Volume_Attribute_Case_Sensitive; + + if (OSL_detail_STATFS_IS_CASE_PRESERVING_FS(sfs)) + pInfo->uAttributes |= osl_Volume_Attribute_Case_Is_Preserved; + + pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes; + } + +#if defined(OSL_detail_STATFS_BLKSIZ) + + if ((uFieldMask & osl_VolumeInfo_Mask_TotalSpace) || + (uFieldMask & osl_VolumeInfo_Mask_UsedSpace)) + { + pInfo->uTotalSpace = OSL_detail_STATFS_BLKSIZ(sfs); + pInfo->uTotalSpace *= static_cast<sal_uInt64>(sfs.f_blocks); + pInfo->uValidFields |= osl_VolumeInfo_Mask_TotalSpace; + } + + if ((uFieldMask & osl_VolumeInfo_Mask_FreeSpace) || + (uFieldMask & osl_VolumeInfo_Mask_UsedSpace)) + { + pInfo->uFreeSpace = OSL_detail_STATFS_BLKSIZ(sfs); + + if (getuid() == 0) + pInfo->uFreeSpace *= static_cast<sal_uInt64>(sfs.f_bfree); + else + pInfo->uFreeSpace *= static_cast<sal_uInt64>(sfs.f_bavail); + + pInfo->uValidFields |= osl_VolumeInfo_Mask_FreeSpace; + } + + if ((pInfo->uValidFields & osl_VolumeInfo_Mask_TotalSpace) && + (pInfo->uValidFields & osl_VolumeInfo_Mask_FreeSpace )) + { + pInfo->uUsedSpace = pInfo->uTotalSpace - pInfo->uFreeSpace; + pInfo->uValidFields |= osl_VolumeInfo_Mask_UsedSpace; + } + +#endif /* OSL_detail_STATFS_BLKSIZ */ + +#if defined(OSL_detail_STATFS_TYPENAME) + + if (uFieldMask & osl_VolumeInfo_Mask_FileSystemName) + { + rtl_string2UString( + &(pInfo->ustrFileSystemName), + OSL_detail_STATFS_TYPENAME(sfs), + rtl_str_getLength(OSL_detail_STATFS_TYPENAME(sfs)), + osl_getThreadTextEncoding(), + OUSTRING_TO_OSTRING_CVTFLAGS); + OSL_ASSERT(pInfo->ustrFileSystemName != nullptr); + + pInfo->uValidFields |= osl_VolumeInfo_Mask_FileSystemName; + } + +#endif /* OSL_detail_STATFS_TYPENAME */ + } + + pInfo->uMaxNameLength = 0; + if (uFieldMask & osl_VolumeInfo_Mask_MaxNameLength) + { + long nLen = pathconf(pszDirectory, _PC_NAME_MAX); + if (nLen > 0) + { + pInfo->uMaxNameLength = static_cast<sal_uInt32>(nLen); + pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxNameLength; + } + } + + pInfo->uMaxPathLength = 0; + if (uFieldMask & osl_VolumeInfo_Mask_MaxPathLength) + { + long nLen = pathconf (pszDirectory, _PC_PATH_MAX); + if (nLen > 0) + { + pInfo->uMaxPathLength = static_cast<sal_uInt32>(nLen); + pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxPathLength; + } + } + + return osl_File_E_None; +} + +oslFileError osl_getVolumeDeviceMountPath( oslVolumeDeviceHandle, rtl_uString ** ) +{ + return osl_File_E_INVAL; +} + +oslFileError osl_acquireVolumeDeviceHandle( oslVolumeDeviceHandle ) +{ + return osl_File_E_INVAL; +} + +oslFileError osl_releaseVolumeDeviceHandle( oslVolumeDeviceHandle ) +{ + return osl_File_E_INVAL; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |