X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fluci.git;a=blobdiff_plain;f=contrib%2Flar%2Flar.c;h=2a0fa7da68fd39dc965960d8586cd01853b74c7b;hp=255bc01503e8f8e768ff1a098b199173b750db85;hb=43c395abe02248e8ca56e8d8697e76ade1bafbaf;hpb=36a9415469571fa972b6ff9004401aee393d28ad diff --git a/contrib/lar/lar.c b/contrib/lar/lar.c index 255bc0150..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 + * + * 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,12 +45,83 @@ 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; uint32_t idx_offset; uint32_t idx_length; - lar_index *idx_map, *idx_ptr; + lar_index *idx_map; + lar_index *idx_ptr; if( lseek(ar->fd, -(sizeof(idx_offset)), SEEK_END) == -1 ) LAR_DIE("Unable to seek to end of archive"); @@ -45,18 +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; } @@ -64,57 +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 -) { - if( idx_ptr->nlength >= LAR_FNAME_BUFFER ) - LAR_DIE("Filename exceeds maximum allowed length"); +lar_member * lar_mmap_member( lar_archive *ar, lar_index *idx_ptr ) +{ + 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 memberfile[LAR_FNAME_BUFFER]; - char *memberdata; - size_t pgsz = getpagesize(); + 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) ) - { - memberdata = mmap( - 0, idx_ptr->flength + ( idx_ptr->foffset % pgsz ), - PROT_READ, MAP_PRIVATE, ar->fd, - idx_ptr->foffset - ( idx_ptr->foffset % pgsz ) - ); - - 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[idx_ptr->foffset % pgsz]; - - member->mmap = memberdata; - member->mlen = idx_ptr->flength + ( idx_ptr->foffset % pgsz ); - - 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; } @@ -135,7 +213,7 @@ lar_archive * lar_open( const char *filename ) int fd; struct stat as; lar_archive *ar; - + if( stat(filename, &as) == -1 ) return NULL; @@ -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,11 +246,83 @@ 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, 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); + + if( path ) + { + for( pln = 0; path[pln] != '\0'; pln++ ) + if( pln >= (sizeof(buffer) - 5) ) + LAR_DIE("Library path exceeds maximum allowed length"); + + 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] == sep ) seg++; + } + + while( seg > 0 ) + { + for( i = 0, j = 1; (i < len) && (j <= seg); i++ ) + { + if( package[i] == sep ) { + if( j < seg ) j++; else break; + } + + buffer[pln+i] = ( package[i] == sep ) ? LAR_DIRSEP : package[i]; + } + + strcpy(&buffer[pln+i], ".lar"); + + if( (stat(buffer, &s) > -1) && (s.st_mode & S_IFREG) ) + return lar_open(buffer); + + seg--; + } + + return NULL; +} + +lar_member * lar_find_member( lar_archive *ar, const char *package ) +{ + int len; + LAR_FNAME(buffer); + + for( len = 0; package[len] != '\0'; len++ ) + { + if( len >= (sizeof(buffer) - 5) ) + LAR_DIE("Package name exceeds maximum allowed length"); + + buffer[len] = ( package[len] == '.' ) ? '/' : package[len]; + } + + strcpy(&buffer[len], ".lua"); + + return lar_open_member(ar, buffer); +}