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
00028
00029 #include "precomp.h"
00030 #include "file.h"
00031 #include "exception.h"
00032 #include "string_help.h"
00033 #include "security_descriptor.h"
00034 #ifndef WIN32
00035 #include <sys/types.h>
00036 #include <sys/stat.h>
00037 #include <fcntl.h>
00038 #include <unistd.h>
00039 #endif
00040
00041 #ifdef WIN32
00042 #define invalid_handle INVALID_HANDLE_VALUE
00043 #else
00044 #define invalid_handle -1
00045 #endif
00046
00048
00049
00050 CL_File::CL_File() : handle(invalid_handle)
00051 {
00052 }
00053
00054 CL_File::CL_File(const CL_String &filename, CreateMode create_mode, unsigned int access, unsigned int share)
00055 : handle(invalid_handle)
00056 {
00057 bool result = create(filename, create_mode, access, share);
00058 if (result == false)
00059 throw CL_Exception(TEXT("Unable to create file"));
00060 }
00061
00062 CL_File::CL_File(const CL_String &filename, OpenMode open_mode, unsigned int access, unsigned int share)
00063 : handle(invalid_handle)
00064 {
00065 bool result = open(filename, open_mode, access, share);
00066 if (result == false)
00067 throw CL_Exception(TEXT("Unable to open file"));
00068 }
00069
00070 CL_File::CL_File(
00071 const CL_String &filename,
00072 CreateMode mode,
00073 const CL_SecurityDescriptor &permissions,
00074 unsigned int access,
00075 unsigned int share)
00076 : handle(invalid_handle)
00077 {
00078 bool result = create(filename, mode, permissions, access, share);
00079 if (result == false)
00080 throw CL_Exception(TEXT("Unable to create file"));
00081 }
00082
00083 CL_File::CL_File(
00084 const CL_String &filename,
00085 OpenMode mode,
00086 const CL_SecurityDescriptor &permissions,
00087 unsigned int access,
00088 unsigned int share)
00089 : handle(invalid_handle)
00090 {
00091 bool result = open(filename, mode, permissions, access, share);
00092 if (result == false)
00093 throw CL_Exception(TEXT("Unable to open file"));
00094 }
00095
00096 CL_File::~CL_File()
00097 {
00098 close();
00099 }
00100
00102
00103
00104 int CL_File::get_size() const
00105 {
00106 #ifdef WIN32
00107 if (handle == invalid_handle)
00108 throw CL_Exception(TEXT("Unable to get file size, no file open"));
00109
00110 DWORD size = GetFileSize(handle, 0);
00111 if (size == INVALID_FILE_SIZE)
00112 throw CL_Exception(TEXT("Unable to get file size"));
00113
00114 return size;
00115 #else
00116 if (handle == invalid_handle)
00117 throw CL_Exception(TEXT("Unable to get file size, no file open"));
00118
00119 off_t old_pos = lseek(handle, 0, SEEK_CUR);
00120 if (old_pos == (off_t) -1)
00121 throw CL_Exception(TEXT("Unable to get file size"));
00122 off_t size = lseek(handle, 0, SEEK_END);
00123 lseek(handle, old_pos, SEEK_SET);
00124
00125 if (size == (off_t) -1)
00126 throw CL_Exception(TEXT("Unable to get file size"));
00127
00128 return (int) size;
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141 #endif
00142 }
00143
00144 int CL_File::get_position() const
00145 {
00146 #ifdef WIN32
00147 if (handle == invalid_handle)
00148 throw CL_Exception(TEXT("Unable to get file position pointer, no file open"));
00149
00150 DWORD pos = SetFilePointer(handle, 0, 0, FILE_CURRENT);
00151 if (pos == INVALID_SET_FILE_POINTER)
00152 throw CL_Exception(TEXT("Unable to get file position pointer"));
00153
00154 return (int) pos;
00155 #else
00156 if (handle == invalid_handle)
00157 throw CL_Exception(TEXT("Unable to get file position pointer, no file open"));
00158
00159 off_t pos = lseek(handle, 0, SEEK_CUR);
00160 if (pos == (off_t) -1)
00161 throw CL_Exception(TEXT("Unable to get file position pointer"));
00162
00163 return pos;
00164 #endif
00165 }
00166
00167 CL_SecurityDescriptor CL_File::get_permissions() const
00168 {
00169 CL_SecurityDescriptor security_descriptor;
00170 return security_descriptor;
00171 }
00172
00174
00175
00176 bool CL_File::create(const CL_String &filename, CreateMode create_mode, unsigned int access, unsigned int share)
00177 {
00178 if (handle != invalid_handle)
00179 close();
00180
00181 #ifdef WIN32
00182 DWORD win32_desired_access = 0;
00183 DWORD win32_share_mode = 0;
00184 DWORD win32_create_mode = 0;
00185 LPSECURITY_ATTRIBUTES win32_security_attributes = 0;
00186
00187 switch (create_mode)
00188 {
00189 case create_always: win32_create_mode = CREATE_ALWAYS; break;
00190 case create_new: win32_create_mode = CREATE_NEW; break;
00191 }
00192
00193 if (access & access_read)
00194 win32_desired_access |= GENERIC_READ;
00195 if (access & access_write)
00196 win32_desired_access |= GENERIC_WRITE;
00197
00198 if (share & share_read)
00199 win32_share_mode |= FILE_SHARE_READ;
00200 if (share & share_write)
00201 win32_share_mode |= FILE_SHARE_WRITE;
00202 if (share & share_delete)
00203 win32_share_mode |= FILE_SHARE_DELETE;
00204
00205 handle = CreateFile(
00206 filename.c_str(),
00207 win32_desired_access,
00208 win32_share_mode,
00209 win32_security_attributes,
00210 win32_create_mode,
00211 FILE_ATTRIBUTE_NORMAL,
00212 0);
00213
00214 return (handle != invalid_handle);
00215 #else
00216 int flags = 0;
00217 mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH;
00218
00219 if ((access & access_read) && (access & access_write))
00220 flags |= O_RDWR;
00221 else if (access & access_read)
00222 flags |= O_RDONLY;
00223 else if (access & access_write)
00224 flags |= O_WRONLY;
00225
00226 if (create_mode == create_always)
00227 flags |= O_CREAT | O_TRUNC;
00228 else if (create_mode == create_new)
00229 flags |= O_CREAT | O_EXCL;
00230
00231 CL_StringA filename_a = CL_StringHelp::text_to_local8(filename);
00232 handle = ::open(filename_a.c_str(), flags, mode);
00233 if (handle == -1)
00234 return false;
00235
00236 return true;
00237 #endif
00238 }
00239
00240 bool CL_File::create(
00241 const CL_String &filename,
00242 CreateMode mode,
00243 const CL_SecurityDescriptor &permissions,
00244 unsigned int access,
00245 unsigned int share)
00246 {
00247 return create(filename, mode, access, share);
00248 }
00249
00250 bool CL_File::open(const CL_String &filename, OpenMode open_mode, unsigned int access, unsigned int share)
00251 {
00252 #ifdef WIN32
00253 DWORD win32_desired_access = 0;
00254 DWORD win32_share_mode = 0;
00255 DWORD win32_create_mode = 0;
00256 LPSECURITY_ATTRIBUTES win32_security_attributes = 0;
00257
00258 switch (open_mode)
00259 {
00260 case open_always: win32_create_mode = OPEN_ALWAYS; break;
00261 case open_existing: win32_create_mode = OPEN_EXISTING; break;
00262 case open_existing_truncate: win32_create_mode = TRUNCATE_EXISTING; break;
00263 }
00264
00265 if (access & access_read)
00266 win32_desired_access |= GENERIC_READ;
00267 if (access & access_write)
00268 win32_desired_access |= GENERIC_WRITE;
00269
00270 if (share & share_read)
00271 win32_share_mode |= FILE_SHARE_READ;
00272 if (share & share_write)
00273 win32_share_mode |= FILE_SHARE_WRITE;
00274 if (share & share_delete)
00275 win32_share_mode |= FILE_SHARE_DELETE;
00276
00277 handle = CreateFile(
00278 filename.c_str(),
00279 win32_desired_access,
00280 win32_share_mode,
00281 win32_security_attributes,
00282 win32_create_mode,
00283 FILE_ATTRIBUTE_NORMAL,
00284 0);
00285
00286 return (handle != invalid_handle);
00287 #else
00288 int flags = 0;
00289 mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH;
00290
00291 if ((access & access_read) && (access & access_write))
00292 flags |= O_RDWR;
00293 else if (access & access_read)
00294 flags |= O_RDONLY;
00295 else if (access & access_write)
00296 flags |= O_WRONLY;
00297
00298 if (open_mode == open_always)
00299 flags |= O_CREAT;
00300 else if (open_mode == open_existing)
00301 flags |= 0;
00302 else if (open_mode == open_existing_truncate)
00303 flags |= O_TRUNC;
00304
00305 CL_StringA filename_a = CL_StringHelp::text_to_local8(filename);
00306 handle = ::open(filename_a.c_str(), flags, mode);
00307 if (handle == -1)
00308 return false;
00309
00310 return true;
00311 #endif
00312 }
00313
00314 bool CL_File::open(
00315 const CL_String &filename,
00316 OpenMode mode,
00317 const CL_SecurityDescriptor &permissions,
00318 unsigned int access,
00319 unsigned int share)
00320 {
00321 return open(filename, mode, access, share);
00322 }
00323
00324 void CL_File::close()
00325 {
00326 #ifdef WIN32
00327 if (handle != invalid_handle)
00328 CloseHandle(handle);
00329 #else
00330 if (handle != invalid_handle)
00331 ::close(handle);
00332 #endif
00333 handle = invalid_handle;
00334 }
00335
00336 bool CL_File::set_permissions(const CL_SecurityDescriptor &permissions)
00337 {
00338 return false;
00339 }
00340
00341 int CL_File::read(void *buffer, int size, bool read_all)
00342 {
00343 if (peeked_data.get_size() > 0)
00344 {
00345 #define cl_min(a,b) ((a)<(b)?(a):(b))
00346 int peek_amount = cl_min(size, peeked_data.get_size());
00347 memcpy(buffer, peeked_data.get_data(), peek_amount);
00348 memmove(peeked_data.get_data(), peeked_data.get_data()+peek_amount, peeked_data.get_size()-peek_amount);
00349 peeked_data.set_size(peeked_data.get_size()-peek_amount);
00350 if (peek_amount <= size)
00351 return peek_amount + read((char*) buffer+peek_amount, size-peek_amount);
00352 }
00353
00354 return lowlevel_read(buffer, size, read_all);
00355 }
00356
00357 int CL_File::write(const void *buffer, int size, bool write_all)
00358 {
00359 if (handle == invalid_handle)
00360 throw CL_Exception(TEXT("Unable to write to file, no file open"));
00361
00362 #ifdef WIN32
00363 DWORD written = 0;
00364 BOOL result = WriteFile(handle, buffer, size, &written, 0);
00365 if (result == TRUE)
00366 return written;
00367 else
00368 return -1;
00369 #else
00370 int result = ::write(handle, buffer, size);
00371 return result;
00372 #endif
00373 }
00374
00375 int CL_File::send(const void *data, int len, bool send_all)
00376 {
00377 return write(data, len, send_all);
00378 }
00379
00380 int CL_File::receive(void *data, int len, bool receive_all)
00381 {
00382 return read(data, len, receive_all);
00383 }
00384
00385 int CL_File::peek(void *data, int len)
00386 {
00387 if (peeked_data.get_size() >= len)
00388 {
00389 memcpy(data, peeked_data.get_data(), len);
00390 return len;
00391 }
00392 else
00393 {
00394 int old_size = peeked_data.get_size();
00395 try
00396 {
00397 peeked_data.set_size(len);
00398 int bytes_read = lowlevel_read(peeked_data.get_data()+old_size, len-old_size, false);
00399 peeked_data.set_size(old_size+bytes_read);
00400 memcpy(data, peeked_data.get_data(), peeked_data.get_size());
00401 return peeked_data.get_size();
00402 }
00403 catch (CL_Exception e)
00404 {
00405 peeked_data.set_size(old_size);
00406 throw e;
00407 }
00408 }
00409 }
00410
00411 bool CL_File::seek(int position, SeekMode seek_mode)
00412 {
00413 if (handle == invalid_handle)
00414 throw CL_Exception(TEXT("Unable to get file position pointer, no file open"));
00415
00416 #ifdef WIN32
00417 DWORD moveMethod = FILE_BEGIN;
00418 switch (seek_mode)
00419 {
00420 case seek_set: moveMethod = FILE_BEGIN; break;
00421 case seek_cur: moveMethod = FILE_CURRENT; break;
00422 case seek_end: moveMethod = FILE_END; break;
00423 }
00424
00425 DWORD new_pos = SetFilePointer(handle, position, 0, moveMethod);
00426 return (new_pos != INVALID_FILE_SIZE);
00427 #else
00428 int mode = SEEK_SET;
00429 if (seek_mode == seek_set)
00430 mode = SEEK_SET;
00431 else if (seek_mode == seek_cur)
00432 mode = SEEK_CUR;
00433 else if (seek_mode == seek_end)
00434 mode = SEEK_END;
00435
00436 off_t new_pos = lseek(handle, position, mode);
00437 if (new_pos == (off_t) -1)
00438 return false;
00439 else
00440 return true;
00441 #endif
00442 }
00443
00445
00446
00447 int CL_File::lowlevel_read(void *buffer, int size, bool read_all)
00448 {
00449 if (handle == invalid_handle)
00450 throw CL_Exception(TEXT("Unable to read from file, no file open"));
00451
00452 #ifdef WIN32
00453 DWORD bytes_read = 0;
00454 BOOL result = ReadFile(handle, buffer, size, &bytes_read, 0);
00455 if (result == TRUE)
00456 return bytes_read;
00457 else
00458 return -1;
00459 #else
00460 int result = ::read(handle, buffer, size);
00461 return result;
00462 #endif
00463 }