00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <stdio.h>
00018 #include <stdlib.h>
00019
00020 #if defined(_WIN32) || defined(_WIN64)
00021 #include <spl/configwin32.h>
00022 #else
00023 #include <spl/autoconf/config.h>
00024 #endif
00025
00026 #ifdef HAVE_ERRNO_H
00027 #include <errno.h>
00028 #endif
00029 #ifdef HAVE_FCNTL_H
00030 #include <fcntl.h>
00031 #endif
00032 #ifdef HAVE_SYS_TYPES_H
00033 #include <sys/types.h>
00034 #endif
00035 #ifdef HAVE_IO_H
00036 #include <io.h>
00037 #endif
00038 #ifdef HAVE_DIRECT_H
00039 #include <direct.h>
00040 #endif
00041 #ifdef HAVE_DIRENT_H
00042 #include <dirent.h>
00043 #endif
00044 #ifdef HAVE_SYS_STAT_H
00045 #include <sys/stat.h>
00046 #endif
00047 #ifdef HAVE_UNISTD_H
00048 #include <unistd.h>
00049 #endif
00050 #ifdef HAVE_SYS_STAT_H
00051 #include <sys/stat.h>
00052 #endif
00053
00054 #include <spl/io/Directory.h>
00055 #include <spl/Environment.h>
00056 #include <spl/io/File.h>
00057 #include <spl/io/FileStream.h>
00058 #include <spl/Int32.h>
00059 #include <spl/io/WinPerm.h>
00060
00061 #ifdef _WINDOWS
00062 extern bool EncodePermissions(const Permissions& perm, _WinPerms &wperm);
00063 extern bool DecodePermissions(_WinPerms &wperm, Permissions &perm);
00064 #include <Aclapi.h>
00065 #else
00066 extern void EncodePermissions(const Permissions& perm, mode_t& mode);
00067 extern void DecodePermissions(const mode_t mode, Permissions& perm);
00068 #endif
00069
00070 FILE *_msokfopen(const char* filename, const char* mode)
00071 {
00072 #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
00073 FILE* fp = 0;
00074 errno_t err = fopen_s( &fp, File::ToOsFilePath(filename)->GetChars(), mode );
00075 if ( !err && fp )
00076 return fp;
00077 return NULL;
00078 #else
00079 return fopen( filename, mode );
00080 #endif
00081 }
00082
00083 void File::Delete( const String& filename )
00084 {
00085 if (remove( ToOsFilePath(filename)->GetChars() ) != 0)
00086 {
00087 throw new IOException(Environment::LastErrorMessage());
00088 }
00089 }
00090
00091 void File::Rename(const String& oldname, const String& newname)
00092 {
00093 if (rename(oldname.GetChars(), newname.GetChars()) != 0)
00094 {
00095 throw new IOException(Environment::LastErrorMessage());
00096 }
00097 }
00098
00099 bool File::Exists( const String& filename )
00100 {
00101 bool ret = false;
00102 FILE *fp = _msokfopen(filename.GetChars(), "r");
00103 if ( NULL != fp )
00104 {
00105 ret = true;
00106 fclose(fp);
00107 }
00108 return ret;
00109 }
00110
00111 bool File::IsFile(const String& filename)
00112 {
00113 #ifdef WIN32
00114
00115 struct _stat stbuf;
00116 if(::_stat(Directory::RemoveTrailingSeperator(filename)->GetChars(), &stbuf) != 0)
00117 {
00118 return false;
00119 }
00120
00121 return (stbuf.st_mode & _S_IFREG) != 0;
00122
00123 #else
00124
00125 struct stat stbuf;
00126 if(::stat(filename.GetChars(), &stbuf) != 0)
00127 {
00128 return false;
00129 }
00130 return S_ISREG(stbuf.st_mode);
00131
00132 #endif
00133 }
00134
00135 spl::IStreamPtr File::Create( const String& filename )
00136 {
00137 return FileStreamPtr(new FileStream(ToOsFilePath(filename)->GetChars(), File::FILEMODE_OpenOrCreate, File::FILEACC_ReadWrite));
00138 }
00139
00140 void File::Copy( const String& sourcefile, const String& destfile )
00141 {
00142 Copy(sourcefile, destfile, false);
00143 }
00144
00145 void File::Copy( const String& sourcefile, const String& destfile, bool overwrite )
00146 {
00147 if ( ! File::Exists(sourcefile) )
00148 {
00149 throw new InvalidArgumentException("Source file not found.");
00150 }
00151 if ( !overwrite && File::Exists(destfile) )
00152 {
00153 throw new IOException("Destination file exists");
00154 }
00155
00156 #ifdef _WINDOWS
00157
00158 if(::CopyFile(sourcefile.GetChars(), destfile.GetChars(), overwrite ? FALSE : TRUE) != TRUE)
00159 {
00160 throw new IOException(Environment::LastErrorMessage());
00161 }
00162
00163 #else
00164
00165 #define BUFSIZE 256
00166
00167 FILE *fpfrom, *fpto;
00168 char mode[5];
00169 char buf[BUFSIZE];
00170
00171 strcpy(mode, "r");
00172 if ( true )
00173 {
00174 strcat(mode, "b");
00175 }
00176 if ( NULL == (fpfrom = _msokfopen(sourcefile.GetChars(), mode)) )
00177 {
00178 throw new IOException(Environment::LastErrorMessage());
00179 }
00180 strcpy(mode, "w");
00181 if ( true )
00182 {
00183 strcat(mode, "b");
00184 }
00185 if ( NULL == (fpto = _msokfopen(destfile.GetChars(), mode)) )
00186 {
00187 fclose( fpfrom );
00188 throw new IOException(Environment::LastErrorMessage());
00189 }
00190 while ( ! feof( fpfrom ) )
00191 {
00192 size_t len = fread(buf, 1, BUFSIZE, fpfrom);
00193 if ( fwrite(buf, 1, len, fpto) != len )
00194 {
00195 fclose( fpto );
00196 fclose( fpfrom );
00197 throw new IOException(Environment::LastErrorMessage());
00198 }
00199 }
00200 fclose( fpto );
00201 fclose( fpfrom );
00202
00203 #endif
00204 }
00205
00206 RefCountPtr<Array<byte> > File::LoadBinary( const String& filename )
00207 {
00208 int size;
00209
00210 #ifdef _WINDOWS
00211 struct _finddata_t c_file;
00212 #if _MSC_VER >= 1400
00213 intptr_t hFile;
00214 #else
00215 long hFile;
00216 #endif
00217 if( (hFile = _findfirst( ToOsFilePath(filename)->GetChars(), &c_file )) == -1 )
00218 {
00219 return RefCountPtr<Array<byte> >();
00220 }
00221 size = c_file.size;
00222 _findclose( hFile );
00223 #else
00224 struct stat st;
00225 stat(filename.GetChars(), &st);
00226 size = st.st_size;
00227 #endif
00228
00229 FILE *fp = _msokfopen(filename.GetChars(), "rb");
00230 if ( NULL == fp )
00231 {
00232 return RefCountPtr<Array<byte> >();
00233 }
00234
00235 RefCountPtr<Array<byte> > buf( new Array<byte>(size) );
00236 if ( size != (int)fread(buf.Get(), 1, size, fp) )
00237 {
00238 return RefCountPtr<Array<byte> >();
00239 }
00240 return buf;
00241 }
00242
00243 StringPtr File::LoadText( const String& filename )
00244 {
00245 int size;
00246
00247 #ifdef _WINDOWS
00248 struct _finddata_t c_file;
00249 #if _MSC_VER >= 1400
00250 intptr_t hFile;
00251 #else
00252 long hFile;
00253 #endif
00254 if( (hFile = _findfirst( ToOsFilePath(filename)->GetChars(), &c_file )) == -1 )
00255 {
00256 return StringPtr();
00257 }
00258 size = c_file.size;
00259 _findclose( hFile );
00260 #else
00261 struct stat st;
00262 stat(filename.GetChars(), &st);
00263 if (0 == (size = st.st_size))
00264 {
00265 size = 1024;
00266 }
00267 #endif
00268
00269 FILE *fp = _msokfopen(filename.GetChars(), "r");
00270 if ( NULL == fp )
00271 {
00272 return StringPtr();
00273 }
00274
00275 const int cbufSize = 512;
00276 char cbuf[cbufSize];
00277 StringBuffer buf( size );
00278 int count;
00279
00280 while ((count = (int)fread(cbuf, 1, cbufSize, fp) ) > 0)
00281 {
00282 buf.Append(cbuf, 0, count);
00283 }
00284 return buf.ToString();
00285 }
00286
00287 StringPtr File::ToOsFilePath( const String& filepathname )
00288 {
00289 #ifdef _WIN32
00290 return filepathname.Replace('/', '\\');
00291 #else
00292 StringPtr fpn = filepathname.Replace('\\', '/');
00293 if ( fpn->IndexOf(':') > -1 )
00294 {
00295 throw new InvalidArgumentException("Colons not allowed in unix file names");
00296 }
00297 return fpn;
00298 #endif
00299 }
00300
00301 StringPtr File::GetFileName( const String& filepathname )
00302 {
00303 char sep[2];
00304 sep[0] = Directory::SeperatorChar();
00305 sep[1] = '\0';
00306 RefCountPtr<Vector<StringPtr> > parts = filepathname.Split(sep);
00307 if (parts->Count() == 0)
00308 {
00309 return StringPtr(new String());
00310 }
00311 return parts->ElementAt(parts->Count() -1);
00312 }
00313
00314 TextWriterPtr File::AppendText( const String& filename )
00315 {
00316 return TextWriterPtr(new TextWriter(FileStreamPtr(new FileStream(*ToOsFilePath(filename), File::FILEMODE_Append, File::FILEACC_Write))));
00317 }
00318
00319 TextWriterPtr File::CreateText( const String& filename )
00320 {
00321 return TextWriterPtr(new TextWriter( FileStreamPtr(new FileStream(*ToOsFilePath(filename), File::FILEMODE_Create, File::FILEACC_ReadWrite )) ));
00322 }
00323
00324 TextReaderPtr File::ReadText( const String& filename )
00325 {
00326 return TextReaderPtr(new TextReader( FileStreamPtr(new FileStream(*ToOsFilePath(filename), File::FILEMODE_Open, File::FILEACC_Read )) ));
00327 }
00328
00329 spl::IStreamPtr File::Open( const String& filename, FileMode mode )
00330 {
00331 return FileStreamPtr(new FileStream(*ToOsFilePath(filename), mode, File::FILEACC_ReadWrite ));
00332 }
00333
00334 spl::IStreamPtr File::Open( const String& filename, FileMode mode, FileAccess access )
00335 {
00336 return FileStreamPtr(new FileStream(*ToOsFilePath(filename), mode, access));
00337 }
00338
00339 spl::IStreamPtr File::OpenRead( const String& filename )
00340 {
00341 return FileStreamPtr(new FileStream(*ToOsFilePath(filename), File::FILEMODE_Open, File::FILEACC_Read));
00342 }
00343
00344 spl::IStreamPtr File::OpenText( const String& filename )
00345 {
00346 return FileStreamPtr(new FileStream(*ToOsFilePath(filename), File::FILEMODE_Open, File::FILEACC_ReadWrite));
00347 }
00348
00349 spl::IStreamPtr File::OpenWrite( const String& filename )
00350 {
00351 return FileStreamPtr(new FileStream(*ToOsFilePath(filename), File::FILEMODE_Open, File::FILEACC_Write ));
00352 }
00353
00354 long File::Size( const String& filename )
00355 {
00356 struct stat file_stats;
00357 if(0 != stat(ToOsFilePath(filename)->GetChars(), &file_stats))
00358 {
00359 throw new IOException(Environment::LastErrorMessage());
00360 }
00361 return (long)file_stats.st_size;
00362 }
00363
00364 DateTime File::GetCreationTime( const String& filename )
00365 {
00366 struct stat file_stats;
00367 if(0 != stat(ToOsFilePath(filename)->GetChars(), &file_stats))
00368 {
00369 throw new IOException(Environment::LastErrorMessage());
00370 }
00371 return DateTime(file_stats.st_ctime);
00372 }
00373
00374 DateTime File::GetLastAccessTime( const String& filename )
00375 {
00376 struct stat file_stats;
00377 if(0 != stat(ToOsFilePath(filename)->GetChars(), &file_stats))
00378 {
00379 throw new IOException(Environment::LastErrorMessage());
00380 }
00381 return DateTime(file_stats.st_atime);
00382 }
00383
00384 DateTime File::GetLastWriteTime( const String& filename )
00385 {
00386 struct stat file_stats;
00387 if(0 != stat(ToOsFilePath(filename)->GetChars(), &file_stats))
00388 {
00389 throw new IOException(Environment::LastErrorMessage());
00390 }
00391 return DateTime(file_stats.st_mtime);
00392 }
00393
00394 Permissions File::GetPermissions(const String& filename)
00395 {
00396 Permissions perms;
00397
00398 #ifdef _WINDOWS
00399
00400 _WinPerms wperm;
00401
00402 if(::GetNamedSecurityInfo((LPTSTR)(Directory::RemoveTrailingSeperator(filename)->GetChars()),
00403 SE_FILE_OBJECT,
00404 (OWNER_SECURITY_INFORMATION
00405 | GROUP_SECURITY_INFORMATION
00406 | DACL_SECURITY_INFORMATION),
00407 &wperm.user, &wperm.group, &wperm.dacl, NULL,
00408 &wperm.pdesc) != ERROR_SUCCESS)
00409 {
00410 throw new IOException(Environment::LastErrorMessage());
00411 }
00412
00413 DecodePermissions(wperm, perms);
00414
00415 #else
00416
00417 struct stat stbuf;
00418
00419 if(::stat(filename.GetChars(), &stbuf) != 0)
00420 {
00421 throw new IOException("stat error");
00422 }
00423
00424 DecodePermissions(stbuf.st_mode, perms);
00425
00426 #endif
00427
00428 return perms;
00429 }
00430
00431 void File::SetPermissions(const String& filename, const Permissions& perms)
00432 {
00433 #ifdef WIN32
00434
00435 _WinPerms wperm;
00436
00437 if(! EncodePermissions(perms, wperm))
00438 {
00439 throw new IOException(Environment::LastErrorMessage());
00440 }
00441
00442 if(::SetFileSecurity(Directory::RemoveTrailingSeperator(filename)->GetChars(), DACL_SECURITY_INFORMATION, wperm.pdesc) != TRUE)
00443 {
00444 throw new IOException(Environment::LastErrorMessage());
00445 }
00446
00447 #else
00448
00449 mode_t mode;
00450 EncodePermissions(perms, mode);
00451
00452 if(::chmod(filename.GetChars(), mode) != 0)
00453 {
00454 throw new IOException(Environment::LastErrorMessage());
00455 }
00456
00457 #endif
00458 }
00459
00460 void File::Move(const String &oldFile, const String &newFile)
00461 {
00462 #ifdef WIN32
00463
00464 if(::MoveFile(Directory::RemoveTrailingSeperator(oldFile)->GetChars(), Directory::RemoveTrailingSeperator(newFile)->GetChars()) != TRUE)
00465 {
00466 throw new IOException(Environment::LastErrorMessage());
00467 }
00468
00469 #else
00470
00471 int r = ::link(oldFile.GetChars(), newFile.GetChars());
00472 if(r != 0)
00473 {
00474 throw new IOException(Environment::LastErrorMessage());
00475 }
00476
00477 if(::unlink(oldFile.GetChars()) != 0)
00478 {
00479 ::unlink(newFile.GetChars());
00480
00481 throw new IOException(Environment::LastErrorMessage());
00482 }
00483
00484 #endif
00485 }