diff options
author | Michael Dankov <tryagain@navit-project.org> | 2016-08-28 00:45:27 +0300 |
---|---|---|
committer | Michael Dankov <tryagain@navit-project.org> | 2016-08-28 00:45:27 +0300 |
commit | c1f629aefb3e56551db19f984342d3eae3026df9 (patch) | |
tree | eda6cad5d4080e9c9485a5c7351f9202cfa5a607 | |
parent | 4ed691696de132289e4023e2fbd7e7854d78c88b (diff) | |
download | navit-c1f629aefb3e56551db19f984342d3eae3026df9.tar.gz |
refactor:map/binfile:generalize zipfile functions
Prepare to move zipfile reading functions into a separate file.
-rw-r--r-- | navit/map/binfile/binfile.c | 131 |
1 files changed, 88 insertions, 43 deletions
diff --git a/navit/map/binfile/binfile.c b/navit/map/binfile/binfile.c index 4ca4c6bf5..07d556e93 100644 --- a/navit/map/binfile/binfile.c +++ b/navit/map/binfile/binfile.c @@ -234,8 +234,13 @@ static void eoc_to_cpu(struct zip_eoc *eoc) { static void binfile_check_version(struct map_priv *m); -static struct zip_eoc * -binfile_read_eoc(struct file *fi) +/** + * @brief Read the "end of central directory" structure, verifying its signature + * @param fi file to read from + * @return structure read, or NULL if file cannot be read or eoc signature is wrong + */ +struct zip_eoc * +zipfile_read_eoc(struct file *fi) { struct zip_eoc *eoc; eoc=(struct zip_eoc *)file_data_read(fi,fi->size-sizeof(struct zip_eoc), sizeof(struct zip_eoc)); @@ -251,8 +256,13 @@ binfile_read_eoc(struct file *fi) return eoc; } -static struct zip64_eoc * -binfile_read_eoc64(struct file *fi) +/** + * @brief Read the 64 bit "end of central directory" structure, verifying its signature + * @param fi file to read from + * @return structure read, or NULL if file cannot be read or eoc64 signature is wrong + */ +struct zip64_eoc * +zipfile_read_eoc64(struct file *fi) { struct zip64_eocl *eocl; struct zip64_eoc *eoc; @@ -269,7 +279,7 @@ binfile_read_eoc64(struct file *fi) if (eoc) { if (eoc->zip64esig != zip64_eoc_sig) { file_data_free(fi,(unsigned char *)eoc); - dbg(lvl_warning,"map file %s: eoc wrong\n", fi->name); + dbg(lvl_warning,"map file %s: eoc wrong\n", fi->name); eoc=NULL; } dbg(lvl_debug,"eoc64 ok 0x"LONGLONG_HEX_FMT " 0x"LONGLONG_HEX_FMT "\n",eoc->zip64eofst,eoc->zip64ecsz); @@ -278,30 +288,45 @@ binfile_read_eoc64(struct file *fi) return eoc; } -static int -binfile_cd_extra(struct zip_cd *cd) +/** + * @brief Get size of data needed to read after a given central struct zip_cd to fetch + * both file name and "extra field". + * @param cd zip_cd structure + * @return count of bytes in filename and extra field + */ +int +zipfile_cd_name_and_extra_len(struct zip_cd *cd) { return cd->zipcfnl+cd->zipcxtl; } -static struct zip_cd * -binfile_read_cd(struct map_priv *m, int offset, int len) +/** + * @brief Get the zip central directory header, change byte order if needed and verify signature. + * @param fi zip file to read from + * @param eoc zip end of central directory structure (pre-fetched) + * @param eoc64 zip64 end of central directory structure (pre-fetched) + * @param offset offset relative to beginnning of the central directory to read from + * @param len amount of bytes to read, -1 to read struct zip_cd and following filename and extra field + * @return central directory data read + */ +struct zip_cd * +zipfile_read_cd(struct file *fi, struct zip_eoc *eoc, struct zip64_eoc *eoc64, int offset, int len) { struct zip_cd *cd; - long long cdoffset=m->eoc64?m->eoc64->zip64eofst:m->eoc->zipeofst; + long long cdoffset=eoc64?eoc64->zip64eofst:eoc->zipeofst; if (len == -1) { - cd=(struct zip_cd *)file_data_read(m->fi,cdoffset+offset, sizeof(*cd)); + cd=(struct zip_cd *)file_data_read(fi,cdoffset+offset, sizeof(*cd)); cd_to_cpu(cd); - len=binfile_cd_extra(cd); - file_data_free(m->fi,(unsigned char *)cd); + len=zipfile_cd_name_and_extra_len(cd); + file_data_free(fi,(unsigned char *)cd); } - cd=(struct zip_cd *)file_data_read(m->fi,cdoffset+offset, sizeof(*cd)+len); + cd=(struct zip_cd *)file_data_read(fi,cdoffset+offset, sizeof(*cd)+len); if (cd) { dbg(lvl_debug,"cd at "LONGLONG_FMT" %zu bytes\n",cdoffset+offset, sizeof(*cd)+len); cd_to_cpu(cd); dbg(lvl_debug,"sig 0x%x\n", cd->zipcensig); if (cd->zipcensig != zip_cd_sig) { - file_data_free(m->fi,(unsigned char *)cd); + file_data_free(fi,(unsigned char *)cd); cd=NULL; } } @@ -315,8 +340,8 @@ binfile_read_cd(struct map_priv *m, int offset, int len) * @param cd pointer to zip central directory structure * @return pointer to ZIP64 extra field, or NULL if not available */ -static struct zip_cd_ext * -binfile_cd_ext(struct zip_cd *cd) +struct zip_cd_ext * +zipfile_cd_ext(struct zip_cd *cd) { struct zip_cd_ext *ext; if (cd->zipofst != zip_size_64bit_placeholder) @@ -330,22 +355,29 @@ binfile_cd_ext(struct zip_cd *cd) } /** + * @brief Get local file header offset for a given central directory element. + * Will use ZIP64 data if present. * @param cd pointer to zip central directory structure * @return Offset of local file header in zip file. - * Will use ZIP64 data if present. */ -static long long -binfile_cd_offset(struct zip_cd *cd) +long long +zipfile_cd_offset(struct zip_cd *cd) { - struct zip_cd_ext *ext=binfile_cd_ext(cd); + struct zip_cd_ext *ext=zipfile_cd_ext(cd); if (ext) return ext->zipofst; else return cd->zipofst; } -static struct zip_lfh * -binfile_read_lfh(struct file *fi, long long offset) +/** + * @brief Read local file header at a given offset, change byte order if needed and verify signature. + * @param fi file to read from + * @param offset offset to read at + * @return local file header structure read. + */ +struct zip_lfh * +zipfile_read_lfh(struct file *fi, long long offset) { struct zip_lfh *lfh; @@ -360,8 +392,8 @@ binfile_read_lfh(struct file *fi, long long offset) return lfh; } -static unsigned char * -binfile_read_content(struct map_priv *m, struct file *fi, long long offset, struct zip_lfh *lfh) +unsigned char * +zipfile_read_content(struct file *fi, long long offset, struct zip_lfh *lfh, char *passwd) { struct zip_enc *enc; unsigned char *ret=NULL; @@ -377,28 +409,41 @@ binfile_read_content(struct map_priv *m, struct file *fi, long long offset, stru ret=file_data_read_compressed(fi,offset, lfh->zipsize, lfh->zipuncmp); break; case 99: - if (!m->passwd) + if (!passwd) break; enc=(struct zip_enc *)file_data_read(fi, offset, sizeof(*enc)); offset+=lfh->zipxtraln; switch (enc->compress_method) { case 0: - ret=file_data_read_encrypted(fi, offset, lfh->zipsize, lfh->zipuncmp, 0, m->passwd); + ret=file_data_read_encrypted(fi, offset, lfh->zipsize, lfh->zipuncmp, 0, passwd); break; case 8: - ret=file_data_read_encrypted(fi, offset, lfh->zipsize, lfh->zipuncmp, 1, m->passwd); + ret=file_data_read_encrypted(fi, offset, lfh->zipsize, lfh->zipuncmp, 1, passwd); break; default: - dbg(lvl_error,"map file %s: unknown encrypted compression method %d\n", fi->name, enc->compress_method); + dbg(lvl_error,"zip file %s: unknown encrypted compression method %d\n", fi->name, enc->compress_method); } file_data_free(fi, (unsigned char *)enc); break; default: - dbg(lvl_error,"map file %s: unknown compression method %d\n", fi->name, lfh->zipmthd); + dbg(lvl_error,"zip file %s: unknown compression method %d\n", fi->name, lfh->zipmthd); } return ret; } +static unsigned char * +binfile_read_content(struct map_priv *m, struct file *fi, long long offset, struct zip_lfh *lfh) +{ + return zipfile_read_content(fi, offset, lfh, m->passwd); +} + + +static struct zip_cd * +binfile_read_cd(struct map_priv *m, int offset, int len) +{ + return zipfile_read_cd(m->fi, m->eoc, m->eoc64, offset, len); +} + static int binfile_search_cd(struct map_priv *m, int offset, char *name, int partial, int skip) { @@ -540,8 +585,8 @@ binfile_extract(struct map_priv *m, char *dir, char *filename, int partial) file_mkdir(fulld, 1); } if (full[len-2] != '/') { - lfh=binfile_read_lfh(m->fi, binfile_cd_offset(cd)); - start=binfile_read_content(m, m->fi, binfile_cd_offset(cd), lfh); + lfh=zipfile_read_lfh(m->fi, zipfile_cd_offset(cd)); + start=binfile_read_content(m, m->fi, zipfile_cd_offset(cd), lfh); dbg(lvl_debug,"fopen '%s'\n", full); f=fopen(full,"w"); fwrite(start, lfh->zipuncmp, 1, f); @@ -926,18 +971,18 @@ zipfile_to_tile(struct map_priv *m, struct zip_cd *cd, struct tile *t) char *zipfn; struct file *fi; dbg(lvl_debug,"enter %p %p %p\n", m, cd, t); - dbg(lvl_debug,"cd->zipofst=0x"LONGLONG_HEX_FMT "\n", binfile_cd_offset(cd)); + dbg(lvl_debug,"cd->zipofst=0x"LONGLONG_HEX_FMT "\n", zipfile_cd_offset(cd)); t->start=NULL; t->mode=1; if (m->fis) fi=m->fis[cd->zipdsk]; else fi=m->fi; - lfh=binfile_read_lfh(fi, binfile_cd_offset(cd)); - zipfn=(char *)(file_data_read(fi,binfile_cd_offset(cd)+sizeof(struct zip_lfh), lfh->zipfnln)); + lfh=zipfile_read_lfh(fi, zipfile_cd_offset(cd)); + zipfn=(char *)(file_data_read(fi,zipfile_cd_offset(cd)+sizeof(struct zip_lfh), lfh->zipfnln)); strncpy(buffer, zipfn, lfh->zipfnln); buffer[lfh->zipfnln]='\0'; - t->start=(int *)binfile_read_content(m, fi, binfile_cd_offset(cd), lfh); + t->start=(int *)binfile_read_content(m, fi, zipfile_cd_offset(cd), lfh); t->end=t->start+lfh->zipuncmp/4; t->fi=fi; file_data_free(fi, (unsigned char *)zipfn); @@ -1091,7 +1136,7 @@ download_request(struct map_download *download) url.u.str=g_strdup_printf("%smemberid=%d",download->m->url,download->zipfile); download->dl_size=-1; } else { - long long offset=binfile_cd_offset(download->cd_copy); + long long offset=zipfile_cd_offset(download->cd_copy); int size=download->cd_copy->zipcsiz+sizeof(struct zip_lfh)+download->cd_copy->zipcfnl; url.u.str=g_strdup(download->m->url); http_header.u.str=g_strdup_printf("Range: bytes="LONGLONG_FMT"-"LONGLONG_FMT,offset,offset+size-1); @@ -1170,7 +1215,7 @@ download_finish(struct map_download *download) long long lfh_offset; file_data_write(download->file, download->offset, sizeof(struct zip_eoc), (void *)download->zip_eoc); lfh=(struct zip_lfh *)(file_data_read(download->file,download->start_offset, sizeof(struct zip_lfh))); - ext=binfile_cd_ext(download->cd_copy); + ext=zipfile_cd_ext(download->cd_copy); if (ext) ext->zipofst=download->start_offset; else @@ -1178,12 +1223,12 @@ download_finish(struct map_download *download) download->cd_copy->zipcsiz=lfh->zipsize; download->cd_copy->zipcunc=lfh->zipuncmp; download->cd_copy->zipccrc=lfh->zipcrc; - lfh_offset = binfile_cd_offset(download->cd_copy)+sizeof(struct zip_lfh); + lfh_offset = zipfile_cd_offset(download->cd_copy)+sizeof(struct zip_lfh); lfh_filename=(char *)file_data_read(download->file,lfh_offset,lfh->zipfnln); memcpy(download->cd_copy+1,lfh_filename,lfh->zipfnln); file_data_remove(download->file,(void *)lfh_filename); file_data_remove(download->file,(void *)lfh); - file_data_write(download->file, download->m->eoc->zipeofst + download->zipfile*download->m->cde_size, binfile_cd_extra(download->cd_copy)+sizeof(struct zip_cd), (void *)download->cd_copy); + file_data_write(download->file, download->m->eoc->zipeofst + download->zipfile*download->m->cde_size, zipfile_cd_name_and_extra_len(download->cd_copy)+sizeof(struct zip_cd), (void *)download->cd_copy); file_data_flush(download->file, download->m->eoc->zipeofst + download->zipfile*download->m->cde_size, sizeof(struct zip_cd)); g_free(download->cd_copy); @@ -2563,8 +2608,8 @@ map_binfile_zip_setup(struct map_priv *m, char *filename, int mmap) { struct zip_cd *first_cd; int i; - if (!(m->eoc=binfile_read_eoc(m->fi))) { - dbg(lvl_error,"map file %s: unable to read eoc\n", filename); + if (!(m->eoc=zipfile_read_eoc(m->fi))) { + dbg(lvl_error,"zip file %s: unable to read eoc\n", filename); return 0; } dbg_assert(m->eoc->zipedsk == m->eoc->zipecen); @@ -2581,7 +2626,7 @@ map_binfile_zip_setup(struct map_priv *m, char *filename, int mmap) g_free(tmpfilename); } dbg(lvl_debug,"num_disk %d\n",m->eoc->zipedsk); - m->eoc64=binfile_read_eoc64(m->fi); + m->eoc64=zipfile_read_eoc64(m->fi); if (!binfile_get_index(m)) { dbg(lvl_error,"map file %s: no index found\n", filename); return 0; |