00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "CeylanStandardFileSystemManager.h"
00028
00029
00030 #include "CeylanStandardFile.h"
00031 #include "CeylanStandardDirectory.h"
00032
00033 #include "CeylanStringUtils.h"
00034 #include "CeylanOperators.h"
00035 #include "CeylanHolder.h"
00036 #include "CeylanRegularExpression.h"
00037
00038
00039 #ifdef CEYLAN_USES_CONFIG_H
00040 #include "CeylanConfig.h"
00041 #endif // CEYLAN_USES_CONFIG_H
00042
00043
00044 #include <fstream>
00045 using std::ifstream ;
00046 using std::ios ;
00047
00048 using std::string ;
00049 using std::list ;
00050
00051
00052
00053
00054 extern "C"
00055 {
00056
00057 #ifdef CEYLAN_USES_DIRECT_H
00058 #include <direct.h>
00059 #endif // CEYLAN_USES_DIRECT_H
00060
00061 #ifdef CEYLAN_USES_SYS_STAT_H
00062 #include <sys/stat.h>
00063 #endif // CEYLAN_USES_SYS_STAT_H
00064
00065 #ifdef CEYLAN_USES_UTIME_H
00066 #include <utime.h>
00067 #endif // CEYLAN_USES_UTIME_H
00068
00069 #ifdef CEYLAN_USES_SYS_UTIME_H
00070 #include <sys/utime.h>
00071 #endif // CEYLAN_USES_SYS_UTIME_H
00072
00073 }
00074
00075
00076 #ifndef PATH_MAX
00077 #define PATH_MAX 1024
00078 #endif // PATH_MAX
00079
00080
00081 using namespace Ceylan::System ;
00082
00083
00084
00085 StandardFileSystemManager *
00086 StandardFileSystemManager::_StandardFileSystemManager = 0 ;
00087
00088
00089
00090 #if CEYLAN_ARCH_WINDOWS
00091
00092
00093 const string StandardFileSystemManager::RootDirectoryPrefix = "c:" ;
00094 const Ceylan::Latin1Char StandardFileSystemManager::Separator = '\\' ;
00095
00096 #else // CEYLAN_ARCH_WINDOWS
00097
00098 const string StandardFileSystemManager::RootDirectoryPrefix = "" ;
00099 const Ceylan::Latin1Char StandardFileSystemManager::Separator = '/' ;
00100
00101 #endif // CEYLAN_ARCH_WINDOWS
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 bool StandardFileSystemManager::existsAsEntry( const string & entryPath ) const
00112 {
00113
00114 #ifdef CEYLAN_USES_STAT
00115
00116 struct stat buf ;
00117
00118 return ( ::stat( entryPath.c_str(), & buf ) == 0 ) ;
00119
00120 #else // CEYLAN_USES_STAT
00121
00122 #ifdef CEYLAN_USES__STAT
00123
00124 struct _stat buf ;
00125
00126 return ( ::_stat( entryPath.c_str(), & buf ) == 0 ) ;
00127
00128
00129 #else // CEYLAN_USES__STAT
00130
00131 throw EntryLookupFailed(
00132 "StandardFileSystemManager::existsAsEntry: "
00133 "not available on this platform." ) ;
00134
00135 #endif // CEYLAN_USES__STAT
00136
00137 #endif // CEYLAN_USES_STAT
00138
00139 }
00140
00141
00142
00143 void StandardFileSystemManager::createSymbolicLink(
00144 const string & linkTarget, const string & linkName )
00145 {
00146
00147 #if CEYLAN_USES_SYMBOLIC_LINKS
00148
00149 if ( ::symlink( linkTarget.c_str(), linkName.c_str() ) == -1 )
00150 throw SymlinkFailed( "StandardFileSystemManager::createSymbolicLink "
00151 "failed when creating link '" + linkName
00152 + "' which was to point to '" + linkTarget
00153 + "': " + System::explainError() ) ;
00154
00155 #else // CEYLAN_USES_SYMBOLIC_LINKS
00156
00157 throw SymlinkFailed( "StandardFileSystemManager::createSymbolicLink: "
00158 "symbolic link feature not available" ) ;
00159
00160 #endif // CEYLAN_USES_SYMBOLIC_LINKS
00161
00162 }
00163
00164
00165
00166 time_t StandardFileSystemManager::getEntryChangeTime( const string & entryPath )
00167 {
00168
00169 #ifdef CEYLAN_USES_STAT
00170
00171 struct stat buf ;
00172
00173 if ( ::stat( entryPath.c_str(), & buf ) == 0 )
00174 return buf.st_ctime ;
00175
00176
00177
00178 #else // CEYLAN_USES_STAT
00179
00180
00181 #ifdef CEYLAN_USES__STAT
00182
00183 struct _stat buf ;
00184
00185 if ( ::_stat( entryPath.c_str(), & buf ) == 0 )
00186 return buf.st_ctime ;
00187
00188
00189
00190 #else // CEYLAN_USES__STAT
00191
00192 throw GetChangeTimeFailed( "StandardFileSystemManager::getEntryChangeTime: "
00193 "not available on this platform." ) ;
00194
00195 #endif // CEYLAN_USES__STAT
00196
00197
00198 #endif // CEYLAN_USES_STAT
00199
00200 throw GetChangeTimeFailed(
00201 "StandardFileSystemManager::getEntryChangeTime: "
00202 "unable to get last change time for entry '" + entryPath + "': "
00203 + System::explainError() ) ;
00204
00205 }
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215 const string & StandardFileSystemManager::getRootDirectoryPrefix() const
00216 {
00217
00218 return RootDirectoryPrefix ;
00219
00220 }
00221
00222
00223
00224 Ceylan::Latin1Char StandardFileSystemManager::getSeparator() const
00225 {
00226
00227 return Separator ;
00228
00229 }
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239 File & StandardFileSystemManager::createFile( const string & filename,
00240 OpeningFlag createFlag, PermissionFlag permissionFlag )
00241 {
00242
00243 return StandardFile::Create( filename, createFlag, permissionFlag ) ;
00244
00245 }
00246
00247
00248
00249 File & StandardFileSystemManager::openFile( const string & filename,
00250 OpeningFlag openFlag )
00251 {
00252
00253 return StandardFile::Open( filename, openFlag ) ;
00254
00255 }
00256
00257
00258
00259 bool StandardFileSystemManager::existsAsFileOrSymbolicLink(
00260 const string & filename ) const
00261 {
00262
00263 #ifdef CEYLAN_USES_STAT
00264
00265 struct stat buf ;
00266
00267
00268 #if CEYLAN_USES_SYMBOLIC_LINKS
00269
00270
00271 return ( ::stat( filename.c_str(), & buf ) == 0
00272 && ( S_ISREG( buf.st_mode ) || S_ISLNK( buf.st_mode ) ) ) ;
00273
00274 #else // CEYLAN_USES_SYMBOLIC_LINKS
00275
00276
00277 return ( ::stat( filename.c_str(), & buf ) == 0
00278 && S_ISREG( buf.st_mode ) ) ;
00279
00280 #endif // CEYLAN_USES_SYMBOLIC_LINKS
00281
00282 #else // CEYLAN_USES_STAT
00283
00284 #ifdef CEYLAN_USES__STAT
00285
00286 struct _stat buf ;
00287
00288 return ( ::_stat( filename.c_str(), & buf ) == 0
00289 && ( buf.st_mode & _S_IFREG ) ) ;
00290
00291 #else // CEYLAN_USES__STAT
00292
00293 throw FileLookupFailed(
00294 "StandardFileSystemManager::existsAsFileOrSymbolicLink: "
00295 "not available on this platform." ) ;
00296
00297 #endif // CEYLAN_USES__STAT
00298
00299 #endif // CEYLAN_USES_STAT
00300
00301 }
00302
00303
00304
00305 void StandardFileSystemManager::removeFile( const string & filename )
00306 {
00307
00308 #ifdef CEYLAN_USES_UNLINK
00309
00310 if ( ::unlink( filename.c_str() ) != 0 )
00311 throw FileRemoveFailed(
00312 "StandardFileSystemManager::removeFile failed for '"
00313 + filename + "': " + System::explainError() ) ;
00314
00315 #else // CEYLAN_USES_UNLINK
00316
00317 #ifdef CEYLAN_USES__UNLINK
00318
00319 if ( ::_unlink( filename.c_str() ) != 0 )
00320 throw FileRemoveFailed(
00321 "StandardFileSystemManager::removeFile failed: file '" + filename
00322 + "': " + System::explainError() ) ;
00323
00324 #else // CEYLAN_USES__UNLINK
00325
00326 throw FileRemoveFailed( "StandardFileSystemManager::removeFile: "
00327 "not available on this platform." ) ;
00328
00329 #endif // CEYLAN_USES__UNLINK
00330
00331 #endif // CEYLAN_USES_UNLINK
00332
00333 }
00334
00335
00336
00337 void StandardFileSystemManager::moveFile( const string & sourceFilename,
00338 const string & targetFilename )
00339 {
00340
00341 #ifdef CEYLAN_USES_RENAME
00342
00343
00344
00345 if ( ::rename( sourceFilename.c_str(), targetFilename.c_str() ) == -1 )
00346 throw FileMoveFailed(
00347 "StandardFileSystemManager::moveFile failed when moving '"
00348 + sourceFilename + "' to '" + targetFilename + "': "
00349 + System::explainError() ) ;
00350
00351 #else // CEYLAN_USES_RENAME
00352
00353
00354
00355 try
00356 {
00357
00358 copyFile( sourceFilename, targetFilename ) ;
00359 removeFile( sourceFilename ) ;
00360
00361 }
00362 catch( const FileException & e )
00363 {
00364
00365 throw FileMoveFailed( "StandardFileSystemManager::moveFile failed: "
00366 + e.toString() ) ;
00367
00368 }
00369
00370
00371 #endif // CEYLAN_USES_RENAME
00372
00373 }
00374
00375
00376
00377 void StandardFileSystemManager::copyFile( const string & sourceFilename,
00378 const string & targetFilename )
00379 {
00380
00381 #if CEYLAN_USES_FILE_DESCRIPTORS
00382
00383
00384
00385
00386 try
00387 {
00388
00389 Ceylan::Holder<StandardFile> sourceFile(
00390 StandardFile::Open( sourceFilename ) ) ;
00391
00392 sourceFile->saveAs( targetFilename ) ;
00393 sourceFile->close() ;
00394
00395
00396
00397 }
00398 catch ( const FileException & e )
00399 {
00400 throw FileCopyFailed(
00401 "StandardFileSystemManager::copyFile failed when copying '"
00402 + sourceFilename + "' to '" + targetFilename + "': "
00403 + e.toString() ) ;
00404 }
00405
00406
00407 #else // if CEYLAN_USES_FILE_DESCRIPTORS
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432 try
00433 {
00434
00435 Size fileSize = getSize( sourceFilename ) ;
00436
00437 StandardFile & sourceFile = StandardFile::Open( sourceFilename ) ;
00438
00439
00440 StandardFile & targetFile = StandardFile::Create(
00441 targetFilename, File::CreateToWriteBinary, File::OwnerReadWrite ) ;
00442
00443 Size written = 0 ;
00444
00445 Size bufferSize = ( fileSize > File::BigBufferSize ?
00446 File::BigBufferSize: fileSize ) ;
00447
00448 char * buf = new char[ bufferSize ] ;
00449
00450 SignedSize readCount ;
00451
00452 while ( written < fileSize )
00453 {
00454
00455 Size toRead = fileSize - written ;
00456
00457 if ( toRead > bufferSize )
00458 toRead = bufferSize ;
00459
00460 try
00461 {
00462
00463 readCount = static_cast<SignedSize>(
00464 sourceFile.read( buf, toRead ) ) ;
00465
00466 }
00467 catch( const InputStream::ReadFailedException & e )
00468 {
00469
00470 delete [] buf ;
00471
00472 throw FileCopyFailed( "StandardFileSystemManager::copyFile "
00473 "failed when copying '" + sourceFilename + "' to '"
00474 + targetFilename + "': " + e.toString() ) ;
00475
00476 }
00477
00478
00479 try
00480 {
00481
00482 targetFile.write( buf, readCount ) ;
00483
00484 }
00485 catch( const OutputStream::WriteFailedException & e )
00486 {
00487
00488 delete [] buf ;
00489
00490 throw FileCopyFailed( "StandardFileSystemManager::copyFile "
00491 "failed when copying '" + sourceFilename + "' to '"
00492 + targetFilename + "': " + e.toString() ) ;
00493
00494 }
00495
00496 written += readCount ;
00497 }
00498
00499 delete [] buf ;
00500
00501 targetFile.close() ;
00502 sourceFile.close() ;
00503
00504 }
00505 catch ( const SystemException & e )
00506 {
00507
00508 throw FileCopyFailed( "StandardFileSystemManager::copyFile "
00509 "failed when copying '" + sourceFilename + "' to '"
00510 + targetFilename + "': " + e.toString() ) ;
00511
00512 }
00513
00514 #endif // if CEYLAN_USES_FILE_DESCRIPTORS
00515
00516 }
00517
00518
00519
00520 Size StandardFileSystemManager::getSize( const string & filename )
00521 {
00522
00523 #ifdef CEYLAN_USES_STAT
00524
00525 struct stat buf ;
00526
00527 if ( ::stat( filename.c_str(), & buf ) == 0 )
00528 return static_cast<Size>( buf.st_size ) ;
00529
00530 throw FileSizeRequestFailed( "StandardFileSystemManager::getSize: "
00531 "could not stat file '" + filename + "': " + System::explainError() ) ;
00532
00533 #else // CEYLAN_USES_STAT
00534
00535
00536 #if CEYLAN_USES_FILE_DESCRIPTORS == 0
00537
00538
00539
00540 ifstream tmpFile ;
00541
00542 tmpFile.open( filename.c_str(), ios::binary ) ;
00543
00544 if ( ( ! tmpFile.is_open() ) || ( ! tmpFile.good() ) )
00545 throw FileSizeRequestFailed(
00546 "StandardFileSystemManager::getSize: failed for '" + filename
00547 + "': error opening file, "
00548 + StandardFile::InterpretState( tmpFile ) ) ;
00549
00550 tmpFile.seekg( 0, ios::end ) ;
00551
00552 Size size = static_cast<Size>( tmpFile.tellg() ) ;
00553
00554 tmpFile.close() ;
00555
00556 return size ;
00557
00558 #else // CEYLAN_USES_FILE_DESCRIPTORS
00559
00560 throw FileSizeRequestFailed( "StandardFileSystemManager::getSize: "
00561 "not available on this platform." ) ;
00562
00563 #endif // CEYLAN_USES_FILE_DESCRIPTORS
00564
00565 #endif // CEYLAN_USES_STAT
00566
00567 }
00568
00569
00570
00571 time_t StandardFileSystemManager::getLastChangeTimeFile(
00572 const string & filename )
00573 {
00574
00575 #ifdef CEYLAN_USES_STAT
00576
00577 struct stat buf ;
00578
00579 if ( ::stat( filename.c_str(), & buf ) == 0 )
00580 return buf.st_ctime ;
00581
00582 #else // CEYLAN_USES_STAT
00583
00584
00585 #ifdef CEYLAN_USES__STAT
00586
00587 struct _stat buf ;
00588
00589 if ( ::_stat( filename.c_str(), & buf ) == 0 )
00590 return buf.st_ctime ;
00591
00592 #else // CEYLAN_USES__STAT
00593
00594 throw FileLastChangeTimeRequestFailed(
00595 "StandardFileSystemManager::getLastChangeTimeFile: "
00596 "not available on this platform." ) ;
00597
00598 #endif // CEYLAN_USES__STAT
00599
00600
00601 #endif // CEYLAN_USES_STAT
00602
00603 throw FileLastChangeTimeRequestFailed(
00604 "StandardFileSystemManager::getLastChangeTimeFile: "
00605 "unable to get last change time for file '" + filename + "': "
00606 + System::explainError() ) ;
00607
00608 }
00609
00610
00611
00612 void StandardFileSystemManager::touch( const string & filename )
00613 {
00614
00615 #ifdef CEYLAN_USES_UTIME
00616
00617 if ( ::utime( filename.c_str(), 0 ) )
00618 throw FileTouchFailed( "StandardFileSystemManager::touch failed for '"
00619 + filename + "': " + System::explainError() ) ;
00620
00621 #else // CEYLAN_USES_UTIME
00622
00623 #ifdef CEYLAN_USES__UTIME
00624
00625 if ( ::_utime( filename.c_str(), 0 ) == -1 )
00626 throw FileTouchFailed( "StandardFileSystemManager::touch failed for '"
00627 + filename + "': " + System::explainError() ) ;
00628
00629 #else // CEYLAN_USES__UTIME
00630
00631 throw FileTouchFailed( "StandardFileSystemManager::touch "
00632 "not available on this platform." ) ;
00633
00634 #endif // CEYLAN_USES__UTIME
00635
00636 #endif // CEYLAN_USES_UTIME
00637
00638 }
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650 Directory & StandardFileSystemManager::createDirectory(
00651 const string & newDirectoryName )
00652 {
00653
00654 return StandardDirectory::Create( newDirectoryName ) ;
00655
00656 }
00657
00658
00659
00660 Directory & StandardFileSystemManager::openDirectory(
00661 const string & directoryName )
00662 {
00663
00664 return StandardDirectory::Open( directoryName ) ;
00665
00666 }
00667
00668
00669
00670 bool StandardFileSystemManager::existsAsDirectory(
00671 const string & directoryPath ) const
00672 {
00673
00674 #ifdef CEYLAN_USES_STAT
00675
00676 struct stat buf ;
00677
00678 return ::stat( directoryPath.c_str(), & buf ) == 0
00679 && ( S_ISDIR( buf.st_mode ) ) ;
00680
00681 #else // CEYLAN_USES_STAT
00682
00683 #ifdef CEYLAN_USES__STAT
00684
00685 struct _stat buf ;
00686
00687 if ( ::_stat( directoryPath.c_str(), & buf ) == 0 )
00688 {
00689
00690 if ( buf.st_mode & _S_IFDIR )
00691 {
00692
00693
00694
00695
00696
00697 return true ;
00698
00699 }
00700 else
00701 {
00702
00703
00704
00705
00706
00707 return false ;
00708
00709 }
00710
00711 }
00712 else
00713 {
00714
00715
00716
00717
00718
00719
00720 return false ;
00721
00722 }
00723
00724 #else // CEYLAN_USES__STAT
00725
00726 throw DirectoryLookupFailed(
00727 "StandardFileSystemManager::existsAsDirectory: "
00728 "operation not supported on this platform." ) ;
00729
00730 #endif // CEYLAN_USES__STAT
00731
00732 #endif // CEYLAN_USES_STAT
00733
00734 }
00735
00736
00737
00738 void StandardFileSystemManager::removeDirectory( const string & directoryPath,
00739 bool recursive )
00740 {
00741
00742 #if CEYLAN_ARCH_NINTENDO_DS
00743
00744 throw DirectoryRemoveFailed( "StandardFileSystemManager::removeDirectory:"
00745 "not supported on the Nintendo DS platform." ) ;
00746
00747 #else // CEYLAN_ARCH_NINTENDO_DS
00748
00749 #if defined(CEYLAN_USES_RMDIR) || defined(CEYLAN_USES__RMDIR)
00750
00751
00752
00753
00754 #ifdef CEYLAN_USES_STAT
00755
00756 struct stat buf ;
00757
00758 #else // CEYLAN_USES_STAT
00759
00760 struct _stat buf ;
00761
00762 #endif // CEYLAN_USES_STAT
00763
00764 if ( directoryPath.empty() )
00765 throw DirectoryRemoveFailed(
00766 "StandardFileSystemManager::removeDirectory: "
00767 "void directory specified" ) ;
00768
00769
00770 string thisPath = directoryPath ;
00771
00772 removeLeadingSeparator( thisPath ) ;
00773
00774
00775 if ( recursive )
00776 {
00777
00778 StandardDirectory & d = StandardDirectory::Open( thisPath ) ;
00779
00780 list<string> nodes ;
00781 d.getEntries( nodes ) ;
00782
00783 for ( list<string>::const_iterator it = nodes.begin();
00784 it != nodes.end(); it++ )
00785 {
00786
00787 string newPath = joinPath( thisPath, *it ) ;
00788
00789 #ifdef CEYLAN_USES_STAT
00790
00791 if ( ::stat( newPath.c_str(), & buf ) == 0 )
00792
00793 #else // CEYLAN_USES_STAT
00794
00795 if ( ::_stat( newPath.c_str(), & buf ) == 0 )
00796
00797 #endif // CEYLAN_USES_STAT
00798
00799 {
00800
00801
00802 #if CEYLAN_USES_SYMBOLIC_LINKS
00803 if ( S_ISLNK( buf.st_mode ) || ! S_ISDIR( buf.st_mode ) )
00804 #else
00805
00806 #if CEYLAN_ARCH_WINDOWS
00807 if ( ! ( buf.st_mode & _S_IFDIR ) )
00808 #else
00809 if ( ! S_ISDIR( buf.st_mode ) )
00810 #endif
00811
00812 #endif
00813 {
00814
00815
00816 #ifdef CEYLAN_USES_UNLINK
00817 if ( ::unlink( newPath.c_str() ) )
00818 #else // CEYLAN_USES_UNLINK
00819 if ( ::_unlink( newPath.c_str() ) )
00820 #endif // CEYLAN_USES_UNLINK
00821 throw DirectoryRemoveFailed(
00822 "StandardFileSystemManager::removeDirectory"
00823 " failed in unlink for '" + newPath + ": "
00824 + System::explainError() ) ;
00825 }
00826 else
00827
00828
00829 #if CEYLAN_ARCH_WINDOWS
00830 if ( buf.st_mode & _S_IFDIR )
00831 #else // CEYLAN_ARCH_WINDOWS
00832 if ( S_ISDIR( buf.st_mode ) )
00833 #endif // CEYLAN_ARCH_WINDOWS
00834 {
00835
00836 removeDirectory( newPath ) ;
00837 }
00838
00839 }
00840 else
00841 {
00842
00843 throw DirectoryRemoveFailed(
00844 "StandardFileSystemManager::removeDirectory "
00845 "failed in stat for " + newPath + ": "
00846 + System::explainError() ) ;
00847 }
00848 }
00849
00850 }
00851
00852 #ifdef CEYLAN_USES_RMDIR
00853
00854 if ( ::rmdir( thisPath.c_str() ) )
00855 throw DirectoryRemoveFailed(
00856 "StandardFileSystemManager::removeDirectory failed in rmdir for "
00857 + thisPath + ": " + explainError() ) ;
00858
00859 #elif defined(CEYLAN_USES__RMDIR) // CEYLAN_USES_RMDIR
00860
00861 if ( ::_rmdir( thisPath.c_str() ) )
00862 throw DirectoryRemoveFailed(
00863 "StandardFileSystemManager::removeDirectory failed in _rmdir for "
00864 + thisPath + ": " + System::explainError() ) ;
00865
00866 #else // CEYLAN_USES_RMDIR
00867
00868 throw DirectoryRemoveFailed( "StandardFileSystemManager::removeDirectory "
00869 "not available on this platform." ) ;
00870
00871 #endif // CEYLAN_USES_RMDIR
00872
00873
00874
00875 #else // CEYLAN_USES_RMDIR
00876
00877 throw DirectoryRemoveFailed( "StandardFileSystemManager::removeDirectory "
00878 "not available on this platform." ) ;
00879
00880 #endif // CEYLAN_USES_RMDIR
00881
00882 #endif // CEYLAN_ARCH_NINTENDO_DS
00883
00884 }
00885
00886
00887
00888 void StandardFileSystemManager::moveDirectory(
00889 const string & sourceDirectoryPath, const string & targetDirectoryPath )
00890 {
00891
00892
00893 #ifdef CEYLAN_USES_RENAME
00894
00895
00896
00897 if ( ::rename( sourceDirectoryPath.c_str(), targetDirectoryPath.c_str() )
00898 == -1 )
00899 throw DirectoryMoveFailed(
00900 "StandardFileSystemManager::moveDirectory failed when renaming '"
00901 + sourceDirectoryPath + "' into '" + targetDirectoryPath + "': "
00902 + System::explainError() ) ;
00903
00904 #else // CEYLAN_USES_RENAME
00905
00906
00907
00908 try
00909 {
00910
00911 copyDirectory( sourceDirectoryPath, targetDirectoryPath ) ;
00912 removeDirectory( sourceDirectoryPath ) ;
00913
00914 }
00915 catch( const DirectoryException & e )
00916 {
00917
00918 throw DirectoryMoveFailed(
00919 "StandardFileSystemManager::moveDirectory failed: "
00920 + e.toString() ) ;
00921
00922 }
00923
00924
00925 #endif // CEYLAN_USES_RENAME
00926
00927 }
00928
00929
00930
00931 void StandardFileSystemManager::copyDirectory(
00932 const string & sourceDirectoryPath, const string & targetDirectoryPath )
00933 {
00934
00935 throw DirectoryCopyFailed( "StandardFileSystemManager::copyDirectory: "
00936 "not supported on this platform." ) ;
00937
00938 }
00939
00940
00941
00942 time_t StandardFileSystemManager::getLastChangeTimeDirectory(
00943 const string & directoryPath )
00944 {
00945
00946 #ifdef CEYLAN_USES_STAT
00947
00948 struct stat buf ;
00949
00950 if ( ::stat( directoryPath.c_str(), & buf ) == 0 )
00951 return buf.st_ctime ;
00952
00953 #else // CEYLAN_USES_STAT
00954
00955
00956 #ifdef CEYLAN_USES__STAT
00957
00958 struct _stat buf ;
00959
00960 if ( ::_stat( directoryPath.c_str(), & buf ) == 0 )
00961 return buf.st_ctime ;
00962
00963 #else // CEYLAN_USES__STAT
00964
00965 throw DirectoryLastChangeTimeRequestFailed(
00966 "StandardFileSystemManager::getLastChangeTimeDirectory: "
00967 "not available on this platform." ) ;
00968
00969 #endif // CEYLAN_USES__STAT
00970
00971
00972 #endif // CEYLAN_USES_STAT
00973
00974 throw DirectoryLastChangeTimeRequestFailed(
00975 "StandardFileSystemManager::getLastChangeTimeDirectory: "
00976 "unable to get last change time for directory '" + directoryPath + "': "
00977 + explainError() ) ;
00978
00979 }
00980
00981
00982
00983 bool StandardFileSystemManager::isAValidDirectoryPath(
00984 const string & directoryString )
00985 {
00986
00987 #if CEYLAN_USES_REGEX
00988
00989 string directoryPattern = "^[" + RootDirectoryPrefix
00990 + Separator + "]{1,1}" ;
00991
00992 Ceylan::RegExp target( directoryString ) ;
00993
00994 return target.matches( directoryPattern ) ;
00995
00996 #else // CEYLAN_USES_REGEX
00997
00998
00999 return true ;
01000
01001 #endif // CEYLAN_USES_REGEX
01002
01003 }
01004
01005
01006
01007 bool StandardFileSystemManager::isAbsolutePath( const string & path )
01008 {
01009
01010 if ( path.empty() )
01011 return false ;
01012
01013
01014
01015
01016
01017
01018
01019 #if CEYLAN_ARCH_WINDOWS
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029 if ( ( Ceylan::isLetter( path[0] ) ) && ( path[1] == ':' ) )
01030 return true ;
01031
01032 return false ;
01033
01034 #else // CEYLAN_ARCH_WINDOWS
01035
01036 return ( path[0] == Separator ) ;
01037
01038 #endif // CEYLAN_ARCH_WINDOWS
01039
01040 }
01041
01042
01043
01044 std::string StandardFileSystemManager::getCurrentWorkingDirectoryPath()
01045 {
01046
01047 #ifdef CEYLAN_USES_GETCWD
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062 char * buf = new char[ PATH_MAX + 1 ] ;
01063
01064 if ( ::getcwd( buf, PATH_MAX ) )
01065 {
01066
01067 string res( buf ) ;
01068 delete [] buf ;
01069
01070 return res ;
01071
01072 }
01073 else
01074 {
01075
01076 delete [] buf ;
01077
01078 throw DirectoryGetCurrentFailed(
01079 "StandardFileSystemManager::getCurrentWorkingDirectoryPath: "
01080 "unable to determine current directory: " + explainError() ) ;
01081
01082 }
01083
01084 #else // CEYLAN_USES_GETCWD
01085
01086 #ifdef CEYLAN_USES__GETCWD
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102 char * buf = new char[ PATH_MAX + 1 ] ;
01103
01104 if ( ::_getcwd( buf, PATH_MAX ) )
01105 {
01106
01107 string res( buf ) ;
01108 delete [] buf ;
01109
01110 return res ;
01111
01112 }
01113 else
01114 {
01115
01116 delete [] buf ;
01117
01118 throw DirectoryGetCurrentFailed(
01119 "StandardFileSystemManager::getCurrentWorkingdirectoryPath: "
01120 "unable to determine current directory: " + explainError() ) ;
01121
01122 }
01123
01124 #else // CEYLAN_USES__GETCWD
01125
01126 throw DirectoryGetCurrentFailed(
01127 "StandardFileSystemManager::getCurrentWorkingdirectoryPath: "
01128 "not available on this platform" ) ;
01129
01130 #endif // CEYLAN_USES__GETCWD
01131
01132 #endif // CEYLAN_USES_GETCWD
01133
01134 }
01135
01136
01137
01138 void StandardFileSystemManager::changeWorkingDirectory(
01139 const string & newWorkingDirectory )
01140 {
01141
01142 #ifdef CEYLAN_USES_CHDIR
01143
01144 if ( ::chdir( newWorkingDirectory.c_str() ) != 0 )
01145
01146 #else // CEYLAN_USES_CHDIR
01147
01148 #ifdef CEYLAN_USES__CHDIR
01149
01150 if ( ::_chdir( newWorkingDirectory.c_str() ) != 0 )
01151
01152 #else // CEYLAN_USES__CHDIR
01153
01154 throw DirectoryChangeFailed(
01155 "StandardFileSystemManager::changeWorkingDirectory: "
01156 "not supported on this platform" ) ;
01157
01158 #endif // CEYLAN_USES__CHDIR
01159
01160 #endif // CEYLAN_USES_CHDIR
01161
01162
01163 throw DirectoryChangeFailed(
01164 "StandardFileSystemManager::changeWorkingDirectory: "
01165 "unable to change current working directory to "
01166 + newWorkingDirectory + ": " + explainError() ) ;
01167
01168 }
01169
01170
01171
01172
01173
01174
01175
01176
01177 const string StandardFileSystemManager::toString(
01178 Ceylan::VerbosityLevels level ) const
01179 {
01180
01181 return "Standard filesystem manager" ;
01182
01183 }
01184
01185
01186
01187
01188
01189
01190
01191 StandardFileSystemManager &
01192 StandardFileSystemManager::GetStandardFileSystemManager()
01193 {
01194
01195 if ( _StandardFileSystemManager == 0 )
01196 _StandardFileSystemManager = new StandardFileSystemManager() ;
01197
01198 return *_StandardFileSystemManager ;
01199
01200 }
01201
01202
01203
01204 void StandardFileSystemManager::RemoveStandardFileSystemManager()
01205 {
01206
01207 if ( _StandardFileSystemManager != 0 )
01208 {
01209
01210 if ( FileSystemManager::_CurrentDefaultFileSystemManager ==
01211 _StandardFileSystemManager )
01212 FileSystemManager::_CurrentDefaultFileSystemManager = 0 ;
01213
01214 delete _StandardFileSystemManager ;
01215 _StandardFileSystemManager = 0 ;
01216
01217 }
01218
01219 }
01220
01221
01222
01223
01224 StandardFileSystemManager::StandardFileSystemManager()
01225 {
01226
01227 #if CEYLAN_ARCH_NINTENDO_DS
01228
01229 throw StandardFileSystemManagerException(
01230 "StandardFileSystemManager constructor: "
01231 "not supported on the Nintendo DS platform." ) ;
01232
01233 #endif // CEYLAN_ARCH_NINTENDO_DS
01234
01235 }
01236
01237
01238
01239 StandardFileSystemManager::~StandardFileSystemManager() throw()
01240 {
01241
01242 if ( _StandardFileSystemManager == this )
01243 _StandardFileSystemManager = 0 ;
01244
01245
01246
01247 }
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259 FileDescriptor StandardFileSystemManager::Duplicate( FileDescriptor fd )
01260 {
01261
01262 #if CEYLAN_ARCH_NINTENDO_DS
01263
01264 throw DuplicateFailed( "StandardFileSystemManager::Duplicate failed: "
01265 "not supported on the Nintendo DS platform." ) ;
01266
01267 #else // CEYLAN_ARCH_NINTENDO_DS
01268
01269 #if CEYLAN_USES_FILE_DESCRIPTORS
01270
01271 FileDescriptor newFD = ::dup( fd ) ;
01272
01273 if ( newFD == -1 )
01274 throw DuplicateFailed(
01275 "StandardFileSystemManager::Duplicate failed for file descriptor "
01276 + Ceylan::toString( fd ) + "." ) ;
01277
01278 return newFD ;
01279
01280 #else // CEYLAN_USES_FILE_DESCRIPTORS
01281
01282 throw DuplicateFailed( "StandardFileSystemManager::Duplicate: "
01283 "file descriptor feature not available." ) ;
01284
01285 #endif // CEYLAN_USES_FILE_DESCRIPTORS
01286
01287 #endif // CEYLAN_ARCH_NINTENDO_DS
01288
01289 }
01290