/************************************************************** * * 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 #include #include #include #include #include #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 #include #define HAVE_STATFS_H #include static const sal_Char* MOUNTTAB="/etc/mnttab"; #elif defined(LINUX) #include #include #define HAVE_STATFS_H #include //#include static const sal_Char* MOUNTTAB="/etc/mtab"; #elif defined(NETBSD) || defined(FREEBSD) #include #include #include #include //#include #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 #include #include #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