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