xref: /aoo41x/main/sal/osl/unx/file_volume.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include "osl/file.h"
29 
30 #include "osl/diagnose.h"
31 #include "osl/thread.h"
32 #include "rtl/alloc.h"
33 
34 #include "file_error_transl.h"
35 #include "file_url.h"
36 #include "system.h"
37 
38 #include <errno.h>
39 #include <limits.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <unistd.h>
43 #include <sys/wait.h>
44 
45 #ifdef HAVE_STATFS_H
46 #undef HAVE_STATFS_H
47 #endif
48 
49 #if defined(LINUX) && defined(__FreeBSD_kernel__)
50 #undef LINUX
51 #define FREEBSD 1
52 #endif
53 
54 
55 #if defined(SOLARIS)
56 
57 #include <sys/mnttab.h>
58 #include <sys/statvfs.h>
59 #define  HAVE_STATFS_H
60 #include <sys/fs/ufs_quota.h>
61 static const sal_Char* MOUNTTAB="/etc/mnttab";
62 
63 #elif defined(LINUX)
64 
65 #include <mntent.h>
66 #include <sys/vfs.h>
67 #define  HAVE_STATFS_H
68 #include <sys/quota.h>
69 //#include <ctype.h>
70 static const sal_Char* MOUNTTAB="/etc/mtab";
71 
72 #elif defined(NETBSD) || defined(FREEBSD)
73 
74 #include <sys/param.h>
75 #include <sys/ucred.h>
76 #include <sys/mount.h>
77 #include <ufs/ufs/quota.h>
78 //#include <ctype.h>
79 #define  HAVE_STATFS_H
80 
81 /* No mounting table on *BSD
82  * This information is stored only in the kernel. */
83 /* static const sal_Char* MOUNTTAB="/etc/mtab"; */
84 
85 #elif defined(MACOSX)
86 
87 #include <ufs/ufs/quota.h>
88 //#include <ctype.h>
89 #include <sys/param.h>
90 #include <sys/mount.h>
91 #define HAVE_STATFS_H
92 // static const sal_Char* MOUNTTAB="/etc/mtab";
93 
94 #endif /* HAVE_STATFS_H */
95 
96 /************************************************************************
97  *   ToDo
98  *
99  *   - Fix: check for corresponding struct sizes in exported functions
100  *   - check size/use of oslVolumeDeviceHandle
101  *   - check size/use of oslVolumeInfo
102  ***********************************************************************/
103 /******************************************************************************
104  *
105  *                  Data Type Definition
106  *
107  ******************************************************************************/
108 
109 typedef struct _oslVolumeDeviceHandleImpl
110 {
111     sal_Char pszMountPoint[PATH_MAX];
112     sal_Char pszFilePath[PATH_MAX];
113     sal_Char pszDevice[PATH_MAX];
114     sal_Char ident[4];
115     sal_uInt32   RefCount;
116 } oslVolumeDeviceHandleImpl;
117 
118 /******************************************************************************
119  *
120  *                  'removeable device' aka floppy functions
121  *
122  *****************************************************************************/
123 
124 static oslVolumeDeviceHandle  osl_isFloppyDrive(const sal_Char* pszPath);
125 static oslFileError   osl_mountFloppy(oslVolumeDeviceHandle hFloppy);
126 static oslFileError   osl_unmountFloppy(oslVolumeDeviceHandle hFloppy);
127 
128 #if defined(SOLARIS)
129 static sal_Bool       osl_isFloppyMounted(sal_Char* pszPath, sal_Char* pszMountPath);
130 static sal_Bool       osl_getFloppyMountEntry(const sal_Char* pszPath, sal_Char* pBuffer);
131 static sal_Bool       osl_checkFloppyPath(sal_Char* pszPath, sal_Char* pszFilePath, sal_Char* pszDevicePath);
132 #endif /* SOLARIS */
133 
134 #if defined(LINUX)
135 static sal_Bool       osl_isFloppyMounted(oslVolumeDeviceHandleImpl* pDevice);
136 static sal_Bool       osl_getFloppyMountEntry(const sal_Char* pszPath, oslVolumeDeviceHandleImpl* pItem);
137 #endif /* LINUX */
138 
139 #ifdef DEBUG_OSL_FILE
140 static void           osl_printFloppyHandle(oslVolumeDeviceHandleImpl* hFloppy);
141 #endif /* DEBUG_OSL_FILE */
142 
143 /******************************************************************************
144  *
145  *                  C-String Function Declarations
146  *
147  *****************************************************************************/
148 
149 static oslFileError osl_psz_getVolumeInformation(const sal_Char* , oslVolumeInfo* pInfo, sal_uInt32 uFieldMask);
150 
151 /****************************************************************************/
152 /*	osl_getVolumeInformation */
153 /****************************************************************************/
154 
155 oslFileError osl_getVolumeInformation( rtl_uString* ustrDirectoryURL, oslVolumeInfo* pInfo, sal_uInt32 uFieldMask )
156 {
157     char path[PATH_MAX];
158     oslFileError eRet;
159 
160     OSL_ASSERT( ustrDirectoryURL );
161     OSL_ASSERT( pInfo );
162 
163     /* convert directory url to system path */
164     eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL );
165     if( eRet != osl_File_E_None )
166         return eRet;
167 
168 #ifdef MACOSX
169     if ( macxp_resolveAlias( path, PATH_MAX ) != 0 )
170       return oslTranslateFileError( OSL_FET_ERROR, errno );
171 #endif/* MACOSX */
172 
173     return osl_psz_getVolumeInformation( path, pInfo, uFieldMask);
174 }
175 
176 /******************************************************************************
177  *
178  *                  C-String Versions of Exported Module Functions
179  *
180  *****************************************************************************/
181 
182 #ifdef HAVE_STATFS_H
183 
184 #if defined(FREEBSD) || defined(NETBSD) || defined(MACOSX)
185 #   define __OSL_STATFS_STRUCT      			struct statfs
186 #   define __OSL_STATFS(dir, sfs)   			statfs((dir), (sfs))
187 #   define __OSL_STATFS_BLKSIZ(a)   			((sal_uInt64)((a).f_bsize))
188 #   define __OSL_STATFS_TYPENAME(a) 			((a).f_fstypename)
189 #   define __OSL_STATFS_ISREMOTE(a) 			(((a).f_type & MNT_LOCAL) == 0)
190 
191 /* always return true if queried for the properties of
192    the file system. If you think this is wrong under any
193    of the target platforms fix it!!!! */
194 #	define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a)	 (1)
195 #	define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) (1)
196 #endif /* FREEBSD || NETBSD || MACOSX */
197 
198 #if defined(LINUX)
199 #	define __OSL_NFS_SUPER_MAGIC				 0x6969
200 #	define __OSL_SMB_SUPER_MAGIC				 0x517B
201 #	define __OSL_MSDOS_SUPER_MAGIC  			 0x4d44
202 #	define __OSL_NTFS_SUPER_MAGIC				 0x5346544e
203 #   define __OSL_STATFS_STRUCT       		     struct statfs
204 #   define __OSL_STATFS(dir, sfs)    			 statfs((dir), (sfs))
205 #   define __OSL_STATFS_BLKSIZ(a)    			 ((sal_uInt64)((a).f_bsize))
206 #   define __OSL_STATFS_IS_NFS(a)     			 (__OSL_NFS_SUPER_MAGIC == (a).f_type)
207 #   define __OSL_STATFS_IS_SMB(a)     			 (__OSL_SMB_SUPER_MAGIC == (a).f_type)
208 #   define __OSL_STATFS_ISREMOTE(a)  			 (__OSL_STATFS_IS_NFS((a)) || __OSL_STATFS_IS_SMB((a)))
209 #	define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a)  ((__OSL_MSDOS_SUPER_MAGIC != (a).f_type) && (__OSL_NTFS_SUPER_MAGIC != (a).f_type))
210 #	define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) ((__OSL_MSDOS_SUPER_MAGIC != (a).f_type))
211 #endif /* LINUX */
212 
213 #if defined(SOLARIS)
214 #   define __OSL_STATFS_STRUCT          		 struct statvfs
215 #   define __OSL_STATFS(dir, sfs)	    		 statvfs((dir), (sfs))
216 #   define __OSL_STATFS_BLKSIZ(a)       		 ((sal_uInt64)((a).f_frsize))
217 #   define __OSL_STATFS_TYPENAME(a)     		 ((a).f_basetype)
218 #   define __OSL_STATFS_ISREMOTE(a)     		 (rtl_str_compare((a).f_basetype, "nfs") == 0)
219 
220 /* always return true if queried for the properties of
221    the file system. If you think this is wrong under any
222    of the target platforms fix it!!!! */
223 #	define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a)	 (1)
224 #	define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) (1)
225 #endif /* SOLARIS */
226 
227 #   define __OSL_STATFS_INIT(a) 	    (memset(&(a), 0, sizeof(__OSL_STATFS_STRUCT)))
228 
229 #else /* no statfs available */
230 
231 #   define __OSL_STATFS_STRUCT        			 struct dummy {int i;}
232 #   define __OSL_STATFS_INIT(a)       			 ((void)0)
233 #   define __OSL_STATFS(dir, sfs)     		     (1)
234 #   define __OSL_STATFS_ISREMOTE(sfs) 			 (0)
235 #	define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a)	 (1)
236 #	define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) (1)
237 #endif /* HAVE_STATFS_H */
238 
239 
240 static oslFileError osl_psz_getVolumeInformation (
241 	const sal_Char* pszDirectory, oslVolumeInfo* pInfo, sal_uInt32 uFieldMask)
242 {
243     __OSL_STATFS_STRUCT sfs;
244 
245     if (!pInfo)
246         return osl_File_E_INVAL;
247 
248     __OSL_STATFS_INIT(sfs);
249 
250     pInfo->uValidFields = 0;
251     pInfo->uAttributes  = 0;
252 
253 	if ((__OSL_STATFS(pszDirectory, &sfs)) < 0)
254 	{
255 		oslFileError result = oslTranslateFileError(OSL_FET_ERROR, errno);
256 		return (result);
257 	}
258 
259     /* FIXME: how to detect the kind of storage (fixed, cdrom, ...) */
260 	if (uFieldMask & osl_VolumeInfo_Mask_Attributes)
261 	{
262 	    if (__OSL_STATFS_ISREMOTE(sfs))
263 			pInfo->uAttributes  |= osl_Volume_Attribute_Remote;
264 
265 		pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
266 	}
267 
268 	if (uFieldMask & osl_VolumeInfo_Mask_FileSystemCaseHandling)
269 	{
270 		if (__OSL_STATFS_IS_CASE_SENSITIVE_FS(sfs))
271 			pInfo->uAttributes |= osl_Volume_Attribute_Case_Sensitive;
272 
273 		if (__OSL_STATFS_IS_CASE_PRESERVING_FS(sfs))
274 			pInfo->uAttributes |= osl_Volume_Attribute_Case_Is_Preserved;
275 
276 		pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
277 	}
278 
279 	pInfo->uTotalSpace = 0;
280     pInfo->uFreeSpace  = 0;
281     pInfo->uUsedSpace  = 0;
282 
283 #if defined(__OSL_STATFS_BLKSIZ)
284 
285 	if ((uFieldMask & osl_VolumeInfo_Mask_TotalSpace) ||
286 		(uFieldMask & osl_VolumeInfo_Mask_UsedSpace))
287 	{
288 		pInfo->uTotalSpace   = __OSL_STATFS_BLKSIZ(sfs);
289 		pInfo->uTotalSpace  *= (sal_uInt64)(sfs.f_blocks);
290 		pInfo->uValidFields |= osl_VolumeInfo_Mask_TotalSpace;
291 	}
292 
293 	if ((uFieldMask & osl_VolumeInfo_Mask_FreeSpace) ||
294 		(uFieldMask & osl_VolumeInfo_Mask_UsedSpace))
295 	{
296 		pInfo->uFreeSpace = __OSL_STATFS_BLKSIZ(sfs);
297 
298 		if (getuid() == 0)
299 			pInfo->uFreeSpace *= (sal_uInt64)(sfs.f_bfree);
300 		else
301 			pInfo->uFreeSpace *= (sal_uInt64)(sfs.f_bavail);
302 
303 		pInfo->uValidFields |= osl_VolumeInfo_Mask_FreeSpace;
304 	}
305 
306 #endif  /* __OSL_STATFS_BLKSIZ */
307 
308 	if ((pInfo->uValidFields & osl_VolumeInfo_Mask_TotalSpace) &&
309 		(pInfo->uValidFields & osl_VolumeInfo_Mask_FreeSpace ))
310 	{
311 		pInfo->uUsedSpace    = pInfo->uTotalSpace - pInfo->uFreeSpace;
312 		pInfo->uValidFields |= osl_VolumeInfo_Mask_UsedSpace;
313 	}
314 
315 	pInfo->uMaxNameLength = 0;
316 	if (uFieldMask & osl_VolumeInfo_Mask_MaxNameLength)
317 	{
318 		long nLen = pathconf(pszDirectory, _PC_NAME_MAX);
319 		if (nLen > 0)
320 		{
321 			pInfo->uMaxNameLength = (sal_uInt32)nLen;
322 			pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxNameLength;
323 		}
324 	}
325 
326 	pInfo->uMaxPathLength = 0;
327 	if (uFieldMask & osl_VolumeInfo_Mask_MaxPathLength)
328 	{
329 		long nLen = pathconf (pszDirectory, _PC_PATH_MAX);
330 		if (nLen > 0)
331 		{
332 			pInfo->uMaxPathLength  = (sal_uInt32)nLen;
333 			pInfo->uValidFields   |= osl_VolumeInfo_Mask_MaxPathLength;
334 		}
335 	}
336 
337 #if defined(__OSL_STATFS_TYPENAME)
338 
339 	if (uFieldMask & osl_VolumeInfo_Mask_FileSystemName)
340 	{
341     	rtl_string2UString(
342         	&(pInfo->ustrFileSystemName),
343         	__OSL_STATFS_TYPENAME(sfs),
344         	rtl_str_getLength(__OSL_STATFS_TYPENAME(sfs)),
345         	osl_getThreadTextEncoding(),
346         	OUSTRING_TO_OSTRING_CVTFLAGS);
347         OSL_ASSERT(pInfo->ustrFileSystemName != 0);
348 
349 		pInfo->uValidFields |= osl_VolumeInfo_Mask_FileSystemName;
350 	}
351 
352 #endif /* __OSL_STATFS_TYPENAME */
353 
354     if (uFieldMask & osl_VolumeInfo_Mask_DeviceHandle)
355     {
356         /* FIXME: check also entries in mntent for the device
357 		   and fill it with correct values */
358 
359         *pInfo->pDeviceHandle = osl_isFloppyDrive(pszDirectory);
360 
361         if (*pInfo->pDeviceHandle)
362         {
363             pInfo->uValidFields |= osl_VolumeInfo_Mask_DeviceHandle;
364             pInfo->uAttributes  |= osl_Volume_Attribute_Removeable;
365 			pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes;
366         }
367     }
368     return osl_File_E_None;
369 }
370 
371 /******************************************************************************
372  *
373  *                  GENERIC FLOPPY FUNCTIONS
374  *
375  *****************************************************************************/
376 
377 
378 /*****************************************
379  * osl_unmountVolumeDevice
380  ****************************************/
381 
382 oslFileError osl_unmountVolumeDevice( oslVolumeDeviceHandle Handle )
383 {
384     oslFileError tErr = osl_File_E_NOSYS;
385 
386     tErr = osl_unmountFloppy(Handle);
387 
388  	/* Perhaps current working directory is set to mount point */
389 
390  	if ( tErr )
391 	{
392 		sal_Char *pszHomeDir = getenv("HOME");
393 
394 		if ( pszHomeDir && strlen( pszHomeDir ) && 0 == chdir( pszHomeDir ) )
395 		{
396 			/* try again */
397 
398     		tErr = osl_unmountFloppy(Handle);
399 
400 			OSL_ENSURE( tErr, "osl_unmountvolumeDevice: CWD was set to volume mount point" );
401 		}
402 	}
403 
404     return tErr;
405 }
406 
407 /*****************************************
408  * osl_automountVolumeDevice
409  ****************************************/
410 
411 oslFileError osl_automountVolumeDevice( oslVolumeDeviceHandle Handle )
412 {
413     oslFileError tErr = osl_File_E_NOSYS;
414 
415     tErr = osl_mountFloppy(Handle);
416 
417     return tErr;
418 }
419 
420 /*****************************************
421  * osl_getVolumeDeviceMountPath
422  ****************************************/
423 static rtl_uString* oslMakeUStrFromPsz(const sal_Char* pszStr, rtl_uString** ustrValid)
424 {
425     rtl_string2UString(
426         ustrValid,
427         pszStr,
428         rtl_str_getLength( pszStr ),
429         osl_getThreadTextEncoding(),
430         OUSTRING_TO_OSTRING_CVTFLAGS );
431     OSL_ASSERT(*ustrValid != 0);
432 
433     return *ustrValid;
434 }
435 
436 oslFileError osl_getVolumeDeviceMountPath( oslVolumeDeviceHandle Handle, rtl_uString **pstrPath )
437 {
438     oslVolumeDeviceHandleImpl* pItem = (oslVolumeDeviceHandleImpl*) Handle;
439     sal_Char Buffer[PATH_MAX];
440 
441     Buffer[0] = '\0';
442 
443     if ( pItem == 0 || pstrPath == 0 )
444     {
445         return osl_File_E_INVAL;
446     }
447 
448     if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
449     {
450         return osl_File_E_INVAL;
451     }
452 
453 #ifdef DEBUG_OSL_FILE
454     fprintf(stderr,"Handle is:\n");
455     osl_printFloppyHandle(pItem);
456 #endif
457 
458 	snprintf(Buffer, sizeof(Buffer), "file://%s", pItem->pszMountPoint);
459 
460 #ifdef DEBUG_OSL_FILE
461     fprintf(stderr,"Mount Point is: '%s'\n",Buffer);
462 #endif
463 
464     oslMakeUStrFromPsz(Buffer, pstrPath);
465 
466     return osl_File_E_None;
467 }
468 
469 /*****************************************
470  * osl_acquireVolumeDeviceHandle
471  ****************************************/
472 
473 oslFileError SAL_CALL osl_acquireVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
474 {
475     oslVolumeDeviceHandleImpl* pItem =(oslVolumeDeviceHandleImpl*) Handle;
476 
477     if ( pItem == 0 )
478     {
479         return osl_File_E_INVAL;
480     }
481 
482     if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
483     {
484         return osl_File_E_INVAL;
485     }
486 
487     ++pItem->RefCount;
488 
489     return osl_File_E_None;
490 }
491 
492 /*****************************************
493  * osl_releaseVolumeDeviceHandle
494  ****************************************/
495 
496 oslFileError osl_releaseVolumeDeviceHandle( oslVolumeDeviceHandle Handle )
497 {
498     oslVolumeDeviceHandleImpl* pItem =(oslVolumeDeviceHandleImpl*) Handle;
499 
500     if ( pItem == 0 )
501     {
502         return osl_File_E_INVAL;
503     }
504 
505     if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
506     {
507         return osl_File_E_INVAL;
508     }
509 
510     --pItem->RefCount;
511 
512     if ( pItem->RefCount == 0 )
513     {
514         rtl_freeMemory(pItem);
515     }
516 
517     return osl_File_E_None;
518 }
519 
520 #ifndef MACOSX
521 
522 /*****************************************
523  * osl_newVolumeDeviceHandleImpl
524  ****************************************/
525 
526 static oslVolumeDeviceHandleImpl* osl_newVolumeDeviceHandleImpl()
527 {
528     oslVolumeDeviceHandleImpl* pHandle;
529     const size_t               nSizeOfHandle = sizeof(oslVolumeDeviceHandleImpl);
530 
531     pHandle = (oslVolumeDeviceHandleImpl*) rtl_allocateMemory (nSizeOfHandle);
532     if (pHandle != NULL)
533     {
534         pHandle->ident[0]         = 'O';
535         pHandle->ident[1]         = 'V';
536         pHandle->ident[2]         = 'D';
537         pHandle->ident[3]         = 'H';
538         pHandle->pszMountPoint[0] = '\0';
539         pHandle->pszFilePath[0]   = '\0';
540         pHandle->pszDevice[0]     = '\0';
541         pHandle->RefCount         = 1;
542     }
543     return pHandle;
544 }
545 
546 /*****************************************
547  * osl_freeVolumeDeviceHandleImpl
548  ****************************************/
549 
550 static void osl_freeVolumeDeviceHandleImpl (oslVolumeDeviceHandleImpl* pHandle)
551 {
552     if (pHandle != NULL)
553         rtl_freeMemory (pHandle);
554 }
555 #endif
556 
557 /******************************************************************************
558  *
559  *                  SOLARIS FLOPPY FUNCTIONS
560  *
561  *****************************************************************************/
562 
563 #if defined(SOLARIS)
564 /* compare a given devicename with the typical device names on a Solaris box */
565 static sal_Bool
566 osl_isAFloppyDevice (const char* pDeviceName)
567 {
568     const char* pFloppyDevice [] = {
569         "/dev/fd",           "/dev/rfd",
570         "/dev/diskette",     "/dev/rdiskette",
571         "/vol/dev/diskette", "/vol/dev/rdiskette"
572     };
573 
574     int i;
575     for (i = 0; i < (sizeof(pFloppyDevice)/sizeof(pFloppyDevice[0])); i++)
576     {
577         if (strncmp(pDeviceName, pFloppyDevice[i], strlen(pFloppyDevice[i])) == 0)
578             return sal_True;
579     }
580     return sal_False;
581 }
582 
583 /* compare two directories whether the first may be a parent of the second. this
584  * does not realpath() resolving */
585 static sal_Bool
586 osl_isAParentDirectory (const char* pParentDir, const char* pSubDir)
587 {
588     return strncmp(pParentDir, pSubDir, strlen(pParentDir)) == 0;
589 }
590 
591 /* the name of the routine is obviously silly. But anyway create a
592  * oslVolumeDeviceHandle with correct mount point, device name and a resolved filepath
593  * only if pszPath points to file or directory on a floppy */
594 static oslVolumeDeviceHandle
595 osl_isFloppyDrive(const sal_Char* pszPath)
596 {
597     FILE*                       pMountTab;
598     struct mnttab               aMountEnt;
599     oslVolumeDeviceHandleImpl*  pHandle;
600 
601     if ((pHandle = osl_newVolumeDeviceHandleImpl()) == NULL)
602     {
603         return NULL;
604     }
605     if (realpath(pszPath, pHandle->pszFilePath) == NULL)
606     {
607         osl_freeVolumeDeviceHandleImpl (pHandle);
608         return NULL;
609     }
610     if ((pMountTab = fopen (MOUNTTAB, "r")) == NULL)
611     {
612         osl_freeVolumeDeviceHandleImpl (pHandle);
613         return NULL;
614     }
615 
616     while (getmntent(pMountTab, &aMountEnt) == 0)
617     {
618         const char *pMountPoint = aMountEnt.mnt_mountp;
619         const char *pDevice     = aMountEnt.mnt_special;
620         if (   osl_isAParentDirectory (aMountEnt.mnt_mountp, pHandle->pszFilePath)
621             && osl_isAFloppyDevice    (aMountEnt.mnt_special))
622         {
623             /* skip the last item for it is the name of the disk */
624             char * pc = strrchr( aMountEnt.mnt_special, '/' );
625 
626             if ( NULL != pc )
627             {
628                 int len = pc - aMountEnt.mnt_special;
629 
630                 strncpy( pHandle->pszDevice, aMountEnt.mnt_special, len );
631                 pHandle->pszDevice[len] = '\0';
632             }
633             else
634 			{
635 				/* #106048 use save str functions to avoid buffer overflows */
636 				memset(pHandle->pszDevice, 0, sizeof(pHandle->pszDevice));
637 				strncpy(pHandle->pszDevice, aMountEnt.mnt_special, sizeof(pHandle->pszDevice) - 1);
638             }
639 
640             /* remember the mount point */
641 			memset(pHandle->pszMountPoint, 0, sizeof(pHandle->pszMountPoint));
642 			strncpy(pHandle->pszMountPoint, aMountEnt.mnt_mountp, sizeof(pHandle->pszMountPoint) - 1);
643 
644             fclose (pMountTab);
645             return pHandle;
646         }
647     }
648 
649     fclose (pMountTab);
650     osl_freeVolumeDeviceHandleImpl (pHandle);
651     return NULL;
652 }
653 
654 static oslFileError osl_mountFloppy(oslVolumeDeviceHandle hFloppy)
655 {
656     FILE*                       pMountTab;
657     struct mnttab               aMountEnt;
658     oslVolumeDeviceHandleImpl*  pHandle = (oslVolumeDeviceHandleImpl*) hFloppy;
659 
660     int nRet=0;
661     sal_Char pszCmd[512] = "";
662 
663     if ( pHandle == 0 )
664         return osl_File_E_INVAL;
665 
666     /* FIXME: don't know what this is good for */
667     if ( pHandle->ident[0] != 'O' || pHandle->ident[1] != 'V' || pHandle->ident[2] != 'D' || pHandle->ident[3] != 'H' )
668         return osl_File_E_INVAL;
669 
670     snprintf(pszCmd, sizeof(pszCmd), "eject -q %s > /dev/null 2>&1", pHandle->pszDevice);
671 
672     nRet = system( pszCmd );
673 
674     switch ( WEXITSTATUS(nRet) )
675     {
676     case 0:
677         {
678             /* lookup the device in mount tab again */
679             if ((pMountTab = fopen (MOUNTTAB, "r")) == NULL)
680                 return osl_File_E_BUSY;
681 
682             while (getmntent(pMountTab, &aMountEnt) == 0)
683             {
684                 const char *pMountPoint = aMountEnt.mnt_mountp;
685                 const char *pDevice     = aMountEnt.mnt_special;
686                 if ( 0 == strncmp( pHandle->pszDevice, aMountEnt.mnt_special, strlen(pHandle->pszDevice) ) )
687                 {
688 					memset(pHandle->pszMountPoint, 0, sizeof(pHandle->pszMountPoint));
689                     strncpy (pHandle->pszMountPoint, aMountEnt.mnt_mountp, sizeof(pHandle->pszMountPoint) - 1);
690 
691                     fclose (pMountTab);
692                     return osl_File_E_None;
693                 }
694             }
695 
696             fclose (pMountTab);
697             return osl_File_E_BUSY;
698         }
699         //break; // break not necessary here, see return statements before
700 
701     case 1:
702         return osl_File_E_BUSY;
703 
704     default:
705         break;
706     }
707 
708     return osl_File_E_BUSY;
709 }
710 
711 static oslFileError osl_unmountFloppy(oslVolumeDeviceHandle hFloppy)
712 {
713 //    FILE*                       pMountTab;
714 //    struct mnttab               aMountEnt;
715     oslVolumeDeviceHandleImpl*  pHandle = (oslVolumeDeviceHandleImpl*) hFloppy;
716 
717     int nRet=0;
718     sal_Char pszCmd[512] = "";
719 
720     if ( pHandle == 0 )
721         return osl_File_E_INVAL;
722 
723     /* FIXME: don't know what this is good for */
724     if ( pHandle->ident[0] != 'O' || pHandle->ident[1] != 'V' || pHandle->ident[2] != 'D' || pHandle->ident[3] != 'H' )
725         return osl_File_E_INVAL;
726 
727     snprintf(pszCmd, sizeof(pszCmd), "eject %s > /dev/null 2>&1", pHandle->pszDevice);
728 
729     nRet = system( pszCmd );
730 
731     switch ( WEXITSTATUS(nRet) )
732     {
733     case 0:
734         {
735             FILE*         pMountTab;
736             struct mnttab aMountEnt;
737 
738             /* lookup if device is still in mount tab */
739             if ((pMountTab = fopen (MOUNTTAB, "r")) == NULL)
740                 return osl_File_E_BUSY;
741 
742             while (getmntent(pMountTab, &aMountEnt) == 0)
743             {
744                 const char *pMountPoint = aMountEnt.mnt_mountp;
745                 const char *pDevice     = aMountEnt.mnt_special;
746                 if ( 0 == strncmp( pHandle->pszDevice, aMountEnt.mnt_special, strlen(pHandle->pszDevice) ) )
747                 {
748                     fclose (pMountTab);
749                     return osl_File_E_BUSY;
750                 }
751             }
752 
753             fclose (pMountTab);
754             pHandle->pszMountPoint[0] = 0;
755             return osl_File_E_None;
756         }
757 
758         //break; //break not necessary, see return statements before
759 
760     case 1:
761         return osl_File_E_NODEV;
762 
763     case 4:
764         pHandle->pszMountPoint[0] = 0;
765         return osl_File_E_None;
766 
767     default:
768         break;
769     }
770 
771     return osl_File_E_BUSY;
772 }
773 
774 #endif /* SOLARIS */
775 
776 /******************************************************************************
777  *
778  *                  LINUX FLOPPY FUNCTIONS
779  *
780  *****************************************************************************/
781 
782 #if defined(LINUX)
783 static oslVolumeDeviceHandle
784 osl_isFloppyDrive (const sal_Char* pszPath)
785 {
786     oslVolumeDeviceHandleImpl* pItem = osl_newVolumeDeviceHandleImpl();
787     if (osl_getFloppyMountEntry(pszPath, pItem))
788         return (oslVolumeDeviceHandle) pItem;
789 
790     osl_freeVolumeDeviceHandleImpl (pItem);
791     return 0;
792 }
793 #endif /* LINUX */
794 
795 #if defined(LINUX)
796 static oslFileError osl_mountFloppy(oslVolumeDeviceHandle hFloppy)
797 {
798     sal_Bool bRet = sal_False;
799     oslVolumeDeviceHandleImpl* pItem=0;
800     int nRet;
801     sal_Char  pszCmd[PATH_MAX];
802     const sal_Char* pszMountProg = "mount";
803     sal_Char* pszSuDo = 0;
804     sal_Char* pszTmp = 0;
805 
806     pszCmd[0] = '\0';
807 
808 #ifdef TRACE_OSL_FILE
809     fprintf(stderr,"In  osl_mountFloppy\n");
810 #endif
811 
812     pItem = (oslVolumeDeviceHandleImpl*) hFloppy;
813 
814     if ( pItem == 0 )
815     {
816 #ifdef TRACE_OSL_FILE
817         fprintf(stderr,"Out osl_mountFloppy [pItem == 0]\n");
818 #endif
819 
820         return osl_File_E_INVAL;
821     }
822 
823     if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
824     {
825 #ifdef TRACE_OSL_FILE
826         fprintf(stderr,"Out osl_mountFloppy [invalid handle]\n");
827 #endif
828         return osl_File_E_INVAL;
829     }
830 
831     bRet = osl_isFloppyMounted(pItem);
832     if ( bRet == sal_True )
833     {
834 #ifdef DEBUG_OSL_FILE
835         fprintf(stderr,"detected mounted floppy at '%s'\n",pItem->pszMountPoint);
836 #endif
837         return osl_File_E_BUSY;
838     }
839 
840     /* mfe: we can't use the mount(2) system call!!!   */
841     /*      even if we are root                        */
842     /*      since mtab is not updated!!!               */
843     /*      but we need it to be updated               */
844     /*      some "magic" must be done                  */
845 
846 /*      nRet = mount(pItem->pszDevice,pItem->pszMountPoint,0,0,0); */
847 /*      if ( nRet != 0 ) */
848 /*      { */
849 /*          nRet=errno; */
850 /*  #ifdef DEBUG_OSL_FILE */
851 /*          perror("mount"); */
852 /*  #endif */
853 /*      } */
854 
855     pszTmp = getenv("SAL_MOUNT_MOUNTPROG");
856     if ( pszTmp != 0 )
857     {
858         pszMountProg=pszTmp;
859     }
860 
861     pszTmp=getenv("SAL_MOUNT_SU_DO");
862     if ( pszTmp != 0 )
863     {
864         pszSuDo=pszTmp;
865     }
866 
867     if ( pszSuDo != 0 )
868     {
869         snprintf(pszCmd, sizeof(pszCmd), "%s %s %s %s",pszSuDo,pszMountProg,pItem->pszDevice,pItem->pszMountPoint);
870     }
871     else
872     {
873         snprintf(pszCmd, sizeof(pszCmd), "%s %s",pszMountProg,pItem->pszMountPoint);
874     }
875 
876 
877 #ifdef DEBUG_OSL_FILE
878     fprintf(stderr,"executing '%s'\n",pszCmd);
879 #endif
880 
881     nRet = system(pszCmd);
882 
883 #ifdef DEBUG_OSL_FILE
884     fprintf(stderr,"call returned '%i'\n",nRet);
885     fprintf(stderr,"exit status is '%i'\n", WEXITSTATUS(nRet));
886 #endif
887 
888 
889     switch ( WEXITSTATUS(nRet) )
890     {
891     case 0:
892         nRet=0;
893         break;
894 
895     case 2:
896         nRet=EPERM;
897         break;
898 
899     case 4:
900         nRet=ENOENT;
901         break;
902 
903     case 8:
904         nRet=EINTR;
905         break;
906 
907     case 16:
908         nRet=EPERM;
909         break;
910 
911     case 32:
912         nRet=EBUSY;
913         break;
914 
915     case 64:
916         nRet=EAGAIN;
917         break;
918 
919     default:
920         nRet=EBUSY;
921         break;
922     }
923 
924     return ((0 == nRet) ? oslTranslateFileError(OSL_FET_SUCCESS, nRet) : oslTranslateFileError(OSL_FET_ERROR, nRet));
925 }
926 #endif /* LINUX */
927 
928 
929 #if defined(LINUX)
930 static oslFileError osl_unmountFloppy(oslVolumeDeviceHandle hFloppy)
931 {
932     oslVolumeDeviceHandleImpl* pItem=0;
933     int nRet=0;
934     sal_Char pszCmd[PATH_MAX];
935     sal_Char* pszTmp = 0;
936     sal_Char* pszSuDo = 0;
937     const sal_Char* pszUmountProg = "umount";
938 
939     pszCmd[0] = '\0';
940 
941 #ifdef TRACE_OSL_FILE
942     fprintf(stderr,"In  osl_unmountFloppy\n");
943 #endif
944 
945     pItem = (oslVolumeDeviceHandleImpl*) hFloppy;
946 
947     if ( pItem == 0 )
948     {
949 #ifdef TRACE_OSL_FILE
950         fprintf(stderr,"Out osl_unmountFloppy [pItem==0]\n");
951 #endif
952         return osl_File_E_INVAL;
953     }
954 
955     if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
956     {
957 #ifdef TRACE_OSL_FILE
958         fprintf(stderr,"Out osl_unmountFloppy [invalid handle]\n");
959 #endif
960         return osl_File_E_INVAL;
961     }
962 
963     /* mfe: we can't use the umount(2) system call!!!  */
964     /*      even if we are root                        */
965     /*      since mtab is not updated!!!               */
966     /*      but we need it to be updated               */
967     /*      some "magic" must be done                  */
968 
969 /*      nRet=umount(pItem->pszDevice); */
970 /*      if ( nRet != 0 ) */
971 /*      { */
972 /*          nRet = errno; */
973 
974 /*  #ifdef DEBUG_OSL_FILE */
975 /*          perror("mount"); */
976 /*  #endif */
977 /*      } */
978 
979 
980     pszTmp = getenv("SAL_MOUNT_UMOUNTPROG");
981     if ( pszTmp != 0 )
982     {
983         pszUmountProg=pszTmp;
984     }
985 
986     pszTmp = getenv("SAL_MOUNT_SU_DO");
987     if ( pszTmp != 0 )
988     {
989         pszSuDo=pszTmp;
990     }
991 
992     if ( pszSuDo != 0 )
993     {
994         snprintf(pszCmd, sizeof(pszCmd), "%s %s %s",pszSuDo,pszUmountProg,pItem->pszMountPoint);
995     }
996     else
997     {
998         snprintf(pszCmd, sizeof(pszCmd), "%s %s",pszUmountProg,pItem->pszMountPoint);
999     }
1000 
1001 
1002 #ifdef DEBUG_OSL_FILE
1003     fprintf(stderr,"executing '%s'\n",pszCmd);
1004 #endif
1005 
1006     nRet = system(pszCmd);
1007 
1008 #ifdef DEBUG_OSL_FILE
1009     fprintf(stderr,"call returned '%i'\n",nRet);
1010     fprintf(stderr,"exit status is '%i'\n", WEXITSTATUS(nRet));
1011 #endif
1012 
1013     switch ( WEXITSTATUS(nRet) )
1014     {
1015     case 0:
1016         nRet=0;
1017         break;
1018 
1019     default:
1020         nRet=EBUSY;
1021         break;
1022     }
1023 
1024 #ifdef TRACE_OSL_FILE
1025     fprintf(stderr,"Out osl_unmountFloppy [ok]\n");
1026 #endif
1027 
1028     return ((0 == nRet) ? oslTranslateFileError(OSL_FET_SUCCESS, nRet) : oslTranslateFileError(OSL_FET_ERROR, nRet));
1029 
1030 /*    return osl_File_E_None;*/
1031 }
1032 
1033 #endif /* LINUX */
1034 
1035 #if defined(LINUX)
1036 static sal_Bool
1037 osl_getFloppyMountEntry(const sal_Char* pszPath, oslVolumeDeviceHandleImpl* pItem)
1038 {
1039     struct mntent* pMountEnt;
1040     FILE*          pMountTab;
1041 
1042     pMountTab = setmntent (MOUNTTAB, "r");
1043     if (pMountTab == 0)
1044         return sal_False;
1045 
1046     while ((pMountEnt = getmntent(pMountTab)) != 0)
1047     {
1048         if (   strncmp(pMountEnt->mnt_dir,    pszPath,   strlen(pMountEnt->mnt_dir)) == 0
1049             && strncmp(pMountEnt->mnt_fsname, "/dev/fd", strlen("/dev/fd")) == 0)
1050         {
1051 			memset(pItem->pszMountPoint, 0, sizeof(pItem->pszMountPoint));
1052             strncpy(pItem->pszMountPoint, pMountEnt->mnt_dir, sizeof(pItem->pszMountPoint) - 1);
1053 
1054 			memset(pItem->pszFilePath, 0, sizeof(pItem->pszFilePath));
1055             strncpy(pItem->pszFilePath, pMountEnt->mnt_dir, sizeof(pItem->pszFilePath) - 1);
1056 
1057 			memset(pItem->pszDevice, 0, sizeof(pItem->pszDevice));
1058             strncpy(pItem->pszDevice, pMountEnt->mnt_fsname, sizeof(pItem->pszDevice) - 1);
1059 
1060             endmntent (pMountTab);
1061             return sal_True;
1062         }
1063     }
1064 
1065     endmntent (pMountTab);
1066     return sal_False;
1067 }
1068 #endif /* LINUX */
1069 
1070 #if defined(LINUX)
1071 static sal_Bool
1072 osl_isFloppyMounted (oslVolumeDeviceHandleImpl* pDevice)
1073 {
1074     oslVolumeDeviceHandleImpl aItem;
1075 
1076     if (   osl_getFloppyMountEntry (pDevice->pszMountPoint, &aItem)
1077         && strcmp (aItem.pszMountPoint, pDevice->pszMountPoint) == 0
1078         && strcmp (aItem.pszDevice,     pDevice->pszDevice) == 0)
1079     {
1080         return sal_True;
1081     }
1082     return sal_False;
1083 }
1084 #endif /* LINUX */
1085 
1086 /* NetBSD floppy functions have to be added here. Until we have done that,
1087  * we use the MACOSX definitions for nonexistent floppy.
1088  * */
1089 
1090 /******************************************************************************
1091  *
1092  *                  MAC OS X FLOPPY FUNCTIONS
1093  *
1094  *****************************************************************************/
1095 
1096 #if (defined(MACOSX) || defined(NETBSD) || defined(FREEBSD))
1097 static oslVolumeDeviceHandle osl_isFloppyDrive(const sal_Char* pszPath)
1098 {
1099     return NULL;
1100 }
1101 #endif /* MACOSX */
1102 
1103 #if ( defined(MACOSX) || defined(NETBSD) || defined(FREEBSD))
1104 static oslFileError osl_mountFloppy(oslVolumeDeviceHandle hFloppy)
1105 {
1106     return osl_File_E_BUSY;
1107 }
1108 #endif /* MACOSX */
1109 
1110 #if ( defined(MACOSX) || defined(NETBSD) || defined(FREEBSD))
1111 static oslFileError osl_unmountFloppy(oslVolumeDeviceHandle hFloppy)
1112 {
1113     return osl_File_E_BUSY;
1114 }
1115 #endif /* MACOSX */
1116 
1117 #if ( defined(NETBSD) || defined(FREEBSD) )
1118 static sal_Bool osl_getFloppyMountEntry(const sal_Char* pszPath, oslVolumeDeviceHandleImpl* pItem)
1119 {
1120     return sal_False;
1121 }
1122 #endif /* NETBSD || FREEBSD */
1123 
1124 #if ( defined(NETBSD) || defined(FREEBSD) )
1125 static sal_Bool osl_isFloppyMounted(oslVolumeDeviceHandleImpl* pDevice)
1126 {
1127     return sal_False;
1128 }
1129 #endif /* NETBSD || FREEBSD */
1130 
1131 
1132 #ifdef DEBUG_OSL_FILE
1133 static void osl_printFloppyHandle(oslVolumeDeviceHandleImpl* pItem)
1134 {
1135     if (pItem == 0 )
1136     {
1137         fprintf(stderr,"NULL Handle\n");
1138         return;
1139     }
1140     if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' )
1141     {
1142 #ifdef TRACE_OSL_FILE
1143         fprintf(stderr,"Invalid Handle]\n");
1144 #endif
1145         return;
1146     }
1147 
1148 
1149     fprintf(stderr,"MountPoint : '%s'\n",pItem->pszMountPoint);
1150     fprintf(stderr,"FilePath   : '%s'\n",pItem->pszFilePath);
1151     fprintf(stderr,"Device     : '%s'\n",pItem->pszDevice);
1152 
1153     return;
1154 }
1155 #endif
1156