applications/luci-upnp: add a note that up and download speeds are informational...
[project/luci.git] / contrib / lar / lar.c
index 6bac9d6..2a0fa7d 100644 (file)
@@ -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,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;
 }
@@ -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,20 +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 )
 {
-       int seg = 1;
-       int len = 0;
-       int pln = 0;
-       int i, j;
+       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);
 
@@ -192,27 +276,29 @@ 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];
                }
 
-               buffer[pln+i+0] = '.'; buffer[pln+i+1] = 'l'; buffer[pln+i+2] = 'a';
-               buffer[pln+i+3] = 'r'; buffer[pln+i+4] = '\0';
+               strcpy(&buffer[pln+i], ".lar");
 
                if( (stat(buffer, &s) > -1) && (s.st_mode & S_IFREG) )
                        return lar_open(buffer);
@@ -236,8 +322,7 @@ lar_member * lar_find_member( lar_archive *ar, const char *package )
                buffer[len] = ( package[len] == '.' ) ? '/' : package[len];
        }
 
-       buffer[len+0] = '.'; buffer[len+1] = 'l'; buffer[len+2] = 'u';
-       buffer[len+3] = 'a'; buffer[len+4] = '\0';
+       strcpy(&buffer[len], ".lua");
 
        return lar_open_member(ar, buffer);
 }