1<section> <date> 2005 </date>
2<H2> zzip/mmapped </H2> zip access for mmapped views
3
4<BLOCKQUOTE>
5  These routines are fully independent from the traditional zzip
6  implementation. They assume a readonly mmapped sharedmem block
7  representing a complete zip file. The functions show how to
8  parse the structure, find files and return a decoded bytestream.
9</BLOCKQUOTE>
10
11<section>
12<H3> zzip disk handle </H3>
13
14<P>
15  Other than with the <a href="fseeko.html">fseeko</a> alternative
16  interface there is no need to have an actual disk handle to the
17  zip archive. Instead you can use a bytewise copy of a file or
18  even use a mmapped view of a file. This is generally the fastest
19  way to get to the data contained in a zipped file. All it requires
20  is enough of virtual memory space but a desktop computer with a
21  a modern operating system will easily take care of that.
22</P>
23
24<P>
25  The zzipmmapped library provides a number of calls to create a
26  disk handle representing a zip archive in virtual memory. Per
27  default we use the sys/mmap.h (or MappedView) functionality
28  of the operating system. The <code>zzip_disk_open</code> will
29  open a system file descriptor and try to <code>zzip_disk_mmap</code>
30  the complete zip content. When finished with the zip archive
31  call <code>zzip_disk_close</code> to release the mapped view
32  and all management data.
33</P>
34
35<PRE>
36  ZZIP_DISK*  zzip_disk_open(char* filename);
37  int         zzip_disk_close(ZZIP_DISK* disk);
38
39  ZZIP_DISK*  zzip_disk_new(void);
40  ZZIP_DISK*  zzip_disk_mmap(int fd);
41  int         zzip_disk_munmap(ZZIP_DISK* disk);
42  int         zzip_disk_init(ZZIP_DISK* disk,
43                            char* buffer, zzip_size_t buflen);
44</PRE>
45
46</section><section>
47<H3> reading the central directory </H3>
48
49<P>
50  To get access to a zipped file, you need a pointer to an entry in the
51  mmapped zip disk known  under the type <code>ZZIP_DISK_ENTRY</code>.
52  This is again modelled after the <code>DIR_ENTRY</code> type in being
53  a representation of a file name inside the zip central directory. To
54  get an initial zzip disk entry pointer, use <code>zzip_disk_findfirst</code>,
55  to move the pointer to the next entry use <code>zzip_disk_findnext</code>.
56</P>
57<PRE>
58   extern ZZIP_ENTRY* zzip_disk_findfirst(FILE* disk);
59   extern ZZIP_ENTRY* zzip_disk_findnext(ZZIP_ENTRY*  entry);
60</PRE>
61<P>
62  These two calls will allow to walk all zip archive members in the
63  order listed in the zip central directory. To actually implement a
64  directory lister ("zzipdir"), you need to get the name string of the
65  zzip entry. This is not just a pointer: the zzip disk entry is not
66  null terminated actually. Therefore we have a helper function that
67  will <code>strdup</code> the entry name as a normal C string:
68</P>
69<PRE>
70  #include &lt;zzip/mmapped.h&gt;
71  void _zzip_dir(char* filename)
72  {
73      ZZIP_DISK* disk = zzip_disk_open (filename);
74      if (! disk) return disk;
75      for (ZZIP_DISK_ENTRY* entry = zzip_disk_findfirst (disk);
76           entry ; entry = zzip_disk_findnext (entry)) {
77          char* name = zzip_disk_entry_strdup_name (entry);
78          puts (name); free (name);
79      }
80  }
81</PRE>
82
83</section><section>
84<H3> find a zipped file </H3>
85
86<P>
87  The central directory walk can be used to find any file in the
88  zip archive. The <code>zzipfseeko</code> library however provides
89  two convenience functions that allow to jump directly to the
90  zip disk entry of a given name or pattern. You are free to use
91  the returned <code>ZZIP_DISK_ENTRY</code> pointer for later calls
92  that type. There is no need to free this pointer as it is really
93  a pointer into the mmapped area of the <code>ZZIP_DISK</code>.
94  But do not forget to free that one via <code>zzip_disk_close</code>.
95</P>
96<PRE>
97  ZZIP_DISK_ENTRY* zzip_disk_findfile(ZZIP_DISK* disk, char* filename,
98                                      ZZIP_DISK_ENTRY* after,
99                                      zzip_strcmp_fn_t compare);
100
101  ZZIP_DISK_ENTRY* zzip_disk_findmatch(ZZIP_DISK* disk, char* filespec,
102                                       ZZIP_ENTRY* after,
103                                       zzip_fnmatch_fn_t compare, int flags);
104</PRE>
105<P>
106  In general only the first two arguments are non-null pointing to the
107  zip disk handle and the file name to look for. The "after" argument
108  is an old value and allows you to walk the zip directory similar to
109  <code>zzip_disk_entry_findnext</code> but actually leaping forward. The
110  compare function can be used for alternate match behavior: the default
111  of <code>strcmp</code> might be changed to <code>strncmp</code> for
112  a caseless match. The "flags" of the second call are forwarded to the
113  posix <code>fnmatch</code> which we use as the default function.
114</P>
115<P>
116  If you do know a specific zzipped filename then you can just use
117  <code>zzip_disk_entry_findfile</code> and supply the return value to
118  <code>zzip_disk_entry_fopen</code>. There is a convenience function
119  <code>zzip_disk_fopen</code> that will do just that and therefore
120  only requires a disk handle and a filename to find-n-open.
121</P>
122<PRE>
123  #include &lt;zzip/mmapped.h&gt;
124
125  int _zzip_read(ZZIP_DISK* disk, char* filename, void* buffer, int bytes)
126  {
127      ZZIP_DISK_FILE* file = zzip_disk_fopen (disk, filename);
128      if (! file) return -1;
129      int bytes = zzip_disk_fread (buffer, 1, bytes, file);
130      zzip_disk_fclose (file);
131      return bytes;
132  }
133</PRE>
134
135</section><section>
136<H3> reading bytes </H3>
137
138<P>
139  The example has shown already how to read some bytes off the head of
140  a zipped file. In general the zzipmmapped api is used to replace a few
141  system file routines that access a file. For that purpose we provide three
142  functions that look very similar to the stdio functions of
143  <code>fopen()</code>, <code>fread()</code> and <code>fclose()</code>.
144  These work on an active file descriptor of type <code>ZZIP_DISK_FILE</code>.
145</P>
146
147<PRE>
148   ZZIP_DISK_FILE* zzip_disk_entry_fopen  (ZZIP_DISK* disk,
149                                           ZZIP_DISK_ENTRY* entry);
150   ZZIP_DISK_FILE* zzip_disk_fopen  (ZZIP_DISK* disk, char* filename);
151   zzip_size_t     zzip_disk_fread  (void* ptr,
152                                     zzip_size_t sized, zzip_size_t nmemb,
153                                     ZZIP_DISK_FILE* file);
154   int             zzip_disk_fclose (ZZIP_DISK_FILE* file);
155   int             zzip_disk_feof   (ZZIP_DISK_FILE* file);
156</PRE>
157
158<P>
159  In all of the examples you need to remember that you provide a single
160  <code>ZZIP_DISK</code> descriptor for a memory block which is in reality
161  a virtual filesystem on its own. Per default filenames are matched case
162  sensitive also on win32 systems. The findnext function will walk all
163  files on the zip virtual filesystem table and return a name entry
164  with the full pathname, i.e. including any directory names to the
165  root of the zip disk <code>FILE</code>.
166</P>
167
168</section><section>
169<H3> ZZIP_DISK_ENTRY inspection </H3>
170
171<P>
172  The <code>ZZIP_DISK_FILE</code> is a special file descriptor handle
173  of the <code>zzipmmapped</code> library - but the
174  <code>ZZIP_DISK_ENTRY</code> is not so special. It is actually a pointer
175  directly into the zip central directory managed by <code>ZZIP_DISK</code>.
176  While <code>zzip/mmapped.h</code> will not reveal the structure on its own,
177  you can include <code>zzip/format.h</code> to get access to the actual
178  structure content of a <code>ZZIP_DISK_ENTRY</code> by its definition
179<br><b><code>&nbsp;&nbsp;&nbsp;&nbsp;struct zzip_disk_entry</code></b>.
180</P>
181
182<P>
183  In reality however it is not a good idea to actually read the bytes
184  in the <code>zzip_disk_entry</code> structure unless you seriously know
185  the internals of a zip archive entry. That includes any byteswapping
186  needed on bigendian platforms. Instead you want to take advantage of
187  helper macros defined in <code>zzip/fetch.h</code>. These will take
188  care to convert any struct data member to the host native format.
189</P>
190<PRE>
191extern uint16_t    zzip_disk_entry_get_flags( zzip_disk_entry* entry);
192extern uint16_t    zzip_disk_entry_get_compr( zzip_disk_entry* entry);
193extern uint32_t    zzip_disk_entry_get_crc32( zzip_disk_entry* entry);
194
195extern zzip_size_t zzip_disk_entry_csize( zzip_disk_entry* entry);
196extern zzip_size_t zzip_disk_entry_usize( zzip_disk_entry* entry);
197extern zzip_size_t zzip_disk_entry_namlen( zzip_disk_entry* entry);
198extern zzip_size_t zzip_disk_entry_extras( zzip_disk_entry* entry);
199extern zzip_size_t zzip_disk_entry_comment( zzip_disk_entry* entry);
200extern int         zzip_disk_entry_diskstart( zzip_disk_entry* entry);
201extern int         zzip_disk_entry_filetype( zzip_disk_entry* entry);
202extern int         zzip_disk_entry_filemode( zzip_disk_entry* entry);
203
204extern zzip_off_t  zzip_disk_entry_fileoffset( zzip_disk_entry* entry);
205extern zzip_size_t zzip_disk_entry_sizeof_tail( zzip_disk_entry* entry);
206extern zzip_size_t zzip_disk_entry_sizeto_end( zzip_disk_entry* entry);
207extern char*       zzip_disk_entry_skipto_end( zzip_disk_entry* entry);
208</PRE>
209
210<P>
211  Additionally the <code>zzipmmapped</code> library has two additional
212  functions that can convert a mmapped disk entry to (a) the local
213  file header of a compressed file and (b) the start of the data area
214  of the compressed file. These are used internally upon opening of
215  a disk entry but they may be useful too for direct inspection of the
216  zip data area in special applications.
217</P>
218<PRE>
219  char*  zzip_disk_entry_to_data(ZZIP_DISK* disk,
220                                 struct zzip_disk_entry* entry);
221  struct zzip_file_header*
222         zzip_disk_entry_to_file_header(ZZIP_DISK* disk,
223                                 struct zzip_disk_entry* entry);
224</PRE>
225
226</section></section>
227