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