1<section> <date> 2005 </date>
2<H2> zzip/fseeko </H2> zip access for stdio handle
3
4<BLOCKQUOTE>
5  These routines are fully independent from the traditional zzip
6  implementation. They assume a readonly seekable stdio handle
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> stdio disk handle </H3>
13
14<P>
15  Other than with the <a href="mmapped.html">mmapped</a> alternative
16  interface there is no need to build special handle for the zip
17  disk file. The normal stdio file handle (of type <b><code>FILE</code></b>)
18  serves as the disk access representation. You can open that stdio file
19  handle any way you want. Note however that the <code>zzipfseeko</code>
20  routines modify the access state of that file handle, especially the
21  read position.
22</P>
23
24<P>
25  To get access to a zipped file, you need a zip archive entry known
26  under the type <code>ZZIP_ENTRY</code>. This is again modelled after
27  the <code>DIR_ENTRY</code> type in being a representation of a file
28  name inside the zip central directory. To get a fresh zzip entry, use
29  <code>zzip_entry_findfirst</code>, to get the next use
30  <code>zzip_entry_findnext</code>, and do not forget to free the
31  resource with <code>zzip_entry_free</code>.
32</P>
33<PRE>
34   extern ZZIP_ENTRY* zzip_entry_findfirst(FILE* disk);
35   extern ZZIP_ENTRY* zzip_entry_findnext(ZZIP_ENTRY*  entry);
36   extern int         zzip_entry_free(ZZIP_ENTRY* entry);
37</PRE>
38<P>
39  These three calls will allow to walk all zip archive members in the
40  order listed in the zip central directory. To actually implement a
41  directory lister ("zzipdir"), you need to get the name string of the
42  zzip entry. This is not just a pointer: the zzip disk entry is not
43  null terminated actually. Therefore we have a helper function that
44  will <code>strdup</code> the entry name as a normal C string:
45</P>
46<PRE>
47  #include &lt;zzip/fseeko.h&gt;
48  void _zzip_dir(FILE* disk)
49  {
50      for (ZZIP_ENTRY* entry = zzip_findfirst (disk);
51           entry ; entry = zzip_findnext (entry)) {
52          char* name = zzip_entry_strdup_name (entry);
53          puts (name); free (name);
54      }
55  }
56</PRE>
57
58</section><section>
59<H3> find a zipped file </H3>
60
61<P>
62  The central directory walk can be used to find any file in the
63  zip archive. The <code>zzipfseeko</code> library however provides
64  two convenience functions that allow to jump directly to the
65  zip disk entry of a given name or pattern. You are free to use
66  the newly allocated <code>ZZIP_ENTRY</code> for later calls on
67  that handle type. Do not forget to <code>zzip_entry_free</code>
68  the handle unless the handle is consumed by a routine, e.g.
69  <code>zzip_entry_findnext</code> to hit the end of directory.
70</P>
71<PRE>
72  extern ZZIP_ENTRY* zzip_entry_findfile(FILE* disk, char* filename,
73                                         ZZIP_ENTRY* _zzip_restrict entry,
74                                         zzip_strcmp_fn_t compare);
75
76  extern ZZIP_ENTRY* zzip_entry_findmatch(FILE* disk, char* filespec,
77                                         ZZIP_ENTRY* _zzip_restrict entry,
78                                         zzip_fnmatch_fn_t compare, int flags);
79</PRE>
80<P>
81  In general only the first two arguments are non-null pointing to the
82  stdio disk handle and the file name to look for. The "entry" argument
83  is an old value and allows you to walk the zip directory similar to
84  <code>zzip_entry_findnext</code> but actually leaping forward. The
85  compare function can be used for alternate match behavior: the default
86  of <code>strcmp</code> might be changed to <code>strncmp</code> for
87  a caseless match. The "flags" of the second call are forwarded to the
88  posix <code>fnmatch</code> which we use as the default function.
89</P>
90<P>
91  If you do know a specific filename then you can just use
92  <code>zzip_entry_findfile</code> and supply the return value to
93  <code>zzip_entry_fopen</code> with the second argument set to "1"
94  to tell the function to actually consume whichever entry was given.
95  That allows you to skip an explicit <code>zzip_entry_free</code>
96  as it is included in a later <code>zzip_entry_fclose</code>.
97</P>
98<PRE>
99  #include &lt;zzip/fseeko.h&gt;
100<small>
101       /* zzipfseeko already exports this convenience function: */</small>
102  ZZIP_ENTRY_FILE* zzip_entry_ffile(FILE* disk, char* filename) {
103      return zzip_entry_fopen (zzip_entry_findfile (filename, 0, 0), 1);
104  }
105
106  int _zzip_read(FILE* disk, char* filename, void* buffer, int bytes)
107  {
108      ZZIP_ENTRY_FILE* file = zzip_entry_ffile (disk, filename);
109      if (! file) return -1;
110      int bytes = zzip_entry_fread (buffer, 1, bytes, file);
111      zzip_entry_fclose (file);
112      return bytes;
113  }
114</PRE>
115
116</section><section>
117<H3> reading bytes </H3>
118
119<P>
120  The example has shown already how to read some bytes off the head of
121  a zipped file. In general the zzipfseeko api is used to replace a few
122  stdio routines that access a file. For that purpose we provide three
123  functions that look very similar to the stdio functions of
124  <code>fopen()</code>, <code>fread()</code> and <code>fclose()</code>.
125  These work on an active file descriptor of type <code>ZZIP_ENTRY_FILE</code>.
126  Note that this <code>zzip_entry_fopen()</code> uses <code>ZZIP_ENTRY</code>
127  argument as returned by the findfile api. To open a new reader handle from
128  a disk archive and file name you can use the <code>zzip_entry_ffile()</code>
129  convenience call.
130</P>
131
132<PRE>
133   ZZIP_ENTRY_FILE* zzip_entry_ffile  (FILE* disk, char* filename);
134   ZZIP_ENTRY_FILE* zzip_entry_fopen  (ZZIP_ENTRY* entry, int takeover);
135   zzip_size_t      zzip_entry_fread  (void* ptr,
136                                       zzip_size_t sized, zzip_size_t nmemb,
137                                       ZZIP_ENTRY_FILE* file);
138   int              zzip_entry_fclose (ZZIP_ENTRY_FILE* file);
139   int              zzip_entry_feof   (ZZIP_ENTRY_FILE* file);
140</PRE>
141
142<P>
143  In all of the examples you need to remember that you provide a single
144  stdio <code>FILE</code> descriptor which is in reality a virtual
145  filesystem on its own. Per default filenames are matched case
146  sensitive also on win32 systems. The findnext function will walk all
147  files on the zip virtual filesystem table and return a name entry
148  with the full pathname, i.e. including any directory names to the
149  root of the zip disk <code>FILE</code>.
150</P>
151
152</section><section>
153<H3> ZZIP_ENTRY inspection </H3>
154
155<P>
156  The <code>ZZIP_ENTRY_FILE</code> is a special file descriptor handle
157  of the <code>zzipfseeko</code> library - but the <code>ZZIP_ENTRY</code>
158  is not so special. It is actually a bytewise copy of the data inside the
159  zip disk archive (plus some internal hints appended). While
160  <code>zzip/fseeko.h</code> will not reveal the structure on its own,
161  you can include <code>zzip/format.h</code> to get access to the actual
162  structure content of a <code>ZZIP_ENTRY</code> by (up)casting it to
163<br><b><code>&nbsp;&nbsp;&nbsp;&nbsp;struct zzip_disk_entry</code></b>.
164</P>
165
166<P>
167  In reality however it is not a good idea to actually read the bytes
168  in the <code>zzip_disk_entry</code> structure unless you seriously know
169  the internals of a zip archive entry. That includes any byteswapping
170  needed on bigendian platforms. Instead you want to take advantage of
171  helper macros defined in <code>zzip/fetch.h</code>. These will take
172  care to convert any struct data member to the host native format.
173</P>
174<PRE>
175extern uint16_t    zzip_disk_entry_get_flags( zzip_disk_entry* entry);
176extern uint16_t    zzip_disk_entry_get_compr( zzip_disk_entry* entry);
177extern uint32_t    zzip_disk_entry_get_crc32( zzip_disk_entry* entry);
178
179extern zzip_size_t zzip_disk_entry_csize( zzip_disk_entry* entry);
180extern zzip_size_t zzip_disk_entry_usize( zzip_disk_entry* entry);
181extern zzip_size_t zzip_disk_entry_namlen( zzip_disk_entry* entry);
182extern zzip_size_t zzip_disk_entry_extras( zzip_disk_entry* entry);
183extern zzip_size_t zzip_disk_entry_comment( zzip_disk_entry* entry);
184extern int         zzip_disk_entry_diskstart( zzip_disk_entry* entry);
185extern int         zzip_disk_entry_filetype( zzip_disk_entry* entry);
186extern int         zzip_disk_entry_filemode( zzip_disk_entry* entry);
187
188extern zzip_off_t  zzip_disk_entry_fileoffset( zzip_disk_entry* entry);
189extern zzip_size_t zzip_disk_entry_sizeof_tail( zzip_disk_entry* entry);
190extern zzip_size_t zzip_disk_entry_sizeto_end( zzip_disk_entry* entry);
191extern char*       zzip_disk_entry_skipto_end( zzip_disk_entry* entry);
192</PRE>
193</section></section>
194