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