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 <zzip/fseeko.h> 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 <zzip/fseeko.h> 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> 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