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