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