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