Add pointlog2svg utility for the thesis
[numtypysics.git] / ZipFile.cpp
blobe11c88ec35ce7a3d97df39010b6017aca5d3d1f5
1 /*
2 * This file is part of NumptyPhysics
3 * Copyright (C) 2008 Tim Edmonds
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 3 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
17 #include "ZipFile.h"
18 #include <string>
19 #include <cstring>
20 #include <cstdio>
21 #include <fcntl.h>
22 #include <sys/stat.h>
23 #include <sys/mman.h>
24 #include <unistd.h>
25 #include <zlib.h>
27 //zip file structs and uncompress_int below lifted from navit project (GPL).
28 struct zip_lfh {
29 int ziplocsig;
30 short zipver;
31 short zipgenfld;
32 short zipmthd;
33 short ziptime;
34 short zipdate;
35 int zipcrc;
36 unsigned int zipsize;
37 unsigned int zipuncmp;
38 unsigned short zipfnln;
39 unsigned short zipxtraln;
40 char zipname[0];
41 } __attribute__ ((packed));
43 struct zip_cd {
44 int zipcensig;
45 char zipcver;
46 char zipcos;
47 char zipcvxt;
48 char zipcexos;
49 short zipcflg;
50 short zipcmthd;
51 short ziptim;
52 short zipdat;
53 int zipccrc;
54 unsigned int zipcsiz;
55 unsigned int zipcunc;
56 unsigned short zipcfnl;
57 unsigned short zipcxtl;
58 unsigned short zipccml;
59 unsigned short zipdsk;
60 unsigned short zipint;
61 unsigned int zipext;
62 unsigned int zipofst;
63 char zipcfn[0];
64 } __attribute__ ((packed));
66 struct zip_eoc {
67 int zipesig;
68 unsigned short zipedsk;
69 unsigned short zipecen;
70 unsigned short zipenum;
71 unsigned short zipecenn;
72 unsigned int zipecsz;
73 unsigned int zipeofst;
74 short zipecoml;
75 char zipecom[0];
76 } __attribute__ ((packed));
78 int uncompress_int(unsigned char *dest, int *destLen,
79 const unsigned char *source, int sourceLen)
81 z_stream stream;
82 int err;
84 stream.next_in = (Bytef*)source;
85 stream.avail_in = (uInt)sourceLen;
86 stream.next_out = dest;
87 stream.avail_out = (uInt)*destLen;
89 stream.zalloc = (alloc_func)0;
90 stream.zfree = (free_func)0;
92 err = inflateInit2(&stream, -MAX_WBITS);
93 if (err != Z_OK) return err;
95 err = inflate(&stream, Z_FINISH);
96 if (err != Z_STREAM_END) {
97 inflateEnd(&stream);
98 if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
99 return Z_DATA_ERROR;
100 return err;
102 *destLen = stream.total_out;
104 err = inflateEnd(&stream);
105 return err;
110 ZipFile::ZipFile(const std::string& fn)
112 m_temp = NULL;
113 m_fd=open(fn.c_str(), O_RDONLY);
114 struct stat stat;
115 fstat(m_fd, &stat);
116 m_dataLen = stat.st_size;
117 // TODO - win32
118 m_data = (unsigned char*)mmap(NULL,m_dataLen,PROT_READ,MAP_PRIVATE, m_fd, 0);
119 if ( !m_data ) throw "mmap failed";
120 if ( *(int*)&m_data[0] != 0x04034b50 ) throw "bad zip magic";
121 m_eoc = (zip_eoc*)&m_data[m_dataLen-sizeof(zip_eoc)];
122 m_firstcd = (zip_cd*)&m_data[m_eoc->zipeofst];
123 if ( m_eoc && m_firstcd ) {
124 m_entries = m_eoc->zipenum;
125 } else {
126 m_entries = 0;
131 ZipFile::~ZipFile()
133 delete[] m_temp;
134 if ( m_data ) munmap( m_data, m_dataLen );
135 if ( m_fd ) close( m_fd );
139 std::string ZipFile::entryName( int n )
141 if ( n < 0 || n >= m_entries ) return std::string();
142 zip_cd* cd = m_firstcd;
143 for ( int count=0; cd < (zip_cd*)m_eoc && count < n; count++ ) {
144 cd = (zip_cd*)(((char*)cd) + sizeof(zip_cd) + cd->zipcfnl + cd->zipcxtl + cd->zipccml);
146 zip_lfh* lfh = (zip_lfh*)&m_data[cd->zipofst];
148 if ( lfh ) {
149 return std::string(lfh->zipname,lfh->zipfnln);
151 return std::string();
154 unsigned char* ZipFile::extract( int n, int *l )
156 if ( n < 0 || n >= m_entries ) return NULL;
157 zip_cd* cd = m_firstcd;
158 for ( int count=0; cd < (zip_cd*)m_eoc && count < n; count++ ) {
159 cd = (zip_cd*)(((char*)cd) + sizeof(zip_cd) + cd->zipcfnl + cd->zipcxtl + cd->zipccml);
161 zip_lfh* lfh = (zip_lfh*)&m_data[cd->zipofst];
163 if ( lfh ) {
164 *l = lfh->zipuncmp;
165 unsigned char* zdat = (unsigned char*)lfh + sizeof(*lfh) + lfh->zipfnln + lfh->zipxtraln;
166 switch (lfh->zipmthd) {
167 case 0:
168 return zdat;
169 case 8:
170 delete[] m_temp;
171 m_temp = new unsigned char[*l];
172 if ( uncompress_int(m_temp, l, zdat, lfh->zipsize) == Z_OK) {
173 return m_temp;
177 return NULL;