BESUncompressBZ2.cc

Go to the documentation of this file.
00001 // BESUncompressBZ2.cc
00002 
00003 // This file is part of bes, A C++ back-end server implementation framework
00004 // for the OPeNDAP Data Access Protocol.
00005 
00006 // Copyright (c) 2004-2009 University Corporation for Atmospheric Research
00007 // Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
00008 //
00009 // This library is free software; you can redistribute it and/or
00010 // modify it under the terms of the GNU Lesser General Public
00011 // License as published by the Free Software Foundation; either
00012 // version 2.1 of the License, or (at your option) any later version.
00013 // 
00014 // This library is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017 // Lesser General Public License for more details.
00018 // 
00019 // You should have received a copy of the GNU Lesser General Public
00020 // License along with this library; if not, write to the Free Software
00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 //
00023 // You can contact University Corporation for Atmospheric Research at
00024 // 3080 Center Green Drive, Boulder, CO 80301
00025  
00026 // (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005
00027 // Please read the full copyright statement in the file COPYRIGHT_UCAR.
00028 //
00029 // Authors:
00030 //      pwest       Patrick West <pwest@ucar.edu>
00031 //      jgarcia     Jose Garcia <jgarcia@ucar.edu>
00032 
00033 
00034 #include "config.h"
00035 
00036 #ifdef HAVE_BZLIB_H
00037 #include <bzlib.h>
00038 #endif
00039 
00040 #include <cstring>
00041 #include <cerrno>
00042 #include <sstream>
00043 
00044 using std::ostringstream ;
00045 
00046 #include "BESUncompressBZ2.h"
00047 #include "BESInternalError.h"
00048 #include "BESDebug.h"
00049 
00050 #define CHUNK 4096
00051 
00052 void
00053 bz_internal_error ( int errcode )
00054 {
00055     ostringstream strm ;
00056     strm << "internal error in bz2 library occurred: " << errcode ;
00057     throw BESInternalError( strm.str(), __FILE__, __LINE__ ) ;
00058 }
00059 
00066 void
00067 BESUncompressBZ2::uncompress( const string &src_name, const string &target )
00068 {
00069 #ifndef HAVE_BZLIB_H
00070     string err = "Unable to uncompress bz2 files, feature not built. Check config.h in bes directory for HAVE_BZLIB_H flag set to 1" ;
00071     throw BESInternalError( err, __FILE__, __LINE__ ) ;
00072 #else
00073     FILE *src = fopen( src_name.c_str(), "rb" ) ;
00074     if( !src )
00075     {
00076         char *serr = strerror( errno ) ;
00077         string err = "Unable to open the compressed file "
00078                      + src_name + ": " ;
00079         if( serr )
00080         {
00081             err.append( serr ) ;
00082         }
00083         else
00084         {
00085             err.append( "unknown error occurred" ) ;
00086         }
00087         throw BESInternalError( err, __FILE__, __LINE__ ) ;
00088     }
00089 
00090     FILE *dest = fopen( target.c_str(), "wb" ) ;
00091     if( !dest )
00092     {
00093         char *serr = strerror( errno ) ;
00094         string err = "Unable to create the uncompressed file "
00095                      + target + ": " ;
00096         if( serr )
00097         {
00098             err.append( serr ) ;
00099         }
00100         else
00101         {
00102             err.append( "unknown error occurred" ) ;
00103         }
00104         fclose( src ) ;
00105         throw BESInternalError( err, __FILE__, __LINE__ ) ;
00106     }
00107 
00108     int bzerror = 0 ; // any error flags will be stored here
00109     int verbosity = 0 ; // 0 is silent up to 4 which is very verbose
00110     int small = 0 ; // if non zero then memory management is different
00111     void *unused = NULL ; // any unused bytes would be stored in here
00112     int nunused = 0 ; // the size of the unused buffer
00113     char in[CHUNK] ; // input buffer used to read uncompressed data in bzRead
00114 
00115     BZFILE *bsrc = NULL ;
00116 
00117     bsrc = BZ2_bzReadOpen( &bzerror, src, verbosity, small, NULL, 0 ) ;
00118     if( bsrc == NULL )
00119     {
00120         const char *berr = BZ2_bzerror( bsrc, &bzerror ) ;
00121         string err = "bzReadOpen failed on " + src_name + ": "  ;
00122         if( berr )
00123         {
00124             err.append( berr ) ;
00125         }
00126         else
00127         {
00128             err.append( "Unknown error" ) ;
00129         }
00130         fclose( dest ) ;
00131         remove( target.c_str() ) ;
00132         fclose( src ) ;
00133 
00134         throw BESInternalError( err, __FILE__, __LINE__ ) ;
00135     }
00136 
00137     bool done = false ;
00138     while( !done )
00139     {
00140         int bytes_read = BZ2_bzRead( &bzerror, bsrc, in, CHUNK ) ;
00141         if( bzerror != BZ_OK && bzerror != BZ_STREAM_END )
00142         {
00143             const char *berr = BZ2_bzerror( bsrc, &bzerror ) ;
00144             string err = "bzRead failed on " + src_name + ": " ;
00145             if( berr )
00146             {
00147                 err.append( berr ) ;
00148             }
00149             else
00150             {
00151                 err.append( "Unknown error" ) ;
00152             }
00153 
00154             BZ2_bzReadClose( &bzerror, bsrc ) ;
00155             fclose( dest ) ;
00156             remove( target.c_str() ) ;
00157             fclose( src ) ;
00158 
00159             throw BESInternalError( err, __FILE__, __LINE__ ) ;
00160         }
00161         //if( bytes_read == 0 || bzerror == BZ_STREAM_END )
00162         if( bzerror == BZ_STREAM_END )
00163         {
00164             done = true ;
00165         }
00166         int bytes_written = fwrite( in, 1, bytes_read, dest) ;
00167         if( bytes_written < bytes_read )
00168         {
00169             ostringstream strm ;
00170             strm << "Error writing uncompressed data "
00171                          << "to dest file " << target << ": "
00172                          << "wrote " << bytes_written << " "
00173                          << "instead of " << bytes_read ;
00174 
00175             BZ2_bzReadClose( &bzerror, bsrc ) ;
00176             fclose( dest ) ;
00177             remove( target.c_str() ) ;
00178             fclose( src ) ;
00179 
00180             throw BESInternalError( strm.str(), __FILE__, __LINE__ ) ;
00181         }
00182     }
00183 
00184     BZ2_bzReadClose( &bzerror, bsrc ) ;
00185     fclose( dest ) ;
00186     fclose( src ) ;
00187 #endif
00188 }
00189 

Generated on Thu Sep 16 15:20:31 2010 for OPeNDAP Hyrax Back End Server (BES) by  doxygen 1.4.7