From: Jo-Philipp Wich Date: Mon, 13 Apr 2009 15:10:01 +0000 (+0000) Subject: contrib/lar: X-Git-Tag: 0.9.0~517 X-Git-Url: https://git.archive.openwrt.org/?p=project%2Fluci.git;a=commitdiff_plain;h=eb4a870be600f3f8704737278ef75c7d050f7172 contrib/lar: - add lua binding for lar library - introduce mmap() support for lua --- diff --git a/contrib/lar/Makefile b/contrib/lar/Makefile index 64c323505..cc328de6d 100644 --- a/contrib/lar/Makefile +++ b/contrib/lar/Makefile @@ -2,7 +2,7 @@ GCC := gcc CFLAGS := -Wall LDFLAGS := -OBJ = cli.o lar.o +OBJ = cli.o lar.o md5.o BIN = lar cli: $(OBJ) diff --git a/contrib/lar/cli.c b/contrib/lar/cli.c index 098f55d9d..36216d46e 100644 --- a/contrib/lar/cli.c +++ b/contrib/lar/cli.c @@ -18,16 +18,24 @@ int do_print_member( lar_archive *ar, const char *name ) int do_print_index( lar_archive *ar ) { lar_index *index = ar->index; - LAR_FNAME(filename); - while(index) + if( ar->has_filenames ) { - lar_get_filename(ar, index, filename); - printf("%s\n", filename); - index = index->next; + while(index) + { + if( index->type == LAR_TYPE_REGULAR ) + { + printf("%s\n", index->filename); + } + + index = index->next; + } + + return 0; } - return 0; + LAR_DIE("The archive contains no file list"); + return 1; } int do_require( const char *package, const char *path ) @@ -36,7 +44,7 @@ int do_require( const char *package, const char *path ) lar_archive *ar; lar_member *mb; - if( (ar = lar_find_archive(package, path)) != NULL ) + if( (ar = lar_find_archive(package, path, 1)) != NULL ) { if( (mb = lar_find_member(ar, package)) != NULL ) { @@ -51,12 +59,33 @@ int do_require( const char *package, const char *path ) return stat; } +int do_findfile( const char *filename, const char *path ) +{ + int stat = 1; + lar_archive *ar; + lar_member *mb; + + if( (ar = lar_find_archive(filename, path, 0)) != NULL ) + { + if( (mb = lar_open_member(ar, filename)) != NULL ) + { + write(fileno(stdout), mb->data, mb->length); + lar_close_member(mb); + stat = 0; + } + + lar_close(ar); + } + + return stat; +} + int main( int argc, const char* argv[] ) { lar_archive *ar; int stat = 0; - if( argv[1] != NULL ) + if( argv[1] != NULL && argv[2] != NULL ) { switch(argv[1][0]) { @@ -80,6 +109,10 @@ int main( int argc, const char* argv[] ) case 'r': stat = do_require(argv[2], argv[3]); break; + + case 'f': + stat = do_findfile(argv[2], argv[3]); + break; } return stat; @@ -89,6 +122,7 @@ int main( int argc, const char* argv[] ) printf("Usage:\n"); printf("\tlar show []\n"); printf("\tlar require []\n"); + printf("\tlar find []\n"); return 1; } 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 + * + * 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"); diff --git a/contrib/lar/lar.h b/contrib/lar/lar.h index 04245ce63..fcbd94d10 100644 --- a/contrib/lar/lar.h +++ b/contrib/lar/lar.h @@ -1,3 +1,22 @@ +/* + * 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. + */ + + #ifndef __LAR_H #define __LAR_H @@ -13,6 +32,7 @@ #include #include +#include "md5.h" #define LAR_DIE(s) \ do { \ @@ -27,6 +47,9 @@ #define LAR_FNAME_BUFFER 1024 #define LAR_FNAME(s) char s[LAR_FNAME_BUFFER] +#define LAR_TYPE_REGULAR 0x0000 +#define LAR_TYPE_FILELIST 0xFFFF + #ifdef __WIN32__ #define LAR_DIRSEP '\\' #else @@ -35,12 +58,12 @@ struct lar_index_item { - uint32_t noffset; - uint32_t nlength; - uint32_t foffset; - uint32_t flength; + uint32_t offset; + uint32_t length; uint16_t type; uint16_t flags; + char id[16]; + char *filename; struct lar_index_item *next; }; @@ -55,6 +78,7 @@ struct lar_member_item { struct lar_archive_handle { int fd; + int has_filenames; off_t length; char filename[LAR_FNAME_BUFFER]; struct lar_index_item *index; @@ -64,14 +88,16 @@ typedef struct lar_index_item lar_index; typedef struct lar_member_item lar_member; typedef struct lar_archive_handle lar_archive; - -int lar_read32( int fd, uint32_t *val ); -int lar_read16( int fd, uint16_t *val ); +/* +static int lar_read_filenames( lar_archive *ar ); +static int lar_read32( int fd, uint32_t *val ); +static int lar_read16( int fd, uint16_t *val ); +static void lar_md5( char *md5, const char *data, int len ); +*/ lar_index * lar_get_index( lar_archive *ar ); -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 ); lar_member * lar_open_member( lar_archive *ar, const char *name ); @@ -81,7 +107,7 @@ lar_archive * lar_open( const char *filename ); int lar_close( lar_archive *ar ); -lar_archive * lar_find_archive( const char *package, const char *path ); +lar_archive * lar_find_archive( const char *package, const char *path, int pkg); lar_member * lar_find_member( lar_archive *ar, const char *package ); diff --git a/contrib/lar/larlib.c b/contrib/lar/larlib.c new file mode 100644 index 000000000..5467ed5b9 --- /dev/null +++ b/contrib/lar/larlib.c @@ -0,0 +1,540 @@ +/* + * 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 "lua.h" +#include "lualib.h" +#include "lauxlib.h" +#include "lar.h" + +typedef struct { + int fd; + char *data; + size_t length; +} mmap_handle; + +static int larlib_perror( lua_State *L, const char *message ) +{ + lua_pushnil(L); + lua_pushstring(L, message); + + return 2; +} + +int larlib_open( lua_State *L ) +{ + lar_archive *ar, **udata; + const char *filename = luaL_checkstring( L, 1 ); + + if( filename != NULL && (ar = lar_open(filename)) != NULL ) + { + if( (udata = lua_newuserdata(L, sizeof(lar_archive *))) != NULL ) + { + *udata = ar; + luaL_getmetatable(L, "lar.archive"); + lua_setmetatable(L, -2); + } + else + { + return luaL_error(L, "Out of memory"); + } + } + else + { + return larlib_perror(L, "Archive not found"); + } + + return 1; +} + +int larlib_find( lua_State *L ) +{ + const char *filename = luaL_checkstring( L, 1 ); + const char *basepath = luaL_optstring( L, 2, "./" ); + int is_pkg = strstr(filename, "/") ? 0 : 1; + lar_archive *ar, **udata; + + if( ((ar = lar_find_archive(filename, basepath, is_pkg)) != NULL) || + ((ar = lar_find_archive(filename, LUA_LDIR, is_pkg)) != NULL) || + ((ar = lar_find_archive(filename, LUA_CDIR, is_pkg)) != NULL) ) + { + if( (udata = lua_newuserdata(L, sizeof(lar_archive *))) != NULL ) + { + *udata = ar; + luaL_getmetatable(L, "lar.archive"); + lua_setmetatable(L, -2); + } + else + { + return luaL_error(L, "Out of memory"); + } + } + else + { + return larlib_perror(L, "Archive not found"); + } + + return 1; +} + +int larlib_md5( lua_State *L ) +{ + int i; + char md5[16], md5_hex[33]; + const char *data = luaL_checkstring( L, 1 ); + md5_state_t state; + + md5_init(&state); + md5_append(&state, (const md5_byte_t *)data, strlen(data)); + md5_finish(&state, (md5_byte_t *)md5); + + for( i = 0; i < 16; i++ ) + sprintf(&md5_hex[i*2], "%02x", (unsigned char)md5[i]); + + lua_pushstring(L, md5_hex); + return 1; +} + +int larlib_md5_file( lua_State *L ) +{ + int i, fd, len; + char md5[16], md5_hex[33], buffer[1024]; + const char *filename = luaL_checkstring( L, 1 ); + md5_state_t state; + + if( (fd = open(filename, O_RDONLY)) != -1 ) + { + md5_init(&state); + + while( (len = read(fd, buffer, 1024)) > 0 ) + md5_append(&state, (const md5_byte_t *)buffer, len); + + md5_finish(&state, (md5_byte_t *)md5); + + for( i = 0; i < 16; i++ ) + sprintf(&md5_hex[i*2], "%02x", (unsigned char)md5[i]); + + close(fd); + lua_pushstring(L, md5_hex); + } + else + { + return larlib_perror(L, strerror(errno)); + } + + return 1; +} + +static int larlib_mkpath( const char *name, const char *path, char *buffer ) +{ + int nlen = strlen(name); + int plen = strlen(path); + + if( (nlen + plen + 1) <= 1024 ) + { + strcpy(buffer, path); + + if( buffer[plen-1] != '/' ) + buffer[plen++] = '/'; + + strcpy(&buffer[plen], name); + buffer[plen + nlen] = '\0'; + + return 0; + } + + return 1; +} + +static int larlib__gc( lua_State *L ) +{ + lar_archive **archive = luaL_checkudata( L, 1, "lar.archive" ); + + if( *archive ) + lar_close(*archive); + + *archive = NULL; + return 0; +} + + +static int larlib_member__open( lua_State *L, lar_member *mb ) +{ + lar_archive **archive = NULL; + const char *filename = NULL; + lar_member **udata; + + if( mb == NULL ) + { + *archive = luaL_checkudata( L, 1, "lar.archive" ); + filename = luaL_checkstring( L, 2 ); + } + + if( mb != NULL || (mb = lar_open_member(*archive, filename)) != NULL ) + { + if( (udata = lua_newuserdata(L, sizeof(lar_member *))) != NULL ) + { + *udata = mb; + luaL_getmetatable(L, "lar.member"); + lua_setmetatable(L, -2); + } + else + { + return luaL_error(L, "Out of memory"); + } + } + else + { + return larlib_perror(L, "Member not found in archive"); + } + + return 1; +} + +int larlib_member_open( lua_State *L ) +{ + return larlib_member__open( L, NULL ); +} + +int larlib_member_find( lua_State *L ) +{ + lar_archive **archive = luaL_checkudata( L, 1, "lar.archive" ); + const char *package = luaL_checkstring( L, 2 ); + lar_member *mb, **udata; + + if( (mb = lar_find_member(*archive, package)) != NULL ) + { + if( (udata = lua_newuserdata(L, sizeof(lar_member *))) != NULL ) + { + *udata = mb; + luaL_getmetatable(L, "lar.member"); + lua_setmetatable(L, -2); + } + else + { + return luaL_error(L, "Out of memory"); + } + } + else + { + return larlib_perror(L, "Member not found in archive"); + } + + return 1; +} + +int larlib_member_size( lua_State *L ) +{ + lar_member **member = luaL_checkudata( L, 1, "lar.member" ); + lua_pushnumber(L, (*member)->length); + return 1; +} + +int larlib_member_type( lua_State *L ) +{ + lar_member **member = luaL_checkudata( L, 1, "lar.member" ); + lua_pushnumber(L, (*member)->type); + return 1; +} + +int larlib_member_flags( lua_State *L ) +{ + lar_member **member = luaL_checkudata( L, 1, "lar.member" ); + lua_pushnumber(L, (*member)->flags); + return 1; +} + +int larlib_member_read( lua_State *L ) +{ + lar_member **member = luaL_checkudata( L, 1, "lar.member" ); + int start = luaL_checknumber( L, 2 ); + int length = luaL_optnumber( L, 3, (*member)->length ); + char *stringcopy; + + if( (start >= 0) && (start < (*member)->length) && (length > 0) ) + { + if( (start + length) >= (*member)->length ) + length = (*member)->length - start; + + if( (stringcopy = (char *)malloc(length + 1)) != NULL ) + { + memcpy(stringcopy, &(*member)->data[start], length); + stringcopy[length] = '\0'; + lua_pushstring(L, stringcopy); + free(stringcopy); + } + else + { + return luaL_error(L, "Out of memory"); + } + } + else + { + return larlib_perror(L, "Invalid argument"); + } + + return 1; +} + +int larlib_member_data( lua_State *L ) +{ + lar_member **member = luaL_checkudata( L, 1, "lar.member" ); + lua_pushstring(L, (*member)->data); + return 1; +} + +int larlib_member_load( lua_State *L ) +{ + lar_member **member = luaL_checkudata( L, 1, "lar.member" ); + int status = luaL_loadbuffer( L, (*member)->data, (*member)->length, + "=(lar member)" ); + + if( status ) + { + lua_pushnil(L); + lua_insert(L, -2); + return 2; + } + + return 1; +} + +static int larlib_member__gc( lua_State *L ) +{ + lar_member **member = luaL_checkudata( L, 1, "lar.member" ); + + if( *member ) + lar_close_member(*member); + + *member = NULL; + return 0; +} + + +static int larlib_mmfile__open( lua_State *L, const char *filename ) +{ + struct stat s; + mmap_handle *fh, **udata; + + if( filename == NULL ) + filename = (const char *)luaL_checkstring( L, 1 ); + + if( (fh = (mmap_handle *)malloc(sizeof(mmap_handle))) == NULL ) + return larlib_perror(L, "Out of memory"); + + if( stat(filename, &s) > -1 && (fh->fd = open(filename, O_RDONLY)) > -1 ) + { + fh->length = s.st_size; + fh->data = mmap( 0, s.st_size, PROT_READ, MAP_PRIVATE, fh->fd, 0 ); + + if( fh->data == MAP_FAILED ) + return larlib_perror(L, "Failed to mmap() file"); + + if( (udata = lua_newuserdata(L, sizeof(char *))) != NULL ) + { + *udata = fh; + luaL_getmetatable(L, "lar.mmfile"); + lua_setmetatable(L, -2); + } + else + { + return larlib_perror(L, "Out of memory"); + } + } + else + { + return larlib_perror(L, strerror(errno)); + } + + return 1; +} + +int larlib_mmfile_open( lua_State *L ) +{ + return larlib_mmfile__open(L, NULL); +} + +int larlib_mmfile_size( lua_State *L ) +{ + mmap_handle **fh = luaL_checkudata( L, 1, "lar.mmfile" ); + lua_pushnumber(L, (*fh)->length); + return 1; +} + +int larlib_mmfile_read( lua_State *L ) +{ + mmap_handle **fh = luaL_checkudata( L, 1, "lar.mmfile" ); + int start = luaL_checknumber( L, 2 ); + int length = luaL_optnumber( L, 3, (*fh)->length ); + char *stringcopy; + + if( (start >= 0) && (start < (*fh)->length) && (length > 0) ) + { + if( (start + length) >= (*fh)->length ) + length = (*fh)->length - start; + + if( (stringcopy = (char *)malloc(length + 1)) != NULL ) + { + memcpy(stringcopy, &(*fh)->data[start], length); + stringcopy[length] = '\0'; + lua_pushstring(L, stringcopy); + free(stringcopy); + } + else + { + return luaL_error(L, "Out of memory"); + } + } + else + { + return larlib_perror(L, "Invalid argument"); + } + + return 1; +} + +int larlib_mmfile_data( lua_State *L ) +{ + mmap_handle **fh = luaL_checkudata( L, 1, "lar.mmfile" ); + lua_pushstring(L, (*fh)->data); + return 1; +} + +int larlib_mmfile_load( lua_State *L ) +{ + mmap_handle **fh = luaL_checkudata( L, 1, "lar.mmfile" ); + int status = luaL_loadbuffer(L, (*fh)->data, (*fh)->length, "=(mmap file)"); + + if( status ) + { + lua_pushnil(L); + lua_insert(L, -2); + return 2; + } + + return 1; +} + +static int larlib_mmfile__gc( lua_State *L ) +{ + mmap_handle **fh = luaL_checkudata( L, 1, "lar.mmfile" ); + + if( *fh ) + { + close((*fh)->fd); + munmap((*fh)->data, (*fh)->length); + free(*fh); + *fh = NULL; + } + + return 0; +} + + +int larlib_findfile( lua_State *L ) +{ + int i; + const char *filename = luaL_checkstring( L, 1 ); + const char *basepath = luaL_optstring( L, 2, "./" ); + char filepath[1024]; + struct stat s; + lar_archive *ar; + lar_member *mb; + + const char *searchpath[3] = { basepath, LUA_LDIR, LUA_CDIR }; + + for( i = 0; i < 3; i++ ) + if( !larlib_mkpath(filename, searchpath[i], filepath) ) + if( stat(filepath, &s) > -1 && (s.st_mode & S_IFREG) ) + return larlib_mmfile__open( L, filepath ); + + for( i = 0; i < 3; i++ ) + if( (ar = lar_find_archive(filename, searchpath[i], 0)) != NULL ) + if( (mb = lar_open_member(ar, filename)) != NULL ) + return larlib_member__open( L, mb ); + + return larlib_perror(L, "File not found"); +} + + +static const luaL_reg LAR_REG[] = { + { "open", larlib_open }, + { "find", larlib_find }, + { "md5", larlib_md5 }, + { "md5_file", larlib_md5_file }, + { "mmap", larlib_mmfile_open }, + { "findfile", larlib_findfile }, + { NULL, NULL } +}; + +static const luaL_reg LAR_ARCHIVE_REG[] = { + { "member", larlib_member_open }, + { "find", larlib_member_find }, + { "__gc", larlib__gc }, + { NULL, NULL } +}; + +static const luaL_reg LAR_MEMBER_REG[] = { + { "size", larlib_member_size }, + { "type", larlib_member_type }, + { "flags", larlib_member_flags }, + { "read", larlib_member_read }, + { "data", larlib_member_data }, + { "load", larlib_member_load }, + { "__gc", larlib_member__gc }, + { NULL, NULL } +}; + +static const luaL_reg LAR_MMFILE_REG[] = { + { "size", larlib_mmfile_size }, + { "read", larlib_mmfile_read }, + { "data", larlib_mmfile_data }, + { "load", larlib_mmfile_load }, + { "__gc", larlib_mmfile__gc }, + { NULL, NULL } +}; + + +LUALIB_API int luaopen_larlib( lua_State *L ) +{ + luaL_newmetatable(L, "lar"); + luaL_register(L, NULL, LAR_REG); + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + lua_setglobal(L, "lar"); + + luaL_newmetatable(L, "lar.archive"); + luaL_register(L, NULL, LAR_ARCHIVE_REG); + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + lua_setglobal(L, "lar.archive"); + + luaL_newmetatable(L, "lar.member"); + luaL_register(L, NULL, LAR_MEMBER_REG); + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + lua_setglobal(L, "lar.member"); + + luaL_newmetatable(L, "lar.mmfile"); + luaL_register(L, NULL, LAR_MMFILE_REG); + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + lua_setglobal(L, "lar.mmfile"); + + return 1; +} diff --git a/contrib/lar/md5.c b/contrib/lar/md5.c new file mode 100644 index 000000000..c35d96c5e --- /dev/null +++ b/contrib/lar/md5.c @@ -0,0 +1,381 @@ +/* + Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + L. Peter Deutsch + ghost@aladdin.com + + */ +/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321, whose + text is available at + http://www.ietf.org/rfc/rfc1321.txt + The code is derived from the text of the RFC, including the test suite + (section A.5) but excluding the rest of Appendix A. It does not include + any code or documentation that is identified in the RFC as being + copyrighted. + + The original and principal author of md5.c is L. Peter Deutsch + . Other authors are noted in the change history + that follows (in reverse chronological order): + + 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order + either statically or dynamically; added missing #include + in library. + 2002-03-11 lpd Corrected argument list for main(), and added int return + type, in test program and T value program. + 2002-02-21 lpd Added missing #include in test program. + 2000-07-03 lpd Patched to eliminate warnings about "constant is + unsigned in ANSI C, signed in traditional"; made test program + self-checking. + 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. + 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). + 1999-05-03 lpd Original version. + */ + +#include "md5.h" +#include + +#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ +#ifdef ARCH_IS_BIG_ENDIAN +# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1) +#else +# define BYTE_ORDER 0 +#endif + +#define T_MASK ((md5_word_t)~0) +#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) +#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) +#define T3 0x242070db +#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) +#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) +#define T6 0x4787c62a +#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) +#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) +#define T9 0x698098d8 +#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) +#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) +#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) +#define T13 0x6b901122 +#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) +#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) +#define T16 0x49b40821 +#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) +#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) +#define T19 0x265e5a51 +#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) +#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) +#define T22 0x02441453 +#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) +#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) +#define T25 0x21e1cde6 +#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) +#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) +#define T28 0x455a14ed +#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) +#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) +#define T31 0x676f02d9 +#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) +#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) +#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) +#define T35 0x6d9d6122 +#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) +#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) +#define T38 0x4bdecfa9 +#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) +#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) +#define T41 0x289b7ec6 +#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) +#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) +#define T44 0x04881d05 +#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) +#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) +#define T47 0x1fa27cf8 +#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) +#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) +#define T50 0x432aff97 +#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) +#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) +#define T53 0x655b59c3 +#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) +#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) +#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) +#define T57 0x6fa87e4f +#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) +#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) +#define T60 0x4e0811a1 +#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) +#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) +#define T63 0x2ad7d2bb +#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) + + +static void +md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) +{ + md5_word_t + a = pms->abcd[0], b = pms->abcd[1], + c = pms->abcd[2], d = pms->abcd[3]; + md5_word_t t; +#if BYTE_ORDER > 0 + /* Define storage only for big-endian CPUs. */ + md5_word_t X[16]; +#else + /* Define storage for little-endian or both types of CPUs. */ + md5_word_t xbuf[16]; + const md5_word_t *X; +#endif + + { +#if BYTE_ORDER == 0 + /* + * Determine dynamically whether this is a big-endian or + * little-endian machine, since we can use a more efficient + * algorithm on the latter. + */ + static const int w = 1; + + if (*((const md5_byte_t *)&w)) /* dynamic little-endian */ +#endif +#if BYTE_ORDER <= 0 /* little-endian */ + { + /* + * On little-endian machines, we can process properly aligned + * data without copying it. + */ + if (!((data - (const md5_byte_t *)0) & 3)) { + /* data are properly aligned */ + X = (const md5_word_t *)data; + } else { + /* not aligned */ + memcpy(xbuf, data, 64); + X = xbuf; + } + } +#endif +#if BYTE_ORDER == 0 + else /* dynamic big-endian */ +#endif +#if BYTE_ORDER >= 0 /* big-endian */ + { + /* + * On big-endian machines, we must arrange the bytes in the + * right order. + */ + const md5_byte_t *xp = data; + int i; + +# if BYTE_ORDER == 0 + X = xbuf; /* (dynamic only) */ +# else +# define xbuf X /* (static only) */ +# endif + for (i = 0; i < 16; ++i, xp += 4) + xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); + } +#endif + } + +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) + + /* Round 1. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ +#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + F(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 7, T1); + SET(d, a, b, c, 1, 12, T2); + SET(c, d, a, b, 2, 17, T3); + SET(b, c, d, a, 3, 22, T4); + SET(a, b, c, d, 4, 7, T5); + SET(d, a, b, c, 5, 12, T6); + SET(c, d, a, b, 6, 17, T7); + SET(b, c, d, a, 7, 22, T8); + SET(a, b, c, d, 8, 7, T9); + SET(d, a, b, c, 9, 12, T10); + SET(c, d, a, b, 10, 17, T11); + SET(b, c, d, a, 11, 22, T12); + SET(a, b, c, d, 12, 7, T13); + SET(d, a, b, c, 13, 12, T14); + SET(c, d, a, b, 14, 17, T15); + SET(b, c, d, a, 15, 22, T16); +#undef SET + + /* Round 2. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ +#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + G(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 1, 5, T17); + SET(d, a, b, c, 6, 9, T18); + SET(c, d, a, b, 11, 14, T19); + SET(b, c, d, a, 0, 20, T20); + SET(a, b, c, d, 5, 5, T21); + SET(d, a, b, c, 10, 9, T22); + SET(c, d, a, b, 15, 14, T23); + SET(b, c, d, a, 4, 20, T24); + SET(a, b, c, d, 9, 5, T25); + SET(d, a, b, c, 14, 9, T26); + SET(c, d, a, b, 3, 14, T27); + SET(b, c, d, a, 8, 20, T28); + SET(a, b, c, d, 13, 5, T29); + SET(d, a, b, c, 2, 9, T30); + SET(c, d, a, b, 7, 14, T31); + SET(b, c, d, a, 12, 20, T32); +#undef SET + + /* Round 3. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + H(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 5, 4, T33); + SET(d, a, b, c, 8, 11, T34); + SET(c, d, a, b, 11, 16, T35); + SET(b, c, d, a, 14, 23, T36); + SET(a, b, c, d, 1, 4, T37); + SET(d, a, b, c, 4, 11, T38); + SET(c, d, a, b, 7, 16, T39); + SET(b, c, d, a, 10, 23, T40); + SET(a, b, c, d, 13, 4, T41); + SET(d, a, b, c, 0, 11, T42); + SET(c, d, a, b, 3, 16, T43); + SET(b, c, d, a, 6, 23, T44); + SET(a, b, c, d, 9, 4, T45); + SET(d, a, b, c, 12, 11, T46); + SET(c, d, a, b, 15, 16, T47); + SET(b, c, d, a, 2, 23, T48); +#undef SET + + /* Round 4. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ +#define I(x, y, z) ((y) ^ ((x) | ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + I(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 6, T49); + SET(d, a, b, c, 7, 10, T50); + SET(c, d, a, b, 14, 15, T51); + SET(b, c, d, a, 5, 21, T52); + SET(a, b, c, d, 12, 6, T53); + SET(d, a, b, c, 3, 10, T54); + SET(c, d, a, b, 10, 15, T55); + SET(b, c, d, a, 1, 21, T56); + SET(a, b, c, d, 8, 6, T57); + SET(d, a, b, c, 15, 10, T58); + SET(c, d, a, b, 6, 15, T59); + SET(b, c, d, a, 13, 21, T60); + SET(a, b, c, d, 4, 6, T61); + SET(d, a, b, c, 11, 10, T62); + SET(c, d, a, b, 2, 15, T63); + SET(b, c, d, a, 9, 21, T64); +#undef SET + + /* Then perform the following additions. (That is increment each + of the four registers by the value it had before this block + was started.) */ + pms->abcd[0] += a; + pms->abcd[1] += b; + pms->abcd[2] += c; + pms->abcd[3] += d; +} + +void +md5_init(md5_state_t *pms) +{ + pms->count[0] = pms->count[1] = 0; + pms->abcd[0] = 0x67452301; + pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; + pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; + pms->abcd[3] = 0x10325476; +} + +void +md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) +{ + const md5_byte_t *p = data; + int left = nbytes; + int offset = (pms->count[0] >> 3) & 63; + md5_word_t nbits = (md5_word_t)(nbytes << 3); + + if (nbytes <= 0) + return; + + /* Update the message length. */ + pms->count[1] += nbytes >> 29; + pms->count[0] += nbits; + if (pms->count[0] < nbits) + pms->count[1]++; + + /* Process an initial partial block. */ + if (offset) { + int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); + + memcpy(pms->buf + offset, p, copy); + if (offset + copy < 64) + return; + p += copy; + left -= copy; + md5_process(pms, pms->buf); + } + + /* Process full blocks. */ + for (; left >= 64; p += 64, left -= 64) + md5_process(pms, p); + + /* Process a final partial block. */ + if (left) + memcpy(pms->buf, p, left); +} + +void +md5_finish(md5_state_t *pms, md5_byte_t digest[16]) +{ + static const md5_byte_t pad[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + md5_byte_t data[8]; + int i; + + /* Save the length before padding. */ + for (i = 0; i < 8; ++i) + data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); + /* Pad to 56 bytes mod 64. */ + md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); + /* Append the length. */ + md5_append(pms, data, 8); + for (i = 0; i < 16; ++i) + digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); +} diff --git a/contrib/lar/md5.h b/contrib/lar/md5.h new file mode 100644 index 000000000..698c995d8 --- /dev/null +++ b/contrib/lar/md5.h @@ -0,0 +1,91 @@ +/* + Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + L. Peter Deutsch + ghost@aladdin.com + + */ +/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321, whose + text is available at + http://www.ietf.org/rfc/rfc1321.txt + The code is derived from the text of the RFC, including the test suite + (section A.5) but excluding the rest of Appendix A. It does not include + any code or documentation that is identified in the RFC as being + copyrighted. + + The original and principal author of md5.h is L. Peter Deutsch + . Other authors are noted in the change history + that follows (in reverse chronological order): + + 2002-04-13 lpd Removed support for non-ANSI compilers; removed + references to Ghostscript; clarified derivation from RFC 1321; + now handles byte order either statically or dynamically. + 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. + 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); + added conditionalization for C++ compilation from Martin + Purschke . + 1999-05-03 lpd Original version. + */ + +#ifndef md5_INCLUDED +# define md5_INCLUDED + +/* + * This package supports both compile-time and run-time determination of CPU + * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be + * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is + * defined as non-zero, the code will be compiled to run only on big-endian + * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to + * run on either big- or little-endian CPUs, but will run slightly less + * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. + */ + +typedef unsigned char md5_byte_t; /* 8-bit byte */ +typedef unsigned int md5_word_t; /* 32-bit word */ + +/* Define the state of the MD5 Algorithm. */ +typedef struct md5_state_s { + md5_word_t count[2]; /* message length in bits, lsw first */ + md5_word_t abcd[4]; /* digest buffer */ + md5_byte_t buf[64]; /* accumulate block */ +} md5_state_t; + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Initialize the algorithm. */ +void md5_init(md5_state_t *pms); + +/* Append a string to the message. */ +void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); + +/* Finish the message and return the digest. */ +void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* md5_INCLUDED */ diff --git a/contrib/lar/openwrt/050-lar-source-loader.patch b/contrib/lar/openwrt/050-lar-source-loader.patch index c17c2f5c8..ac282dc44 100644 --- a/contrib/lar/openwrt/050-lar-source-loader.patch +++ b/contrib/lar/openwrt/050-lar-source-loader.patch @@ -1,22 +1,41 @@ -diff -Nurb lua-5.1.4.orig/src/Makefile lua-5.1.4/src/Makefile +diff -Nbur lua-5.1.4.orig/src/Makefile lua-5.1.4/src/Makefile --- lua-5.1.4.orig/src/Makefile 2009-04-06 21:36:52.000000000 +0200 -+++ lua-5.1.4/src/Makefile 2009-04-06 23:04:42.000000000 +0200 ++++ lua-5.1.4/src/Makefile 2009-04-11 01:02:45.000000000 +0200 @@ -28,7 +28,7 @@ lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o \ lundump.o lvm.o lzio.o lnum.o LIB_O= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \ - lstrlib.o loadlib.o linit.o -+ lstrlib.o loadlib.o linit.o lar.o ++ lstrlib.o loadlib.o linit.o lar.o md5.o larlib.o LUA_T= lua LUA_O= lua.o -diff -Nurb lua-5.1.4.orig/src/lar.c lua-5.1.4/src/lar.c +diff -Nbur lua-5.1.4.orig/src/lar.c lua-5.1.4/src/lar.c --- lua-5.1.4.orig/src/lar.c 1970-01-01 01:00:00.000000000 +0100 -+++ lua-5.1.4/src/lar.c 2009-04-07 03:53:29.000000000 +0200 -@@ -0,0 +1,242 @@ ++++ lua-5.1.4/src/lar.c 2009-04-13 16:51:07.000000000 +0200 +@@ -0,0 +1,328 @@ ++/* ++ * 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]; + @@ -29,7 +48,7 @@ diff -Nurb lua-5.1.4.orig/src/lar.c lua-5.1.4/src/lar.c + return 0; +} + -+int lar_read16( int fd, uint16_t *val ) ++static int lar_read16( int fd, uint16_t *val ) +{ + uint8_t buffer[3]; + @@ -42,6 +61,76 @@ diff -Nurb lua-5.1.4.orig/src/lar.c lua-5.1.4/src/lar.c + 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; @@ -62,16 +151,19 @@ diff -Nurb lua-5.1.4.orig/src/lar.c lua-5.1.4/src/lar.c + + 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; + } @@ -79,58 +171,43 @@ diff -Nurb lua-5.1.4.orig/src/lar.c lua-5.1.4/src/lar.c + 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 ); + -+ if( lseek(ar->fd, idx_ptr->noffset, SEEK_SET) == -1 ) -+ LAR_DIE("Unexpected EOF while seeking filename"); ++ char *memberdata = mmap( ++ 0, idx_ptr->length + pgof, PROT_READ, MAP_PRIVATE, ++ ar->fd, idx_ptr->offset - pgof ++ ); + -+ if( read(ar->fd, filename, idx_ptr->nlength) < idx_ptr->nlength ) -+ LAR_DIE("Unexpected EOF while reading filename"); ++ if( memberdata == MAP_FAILED ) ++ LAR_DIE("Failed to mmap() member data"); + -+ filename[idx_ptr->nlength] = '\0'; ++ 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]; + -+ return idx_ptr->nlength; ++ member->mmap = memberdata; ++ member->mlen = idx_ptr->length + pgof; ++ ++ 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; + } @@ -142,6 +219,7 @@ diff -Nurb lua-5.1.4.orig/src/lar.c lua-5.1.4/src/lar.c +{ + int stat = munmap(member->mmap, member->mlen); + free(member); ++ member = NULL; + + return stat; +} @@ -166,6 +244,8 @@ diff -Nurb lua-5.1.4.orig/src/lar.c lua-5.1.4/src/lar.c + ar->index = lar_get_index(ar); + strncpy(ar->filename, filename, sizeof(ar->filename)); + ++ ar->has_filenames = lar_read_filenames(ar); ++ + return ar; + } + @@ -182,21 +262,24 @@ diff -Nurb lua-5.1.4.orig/src/lar.c lua-5.1.4/src/lar.c + 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); + @@ -209,23 +292,26 @@ diff -Nurb lua-5.1.4.orig/src/lar.c lua-5.1.4/src/lar.c + 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"); @@ -256,10 +342,29 @@ diff -Nurb lua-5.1.4.orig/src/lar.c lua-5.1.4/src/lar.c + + return lar_open_member(ar, buffer); +} -diff -Nurb lua-5.1.4.orig/src/lar.h lua-5.1.4/src/lar.h +diff -Nbur lua-5.1.4.orig/src/lar.h lua-5.1.4/src/lar.h --- lua-5.1.4.orig/src/lar.h 1970-01-01 01:00:00.000000000 +0100 -+++ lua-5.1.4/src/lar.h 2009-04-06 23:06:31.000000000 +0200 -@@ -0,0 +1,88 @@ ++++ lua-5.1.4/src/lar.h 2009-04-13 16:51:32.000000000 +0200 +@@ -0,0 +1,114 @@ ++/* ++ * 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. ++ */ ++ ++ +#ifndef __LAR_H +#define __LAR_H + @@ -275,6 +380,7 @@ diff -Nurb lua-5.1.4.orig/src/lar.h lua-5.1.4/src/lar.h +#include +#include + ++#include "md5.h" + +#define LAR_DIE(s) \ + do { \ @@ -289,6 +395,9 @@ diff -Nurb lua-5.1.4.orig/src/lar.h lua-5.1.4/src/lar.h +#define LAR_FNAME_BUFFER 1024 +#define LAR_FNAME(s) char s[LAR_FNAME_BUFFER] + ++#define LAR_TYPE_REGULAR 0x0000 ++#define LAR_TYPE_FILELIST 0xFFFF ++ +#ifdef __WIN32__ +#define LAR_DIRSEP '\\' +#else @@ -297,12 +406,12 @@ diff -Nurb lua-5.1.4.orig/src/lar.h lua-5.1.4/src/lar.h + + +struct lar_index_item { -+ uint32_t noffset; -+ uint32_t nlength; -+ uint32_t foffset; -+ uint32_t flength; ++ uint32_t offset; ++ uint32_t length; + uint16_t type; + uint16_t flags; ++ char id[16]; ++ char *filename; + struct lar_index_item *next; +}; + @@ -317,6 +426,7 @@ diff -Nurb lua-5.1.4.orig/src/lar.h lua-5.1.4/src/lar.h + +struct lar_archive_handle { + int fd; ++ int has_filenames; + off_t length; + char filename[LAR_FNAME_BUFFER]; + struct lar_index_item *index; @@ -326,14 +436,16 @@ diff -Nurb lua-5.1.4.orig/src/lar.h lua-5.1.4/src/lar.h +typedef struct lar_member_item lar_member; +typedef struct lar_archive_handle lar_archive; + -+ -+int lar_read32( int fd, uint32_t *val ); -+int lar_read16( int fd, uint16_t *val ); ++/* ++static int lar_read_filenames( lar_archive *ar ); ++static int lar_read32( int fd, uint32_t *val ); ++static int lar_read16( int fd, uint16_t *val ); ++static void lar_md5( char *md5, const char *data, int len ); ++*/ + +lar_index * lar_get_index( lar_archive *ar ); + -+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 ); + +lar_member * lar_open_member( lar_archive *ar, const char *name ); + @@ -343,14 +455,569 @@ diff -Nurb lua-5.1.4.orig/src/lar.h lua-5.1.4/src/lar.h + +int lar_close( lar_archive *ar ); + -+lar_archive * lar_find_archive( const char *package, const char *path ); ++lar_archive * lar_find_archive( const char *package, const char *path, int pkg); + +lar_member * lar_find_member( lar_archive *ar, const char *package ); + +#endif -diff -Nurb lua-5.1.4.orig/src/loadlib.c lua-5.1.4/src/loadlib.c +diff -Nbur lua-5.1.4.orig/src/larlib.c lua-5.1.4/src/larlib.c +--- lua-5.1.4.orig/src/larlib.c 1970-01-01 01:00:00.000000000 +0100 ++++ lua-5.1.4/src/larlib.c 2009-04-13 16:51:15.000000000 +0200 +@@ -0,0 +1,540 @@ ++/* ++ * 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 "lua.h" ++#include "lualib.h" ++#include "lauxlib.h" ++#include "lar.h" ++ ++typedef struct { ++ int fd; ++ char *data; ++ size_t length; ++} mmap_handle; ++ ++static int larlib_perror( lua_State *L, const char *message ) ++{ ++ lua_pushnil(L); ++ lua_pushstring(L, message); ++ ++ return 2; ++} ++ ++int larlib_open( lua_State *L ) ++{ ++ lar_archive *ar, **udata; ++ const char *filename = luaL_checkstring( L, 1 ); ++ ++ if( filename != NULL && (ar = lar_open(filename)) != NULL ) ++ { ++ if( (udata = lua_newuserdata(L, sizeof(lar_archive *))) != NULL ) ++ { ++ *udata = ar; ++ luaL_getmetatable(L, "lar.archive"); ++ lua_setmetatable(L, -2); ++ } ++ else ++ { ++ return luaL_error(L, "Out of memory"); ++ } ++ } ++ else ++ { ++ return larlib_perror(L, "Archive not found"); ++ } ++ ++ return 1; ++} ++ ++int larlib_find( lua_State *L ) ++{ ++ const char *filename = luaL_checkstring( L, 1 ); ++ const char *basepath = luaL_optstring( L, 2, "./" ); ++ int is_pkg = strstr(filename, "/") ? 0 : 1; ++ lar_archive *ar, **udata; ++ ++ if( ((ar = lar_find_archive(filename, basepath, is_pkg)) != NULL) || ++ ((ar = lar_find_archive(filename, LUA_LDIR, is_pkg)) != NULL) || ++ ((ar = lar_find_archive(filename, LUA_CDIR, is_pkg)) != NULL) ) ++ { ++ if( (udata = lua_newuserdata(L, sizeof(lar_archive *))) != NULL ) ++ { ++ *udata = ar; ++ luaL_getmetatable(L, "lar.archive"); ++ lua_setmetatable(L, -2); ++ } ++ else ++ { ++ return luaL_error(L, "Out of memory"); ++ } ++ } ++ else ++ { ++ return larlib_perror(L, "Archive not found"); ++ } ++ ++ return 1; ++} ++ ++int larlib_md5( lua_State *L ) ++{ ++ int i; ++ char md5[16], md5_hex[33]; ++ const char *data = luaL_checkstring( L, 1 ); ++ md5_state_t state; ++ ++ md5_init(&state); ++ md5_append(&state, (const md5_byte_t *)data, strlen(data)); ++ md5_finish(&state, (md5_byte_t *)md5); ++ ++ for( i = 0; i < 16; i++ ) ++ sprintf(&md5_hex[i*2], "%02x", (unsigned char)md5[i]); ++ ++ lua_pushstring(L, md5_hex); ++ return 1; ++} ++ ++int larlib_md5_file( lua_State *L ) ++{ ++ int i, fd, len; ++ char md5[16], md5_hex[33], buffer[1024]; ++ const char *filename = luaL_checkstring( L, 1 ); ++ md5_state_t state; ++ ++ if( (fd = open(filename, O_RDONLY)) != -1 ) ++ { ++ md5_init(&state); ++ ++ while( (len = read(fd, buffer, 1024)) > 0 ) ++ md5_append(&state, (const md5_byte_t *)buffer, len); ++ ++ md5_finish(&state, (md5_byte_t *)md5); ++ ++ for( i = 0; i < 16; i++ ) ++ sprintf(&md5_hex[i*2], "%02x", (unsigned char)md5[i]); ++ ++ close(fd); ++ lua_pushstring(L, md5_hex); ++ } ++ else ++ { ++ return larlib_perror(L, strerror(errno)); ++ } ++ ++ return 1; ++} ++ ++static int larlib_mkpath( const char *name, const char *path, char *buffer ) ++{ ++ int nlen = strlen(name); ++ int plen = strlen(path); ++ ++ if( (nlen + plen + 1) <= 1024 ) ++ { ++ strcpy(buffer, path); ++ ++ if( buffer[plen-1] != '/' ) ++ buffer[plen++] = '/'; ++ ++ strcpy(&buffer[plen], name); ++ buffer[plen + nlen] = '\0'; ++ ++ return 0; ++ } ++ ++ return 1; ++} ++ ++static int larlib__gc( lua_State *L ) ++{ ++ lar_archive **archive = luaL_checkudata( L, 1, "lar.archive" ); ++ ++ if( *archive ) ++ lar_close(*archive); ++ ++ *archive = NULL; ++ return 0; ++} ++ ++ ++static int larlib_member__open( lua_State *L, lar_member *mb ) ++{ ++ lar_archive **archive = NULL; ++ const char *filename = NULL; ++ lar_member **udata; ++ ++ if( mb == NULL ) ++ { ++ *archive = luaL_checkudata( L, 1, "lar.archive" ); ++ filename = luaL_checkstring( L, 2 ); ++ } ++ ++ if( mb != NULL || (mb = lar_open_member(*archive, filename)) != NULL ) ++ { ++ if( (udata = lua_newuserdata(L, sizeof(lar_member *))) != NULL ) ++ { ++ *udata = mb; ++ luaL_getmetatable(L, "lar.member"); ++ lua_setmetatable(L, -2); ++ } ++ else ++ { ++ return luaL_error(L, "Out of memory"); ++ } ++ } ++ else ++ { ++ return larlib_perror(L, "Member not found in archive"); ++ } ++ ++ return 1; ++} ++ ++int larlib_member_open( lua_State *L ) ++{ ++ return larlib_member__open( L, NULL ); ++} ++ ++int larlib_member_find( lua_State *L ) ++{ ++ lar_archive **archive = luaL_checkudata( L, 1, "lar.archive" ); ++ const char *package = luaL_checkstring( L, 2 ); ++ lar_member *mb, **udata; ++ ++ if( (mb = lar_find_member(*archive, package)) != NULL ) ++ { ++ if( (udata = lua_newuserdata(L, sizeof(lar_member *))) != NULL ) ++ { ++ *udata = mb; ++ luaL_getmetatable(L, "lar.member"); ++ lua_setmetatable(L, -2); ++ } ++ else ++ { ++ return luaL_error(L, "Out of memory"); ++ } ++ } ++ else ++ { ++ return larlib_perror(L, "Member not found in archive"); ++ } ++ ++ return 1; ++} ++ ++int larlib_member_size( lua_State *L ) ++{ ++ lar_member **member = luaL_checkudata( L, 1, "lar.member" ); ++ lua_pushnumber(L, (*member)->length); ++ return 1; ++} ++ ++int larlib_member_type( lua_State *L ) ++{ ++ lar_member **member = luaL_checkudata( L, 1, "lar.member" ); ++ lua_pushnumber(L, (*member)->type); ++ return 1; ++} ++ ++int larlib_member_flags( lua_State *L ) ++{ ++ lar_member **member = luaL_checkudata( L, 1, "lar.member" ); ++ lua_pushnumber(L, (*member)->flags); ++ return 1; ++} ++ ++int larlib_member_read( lua_State *L ) ++{ ++ lar_member **member = luaL_checkudata( L, 1, "lar.member" ); ++ int start = luaL_checknumber( L, 2 ); ++ int length = luaL_optnumber( L, 3, (*member)->length ); ++ char *stringcopy; ++ ++ if( (start >= 0) && (start < (*member)->length) && (length > 0) ) ++ { ++ if( (start + length) >= (*member)->length ) ++ length = (*member)->length - start; ++ ++ if( (stringcopy = (char *)malloc(length + 1)) != NULL ) ++ { ++ memcpy(stringcopy, &(*member)->data[start], length); ++ stringcopy[length] = '\0'; ++ lua_pushstring(L, stringcopy); ++ free(stringcopy); ++ } ++ else ++ { ++ return luaL_error(L, "Out of memory"); ++ } ++ } ++ else ++ { ++ return larlib_perror(L, "Invalid argument"); ++ } ++ ++ return 1; ++} ++ ++int larlib_member_data( lua_State *L ) ++{ ++ lar_member **member = luaL_checkudata( L, 1, "lar.member" ); ++ lua_pushstring(L, (*member)->data); ++ return 1; ++} ++ ++int larlib_member_load( lua_State *L ) ++{ ++ lar_member **member = luaL_checkudata( L, 1, "lar.member" ); ++ int status = luaL_loadbuffer( L, (*member)->data, (*member)->length, ++ "=(lar member)" ); ++ ++ if( status ) ++ { ++ lua_pushnil(L); ++ lua_insert(L, -2); ++ return 2; ++ } ++ ++ return 1; ++} ++ ++static int larlib_member__gc( lua_State *L ) ++{ ++ lar_member **member = luaL_checkudata( L, 1, "lar.member" ); ++ ++ if( *member ) ++ lar_close_member(*member); ++ ++ *member = NULL; ++ return 0; ++} ++ ++ ++static int larlib_mmfile__open( lua_State *L, const char *filename ) ++{ ++ struct stat s; ++ mmap_handle *fh, **udata; ++ ++ if( filename == NULL ) ++ filename = (const char *)luaL_checkstring( L, 1 ); ++ ++ if( (fh = (mmap_handle *)malloc(sizeof(mmap_handle))) == NULL ) ++ return larlib_perror(L, "Out of memory"); ++ ++ if( stat(filename, &s) > -1 && (fh->fd = open(filename, O_RDONLY)) > -1 ) ++ { ++ fh->length = s.st_size; ++ fh->data = mmap( 0, s.st_size, PROT_READ, MAP_PRIVATE, fh->fd, 0 ); ++ ++ if( fh->data == MAP_FAILED ) ++ return larlib_perror(L, "Failed to mmap() file"); ++ ++ if( (udata = lua_newuserdata(L, sizeof(char *))) != NULL ) ++ { ++ *udata = fh; ++ luaL_getmetatable(L, "lar.mmfile"); ++ lua_setmetatable(L, -2); ++ } ++ else ++ { ++ return larlib_perror(L, "Out of memory"); ++ } ++ } ++ else ++ { ++ return larlib_perror(L, strerror(errno)); ++ } ++ ++ return 1; ++} ++ ++int larlib_mmfile_open( lua_State *L ) ++{ ++ return larlib_mmfile__open(L, NULL); ++} ++ ++int larlib_mmfile_size( lua_State *L ) ++{ ++ mmap_handle **fh = luaL_checkudata( L, 1, "lar.mmfile" ); ++ lua_pushnumber(L, (*fh)->length); ++ return 1; ++} ++ ++int larlib_mmfile_read( lua_State *L ) ++{ ++ mmap_handle **fh = luaL_checkudata( L, 1, "lar.mmfile" ); ++ int start = luaL_checknumber( L, 2 ); ++ int length = luaL_optnumber( L, 3, (*fh)->length ); ++ char *stringcopy; ++ ++ if( (start >= 0) && (start < (*fh)->length) && (length > 0) ) ++ { ++ if( (start + length) >= (*fh)->length ) ++ length = (*fh)->length - start; ++ ++ if( (stringcopy = (char *)malloc(length + 1)) != NULL ) ++ { ++ memcpy(stringcopy, &(*fh)->data[start], length); ++ stringcopy[length] = '\0'; ++ lua_pushstring(L, stringcopy); ++ free(stringcopy); ++ } ++ else ++ { ++ return luaL_error(L, "Out of memory"); ++ } ++ } ++ else ++ { ++ return larlib_perror(L, "Invalid argument"); ++ } ++ ++ return 1; ++} ++ ++int larlib_mmfile_data( lua_State *L ) ++{ ++ mmap_handle **fh = luaL_checkudata( L, 1, "lar.mmfile" ); ++ lua_pushstring(L, (*fh)->data); ++ return 1; ++} ++ ++int larlib_mmfile_load( lua_State *L ) ++{ ++ mmap_handle **fh = luaL_checkudata( L, 1, "lar.mmfile" ); ++ int status = luaL_loadbuffer(L, (*fh)->data, (*fh)->length, "=(mmap file)"); ++ ++ if( status ) ++ { ++ lua_pushnil(L); ++ lua_insert(L, -2); ++ return 2; ++ } ++ ++ return 1; ++} ++ ++static int larlib_mmfile__gc( lua_State *L ) ++{ ++ mmap_handle **fh = luaL_checkudata( L, 1, "lar.mmfile" ); ++ ++ if( *fh ) ++ { ++ close((*fh)->fd); ++ munmap((*fh)->data, (*fh)->length); ++ free(*fh); ++ *fh = NULL; ++ } ++ ++ return 0; ++} ++ ++ ++int larlib_findfile( lua_State *L ) ++{ ++ int i; ++ const char *filename = luaL_checkstring( L, 1 ); ++ const char *basepath = luaL_optstring( L, 2, "./" ); ++ char filepath[1024]; ++ struct stat s; ++ lar_archive *ar; ++ lar_member *mb; ++ ++ const char *searchpath[3] = { basepath, LUA_LDIR, LUA_CDIR }; ++ ++ for( i = 0; i < 3; i++ ) ++ if( !larlib_mkpath(filename, searchpath[i], filepath) ) ++ if( stat(filepath, &s) > -1 && (s.st_mode & S_IFREG) ) ++ return larlib_mmfile__open( L, filepath ); ++ ++ for( i = 0; i < 3; i++ ) ++ if( (ar = lar_find_archive(filename, searchpath[i], 0)) != NULL ) ++ if( (mb = lar_open_member(ar, filename)) != NULL ) ++ return larlib_member__open( L, mb ); ++ ++ return larlib_perror(L, "File not found"); ++} ++ ++ ++static const luaL_reg LAR_REG[] = { ++ { "open", larlib_open }, ++ { "find", larlib_find }, ++ { "md5", larlib_md5 }, ++ { "md5_file", larlib_md5_file }, ++ { "mmap", larlib_mmfile_open }, ++ { "findfile", larlib_findfile }, ++ { NULL, NULL } ++}; ++ ++static const luaL_reg LAR_ARCHIVE_REG[] = { ++ { "member", larlib_member_open }, ++ { "find", larlib_member_find }, ++ { "__gc", larlib__gc }, ++ { NULL, NULL } ++}; ++ ++static const luaL_reg LAR_MEMBER_REG[] = { ++ { "size", larlib_member_size }, ++ { "type", larlib_member_type }, ++ { "flags", larlib_member_flags }, ++ { "read", larlib_member_read }, ++ { "data", larlib_member_data }, ++ { "load", larlib_member_load }, ++ { "__gc", larlib_member__gc }, ++ { NULL, NULL } ++}; ++ ++static const luaL_reg LAR_MMFILE_REG[] = { ++ { "size", larlib_mmfile_size }, ++ { "read", larlib_mmfile_read }, ++ { "data", larlib_mmfile_data }, ++ { "load", larlib_mmfile_load }, ++ { "__gc", larlib_mmfile__gc }, ++ { NULL, NULL } ++}; ++ ++ ++LUALIB_API int luaopen_larlib( lua_State *L ) ++{ ++ luaL_newmetatable(L, "lar"); ++ luaL_register(L, NULL, LAR_REG); ++ lua_pushvalue(L, -1); ++ lua_setfield(L, -2, "__index"); ++ lua_setglobal(L, "lar"); ++ ++ luaL_newmetatable(L, "lar.archive"); ++ luaL_register(L, NULL, LAR_ARCHIVE_REG); ++ lua_pushvalue(L, -1); ++ lua_setfield(L, -2, "__index"); ++ lua_setglobal(L, "lar.archive"); ++ ++ luaL_newmetatable(L, "lar.member"); ++ luaL_register(L, NULL, LAR_MEMBER_REG); ++ lua_pushvalue(L, -1); ++ lua_setfield(L, -2, "__index"); ++ lua_setglobal(L, "lar.member"); ++ ++ luaL_newmetatable(L, "lar.mmfile"); ++ luaL_register(L, NULL, LAR_MMFILE_REG); ++ lua_pushvalue(L, -1); ++ lua_setfield(L, -2, "__index"); ++ lua_setglobal(L, "lar.mmfile"); ++ ++ return 1; ++} +diff -Nbur lua-5.1.4.orig/src/linit.c lua-5.1.4/src/linit.c +--- lua-5.1.4.orig/src/linit.c 2009-04-06 21:36:52.000000000 +0200 ++++ lua-5.1.4/src/linit.c 2009-04-11 01:27:00.000000000 +0200 +@@ -23,6 +23,7 @@ + {LUA_STRLIBNAME, luaopen_string}, + {LUA_MATHLIBNAME, luaopen_math}, + {LUA_DBLIBNAME, luaopen_debug}, ++ {LUA_LARLIBNAME, luaopen_larlib}, + {NULL, NULL} + }; + +diff -Nbur lua-5.1.4.orig/src/loadlib.c lua-5.1.4/src/loadlib.c --- lua-5.1.4.orig/src/loadlib.c 2009-04-06 21:36:52.000000000 +0200 -+++ lua-5.1.4/src/loadlib.c 2009-04-07 01:55:21.000000000 +0200 ++++ lua-5.1.4/src/loadlib.c 2009-04-11 01:04:47.000000000 +0200 @@ -21,6 +21,7 @@ #include "lauxlib.h" #include "lualib.h" @@ -368,9 +1035,9 @@ diff -Nurb lua-5.1.4.orig/src/loadlib.c lua-5.1.4/src/loadlib.c + lar_member *mb; + const char *name = luaL_checkstring(L, 1); + -+ if( (ar = lar_find_archive(name, "./")) || -+ (ar = lar_find_archive(name, LUA_LDIR)) || -+ (ar = lar_find_archive(name, LUA_CDIR)) ++ if( (ar = lar_find_archive(name, "./", 1)) || ++ (ar = lar_find_archive(name, LUA_LDIR, 1)) || ++ (ar = lar_find_archive(name, LUA_CDIR, 1)) + ) { + if( (mb = lar_find_member(ar, name)) != NULL ) { + if( luaL_loadbuffer(L, mb->data, mb->length, ar->filename) != 0 ) { @@ -405,3 +1072,496 @@ diff -Nurb lua-5.1.4.orig/src/loadlib.c lua-5.1.4/src/loadlib.c LUALIB_API int luaopen_package (lua_State *L) { +diff -Nbur lua-5.1.4.orig/src/lualib.h lua-5.1.4/src/lualib.h +--- lua-5.1.4.orig/src/lualib.h 2009-04-06 21:36:52.000000000 +0200 ++++ lua-5.1.4/src/lualib.h 2009-04-11 01:28:24.000000000 +0200 +@@ -39,6 +39,9 @@ + #define LUA_LOADLIBNAME "package" + LUALIB_API int (luaopen_package) (lua_State *L); + ++#define LUA_LARLIBNAME "lar" ++LUALIB_API int (luaopen_larlib) (lua_State *L); ++ + + /* open all previous libraries */ + LUALIB_API void (luaL_openlibs) (lua_State *L); +diff -Nbur lua-5.1.4.orig/src/md5.c lua-5.1.4/src/md5.c +--- lua-5.1.4.orig/src/md5.c 1970-01-01 01:00:00.000000000 +0100 ++++ lua-5.1.4/src/md5.c 2009-04-10 23:07:56.000000000 +0200 +@@ -0,0 +1,381 @@ ++/* ++ Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. ++ ++ This software is provided 'as-is', without any express or implied ++ warranty. In no event will the authors be held liable for any damages ++ arising from the use of this software. ++ ++ Permission is granted to anyone to use this software for any purpose, ++ including commercial applications, and to alter it and redistribute it ++ freely, subject to the following restrictions: ++ ++ 1. The origin of this software must not be misrepresented; you must not ++ claim that you wrote the original software. If you use this software ++ in a product, an acknowledgment in the product documentation would be ++ appreciated but is not required. ++ 2. Altered source versions must be plainly marked as such, and must not be ++ misrepresented as being the original software. ++ 3. This notice may not be removed or altered from any source distribution. ++ ++ L. Peter Deutsch ++ ghost@aladdin.com ++ ++ */ ++/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */ ++/* ++ Independent implementation of MD5 (RFC 1321). ++ ++ This code implements the MD5 Algorithm defined in RFC 1321, whose ++ text is available at ++ http://www.ietf.org/rfc/rfc1321.txt ++ The code is derived from the text of the RFC, including the test suite ++ (section A.5) but excluding the rest of Appendix A. It does not include ++ any code or documentation that is identified in the RFC as being ++ copyrighted. ++ ++ The original and principal author of md5.c is L. Peter Deutsch ++ . Other authors are noted in the change history ++ that follows (in reverse chronological order): ++ ++ 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order ++ either statically or dynamically; added missing #include ++ in library. ++ 2002-03-11 lpd Corrected argument list for main(), and added int return ++ type, in test program and T value program. ++ 2002-02-21 lpd Added missing #include in test program. ++ 2000-07-03 lpd Patched to eliminate warnings about "constant is ++ unsigned in ANSI C, signed in traditional"; made test program ++ self-checking. ++ 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. ++ 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). ++ 1999-05-03 lpd Original version. ++ */ ++ ++#include "md5.h" ++#include ++ ++#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ ++#ifdef ARCH_IS_BIG_ENDIAN ++# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1) ++#else ++# define BYTE_ORDER 0 ++#endif ++ ++#define T_MASK ((md5_word_t)~0) ++#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) ++#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) ++#define T3 0x242070db ++#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) ++#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) ++#define T6 0x4787c62a ++#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) ++#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) ++#define T9 0x698098d8 ++#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) ++#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) ++#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) ++#define T13 0x6b901122 ++#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) ++#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) ++#define T16 0x49b40821 ++#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) ++#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) ++#define T19 0x265e5a51 ++#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) ++#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) ++#define T22 0x02441453 ++#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) ++#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) ++#define T25 0x21e1cde6 ++#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) ++#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) ++#define T28 0x455a14ed ++#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) ++#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) ++#define T31 0x676f02d9 ++#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) ++#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) ++#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) ++#define T35 0x6d9d6122 ++#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) ++#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) ++#define T38 0x4bdecfa9 ++#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) ++#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) ++#define T41 0x289b7ec6 ++#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) ++#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) ++#define T44 0x04881d05 ++#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) ++#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) ++#define T47 0x1fa27cf8 ++#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) ++#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) ++#define T50 0x432aff97 ++#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) ++#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) ++#define T53 0x655b59c3 ++#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) ++#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) ++#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) ++#define T57 0x6fa87e4f ++#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) ++#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) ++#define T60 0x4e0811a1 ++#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) ++#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) ++#define T63 0x2ad7d2bb ++#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) ++ ++ ++static void ++md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) ++{ ++ md5_word_t ++ a = pms->abcd[0], b = pms->abcd[1], ++ c = pms->abcd[2], d = pms->abcd[3]; ++ md5_word_t t; ++#if BYTE_ORDER > 0 ++ /* Define storage only for big-endian CPUs. */ ++ md5_word_t X[16]; ++#else ++ /* Define storage for little-endian or both types of CPUs. */ ++ md5_word_t xbuf[16]; ++ const md5_word_t *X; ++#endif ++ ++ { ++#if BYTE_ORDER == 0 ++ /* ++ * Determine dynamically whether this is a big-endian or ++ * little-endian machine, since we can use a more efficient ++ * algorithm on the latter. ++ */ ++ static const int w = 1; ++ ++ if (*((const md5_byte_t *)&w)) /* dynamic little-endian */ ++#endif ++#if BYTE_ORDER <= 0 /* little-endian */ ++ { ++ /* ++ * On little-endian machines, we can process properly aligned ++ * data without copying it. ++ */ ++ if (!((data - (const md5_byte_t *)0) & 3)) { ++ /* data are properly aligned */ ++ X = (const md5_word_t *)data; ++ } else { ++ /* not aligned */ ++ memcpy(xbuf, data, 64); ++ X = xbuf; ++ } ++ } ++#endif ++#if BYTE_ORDER == 0 ++ else /* dynamic big-endian */ ++#endif ++#if BYTE_ORDER >= 0 /* big-endian */ ++ { ++ /* ++ * On big-endian machines, we must arrange the bytes in the ++ * right order. ++ */ ++ const md5_byte_t *xp = data; ++ int i; ++ ++# if BYTE_ORDER == 0 ++ X = xbuf; /* (dynamic only) */ ++# else ++# define xbuf X /* (static only) */ ++# endif ++ for (i = 0; i < 16; ++i, xp += 4) ++ xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); ++ } ++#endif ++ } ++ ++#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) ++ ++ /* Round 1. */ ++ /* Let [abcd k s i] denote the operation ++ a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ ++#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) ++#define SET(a, b, c, d, k, s, Ti)\ ++ t = a + F(b,c,d) + X[k] + Ti;\ ++ a = ROTATE_LEFT(t, s) + b ++ /* Do the following 16 operations. */ ++ SET(a, b, c, d, 0, 7, T1); ++ SET(d, a, b, c, 1, 12, T2); ++ SET(c, d, a, b, 2, 17, T3); ++ SET(b, c, d, a, 3, 22, T4); ++ SET(a, b, c, d, 4, 7, T5); ++ SET(d, a, b, c, 5, 12, T6); ++ SET(c, d, a, b, 6, 17, T7); ++ SET(b, c, d, a, 7, 22, T8); ++ SET(a, b, c, d, 8, 7, T9); ++ SET(d, a, b, c, 9, 12, T10); ++ SET(c, d, a, b, 10, 17, T11); ++ SET(b, c, d, a, 11, 22, T12); ++ SET(a, b, c, d, 12, 7, T13); ++ SET(d, a, b, c, 13, 12, T14); ++ SET(c, d, a, b, 14, 17, T15); ++ SET(b, c, d, a, 15, 22, T16); ++#undef SET ++ ++ /* Round 2. */ ++ /* Let [abcd k s i] denote the operation ++ a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ ++#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) ++#define SET(a, b, c, d, k, s, Ti)\ ++ t = a + G(b,c,d) + X[k] + Ti;\ ++ a = ROTATE_LEFT(t, s) + b ++ /* Do the following 16 operations. */ ++ SET(a, b, c, d, 1, 5, T17); ++ SET(d, a, b, c, 6, 9, T18); ++ SET(c, d, a, b, 11, 14, T19); ++ SET(b, c, d, a, 0, 20, T20); ++ SET(a, b, c, d, 5, 5, T21); ++ SET(d, a, b, c, 10, 9, T22); ++ SET(c, d, a, b, 15, 14, T23); ++ SET(b, c, d, a, 4, 20, T24); ++ SET(a, b, c, d, 9, 5, T25); ++ SET(d, a, b, c, 14, 9, T26); ++ SET(c, d, a, b, 3, 14, T27); ++ SET(b, c, d, a, 8, 20, T28); ++ SET(a, b, c, d, 13, 5, T29); ++ SET(d, a, b, c, 2, 9, T30); ++ SET(c, d, a, b, 7, 14, T31); ++ SET(b, c, d, a, 12, 20, T32); ++#undef SET ++ ++ /* Round 3. */ ++ /* Let [abcd k s t] denote the operation ++ a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ ++#define H(x, y, z) ((x) ^ (y) ^ (z)) ++#define SET(a, b, c, d, k, s, Ti)\ ++ t = a + H(b,c,d) + X[k] + Ti;\ ++ a = ROTATE_LEFT(t, s) + b ++ /* Do the following 16 operations. */ ++ SET(a, b, c, d, 5, 4, T33); ++ SET(d, a, b, c, 8, 11, T34); ++ SET(c, d, a, b, 11, 16, T35); ++ SET(b, c, d, a, 14, 23, T36); ++ SET(a, b, c, d, 1, 4, T37); ++ SET(d, a, b, c, 4, 11, T38); ++ SET(c, d, a, b, 7, 16, T39); ++ SET(b, c, d, a, 10, 23, T40); ++ SET(a, b, c, d, 13, 4, T41); ++ SET(d, a, b, c, 0, 11, T42); ++ SET(c, d, a, b, 3, 16, T43); ++ SET(b, c, d, a, 6, 23, T44); ++ SET(a, b, c, d, 9, 4, T45); ++ SET(d, a, b, c, 12, 11, T46); ++ SET(c, d, a, b, 15, 16, T47); ++ SET(b, c, d, a, 2, 23, T48); ++#undef SET ++ ++ /* Round 4. */ ++ /* Let [abcd k s t] denote the operation ++ a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ ++#define I(x, y, z) ((y) ^ ((x) | ~(z))) ++#define SET(a, b, c, d, k, s, Ti)\ ++ t = a + I(b,c,d) + X[k] + Ti;\ ++ a = ROTATE_LEFT(t, s) + b ++ /* Do the following 16 operations. */ ++ SET(a, b, c, d, 0, 6, T49); ++ SET(d, a, b, c, 7, 10, T50); ++ SET(c, d, a, b, 14, 15, T51); ++ SET(b, c, d, a, 5, 21, T52); ++ SET(a, b, c, d, 12, 6, T53); ++ SET(d, a, b, c, 3, 10, T54); ++ SET(c, d, a, b, 10, 15, T55); ++ SET(b, c, d, a, 1, 21, T56); ++ SET(a, b, c, d, 8, 6, T57); ++ SET(d, a, b, c, 15, 10, T58); ++ SET(c, d, a, b, 6, 15, T59); ++ SET(b, c, d, a, 13, 21, T60); ++ SET(a, b, c, d, 4, 6, T61); ++ SET(d, a, b, c, 11, 10, T62); ++ SET(c, d, a, b, 2, 15, T63); ++ SET(b, c, d, a, 9, 21, T64); ++#undef SET ++ ++ /* Then perform the following additions. (That is increment each ++ of the four registers by the value it had before this block ++ was started.) */ ++ pms->abcd[0] += a; ++ pms->abcd[1] += b; ++ pms->abcd[2] += c; ++ pms->abcd[3] += d; ++} ++ ++void ++md5_init(md5_state_t *pms) ++{ ++ pms->count[0] = pms->count[1] = 0; ++ pms->abcd[0] = 0x67452301; ++ pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; ++ pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; ++ pms->abcd[3] = 0x10325476; ++} ++ ++void ++md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) ++{ ++ const md5_byte_t *p = data; ++ int left = nbytes; ++ int offset = (pms->count[0] >> 3) & 63; ++ md5_word_t nbits = (md5_word_t)(nbytes << 3); ++ ++ if (nbytes <= 0) ++ return; ++ ++ /* Update the message length. */ ++ pms->count[1] += nbytes >> 29; ++ pms->count[0] += nbits; ++ if (pms->count[0] < nbits) ++ pms->count[1]++; ++ ++ /* Process an initial partial block. */ ++ if (offset) { ++ int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); ++ ++ memcpy(pms->buf + offset, p, copy); ++ if (offset + copy < 64) ++ return; ++ p += copy; ++ left -= copy; ++ md5_process(pms, pms->buf); ++ } ++ ++ /* Process full blocks. */ ++ for (; left >= 64; p += 64, left -= 64) ++ md5_process(pms, p); ++ ++ /* Process a final partial block. */ ++ if (left) ++ memcpy(pms->buf, p, left); ++} ++ ++void ++md5_finish(md5_state_t *pms, md5_byte_t digest[16]) ++{ ++ static const md5_byte_t pad[64] = { ++ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ++ }; ++ md5_byte_t data[8]; ++ int i; ++ ++ /* Save the length before padding. */ ++ for (i = 0; i < 8; ++i) ++ data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); ++ /* Pad to 56 bytes mod 64. */ ++ md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); ++ /* Append the length. */ ++ md5_append(pms, data, 8); ++ for (i = 0; i < 16; ++i) ++ digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); ++} +diff -Nbur lua-5.1.4.orig/src/md5.h lua-5.1.4/src/md5.h +--- lua-5.1.4.orig/src/md5.h 1970-01-01 01:00:00.000000000 +0100 ++++ lua-5.1.4/src/md5.h 2009-04-10 23:07:56.000000000 +0200 +@@ -0,0 +1,91 @@ ++/* ++ Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. ++ ++ This software is provided 'as-is', without any express or implied ++ warranty. In no event will the authors be held liable for any damages ++ arising from the use of this software. ++ ++ Permission is granted to anyone to use this software for any purpose, ++ including commercial applications, and to alter it and redistribute it ++ freely, subject to the following restrictions: ++ ++ 1. The origin of this software must not be misrepresented; you must not ++ claim that you wrote the original software. If you use this software ++ in a product, an acknowledgment in the product documentation would be ++ appreciated but is not required. ++ 2. Altered source versions must be plainly marked as such, and must not be ++ misrepresented as being the original software. ++ 3. This notice may not be removed or altered from any source distribution. ++ ++ L. Peter Deutsch ++ ghost@aladdin.com ++ ++ */ ++/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */ ++/* ++ Independent implementation of MD5 (RFC 1321). ++ ++ This code implements the MD5 Algorithm defined in RFC 1321, whose ++ text is available at ++ http://www.ietf.org/rfc/rfc1321.txt ++ The code is derived from the text of the RFC, including the test suite ++ (section A.5) but excluding the rest of Appendix A. It does not include ++ any code or documentation that is identified in the RFC as being ++ copyrighted. ++ ++ The original and principal author of md5.h is L. Peter Deutsch ++ . Other authors are noted in the change history ++ that follows (in reverse chronological order): ++ ++ 2002-04-13 lpd Removed support for non-ANSI compilers; removed ++ references to Ghostscript; clarified derivation from RFC 1321; ++ now handles byte order either statically or dynamically. ++ 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. ++ 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); ++ added conditionalization for C++ compilation from Martin ++ Purschke . ++ 1999-05-03 lpd Original version. ++ */ ++ ++#ifndef md5_INCLUDED ++# define md5_INCLUDED ++ ++/* ++ * This package supports both compile-time and run-time determination of CPU ++ * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be ++ * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is ++ * defined as non-zero, the code will be compiled to run only on big-endian ++ * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to ++ * run on either big- or little-endian CPUs, but will run slightly less ++ * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. ++ */ ++ ++typedef unsigned char md5_byte_t; /* 8-bit byte */ ++typedef unsigned int md5_word_t; /* 32-bit word */ ++ ++/* Define the state of the MD5 Algorithm. */ ++typedef struct md5_state_s { ++ md5_word_t count[2]; /* message length in bits, lsw first */ ++ md5_word_t abcd[4]; /* digest buffer */ ++ md5_byte_t buf[64]; /* accumulate block */ ++} md5_state_t; ++ ++#ifdef __cplusplus ++extern "C" ++{ ++#endif ++ ++/* Initialize the algorithm. */ ++void md5_init(md5_state_t *pms); ++ ++/* Append a string to the message. */ ++void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); ++ ++/* Finish the message and return the digest. */ ++void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); ++ ++#ifdef __cplusplus ++} /* end extern "C" */ ++#endif ++ ++#endif /* md5_INCLUDED */