Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

file.cpp

Go to the documentation of this file.
00001 /*
00002 **  ClanLib SDK
00003 **  Copyright (c) 1997-2005 The ClanLib Team
00004 **
00005 **  This software is provided 'as-is', without any express or implied
00006 **  warranty.  In no event will the authors be held liable for any damages
00007 **  arising from the use of this software.
00008 **
00009 **  Permission is granted to anyone to use this software for any purpose,
00010 **  including commercial applications, and to alter it and redistribute it
00011 **  freely, subject to the following restrictions:
00012 **
00013 **  1. The origin of this software must not be misrepresented; you must not
00014 **     claim that you wrote the original software. If you use this software
00015 **     in a product, an acknowledgment in the product documentation would be
00016 **     appreciated but is not required.
00017 **  2. Altered source versions must be plainly marked as such, and must not be
00018 **     misrepresented as being the original software.
00019 **  3. This notice may not be removed or altered from any source distribution.
00020 **
00021 **  Note: Some of the libraries ClanLib link to may have additional
00022 **  requirements or restrictions.
00023 **
00024 **  File Author(s):
00025 **
00026 **    Magnus Norddahl
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 // CL_File Construction:
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 // CL_File Attributes:
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         In what file is stat defined in!?!? Stupid piss-poor linux docs..
00131         (yes my limited grep'ing skills couldnt find it either)
00132 
00133         stat s;
00134         memset(&s, 0, sizeof(stat));
00135         int result = fstat(handle, &s);
00136         if (result == -1)
00137                 throw CL_Exception(TEXT("Unable to file size"));
00138 
00139         return (int) s.st_size;
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 // CL_File Operations:
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; // ug+rx, o+r
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; // ug+rx, o+r
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 // CL_File Implementation:
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 }

Generated on Sat Feb 19 22:51:16 2005 for npcore by  doxygen 1.4.1