1 static char rcsid[] = "$Id: bzip2.c 219867 2019-08-09 20:06:43Z twu $";
2 #ifdef HAVE_CONFIG_H
3 #include <config.h>
4 #endif
5 
6 #include "bzip2.h"
7 
8 #include <stddef.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include "mem.h"
12 
13 
14 #ifdef HAVE_BZLIB
15 #include <bzlib.h>
16 #endif
17 
18 #define BUFFER_SIZE 131072
19 
20 #define T Bzip2_T
21 struct T {
22   FILE *fp;
23 #ifdef HAVE_BZLIB
24   BZFILE *bzfile;
25 #endif
26 
27   bool eofp;
28 
29   char *buffer;
30   int navail;
31   int bufferi;
32 };
33 
34 
35 T
Bzip2_new(char * filename)36 Bzip2_new (char *filename) {
37   T new = (T) MALLOC(sizeof(*new));
38   int error;
39   FILE *fp;
40 
41 #ifndef HAVE_BZLIB
42   fprintf(stderr,"Bzip2_new called when BZLIB is unavailable\n");
43   exit(9);
44 
45 #else
46   fp = fopen(filename,"r");
47   if (fp == NULL) {
48     fprintf(stderr,"Unable to open bzip2 file %s\n",filename);
49     exit(9);
50   } else {
51     new->fp = fp;
52   }
53 
54   new->bzfile = BZ2_bzReadOpen(&error,fp,/*small*/0,/*verbosity*/0,/*unused*/NULL,/*nunused*/0);
55   if (error != BZ_OK) {
56     fprintf(stderr,"BZ2_bzReadOpen gave error %d\n",error);
57     exit(9);
58   }
59 #endif
60 
61   new->eofp = false;
62   new->buffer = (char *) CALLOC(BUFFER_SIZE,sizeof(char));
63   new->navail = 0;
64   new->bufferi = 0;
65 
66   return new;
67 }
68 
69 void
Bzip2_free(T * old)70 Bzip2_free (T *old) {
71 #ifdef HAVE_BZLIB
72   int error;
73 
74   BZ2_bzReadClose(&error,(*old)->bzfile);
75   if (error != BZ_OK) {
76     fprintf(stderr,"BZ2_bzReadClose gave error %d\n",error);
77     exit(9);
78   }
79   fclose((*old)->fp);
80 #endif
81 
82   FREE((*old)->buffer);
83   FREE(*old);
84   return;
85 }
86 
87 
88 int
bzgetc(T this)89 bzgetc (T this) {
90 #ifdef HAVE_BZLIB
91   int error;
92 #endif
93 
94   if (this->navail > 0) {
95     this->navail -= 1;
96     return this->buffer[this->bufferi++];
97 
98   } else if (this->eofp == true) {
99     return EOF;
100 
101   } else {
102 #ifdef HAVE_BZLIB
103     this->navail = BZ2_bzRead(&error,this->bzfile,this->buffer,BUFFER_SIZE);
104     if (error == BZ_STREAM_END) {
105       this->eofp = true;
106     } else if (error != BZ_OK) {
107       fprintf(stderr,"BZ2_bzRead gave error %d\n",error);
108       exit(9);
109     }
110 #endif
111     this->bufferi = 1;
112     this->navail -= 1;
113     return this->buffer[0];
114   }
115 }
116 
117 
118 bool
bzeof(T this)119 bzeof (T this) {
120   if (this->navail > 0) {
121     return false;
122   } else {
123     return this->eofp;
124   }
125 }
126 
127 char *
bzgets(T this,char * buffer,int maxlength)128 bzgets (T this, char *buffer, int maxlength) {
129   int n = 0;
130   int c = '\0';
131 
132   if (this->navail == 0 && this->eofp == true) {
133     return (char *) NULL;
134   } else {
135     while (c != '\n' && n < maxlength - 1 && (c = bzgetc(this)) != EOF) {
136       buffer[n++] = c;
137     }
138     buffer[n] = '\0';
139     return buffer;
140   }
141 }
142 
143 
144 #if 0
145 int
146 main (int argc, char *argv[]) {
147   char *filename;
148   T bzip2;
149   char string[100];
150 
151   filename = argv[1];
152   bzip2 = Bzip2_new(filename);
153   while (bzeof(bzip2) == false) {
154     bzgets(bzip2,string,100);
155     printf("%s",string);
156   }
157   Bzip2_free(&bzip2);
158   return 0;
159 }
160 #endif
161 
162