diff options
Diffstat (limited to 'contrib/lar/lar.c')
-rw-r--r-- | contrib/lar/lar.c | 186 |
1 files changed, 136 insertions, 50 deletions
diff --git a/contrib/lar/lar.c b/contrib/lar/lar.c index f968634af..2a0fa7da6 100644 --- a/contrib/lar/lar.c +++ b/contrib/lar/lar.c @@ -1,6 +1,25 @@ +/* + * lar - Lua Archive Library + * + * Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + #include "lar.h" -int lar_read32( int fd, uint32_t *val ) +static int lar_read32( int fd, uint32_t *val ) { uint8_t buffer[5]; @@ -13,7 +32,7 @@ int lar_read32( int fd, uint32_t *val ) return 0; } -int lar_read16( int fd, uint16_t *val ) +static int lar_read16( int fd, uint16_t *val ) { uint8_t buffer[3]; @@ -26,6 +45,76 @@ int lar_read16( int fd, uint16_t *val ) return 0; } +static void lar_md5( char *md5, const char *data, int len ) +{ + md5_state_t state; + + md5_init(&state); + md5_append(&state, (const md5_byte_t *)data, len); + md5_finish(&state, (md5_byte_t *)md5); +} + +static int lar_read_filenames( lar_archive *ar ) +{ + int i; + int j; + char *filelist; + size_t pgof; + size_t pgsz = getpagesize(); + lar_index *idx_ptr; + lar_index *idx_filelist = ar->index; + + while(idx_filelist) + { + if( idx_filelist->type == LAR_TYPE_FILELIST ) + break; + + idx_filelist = idx_filelist->next; + } + + if( idx_filelist != NULL ) + { + pgof = ( idx_filelist->offset % pgsz ); + + filelist = mmap( + 0, idx_filelist->length + pgof, PROT_READ, MAP_PRIVATE, + ar->fd, idx_filelist->offset - pgof + ); + + if( filelist == MAP_FAILED ) + LAR_DIE("Failed to mmap() file list"); + + + idx_ptr = ar->index; + i = pgof; + + while(idx_ptr) + { + if( idx_ptr->type == LAR_TYPE_REGULAR ) + { + j = strlen(&filelist[i]) + 1; + + if( (j >= LAR_FNAME_BUFFER) || + ((i+j) > (idx_filelist->length+pgof)) ) + LAR_DIE("Filename exceeds maximum allowed length"); + + idx_ptr->filename = (char *)malloc(j); + memcpy(idx_ptr->filename, &filelist[i], j); + + i += j; + } + + idx_ptr = idx_ptr->next; + } + + munmap(filelist, idx_filelist->length + pgof); + + return 1; + } + + return 0; +} + lar_index * lar_get_index( lar_archive *ar ) { uint32_t i; @@ -46,16 +135,19 @@ lar_index * lar_get_index( lar_archive *ar ) idx_map = NULL; - for( i = 0; i < idx_length; i += (sizeof(lar_index) - sizeof(char *)) ) { + for( i = 0; i < idx_length; i += (sizeof(lar_index) - 2 * sizeof(char *)) ) + { idx_ptr = (lar_index *)malloc(sizeof(lar_index)); + idx_ptr->filename = NULL; - lar_read32(ar->fd, &idx_ptr->noffset); - lar_read32(ar->fd, &idx_ptr->nlength); - lar_read32(ar->fd, &idx_ptr->foffset); - lar_read32(ar->fd, &idx_ptr->flength); + lar_read32(ar->fd, &idx_ptr->offset); + lar_read32(ar->fd, &idx_ptr->length); lar_read16(ar->fd, &idx_ptr->type); lar_read16(ar->fd, &idx_ptr->flags); + if(read(ar->fd,&idx_ptr->id,sizeof(idx_ptr->id)) < sizeof(idx_ptr->id)) + LAR_DIE("Unexpected EOF while reading member id"); + idx_ptr->next = idx_map; idx_map = idx_ptr; } @@ -63,58 +155,43 @@ lar_index * lar_get_index( lar_archive *ar ) return idx_map; } -uint32_t lar_get_filename( lar_archive *ar, lar_index *idx_ptr, char *filename ) +lar_member * lar_mmap_member( lar_archive *ar, lar_index *idx_ptr ) { - if( idx_ptr->nlength >= LAR_FNAME_BUFFER ) - LAR_DIE("Filename exceeds maximum allowed length"); + lar_member *member; + size_t pgsz = getpagesize(); + size_t pgof = ( idx_ptr->offset % pgsz ); + + char *memberdata = mmap( + 0, idx_ptr->length + pgof, PROT_READ, MAP_PRIVATE, + ar->fd, idx_ptr->offset - pgof + ); - if( lseek(ar->fd, idx_ptr->noffset, SEEK_SET) == -1 ) - LAR_DIE("Unexpected EOF while seeking filename"); + if( memberdata == MAP_FAILED ) + LAR_DIE("Failed to mmap() member data"); - if( read(ar->fd, filename, idx_ptr->nlength) < idx_ptr->nlength ) - LAR_DIE("Unexpected EOF while reading filename"); + member = (lar_member *)malloc(sizeof(lar_member)); + member->type = idx_ptr->type; + member->flags = idx_ptr->flags; + member->length = idx_ptr->length; + member->data = &memberdata[pgof]; - filename[idx_ptr->nlength] = '\0'; + member->mmap = memberdata; + member->mlen = idx_ptr->length + pgof; - return idx_ptr->nlength; + return member; } lar_member * lar_open_member( lar_archive *ar, const char *name ) { lar_index *idx_ptr = ar->index; - lar_member *member; - char *memberdata; - size_t pgof; - size_t pgsz = getpagesize(); - LAR_FNAME(memberfile); + char mbid[sizeof(idx_ptr->id)]; + + lar_md5(mbid, name, strlen(name)); while(idx_ptr) { - lar_get_filename(ar, idx_ptr, memberfile); - - if( !strncmp(memberfile, name, idx_ptr->nlength) ) - { - pgof = ( idx_ptr->foffset % pgsz ); - - memberdata = mmap( - 0, idx_ptr->flength + pgof, PROT_READ, MAP_PRIVATE, - ar->fd, idx_ptr->foffset - pgof - ); - - if( memberdata == MAP_FAILED ) - LAR_DIE("Failed to mmap() member data"); - - member = (lar_member *)malloc(sizeof(lar_member)); - member->type = idx_ptr->type; - member->flags = idx_ptr->flags; - member->length = idx_ptr->flength; - member->data = &memberdata[pgof]; - - member->mmap = memberdata; - member->mlen = idx_ptr->flength + pgof; - - return member; - } + if( !strncmp(mbid, idx_ptr->id, sizeof(mbid)) ) + return lar_mmap_member(ar, idx_ptr); idx_ptr = idx_ptr->next; } @@ -126,6 +203,7 @@ int lar_close_member( lar_member *member ) { int stat = munmap(member->mmap, member->mlen); free(member); + member = NULL; return stat; } @@ -150,6 +228,8 @@ lar_archive * lar_open( const char *filename ) ar->index = lar_get_index(ar); strncpy(ar->filename, filename, sizeof(ar->filename)); + ar->has_filenames = lar_read_filenames(ar); + return ar; } @@ -166,21 +246,24 @@ int lar_close( lar_archive *ar ) idx_head = ar->index; do { idx_next = idx_head->next; + free(idx_head->filename); free(idx_head); } while( (idx_head = idx_next) != NULL ); free(ar); + ar = NULL; return 0; } -lar_archive * lar_find_archive( const char *package, const char *path ) +lar_archive * lar_find_archive( const char *package, const char *path, int pkg ) { uint32_t i; uint32_t j; uint32_t seg = 1; uint32_t len = 0; uint32_t pln = 0; + char sep = ( pkg ? '.' : '/' ); struct stat s; LAR_FNAME(buffer); @@ -193,23 +276,26 @@ lar_archive * lar_find_archive( const char *package, const char *path ) memcpy(buffer, path, pln); } + if( buffer[pln-1] != '/' ) + buffer[pln++] = '/'; + for( len = 0; package[len] != '\0'; len++ ) { if( len >= (sizeof(buffer) - 5 - pln) ) LAR_DIE("Package name exceeds maximum allowed length"); - if( package[len] == '.' ) seg++; + if( package[len] == sep ) seg++; } while( seg > 0 ) { for( i = 0, j = 1; (i < len) && (j <= seg); i++ ) { - if( package[i] == '.' ) { + if( package[i] == sep ) { if( j < seg ) j++; else break; } - buffer[pln+i] = ( package[i] == '.' ) ? LAR_DIRSEP : package[i]; + buffer[pln+i] = ( package[i] == sep ) ? LAR_DIRSEP : package[i]; } strcpy(&buffer[pln+i], ".lar"); |