1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 #include "osl/file.hxx" 25 26 #include "osl/diagnose.h" 27 #include "osl/thread.h" 28 #include <osl/signal.h> 29 #include "rtl/alloc.h" 30 31 #include "system.h" 32 #include "file_impl.hxx" 33 #include "file_error_transl.h" 34 #include "file_path_helper.hxx" 35 #include "file_url.h" 36 #include "uunxapi.hxx" 37 38 #include <sys/types.h> 39 #include <errno.h> 40 #include <dirent.h> 41 #include <limits.h> 42 #include <stdio.h> 43 #include <string.h> 44 #include <unistd.h> 45 #include <sys/stat.h> 46 #include <sys/mman.h> 47 48 #include <algorithm> 49 50 /************************************************************************ 51 * ToDo 52 * 53 * - Fix: check for corresponding struct sizes in exported functions 54 * - check size/use of oslDirectory 55 * - check size/use of oslDirectoryItem 56 ***********************************************************************/ 57 /****************************************************************************** 58 * 59 * Data Type Definition 60 * 61 ******************************************************************************/ 62 63 typedef struct 64 { 65 rtl_uString* ustrPath; /* holds native directory path */ 66 DIR* pDirStruct; 67 } oslDirectoryImpl; 68 69 #if 0 70 /* FIXME: reintroducing this may save some extra bytes per Item */ 71 typedef struct 72 { 73 rtl_uString* ustrFileName; /* holds native file name */ 74 rtl_uString* ustrDirPath; /* holds native dir path */ 75 sal_uInt32 RefCount; 76 } oslDirectoryItemImpl; 77 #endif 78 79 DirectoryItem_Impl::DirectoryItem_Impl( 80 rtl_uString * ustrFilePath, unsigned char DType) 81 : m_RefCount (1), 82 m_ustrFilePath (ustrFilePath), 83 m_DType (DType) 84 { 85 if (m_ustrFilePath != 0) 86 rtl_uString_acquire(m_ustrFilePath); 87 } 88 DirectoryItem_Impl::~DirectoryItem_Impl() 89 { 90 if (m_ustrFilePath != 0) 91 rtl_uString_release(m_ustrFilePath); 92 } 93 94 void * DirectoryItem_Impl::operator new(size_t n) 95 { 96 return rtl_allocateMemory(n); 97 } 98 void DirectoryItem_Impl::operator delete(void * p, size_t) 99 { 100 rtl_freeMemory(p); 101 } 102 103 void DirectoryItem_Impl::acquire() 104 { 105 ++m_RefCount; 106 } 107 void DirectoryItem_Impl::release() 108 { 109 if (0 == --m_RefCount) 110 delete this; 111 } 112 113 oslFileType DirectoryItem_Impl::getFileType() const 114 { 115 switch (m_DType) 116 { 117 #ifdef _DIRENT_HAVE_D_TYPE 118 case DT_LNK: 119 return osl_File_Type_Link; 120 case DT_DIR: 121 return osl_File_Type_Directory; 122 case DT_REG: 123 return osl_File_Type_Regular; 124 case DT_FIFO: 125 return osl_File_Type_Fifo; 126 case DT_SOCK: 127 return osl_File_Type_Socket; 128 case DT_CHR: 129 case DT_BLK: 130 return osl_File_Type_Special; 131 #endif /* _DIRENT_HAVE_D_TYPE */ 132 default: 133 break; 134 } 135 return osl_File_Type_Unknown; 136 } 137 138 /****************************************************************************** 139 * 140 * C-String Function Declarations 141 * 142 *****************************************************************************/ 143 144 static oslFileError osl_psz_createDirectory(const sal_Char* pszPath); 145 static oslFileError osl_psz_removeDirectory(const sal_Char* pszPath); 146 147 /******************************************************************* 148 * osl_openDirectory 149 ******************************************************************/ 150 151 oslFileError SAL_CALL osl_openDirectory(rtl_uString* ustrDirectoryURL, oslDirectory* pDirectory) 152 { 153 rtl_uString* ustrSystemPath = NULL; 154 oslFileError eRet; 155 156 char path[PATH_MAX]; 157 158 if ((0 == ustrDirectoryURL) || (0 == ustrDirectoryURL->length) || (0 == pDirectory)) 159 return osl_File_E_INVAL; 160 161 /* convert file URL to system path */ 162 eRet = osl_getSystemPathFromFileURL_Ex(ustrDirectoryURL, &ustrSystemPath, sal_False); 163 164 if( osl_File_E_None != eRet ) 165 return eRet; 166 167 osl_systemPathRemoveSeparator(ustrSystemPath); 168 169 /* convert unicode path to text */ 170 if ( UnicodeToText( path, PATH_MAX, ustrSystemPath->buffer, ustrSystemPath->length ) 171 #ifdef MACOSX 172 && macxp_resolveAlias( path, PATH_MAX ) == 0 173 #endif /* MACOSX */ 174 ) 175 { 176 /* open directory */ 177 DIR *pdir = opendir( path ); 178 179 if( pdir ) 180 { 181 /* create and initialize impl structure */ 182 oslDirectoryImpl* pDirImpl = (oslDirectoryImpl*) rtl_allocateMemory( sizeof(oslDirectoryImpl) ); 183 184 if( pDirImpl ) 185 { 186 pDirImpl->pDirStruct = pdir; 187 pDirImpl->ustrPath = ustrSystemPath; 188 189 *pDirectory = (oslDirectory) pDirImpl; 190 return osl_File_E_None; 191 } 192 else 193 { 194 errno = ENOMEM; 195 closedir( pdir ); 196 } 197 } 198 else 199 { 200 #ifdef DEBUG_OSL_FILE 201 perror ("osl_openDirectory"); fprintf (stderr, path); 202 #endif 203 } 204 } 205 206 rtl_uString_release( ustrSystemPath ); 207 208 return oslTranslateFileError(OSL_FET_ERROR, errno); 209 } 210 211 /****************************************************************************/ 212 /* osl_closeDirectory */ 213 /****************************************************************************/ 214 215 oslFileError SAL_CALL osl_closeDirectory( oslDirectory Directory ) 216 { 217 oslDirectoryImpl* pDirImpl = (oslDirectoryImpl*) Directory; 218 oslFileError err = osl_File_E_None; 219 220 OSL_ASSERT( Directory ); 221 222 if( NULL == pDirImpl ) 223 return osl_File_E_INVAL; 224 225 /* close directory */ 226 if( closedir( pDirImpl->pDirStruct ) ) 227 { 228 err = oslTranslateFileError(OSL_FET_ERROR, errno); 229 } 230 231 /* cleanup members */ 232 rtl_uString_release( pDirImpl->ustrPath ); 233 234 rtl_freeMemory( pDirImpl ); 235 236 return err; 237 } 238 239 /********************************************** 240 * osl_readdir_impl_ 241 * 242 * readdir wrapper, filters out "." and ".." 243 * on request 244 *********************************************/ 245 246 static struct dirent* osl_readdir_impl_(DIR* pdir, sal_Bool bFilterLocalAndParentDir) 247 { 248 struct dirent* pdirent; 249 250 while ((pdirent = readdir(pdir)) != NULL) 251 { 252 if (bFilterLocalAndParentDir && 253 ((0 == strcmp(pdirent->d_name, ".")) || (0 == strcmp(pdirent->d_name, "..")))) 254 continue; 255 else 256 break; 257 } 258 259 return pdirent; 260 } 261 262 /**************************************************************************** 263 * osl_getNextDirectoryItem 264 ***************************************************************************/ 265 266 oslFileError SAL_CALL osl_getNextDirectoryItem(oslDirectory Directory, oslDirectoryItem* pItem, sal_uInt32 /*uHint*/) 267 { 268 oslDirectoryImpl* pDirImpl = (oslDirectoryImpl*)Directory; 269 rtl_uString* ustrFileName = NULL; 270 rtl_uString* ustrFilePath = NULL; 271 struct dirent* pEntry; 272 273 OSL_ASSERT(Directory); 274 OSL_ASSERT(pItem); 275 276 if ((NULL == Directory) || (NULL == pItem)) 277 return osl_File_E_INVAL; 278 279 pEntry = osl_readdir_impl_(pDirImpl->pDirStruct, sal_True); 280 281 if (NULL == pEntry) 282 return osl_File_E_NOENT; 283 284 285 #if defined(MACOSX) 286 287 // convert decomposed filename to precomposed unicode 288 char composed_name[BUFSIZ]; 289 CFMutableStringRef strRef = CFStringCreateMutable (NULL, 0 ); 290 CFStringAppendCString( strRef, pEntry->d_name, kCFStringEncodingUTF8 ); //UTF8 is default on Mac OSX 291 CFStringNormalize( strRef, kCFStringNormalizationFormC ); 292 CFStringGetCString( strRef, composed_name, BUFSIZ, kCFStringEncodingUTF8 ); 293 CFRelease( strRef ); 294 rtl_string2UString( &ustrFileName, composed_name, strlen( composed_name), 295 osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS ); 296 297 #else // not MACOSX 298 /* convert file name to unicode */ 299 rtl_string2UString( &ustrFileName, pEntry->d_name, strlen( pEntry->d_name ), 300 osl_getThreadTextEncoding(), OSTRING_TO_OUSTRING_CVTFLAGS ); 301 OSL_ASSERT(ustrFileName != 0); 302 303 #endif 304 305 osl_systemPathMakeAbsolutePath(pDirImpl->ustrPath, ustrFileName, &ustrFilePath); 306 rtl_uString_release( ustrFileName ); 307 308 DirectoryItem_Impl * pImpl = static_cast< DirectoryItem_Impl* >(*pItem); 309 if (0 != pImpl) 310 { 311 pImpl->release(), pImpl = 0; 312 } 313 #ifdef _DIRENT_HAVE_D_TYPE 314 pImpl = new DirectoryItem_Impl(ustrFilePath, pEntry->d_type); 315 #else 316 pImpl = new DirectoryItem_Impl(ustrFilePath); 317 #endif /* _DIRENT_HAVE_D_TYPE */ 318 *pItem = pImpl; 319 rtl_uString_release( ustrFilePath ); 320 321 return osl_File_E_None; 322 } 323 324 /****************************************************************************/ 325 /* osl_getDirectoryItem */ 326 /****************************************************************************/ 327 328 oslFileError SAL_CALL osl_getDirectoryItem( rtl_uString* ustrFileURL, oslDirectoryItem* pItem ) 329 { 330 rtl_uString* ustrSystemPath = NULL; 331 oslFileError osl_error = osl_File_E_INVAL; 332 333 OSL_ASSERT((0 != ustrFileURL) && (0 != pItem)); 334 if ((0 == ustrFileURL) || (0 == ustrFileURL->length) || (0 == pItem)) 335 return osl_File_E_INVAL; 336 337 osl_error = osl_getSystemPathFromFileURL_Ex(ustrFileURL, &ustrSystemPath, sal_False); 338 if (osl_File_E_None != osl_error) 339 return osl_error; 340 341 osl_systemPathRemoveSeparator(ustrSystemPath); 342 343 if (-1 == access_u(ustrSystemPath, F_OK)) 344 { 345 osl_error = oslTranslateFileError(OSL_FET_ERROR, errno); 346 } 347 else 348 { 349 *pItem = new DirectoryItem_Impl(ustrSystemPath); 350 } 351 rtl_uString_release(ustrSystemPath); 352 353 return osl_error; 354 } 355 356 357 /****************************************************************************/ 358 /* osl_acquireDirectoryItem */ 359 /****************************************************************************/ 360 361 oslFileError SAL_CALL osl_acquireDirectoryItem( oslDirectoryItem Item ) 362 { 363 DirectoryItem_Impl * pImpl = static_cast< DirectoryItem_Impl* >(Item); 364 if (0 == pImpl) 365 return osl_File_E_INVAL; 366 367 pImpl->acquire(); 368 return osl_File_E_None; 369 } 370 371 /****************************************************************************/ 372 /* osl_releaseDirectoryItem */ 373 /****************************************************************************/ 374 375 oslFileError SAL_CALL osl_releaseDirectoryItem( oslDirectoryItem Item ) 376 { 377 DirectoryItem_Impl * pImpl = static_cast< DirectoryItem_Impl* >(Item); 378 if (0 == pImpl) 379 return osl_File_E_INVAL; 380 381 pImpl->release(); 382 return osl_File_E_None; 383 } 384 385 /****************************************************************************/ 386 /* osl_createDirectory */ 387 /****************************************************************************/ 388 389 oslFileError SAL_CALL osl_createDirectory( rtl_uString* ustrDirectoryURL ) 390 { 391 char path[PATH_MAX]; 392 oslFileError eRet; 393 394 OSL_ASSERT( ustrDirectoryURL ); 395 396 /* convert directory url to system path */ 397 eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL ); 398 if( eRet != osl_File_E_None ) 399 return eRet; 400 401 #ifdef MACOSX 402 if ( macxp_resolveAlias( path, PATH_MAX ) != 0 ) 403 return oslTranslateFileError( OSL_FET_ERROR, errno ); 404 #endif/* MACOSX */ 405 406 return osl_psz_createDirectory( path ); 407 } 408 409 /****************************************************************************/ 410 /* osl_removeDirectory */ 411 /****************************************************************************/ 412 413 oslFileError SAL_CALL osl_removeDirectory( rtl_uString* ustrDirectoryURL ) 414 { 415 char path[PATH_MAX]; 416 oslFileError eRet; 417 418 OSL_ASSERT( ustrDirectoryURL ); 419 420 /* convert directory url to system path */ 421 eRet = FileURLToPath( path, PATH_MAX, ustrDirectoryURL ); 422 if( eRet != osl_File_E_None ) 423 return eRet; 424 425 #ifdef MACOSX 426 if ( macxp_resolveAlias( path, PATH_MAX ) != 0 ) 427 return oslTranslateFileError( OSL_FET_ERROR, errno ); 428 #endif/* MACOSX */ 429 430 return osl_psz_removeDirectory( path ); 431 } 432 433 /***************************************** 434 * osl_psz_createDirectory 435 ****************************************/ 436 437 static oslFileError osl_psz_createDirectory( const sal_Char* pszPath ) 438 { 439 int nRet=0; 440 int mode = S_IRWXU | S_IRWXG | S_IRWXO; 441 442 nRet = mkdir(pszPath,mode); 443 444 if ( nRet < 0 ) 445 { 446 nRet=errno; 447 return oslTranslateFileError(OSL_FET_ERROR, nRet); 448 } 449 450 return osl_File_E_None; 451 } 452 453 /***************************************** 454 * osl_psz_removeDirectory 455 ****************************************/ 456 457 static oslFileError osl_psz_removeDirectory( const sal_Char* pszPath ) 458 { 459 int nRet=0; 460 461 nRet = rmdir(pszPath); 462 463 if ( nRet < 0 ) 464 { 465 nRet=errno; 466 return oslTranslateFileError(OSL_FET_ERROR, nRet); 467 } 468 469 return osl_File_E_None; 470 } 471 472 /****************************************************************************/ 473 /* osl_createDirectoryPath */ 474 /****************************************************************************/ 475 476 static int path_make_parent(sal_Unicode* path) 477 { 478 int i = rtl_ustr_lastIndexOfChar(path, '/'); 479 480 if (i > 0) 481 { 482 *(path + i) = 0; 483 return i; 484 } 485 else 486 return 0; 487 } 488 489 static int create_dir_with_callback( 490 sal_Unicode* directory_path, 491 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc, 492 void* pData) 493 { 494 int mode = S_IRWXU | S_IRWXG | S_IRWXO; 495 496 if (osl::mkdir(directory_path, mode) == 0) 497 { 498 if (aDirectoryCreationCallbackFunc) 499 { 500 rtl::OUString url; 501 osl::FileBase::getFileURLFromSystemPath(directory_path, url); 502 aDirectoryCreationCallbackFunc(pData, url.pData); 503 } 504 return 0; 505 } 506 return errno; 507 } 508 509 static oslFileError create_dir_recursively_( 510 sal_Unicode* dir_path, 511 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc, 512 void* pData) 513 { 514 OSL_PRECOND((rtl_ustr_getLength(dir_path) > 0) && ((dir_path + (rtl_ustr_getLength(dir_path) - 1)) != (dir_path + rtl_ustr_lastIndexOfChar(dir_path, '/'))), \ 515 "Path must not end with a slash"); 516 517 int native_err = create_dir_with_callback( 518 dir_path, aDirectoryCreationCallbackFunc, pData); 519 520 if (native_err == 0) 521 return osl_File_E_None; 522 523 if (native_err != ENOENT) 524 return oslTranslateFileError(OSL_FET_ERROR, native_err); 525 526 // we step back until '/a_dir' at maximum because 527 // we should get an error unequal ENOENT when 528 // we try to create 'a_dir' at '/' and would so 529 // return before 530 int pos = path_make_parent(dir_path); 531 532 oslFileError osl_error = create_dir_recursively_( 533 dir_path, aDirectoryCreationCallbackFunc, pData); 534 535 if (osl_File_E_None != osl_error) 536 return osl_error; 537 538 dir_path[pos] = '/'; 539 540 return create_dir_recursively_(dir_path, aDirectoryCreationCallbackFunc, pData); 541 } 542 543 oslFileError SAL_CALL osl_createDirectoryPath( 544 rtl_uString* aDirectoryUrl, 545 oslDirectoryCreationCallbackFunc aDirectoryCreationCallbackFunc, 546 void* pData) 547 { 548 if (aDirectoryUrl == NULL) 549 return osl_File_E_INVAL; 550 551 rtl::OUString sys_path; 552 oslFileError osl_error = osl_getSystemPathFromFileURL_Ex( 553 aDirectoryUrl, &sys_path.pData, sal_False); 554 555 if (osl_error != osl_File_E_None) 556 return osl_error; 557 558 osl::systemPathRemoveSeparator(sys_path); 559 560 // const_cast because sys_path is a local copy which we want to modify inplace instead of 561 // coyp it into another buffer on the heap again 562 return create_dir_recursively_(sys_path.pData->buffer, aDirectoryCreationCallbackFunc, pData); 563 } 564 565 /****************************************************************************** 566 * 567 * C-String Function Declarations 568 * 569 *****************************************************************************/ 570 571 static oslFileError osl_psz_removeFile(const sal_Char* pszPath); 572 static oslFileError osl_psz_copyFile(const sal_Char* pszPath, const sal_Char* pszDestPath); 573 static oslFileError osl_psz_moveFile(const sal_Char* pszPath, const sal_Char* pszDestPath); 574 575 576 /****************************************************************************** 577 * 578 * Static Module Utility Function Declarations 579 * 580 *****************************************************************************/ 581 582 static oslFileError oslDoCopy(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, mode_t nMode, size_t nSourceSize, int DestFileExists); 583 static oslFileError oslChangeFileModes(const sal_Char* pszFileName, mode_t nMode, time_t nAcTime, time_t nModTime, uid_t nUID, gid_t nGID); 584 static int oslDoCopyLink(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName); 585 static int oslDoCopyFile(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, size_t nSourceSize, mode_t mode); 586 static oslFileError oslDoMoveFile(const sal_Char* pszPath, const sal_Char* pszDestPath); 587 588 /****************************************************************************/ 589 /* osl_moveFile */ 590 /****************************************************************************/ 591 592 oslFileError SAL_CALL osl_moveFile( rtl_uString* ustrFileURL, rtl_uString* ustrDestURL ) 593 { 594 char srcPath[PATH_MAX]; 595 char destPath[PATH_MAX]; 596 oslFileError eRet; 597 598 OSL_ASSERT( ustrFileURL ); 599 OSL_ASSERT( ustrDestURL ); 600 601 /* convert source url to system path */ 602 eRet = FileURLToPath( srcPath, PATH_MAX, ustrFileURL ); 603 if( eRet != osl_File_E_None ) 604 return eRet; 605 606 /* convert destination url to system path */ 607 eRet = FileURLToPath( destPath, PATH_MAX, ustrDestURL ); 608 if( eRet != osl_File_E_None ) 609 return eRet; 610 611 #ifdef MACOSX 612 if ( macxp_resolveAlias( srcPath, PATH_MAX ) != 0 || macxp_resolveAlias( destPath, PATH_MAX ) != 0 ) 613 return oslTranslateFileError( OSL_FET_ERROR, errno ); 614 #endif/* MACOSX */ 615 616 return oslDoMoveFile( srcPath, destPath ); 617 } 618 619 /****************************************************************************/ 620 /* osl_copyFile */ 621 /****************************************************************************/ 622 623 oslFileError SAL_CALL osl_copyFile( rtl_uString* ustrFileURL, rtl_uString* ustrDestURL ) 624 { 625 char srcPath[PATH_MAX]; 626 char destPath[PATH_MAX]; 627 oslFileError eRet; 628 629 OSL_ASSERT( ustrFileURL ); 630 OSL_ASSERT( ustrDestURL ); 631 632 /* convert source url to system path */ 633 eRet = FileURLToPath( srcPath, PATH_MAX, ustrFileURL ); 634 if( eRet != osl_File_E_None ) 635 return eRet; 636 637 /* convert destination url to system path */ 638 eRet = FileURLToPath( destPath, PATH_MAX, ustrDestURL ); 639 if( eRet != osl_File_E_None ) 640 return eRet; 641 642 #ifdef MACOSX 643 if ( macxp_resolveAlias( srcPath, PATH_MAX ) != 0 || macxp_resolveAlias( destPath, PATH_MAX ) != 0 ) 644 return oslTranslateFileError( OSL_FET_ERROR, errno ); 645 #endif/* MACOSX */ 646 647 return osl_psz_copyFile( srcPath, destPath ); 648 } 649 650 /****************************************************************************/ 651 /* osl_removeFile */ 652 /****************************************************************************/ 653 654 oslFileError SAL_CALL osl_removeFile( rtl_uString* ustrFileURL ) 655 { 656 char path[PATH_MAX]; 657 oslFileError eRet; 658 659 OSL_ASSERT( ustrFileURL ); 660 661 /* convert file url to system path */ 662 eRet = FileURLToPath( path, PATH_MAX, ustrFileURL ); 663 if( eRet != osl_File_E_None ) 664 return eRet; 665 666 #ifdef MACOSX 667 if ( macxp_resolveAlias( path, PATH_MAX ) != 0 ) 668 return oslTranslateFileError( OSL_FET_ERROR, errno ); 669 #endif/* MACOSX */ 670 671 return osl_psz_removeFile( path ); 672 } 673 674 /****************************************************************************** 675 * 676 * Utility Functions 677 * 678 *****************************************************************************/ 679 680 /***************************************** 681 * oslDoMoveFile 682 ****************************************/ 683 684 static oslFileError oslDoMoveFile( const sal_Char* pszPath, const sal_Char* pszDestPath) 685 { 686 oslFileError tErr=osl_File_E_invalidError; 687 688 tErr = osl_psz_moveFile(pszPath,pszDestPath); 689 if ( tErr == osl_File_E_None ) 690 { 691 return tErr; 692 } 693 694 if ( tErr != osl_File_E_XDEV ) 695 { 696 return tErr; 697 } 698 699 tErr=osl_psz_copyFile(pszPath,pszDestPath); 700 701 if ( tErr != osl_File_E_None ) 702 { 703 oslFileError tErrRemove; 704 tErrRemove=osl_psz_removeFile(pszDestPath); 705 return tErr; 706 } 707 708 tErr=osl_psz_removeFile(pszPath); 709 710 return tErr; 711 } 712 713 /***************************************** 714 * osl_psz_removeFile 715 ****************************************/ 716 static oslFileError osl_psz_removeFile( const sal_Char* pszPath ) 717 { 718 int nRet=0; 719 struct stat aStat; 720 721 nRet = lstat(pszPath,&aStat); 722 if ( nRet < 0 ) 723 { 724 nRet=errno; 725 return oslTranslateFileError(OSL_FET_ERROR, nRet); 726 } 727 728 if ( S_ISDIR(aStat.st_mode) ) 729 { 730 return osl_File_E_ISDIR; 731 } 732 733 nRet = unlink(pszPath); 734 if ( nRet < 0 ) 735 { 736 nRet=errno; 737 return oslTranslateFileError(OSL_FET_ERROR, nRet); 738 } 739 740 return osl_File_E_None; 741 } 742 743 /***************************************** 744 * osl_psz_moveFile 745 ****************************************/ 746 747 static oslFileError osl_psz_moveFile(const sal_Char* pszPath, const sal_Char* pszDestPath) 748 { 749 750 int nRet = 0; 751 752 nRet = rename(pszPath,pszDestPath); 753 754 if ( nRet < 0 ) 755 { 756 nRet=errno; 757 return oslTranslateFileError(OSL_FET_ERROR, nRet); 758 } 759 760 return osl_File_E_None; 761 } 762 763 /***************************************** 764 * osl_psz_copyFile 765 ****************************************/ 766 767 static oslFileError osl_psz_copyFile( const sal_Char* pszPath, const sal_Char* pszDestPath ) 768 { 769 time_t nAcTime=0; 770 time_t nModTime=0; 771 uid_t nUID=0; 772 gid_t nGID=0; 773 int nRet=0; 774 mode_t nMode=0; 775 struct stat aFileStat; 776 oslFileError tErr=osl_File_E_invalidError; 777 size_t nSourceSize=0; 778 int DestFileExists=1; 779 780 /* mfe: does the source file really exists? */ 781 nRet = lstat(pszPath,&aFileStat); 782 783 if ( nRet < 0 ) 784 { 785 nRet=errno; 786 return oslTranslateFileError(OSL_FET_ERROR, nRet); 787 } 788 789 /* mfe: we do only copy files here! */ 790 if ( S_ISDIR(aFileStat.st_mode) ) 791 { 792 return osl_File_E_ISDIR; 793 } 794 795 nSourceSize=(size_t)aFileStat.st_size; 796 nMode=aFileStat.st_mode; 797 nAcTime=aFileStat.st_atime; 798 nModTime=aFileStat.st_mtime; 799 nUID=aFileStat.st_uid; 800 nGID=aFileStat.st_gid; 801 802 nRet = stat(pszDestPath,&aFileStat); 803 if ( nRet < 0 ) 804 { 805 nRet=errno; 806 807 if ( nRet == ENOENT ) 808 { 809 DestFileExists=0; 810 } 811 /* return oslTranslateFileError(nRet);*/ 812 } 813 814 /* mfe: the destination file must not be a directory! */ 815 if ( nRet == 0 && S_ISDIR(aFileStat.st_mode) ) 816 { 817 return osl_File_E_ISDIR; 818 } 819 else 820 { 821 /* mfe: file does not exists or is no dir */ 822 } 823 824 tErr = oslDoCopy(pszPath,pszDestPath,nMode,nSourceSize,DestFileExists); 825 826 if ( tErr != osl_File_E_None ) 827 { 828 return tErr; 829 } 830 831 /* 832 * mfe: ignore return code 833 * since only the success of the copy is 834 * important 835 */ 836 oslChangeFileModes(pszDestPath,nMode,nAcTime,nModTime,nUID,nGID); 837 838 return tErr; 839 } 840 841 842 /****************************************************************************** 843 * 844 * Utility Functions 845 * 846 *****************************************************************************/ 847 848 /***************************************** 849 * oslDoCopy 850 ****************************************/ 851 852 #define TMP_DEST_FILE_EXTENSION ".osl-tmp" 853 854 static oslFileError oslDoCopy(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, mode_t nMode, size_t nSourceSize, int DestFileExists) 855 { 856 int nRet=0; 857 sal_Char pszTmpDestFile[PATH_MAX]; 858 size_t size_tmp_dest_buff = sizeof(pszTmpDestFile); 859 860 /* Quick fix for #106048, the whole copy file function seems 861 to be erroneous anyway and needs to be rewritten. 862 Besides osl_copyFile is currently not used from OO/SO code. 863 */ 864 memset(pszTmpDestFile, 0, size_tmp_dest_buff); 865 866 if ( DestFileExists ) 867 { 868 strncpy(pszTmpDestFile, pszDestFileName, size_tmp_dest_buff - 1); 869 870 if ((strlen(pszTmpDestFile) + strlen(TMP_DEST_FILE_EXTENSION)) >= size_tmp_dest_buff) 871 return osl_File_E_NAMETOOLONG; 872 873 strncat(pszTmpDestFile, TMP_DEST_FILE_EXTENSION, strlen(TMP_DEST_FILE_EXTENSION)); 874 875 /* FIXME: what if pszTmpDestFile already exists? */ 876 /* with getcanonical??? */ 877 nRet=rename(pszDestFileName,pszTmpDestFile); 878 } 879 880 /* mfe: should be S_ISREG */ 881 if ( !S_ISLNK(nMode) ) 882 { 883 /* copy SourceFile to DestFile */ 884 nRet = oslDoCopyFile(pszSourceFileName,pszDestFileName,nSourceSize, nMode); 885 } 886 /* mfe: OK redundant at the moment */ 887 else if ( S_ISLNK(nMode) ) 888 { 889 nRet = oslDoCopyLink(pszSourceFileName,pszDestFileName); 890 } 891 else 892 { 893 /* mfe: what to do here? */ 894 nRet=ENOSYS; 895 } 896 897 if ( nRet > 0 && DestFileExists == 1 ) 898 { 899 unlink(pszDestFileName); 900 rename(pszTmpDestFile,pszDestFileName); 901 } 902 903 if ( nRet > 0 ) 904 { 905 return oslTranslateFileError(OSL_FET_ERROR, nRet); 906 } 907 908 if ( DestFileExists == 1 ) 909 { 910 unlink(pszTmpDestFile); 911 } 912 913 return osl_File_E_None; 914 } 915 916 /***************************************** 917 * oslChangeFileModes 918 ****************************************/ 919 920 static oslFileError oslChangeFileModes( const sal_Char* pszFileName, mode_t nMode, time_t nAcTime, time_t nModTime, uid_t nUID, gid_t nGID) 921 { 922 int nRet=0; 923 struct utimbuf aTimeBuffer; 924 925 nRet = chmod(pszFileName,nMode); 926 if ( nRet < 0 ) 927 { 928 nRet=errno; 929 return oslTranslateFileError(OSL_FET_ERROR, nRet); 930 } 931 932 aTimeBuffer.actime=nAcTime; 933 aTimeBuffer.modtime=nModTime; 934 nRet=utime(pszFileName,&aTimeBuffer); 935 if ( nRet < 0 ) 936 { 937 nRet=errno; 938 return oslTranslateFileError(OSL_FET_ERROR, nRet); 939 } 940 941 if ( nUID != getuid() ) 942 { 943 nUID=getuid(); 944 } 945 946 nRet=chown(pszFileName,nUID,nGID); 947 if ( nRet < 0 ) 948 { 949 nRet=errno; 950 951 /* mfe: do not return an error here! */ 952 /* return oslTranslateFileError(nRet);*/ 953 } 954 955 return osl_File_E_None; 956 } 957 958 /***************************************** 959 * oslDoCopyLink 960 ****************************************/ 961 962 static int oslDoCopyLink(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName) 963 { 964 int nRet=0; 965 966 /* mfe: if dest file is symbolic link remove the link and place the file instead (hro says so) */ 967 /* mfe: if source is a link copy the link and not the file it points to (hro says so) */ 968 sal_Char pszLinkContent[PATH_MAX]; 969 970 pszLinkContent[0] = '\0'; 971 972 nRet = readlink(pszSourceFileName,pszLinkContent,PATH_MAX-1); 973 974 if ( nRet < 0 ) 975 { 976 nRet=errno; 977 return nRet; 978 } 979 else 980 pszLinkContent[ nRet ] = 0; 981 982 nRet = symlink(pszLinkContent,pszDestFileName); 983 984 if ( nRet < 0 ) 985 { 986 nRet=errno; 987 return nRet; 988 } 989 990 return 0; 991 } 992 993 /***************************************** 994 * oslDoCopyFile 995 ****************************************/ 996 997 static int oslDoCopyFile(const sal_Char* pszSourceFileName, const sal_Char* pszDestFileName, size_t nSourceSize, mode_t mode) 998 { 999 int SourceFileFD=0; 1000 int DestFileFD=0; 1001 int nRet=0; 1002 1003 SourceFileFD=open(pszSourceFileName,O_RDONLY); 1004 if ( SourceFileFD < 0 ) 1005 { 1006 nRet=errno; 1007 return nRet; 1008 } 1009 1010 DestFileFD=open(pszDestFileName, O_WRONLY | O_CREAT, mode); 1011 1012 if ( DestFileFD < 0 ) 1013 { 1014 nRet=errno; 1015 close(SourceFileFD); 1016 return nRet; 1017 } 1018 1019 size_t nWritten = 0; 1020 size_t nRemains = nSourceSize; 1021 1022 if ( nRemains ) 1023 { 1024 /* mmap has problems, try the direct streaming */ 1025 char pBuffer[0x8000]; 1026 size_t nRead = 0; 1027 1028 nRemains = nSourceSize; 1029 1030 do 1031 { 1032 nRead = 0; 1033 nWritten = 0; 1034 1035 size_t nToRead = std::min( (size_t)0x8000, nRemains ); 1036 nRead = read( SourceFileFD, pBuffer, nToRead ); 1037 if ( (size_t)-1 != nRead ) 1038 nWritten = write( DestFileFD, pBuffer, nRead ); 1039 1040 if ( (size_t)-1 != nWritten ) 1041 nRemains -= nWritten; 1042 } 1043 while( nRemains && (size_t)-1 != nRead && nRead == nWritten ); 1044 } 1045 1046 if ( nRemains ) 1047 { 1048 if ( errno ) 1049 nRet = errno; 1050 else 1051 nRet = ENOSPC; 1052 } 1053 1054 close( SourceFileFD ); 1055 if ( close( DestFileFD ) == -1 && nRet == 0 ) 1056 nRet = errno; 1057 1058 return nRet; 1059 } 1060 1061