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 #include <string.h>
00026 
00027 #include "MemoryImpl.h"
00028 
00029 // include this file last
00030 #include "smbios/message.h"
00031 
00032 using namespace std;
00033 
00034 namespace memory
00035 {
00036     MemoryFactory::~MemoryFactory() throw()
00037     {}
00038     MemoryFactory::MemoryFactory()
00039     {}
00040 
00041     MemoryFactory *MemoryFactory::getFactory()
00042     {
00043         // reinterpret_cast<...>(0) to ensure template parameter is correct
00044         // this is a workaround for VC6 which cannot use explicit member template
00045         // function initialization.
00046         return MemoryFactoryImpl::getFactory(reinterpret_cast<MemoryFactoryImpl *>(0));
00047     }
00048 
00049     IMemory           *MemoryFactoryImpl::_mem_instance = 0;
00050 
00051     MemoryFactoryImpl::~MemoryFactoryImpl() throw()
00052     {
00053         if( _mem_instance )
00054         {
00055             delete _mem_instance;
00056         }
00057         _mem_instance = 0;
00058     }
00059 
00060     //
00061     // MemoryFactoryImpl::MemoryFactoryImpl()   // Constructor
00062     //  -- Moved to the Memory_OSNAME.cc file
00063     //     so that the default parameters can be OS-Specific
00064     //
00065 
00066 
00067     IMemory *MemoryFactoryImpl::getSingleton()
00068     {
00069         if (! _mem_instance)
00070             _mem_instance = makeNew();
00071 
00072         return _mem_instance;
00073     }
00074 
00075     IMemory *MemoryFactoryImpl::makeNew()
00076     {
00077         if (mode == UnitTestMode)
00078         {
00079             return new MemoryFile( getParameterString("memFile") );
00080         }
00081         else if (mode == AutoDetectMode)
00082         {
00083             return new MemoryOsSpecific( getParameterString("memFile") );
00084         }
00085         else
00086         {
00087             throw smbios::NotImplementedImpl( _("Unknown Memory mode requested.") );
00088         }
00089     }
00090 
00091 
00092     //
00093     // IMemory
00094     //
00095 
00096     IMemory::~IMemory ()
00097     {}
00098 
00099     IMemory::IMemory ()
00100     {}
00101 
00102     MemoryFile::MemoryFile( const string initFilename )
00103             : IMemory(), filename(initFilename), fd(0), rw(false), reopenHint(1)
00104     {
00105         // workaround MSVC++ bugs...
00106         if( filename == "" )
00107         {
00108             throw AccessErrorImpl( _("File name passed in was null or zero-length.") );
00109         }
00110 
00111         // fopen portable to Windows if "b" is added to mode.
00112         fd = fopen( filename.c_str(), "rb" ); // open for read to start
00113         if (!fd)
00114         {
00115             AccessErrorImpl accessError;
00116             accessError.setMessageString( _("Unable to open memory. File: %(file)s, OS Error: %(err)s") );
00117             accessError.setParameter( "file", filename );
00118             accessError.setParameter( "err", strerror(errno) );
00119             throw accessError;
00120         }
00121 
00122         if (reopenHint>0)
00123         {
00124             fclose(fd);
00125             fd=0;
00126         }
00127     }
00128 
00129     MemoryFile::~MemoryFile()
00130     {
00131         if (fd)
00132         {
00133             fclose(fd);
00134             fd = 0;
00135         }
00136     }
00137 
00138     u8 MemoryFile::getByte( u64 offset ) const
00139     {
00140         u8 value = 0;
00141         fillBuffer( &value, offset, 1 );
00142         return value;
00143     }
00144 
00145 
00146     void MemoryFile::fillBuffer(u8 *buffer, u64 offset, unsigned int length) const
00147     {
00148         if (!fd)
00149         {
00150             // fopen portable to Windows if "b" is added to mode.
00151             fd = fopen( filename.c_str(), "rb" ); // open for read to start
00152             if (!fd)
00153             {
00154                 AccessErrorImpl accessError;
00155                 accessError.setMessageString( _("Unable to open memory. File: %(file)s, OS Error: %(err)s") );
00156                 accessError.setParameter( "file", filename );
00157                 accessError.setParameter( "err", strerror(errno) );
00158                 throw accessError;
00159             }
00160         }
00161         // FSEEK is a macro defined in config/ for portability
00162         int ret = FSEEK(fd, offset, 0);
00163         if (ret)
00164         {
00165             OutOfBoundsImpl outOfBounds;
00166             outOfBounds.setMessageString(_("Seek error trying to seek to memory location. OS Error: %(err)s"));
00167             outOfBounds.setParameter("err", strerror(errno) );
00168             fclose(fd);
00169             fd = 0;
00170             throw outOfBounds;
00171         }
00172         size_t bytesRead = fread( buffer, 1, length, fd );
00173 
00174         if (reopenHint>0)
00175         {
00176             fclose(fd);
00177             fd=0;
00178         }
00179 
00180         // TODO: handle short reads
00181         if ((length != bytesRead))
00182         {
00183             AccessErrorImpl accessError;
00184             accessError.setMessageString(_("Read error trying to read memory. OS Error: %(err)s"));
00185             accessError.setParameter("err", strerror(errno) );
00186             if(fd) 
00187             {
00188                 fclose(fd);
00189                 fd = 0;
00190             }
00191             throw accessError;
00192         }
00193     }
00194 
00195     void MemoryFile::putByte( u64 offset, u8 byte ) const
00196     {
00197         if(!rw || !fd)
00198         {
00199             if(fd)
00200             {
00201                 fclose(fd);
00202                 fd = 0;
00203             }
00204 
00205             fd = fopen( filename.c_str(), "r+b" ); // reopen for write
00206             if(!fd)
00207             {
00208                 AccessErrorImpl accessError;
00209                 accessError.setMessageString( _("Unable to re-open memory file for writing. File: %(file)s, OS Error: %(err)s") );
00210                 accessError.setParameter( "file", filename );
00211                 accessError.setParameter( "err", strerror(errno) );
00212                 throw accessError;
00213             }
00214         }
00215         // FSEEK is a macro defined in config/ for portability
00216         int ret = FSEEK(fd, offset, 0);
00217         if( 0 != ret )
00218         {
00219             OutOfBoundsImpl outOfBounds;
00220             outOfBounds.setMessageString(_("Seek error trying to seek to memory location. OS Error: %(err)s"));
00221             outOfBounds.setParameter("err", strerror(errno) );
00222             fclose(fd);
00223             fd = 0;
00224             throw outOfBounds;
00225         }
00226         size_t bytesRead = fwrite( &byte, 1, 1, fd );
00227         if (reopenHint > 0)
00228         {
00229             fclose(fd);
00230             fd = 0;
00231         }
00232         if( 1 != bytesRead )
00233         {
00234             AccessErrorImpl accessError;
00235             accessError.setMessageString(_("Error trying to write memory. OS Error: %(err)s"));
00236             accessError.setParameter("err", strerror(errno) );
00237             if(fd)
00238             {
00239                 fclose(fd);
00240                 fd = 0;
00241             }
00242             throw accessError;
00243         }
00244     }
00245 }

Generated on Wed Apr 2 16:37:38 2008 for SMBIOS Library by  doxygen 1.5.1