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