Memory.cpp

Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
00002  * vim:expandtab:autoindent:tabstop=4:shiftwidth=4:filetype=c:cindent:textwidth=0:
00003  *
00004  * Copyright (C) 2005 Dell Inc.
00005  *  by Michael Brown <Michael_E_Brown@dell.com>
00006  * Licensed under the Open Software License version 2.1
00007  *
00008  * Alternatively, you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published
00010  * by the Free Software Foundation; either version 2 of the License,
00011  * or (at your option) any later version.
00012 
00013  * This program is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00016  * See the GNU General Public License for more details.
00017  */
00018 
00019 // compat header should always be first header if including system headers
00020 #define LIBSMBIOS_SOURCE
00021 #include "smbios/compat.h"
00022 
00023 #include <errno.h>
00024 #include <stdio.h>
00025 
00026 #include "MemoryImpl.h"
00027 
00028 // include this file last
00029 #include "smbios/message.h"
00030 
00031 using namespace std;
00032 
00033 namespace memory
00034 {
00035     MemoryFactory::~MemoryFactory() throw()
00036     {}
00037     MemoryFactory::MemoryFactory()
00038     {}
00039 
00040     MemoryFactory *MemoryFactory::getFactory()
00041     {
00042         // reinterpret_cast<...>(0) to ensure template parameter is correct
00043         // this is a workaround for VC6 which cannot use explicit member template
00044         // function initialization.
00045         return MemoryFactoryImpl::getFactory(reinterpret_cast<MemoryFactoryImpl *>(0));
00046     }
00047 
00048     IMemory           *MemoryFactoryImpl::_mem_instance = 0;
00049 
00050     MemoryFactoryImpl::~MemoryFactoryImpl() throw()
00051     {
00052         if( _mem_instance )
00053         {
00054             delete _mem_instance;
00055         }
00056         _mem_instance = 0;
00057     }
00058 
00059     //
00060     // MemoryFactoryImpl::MemoryFactoryImpl()   // Constructor
00061     //  -- Moved to the Memory_OSNAME.cc file
00062     //     so that the default parameters can be OS-Specific
00063     //
00064 
00065 
00066     IMemory *MemoryFactoryImpl::getSingleton()
00067     {
00068         if (! _mem_instance)
00069             _mem_instance = makeNew();
00070 
00071         return _mem_instance;
00072     }
00073 
00074     IMemory *MemoryFactoryImpl::makeNew()
00075     {
00076         if (mode == UnitTestMode)
00077         {
00078             return new MemoryFile( getParameterString("memFile") );
00079         }
00080         else if (mode == AutoDetectMode)
00081         {
00082             return new MemoryOsSpecific( getParameterString("memFile") );
00083         }
00084         else
00085         {
00086             throw smbios::NotImplementedImpl( _("Unknown Memory mode requested.") );
00087         }
00088     }
00089 
00090 
00091     //
00092     // IMemory
00093     //
00094 
00095     IMemory::~IMemory ()
00096     {}
00097 
00098     IMemory::IMemory ()
00099     {}
00100 
00101     MemoryFile::MemoryFile( const string initFilename )
00102             : IMemory(), filename(initFilename), fd(0), rw(false), reopenHint(1)
00103     {
00104         // workaround MSVC++ bugs...
00105         if( filename == "" )
00106         {
00107             throw AccessErrorImpl( _("File name passed in was null or zero-length.") );
00108         }
00109 
00110         // fopen portable to Windows if "b" is added to mode.
00111         fd = fopen( filename.c_str(), "rb" ); // open for read to start
00112         if (!fd)
00113         {
00114             AccessErrorImpl accessError;
00115             accessError.setMessageString( _("Unable to open memory. File: %(file)s, OS Error: %(err)s") );
00116             accessError.setParameter( "file", filename );
00117             accessError.setParameter( "err", strerror(errno) );
00118             throw accessError;
00119         }
00120 
00121         if (reopenHint>0)
00122         {
00123             fclose(fd);
00124             fd=0;
00125         }
00126     }
00127 
00128     MemoryFile::~MemoryFile()
00129     {
00130         if (fd)
00131         {
00132             fclose(fd);
00133             fd = 0;
00134         }
00135     }
00136 
00137     u8 MemoryFile::getByte( u64 offset ) const
00138     {
00139         u8 value = 0;
00140         fillBuffer( &value, offset, 1 );
00141         return value;
00142     }
00143 
00144 
00145     void MemoryFile::fillBuffer(u8 *buffer, u64 offset, unsigned int length) const
00146     {
00147         if (!fd)
00148         {
00149             // fopen portable to Windows if "b" is added to mode.
00150             fd = fopen( filename.c_str(), "rb" ); // open for read to start
00151             if (!fd)
00152             {
00153                 AccessErrorImpl accessError;
00154                 accessError.setMessageString( _("Unable to open memory. File: %(file)s, OS Error: %(err)s") );
00155                 accessError.setParameter( "file", filename );
00156                 accessError.setParameter( "err", strerror(errno) );
00157                 throw accessError;
00158             }
00159         }
00160         // FSEEK is a macro defined in config/ for portability
00161         int ret = FSEEK(fd, offset, 0);
00162         if (ret)
00163         {
00164             OutOfBoundsImpl outOfBounds;
00165             outOfBounds.setMessageString(_("Seek error trying to seek to memory location. OS Error: %(err)s"));
00166             outOfBounds.setParameter("err", strerror(errno) );
00167             fclose(fd);
00168             fd = 0;
00169             throw outOfBounds;
00170         }
00171         size_t bytesRead = fread( buffer, 1, length, fd );
00172 
00173         if (reopenHint>0)
00174         {
00175             fclose(fd);
00176             fd=0;
00177         }
00178 
00179         // TODO: handle short reads
00180         if ((length != bytesRead))
00181         {
00182             AccessErrorImpl accessError;
00183             accessError.setMessageString(_("Read error trying to read memory. OS Error: %(err)s"));
00184             accessError.setParameter("err", strerror(errno) );
00185             if(fd) 
00186             {
00187                 fclose(fd);
00188                 fd = 0;
00189             }
00190             throw accessError;
00191         }
00192     }
00193 
00194     void MemoryFile::putByte( u64 offset, u8 byte ) const
00195     {
00196         if(!rw || !fd)
00197         {
00198             if(fd)
00199             {
00200                 fclose(fd);
00201                 fd = 0;
00202             }
00203 
00204             fd = fopen( filename.c_str(), "r+b" ); // reopen for write
00205             if(!fd)
00206             {
00207                 AccessErrorImpl accessError;
00208                 accessError.setMessageString( _("Unable to re-open memory file for writing. File: %(file)s, OS Error: %(err)s") );
00209                 accessError.setParameter( "file", filename );
00210                 accessError.setParameter( "err", strerror(errno) );
00211                 throw accessError;
00212             }
00213         }
00214         // FSEEK is a macro defined in config/ for portability
00215         int ret = FSEEK(fd, offset, 0);
00216         if( 0 != ret )
00217         {
00218             OutOfBoundsImpl outOfBounds;
00219             outOfBounds.setMessageString(_("Seek error trying to seek to memory location. OS Error: %(err)s"));
00220             outOfBounds.setParameter("err", strerror(errno) );
00221             fclose(fd);
00222             fd = 0;
00223             throw outOfBounds;
00224         }
00225         size_t bytesRead = fwrite( &byte, 1, 1, fd );
00226         if (reopenHint > 0)
00227         {
00228             fclose(fd);
00229             fd = 0;
00230         }
00231         if( 1 != bytesRead )
00232         {
00233             AccessErrorImpl accessError;
00234             accessError.setMessageString(_("Error trying to write memory. OS Error: %(err)s"));
00235             accessError.setParameter("err", strerror(errno) );
00236             if(fd)
00237             {
00238                 fclose(fd);
00239                 fd = 0;
00240             }
00241             throw accessError;
00242         }
00243     }
00244 }

Generated on Tue Aug 28 01:56:33 2007 for SMBIOS Library by  doxygen 1.5.1