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 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 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 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 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 ****************************************/ 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 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 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 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 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 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 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 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 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 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 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 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) 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) 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 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 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)) 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)) 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)) 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) ) 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) ) 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 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