~ubuntu-branches/ubuntu/vivid/cctools/vivid

« back to all changes in this revision

Viewing changes to parrot/src/pfs_file_gzip.cc

  • Committer: Bazaar Package Importer
  • Author(s): Michael Hanke
  • Date: 2011-05-07 09:05:00 UTC
  • Revision ID: james.westby@ubuntu.com-20110507090500-lqpmdtwndor6e7os
Tags: upstream-3.3.2
ImportĀ upstreamĀ versionĀ 3.3.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
Copyright (C) 2003-2004 Douglas Thain and the University of Wisconsin
 
3
Copyright (C) 2005- The University of Notre Dame
 
4
This software is distributed under the GNU General Public License.
 
5
See the file COPYING for details.
 
6
*/
 
7
 
 
8
#include "pfs_file.h"
 
9
#include "pfs_service.h"
 
10
#include "pfs_name.h"
 
11
#include "pfs_file_gzip.h"
 
12
 
 
13
extern "C" {
 
14
#include "debug.h"
 
15
}
 
16
 
 
17
#include <errno.h>
 
18
#include <stdio.h>
 
19
#include <sys/mman.h>
 
20
#include <string.h>
 
21
#include <stdio.h>
 
22
#include <unistd.h>
 
23
#include <fcntl.h>
 
24
#include <stdlib.h>
 
25
#include <zlib.h>
 
26
 
 
27
#define BUFFER_SIZE 65536
 
28
 
 
29
#define STATE_RESET 0
 
30
#define STATE_READY 1
 
31
#define STATE_BROKEN 2
 
32
 
 
33
#define GZIP_MAGIC1 0x1f
 
34
#define GZIP_MAGIC2 0x8b
 
35
 
 
36
#define GZIP_DEFLATE 8
 
37
 
 
38
#define GZIP_FLAG_FTEXT   1
 
39
#define GZIP_FLAG_FHCRC   2
 
40
#define GZIP_FLAG_FNAME   4
 
41
#define GZIP_FLAG_COMMENT 8
 
42
 
 
43
class pfs_file_gzip : public pfs_file
 
44
{
 
45
private:
 
46
        pfs_file *file;
 
47
        z_streamp zstream;
 
48
        unsigned char buffer[BUFFER_SIZE];
 
49
        pfs_off_t compressed_file_pointer;
 
50
        int state;
 
51
 
 
52
        unsigned char read_byte() {
 
53
                char c=0;
 
54
                file->read(&c,1,compressed_file_pointer++);
 
55
                return c;
 
56
        }
 
57
 
 
58
        int read_gzip_header() {
 
59
                int i;
 
60
                int length;
 
61
                unsigned char flags;
 
62
 
 
63
                if(read_byte()!=GZIP_MAGIC1) goto broken;
 
64
                if(read_byte()!=GZIP_MAGIC2) goto broken;
 
65
                if(read_byte()!=GZIP_DEFLATE) goto broken;
 
66
 
 
67
                flags = read_byte();
 
68
 
 
69
                for(i=0;i<6;i++) read_byte();
 
70
 
 
71
                if(flags&GZIP_FLAG_FTEXT) {
 
72
                        length = (read_byte() | (((unsigned int)read_byte())<8));
 
73
                        for(i=0;i<length;i++) read_byte();
 
74
                }
 
75
 
 
76
                if(flags&GZIP_FLAG_FNAME) {
 
77
                        while(read_byte()!=0) {}
 
78
                }
 
79
 
 
80
                if(flags&GZIP_FLAG_COMMENT) {
 
81
                        while(read_byte()!=0) {}
 
82
                }
 
83
                
 
84
                if(flags&GZIP_FLAG_FHCRC) {
 
85
                        read_byte();
 
86
                        read_byte();
 
87
                }
 
88
 
 
89
                inflateInit2(zstream,-15);
 
90
 
 
91
                state = STATE_READY;
 
92
                return 1;
 
93
 
 
94
                broken:
 
95
                state = STATE_BROKEN;
 
96
                return 0;
 
97
        }
 
98
 
 
99
public:
 
100
        
 
101
        pfs_file_gzip( pfs_file *f ) : pfs_file(f->get_name()) {
 
102
                file = f;
 
103
                zstream = (z_streamp) malloc(sizeof(*zstream));
 
104
                memset(zstream,0,sizeof(*zstream));
 
105
                state = STATE_RESET;
 
106
        }
 
107
        
 
108
        ~pfs_file_gzip() {
 
109
                delete file;
 
110
                inflateEnd(zstream);
 
111
                free(zstream);
 
112
        }
 
113
 
 
114
        int close() {
 
115
                file->close();
 
116
                return 0;
 
117
        }
 
118
 
 
119
        pfs_ssize_t read( void *data, pfs_size_t length, pfs_off_t offset )
 
120
        {
 
121
                unsigned char *cdata = (unsigned char*)data;
 
122
                pfs_ssize_t total = 0;
 
123
                pfs_ssize_t actual = 0;
 
124
                int zresult;
 
125
 
 
126
                if(state==STATE_RESET) {
 
127
                        read_gzip_header();
 
128
                }
 
129
                
 
130
                if(state==STATE_BROKEN) {
 
131
                        errno=EIO;
 
132
                        return -1;
 
133
                }
 
134
 
 
135
                while(length>0) {
 
136
                        if(zstream->avail_in==0) {
 
137
                                actual = file->read(buffer,BUFFER_SIZE,compressed_file_pointer);
 
138
                                if(actual<=0) break;
 
139
 
 
140
                                compressed_file_pointer += actual;
 
141
                                zstream->next_in = buffer;
 
142
                                zstream->avail_in = actual;
 
143
                        }
 
144
 
 
145
                        zstream->next_out = cdata;
 
146
                        zstream->avail_out = length;
 
147
 
 
148
                        zresult = inflate(zstream,Z_SYNC_FLUSH);
 
149
                        if(zresult==Z_OK || zresult==Z_STREAM_END) {
 
150
                                actual = length-zstream->avail_out;
 
151
                                if(actual>0) {
 
152
                                        cdata  += actual;
 
153
                                        total  += actual;
 
154
                                        length -= actual;
 
155
                                        continue;
 
156
                                } else {
 
157
                                        break;
 
158
                                }
 
159
                        } else {
 
160
                                debug(D_NOTICE,"decompression error %d on file %s",zresult,get_name()->logical_name);
 
161
                                errno = EIO;
 
162
                                return -1;
 
163
                                break;
 
164
                        }
 
165
                }
 
166
 
 
167
                if(total>0) {
 
168
                        return total;
 
169
                } else {
 
170
                        if(actual<0) {
 
171
                                return -1;
 
172
                        } else {
 
173
                                return 0;
 
174
                        }
 
175
                }
 
176
        }
 
177
 
 
178
        pfs_ssize_t write( const void *data, pfs_size_t length, pfs_off_t offset )
 
179
        {
 
180
                errno = EROFS;
 
181
                return -1;
 
182
        }
 
183
 
 
184
        int fstat( struct pfs_stat *buf )
 
185
        {
 
186
                return file->fstat(buf);
 
187
        }
 
188
 
 
189
        int fstatfs( struct pfs_statfs *buf )
 
190
        {
 
191
                return file->fstatfs(buf);
 
192
        }
 
193
 
 
194
        int ftruncate( pfs_size_t length )
 
195
        {
 
196
                return file->ftruncate(length);
 
197
        }
 
198
 
 
199
        int fsync()
 
200
        {
 
201
                return file->fsync();
 
202
        }
 
203
 
 
204
        int fcntl( int cmd, void *arg )
 
205
        {
 
206
                return file->fcntl(cmd,arg);
 
207
        }
 
208
 
 
209
        int ioctl( int cmd, void *arg )
 
210
        {
 
211
                return file->ioctl(cmd,arg);
 
212
        }
 
213
 
 
214
        int fchmod( mode_t mode )
 
215
        {
 
216
                return file->fchmod(mode);
 
217
        }
 
218
 
 
219
        int fchown( uid_t uid, gid_t gid )
 
220
        {
 
221
                return file->fchown(uid,gid);
 
222
        }
 
223
 
 
224
        int flock( int op )
 
225
        {
 
226
                return file->flock(op);
 
227
        }
 
228
 
 
229
        void * mmap( void *start, pfs_size_t length, int prot, int flags, off_t offset )
 
230
        {
 
231
                return file->mmap(start,length,prot,flags,offset);
 
232
        }
 
233
 
 
234
        struct dirent * fdreaddir( pfs_off_t offset, pfs_off_t *next_offset )
 
235
        {
 
236
                return file->fdreaddir(offset,next_offset);
 
237
        }
 
238
 
 
239
        pfs_name * get_name()
 
240
        {
 
241
                return file->get_name();
 
242
        }
 
243
 
 
244
        pfs_ssize_t get_size()
 
245
        {
 
246
                return file->get_size();
 
247
        }
 
248
 
 
249
        int get_real_fd()
 
250
        {
 
251
                return file->get_real_fd();
 
252
        }
 
253
 
 
254
        int get_local_name( char *n )
 
255
        {
 
256
                return file->get_local_name(n);
 
257
        }
 
258
 
 
259
        int is_seekable()
 
260
        {
 
261
                return 0;
 
262
        }
 
263
};
 
264
 
 
265
pfs_file * pfs_gzip_open( pfs_file *file, int flags, int mode )
 
266
{
 
267
        return new pfs_file_gzip(file);
 
268
}