OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
BESUncompressBZ2.cc
Go to the documentation of this file.
1 // BESUncompressBZ2.cc
2 
3 // This file is part of bes, A C++ back-end server implementation framework
4 // for the OPeNDAP Data Access Protocol.
5 
6 // Copyright (c) 2004-2009 University Corporation for Atmospheric Research
7 // Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 //
23 // You can contact University Corporation for Atmospheric Research at
24 // 3080 Center Green Drive, Boulder, CO 80301
25 
26 // (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005
27 // Please read the full copyright statement in the file COPYRIGHT_UCAR.
28 //
29 // Authors:
30 // pwest Patrick West <pwest@ucar.edu>
31 // jgarcia Jose Garcia <jgarcia@ucar.edu>
32 
33 
34 #include "config.h"
35 
36 #ifdef HAVE_BZLIB_H
37 #include <bzlib.h>
38 #endif
39 
40 #include <cstring>
41 #include <cerrno>
42 #include <sstream>
43 
44 using std::ostringstream ;
45 
46 #include "BESUncompressBZ2.h"
47 #include "BESInternalError.h"
48 #include "BESDebug.h"
49 
50 #define CHUNK 4096
51 
52 void
53 bz_internal_error ( int errcode )
54 {
55  ostringstream strm ;
56  strm << "internal error in bz2 library occurred: " << errcode ;
57  throw BESInternalError( strm.str(), __FILE__, __LINE__ ) ;
58 }
59 
66 void
67 BESUncompressBZ2::uncompress( const string &src_name, const string &target )
68 {
69 #ifndef HAVE_BZLIB_H
70  string err = "Unable to uncompress bz2 files, feature not built. Check config.h in bes directory for HAVE_BZLIB_H flag set to 1" ;
71  throw BESInternalError( err, __FILE__, __LINE__ ) ;
72 #else
73  FILE *src = fopen( src_name.c_str(), "rb" ) ;
74  if( !src )
75  {
76  char *serr = strerror( errno ) ;
77  string err = "Unable to open the compressed file "
78  + src_name + ": " ;
79  if( serr )
80  {
81  err.append( serr ) ;
82  }
83  else
84  {
85  err.append( "unknown error occurred" ) ;
86  }
87  throw BESInternalError( err, __FILE__, __LINE__ ) ;
88  }
89 
90  FILE *dest = fopen( target.c_str(), "wb" ) ;
91  if( !dest )
92  {
93  char *serr = strerror( errno ) ;
94  string err = "Unable to create the uncompressed file "
95  + target + ": " ;
96  if( serr )
97  {
98  err.append( serr ) ;
99  }
100  else
101  {
102  err.append( "unknown error occurred" ) ;
103  }
104  fclose( src ) ;
105  throw BESInternalError( err, __FILE__, __LINE__ ) ;
106  }
107 
108  int bzerror = 0 ; // any error flags will be stored here
109  int verbosity = 0 ; // 0 is silent up to 4 which is very verbose
110  int small = 0 ; // if non zero then memory management is different
111  void *unused = NULL ; // any unused bytes would be stored in here
112  int nunused = 0 ; // the size of the unused buffer
113  char in[CHUNK] ; // input buffer used to read uncompressed data in bzRead
114 
115  BZFILE *bsrc = NULL ;
116 
117  bsrc = BZ2_bzReadOpen( &bzerror, src, verbosity, small, NULL, 0 ) ;
118  if( bsrc == NULL )
119  {
120  const char *berr = BZ2_bzerror( bsrc, &bzerror ) ;
121  string err = "bzReadOpen failed on " + src_name + ": " ;
122  if( berr )
123  {
124  err.append( berr ) ;
125  }
126  else
127  {
128  err.append( "Unknown error" ) ;
129  }
130  fclose( dest ) ;
131  remove( target.c_str() ) ;
132  fclose( src ) ;
133 
134  throw BESInternalError( err, __FILE__, __LINE__ ) ;
135  }
136 
137  bool done = false ;
138  while( !done )
139  {
140  int bytes_read = BZ2_bzRead( &bzerror, bsrc, in, CHUNK ) ;
141  if( bzerror != BZ_OK && bzerror != BZ_STREAM_END )
142  {
143  const char *berr = BZ2_bzerror( bsrc, &bzerror ) ;
144  string err = "bzRead failed on " + src_name + ": " ;
145  if( berr )
146  {
147  err.append( berr ) ;
148  }
149  else
150  {
151  err.append( "Unknown error" ) ;
152  }
153 
154  BZ2_bzReadClose( &bzerror, bsrc ) ;
155  fclose( dest ) ;
156  remove( target.c_str() ) ;
157  fclose( src ) ;
158 
159  throw BESInternalError( err, __FILE__, __LINE__ ) ;
160  }
161  //if( bytes_read == 0 || bzerror == BZ_STREAM_END )
162  if( bzerror == BZ_STREAM_END )
163  {
164  done = true ;
165  }
166  int bytes_written = fwrite( in, 1, bytes_read, dest) ;
167  if( bytes_written < bytes_read )
168  {
169  ostringstream strm ;
170  strm << "Error writing uncompressed data "
171  << "to dest file " << target << ": "
172  << "wrote " << bytes_written << " "
173  << "instead of " << bytes_read ;
174 
175  BZ2_bzReadClose( &bzerror, bsrc ) ;
176  fclose( dest ) ;
177  remove( target.c_str() ) ;
178  fclose( src ) ;
179 
180  throw BESInternalError( strm.str(), __FILE__, __LINE__ ) ;
181  }
182  }
183 
184  BZ2_bzReadClose( &bzerror, bsrc ) ;
185  fclose( dest ) ;
186  fclose( src ) ;
187 #endif
188 }
189 
static void uncompress(const string &src, const string &target)
uncompress a file with the .bz2 file extension
exception thrown if inernal error encountered
#define CHUNK
void bz_internal_error(int errcode)