summaryrefslogtreecommitdiff
path: root/sal/osl/unx/file_volume.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sal/osl/unx/file_volume.cxx')
-rw-r--r--sal/osl/unx/file_volume.cxx1155
1 files changed, 1155 insertions, 0 deletions
diff --git a/sal/osl/unx/file_volume.cxx b/sal/osl/unx/file_volume.cxx
new file mode 100644
index 000000000000..cc7f61ec6a8b
--- /dev/null
+++ b/sal/osl/unx/file_volume.cxx
@@ -0,0 +1,1155 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "osl/file.h"
+
+#include "osl/diagnose.h"
+#include "osl/thread.h"
+#include "rtl/alloc.h"
+
+#include "file_error_transl.h"
+#include "file_url.h"
+#include "system.h"
+
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+#ifdef HAVE_STATFS_H
+#undef HAVE_STATFS_H
+#endif
+
+#if defined(LINUX) && defined(__FreeBSD_kernel__)
+#undef LINUX
+#define FREEBSD 1
+#endif
+
+
+#if defined(SOLARIS)
+
+#include <sys/mnttab.h>
+#include <sys/statvfs.h>
+#define HAVE_STATFS_H
+#include <sys/fs/ufs_quota.h>
+static const sal_Char* MOUNTTAB="/etc/mnttab";
+
+#elif defined(LINUX)
+
+#include <mntent.h>
+#include <sys/vfs.h>
+#define HAVE_STATFS_H
+#include <sys/quota.h>
+//#include <ctype.h>
+static const sal_Char* MOUNTTAB="/etc/mtab";
+
+#elif defined(NETBSD) || defined(FREEBSD)
+
+#include <sys/param.h>
+#include <sys/ucred.h>
+#include <sys/mount.h>
+#include <ufs/ufs/quota.h>
+//#include <ctype.h>
+#define HAVE_STATFS_H
+
+/* No mounting table on *BSD
+ * This information is stored only in the kernel. */
+/* static const sal_Char* MOUNTTAB="/etc/mtab"; */
+
+#elif defined(MACOSX)
+
+#include <ufs/ufs/quota.h>
+//#include <ctype.h>
+#include <sys/param.h>
+#include <sys/mount.h>
+#define HAVE_STATFS_H
+// static const sal_Char* MOUNTTAB="/etc/mtab";
+
+#endif /* HAVE_STATFS_H */
+
+/************************************************************************
+ * ToDo
+ *
+ * - Fix: check for corresponding struct sizes in exported functions
+ * - check size/use of oslVolumeDeviceHandle
+ * - check size/use of oslVolumeInfo
+ ***********************************************************************/
+/******************************************************************************
+ *
+ * Data Type Definition
+ *
+ ******************************************************************************/
+
+typedef struct _oslVolumeDeviceHandleImpl
+{
+ sal_Char pszMountPoint[PATH_MAX];
+ sal_Char pszFilePath[PATH_MAX];
+ sal_Char pszDevice[PATH_MAX];
+ sal_Char ident[4];
+ sal_uInt32 RefCount;
+} oslVolumeDeviceHandleImpl;
+
+/******************************************************************************
+ *
+ * 'removeable device' aka floppy functions
+ *
+ *****************************************************************************/
+
+static oslVolumeDeviceHandle osl_isFloppyDrive(const sal_Char* pszPath);
+static oslFileError osl_mountFloppy(oslVolumeDeviceHandle hFloppy);
+static oslFileError osl_unmountFloppy(oslVolumeDeviceHandle hFloppy);
+
+#if defined(SOLARIS)
+static sal_Bool osl_isFloppyMounted(sal_Char* pszPath, sal_Char* pszMountPath);
+static sal_Bool osl_getFloppyMountEntry(const sal_Char* pszPath, sal_Char* pBuffer);
+static sal_Bool osl_checkFloppyPath(sal_Char* pszPath, sal_Char* pszFilePath, sal_Char* pszDevicePath);
+#endif /* SOLARIS */
+
+#if defined(LINUX)
+static sal_Bool osl_isFloppyMounted(oslVolumeDeviceHandleImpl* pDevice);
+static sal_Bool osl_getFloppyMountEntry(const sal_Char* pszPath, oslVolumeDeviceHandleImpl* pItem);
+#endif /* LINUX */
+
+#ifdef DEBUG_OSL_FILE
+static void osl_printFloppyHandle(oslVolumeDeviceHandleImpl* hFloppy);
+#endif /* DEBUG_OSL_FILE */
+
+/******************************************************************************
+ *
+ * C-String Function Declarations
+ *
+ *****************************************************************************/
+
+static oslFileError osl_psz_getVolumeInformation(const sal_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( OSL_FET_ERROR, 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(NETBSD) || defined(MACOSX)
+# define __OSL_STATFS_STRUCT struct statfs
+# define __OSL_STATFS(dir, sfs) statfs((dir), (sfs))
+# define __OSL_STATFS_BLKSIZ(a) ((sal_uInt64)((a).f_bsize))
+# define __OSL_STATFS_TYPENAME(a) ((a).f_fstypename)
+# define __OSL_STATFS_ISREMOTE(a) (((a).f_type & MNT_LOCAL) == 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_STATFS_IS_CASE_SENSITIVE_FS(a) (1)
+# define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) (1)
+#endif /* FREEBSD || NETBSD || MACOSX */
+
+#if defined(LINUX)
+# define __OSL_NFS_SUPER_MAGIC 0x6969
+# define __OSL_SMB_SUPER_MAGIC 0x517B
+# define __OSL_MSDOS_SUPER_MAGIC 0x4d44
+# define __OSL_NTFS_SUPER_MAGIC 0x5346544e
+# define __OSL_STATFS_STRUCT struct statfs
+# define __OSL_STATFS(dir, sfs) statfs((dir), (sfs))
+# define __OSL_STATFS_BLKSIZ(a) ((sal_uInt64)((a).f_bsize))
+# define __OSL_STATFS_IS_NFS(a) (__OSL_NFS_SUPER_MAGIC == (a).f_type)
+# define __OSL_STATFS_IS_SMB(a) (__OSL_SMB_SUPER_MAGIC == (a).f_type)
+# define __OSL_STATFS_ISREMOTE(a) (__OSL_STATFS_IS_NFS((a)) || __OSL_STATFS_IS_SMB((a)))
+# define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a) ((__OSL_MSDOS_SUPER_MAGIC != (a).f_type) && (__OSL_NTFS_SUPER_MAGIC != (a).f_type))
+# define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) ((__OSL_MSDOS_SUPER_MAGIC != (a).f_type))
+#endif /* LINUX */
+
+#if defined(SOLARIS)
+# define __OSL_STATFS_STRUCT struct statvfs
+# define __OSL_STATFS(dir, sfs) statvfs((dir), (sfs))
+# define __OSL_STATFS_BLKSIZ(a) ((sal_uInt64)((a).f_frsize))
+# define __OSL_STATFS_TYPENAME(a) ((a).f_basetype)
+# define __OSL_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_STATFS_IS_CASE_SENSITIVE_FS(a) (1)
+# define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) (1)
+#endif /* SOLARIS */
+
+# define __OSL_STATFS_INIT(a) (memset(&(a), 0, sizeof(__OSL_STATFS_STRUCT)))
+
+#else /* no statfs available */
+
+# define __OSL_STATFS_STRUCT struct dummy {int i;}
+# define __OSL_STATFS_INIT(a) ((void)0)
+# define __OSL_STATFS(dir, sfs) (1)
+# define __OSL_STATFS_ISREMOTE(sfs) (0)
+# define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a) (1)
+# define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) (1)
+#endif /* HAVE_STATFS_H */
+
+
+static oslFileError osl_psz_getVolumeInformation (
+ const sal_Char* pszDirectory, oslVolumeInfo* pInfo, sal_uInt32 uFieldMask)
+{
+ __OSL_STATFS_STRUCT sfs;
+
+ if (!pInfo)
+ return osl_File_E_INVAL;
+
+ __OSL_STATFS_INIT(sfs);
+
+ pInfo->uValidFields = 0;
+ pInfo->uAttributes = 0;
+
+ if ((__OSL_STATFS(pszDirectory, &sfs)) < 0)
+ {
+ oslFileError result = oslTranslateFileError(OSL_FET_ERROR, errno);
+ return (result);
+ }
+
+ /* FIXME: how to detect the kind of storage (fixed, cdrom, ...) */
+ if (uFieldMask & osl_VolumeInfo_Mask_Attributes)
+ {
+ if (__OSL_STATFS_ISREMOTE(sfs))
+ pInfo->uAttributes |= osl_Volume_Attribute_Remote;
+
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
+ }
+
+ if (uFieldMask & osl_VolumeInfo_Mask_FileSystemCaseHandling)
+ {
+ if (__OSL_STATFS_IS_CASE_SENSITIVE_FS(sfs))
+ pInfo->uAttributes |= osl_Volume_Attribute_Case_Sensitive;
+
+ if (__OSL_STATFS_IS_CASE_PRESERVING_FS(sfs))
+ pInfo->uAttributes |= osl_Volume_Attribute_Case_Is_Preserved;
+
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
+ }
+
+ pInfo->uTotalSpace = 0;
+ pInfo->uFreeSpace = 0;
+ pInfo->uUsedSpace = 0;
+
+#if defined(__OSL_STATFS_BLKSIZ)
+
+ if ((uFieldMask & osl_VolumeInfo_Mask_TotalSpace) ||
+ (uFieldMask & osl_VolumeInfo_Mask_UsedSpace))
+ {
+ pInfo->uTotalSpace = __OSL_STATFS_BLKSIZ(sfs);
+ pInfo->uTotalSpace *= (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_STATFS_BLKSIZ(sfs);
+
+ if (getuid() == 0)
+ pInfo->uFreeSpace *= (sal_uInt64)(sfs.f_bfree);
+ else
+ pInfo->uFreeSpace *= (sal_uInt64)(sfs.f_bavail);
+
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_FreeSpace;
+ }
+
+#endif /* __OSL_STATFS_BLKSIZ */
+
+ 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;
+ }
+
+ pInfo->uMaxNameLength = 0;
+ if (uFieldMask & osl_VolumeInfo_Mask_MaxNameLength)
+ {
+ long nLen = pathconf(pszDirectory, _PC_NAME_MAX);
+ if (nLen > 0)
+ {
+ pInfo->uMaxNameLength = (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 = (sal_uInt32)nLen;
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxPathLength;
+ }
+ }
+
+#if defined(__OSL_STATFS_TYPENAME)
+
+ if (uFieldMask & osl_VolumeInfo_Mask_FileSystemName)
+ {
+ rtl_string2UString(
+ &(pInfo->ustrFileSystemName),
+ __OSL_STATFS_TYPENAME(sfs),
+ rtl_str_getLength(__OSL_STATFS_TYPENAME(sfs)),
+ osl_getThreadTextEncoding(),
+ OUSTRING_TO_OSTRING_CVTFLAGS);
+ OSL_ASSERT(pInfo->ustrFileSystemName != 0);
+
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_FileSystemName;
+ }
+
+#endif /* __OSL_STATFS_TYPENAME */
+
+ if (uFieldMask & osl_VolumeInfo_Mask_DeviceHandle)
+ {
+ /* FIXME: check also entries in mntent for the device
+ and fill it with correct values */
+
+ *pInfo->pDeviceHandle = osl_isFloppyDrive(pszDirectory);
+
+ if (*pInfo->pDeviceHandle)
+ {
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_DeviceHandle;
+ pInfo->uAttributes |= osl_Volume_Attribute_Removeable;
+ pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
+ }
+ }
+ return osl_File_E_None;
+}
+
+/******************************************************************************
+ *
+ * GENERIC FLOPPY FUNCTIONS
+ *
+ *****************************************************************************/
+
+
+/*****************************************
+ * osl_unmountVolumeDevice
+ ****************************************/
+
+oslFileError osl_unmountVolumeDevice( oslVolumeDeviceHandle Handle )
+{
+ oslFileError tErr = osl_File_E_NOSYS;
+
+ tErr = osl_unmountFloppy(Handle);
+
+ /* Perhaps current working directory is set to mount point */
+
+ if ( tErr )
+ {
+ sal_Char *pszHomeDir = getenv("HOME");
+
+ if ( pszHomeDir && strlen( pszHomeDir ) && 0 == chdir( pszHomeDir ) )
+ {
+ /* try again */
+
+ tErr = osl_unmountFloppy(Handle);
+
+ OSL_ENSURE( tErr, "osl_unmountvolumeDevice: CWD was set to volume mount point" );
+ }
+ }
+
+ return tErr;
+}
+
+/*****************************************
+ * osl_automountVolumeDevice
+ ****************************************/
+
+oslFileError osl_automountVolumeDevice( oslVolumeDeviceHandle Handle )
+{
+ oslFileError tErr = osl_File_E_NOSYS;
+
+ tErr = osl_mountFloppy(Handle);
+
+ return tErr;
+}
+
+/*****************************************
+ * osl_getVolumeDeviceMountPath
+ ****************************************/
+static rtl_uString* oslMakeUStrFromPsz(const sal_Char* pszStr, rtl_uString** ustrValid)
+{
+ rtl_string2UString(
+ ustrValid,
+ pszStr,
+ rtl_str_getLength( pszStr ),
+ osl_getThreadTextEncoding(),
+ OUSTRING_TO_OSTRING_CVTFLAGS );
+ OSL_ASSERT(*ustrValid != 0);
+
+ return *ustrValid;
+}
+
+oslFileError osl_getVolumeDeviceMountPath( oslVolumeDeviceHandle Handle, rtl_uString **pstrPath )
+{
+ oslVolumeDeviceHandleImpl* pItem = (oslVolumeDeviceHandleImpl*) Handle;
+ sal_Char Buffer[PATH_MAX];
+
+ Buffer[0] = '\0';
+
+ if ( pItem == 0 || pstrPath == 0 )
+ {
+ return osl_File_E_INVAL;
+ }
+
+ if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
+ {
+ return osl_File_E_INVAL;
+ }
+
+#ifdef DEBUG_OSL_FILE
+ fprintf(stderr,"Handle is:\n");
+ osl_printFloppyHandle(pItem);
+#endif
+
+ snprintf(Buffer, sizeof(Buffer), "file://%s", pItem->pszMountPoint);
+
+#ifdef DEBUG_OSL_FILE
+ fprintf(stderr,"Mount Point is: '%s'\n",Buffer);
+#endif
+
+ oslMakeUStrFromPsz(Buffer, pstrPath);
+
+ return osl_File_E_None;
+}
+
+/*****************************************
+ * osl_acquireVolumeDeviceHandle
+ ****************************************/
+
+oslFileError SAL_CALL osl_acquireVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
+{
+ oslVolumeDeviceHandleImpl* pItem =(oslVolumeDeviceHandleImpl*) Handle;
+
+ if ( pItem == 0 )
+ {
+ return osl_File_E_INVAL;
+ }
+
+ if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
+ {
+ return osl_File_E_INVAL;
+ }
+
+ ++pItem->RefCount;
+
+ return osl_File_E_None;
+}
+
+/*****************************************
+ * osl_releaseVolumeDeviceHandle
+ ****************************************/
+
+oslFileError osl_releaseVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
+{
+ oslVolumeDeviceHandleImpl* pItem =(oslVolumeDeviceHandleImpl*) Handle;
+
+ if ( pItem == 0 )
+ {
+ return osl_File_E_INVAL;
+ }
+
+ if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
+ {
+ return osl_File_E_INVAL;
+ }
+
+ --pItem->RefCount;
+
+ if ( pItem->RefCount == 0 )
+ {
+ rtl_freeMemory(pItem);
+ }
+
+ return osl_File_E_None;
+}
+
+#ifndef MACOSX
+
+/*****************************************
+ * osl_newVolumeDeviceHandleImpl
+ ****************************************/
+
+static oslVolumeDeviceHandleImpl* osl_newVolumeDeviceHandleImpl()
+{
+ oslVolumeDeviceHandleImpl* pHandle;
+ const size_t nSizeOfHandle = sizeof(oslVolumeDeviceHandleImpl);
+
+ pHandle = (oslVolumeDeviceHandleImpl*) rtl_allocateMemory (nSizeOfHandle);
+ if (pHandle != NULL)
+ {
+ pHandle->ident[0] = 'O';
+ pHandle->ident[1] = 'V';
+ pHandle->ident[2] = 'D';
+ pHandle->ident[3] = 'H';
+ pHandle->pszMountPoint[0] = '\0';
+ pHandle->pszFilePath[0] = '\0';
+ pHandle->pszDevice[0] = '\0';
+ pHandle->RefCount = 1;
+ }
+ return pHandle;
+}
+
+/*****************************************
+ * osl_freeVolumeDeviceHandleImpl
+ ****************************************/
+
+static void osl_freeVolumeDeviceHandleImpl (oslVolumeDeviceHandleImpl* pHandle)
+{
+ if (pHandle != NULL)
+ rtl_freeMemory (pHandle);
+}
+#endif
+
+/******************************************************************************
+ *
+ * SOLARIS FLOPPY FUNCTIONS
+ *
+ *****************************************************************************/
+
+#if defined(SOLARIS)
+/* compare a given devicename with the typical device names on a Solaris box */
+static sal_Bool
+osl_isAFloppyDevice (const char* pDeviceName)
+{
+ const char* pFloppyDevice [] = {
+ "/dev/fd", "/dev/rfd",
+ "/dev/diskette", "/dev/rdiskette",
+ "/vol/dev/diskette", "/vol/dev/rdiskette"
+ };
+
+ int i;
+ for (i = 0; i < (sizeof(pFloppyDevice)/sizeof(pFloppyDevice[0])); i++)
+ {
+ if (strncmp(pDeviceName, pFloppyDevice[i], strlen(pFloppyDevice[i])) == 0)
+ return sal_True;
+ }
+ return sal_False;
+}
+
+/* compare two directories whether the first may be a parent of the second. this
+ * does not realpath() resolving */
+static sal_Bool
+osl_isAParentDirectory (const char* pParentDir, const char* pSubDir)
+{
+ return strncmp(pParentDir, pSubDir, strlen(pParentDir)) == 0;
+}
+
+/* the name of the routine is obviously silly. But anyway create a
+ * oslVolumeDeviceHandle with correct mount point, device name and a resolved filepath
+ * only if pszPath points to file or directory on a floppy */
+static oslVolumeDeviceHandle
+osl_isFloppyDrive(const sal_Char* pszPath)
+{
+ FILE* pMountTab;
+ struct mnttab aMountEnt;
+ oslVolumeDeviceHandleImpl* pHandle;
+
+ if ((pHandle = osl_newVolumeDeviceHandleImpl()) == NULL)
+ {
+ return NULL;
+ }
+ if (realpath(pszPath, pHandle->pszFilePath) == NULL)
+ {
+ osl_freeVolumeDeviceHandleImpl (pHandle);
+ return NULL;
+ }
+ if ((pMountTab = fopen (MOUNTTAB, "r")) == NULL)
+ {
+ osl_freeVolumeDeviceHandleImpl (pHandle);
+ return NULL;
+ }
+
+ while (getmntent(pMountTab, &aMountEnt) == 0)
+ {
+ const char *pMountPoint = aMountEnt.mnt_mountp;
+ const char *pDevice = aMountEnt.mnt_special;
+ if ( osl_isAParentDirectory (aMountEnt.mnt_mountp, pHandle->pszFilePath)
+ && osl_isAFloppyDevice (aMountEnt.mnt_special))
+ {
+ /* skip the last item for it is the name of the disk */
+ char * pc = strrchr( aMountEnt.mnt_special, '/' );
+
+ if ( NULL != pc )
+ {
+ int len = pc - aMountEnt.mnt_special;
+
+ strncpy( pHandle->pszDevice, aMountEnt.mnt_special, len );
+ pHandle->pszDevice[len] = '\0';
+ }
+ else
+ {
+ /* #106048 use save str functions to avoid buffer overflows */
+ memset(pHandle->pszDevice, 0, sizeof(pHandle->pszDevice));
+ strncpy(pHandle->pszDevice, aMountEnt.mnt_special, sizeof(pHandle->pszDevice) - 1);
+ }
+
+ /* remember the mount point */
+ memset(pHandle->pszMountPoint, 0, sizeof(pHandle->pszMountPoint));
+ strncpy(pHandle->pszMountPoint, aMountEnt.mnt_mountp, sizeof(pHandle->pszMountPoint) - 1);
+
+ fclose (pMountTab);
+ return pHandle;
+ }
+ }
+
+ fclose (pMountTab);
+ osl_freeVolumeDeviceHandleImpl (pHandle);
+ return NULL;
+}
+
+static oslFileError osl_mountFloppy(oslVolumeDeviceHandle hFloppy)
+{
+ FILE* pMountTab;
+ struct mnttab aMountEnt;
+ oslVolumeDeviceHandleImpl* pHandle = (oslVolumeDeviceHandleImpl*) hFloppy;
+
+ int nRet=0;
+ sal_Char pszCmd[512] = "";
+
+ if ( pHandle == 0 )
+ return osl_File_E_INVAL;
+
+ /* FIXME: don't know what this is good for */
+ if ( pHandle->ident[0] != 'O' || pHandle->ident[1] != 'V' || pHandle->ident[2] != 'D' || pHandle->ident[3] != 'H' )
+ return osl_File_E_INVAL;
+
+ snprintf(pszCmd, sizeof(pszCmd), "eject -q %s > /dev/null 2>&1", pHandle->pszDevice);
+
+ nRet = system( pszCmd );
+
+ switch ( WEXITSTATUS(nRet) )
+ {
+ case 0:
+ {
+ /* lookup the device in mount tab again */
+ if ((pMountTab = fopen (MOUNTTAB, "r")) == NULL)
+ return osl_File_E_BUSY;
+
+ while (getmntent(pMountTab, &aMountEnt) == 0)
+ {
+ const char *pMountPoint = aMountEnt.mnt_mountp;
+ const char *pDevice = aMountEnt.mnt_special;
+ if ( 0 == strncmp( pHandle->pszDevice, aMountEnt.mnt_special, strlen(pHandle->pszDevice) ) )
+ {
+ memset(pHandle->pszMountPoint, 0, sizeof(pHandle->pszMountPoint));
+ strncpy (pHandle->pszMountPoint, aMountEnt.mnt_mountp, sizeof(pHandle->pszMountPoint) - 1);
+
+ fclose (pMountTab);
+ return osl_File_E_None;
+ }
+ }
+
+ fclose (pMountTab);
+ return osl_File_E_BUSY;
+ }
+ //break; // break not necessary here, see return statements before
+
+ case 1:
+ return osl_File_E_BUSY;
+
+ default:
+ break;
+ }
+
+ return osl_File_E_BUSY;
+}
+
+static oslFileError osl_unmountFloppy(oslVolumeDeviceHandle hFloppy)
+{
+// FILE* pMountTab;
+// struct mnttab aMountEnt;
+ oslVolumeDeviceHandleImpl* pHandle = (oslVolumeDeviceHandleImpl*) hFloppy;
+
+ int nRet=0;
+ sal_Char pszCmd[512] = "";
+
+ if ( pHandle == 0 )
+ return osl_File_E_INVAL;
+
+ /* FIXME: don't know what this is good for */
+ if ( pHandle->ident[0] != 'O' || pHandle->ident[1] != 'V' || pHandle->ident[2] != 'D' || pHandle->ident[3] != 'H' )
+ return osl_File_E_INVAL;
+
+ snprintf(pszCmd, sizeof(pszCmd), "eject %s > /dev/null 2>&1", pHandle->pszDevice);
+
+ nRet = system( pszCmd );
+
+ switch ( WEXITSTATUS(nRet) )
+ {
+ case 0:
+ {
+ FILE* pMountTab;
+ struct mnttab aMountEnt;
+
+ /* lookup if device is still in mount tab */
+ if ((pMountTab = fopen (MOUNTTAB, "r")) == NULL)
+ return osl_File_E_BUSY;
+
+ while (getmntent(pMountTab, &aMountEnt) == 0)
+ {
+ const char *pMountPoint = aMountEnt.mnt_mountp;
+ const char *pDevice = aMountEnt.mnt_special;
+ if ( 0 == strncmp( pHandle->pszDevice, aMountEnt.mnt_special, strlen(pHandle->pszDevice) ) )
+ {
+ fclose (pMountTab);
+ return osl_File_E_BUSY;
+ }
+ }
+
+ fclose (pMountTab);
+ pHandle->pszMountPoint[0] = 0;
+ return osl_File_E_None;
+ }
+
+ //break; //break not necessary, see return statements before
+
+ case 1:
+ return osl_File_E_NODEV;
+
+ case 4:
+ pHandle->pszMountPoint[0] = 0;
+ return osl_File_E_None;
+
+ default:
+ break;
+ }
+
+ return osl_File_E_BUSY;
+}
+
+#endif /* SOLARIS */
+
+/******************************************************************************
+ *
+ * LINUX FLOPPY FUNCTIONS
+ *
+ *****************************************************************************/
+
+#if defined(LINUX)
+static oslVolumeDeviceHandle
+osl_isFloppyDrive (const sal_Char* pszPath)
+{
+ oslVolumeDeviceHandleImpl* pItem = osl_newVolumeDeviceHandleImpl();
+ if (osl_getFloppyMountEntry(pszPath, pItem))
+ return (oslVolumeDeviceHandle) pItem;
+
+ osl_freeVolumeDeviceHandleImpl (pItem);
+ return 0;
+}
+#endif /* LINUX */
+
+#if defined(LINUX)
+static oslFileError osl_mountFloppy(oslVolumeDeviceHandle hFloppy)
+{
+ sal_Bool bRet = sal_False;
+ oslVolumeDeviceHandleImpl* pItem=0;
+ int nRet;
+ sal_Char pszCmd[PATH_MAX];
+ const sal_Char* pszMountProg = "mount";
+ sal_Char* pszSuDo = 0;
+ sal_Char* pszTmp = 0;
+
+ pszCmd[0] = '\0';
+
+#ifdef TRACE_OSL_FILE
+ fprintf(stderr,"In osl_mountFloppy\n");
+#endif
+
+ pItem = (oslVolumeDeviceHandleImpl*) hFloppy;
+
+ if ( pItem == 0 )
+ {
+#ifdef TRACE_OSL_FILE
+ fprintf(stderr,"Out osl_mountFloppy [pItem == 0]\n");
+#endif
+
+ return osl_File_E_INVAL;
+ }
+
+ if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
+ {
+#ifdef TRACE_OSL_FILE
+ fprintf(stderr,"Out osl_mountFloppy [invalid handle]\n");
+#endif
+ return osl_File_E_INVAL;
+ }
+
+ bRet = osl_isFloppyMounted(pItem);
+ if ( bRet == sal_True )
+ {
+#ifdef DEBUG_OSL_FILE
+ fprintf(stderr,"detected mounted floppy at '%s'\n",pItem->pszMountPoint);
+#endif
+ return osl_File_E_BUSY;
+ }
+
+ /* mfe: we can't use the mount(2) system call!!! */
+ /* even if we are root */
+ /* since mtab is not updated!!! */
+ /* but we need it to be updated */
+ /* some "magic" must be done */
+
+/* nRet = mount(pItem->pszDevice,pItem->pszMountPoint,0,0,0); */
+/* if ( nRet != 0 ) */
+/* { */
+/* nRet=errno; */
+/* #ifdef DEBUG_OSL_FILE */
+/* perror("mount"); */
+/* #endif */
+/* } */
+
+ pszTmp = getenv("SAL_MOUNT_MOUNTPROG");
+ if ( pszTmp != 0 )
+ {
+ pszMountProg=pszTmp;
+ }
+
+ pszTmp=getenv("SAL_MOUNT_SU_DO");
+ if ( pszTmp != 0 )
+ {
+ pszSuDo=pszTmp;
+ }
+
+ if ( pszSuDo != 0 )
+ {
+ snprintf(pszCmd, sizeof(pszCmd), "%s %s %s %s",pszSuDo,pszMountProg,pItem->pszDevice,pItem->pszMountPoint);
+ }
+ else
+ {
+ snprintf(pszCmd, sizeof(pszCmd), "%s %s",pszMountProg,pItem->pszMountPoint);
+ }
+
+
+#ifdef DEBUG_OSL_FILE
+ fprintf(stderr,"executing '%s'\n",pszCmd);
+#endif
+
+ nRet = system(pszCmd);
+
+#ifdef DEBUG_OSL_FILE
+ fprintf(stderr,"call returned '%i'\n",nRet);
+ fprintf(stderr,"exit status is '%i'\n", WEXITSTATUS(nRet));
+#endif
+
+
+ switch ( WEXITSTATUS(nRet) )
+ {
+ case 0:
+ nRet=0;
+ break;
+
+ case 2:
+ nRet=EPERM;
+ break;
+
+ case 4:
+ nRet=ENOENT;
+ break;
+
+ case 8:
+ nRet=EINTR;
+ break;
+
+ case 16:
+ nRet=EPERM;
+ break;
+
+ case 32:
+ nRet=EBUSY;
+ break;
+
+ case 64:
+ nRet=EAGAIN;
+ break;
+
+ default:
+ nRet=EBUSY;
+ break;
+ }
+
+ return ((0 == nRet) ? oslTranslateFileError(OSL_FET_SUCCESS, nRet) : oslTranslateFileError(OSL_FET_ERROR, nRet));
+}
+#endif /* LINUX */
+
+
+#if defined(LINUX)
+static oslFileError osl_unmountFloppy(oslVolumeDeviceHandle hFloppy)
+{
+ oslVolumeDeviceHandleImpl* pItem=0;
+ int nRet=0;
+ sal_Char pszCmd[PATH_MAX];
+ sal_Char* pszTmp = 0;
+ sal_Char* pszSuDo = 0;
+ const sal_Char* pszUmountProg = "umount";
+
+ pszCmd[0] = '\0';
+
+#ifdef TRACE_OSL_FILE
+ fprintf(stderr,"In osl_unmountFloppy\n");
+#endif
+
+ pItem = (oslVolumeDeviceHandleImpl*) hFloppy;
+
+ if ( pItem == 0 )
+ {
+#ifdef TRACE_OSL_FILE
+ fprintf(stderr,"Out osl_unmountFloppy [pItem==0]\n");
+#endif
+ return osl_File_E_INVAL;
+ }
+
+ if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
+ {
+#ifdef TRACE_OSL_FILE
+ fprintf(stderr,"Out osl_unmountFloppy [invalid handle]\n");
+#endif
+ return osl_File_E_INVAL;
+ }
+
+ /* mfe: we can't use the umount(2) system call!!! */
+ /* even if we are root */
+ /* since mtab is not updated!!! */
+ /* but we need it to be updated */
+ /* some "magic" must be done */
+
+/* nRet=umount(pItem->pszDevice); */
+/* if ( nRet != 0 ) */
+/* { */
+/* nRet = errno; */
+
+/* #ifdef DEBUG_OSL_FILE */
+/* perror("mount"); */
+/* #endif */
+/* } */
+
+
+ pszTmp = getenv("SAL_MOUNT_UMOUNTPROG");
+ if ( pszTmp != 0 )
+ {
+ pszUmountProg=pszTmp;
+ }
+
+ pszTmp = getenv("SAL_MOUNT_SU_DO");
+ if ( pszTmp != 0 )
+ {
+ pszSuDo=pszTmp;
+ }
+
+ if ( pszSuDo != 0 )
+ {
+ snprintf(pszCmd, sizeof(pszCmd), "%s %s %s",pszSuDo,pszUmountProg,pItem->pszMountPoint);
+ }
+ else
+ {
+ snprintf(pszCmd, sizeof(pszCmd), "%s %s",pszUmountProg,pItem->pszMountPoint);
+ }
+
+
+#ifdef DEBUG_OSL_FILE
+ fprintf(stderr,"executing '%s'\n",pszCmd);
+#endif
+
+ nRet = system(pszCmd);
+
+#ifdef DEBUG_OSL_FILE
+ fprintf(stderr,"call returned '%i'\n",nRet);
+ fprintf(stderr,"exit status is '%i'\n", WEXITSTATUS(nRet));
+#endif
+
+ switch ( WEXITSTATUS(nRet) )
+ {
+ case 0:
+ nRet=0;
+ break;
+
+ default:
+ nRet=EBUSY;
+ break;
+ }
+
+#ifdef TRACE_OSL_FILE
+ fprintf(stderr,"Out osl_unmountFloppy [ok]\n");
+#endif
+
+ return ((0 == nRet) ? oslTranslateFileError(OSL_FET_SUCCESS, nRet) : oslTranslateFileError(OSL_FET_ERROR, nRet));
+
+/* return osl_File_E_None;*/
+}
+
+#endif /* LINUX */
+
+#if defined(LINUX)
+static sal_Bool
+osl_getFloppyMountEntry(const sal_Char* pszPath, oslVolumeDeviceHandleImpl* pItem)
+{
+ struct mntent* pMountEnt;
+ FILE* pMountTab;
+
+ pMountTab = setmntent (MOUNTTAB, "r");
+ if (pMountTab == 0)
+ return sal_False;
+
+ while ((pMountEnt = getmntent(pMountTab)) != 0)
+ {
+ if ( strncmp(pMountEnt->mnt_dir, pszPath, strlen(pMountEnt->mnt_dir)) == 0
+ && strncmp(pMountEnt->mnt_fsname, "/dev/fd", strlen("/dev/fd")) == 0)
+ {
+ memset(pItem->pszMountPoint, 0, sizeof(pItem->pszMountPoint));
+ strncpy(pItem->pszMountPoint, pMountEnt->mnt_dir, sizeof(pItem->pszMountPoint) - 1);
+
+ memset(pItem->pszFilePath, 0, sizeof(pItem->pszFilePath));
+ strncpy(pItem->pszFilePath, pMountEnt->mnt_dir, sizeof(pItem->pszFilePath) - 1);
+
+ memset(pItem->pszDevice, 0, sizeof(pItem->pszDevice));
+ strncpy(pItem->pszDevice, pMountEnt->mnt_fsname, sizeof(pItem->pszDevice) - 1);
+
+ endmntent (pMountTab);
+ return sal_True;
+ }
+ }
+
+ endmntent (pMountTab);
+ return sal_False;
+}
+#endif /* LINUX */
+
+#if defined(LINUX)
+static sal_Bool
+osl_isFloppyMounted (oslVolumeDeviceHandleImpl* pDevice)
+{
+ oslVolumeDeviceHandleImpl aItem;
+
+ if ( osl_getFloppyMountEntry (pDevice->pszMountPoint, &aItem)
+ && strcmp (aItem.pszMountPoint, pDevice->pszMountPoint) == 0
+ && strcmp (aItem.pszDevice, pDevice->pszDevice) == 0)
+ {
+ return sal_True;
+ }
+ return sal_False;
+}
+#endif /* LINUX */
+
+/* NetBSD floppy functions have to be added here. Until we have done that,
+ * we use the MACOSX definitions for nonexistent floppy.
+ * */
+
+/******************************************************************************
+ *
+ * MAC OS X FLOPPY FUNCTIONS
+ *
+ *****************************************************************************/
+
+#if (defined(MACOSX) || defined(NETBSD) || defined(FREEBSD))
+static oslVolumeDeviceHandle osl_isFloppyDrive(const sal_Char* pszPath)
+{
+ return NULL;
+}
+#endif /* MACOSX */
+
+#if ( defined(MACOSX) || defined(NETBSD) || defined(FREEBSD))
+static oslFileError osl_mountFloppy(oslVolumeDeviceHandle hFloppy)
+{
+ return osl_File_E_BUSY;
+}
+#endif /* MACOSX */
+
+#if ( defined(MACOSX) || defined(NETBSD) || defined(FREEBSD))
+static oslFileError osl_unmountFloppy(oslVolumeDeviceHandle hFloppy)
+{
+ return osl_File_E_BUSY;
+}
+#endif /* MACOSX */
+
+#if ( defined(NETBSD) || defined(FREEBSD) )
+static sal_Bool osl_getFloppyMountEntry(const sal_Char* pszPath, oslVolumeDeviceHandleImpl* pItem)
+{
+ return sal_False;
+}
+#endif /* NETBSD || FREEBSD */
+
+#if ( defined(NETBSD) || defined(FREEBSD) )
+static sal_Bool osl_isFloppyMounted(oslVolumeDeviceHandleImpl* pDevice)
+{
+ return sal_False;
+}
+#endif /* NETBSD || FREEBSD */
+
+
+#ifdef DEBUG_OSL_FILE
+static void osl_printFloppyHandle(oslVolumeDeviceHandleImpl* pItem)
+{
+ if (pItem == 0 )
+ {
+ fprintf(stderr,"NULL Handle\n");
+ return;
+ }
+ if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
+ {
+#ifdef TRACE_OSL_FILE
+ fprintf(stderr,"Invalid Handle]\n");
+#endif
+ return;
+ }
+
+
+ fprintf(stderr,"MountPoint : '%s'\n",pItem->pszMountPoint);
+ fprintf(stderr,"FilePath : '%s'\n",pItem->pszFilePath);
+ fprintf(stderr,"Device : '%s'\n",pItem->pszDevice);
+
+ return;
+}
+#endif