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         fclose( src ) ;
00132 
00133         throw BESInternalError( err, __FILE__, __LINE__ ) ;
00134     }
00135 
00136     bool done = false ;
00137     while( !done )
00138     {
00139         int bytes_read = BZ2_bzRead( &bzerror, bsrc, in, CHUNK ) ;
00140         if( bzerror != BZ_OK && bzerror != BZ_STREAM_END )
00141         {
00142             const char *berr = BZ2_bzerror( bsrc, &bzerror ) ;
00143             string err = "bzRead failed on " + src_name + ": " ;
00144             if( berr )
00145             {
00146                 err.append( berr ) ;
00147             }
00148             else
00149             {
00150                 err.append( "Unknown error" ) ;
00151             }
00152 
00153             BZ2_bzReadClose( &bzerror, bsrc ) ;
00154             fclose( dest ) ;
00155             fclose( src ) ;
00156 
00157             throw BESInternalError( err, __FILE__, __LINE__ ) ;
00158         }
00159         //if( bytes_read == 0 || bzerror == BZ_STREAM_END )
00160         if( bzerror == BZ_STREAM_END )
00161         {
00162             done = true ;
00163         }
00164         int bytes_written = fwrite( in, 1, bytes_read, dest) ;
00165         if( bytes_written < bytes_read )
00166         {
00167             ostringstream strm ;
00168             strm << "Error writing uncompressed data "
00169                          << "to dest file " << target << ": "
00170                          << "wrote " << bytes_written << " "
00171                          << "instead of " << bytes_read ;
00172 
00173             BZ2_bzReadClose( &bzerror, bsrc ) ;
00174             fclose( dest ) ;
00175             fclose( src ) ;
00176 
00177             throw BESInternalError( strm.str(), __FILE__, __LINE__ ) ;
00178         }
00179     }
00180 
00181     BZ2_bzReadClose( &bzerror, bsrc ) ;
00182     fclose( dest ) ;
00183     fclose( src ) ;
00184 #endif
00185 }
00186 

Generated on Sat Aug 22 06:04:40 2009 for OPeNDAP Hyrax Back End Server (BES) by  doxygen 1.6.0