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