blob: fe95271f6504d6a1b0df07c37a8f978df88704ac [file] [log] [blame]
/**************************************************************
*
* 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
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the 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 <sys/quota.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