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