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 29 /************************************************************************ 30 * ToDo 31 * 32 * Fix osl_getCanonicalName 33 * 34 * - Fix: check for corresponding struct sizes in exported functions 35 * - check size/use of oslDirectory 36 * - check size/use of oslDirectoryItem 37 * - check size/use of oslFileStatus 38 * - check size/use of oslVolumeDeviceHandle 39 * - check size/use of oslVolumeInfo 40 * - check size/use of oslFileHandle 41 ***********************************************************************/ 42 43 #define INCL_DOSDEVIOCTL // OS2 device definitions 44 45 #include "system.h" 46 #include <rtl/alloc.h> 47 48 #include "osl/file.hxx" 49 50 51 #include <sal/types.h> 52 #include <osl/thread.h> 53 #include <osl/diagnose.h> 54 #include "file_error_transl.h" 55 #include <osl/time.h> 56 57 #ifndef _FILE_URL_H_ 58 #include "file_url.h" 59 #endif 60 61 #include "file_path_helper.hxx" 62 #include "uunxapi.hxx" 63 64 #ifndef _STRING_H_ 65 #include <string.h> 66 #endif 67 68 #ifndef _CTYPE_H_ 69 #include <ctype.h> 70 #endif 71 72 #ifndef _WCHAR_H_ 73 #include <wchar.h> 74 #endif 75 76 #if OSL_DEBUG_LEVEL > 1 77 extern void debug_ustring(rtl_uString*); 78 #endif 79 80 81 #ifdef DEBUG_OSL_FILE 82 # define PERROR( a, b ) perror( a ); fprintf( stderr, b ) 83 #else 84 # define PERROR( a, b ) 85 #endif 86 87 extern "C" oslFileHandle osl_createFileHandleFromFD( int fd ); 88 89 struct errentry errtable[] = { 90 { NO_ERROR, osl_File_E_None }, /* 0 */ 91 { ERROR_INVALID_FUNCTION, osl_File_E_INVAL }, /* 1 */ 92 { ERROR_FILE_NOT_FOUND, osl_File_E_NOENT }, /* 2 */ 93 { ERROR_PATH_NOT_FOUND, osl_File_E_NOENT }, /* 3 */ 94 { ERROR_TOO_MANY_OPEN_FILES, osl_File_E_MFILE }, /* 4 */ 95 { ERROR_ACCESS_DENIED, osl_File_E_ACCES }, /* 5 */ 96 { ERROR_INVALID_HANDLE, osl_File_E_BADF }, /* 6 */ 97 { ERROR_ARENA_TRASHED, osl_File_E_NOMEM }, /* 7 */ 98 { ERROR_NOT_ENOUGH_MEMORY, osl_File_E_NOMEM }, /* 8 */ 99 { ERROR_INVALID_BLOCK, osl_File_E_NOMEM }, /* 9 */ 100 { ERROR_BAD_ENVIRONMENT, osl_File_E_2BIG }, /* 10 */ 101 { ERROR_BAD_FORMAT, osl_File_E_NOEXEC }, /* 11 */ 102 { ERROR_INVALID_ACCESS, osl_File_E_INVAL }, /* 12 */ 103 { ERROR_INVALID_DATA, osl_File_E_INVAL }, /* 13 */ 104 { ERROR_INVALID_DRIVE, osl_File_E_NOENT }, /* 15 */ 105 { ERROR_CURRENT_DIRECTORY, osl_File_E_ACCES }, /* 16 */ 106 { ERROR_NOT_SAME_DEVICE, osl_File_E_XDEV }, /* 17 */ 107 { ERROR_NO_MORE_FILES, osl_File_E_NOENT }, /* 18 */ 108 { ERROR_NOT_READY, osl_File_E_NOTREADY }, /* 21 */ 109 { ERROR_LOCK_VIOLATION, osl_File_E_ACCES }, /* 33 */ 110 { ERROR_BAD_NETPATH, osl_File_E_NOENT }, /* 53 */ 111 { ERROR_NETWORK_ACCESS_DENIED, osl_File_E_ACCES }, /* 65 */ 112 { ERROR_BAD_NET_NAME, osl_File_E_NOENT }, /* 67 */ 113 { ERROR_FILE_EXISTS, osl_File_E_EXIST }, /* 80 */ 114 { ERROR_CANNOT_MAKE, osl_File_E_ACCES }, /* 82 */ 115 { ERROR_FAIL_I24, osl_File_E_ACCES }, /* 83 */ 116 { ERROR_INVALID_PARAMETER, osl_File_E_INVAL }, /* 87 */ 117 { ERROR_NO_PROC_SLOTS, osl_File_E_AGAIN }, /* 89 */ 118 { ERROR_DRIVE_LOCKED, osl_File_E_ACCES }, /* 108 */ 119 { ERROR_BROKEN_PIPE, osl_File_E_PIPE }, /* 109 */ 120 { ERROR_DISK_FULL, osl_File_E_NOSPC }, /* 112 */ 121 { ERROR_INVALID_TARGET_HANDLE, osl_File_E_BADF }, /* 114 */ 122 { ERROR_INVALID_HANDLE, osl_File_E_INVAL }, /* 124 */ 123 { ERROR_WAIT_NO_CHILDREN, osl_File_E_CHILD }, /* 128 */ 124 { ERROR_CHILD_NOT_COMPLETE, osl_File_E_CHILD }, /* 129 */ 125 { ERROR_DIRECT_ACCESS_HANDLE, osl_File_E_BADF }, /* 130 */ 126 { ERROR_NEGATIVE_SEEK, osl_File_E_INVAL }, /* 131 */ 127 { ERROR_SEEK_ON_DEVICE, osl_File_E_ACCES }, /* 132 */ 128 { ERROR_DIR_NOT_EMPTY, osl_File_E_NOTEMPTY }, /* 145 */ 129 { ERROR_NOT_LOCKED, osl_File_E_ACCES }, /* 158 */ 130 { ERROR_BAD_PATHNAME, osl_File_E_NOENT }, /* 161 */ 131 { ERROR_MAX_THRDS_REACHED, osl_File_E_AGAIN }, /* 164 */ 132 { ERROR_LOCK_FAILED, osl_File_E_ACCES }, /* 167 */ 133 { ERROR_ALREADY_EXISTS, osl_File_E_EXIST }, /* 183 */ 134 { ERROR_FILENAME_EXCED_RANGE, osl_File_E_NOENT }, /* 206 */ 135 { ERROR_NESTING_NOT_ALLOWED, osl_File_E_AGAIN }, /* 215 */ 136 { ERROR_DIRECTORY, osl_File_E_NOENT }, /* 267 */ 137 //{ ERROR_NOT_ENOUGH_QUOTA, osl_File_E_NOMEM } /* 1816 */ 138 }; 139 140 #define ELEMENTS_OF_ARRAY(arr) (sizeof(arr)/(sizeof((arr)[0]))) 141 142 //##################################################### 143 oslFileError MapError(APIRET dwError) 144 { 145 for (int i = 0; i < ELEMENTS_OF_ARRAY(errtable); ++i ) 146 { 147 if (dwError == errtable[i].oscode) 148 return static_cast<oslFileError>(errtable[i].errnocode); 149 } 150 return osl_File_E_INVAL; 151 } 152 153 /****************************************************************************** 154 * 155 * static members 156 * 157 *****************************************************************************/ 158 159 static const char * pFileLockEnvVar = (char *) -1; 160 161 162 /****************************************************************************** 163 * 164 * C-String Function Declarations 165 * 166 *****************************************************************************/ 167 168 static oslFileError osl_psz_getVolumeInformation(const sal_Char* , oslVolumeInfo* pInfo, sal_uInt32 uFieldMask); 169 static oslFileError osl_psz_removeFile(const sal_Char* pszPath); 170 static oslFileError osl_psz_createDirectory(const sal_Char* pszPath); 171 static oslFileError osl_psz_removeDirectory(const sal_Char* pszPath); 172 static oslFileError osl_psz_copyFile(const sal_Char* pszPath, const sal_Char* pszDestPath); 173 static oslFileError osl_psz_moveFile(const sal_Char* pszPath, const sal_Char* pszDestPath); 174 static oslFileError osl_psz_setFileTime(const sal_Char* strFilePath, const TimeValue* pCreationTime, const TimeValue* pLastAccessTime, const TimeValue* pLastWriteTime); 175 176 177 /****************************************************************************** 178 * 179 * Static Module Utility Function Declarations 180 * 181 *****************************************************************************/ 182 183 static oslFileError oslDoCopy(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, mode_t nMode, size_t nSourceSize, int DestFileExists); 184 static oslFileError oslChangeFileModes(const sal_Char* pszFileName, mode_t nMode, time_t nAcTime, time_t nModTime, uid_t nUID, gid_t nGID); 185 static int oslDoCopyLink(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName); 186 static int oslDoCopyFile(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, size_t nSourceSize, mode_t mode); 187 static oslFileError oslDoMoveFile(const sal_Char* pszPath, const sal_Char* pszDestPath); 188 rtl_uString* oslMakeUStrFromPsz(const sal_Char* pszStr,rtl_uString** uStr); 189 190 /****************************************************************************** 191 * 192 * Non-Static Utility Function Declarations 193 * 194 *****************************************************************************/ 195 196 extern "C" int UnicodeToText( char *, size_t, const sal_Unicode *, sal_Int32 ); 197 extern "C" int TextToUnicode( 198 const char* text, size_t text_buffer_size, sal_Unicode* unic_text, sal_Int32 unic_text_buffer_size); 199 200 /****************************************************************************** 201 * 202 * 'removeable device' aka floppy functions 203 * 204 *****************************************************************************/ 205 206 static oslVolumeDeviceHandle osl_isFloppyDrive(const sal_Char* pszPath); 207 static oslFileError osl_mountFloppy(oslVolumeDeviceHandle hFloppy); 208 static oslFileError osl_unmountFloppy(oslVolumeDeviceHandle hFloppy); 209 210 #ifdef DEBUG_OSL_FILE 211 static void osl_printFloppyHandle(oslVolumeDeviceHandleImpl* hFloppy); 212 #endif 213 214 /********************************************** 215 * _osl_openLocalRoot 216 * enumerate available drives 217 *********************************************/ 218 static oslFileError _osl_openLocalRoot( rtl_uString *strDirectoryPath, oslDirectory *pDirectory) 219 { 220 rtl_uString *ustrSystemPath = NULL; 221 oslFileError error; 222 223 if ( !pDirectory ) 224 return osl_File_E_INVAL; 225 226 *pDirectory = NULL; 227 228 error = osl_getSystemPathFromFileURL_Ex( strDirectoryPath, &ustrSystemPath, sal_False ); 229 230 if ( osl_File_E_None == error ) 231 { 232 /* create and initialize impl structure */ 233 DirectoryImpl* pDirImpl = (DirectoryImpl*) rtl_allocateMemory( sizeof(DirectoryImpl) ); 234 if( pDirImpl ) 235 { 236 ULONG ulDriveNum; 237 APIRET rc; 238 pDirImpl->uType = DIRECTORYTYPE_LOCALROOT; 239 pDirImpl->ustrPath = ustrSystemPath; 240 rc = DosQueryCurrentDisk (&ulDriveNum, &pDirImpl->ulDriveMap); 241 pDirImpl->pDirStruct = 0; 242 pDirImpl->ulNextDrive = 1; 243 pDirImpl->ulNextDriveMask = 1; 244 245 // determine number of floppy-drives 246 BYTE nFloppies; 247 rc = DosDevConfig( (void*) &nFloppies, DEVINFO_FLOPPY ); 248 if (nFloppies == 0) { 249 // if no floppies, start with 3rd drive (C:) 250 pDirImpl->ulNextDrive = 3; 251 pDirImpl->ulNextDriveMask <<= 2; 252 } else if (nFloppies == 1) { 253 // mask drive B (second bit) in this case 254 pDirImpl->ulDriveMap &= ~0x02; 255 } 256 *pDirectory = (oslDirectory) pDirImpl; 257 return osl_File_E_None; 258 } 259 else 260 { 261 errno = osl_File_E_NOMEM; 262 } 263 264 } 265 266 rtl_uString_release( ustrSystemPath ); 267 return error; 268 } 269 270 /********************************************** 271 * _osl_getNextDrive 272 *********************************************/ 273 static oslFileError SAL_CALL _osl_getNextDrive( 274 oslDirectory Directory, oslDirectoryItem *pItem, sal_uInt32 uHint ) 275 { 276 DirectoryImpl *pDirImpl = (DirectoryImpl *)Directory; 277 DirectoryItem_Impl *pItemImpl = NULL; 278 rtl_uString * ustrDrive = NULL; 279 BOOL fSuccess; 280 char buffer[3]; 281 282 uHint = uHint; /* avoid warnings */ 283 284 if ( !pItem ) 285 return osl_File_E_INVAL; 286 287 *pItem = NULL; 288 289 if ( !pDirImpl ) 290 return osl_File_E_INVAL; 291 292 while( pDirImpl->ulNextDrive <= 26) 293 { 294 // exit if bit==1 -> drive found 295 if (pDirImpl->ulDriveMap & pDirImpl->ulNextDriveMask) { 296 297 /* convert file name to unicode */ 298 buffer[0] = '@' + pDirImpl->ulNextDrive; 299 buffer[1] = ':'; 300 buffer[2] = 0; 301 302 pItemImpl = (DirectoryItem_Impl*) rtl_allocateMemory(sizeof(DirectoryItem_Impl)); 303 if ( !pItemImpl ) 304 return osl_File_E_NOMEM; 305 306 memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) ); 307 pItemImpl->uType = DIRECTORYITEM_DRIVE; 308 pItemImpl->nRefCount = 1; 309 310 rtl_string2UString( &pItemImpl->ustrDrive, buffer, 3, 311 osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS ); 312 OSL_ASSERT(pItemImpl->ustrDrive != 0); 313 314 /* use drive as directory item */ 315 *pItem = (oslDirectoryItem) pItemImpl; 316 } 317 // scan next bit position 318 pDirImpl->ulNextDrive++; 319 pDirImpl->ulNextDriveMask <<= 1; 320 321 if (*pItem) // item assigned, return now. 322 return osl_File_E_None; 323 } 324 325 // no more items 326 return osl_File_E_NOENT; 327 } 328 329 /********************************************** 330 * _osl_readdir_impl_ 331 * 332 * readdir wrapper, filters out "." and ".." 333 * on request 334 *********************************************/ 335 336 static struct dirent* _osl_readdir_impl_(DIR* pdir, sal_Bool bFilterLocalAndParentDir) 337 { 338 struct dirent* pdirent; 339 340 while ((pdirent = readdir(pdir)) != NULL) 341 { 342 if (bFilterLocalAndParentDir && 343 ((0 == strcmp(pdirent->d_name, ".")) || (0 == strcmp(pdirent->d_name, "..")))) 344 continue; 345 else 346 break; 347 } 348 349 return pdirent; 350 } 351 352 /******************************************************************* 353 * osl_openDirectory 354 ******************************************************************/ 355 356 oslFileError SAL_CALL osl_openDirectory(rtl_uString* ustrDirectoryURL, oslDirectory* pDirectory) 357 { 358 rtl_uString* ustrSystemPath = NULL; 359 oslFileError eRet; 360 361 char path[PATH_MAX]; 362 363 OSL_ASSERT(ustrDirectoryURL && (ustrDirectoryURL->length > 0)); 364 OSL_ASSERT(pDirectory); 365 366 if (0 == ustrDirectoryURL->length ) 367 return osl_File_E_INVAL; 368 369 if ( 0 == rtl_ustr_compareIgnoreAsciiCase( ustrDirectoryURL->buffer, (const sal_Unicode*)L"file:///" ) ) 370 return _osl_openLocalRoot( ustrDirectoryURL, pDirectory ); 371 372 /* convert file URL to system path */ 373 eRet = osl_getSystemPathFromFileURL_Ex(ustrDirectoryURL, &ustrSystemPath, sal_False); 374 375 if( osl_File_E_None != eRet ) 376 return eRet; 377 378 osl_systemPathRemoveSeparator(ustrSystemPath); 379 380 /* convert unicode path to text */ 381 if ( UnicodeToText( path, PATH_MAX, ustrSystemPath->buffer, ustrSystemPath->length ) ) 382 { 383 // if only the drive is specified (x:), add a \ (x:\) otherwise current 384 // directory is browsed instead of root. 385 if (strlen( path) == 2 && path[1] == ':') 386 strcat( path, "\\"); 387 /* open directory */ 388 DIR *pdir = opendir( path ); 389 390 if( pdir ) 391 { 392 /* create and initialize impl structure */ 393 DirectoryImpl* pDirImpl = (DirectoryImpl*) rtl_allocateMemory( sizeof(DirectoryImpl) ); 394 395 if( pDirImpl ) 396 { 397 pDirImpl->uType = DIRECTORYTYPE_FILESYSTEM; 398 pDirImpl->pDirStruct = pdir; 399 pDirImpl->ustrPath = ustrSystemPath; 400 401 *pDirectory = (oslDirectory) pDirImpl; 402 return osl_File_E_None; 403 } 404 else 405 { 406 errno = ENOMEM; 407 closedir( pdir ); 408 } 409 } 410 else 411 /* should be removed by optimizer in product version */ 412 PERROR( "osl_openDirectory", path ); 413 } 414 415 rtl_uString_release( ustrSystemPath ); 416 417 return oslTranslateFileError(OSL_FET_ERROR, errno); 418 } 419 420 421 /**************************************************************************** 422 * osl_getNextDirectoryItem 423 ***************************************************************************/ 424 425 oslFileError SAL_CALL osl_getNextDirectoryItem(oslDirectory Directory, oslDirectoryItem* pItem, sal_uInt32 uHint) 426 { 427 DirectoryImpl* pDirImpl = (DirectoryImpl*)Directory; 428 DirectoryItem_Impl *pItemImpl = NULL; 429 rtl_uString* ustrFileName = NULL; 430 rtl_uString* ustrFilePath = NULL; 431 struct dirent* pEntry; 432 433 OSL_ASSERT(Directory); 434 OSL_ASSERT(pItem); 435 436 if ((NULL == Directory) || (NULL == pItem)) 437 return osl_File_E_INVAL; 438 439 if ( pDirImpl->uType == DIRECTORYTYPE_LOCALROOT) 440 return _osl_getNextDrive( Directory, pItem, uHint ); 441 442 pEntry = _osl_readdir_impl_(pDirImpl->pDirStruct, sal_True); 443 444 if (NULL == pEntry) 445 return osl_File_E_NOENT; 446 447 pItemImpl = (DirectoryItem_Impl*) rtl_allocateMemory(sizeof(DirectoryItem_Impl)); 448 if ( !pItemImpl ) 449 return osl_File_E_NOMEM; 450 451 memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) ); 452 pItemImpl->uType = DIRECTORYITEM_FILE; 453 pItemImpl->nRefCount = 1; 454 pItemImpl->d_attr = pEntry->d_attr; 455 456 /* convert file name to unicode */ 457 rtl_string2UString( &ustrFileName, pEntry->d_name, strlen( pEntry->d_name ), 458 osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS ); 459 OSL_ASSERT(ustrFileName != 0); 460 461 osl_systemPathMakeAbsolutePath(pDirImpl->ustrPath, ustrFileName, &pItemImpl->ustrFilePath); 462 rtl_uString_release( ustrFileName ); 463 464 *pItem = (oslDirectoryItem)pItemImpl; 465 return osl_File_E_None; 466 } 467 468 /****************************************************************************/ 469 /* osl_closeDirectory */ 470 /****************************************************************************/ 471 472 oslFileError SAL_CALL osl_closeDirectory( oslDirectory Directory ) 473 { 474 DirectoryImpl* pDirImpl = (DirectoryImpl*) Directory; 475 oslFileError err = osl_File_E_None; 476 477 OSL_ASSERT( Directory ); 478 479 if( NULL == pDirImpl ) 480 return osl_File_E_INVAL; 481 482 switch ( pDirImpl->uType ) 483 { 484 case DIRECTORYTYPE_FILESYSTEM: 485 if( closedir( pDirImpl->pDirStruct ) ) 486 err = oslTranslateFileError(OSL_FET_ERROR, errno); 487 break; 488 case DIRECTORYTYPE_LOCALROOT: 489 err = osl_File_E_None; 490 break; 491 #if 0 492 case DIRECTORYTYPE_NETROOT: 493 { 494 DWORD err = WNetCloseEnum(pDirImpl->hDirectory); 495 eError = (err == NO_ERROR) ? osl_File_E_None : MapError(err); 496 } 497 break; 498 #endif 499 default: 500 OSL_ENSURE( 0, "Invalid directory type" ); 501 break; 502 } 503 504 /* cleanup members */ 505 rtl_uString_release( pDirImpl->ustrPath ); 506 507 rtl_freeMemory( pDirImpl ); 508 509 return err; 510 } 511 512 /****************************************************************************/ 513 /* osl_getDirectoryItem */ 514 /****************************************************************************/ 515 516 oslFileError SAL_CALL osl_getDirectoryItem( rtl_uString* ustrFileURL, oslDirectoryItem* pItem ) 517 { 518 rtl_uString* strSysFilePath = NULL; 519 oslFileError error = osl_File_E_INVAL; 520 ULONG dwPathType; 521 PATHTYPE type = PATHTYPE_FILE; 522 523 OSL_ASSERT(ustrFileURL); 524 OSL_ASSERT(pItem); 525 526 /* Assume failure */ 527 if ( !pItem ) 528 return osl_File_E_INVAL; 529 *pItem = NULL; 530 531 if (0 == ustrFileURL->length || NULL == pItem) 532 return osl_File_E_INVAL; 533 534 error = osl_getSystemPathFromFileURL_Ex(ustrFileURL, &strSysFilePath, sal_False); 535 536 if (osl_File_E_None != error) 537 return error; 538 539 dwPathType = IsValidFilePath( strSysFilePath->buffer, NULL, VALIDATEPATH_NORMAL ); 540 541 if ( dwPathType & PATHTYPE_IS_VOLUME ) 542 type = PATHTYPE_VOLUME; 543 else if ( dwPathType & PATHTYPE_IS_SERVER ) 544 type = PATHTYPE_NETSERVER; 545 else 546 type = PATHTYPE_FILE; 547 548 switch ( type ) 549 { 550 case PATHTYPE_NETSERVER: 551 { 552 DirectoryItem_Impl* pItemImpl = 553 reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl))); 554 555 if ( !pItemImpl ) 556 error = osl_File_E_NOMEM; 557 558 if ( osl_File_E_None == error ) 559 { 560 memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) ); 561 pItemImpl->uType = DIRECTORYITEM_SERVER; 562 pItemImpl->nRefCount = 1; 563 rtl_uString_assign( &pItemImpl->ustrFilePath, strSysFilePath ); 564 565 *pItem = pItemImpl; 566 } 567 } 568 break; 569 case PATHTYPE_VOLUME: 570 { 571 DirectoryItem_Impl* pItemImpl = 572 reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl))); 573 574 if ( !pItemImpl ) 575 error = osl_File_E_NOMEM; 576 577 if ( osl_File_E_None == error ) 578 { 579 memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) ); 580 pItemImpl->uType = DIRECTORYITEM_DRIVE; 581 pItemImpl->nRefCount = 1; 582 rtl_uString_assign( &pItemImpl->ustrDrive, strSysFilePath ); 583 584 if ( pItemImpl->ustrDrive->buffer[pItemImpl->ustrDrive->length-1] != sal_Unicode('\\') ) 585 rtl_uString_newConcat( &pItemImpl->ustrDrive, 586 pItemImpl->ustrDrive, rtl::OUString::createFromAscii( "\\" ).pData); 587 588 *pItem = pItemImpl; 589 } 590 } 591 break; 592 default: 593 case PATHTYPE_FILE: 594 { 595 if ( strSysFilePath->length > 0 && strSysFilePath->buffer[strSysFilePath->length - 1] == '\\' ) 596 rtl_uString_newFromStr_WithLength( &strSysFilePath, strSysFilePath->buffer, strSysFilePath->length - 1 ); 597 598 if (0 == access_u(strSysFilePath, F_OK)) 599 { 600 DirectoryItem_Impl *pItemImpl = 601 reinterpret_cast<DirectoryItem_Impl*>(rtl_allocateMemory(sizeof(DirectoryItem_Impl))); 602 603 memset( pItemImpl, 0, sizeof(DirectoryItem_Impl) ); 604 pItemImpl->uType = DIRECTORYITEM_FILE; 605 pItemImpl->nRefCount = 1; 606 rtl_uString_assign( &pItemImpl->ustrFilePath, strSysFilePath ); 607 608 *pItem = pItemImpl; 609 } 610 else 611 error = oslTranslateFileError(OSL_FET_ERROR, errno); 612 } 613 break; 614 } 615 616 if ( strSysFilePath ) 617 rtl_uString_release( strSysFilePath ); 618 619 return error; 620 } 621 622 /****************************************************************************/ 623 /* osl_acquireDirectoryItem */ 624 /****************************************************************************/ 625 626 oslFileError osl_acquireDirectoryItem( oslDirectoryItem Item ) 627 { 628 OSL_ASSERT( Item ); 629 DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item; 630 631 if ( !pItemImpl ) 632 return osl_File_E_INVAL; 633 634 pItemImpl->nRefCount++; 635 return osl_File_E_None; 636 } 637 638 /****************************************************************************/ 639 /* osl_releaseDirectoryItem */ 640 /****************************************************************************/ 641 642 oslFileError osl_releaseDirectoryItem( oslDirectoryItem Item ) 643 { 644 OSL_ASSERT( Item ); 645 DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item; 646 647 if ( !pItemImpl ) 648 return osl_File_E_INVAL; 649 650 if ( ! --pItemImpl->nRefCount ) 651 { 652 if (pItemImpl->ustrFilePath) 653 rtl_uString_release( pItemImpl->ustrFilePath ); 654 if (pItemImpl->ustrDrive) 655 rtl_uString_release( pItemImpl->ustrDrive ); 656 rtl_freeMemory( pItemImpl ); 657 } 658 return osl_File_E_None; 659 } 660 661 /**************************************************************************** 662 * osl_createFileHandleFromFD 663 ***************************************************************************/ 664 665 oslFileHandle osl_createFileHandleFromFD( int fd ) 666 { 667 oslFileHandleImpl* pHandleImpl = NULL; 668 669 if ( fd >= 0 ) 670 { 671 pHandleImpl = (oslFileHandleImpl*) rtl_allocateMemory( sizeof(oslFileHandleImpl) ); 672 673 if( pHandleImpl ) 674 { 675 pHandleImpl->ustrFilePath = NULL; 676 rtl_uString_new( &pHandleImpl->ustrFilePath ); 677 pHandleImpl->fd = fd; 678 679 /* FIXME: should detect whether the file has been locked */ 680 pHandleImpl->bLocked = sal_True; 681 } 682 } 683 684 return (oslFileHandle)pHandleImpl; 685 } 686 687 /**************************************************************************** 688 * osl_openFile 689 ***************************************************************************/ 690 691 oslFileError osl_openFile( rtl_uString* ustrFileURL, oslFileHandle* pHandle, sal_uInt32 uFlags ) 692 { 693 oslFileHandleImpl* pHandleImpl = NULL; 694 oslFileError eRet; 695 rtl_uString* ustrFilePath = NULL; 696 697 char buffer[PATH_MAX]; 698 int fd; 699 int mode = S_IRUSR | S_IRGRP | S_IROTH; 700 int flags = O_RDONLY; 701 702 struct flock aflock; 703 704 /* locking the complete file */ 705 aflock.l_type = 0; 706 aflock.l_whence = SEEK_SET; 707 aflock.l_start = 0; 708 aflock.l_len = 0; 709 710 OSL_ASSERT( ustrFileURL ); 711 OSL_ASSERT( pHandle ); 712 713 if( ( 0 == ustrFileURL->length ) ) 714 return osl_File_E_INVAL; 715 716 /* convert file URL to system path */ 717 eRet = osl_getSystemPathFromFileURL( ustrFileURL, &ustrFilePath ); 718 719 if( osl_File_E_None != eRet ) 720 return eRet; 721 722 osl_systemPathRemoveSeparator(ustrFilePath); 723 724 /* convert unicode path to text */ 725 if( UnicodeToText( buffer, PATH_MAX, ustrFilePath->buffer, ustrFilePath->length ) ) 726 { 727 /* we do not open devices or such here */ 728 if( !( uFlags & osl_File_OpenFlag_Create ) ) 729 { 730 struct stat aFileStat; 731 732 if( 0 > stat( buffer, &aFileStat ) ) 733 { 734 PERROR( "osl_openFile", buffer ); 735 eRet = oslTranslateFileError(OSL_FET_ERROR, errno ); 736 } 737 738 else if( !S_ISREG( aFileStat.st_mode ) ) 739 { 740 eRet = osl_File_E_INVAL; 741 } 742 } 743 744 if( osl_File_E_None == eRet ) 745 { 746 /* 747 * set flags and mode 748 */ 749 750 if ( uFlags & osl_File_OpenFlag_Write ) 751 { 752 mode |= S_IWUSR | S_IWGRP | S_IWOTH; 753 flags = O_RDWR; 754 aflock.l_type = F_WRLCK; 755 } 756 757 if ( uFlags & osl_File_OpenFlag_Create ) 758 { 759 mode |= S_IWUSR | S_IWGRP | S_IWOTH; 760 flags = O_CREAT | O_EXCL | O_RDWR; 761 } 762 763 /* open the file */ 764 fd = open( buffer, flags | O_BINARY, mode); 765 if ( fd >= 0 ) 766 { 767 sal_Bool bNeedsLock = ( ( uFlags & osl_File_OpenFlag_NoLock ) == 0 ); 768 sal_Bool bLocked = sal_False; 769 if( bNeedsLock ) 770 { 771 /* check if file lock is enabled and clear l_type member of flock otherwise */ 772 if( (char *) -1 == pFileLockEnvVar ) 773 { 774 /* FIXME: this is not MT safe */ 775 pFileLockEnvVar = getenv("SAL_ENABLE_FILE_LOCKING"); 776 777 if( NULL == pFileLockEnvVar) 778 pFileLockEnvVar = getenv("STAR_ENABLE_FILE_LOCKING"); 779 } 780 781 if( NULL == pFileLockEnvVar ) 782 aflock.l_type = 0; 783 784 /* lock the file if flock.l_type is set */ 785 bLocked = ( F_WRLCK != aflock.l_type || -1 != fcntl( fd, F_SETLK, &aflock ) ); 786 } 787 788 if ( !bNeedsLock || bLocked ) 789 { 790 /* allocate memory for impl structure */ 791 pHandleImpl = (oslFileHandleImpl*) rtl_allocateMemory( sizeof(oslFileHandleImpl) ); 792 if( pHandleImpl ) 793 { 794 pHandleImpl->ustrFilePath = ustrFilePath; 795 pHandleImpl->fd = fd; 796 pHandleImpl->bLocked = bLocked; 797 798 *pHandle = (oslFileHandle) pHandleImpl; 799 800 return osl_File_E_None; 801 } 802 else 803 { 804 errno = ENOMEM; 805 } 806 } 807 808 close( fd ); 809 } 810 811 PERROR( "osl_openFile", buffer ); 812 eRet = oslTranslateFileError(OSL_FET_ERROR, errno ); 813 } 814 } 815 else 816 eRet = osl_File_E_INVAL; 817 818 rtl_uString_release( ustrFilePath ); 819 return eRet; 820 } 821 822 /****************************************************************************/ 823 /* osl_closeFile */ 824 /****************************************************************************/ 825 826 oslFileError osl_closeFile( oslFileHandle Handle ) 827 { 828 oslFileHandleImpl* pHandleImpl = (oslFileHandleImpl *) Handle; 829 oslFileError eRet = osl_File_E_INVAL; 830 831 OSL_ASSERT( Handle ); 832 833 if( pHandleImpl ) 834 { 835 rtl_uString_release( pHandleImpl->ustrFilePath ); 836 837 /* release file lock if locking is enabled */ 838 if( pFileLockEnvVar ) 839 { 840 struct flock aflock; 841 842 aflock.l_type = F_UNLCK; 843 aflock.l_whence = SEEK_SET; 844 aflock.l_start = 0; 845 aflock.l_len = 0; 846 847 if ( pHandleImpl->bLocked ) 848 { 849 /* FIXME: check if file is really locked ? */ 850 851 /* release the file share lock on this file */ 852 if( -1 == fcntl( pHandleImpl->fd, F_SETLK, &aflock ) ) 853 PERROR( "osl_closeFile", "unlock failed" ); 854 } 855 } 856 857 if( 0 > close( pHandleImpl->fd ) ) 858 { 859 eRet = oslTranslateFileError(OSL_FET_ERROR, errno ); 860 } 861 else 862 eRet = osl_File_E_None; 863 864 rtl_freeMemory( pHandleImpl ); 865 } 866 867 return eRet; 868 } 869 870 /****************************************************************************/ 871 /* osl_isEndOfFile */ 872 /****************************************************************************/ 873 874 oslFileError SAL_CALL osl_isEndOfFile( oslFileHandle Handle, sal_Bool *pIsEOF ) 875 { 876 oslFileHandleImpl* pHandleImpl = (oslFileHandleImpl *) Handle; 877 oslFileError eRet = osl_File_E_INVAL; 878 879 if ( pHandleImpl) 880 { 881 long curPos = lseek( pHandleImpl->fd, 0, SEEK_CUR ); 882 883 if ( curPos >= 0 ) 884 { 885 long endPos = lseek( pHandleImpl->fd, 0, SEEK_END ); 886 887 if ( endPos >= 0 ) 888 { 889 *pIsEOF = ( curPos == endPos ); 890 curPos = lseek( pHandleImpl->fd, curPos, SEEK_SET ); 891 892 if ( curPos >= 0 ) 893 eRet = osl_File_E_None; 894 else 895 eRet = oslTranslateFileError(OSL_FET_ERROR, errno ); 896 } 897 else 898 eRet = oslTranslateFileError(OSL_FET_ERROR, errno ); 899 } 900 else 901 eRet = oslTranslateFileError(OSL_FET_ERROR, errno ); 902 } 903 904 return eRet; 905 } 906 907 908 /****************************************************************************/ 909 /* osl_moveFile */ 910 /****************************************************************************/ 911 912 oslFileError osl_moveFile( rtl_uString* ustrFileURL, rtl_uString* ustrDestURL ) 913 { 914 char srcPath[PATH_MAX]; 915 char destPath[PATH_MAX]; 916 oslFileError eRet; 917 APIRET rc; 918 919 OSL_ASSERT( ustrFileURL ); 920 OSL_ASSERT( ustrDestURL ); 921 922 /* convert source url to system path */ 923 eRet = FileURLToPath( srcPath, PATH_MAX, ustrFileURL ); 924 if( eRet != osl_File_E_None ) 925 return eRet; 926 927 /* convert destination url to system path */ 928 eRet = FileURLToPath( destPath, PATH_MAX, ustrDestURL ); 929 if( eRet != osl_File_E_None ) 930 return eRet; 931 932 //YD 01/05/06 rename() can overwrite existing files. 933 rc = DosDelete( (PCSZ)destPath); 934 rc = DosMove( (PCSZ)srcPath, (PCSZ)destPath); 935 if (!rc) 936 eRet = osl_File_E_None; 937 else 938 eRet = MapError( rc); 939 940 return eRet; 941 } 942 943 /****************************************************************************/ 944 /* osl_copyFile */ 945 /****************************************************************************/ 946 947 #define TMP_DEST_FILE_EXTENSION ".osl-tmp" 948 949 static oslFileError oslDoCopy(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, mode_t nMode, size_t nSourceSize, int DestFileExists) 950 { 951 int nRet=0; 952 sal_Char pszTmpDestFile[PATH_MAX]; 953 size_t size_tmp_dest_buff = sizeof(pszTmpDestFile); 954 955 /* Quick fix for #106048, the whole copy file function seems 956 to be erroneous anyway and needs to be rewritten. 957 Besides osl_copyFile is currently not used from OO/SO code. 958 */ 959 memset(pszTmpDestFile, 0, size_tmp_dest_buff); 960 961 if ( DestFileExists ) 962 { 963 strncpy(pszTmpDestFile, pszDestFileName, size_tmp_dest_buff - 1); 964 965 if ((strlen(pszTmpDestFile) + strlen(TMP_DEST_FILE_EXTENSION)) >= size_tmp_dest_buff) 966 return osl_File_E_NAMETOOLONG; 967 968 strncat(pszTmpDestFile, TMP_DEST_FILE_EXTENSION, strlen(TMP_DEST_FILE_EXTENSION)); 969 970 /* FIXME: what if pszTmpDestFile already exists? */ 971 /* with getcanonical??? */ 972 nRet=rename(pszDestFileName,pszTmpDestFile); 973 } 974 975 /* mfe: should be S_ISREG */ 976 if ( !S_ISLNK(nMode) ) 977 { 978 /* copy SourceFile to DestFile */ 979 nRet = oslDoCopyFile(pszSourceFileName,pszDestFileName,nSourceSize, nMode); 980 } 981 /* mfe: OK redundant at the moment */ 982 else if ( S_ISLNK(nMode) ) 983 { 984 nRet = oslDoCopyLink(pszSourceFileName,pszDestFileName); 985 } 986 else 987 { 988 /* mfe: what to do here? */ 989 nRet=ENOSYS; 990 } 991 992 if ( nRet > 0 && DestFileExists == 1 ) 993 { 994 unlink(pszDestFileName); 995 rename(pszTmpDestFile,pszDestFileName); 996 } 997 998 if ( nRet > 0 ) 999 { 1000 return oslTranslateFileError(OSL_FET_ERROR, nRet); 1001 } 1002 1003 if ( DestFileExists == 1 ) 1004 { 1005 unlink(pszTmpDestFile); 1006 } 1007 1008 return osl_File_E_None; 1009 } 1010 1011 /***************************************** 1012 * oslChangeFileModes 1013 ****************************************/ 1014 1015 static oslFileError oslChangeFileModes( const sal_Char* pszFileName, mode_t nMode, time_t nAcTime, time_t nModTime, uid_t nUID, gid_t nGID) 1016 { 1017 int nRet=0; 1018 struct utimbuf aTimeBuffer; 1019 1020 nRet = chmod(pszFileName,nMode); 1021 if ( nRet < 0 ) 1022 { 1023 nRet=errno; 1024 return oslTranslateFileError(OSL_FET_ERROR, nRet); 1025 } 1026 1027 aTimeBuffer.actime=nAcTime; 1028 aTimeBuffer.modtime=nModTime; 1029 nRet=utime(pszFileName,&aTimeBuffer); 1030 if ( nRet < 0 ) 1031 { 1032 nRet=errno; 1033 return oslTranslateFileError(OSL_FET_ERROR, nRet); 1034 } 1035 1036 if ( nUID != getuid() ) 1037 { 1038 nUID=getuid(); 1039 } 1040 1041 nRet=chown(pszFileName,nUID,nGID); 1042 if ( nRet < 0 ) 1043 { 1044 nRet=errno; 1045 1046 /* mfe: do not return an error here! */ 1047 /* return oslTranslateFileError(nRet);*/ 1048 } 1049 1050 return osl_File_E_None; 1051 } 1052 1053 /***************************************** 1054 * oslDoCopyLink 1055 ****************************************/ 1056 1057 static int oslDoCopyLink(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName) 1058 { 1059 int nRet=0; 1060 1061 /* mfe: if dest file is symbolic link remove the link and place the file instead (hro says so) */ 1062 /* mfe: if source is a link copy the link and not the file it points to (hro says so) */ 1063 sal_Char pszLinkContent[PATH_MAX]; 1064 1065 pszLinkContent[0] = '\0'; 1066 1067 nRet = readlink(pszSourceFileName,pszLinkContent,PATH_MAX); 1068 1069 if ( nRet < 0 ) 1070 { 1071 nRet=errno; 1072 return nRet; 1073 } 1074 else 1075 pszLinkContent[ nRet ] = 0; 1076 1077 nRet = symlink(pszLinkContent,pszDestFileName); 1078 1079 if ( nRet < 0 ) 1080 { 1081 nRet=errno; 1082 return nRet; 1083 } 1084 1085 return 0; 1086 } 1087 1088 /***************************************** 1089 * oslDoCopyFile 1090 ****************************************/ 1091 1092 static int oslDoCopyFile(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, size_t nSourceSize, mode_t mode) 1093 { 1094 int SourceFileFD=0; 1095 int DestFileFD=0; 1096 int nRet=0; 1097 void* pSourceFile=0; 1098 char buffer[ 4096]; 1099 1100 SourceFileFD=open(pszSourceFileName,O_RDONLY | O_BINARY); 1101 if ( SourceFileFD < 0 ) 1102 { 1103 nRet=errno; 1104 return nRet; 1105 } 1106 1107 DestFileFD=open(pszDestFileName, O_WRONLY | O_CREAT | O_BINARY, mode); 1108 if ( DestFileFD < 0 ) 1109 { 1110 nRet=errno; 1111 close(SourceFileFD); 1112 return nRet; 1113 } 1114 1115 /* HACK: because memory mapping fails on various 1116 platforms if the size of the source file is 0 byte */ 1117 if (0 == nSourceSize) 1118 { 1119 close(SourceFileFD); 1120 close(DestFileFD); 1121 return 0; 1122 } 1123 1124 while( (nRet = read(SourceFileFD, buffer, sizeof(buffer))) !=0 ) 1125 { 1126 nRet = write( DestFileFD, buffer, nRet); 1127 } 1128 1129 close(SourceFileFD); 1130 close(DestFileFD); 1131 1132 return nRet; 1133 } 1134 1135 static oslFileError osl_psz_copyFile( const sal_Char* pszPath, const sal_Char* pszDestPath ) 1136 { 1137 time_t nAcTime=0; 1138 time_t nModTime=0; 1139 uid_t nUID=0; 1140 gid_t nGID=0; 1141 int nRet=0; 1142 mode_t nMode=0; 1143 struct stat aFileStat; 1144 oslFileError tErr=osl_File_E_invalidError; 1145 size_t nSourceSize=0; 1146 int DestFileExists=1; 1147 1148 /* mfe: does the source file really exists? */ 1149 nRet = lstat(pszPath,&aFileStat); 1150 1151 if ( nRet < 0 ) 1152 { 1153 nRet=errno; 1154 return oslTranslateFileError(OSL_FET_ERROR, nRet); 1155 } 1156 1157 /* mfe: we do only copy files here! */ 1158 if ( S_ISDIR(aFileStat.st_mode) ) 1159 { 1160 return osl_File_E_ISDIR; 1161 } 1162 1163 nSourceSize=(size_t)aFileStat.st_size; 1164 nMode=aFileStat.st_mode; 1165 nAcTime=aFileStat.st_atime; 1166 nModTime=aFileStat.st_mtime; 1167 nUID=aFileStat.st_uid; 1168 nGID=aFileStat.st_gid; 1169 1170 nRet = stat(pszDestPath,&aFileStat); 1171 if ( nRet < 0 ) 1172 { 1173 nRet=errno; 1174 1175 if ( nRet == ENOENT ) 1176 { 1177 DestFileExists=0; 1178 } 1179 /* return oslTranslateFileError(nRet);*/ 1180 } 1181 1182 /* mfe: the destination file must not be a directory! */ 1183 if ( nRet == 0 && S_ISDIR(aFileStat.st_mode) ) 1184 { 1185 return osl_File_E_ISDIR; 1186 } 1187 else 1188 { 1189 /* mfe: file does not exists or is no dir */ 1190 } 1191 1192 tErr = oslDoCopy(pszPath,pszDestPath,nMode,nSourceSize,DestFileExists); 1193 1194 if ( tErr != osl_File_E_None ) 1195 { 1196 return tErr; 1197 } 1198 1199 /* 1200 * mfe: ignore return code 1201 * since only the success of the copy is 1202 * important 1203 */ 1204 oslChangeFileModes(pszDestPath,nMode,nAcTime,nModTime,nUID,nGID); 1205 1206 return tErr; 1207 } 1208 1209 oslFileError osl_copyFile( rtl_uString* ustrFileURL, rtl_uString* ustrDestURL ) 1210 { 1211 char srcPath[PATH_MAX]; 1212 char destPath[PATH_MAX]; 1213 oslFileError eRet; 1214 APIRET rc; 1215 1216 OSL_ASSERT( ustrFileURL ); 1217 OSL_ASSERT( ustrDestURL ); 1218 1219 /* convert source url to system path */ 1220 eRet = FileURLToPath( srcPath, PATH_MAX, ustrFileURL ); 1221 if( eRet != osl_File_E_None ) 1222 return eRet; 1223 1224 /* convert destination url to system path */ 1225 eRet = FileURLToPath( destPath, PATH_MAX, ustrDestURL ); 1226 if( eRet != osl_File_E_None ) 1227 return eRet; 1228 1229 return osl_psz_copyFile( srcPath, destPath ); 1230 } 1231 1232 /****************************************************************************/ 1233 /* osl_removeFile */ 1234 /****************************************************************************/ 1235 1236 oslFileError osl_removeFile( rtl_uString* ustrFileURL ) 1237 { 1238 char path[PATH_MAX]; 1239 oslFileError eRet; 1240 APIRET rc; 1241 1242 OSL_ASSERT( ustrFileURL ); 1243 1244 /* convert file url to system path */ 1245 eRet = FileURLToPath( path, PATH_MAX, ustrFileURL ); 1246 if( eRet != osl_File_E_None ) 1247 return eRet; 1248 1249 rc = DosDelete( (PCSZ)path); 1250 if (!rc) 1251 eRet = osl_File_E_None; 1252 else 1253 eRet = MapError( rc); 1254 1255 return eRet; 1256 } 1257 1258 /****************************************************************************/ 1259 /* osl_getVolumeInformation */ 1260 /****************************************************************************/ 1261 1262 #define TXFSDC_BLOCKR 0x00 // block device removable 1263 #define TXFSDC_GETBPB 0x00 // get device bpb info 1264 #define TXFSBPB_REMOVABLE 0x08 // BPB attribute for removable 1265 1266 typedef struct drivecmd 1267 { 1268 BYTE cmd; // 0=unlock 1=lock 2=eject 1269 BYTE drv; // 0=A, 1=B 2=C ... 1270 } DRIVECMD; // end of struct "drivecmd" 1271 1272 #pragma pack(push, 1) // byte packing 1273 typedef struct txfs_ebpb // ext. boot parameter block 1274 { // at offset 0x0b in bootsector 1275 USHORT SectSize; // 0B bytes per sector 1276 BYTE ClustSize; // 0D sectors per cluster 1277 USHORT FatOffset; // 0E sectors to 1st FAT 1278 BYTE NrOfFats; // 10 nr of FATS (FAT only) 1279 USHORT RootEntries; // 11 Max entries \ (FAT only) 1280 USHORT Sectors; // 13 nr of sectors if < 64K 1281 BYTE MediaType; // 15 mediatype (F8 for HD) 1282 USHORT FatSectors; // 16 sectors/FAT (FAT only) 1283 USHORT LogGeoSect; // 18 sectors/Track 1284 USHORT LogGeoHead; // 1a nr of heads 1285 ULONG HiddenSectors; // 1c sector-offset from MBR/EBR 1286 ULONG BigSectors; // 20 nr of sectors if >= 64K 1287 } TXFS_EBPB; // last byte is at offset 0x23 1288 1289 typedef struct drivebpb 1290 { 1291 TXFS_EBPB ebpb; // extended BPB 1292 BYTE reserved[6]; 1293 USHORT cyls; 1294 BYTE type; 1295 USHORT attributes; // device attributes 1296 BYTE fill[6]; // documented for IOCtl 1297 } DRIVEBPB; // end of struct "drivebpb" 1298 1299 struct CDInfo { 1300 USHORT usCount; 1301 USHORT usFirst; 1302 }; 1303 1304 #pragma pack(pop) 1305 1306 /*****************************************************************************/ 1307 // Get number of cdrom readers 1308 /*****************************************************************************/ 1309 BOOL GetCDInfo( CDInfo * pCDInfo ) 1310 { 1311 HFILE hFileCD; 1312 ULONG ulAction; 1313 1314 if( NO_ERROR == DosOpen( (PCSZ)"\\DEV\\CD-ROM2$", 1315 &hFileCD, &ulAction, 0, FILE_NORMAL, 1316 OPEN_ACTION_OPEN_IF_EXISTS, 1317 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY, NULL )) { 1318 ULONG ulDataSize = sizeof(CDInfo); 1319 APIRET rc = DosDevIOCtl( hFileCD, 0x82, 0x60, NULL, 0, 1320 NULL, (PVOID)pCDInfo, ulDataSize, &ulDataSize); 1321 DosClose( hFileCD); 1322 if(rc == NO_ERROR) 1323 return TRUE; 1324 } 1325 // failed 1326 pCDInfo->usFirst = 0; 1327 pCDInfo->usCount = 0; 1328 return FALSE; 1329 } 1330 1331 /*****************************************************************************/ 1332 // Determine if unit is a cdrom or not 1333 /*****************************************************************************/ 1334 BOOL DriveIsCDROM(UINT uiDrive, CDInfo *pCDInfo) 1335 { 1336 return (uiDrive >= pCDInfo->usFirst) 1337 && (uiDrive < (pCDInfo->usFirst + pCDInfo->usCount)); 1338 } 1339 1340 /*****************************************************************************/ 1341 // Determine attached fstype, e.g. HPFS for specified drive 1342 /*****************************************************************************/ 1343 BOOL TxFsType // RET FS type resolved 1344 ( 1345 char *drive, // IN Drive specification 1346 char *fstype, // OUT Attached FS type 1347 char *details // OUT details (UNC) or NULL 1348 ) 1349 { 1350 BOOL rc = FALSE; 1351 FSQBUFFER2 *fsinfo; // Attached FS info 1352 ULONG fsdlen = 2048; // Fs info data length 1353 1354 strcpy(fstype, "none"); 1355 if (details) 1356 { 1357 strcpy(details, ""); 1358 } 1359 if ((fsinfo = (FSQBUFFER2*)calloc(1, fsdlen)) != NULL) 1360 { 1361 if (DosQFSAttach((PCSZ)drive, 0, 1, fsinfo, &fsdlen) == NO_ERROR) 1362 { 1363 strcpy(fstype, (char*) fsinfo->szName + fsinfo->cbName +1); 1364 if (details && (fsinfo->cbFSAData != 0)) 1365 { 1366 strcpy( details, (char*) fsinfo->szName + fsinfo->cbName + 1367 fsinfo->cbFSDName +2); 1368 } 1369 rc = TRUE; 1370 } 1371 free(fsinfo); 1372 } 1373 return (rc); 1374 } // end 'TxFsType' 1375 /*---------------------------------------------------------------------------*/ 1376 1377 1378 /*****************************************************************************/ 1379 // Determine if a driveletter represents a removable medium/device 1380 /*****************************************************************************/ 1381 BOOL TxFsIsRemovable // RET drive is removable 1382 ( 1383 char *drive // IN Driveletter to test 1384 ) 1385 { 1386 BOOL rc = FALSE; 1387 DRIVECMD IOCtl; 1388 DRIVEBPB RemAt; 1389 ULONG DataLen; 1390 ULONG ParmLen; 1391 BYTE NoRem; 1392 1393 DosError( FERR_DISABLEHARDERR); // avoid 'not ready' popups 1394 1395 ParmLen = sizeof(IOCtl); 1396 IOCtl.cmd = TXFSDC_BLOCKR; 1397 IOCtl.drv = toupper(drive[0]) - 'A'; 1398 DataLen = sizeof(NoRem); 1399 1400 if (DosDevIOCtl((HFILE) -1, IOCTL_DISK, 1401 DSK_BLOCKREMOVABLE, 1402 &IOCtl, ParmLen, &ParmLen, 1403 &NoRem, DataLen, &DataLen) == NO_ERROR) 1404 { 1405 if (NoRem) // non-removable sofar, check 1406 { // BPB as well (USB devices) 1407 ParmLen = sizeof(IOCtl); 1408 IOCtl.cmd = TXFSDC_GETBPB; 1409 IOCtl.drv = toupper(drive[0]) - 'A'; 1410 DataLen = sizeof(RemAt); 1411 1412 if (DosDevIOCtl((HFILE) -1, IOCTL_DISK, 1413 DSK_GETDEVICEPARAMS, 1414 &IOCtl, ParmLen, &ParmLen, 1415 &RemAt, DataLen, &DataLen) == NO_ERROR) 1416 1417 { 1418 if (RemAt.attributes & TXFSBPB_REMOVABLE) 1419 { 1420 rc = TRUE; // removable, probably USB 1421 } 1422 } 1423 } 1424 else 1425 { 1426 rc = TRUE; // removable block device 1427 } 1428 } 1429 DosError( FERR_ENABLEHARDERR); // enable criterror handler 1430 return (rc); 1431 } // end 'TxFsIsRemovable' 1432 /*---------------------------------------------------------------------------*/ 1433 1434 static oslFileError get_drive_type(const char* path, oslVolumeInfo* pInfo) 1435 { 1436 char Drive_Letter = toupper( *path); 1437 char fstype[ 64]; 1438 1439 pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes; 1440 1441 // check for floppy A/B 1442 BYTE nFloppies; 1443 APIRET rc; 1444 rc = DosDevConfig( (void*) &nFloppies, DEVINFO_FLOPPY ); 1445 if ((Drive_Letter - 'A') < nFloppies) { 1446 pInfo->uAttributes |= osl_Volume_Attribute_Removeable; 1447 pInfo->uAttributes |= osl_Volume_Attribute_FloppyDisk; 1448 return osl_File_E_None; 1449 } 1450 1451 // query system for CD drives 1452 CDInfo cdInfo; 1453 GetCDInfo(&cdInfo); 1454 1455 // query if drive is a CDROM 1456 if (DriveIsCDROM( Drive_Letter - 'A', &cdInfo)) 1457 pInfo->uAttributes |= osl_Volume_Attribute_CompactDisc | osl_Volume_Attribute_Removeable; 1458 1459 if (TxFsIsRemovable( (char*)path)) 1460 pInfo->uAttributes |= osl_Volume_Attribute_Removeable; 1461 1462 if (TxFsType( (char*)path, fstype, NULL) == FALSE) { 1463 // query failed, assume fixed disk 1464 pInfo->uAttributes |= osl_Volume_Attribute_FixedDisk; 1465 return osl_File_E_None; 1466 } 1467 1468 //- Note, connected Win-NT drives use the REAL FS-name like NTFS! 1469 if ((strncasecmp( fstype, "LAN", 3) == 0) //- OS/2 LAN drives 1470 || (strncasecmp( fstype, "NDFS", 4) == 0) //- NetDrive 1471 || (strncasecmp( fstype, "REMOTE", 5) == 0) ) //- NT disconnected 1472 pInfo->uAttributes |= osl_Volume_Attribute_Remote; 1473 else if (strncasecmp( fstype, "RAMFS", 5) == 0) 1474 pInfo->uAttributes |= osl_Volume_Attribute_RAMDisk; 1475 else if ((strncasecmp( fstype, "CD", 2) == 0) // OS2:CDFS, DOS/WIN:CDROM 1476 || (strncasecmp( fstype, "UDF", 3) == 0) ) // OS2:UDF DVD's 1477 pInfo->uAttributes |= osl_Volume_Attribute_CompactDisc | osl_Volume_Attribute_Removeable; 1478 else 1479 pInfo->uAttributes |= osl_Volume_Attribute_FixedDisk; 1480 1481 return osl_File_E_None; 1482 } 1483 1484 //############################################# 1485 inline bool is_volume_space_info_request(sal_uInt32 field_mask) 1486 { 1487 return (field_mask & 1488 (osl_VolumeInfo_Mask_TotalSpace | 1489 osl_VolumeInfo_Mask_UsedSpace | 1490 osl_VolumeInfo_Mask_FreeSpace)); 1491 } 1492 1493 //############################################# 1494 static void get_volume_space_information(const char* path, oslVolumeInfo *pInfo) 1495 { 1496 FSALLOCATE aFSInfoBuf; 1497 ULONG nDriveNumber = toupper( *path) - 'A' + 1; 1498 1499 // disable error popups 1500 DosError(FERR_DISABLEHARDERR); 1501 APIRET rc = DosQueryFSInfo( nDriveNumber, FSIL_ALLOC, 1502 &aFSInfoBuf, sizeof(aFSInfoBuf) ); 1503 // enable error popups 1504 DosError(FERR_ENABLEHARDERR); 1505 if (!rc) 1506 { 1507 uint64_t aBytesPerCluster( uint64_t(aFSInfoBuf.cbSector) * 1508 uint64_t(aFSInfoBuf.cSectorUnit) ); 1509 pInfo->uFreeSpace = aBytesPerCluster * uint64_t(aFSInfoBuf.cUnitAvail); 1510 pInfo->uTotalSpace = aBytesPerCluster * uint64_t(aFSInfoBuf.cUnit); 1511 pInfo->uUsedSpace = pInfo->uTotalSpace - pInfo->uFreeSpace; 1512 pInfo->uValidFields |= osl_VolumeInfo_Mask_TotalSpace | 1513 osl_VolumeInfo_Mask_UsedSpace | 1514 osl_VolumeInfo_Mask_FreeSpace; 1515 } 1516 } 1517 1518 //############################################# 1519 inline bool is_filesystem_attributes_request(sal_uInt32 field_mask) 1520 { 1521 return (field_mask & 1522 (osl_VolumeInfo_Mask_MaxNameLength | 1523 osl_VolumeInfo_Mask_MaxPathLength | 1524 osl_VolumeInfo_Mask_FileSystemName | 1525 osl_VolumeInfo_Mask_FileSystemCaseHandling)); 1526 } 1527 1528 //############################################# 1529 inline bool is_drivetype_request(sal_uInt32 field_mask) 1530 { 1531 return (field_mask & osl_VolumeInfo_Mask_Attributes); 1532 } 1533 1534 typedef struct _FSQBUFFER_ 1535 { 1536 FSQBUFFER2 aBuf; 1537 UCHAR sBuf[64]; 1538 } FSQBUFFER_; 1539 1540 //############################################# 1541 static oslFileError get_filesystem_attributes(const char* path, sal_uInt32 field_mask, oslVolumeInfo* pInfo) 1542 { 1543 pInfo->uAttributes = 0; 1544 1545 oslFileError osl_error = osl_File_E_None; 1546 1547 // osl_get_drive_type must be called first because 1548 // this function resets osl_VolumeInfo_Mask_Attributes 1549 // on failure 1550 if (is_drivetype_request(field_mask)) 1551 osl_error = get_drive_type(path, pInfo); 1552 1553 if ((osl_File_E_None == osl_error) && is_filesystem_attributes_request(field_mask)) 1554 { 1555 FSQBUFFER_ aBuf; 1556 ULONG nBufLen; 1557 APIRET nRet; 1558 1559 nBufLen = sizeof( aBuf ); 1560 // disable error popups 1561 DosError(FERR_DISABLEHARDERR); 1562 nRet = DosQueryFSAttach( (PCSZ)path, 0, FSAIL_QUERYNAME, (_FSQBUFFER2*) &aBuf, &nBufLen ); 1563 if ( !nRet ) 1564 { 1565 char *pType = (char*)(aBuf.aBuf.szName + aBuf.aBuf.cbName + 1); 1566 pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxNameLength; 1567 pInfo->uMaxNameLength = _MAX_FNAME; 1568 1569 pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxPathLength; 1570 pInfo->uMaxPathLength = _MAX_PATH; 1571 1572 pInfo->uValidFields |= osl_VolumeInfo_Mask_FileSystemName; 1573 rtl_uString_newFromAscii(&pInfo->ustrFileSystemName, pType); 1574 1575 // case is preserved always except for FAT 1576 if (strcmp( pType, "FAT" )) 1577 pInfo->uAttributes |= osl_Volume_Attribute_Case_Is_Preserved; 1578 1579 pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes; 1580 } 1581 // enable error popups 1582 DosError(FERR_ENABLEHARDERR); 1583 } 1584 return osl_error; 1585 } 1586 1587 oslFileError SAL_CALL osl_getVolumeInformation( rtl_uString* ustrDirectoryURL, oslVolumeInfo* pInfo, sal_uInt32 uFieldMask ) 1588 { 1589 char volume_root[PATH_MAX]; 1590 oslFileError error; 1591 1592 OSL_ASSERT( ustrDirectoryURL ); 1593 OSL_ASSERT( pInfo ); 1594 1595 /* convert directory url to system path */ 1596 error = FileURLToPath( volume_root, PATH_MAX, ustrDirectoryURL ); 1597 if( error != osl_File_E_None ) 1598 return error; 1599 1600 if (!pInfo) 1601 return osl_File_E_INVAL; 1602 1603 pInfo->uValidFields = 0; 1604 1605 if ((error = get_filesystem_attributes(volume_root, uFieldMask, pInfo)) != osl_File_E_None) 1606 return error; 1607 1608 if (is_volume_space_info_request(uFieldMask)) 1609 get_volume_space_information(volume_root, pInfo); 1610 1611 if (uFieldMask & osl_VolumeInfo_Mask_DeviceHandle) 1612 { 1613 pInfo->uValidFields |= osl_VolumeInfo_Mask_DeviceHandle; 1614 rtl_uString* uVolumeRoot; 1615 rtl_uString_newFromAscii( &uVolumeRoot, volume_root); 1616 osl_getFileURLFromSystemPath( uVolumeRoot, (rtl_uString**)&pInfo->pDeviceHandle); 1617 rtl_uString_release( uVolumeRoot); 1618 } 1619 1620 return osl_File_E_None; 1621 } 1622 1623 /****************************************************************************/ 1624 /* osl_getFileStatus */ 1625 /****************************************************************************/ 1626 static oslFileError _osl_getDriveInfo( 1627 oslDirectoryItem Item, oslFileStatus *pStatus, sal_uInt32 uFieldMask) 1628 { 1629 DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item; 1630 sal_Unicode cDrive[3]; 1631 sal_Unicode cRoot[4]; 1632 1633 if ( !pItemImpl ) 1634 return osl_File_E_INVAL; 1635 1636 pStatus->uValidFields = 0; 1637 1638 cDrive[0] = pItemImpl->ustrDrive->buffer[0]; 1639 cDrive[1] = (sal_Unicode)':'; 1640 cDrive[2] = 0; 1641 cRoot[0] = pItemImpl->ustrDrive->buffer[0]; 1642 cRoot[1] = (sal_Unicode)':'; 1643 cRoot[2] = 0; 1644 1645 if ( uFieldMask & osl_FileStatus_Mask_FileName ) 1646 { 1647 if ( pItemImpl->ustrDrive->buffer[0] == '\\' && 1648 pItemImpl->ustrDrive->buffer[1] == '\\' ) 1649 { 1650 LPCWSTR lpFirstBkSlash = wcschr( (const wchar_t*)&pItemImpl->ustrDrive->buffer[2], '\\' ); 1651 1652 if ( lpFirstBkSlash && lpFirstBkSlash[1] ) 1653 { 1654 LPCWSTR lpLastBkSlash = wcschr( (const wchar_t*)&lpFirstBkSlash[1], '\\' ); 1655 1656 if ( lpLastBkSlash ) 1657 rtl_uString_newFromStr_WithLength( &pStatus->ustrFileName, (sal_Unicode*)&lpFirstBkSlash[1], lpLastBkSlash - lpFirstBkSlash - 1 ); 1658 else 1659 rtl_uString_newFromStr( &pStatus->ustrFileName, (sal_Unicode*)&lpFirstBkSlash[1] ); 1660 pStatus->uValidFields |= osl_FileStatus_Mask_FileName; 1661 } 1662 } 1663 else 1664 { 1665 FSINFO aFSInfoBuf; 1666 ULONG ulFSInfoLevel = FSIL_VOLSER; 1667 ULONG nDriveNumber; 1668 char szFileName[ _MAX_PATH]; 1669 1670 nDriveNumber = toupper(*cDrive) - 'A' + 1; 1671 memset( &aFSInfoBuf, 0, sizeof(FSINFO) ); 1672 // disable error popups 1673 DosError(FERR_DISABLEHARDERR); 1674 APIRET rc = DosQueryFSInfo( nDriveNumber, ulFSInfoLevel, &aFSInfoBuf, sizeof(FSINFO) ); 1675 // enable error popups 1676 DosError(FERR_ENABLEHARDERR); 1677 memset( szFileName, 0, sizeof( szFileName)); 1678 *szFileName = toupper(*cDrive); 1679 strcat( szFileName, ": ["); 1680 if ( !rc || aFSInfoBuf.vol.cch) 1681 strncat( szFileName, aFSInfoBuf.vol.szVolLabel, aFSInfoBuf.vol.cch); 1682 strcat( szFileName, "]"); 1683 rtl_uString_newFromAscii( &pStatus->ustrFileName, szFileName ); 1684 1685 pStatus->uValidFields |= osl_FileStatus_Mask_FileName; 1686 } 1687 } 1688 1689 pStatus->eType = osl_File_Type_Volume; 1690 pStatus->uValidFields |= osl_FileStatus_Mask_Type; 1691 1692 if ( uFieldMask & osl_FileStatus_Mask_FileURL ) 1693 { 1694 rtl_uString *ustrSystemPath = NULL; 1695 1696 rtl_uString_newFromStr( &ustrSystemPath, pItemImpl->ustrDrive->buffer ); 1697 osl_getFileURLFromSystemPath( ustrSystemPath, &pStatus->ustrFileURL ); 1698 rtl_uString_release( ustrSystemPath ); 1699 pStatus->uValidFields |= osl_FileStatus_Mask_FileURL; 1700 } 1701 1702 return osl_File_E_None; 1703 } 1704 1705 oslFileError SAL_CALL osl_getFileStatus( 1706 oslDirectoryItem Item, 1707 oslFileStatus *pStatus, 1708 sal_uInt32 uFieldMask ) 1709 { 1710 DirectoryItem_Impl *pItemImpl = (DirectoryItem_Impl *)Item; 1711 struct stat file_stat; 1712 1713 if ( !pItemImpl ) 1714 return osl_File_E_INVAL; 1715 1716 if ( pItemImpl->uType == DIRECTORYITEM_DRIVE) 1717 return _osl_getDriveInfo( Item, pStatus, uFieldMask ); 1718 1719 osl::lstat(pItemImpl->ustrFilePath, file_stat); 1720 if ( uFieldMask & osl_FileStatus_Mask_Validate ) 1721 { 1722 uFieldMask &= ~ osl_FileStatus_Mask_Validate; 1723 } 1724 1725 /* If no fields to retrieve left ignore pStatus */ 1726 if ( !uFieldMask ) 1727 return osl_File_E_None; 1728 1729 /* Otherwise, this must be a valid pointer */ 1730 if ( !pStatus ) 1731 return osl_File_E_INVAL; 1732 1733 if ( pStatus->uStructSize != sizeof(oslFileStatus) ) 1734 return osl_File_E_INVAL; 1735 1736 pStatus->uValidFields = 0; 1737 1738 /* File time stamps */ 1739 1740 if ( (uFieldMask & osl_FileStatus_Mask_ModifyTime)) 1741 { 1742 pStatus->aModifyTime.Seconds = file_stat.st_mtime; 1743 pStatus->aModifyTime.Nanosec = 0; 1744 pStatus->uValidFields |= osl_FileStatus_Mask_ModifyTime; 1745 } 1746 1747 if ( (uFieldMask & osl_FileStatus_Mask_AccessTime)) 1748 { 1749 pStatus->aAccessTime.Seconds = file_stat.st_atime; 1750 pStatus->aAccessTime.Nanosec = 0; 1751 pStatus->uValidFields |= osl_FileStatus_Mask_AccessTime; 1752 } 1753 1754 if ( (uFieldMask & osl_FileStatus_Mask_CreationTime)) 1755 { 1756 pStatus->aAccessTime.Seconds = file_stat.st_birthtime; 1757 pStatus->aAccessTime.Nanosec = 0; 1758 pStatus->uValidFields |= osl_FileStatus_Mask_CreationTime; 1759 } 1760 1761 /* Most of the fields are already set, regardless of requiered fields */ 1762 1763 osl_systemPathGetFileNameOrLastDirectoryPart(pItemImpl->ustrFilePath, &pStatus->ustrFileName); 1764 pStatus->uValidFields |= osl_FileStatus_Mask_FileName; 1765 1766 if (S_ISLNK(file_stat.st_mode)) 1767 pStatus->eType = osl_File_Type_Link; 1768 else if (S_ISDIR(file_stat.st_mode)) 1769 pStatus->eType = osl_File_Type_Directory; 1770 else if (S_ISREG(file_stat.st_mode)) 1771 pStatus->eType = osl_File_Type_Regular; 1772 else if (S_ISFIFO(file_stat.st_mode)) 1773 pStatus->eType = osl_File_Type_Fifo; 1774 else if (S_ISSOCK(file_stat.st_mode)) 1775 pStatus->eType = osl_File_Type_Socket; 1776 else if (S_ISCHR(file_stat.st_mode) || S_ISBLK(file_stat.st_mode)) 1777 pStatus->eType = osl_File_Type_Special; 1778 else 1779 pStatus->eType = osl_File_Type_Unknown; 1780 1781 pStatus->uValidFields |= osl_FileStatus_Mask_Type; 1782 1783 pStatus->uAttributes = pItemImpl->d_attr; 1784 pStatus->uValidFields |= osl_FileStatus_Mask_Attributes; 1785 1786 pStatus->uFileSize = file_stat.st_size; 1787 pStatus->uValidFields |= osl_FileStatus_Mask_FileSize; 1788 1789 if ( uFieldMask & osl_FileStatus_Mask_LinkTargetURL ) 1790 { 1791 rtl_uString *ustrFullPath = NULL; 1792 1793 rtl_uString_newFromStr( &ustrFullPath, rtl_uString_getStr(pItemImpl->ustrFilePath) ); 1794 osl_getFileURLFromSystemPath( ustrFullPath, &pStatus->ustrLinkTargetURL ); 1795 rtl_uString_release( ustrFullPath ); 1796 1797 pStatus->uValidFields |= osl_FileStatus_Mask_LinkTargetURL; 1798 } 1799 1800 if ( uFieldMask & osl_FileStatus_Mask_FileURL ) 1801 { 1802 rtl_uString *ustrFullPath = NULL; 1803 1804 rtl_uString_newFromStr( &ustrFullPath, rtl_uString_getStr(pItemImpl->ustrFilePath) ); 1805 osl_getFileURLFromSystemPath( ustrFullPath, &pStatus->ustrFileURL ); 1806 rtl_uString_release( ustrFullPath ); 1807 pStatus->uValidFields |= osl_FileStatus_Mask_FileURL; 1808 } 1809 1810 return osl_File_E_None; 1811 } 1812 1813 /****************************************************************************/ 1814 /* osl_createDirectory */ 1815 /****************************************************************************/ 1816 1817 oslFileError osl_createDirectory( rtl_uString* ustrDirectoryURL ) 1818 { 1819 char path[PATH_MAX]; 1820 oslFileError eRet; 1821 APIRET rc; 1822 1823 OSL_ASSERT( ustrDirectoryURL ); 1824 1825 /* convert directory url to system path */ 1826 eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL ); 1827 if( eRet != osl_File_E_None ) 1828 return eRet; 1829 1830 rc = DosCreateDir( (PCSZ)path, NULL); 1831 if (rc == ERROR_ACCESS_DENIED) 1832 rc=ERROR_FILE_EXISTS; 1833 1834 if (!rc) 1835 eRet = osl_File_E_None; 1836 else 1837 eRet = MapError( rc); 1838 1839 return eRet; 1840 } 1841 1842 /****************************************************************************/ 1843 /* osl_removeDirectory */ 1844 /****************************************************************************/ 1845 1846 oslFileError osl_removeDirectory( rtl_uString* ustrDirectoryURL ) 1847 { 1848 char path[PATH_MAX]; 1849 oslFileError eRet; 1850 APIRET rc; 1851 1852 OSL_ASSERT( ustrDirectoryURL ); 1853 1854 /* convert directory url to system path */ 1855 eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL ); 1856 if( eRet != osl_File_E_None ) 1857 return eRet; 1858 1859 rc = DosDeleteDir( (PCSZ)path); 1860 if (!rc) 1861 eRet = osl_File_E_None; 1862 else 1863 eRet = MapError( rc); 1864 1865 return eRet; 1866 } 1867 1868 //############################################# 1869 int path_make_parent(sal_Unicode* path) 1870 { 1871 int i = rtl_ustr_lastIndexOfChar(path, '/'); 1872 1873 if (i > 0) 1874 { 1875 *(path + i) = 0; 1876 return i; 1877 } 1878 else 1879 return 0; 1880 } 1881 1882 //############################################# 1883 int create_dir_with_callback( 1884 sal_Unicode* directory_path, 1885 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc, 1886 void* pData) 1887 { 1888 int mode = S_IRWXU | S_IRWXG | S_IRWXO; 1889 1890 if (osl::mkdir(directory_path, mode) == 0) 1891 { 1892 if (aDirectoryCreationCallbackFunc) 1893 { 1894 rtl::OUString url; 1895 osl::FileBase::getFileURLFromSystemPath(directory_path, url); 1896 aDirectoryCreationCallbackFunc(pData, url.pData); 1897 } 1898 return 0; 1899 } 1900 return errno; 1901 } 1902 1903 //############################################# 1904 oslFileError create_dir_recursively_( 1905 sal_Unicode* dir_path, 1906 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc, 1907 void* pData) 1908 { 1909 OSL_PRECOND((rtl_ustr_getLength(dir_path) > 0) && ((dir_path + (rtl_ustr_getLength(dir_path) - 1)) != (dir_path + rtl_ustr_lastIndexOfChar(dir_path, '/'))), \ 1910 "Path must not end with a slash"); 1911 1912 int native_err = create_dir_with_callback( 1913 dir_path, aDirectoryCreationCallbackFunc, pData); 1914 1915 if (native_err == 0) 1916 return osl_File_E_None; 1917 1918 if (native_err != ENOENT) 1919 return oslTranslateFileError(OSL_FET_ERROR, native_err); 1920 1921 // we step back until '/a_dir' at maximum because 1922 // we should get an error unequal ENOENT when 1923 // we try to create 'a_dir' at '/' and would so 1924 // return before 1925 int pos = path_make_parent(dir_path); 1926 1927 oslFileError osl_error = create_dir_recursively_( 1928 dir_path, aDirectoryCreationCallbackFunc, pData); 1929 1930 if (osl_File_E_None != osl_error) 1931 return osl_error; 1932 1933 dir_path[pos] = '/'; 1934 1935 return create_dir_recursively_(dir_path, aDirectoryCreationCallbackFunc, pData); 1936 } 1937 1938 //####################################### 1939 oslFileError SAL_CALL osl_createDirectoryPath( 1940 rtl_uString* aDirectoryUrl, 1941 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc, 1942 void* pData) 1943 { 1944 if (aDirectoryUrl == NULL) 1945 return osl_File_E_INVAL; 1946 1947 rtl::OUString sys_path; 1948 oslFileError osl_error = osl_getSystemPathFromFileURL_Ex( 1949 aDirectoryUrl, &sys_path.pData, sal_False); 1950 1951 if (osl_error != osl_File_E_None) 1952 return osl_error; 1953 1954 osl::systemPathRemoveSeparator(sys_path); 1955 1956 // const_cast because sys_path is a local copy which we want to modify inplace instead of 1957 // coyp it into another buffer on the heap again 1958 return create_dir_recursively_(sys_path.pData->buffer, aDirectoryCreationCallbackFunc, pData); 1959 } 1960 1961 /****************************************************************************/ 1962 /* osl_getCanonicalName */ 1963 /****************************************************************************/ 1964 1965 oslFileError osl_getCanonicalName( rtl_uString* ustrFileURL, rtl_uString** pustrValidURL ) 1966 { 1967 OSL_ENSURE(sal_False, "osl_getCanonicalName not implemented"); 1968 1969 rtl_uString_newFromString(pustrValidURL, ustrFileURL); 1970 return osl_File_E_None; 1971 } 1972 1973 1974 /****************************************************************************/ 1975 /* osl_setFileAttributes */ 1976 /****************************************************************************/ 1977 1978 oslFileError osl_setFileAttributes( rtl_uString* ustrFileURL, sal_uInt64 uAttributes ) 1979 { 1980 char path[PATH_MAX]; 1981 oslFileError eRet; 1982 FILESTATUS3 fsts3ConfigInfo; 1983 ULONG ulBufSize = sizeof(FILESTATUS3); 1984 APIRET rc = NO_ERROR; 1985 1986 OSL_ASSERT( ustrFileURL ); 1987 1988 /* convert file url to system path */ 1989 eRet = FileURLToPath( path, PATH_MAX, ustrFileURL ); 1990 if( eRet != osl_File_E_None ) 1991 return eRet; 1992 1993 /* query current attributes */ 1994 rc = DosQueryPathInfo( (PCSZ)path, FIL_STANDARD, &fsts3ConfigInfo, ulBufSize); 1995 if (rc != NO_ERROR) 1996 return MapError( rc); 1997 1998 /* set/reset readonly/hidden (see w32\file.cxx) */ 1999 fsts3ConfigInfo.attrFile &= ~(FILE_READONLY | FILE_HIDDEN); 2000 if ( uAttributes & osl_File_Attribute_ReadOnly ) 2001 fsts3ConfigInfo.attrFile |= FILE_READONLY; 2002 if ( uAttributes & osl_File_Attribute_Hidden ) 2003 fsts3ConfigInfo.attrFile |= FILE_HIDDEN; 2004 2005 /* write new attributes */ 2006 rc = DosSetPathInfo( (PCSZ)path, FIL_STANDARD, &fsts3ConfigInfo, ulBufSize, 0); 2007 if (rc != NO_ERROR) 2008 return MapError( rc); 2009 2010 /* everything ok */ 2011 return osl_File_E_None; 2012 } 2013 2014 /****************************************************************************/ 2015 /* osl_setFileTime */ 2016 /****************************************************************************/ 2017 2018 oslFileError osl_setFileTime( rtl_uString* ustrFileURL, const TimeValue* pCreationTime, 2019 const TimeValue* pLastAccessTime, const TimeValue* pLastWriteTime ) 2020 { 2021 char path[PATH_MAX]; 2022 oslFileError eRet; 2023 2024 OSL_ASSERT( ustrFileURL ); 2025 2026 /* convert file url to system path */ 2027 eRet = FileURLToPath( path, PATH_MAX, ustrFileURL ); 2028 if( eRet != osl_File_E_None ) 2029 return eRet; 2030 2031 return osl_psz_setFileTime( path, pCreationTime, pLastAccessTime, pLastWriteTime ); 2032 } 2033 2034 /****************************************************************************** 2035 * 2036 * Exported Module Functions 2037 * (independent of C or Unicode Strings) 2038 * 2039 *****************************************************************************/ 2040 2041 2042 /******************************************* 2043 osl_readFile 2044 ********************************************/ 2045 2046 oslFileError osl_readFile(oslFileHandle Handle, void* pBuffer, sal_uInt64 uBytesRequested, sal_uInt64* pBytesRead) 2047 { 2048 ssize_t nBytes = 0; 2049 oslFileHandleImpl* pHandleImpl = (oslFileHandleImpl*)Handle; 2050 2051 if ((0 == pHandleImpl) || (pHandleImpl->fd < 0) || (0 == pBuffer) || (0 == pBytesRead)) 2052 return osl_File_E_INVAL; 2053 2054 nBytes = read(pHandleImpl->fd, pBuffer, uBytesRequested); 2055 2056 if (-1 == nBytes) 2057 return oslTranslateFileError(OSL_FET_ERROR, errno); 2058 2059 *pBytesRead = nBytes; 2060 return osl_File_E_None; 2061 } 2062 2063 /******************************************* 2064 osl_writeFile 2065 ********************************************/ 2066 2067 oslFileError osl_writeFile(oslFileHandle Handle, const void* pBuffer, sal_uInt64 uBytesToWrite, sal_uInt64* pBytesWritten) 2068 { 2069 ssize_t nBytes = 0; 2070 oslFileHandleImpl* pHandleImpl = (oslFileHandleImpl*)Handle; 2071 2072 OSL_ASSERT(pHandleImpl); 2073 OSL_ASSERT(pBuffer); 2074 OSL_ASSERT(pBytesWritten); 2075 2076 if ((0 == pHandleImpl) || (0 == pBuffer) || (0 == pBytesWritten)) 2077 return osl_File_E_INVAL; 2078 2079 OSL_ASSERT(pHandleImpl->fd >= 0); 2080 2081 if (pHandleImpl->fd < 0) 2082 return osl_File_E_INVAL; 2083 2084 nBytes = write(pHandleImpl->fd, pBuffer, uBytesToWrite); 2085 2086 if (-1 == nBytes) 2087 return oslTranslateFileError(OSL_FET_ERROR, errno); 2088 2089 *pBytesWritten = nBytes; 2090 return osl_File_E_None; 2091 } 2092 2093 /******************************************* 2094 osl_writeFile 2095 ********************************************/ 2096 2097 oslFileError osl_setFilePos( oslFileHandle Handle, sal_uInt32 uHow, sal_Int64 uPos ) 2098 { 2099 oslFileHandleImpl* pHandleImpl=0; 2100 int nRet=0; 2101 off_t nOffset=0; 2102 2103 pHandleImpl = (oslFileHandleImpl*) Handle; 2104 if ( pHandleImpl == 0 ) 2105 { 2106 return osl_File_E_INVAL; 2107 } 2108 2109 if ( pHandleImpl->fd < 0 ) 2110 { 2111 return osl_File_E_INVAL; 2112 } 2113 2114 /* FIXME mfe: setFilePos: Do we have any runtime function to determine LONG_MAX? */ 2115 if ( uPos > LONG_MAX ) 2116 { 2117 return osl_File_E_OVERFLOW; 2118 } 2119 2120 nOffset=(off_t)uPos; 2121 2122 switch(uHow) 2123 { 2124 case osl_Pos_Absolut: 2125 nOffset = lseek(pHandleImpl->fd,nOffset,SEEK_SET); 2126 break; 2127 2128 case osl_Pos_Current: 2129 nOffset = lseek(pHandleImpl->fd,nOffset,SEEK_CUR); 2130 break; 2131 2132 case osl_Pos_End: 2133 nOffset = lseek(pHandleImpl->fd,nOffset,SEEK_END); 2134 break; 2135 2136 default: 2137 return osl_File_E_INVAL; 2138 } 2139 2140 if ( nOffset < 0 ) 2141 { 2142 nRet=errno; 2143 return oslTranslateFileError(OSL_FET_ERROR, nRet); 2144 } 2145 2146 return osl_File_E_None; 2147 } 2148 2149 /************************************************ 2150 * osl_getFilePos 2151 ***********************************************/ 2152 2153 oslFileError osl_getFilePos( oslFileHandle Handle, sal_uInt64* pPos ) 2154 { 2155 oslFileHandleImpl* pHandleImpl=0; 2156 off_t nOffset=0; 2157 int nRet=0; 2158 2159 pHandleImpl = (oslFileHandleImpl*) Handle; 2160 if ( pHandleImpl == 0 || pPos == 0) 2161 { 2162 return osl_File_E_INVAL; 2163 } 2164 2165 if ( pHandleImpl->fd < 0 ) 2166 { 2167 return osl_File_E_INVAL; 2168 } 2169 2170 nOffset = lseek(pHandleImpl->fd,0,SEEK_CUR); 2171 2172 if (nOffset < 0) 2173 { 2174 nRet =errno; 2175 2176 /* *pPos =0; */ 2177 2178 return oslTranslateFileError(OSL_FET_ERROR, nRet); 2179 } 2180 2181 *pPos=nOffset; 2182 2183 return osl_File_E_None; 2184 } 2185 2186 /**************************************************************************** 2187 * osl_getFileSize 2188 ****************************************************************************/ 2189 2190 oslFileError osl_getFileSize( oslFileHandle Handle, sal_uInt64* pSize ) 2191 { 2192 oslFileHandleImpl* pHandleImpl=(oslFileHandleImpl*) Handle; 2193 if (pHandleImpl == 0) 2194 return osl_File_E_INVAL; 2195 2196 struct stat file_stat; 2197 if (fstat(pHandleImpl->fd, &file_stat) == -1) 2198 return oslTranslateFileError(OSL_FET_ERROR, errno); 2199 2200 *pSize = file_stat.st_size; 2201 return osl_File_E_None; 2202 } 2203 2204 /************************************************ 2205 * osl_setFileSize 2206 ***********************************************/ 2207 2208 oslFileError osl_setFileSize( oslFileHandle Handle, sal_uInt64 uSize ) 2209 { 2210 oslFileHandleImpl* pHandleImpl=0; 2211 off_t nOffset=0; 2212 2213 pHandleImpl = (oslFileHandleImpl*) Handle; 2214 if ( pHandleImpl == 0 ) 2215 { 2216 return osl_File_E_INVAL; 2217 } 2218 2219 if ( pHandleImpl->fd < 0 ) 2220 { 2221 return osl_File_E_INVAL; 2222 } 2223 2224 /* FIXME: mfe: setFileSize: Do we have any runtime function to determine LONG_MAX? */ 2225 if ( uSize > LONG_MAX ) 2226 { 2227 return osl_File_E_OVERFLOW; 2228 } 2229 2230 nOffset = (off_t)uSize; 2231 if (ftruncate (pHandleImpl->fd, nOffset) < 0) 2232 { 2233 /* Failure. Try fallback algorithm */ 2234 oslFileError result; 2235 struct stat aStat; 2236 off_t nCurPos; 2237 2238 /* Save original result */ 2239 result = oslTranslateFileError (OSL_FET_ERROR, errno); 2240 PERROR("ftruncate", "Try osl_setFileSize [fallback]\n"); 2241 2242 /* Check against current size. Fail upon 'shrink' */ 2243 if (fstat (pHandleImpl->fd, &aStat) < 0) 2244 { 2245 PERROR("ftruncate: fstat", "Out osl_setFileSize [error]\n"); 2246 return (result); 2247 } 2248 if ((0 <= nOffset) && (nOffset <= aStat.st_size)) 2249 { 2250 /* Failure upon 'shrink'. Return original result */ 2251 return (result); 2252 } 2253 2254 /* Save current position */ 2255 nCurPos = (off_t)lseek (pHandleImpl->fd, (off_t)0, SEEK_CUR); 2256 if (nCurPos == (off_t)(-1)) 2257 { 2258 PERROR("ftruncate: lseek", "Out osl_setFileSize [error]\n"); 2259 return (result); 2260 } 2261 2262 /* Try 'expand' via 'lseek()' and 'write()' */ 2263 if (lseek (pHandleImpl->fd, (off_t)(nOffset - 1), SEEK_SET) < 0) 2264 { 2265 PERROR("ftruncate: lseek", "Out osl_setFileSize [error]\n"); 2266 return (result); 2267 } 2268 if (write (pHandleImpl->fd, (char*)"", (size_t)1) < 0) 2269 { 2270 /* Failure. Restore saved position */ 2271 PERROR("ftruncate: write", "Out osl_setFileSize [error]\n"); 2272 if (lseek (pHandleImpl->fd, (off_t)nCurPos, SEEK_SET) < 0) 2273 { 2274 #ifdef DEBUG_OSL_FILE 2275 perror("ftruncate: lseek"); 2276 #endif /* DEBUG_OSL_FILE */ 2277 } 2278 return (result); 2279 } 2280 2281 /* Success. Restore saved position */ 2282 if (lseek (pHandleImpl->fd, (off_t)nCurPos, SEEK_SET) < 0) 2283 { 2284 PERROR("ftruncate: lseek", "Out osl_setFileSize [error]"); 2285 return (result); 2286 } 2287 } 2288 2289 return (osl_File_E_None); 2290 } 2291 2292 /*###############################################*/ 2293 oslFileError SAL_CALL osl_syncFile(oslFileHandle Handle) 2294 { 2295 oslFileHandleImpl* handle_impl = (oslFileHandleImpl*)Handle; 2296 2297 if (handle_impl == 0) 2298 return osl_File_E_INVAL; 2299 2300 if (fsync(handle_impl->fd) == -1) 2301 return oslTranslateFileError(OSL_FET_ERROR, errno); 2302 2303 return osl_File_E_None; 2304 } 2305 2306 /****************************************************************************** 2307 * 2308 * C-String Versions of Exported Module Functions 2309 * 2310 *****************************************************************************/ 2311 2312 #ifdef HAVE_STATFS_H 2313 2314 #if defined(FREEBSD) || defined(NETBSD) || defined(MACOSX) 2315 # define __OSL_STATFS_STRUCT struct statfs 2316 # define __OSL_STATFS(dir, sfs) statfs((dir), (sfs)) 2317 # define __OSL_STATFS_BLKSIZ(a) ((sal_uInt64)((a).f_bsize)) 2318 # define __OSL_STATFS_TYPENAME(a) ((a).f_fstypename) 2319 # define __OSL_STATFS_ISREMOTE(a) (((a).f_type & MNT_LOCAL) == 0) 2320 2321 /* always return true if queried for the properties of 2322 the file system. If you think this is wrong under any 2323 of the target platforms fix it!!!! */ 2324 # define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a) (1) 2325 # define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) (1) 2326 #endif /* FREEBSD || NETBSD */ 2327 2328 #if defined(LINUX) 2329 # define __OSL_NFS_SUPER_MAGIC 0x6969 2330 # define __OSL_SMB_SUPER_MAGIC 0x517B 2331 # define __OSL_MSDOS_SUPER_MAGIC 0x4d44 2332 # define __OSL_NTFS_SUPER_MAGIC 0x5346544e 2333 # define __OSL_STATFS_STRUCT struct statfs 2334 # define __OSL_STATFS(dir, sfs) statfs((dir), (sfs)) 2335 # define __OSL_STATFS_BLKSIZ(a) ((sal_uInt64)((a).f_bsize)) 2336 # define __OSL_STATFS_IS_NFS(a) (__OSL_NFS_SUPER_MAGIC == (a).f_type) 2337 # define __OSL_STATFS_IS_SMB(a) (__OSL_SMB_SUPER_MAGIC == (a).f_type) 2338 # define __OSL_STATFS_ISREMOTE(a) (__OSL_STATFS_IS_NFS((a)) || __OSL_STATFS_IS_SMB((a))) 2339 # define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a) ((__OSL_MSDOS_SUPER_MAGIC != (a).f_type) && (__OSL_NTFS_SUPER_MAGIC != (a).f_type)) 2340 # define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) ((__OSL_MSDOS_SUPER_MAGIC != (a).f_type)) 2341 #endif /* LINUX */ 2342 2343 #if defined(SOLARIS) 2344 # define __OSL_STATFS_STRUCT struct statvfs 2345 # define __OSL_STATFS(dir, sfs) statvfs((dir), (sfs)) 2346 # define __OSL_STATFS_BLKSIZ(a) ((sal_uInt64)((a).f_frsize)) 2347 # define __OSL_STATFS_TYPENAME(a) ((a).f_basetype) 2348 # define __OSL_STATFS_ISREMOTE(a) (rtl_str_compare((a).f_basetype, "nfs") == 0) 2349 2350 /* always return true if queried for the properties of 2351 the file system. If you think this is wrong under any 2352 of the target platforms fix it!!!! */ 2353 # define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a) (1) 2354 # define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) (1) 2355 #endif /* SOLARIS */ 2356 2357 # define __OSL_STATFS_INIT(a) (memset(&(a), 0, sizeof(__OSL_STATFS_STRUCT))) 2358 2359 #else /* no statfs available */ 2360 2361 # define __OSL_STATFS_STRUCT struct dummy {int i;} 2362 # define __OSL_STATFS_INIT(a) ((void)0) 2363 # define __OSL_STATFS(dir, sfs) (1) 2364 # define __OSL_STATFS_ISREMOTE(sfs) (0) 2365 # define __OSL_STATFS_IS_CASE_SENSITIVE_FS(a) (1) 2366 # define __OSL_STATFS_IS_CASE_PRESERVING_FS(a) (1) 2367 #endif /* HAVE_STATFS_H */ 2368 2369 2370 static oslFileError osl_psz_getVolumeInformation ( 2371 const sal_Char* pszDirectory, oslVolumeInfo* pInfo, sal_uInt32 uFieldMask) 2372 { 2373 __OSL_STATFS_STRUCT sfs; 2374 2375 if (!pInfo) 2376 return osl_File_E_INVAL; 2377 2378 __OSL_STATFS_INIT(sfs); 2379 2380 pInfo->uValidFields = 0; 2381 pInfo->uAttributes = 0; 2382 2383 if ((__OSL_STATFS(pszDirectory, &sfs)) < 0) 2384 { 2385 oslFileError result = oslTranslateFileError(OSL_FET_ERROR, errno); 2386 return (result); 2387 } 2388 2389 /* FIXME: how to detect the kind of storage (fixed, cdrom, ...) */ 2390 if (uFieldMask & osl_VolumeInfo_Mask_Attributes) 2391 { 2392 if (__OSL_STATFS_ISREMOTE(sfs)) 2393 pInfo->uAttributes |= osl_Volume_Attribute_Remote; 2394 2395 pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes; 2396 } 2397 2398 if (uFieldMask & osl_VolumeInfo_Mask_FileSystemCaseHandling) 2399 { 2400 if (__OSL_STATFS_IS_CASE_SENSITIVE_FS(sfs)) 2401 pInfo->uAttributes |= osl_Volume_Attribute_Case_Sensitive; 2402 2403 if (__OSL_STATFS_IS_CASE_PRESERVING_FS(sfs)) 2404 pInfo->uAttributes |= osl_Volume_Attribute_Case_Is_Preserved; 2405 2406 pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes; 2407 } 2408 2409 pInfo->uTotalSpace = 0; 2410 pInfo->uFreeSpace = 0; 2411 pInfo->uUsedSpace = 0; 2412 2413 #if defined(__OSL_STATFS_BLKSIZ) 2414 2415 if ((uFieldMask & osl_VolumeInfo_Mask_TotalSpace) || 2416 (uFieldMask & osl_VolumeInfo_Mask_UsedSpace)) 2417 { 2418 pInfo->uTotalSpace = __OSL_STATFS_BLKSIZ(sfs); 2419 pInfo->uTotalSpace *= (sal_uInt64)(sfs.f_blocks); 2420 pInfo->uValidFields |= osl_VolumeInfo_Mask_TotalSpace; 2421 } 2422 2423 if ((uFieldMask & osl_VolumeInfo_Mask_FreeSpace) || 2424 (uFieldMask & osl_VolumeInfo_Mask_UsedSpace)) 2425 { 2426 pInfo->uFreeSpace = __OSL_STATFS_BLKSIZ(sfs); 2427 2428 if (getuid() == 0) 2429 pInfo->uFreeSpace *= (sal_uInt64)(sfs.f_bfree); 2430 else 2431 pInfo->uFreeSpace *= (sal_uInt64)(sfs.f_bavail); 2432 2433 pInfo->uValidFields |= osl_VolumeInfo_Mask_FreeSpace; 2434 } 2435 2436 #endif /* __OSL_STATFS_BLKSIZ */ 2437 2438 if ((pInfo->uValidFields & osl_VolumeInfo_Mask_TotalSpace) && 2439 (pInfo->uValidFields & osl_VolumeInfo_Mask_FreeSpace )) 2440 { 2441 pInfo->uUsedSpace = pInfo->uTotalSpace - pInfo->uFreeSpace; 2442 pInfo->uValidFields |= osl_VolumeInfo_Mask_UsedSpace; 2443 } 2444 2445 pInfo->uMaxNameLength = 0; 2446 if (uFieldMask & osl_VolumeInfo_Mask_MaxNameLength) 2447 { 2448 long nLen = pathconf(pszDirectory, _PC_NAME_MAX); 2449 if (nLen > 0) 2450 { 2451 pInfo->uMaxNameLength = (sal_uInt32)nLen; 2452 pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxNameLength; 2453 } 2454 } 2455 2456 pInfo->uMaxPathLength = 0; 2457 if (uFieldMask & osl_VolumeInfo_Mask_MaxPathLength) 2458 { 2459 long nLen = pathconf (pszDirectory, _PC_PATH_MAX); 2460 if (nLen > 0) 2461 { 2462 pInfo->uMaxPathLength = (sal_uInt32)nLen; 2463 pInfo->uValidFields |= osl_VolumeInfo_Mask_MaxPathLength; 2464 } 2465 } 2466 2467 #if defined(__OSL_STATFS_TYPENAME) 2468 2469 if (uFieldMask & osl_VolumeInfo_Mask_FileSystemName) 2470 { 2471 rtl_string2UString( 2472 &(pInfo->ustrFileSystemName), 2473 __OSL_STATFS_TYPENAME(sfs), 2474 rtl_str_getLength(__OSL_STATFS_TYPENAME(sfs)), 2475 osl_getThreadTextEncoding(), 2476 OUSTRING_TO_OSTRING_CVTFLAGS); 2477 OSL_ASSERT(pInfo->ustrFileSystemName != 0); 2478 2479 pInfo->uValidFields |= osl_VolumeInfo_Mask_FileSystemName; 2480 } 2481 2482 #endif /* __OSL_STATFS_TYPENAME */ 2483 2484 if (uFieldMask & osl_VolumeInfo_Mask_DeviceHandle) 2485 { 2486 /* FIXME: check also entries in mntent for the device 2487 and fill it with correct values */ 2488 2489 *pInfo->pDeviceHandle = osl_isFloppyDrive(pszDirectory); 2490 2491 if (*pInfo->pDeviceHandle) 2492 { 2493 pInfo->uValidFields |= osl_VolumeInfo_Mask_DeviceHandle; 2494 pInfo->uAttributes |= osl_Volume_Attribute_Removeable; 2495 pInfo->uValidFields |= osl_VolumeInfo_Mask_Attributes; 2496 } 2497 } 2498 return osl_File_E_None; 2499 } 2500 2501 /****************************************** 2502 * osl_psz_setFileTime 2503 *****************************************/ 2504 2505 static oslFileError osl_psz_setFileTime( const sal_Char* pszFilePath, 2506 const TimeValue* /*pCreationTime*/, 2507 const TimeValue* pLastAccessTime, 2508 const TimeValue* pLastWriteTime ) 2509 { 2510 int nRet=0; 2511 struct utimbuf aTimeBuffer; 2512 struct stat aFileStat; 2513 #ifdef DEBUG_OSL_FILE 2514 struct tm* pTM=0; 2515 #endif 2516 2517 nRet = lstat(pszFilePath,&aFileStat); 2518 2519 if ( nRet < 0 ) 2520 { 2521 nRet=errno; 2522 return oslTranslateFileError(OSL_FET_ERROR, nRet); 2523 } 2524 2525 #ifdef DEBUG_OSL_FILE 2526 fprintf(stderr,"File Times are (in localtime):\n"); 2527 pTM=localtime(&aFileStat.st_ctime); 2528 fprintf(stderr,"CreationTime is '%s'\n",asctime(pTM)); 2529 pTM=localtime(&aFileStat.st_atime); 2530 fprintf(stderr,"AccessTime is '%s'\n",asctime(pTM)); 2531 pTM=localtime(&aFileStat.st_mtime); 2532 fprintf(stderr,"Modification is '%s'\n",asctime(pTM)); 2533 2534 fprintf(stderr,"File Times are (in UTC):\n"); 2535 fprintf(stderr,"CreationTime is '%s'\n",ctime(&aFileStat.st_ctime)); 2536 fprintf(stderr,"AccessTime is '%s'\n",ctime(&aTimeBuffer.actime)); 2537 fprintf(stderr,"Modification is '%s'\n",ctime(&aTimeBuffer.modtime)); 2538 #endif 2539 2540 if ( pLastAccessTime != 0 ) 2541 { 2542 aTimeBuffer.actime=pLastAccessTime->Seconds; 2543 } 2544 else 2545 { 2546 aTimeBuffer.actime=aFileStat.st_atime; 2547 } 2548 2549 if ( pLastWriteTime != 0 ) 2550 { 2551 aTimeBuffer.modtime=pLastWriteTime->Seconds; 2552 } 2553 else 2554 { 2555 aTimeBuffer.modtime=aFileStat.st_mtime; 2556 } 2557 2558 /* mfe: Creation time not used here! */ 2559 2560 #ifdef DEBUG_OSL_FILE 2561 fprintf(stderr,"File Times are (in localtime):\n"); 2562 pTM=localtime(&aFileStat.st_ctime); 2563 fprintf(stderr,"CreationTime now '%s'\n",asctime(pTM)); 2564 pTM=localtime(&aTimeBuffer.actime); 2565 fprintf(stderr,"AccessTime now '%s'\n",asctime(pTM)); 2566 pTM=localtime(&aTimeBuffer.modtime); 2567 fprintf(stderr,"Modification now '%s'\n",asctime(pTM)); 2568 2569 fprintf(stderr,"File Times are (in UTC):\n"); 2570 fprintf(stderr,"CreationTime now '%s'\n",ctime(&aFileStat.st_ctime)); 2571 fprintf(stderr,"AccessTime now '%s'\n",ctime(&aTimeBuffer.actime)); 2572 fprintf(stderr,"Modification now '%s'\n",ctime(&aTimeBuffer.modtime)); 2573 #endif 2574 2575 nRet=utime(pszFilePath,&aTimeBuffer); 2576 if ( nRet < 0 ) 2577 { 2578 nRet=errno; 2579 return oslTranslateFileError(OSL_FET_ERROR, nRet); 2580 } 2581 2582 return osl_File_E_None; 2583 } 2584 2585 2586 /***************************************** 2587 * osl_psz_removeFile 2588 ****************************************/ 2589 #if 0 2590 static oslFileError osl_psz_removeFile( const sal_Char* pszPath ) 2591 { 2592 int nRet=0; 2593 struct stat aStat; 2594 2595 nRet = stat(pszPath,&aStat); 2596 if ( nRet < 0 ) 2597 { 2598 nRet=errno; 2599 return oslTranslateFileError(OSL_FET_ERROR, nRet); 2600 } 2601 2602 if ( S_ISDIR(aStat.st_mode) ) 2603 { 2604 return osl_File_E_ISDIR; 2605 } 2606 2607 nRet = unlink(pszPath); 2608 if ( nRet < 0 ) 2609 { 2610 nRet=errno; 2611 return oslTranslateFileError(OSL_FET_ERROR, nRet); 2612 } 2613 2614 return osl_File_E_None; 2615 } 2616 #endif 2617 2618 /***************************************** 2619 * osl_psz_createDirectory 2620 ****************************************/ 2621 #if 0 2622 static oslFileError osl_psz_createDirectory( const sal_Char* pszPath ) 2623 { 2624 int nRet=0; 2625 int mode = S_IRWXU | S_IRWXG | S_IRWXO; 2626 2627 nRet = mkdir(pszPath,mode); 2628 2629 if ( nRet < 0 ) 2630 { 2631 nRet=errno; 2632 return oslTranslateFileError(OSL_FET_ERROR, nRet); 2633 } 2634 2635 return osl_File_E_None; 2636 } 2637 #endif 2638 /***************************************** 2639 * osl_psz_removeDirectory 2640 ****************************************/ 2641 #if 0 2642 static oslFileError osl_psz_removeDirectory( const sal_Char* pszPath ) 2643 { 2644 int nRet=0; 2645 2646 nRet = rmdir(pszPath); 2647 2648 if ( nRet < 0 ) 2649 { 2650 nRet=errno; 2651 return oslTranslateFileError(OSL_FET_ERROR, nRet); 2652 } 2653 2654 return osl_File_E_None; 2655 } 2656 #endif 2657 /***************************************** 2658 * oslDoMoveFile 2659 ****************************************/ 2660 #if 0 2661 static oslFileError oslDoMoveFile( const sal_Char* pszPath, const sal_Char* pszDestPath) 2662 { 2663 oslFileError tErr=osl_File_E_invalidError; 2664 2665 tErr = osl_psz_moveFile(pszPath,pszDestPath); 2666 if ( tErr == osl_File_E_None ) 2667 { 2668 return tErr; 2669 } 2670 2671 if ( tErr != osl_File_E_XDEV ) 2672 { 2673 return tErr; 2674 } 2675 2676 tErr=osl_psz_copyFile(pszPath,pszDestPath); 2677 2678 if ( tErr != osl_File_E_None ) 2679 { 2680 oslFileError tErrRemove; 2681 tErrRemove=osl_psz_removeFile(pszDestPath); 2682 return tErr; 2683 } 2684 2685 tErr=osl_psz_removeFile(pszPath); 2686 2687 return tErr; 2688 } 2689 #endif 2690 /***************************************** 2691 * osl_psz_moveFile 2692 ****************************************/ 2693 #if 0 2694 static oslFileError osl_psz_moveFile(const sal_Char* pszPath, const sal_Char* pszDestPath) 2695 { 2696 2697 int nRet = 0; 2698 2699 nRet = rename(pszPath,pszDestPath); 2700 2701 if ( nRet < 0 ) 2702 { 2703 nRet=errno; 2704 return oslTranslateFileError(OSL_FET_ERROR, nRet); 2705 } 2706 2707 return osl_File_E_None; 2708 } 2709 #endif 2710 /***************************************** 2711 * osl_psz_copyFile 2712 ****************************************/ 2713 #if 0 2714 static oslFileError osl_psz_copyFile( const sal_Char* pszPath, const sal_Char* pszDestPath ) 2715 { 2716 time_t nAcTime=0; 2717 time_t nModTime=0; 2718 uid_t nUID=0; 2719 gid_t nGID=0; 2720 int nRet=0; 2721 mode_t nMode=0; 2722 struct stat aFileStat; 2723 oslFileError tErr=osl_File_E_invalidError; 2724 size_t nSourceSize=0; 2725 int DestFileExists=1; 2726 2727 /* mfe: does the source file really exists? */ 2728 nRet = lstat(pszPath,&aFileStat); 2729 2730 if ( nRet < 0 ) 2731 { 2732 nRet=errno; 2733 return oslTranslateFileError(OSL_FET_ERROR, nRet); 2734 } 2735 2736 /* mfe: we do only copy files here! */ 2737 if ( S_ISDIR(aFileStat.st_mode) ) 2738 { 2739 return osl_File_E_ISDIR; 2740 } 2741 2742 nSourceSize=(size_t)aFileStat.st_size; 2743 nMode=aFileStat.st_mode; 2744 nAcTime=aFileStat.st_atime; 2745 nModTime=aFileStat.st_mtime; 2746 nUID=aFileStat.st_uid; 2747 nGID=aFileStat.st_gid; 2748 2749 nRet = stat(pszDestPath,&aFileStat); 2750 if ( nRet < 0 ) 2751 { 2752 nRet=errno; 2753 2754 if ( nRet == ENOENT ) 2755 { 2756 DestFileExists=0; 2757 } 2758 /* return oslTranslateFileError(nRet);*/ 2759 } 2760 2761 /* mfe: the destination file must not be a directory! */ 2762 if ( nRet == 0 && S_ISDIR(aFileStat.st_mode) ) 2763 { 2764 return osl_File_E_ISDIR; 2765 } 2766 else 2767 { 2768 /* mfe: file does not exists or is no dir */ 2769 } 2770 2771 tErr = oslDoCopy(pszPath,pszDestPath,nMode,nSourceSize,DestFileExists); 2772 2773 if ( tErr != osl_File_E_None ) 2774 { 2775 return tErr; 2776 } 2777 2778 /* 2779 * mfe: ignore return code 2780 * since only the success of the copy is 2781 * important 2782 */ 2783 oslChangeFileModes(pszDestPath,nMode,nAcTime,nModTime,nUID,nGID); 2784 2785 return tErr; 2786 } 2787 #endif 2788 2789 /****************************************************************************** 2790 * 2791 * Utility Functions 2792 * 2793 *****************************************************************************/ 2794 2795 2796 /***************************************** 2797 * oslMakeUStrFromPsz 2798 ****************************************/ 2799 2800 rtl_uString* oslMakeUStrFromPsz(const sal_Char* pszStr, rtl_uString** ustrValid) 2801 { 2802 rtl_string2UString( 2803 ustrValid, 2804 pszStr, 2805 rtl_str_getLength( pszStr ), 2806 osl_getThreadTextEncoding(), 2807 OUSTRING_TO_OSTRING_CVTFLAGS ); 2808 OSL_ASSERT(*ustrValid != 0); 2809 2810 return *ustrValid; 2811 } 2812 2813 /***************************************************************************** 2814 * UnicodeToText 2815 * converting unicode to text manually saves us the penalty of a temporary 2816 * rtl_String object. 2817 ****************************************************************************/ 2818 2819 int UnicodeToText( char * buffer, size_t bufLen, const sal_Unicode * uniText, sal_Int32 uniTextLen ) 2820 { 2821 rtl_UnicodeToTextConverter hConverter; 2822 sal_uInt32 nInfo; 2823 sal_Size nSrcChars, nDestBytes; 2824 2825 /* stolen from rtl/string.c */ 2826 hConverter = rtl_createUnicodeToTextConverter( osl_getThreadTextEncoding() ); 2827 2828 nDestBytes = rtl_convertUnicodeToText( hConverter, 0, uniText, uniTextLen, 2829 buffer, bufLen, 2830 OUSTRING_TO_OSTRING_CVTFLAGS | RTL_UNICODETOTEXT_FLAGS_FLUSH, 2831 &nInfo, &nSrcChars ); 2832 2833 rtl_destroyUnicodeToTextConverter( hConverter ); 2834 2835 if( nInfo & RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL ) 2836 { 2837 errno = EOVERFLOW; 2838 return 0; 2839 } 2840 2841 /* ensure trailing '\0' */ 2842 buffer[nDestBytes] = '\0'; 2843 2844 return nDestBytes; 2845 } 2846 2847 /***************************************************************************** 2848 TextToUnicode 2849 2850 @param text 2851 The text to convert. 2852 2853 @param text_buffer_size 2854 The number of characters. 2855 2856 @param unic_text 2857 The unicode buffer. 2858 2859 @param unic_text_buffer_size 2860 The size in characters of the unicode buffer. 2861 2862 ****************************************************************************/ 2863 2864 int TextToUnicode( 2865 const char* text, 2866 size_t text_buffer_size, 2867 sal_Unicode* unic_text, 2868 sal_Int32 unic_text_buffer_size) 2869 { 2870 rtl_TextToUnicodeConverter hConverter; 2871 sal_uInt32 nInfo; 2872 sal_Size nSrcChars; 2873 sal_Size nDestBytes; 2874 2875 /* stolen from rtl/string.c */ 2876 hConverter = rtl_createTextToUnicodeConverter(osl_getThreadTextEncoding()); 2877 2878 nDestBytes = rtl_convertTextToUnicode(hConverter, 2879 0, 2880 text, text_buffer_size, 2881 unic_text, unic_text_buffer_size, 2882 OSTRING_TO_OUSTRING_CVTFLAGS | RTL_TEXTTOUNICODE_FLAGS_FLUSH, 2883 &nInfo, &nSrcChars); 2884 2885 rtl_destroyTextToUnicodeConverter(hConverter); 2886 2887 if (nInfo & RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL) 2888 { 2889 errno = EOVERFLOW; 2890 return 0; 2891 } 2892 2893 /* ensure trailing '\0' */ 2894 unic_text[nDestBytes] = '\0'; 2895 2896 return nDestBytes; 2897 } 2898 2899 /****************************************************************************** 2900 * 2901 * GENERIC FLOPPY FUNCTIONS 2902 * 2903 *****************************************************************************/ 2904 2905 2906 /***************************************** 2907 * osl_unmountVolumeDevice 2908 ****************************************/ 2909 2910 oslFileError osl_unmountVolumeDevice( oslVolumeDeviceHandle Handle ) 2911 { 2912 oslFileError tErr = osl_File_E_NOSYS; 2913 2914 tErr = osl_unmountFloppy(Handle); 2915 2916 /* Perhaps current working directory is set to mount point */ 2917 2918 if ( tErr ) 2919 { 2920 sal_Char *pszHomeDir = getenv("HOME"); 2921 2922 if ( pszHomeDir && strlen( pszHomeDir ) && 0 == chdir( pszHomeDir ) ) 2923 { 2924 /* try again */ 2925 2926 tErr = osl_unmountFloppy(Handle); 2927 2928 OSL_ENSURE( tErr, "osl_unmountvolumeDevice: CWD was set to volume mount point" ); 2929 } 2930 } 2931 2932 return tErr; 2933 } 2934 2935 /***************************************** 2936 * osl_automountVolumeDevice 2937 ****************************************/ 2938 2939 oslFileError osl_automountVolumeDevice( oslVolumeDeviceHandle Handle ) 2940 { 2941 oslFileError tErr = osl_File_E_NOSYS; 2942 2943 tErr = osl_mountFloppy(Handle); 2944 2945 return tErr; 2946 } 2947 2948 /***************************************** 2949 * osl_getVolumeDeviceMountPath 2950 ****************************************/ 2951 2952 oslFileError osl_getVolumeDeviceMountPath( oslVolumeDeviceHandle Handle, rtl_uString **pstrPath ) 2953 { 2954 oslVolumeDeviceHandleImpl* pItem = (oslVolumeDeviceHandleImpl*) Handle; 2955 sal_Char Buffer[PATH_MAX]; 2956 2957 Buffer[0] = '\0'; 2958 2959 if ( pItem == 0 || pstrPath == 0 ) 2960 { 2961 return osl_File_E_INVAL; 2962 } 2963 2964 if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' ) 2965 { 2966 return osl_File_E_INVAL; 2967 } 2968 2969 #ifdef DEBUG_OSL_FILE 2970 fprintf(stderr,"Handle is:\n"); 2971 osl_printFloppyHandle(pItem); 2972 #endif 2973 2974 snprintf(Buffer, sizeof(Buffer), "file://%s", pItem->pszMountPoint); 2975 2976 #ifdef DEBUG_OSL_FILE 2977 fprintf(stderr,"Mount Point is: '%s'\n",Buffer); 2978 #endif 2979 2980 oslMakeUStrFromPsz(Buffer, pstrPath); 2981 2982 return osl_File_E_None; 2983 } 2984 2985 /***************************************** 2986 * osl_acquireVolumeDeviceHandle 2987 ****************************************/ 2988 2989 oslFileError SAL_CALL osl_acquireVolumeDeviceHandle( oslVolumeDeviceHandle Handle ) 2990 { 2991 oslVolumeDeviceHandleImpl* pItem =(oslVolumeDeviceHandleImpl*) Handle; 2992 2993 if ( pItem == 0 ) 2994 { 2995 return osl_File_E_INVAL; 2996 } 2997 2998 if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' ) 2999 { 3000 return osl_File_E_INVAL; 3001 } 3002 3003 ++pItem->RefCount; 3004 3005 return osl_File_E_None; 3006 } 3007 3008 /***************************************** 3009 * osl_releaseVolumeDeviceHandle 3010 ****************************************/ 3011 3012 oslFileError osl_releaseVolumeDeviceHandle( oslVolumeDeviceHandle Handle ) 3013 { 3014 oslVolumeDeviceHandleImpl* pItem =(oslVolumeDeviceHandleImpl*) Handle; 3015 3016 if ( pItem == 0 ) 3017 { 3018 return osl_File_E_INVAL; 3019 } 3020 3021 if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' ) 3022 { 3023 return osl_File_E_INVAL; 3024 } 3025 3026 --pItem->RefCount; 3027 3028 if ( pItem->RefCount == 0 ) 3029 { 3030 rtl_freeMemory(pItem); 3031 } 3032 3033 return osl_File_E_None; 3034 } 3035 3036 /***************************************** 3037 * osl_newVolumeDeviceHandleImpl 3038 ****************************************/ 3039 3040 static oslVolumeDeviceHandleImpl* osl_newVolumeDeviceHandleImpl() 3041 { 3042 oslVolumeDeviceHandleImpl* pHandle; 3043 const size_t nSizeOfHandle = sizeof(oslVolumeDeviceHandleImpl); 3044 3045 pHandle = (oslVolumeDeviceHandleImpl*) rtl_allocateMemory (nSizeOfHandle); 3046 if (pHandle != NULL) 3047 { 3048 pHandle->ident[0] = 'O'; 3049 pHandle->ident[1] = 'V'; 3050 pHandle->ident[2] = 'D'; 3051 pHandle->ident[3] = 'H'; 3052 pHandle->pszMountPoint[0] = '\0'; 3053 pHandle->pszFilePath[0] = '\0'; 3054 pHandle->pszDevice[0] = '\0'; 3055 pHandle->RefCount = 1; 3056 } 3057 return pHandle; 3058 } 3059 3060 /***************************************** 3061 * osl_freeVolumeDeviceHandleImpl 3062 ****************************************/ 3063 3064 static void osl_freeVolumeDeviceHandleImpl (oslVolumeDeviceHandleImpl* pHandle) 3065 { 3066 if (pHandle != NULL) 3067 rtl_freeMemory (pHandle); 3068 } 3069 3070 3071 /****************************************************************************** 3072 * 3073 * OS/2 FLOPPY FUNCTIONS 3074 * 3075 *****************************************************************************/ 3076 3077 #if defined(OS2) 3078 static oslVolumeDeviceHandle osl_isFloppyDrive(const sal_Char* pszPath) 3079 { 3080 return NULL; 3081 } 3082 3083 static oslFileError osl_mountFloppy(oslVolumeDeviceHandle hFloppy) 3084 { 3085 return osl_File_E_BUSY; 3086 } 3087 3088 static oslFileError osl_unmountFloppy(oslVolumeDeviceHandle hFloppy) 3089 { 3090 return osl_File_E_BUSY; 3091 } 3092 3093 static sal_Bool osl_getFloppyMountEntry(const sal_Char* pszPath, oslVolumeDeviceHandleImpl* pItem) 3094 { 3095 return sal_False; 3096 } 3097 3098 static sal_Bool osl_isFloppyMounted(oslVolumeDeviceHandleImpl* pDevice) 3099 { 3100 return sal_False; 3101 } 3102 3103 3104 #ifdef DEBUG_OSL_FILE 3105 static void osl_printFloppyHandle(oslVolumeDeviceHandleImpl* pItem) 3106 { 3107 if (pItem == 0 ) 3108 { 3109 fprintf(stderr,"NULL Handle\n"); 3110 return; 3111 } 3112 if ( pItem->ident[0] != 'O' || pItem->ident[1] != 'V' || pItem->ident[2] != 'D' || pItem->ident[3] != 'H' ) 3113 { 3114 #ifdef TRACE_OSL_FILE 3115 fprintf(stderr,"Invalid Handle]\n"); 3116 #endif 3117 return; 3118 } 3119 3120 3121 fprintf(stderr,"MountPoint : '%s'\n",pItem->pszMountPoint); 3122 fprintf(stderr,"FilePath : '%s'\n",pItem->pszFilePath); 3123 fprintf(stderr,"Device : '%s'\n",pItem->pszDevice); 3124 3125 return; 3126 } 3127 #endif 3128 3129 #endif /* OS2 */ 3130