contrib/lar: add lar support patch for openwrt lua
[project/luci.git] / contrib / lar / openwrt / 050-lar-source-loader.patch
1 diff -Nurb lua-5.1.4.orig/src/Makefile lua-5.1.4/src/Makefile
2 --- lua-5.1.4.orig/src/Makefile 2009-04-06 21:36:52.000000000 +0200
3 +++ lua-5.1.4/src/Makefile      2009-04-06 23:04:42.000000000 +0200
4 @@ -28,7 +28,7 @@
5         lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o  \
6         lundump.o lvm.o lzio.o lnum.o
7  LIB_O= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \
8 -       lstrlib.o loadlib.o linit.o
9 +       lstrlib.o loadlib.o linit.o lar.o
10  
11  LUA_T= lua
12  LUA_O= lua.o
13 diff -Nurb lua-5.1.4.orig/src/lar.c lua-5.1.4/src/lar.c
14 --- lua-5.1.4.orig/src/lar.c    1970-01-01 01:00:00.000000000 +0100
15 +++ lua-5.1.4/src/lar.c 2009-04-07 00:35:55.000000000 +0200
16 @@ -0,0 +1,243 @@
17 +#include "lar.h"
18 +
19 +int lar_read32( int fd, uint32_t *val )
20 +{
21 +       uint8_t buffer[5];
22 +
23 +       if( read(fd, buffer, 4) < 4 )
24 +               LAR_DIE("Unexpected EOF while reading data");
25 +
26 +       buffer[4] = 0;
27 +       *val = ntohl(*((uint32_t *) buffer));
28 +
29 +       return 0;
30 +}
31 +
32 +int lar_read16( int fd, uint16_t *val )
33 +{
34 +       uint8_t buffer[3];
35 +
36 +       if( read(fd, buffer, 2) < 2 )
37 +               LAR_DIE("Unexpected EOF while reading data");
38 +
39 +       buffer[2] = 0;
40 +       *val = ntohs(*((uint16_t *) buffer));
41 +
42 +       return 0;
43 +}
44 +
45 +lar_index * lar_get_index( lar_archive *ar )
46 +{
47 +       uint32_t i;
48 +       uint32_t idx_offset;
49 +       uint32_t idx_length;
50 +       lar_index *idx_map, *idx_ptr;
51 +
52 +       if( lseek(ar->fd, -(sizeof(idx_offset)), SEEK_END) == -1 )
53 +               LAR_DIE("Unable to seek to end of archive");
54 +
55 +       lar_read32(ar->fd, &idx_offset);
56 +       idx_length = ( ar->length - idx_offset - sizeof(idx_offset) );
57 +
58 +       if( lseek(ar->fd, idx_offset, SEEK_SET) == -1 )
59 +               LAR_DIE("Unable to seek to archive index");
60 +
61 +
62 +       idx_map = NULL;
63 +
64 +       for( i = 0; i < idx_length; \
65 +               i += (sizeof(lar_index) - sizeof(char *))
66 +       ) {
67 +               idx_ptr = (lar_index *)malloc(sizeof(lar_index));
68 +
69 +               lar_read32(ar->fd, &idx_ptr->noffset);
70 +               lar_read32(ar->fd, &idx_ptr->nlength);
71 +               lar_read32(ar->fd, &idx_ptr->foffset);
72 +               lar_read32(ar->fd, &idx_ptr->flength);
73 +               lar_read16(ar->fd, &idx_ptr->type);
74 +               lar_read16(ar->fd, &idx_ptr->flags);
75 +
76 +               idx_ptr->next = idx_map;
77 +               idx_map = idx_ptr;
78 +       }
79 +
80 +       return idx_map;
81 +}
82 +
83 +uint32_t lar_get_filename( lar_archive *ar,
84 +       lar_index *idx_ptr, char *filename
85 +) {
86 +       if( idx_ptr->nlength >= LAR_FNAME_BUFFER )
87 +               LAR_DIE("Filename exceeds maximum allowed length");
88 +
89 +       if( lseek(ar->fd, idx_ptr->noffset, SEEK_SET) == -1 )
90 +               LAR_DIE("Unexpected EOF while seeking filename");
91 +
92 +       if( read(ar->fd, filename, idx_ptr->nlength) < idx_ptr->nlength )
93 +               LAR_DIE("Unexpected EOF while reading filename");
94 +
95 +       filename[idx_ptr->nlength] = 0;
96 +
97 +       return idx_ptr->nlength;
98 +}
99 +
100 +lar_member * lar_open_member( lar_archive *ar, const char *name )
101 +{
102 +       lar_index *idx_ptr = ar->index;
103 +       lar_member *member;
104 +       char memberfile[LAR_FNAME_BUFFER];
105 +       char *memberdata;
106 +       size_t pgsz  = getpagesize();
107 +
108 +       while(idx_ptr)
109 +       {
110 +               lar_get_filename(ar, idx_ptr, memberfile);
111 +
112 +               if( !strncmp(memberfile, name, idx_ptr->nlength) )
113 +               {
114 +                       memberdata = mmap(
115 +                               0, idx_ptr->flength + ( idx_ptr->foffset % pgsz ),
116 +                               PROT_READ, MAP_PRIVATE, ar->fd,
117 +                               idx_ptr->foffset - ( idx_ptr->foffset % pgsz )
118 +                       );
119 +
120 +                       if( memberdata == MAP_FAILED )
121 +                               LAR_DIE("Failed to mmap() member data");
122 +
123 +                       member = (lar_member *)malloc(sizeof(lar_member));
124 +                       member->type   = idx_ptr->type;
125 +                       member->flags  = idx_ptr->flags;
126 +                       member->length = idx_ptr->flength;
127 +                       member->data   = &memberdata[idx_ptr->foffset % pgsz];
128 +
129 +                       member->mmap   = memberdata;
130 +                       member->mlen   = idx_ptr->flength + ( idx_ptr->foffset % pgsz );
131 +
132 +                       return member;
133 +               }
134 +
135 +               idx_ptr = idx_ptr->next;
136 +       }
137 +
138 +       return NULL;
139 +}
140 +
141 +int lar_close_member( lar_member *member )
142 +{
143 +       int stat = munmap(member->mmap, member->mlen);
144 +       free(member);
145 +
146 +       return stat;
147 +}
148 +
149 +lar_archive * lar_open( const char *filename )
150 +{
151 +       int fd;
152 +       struct stat as;
153 +       lar_archive *ar;
154 +
155 +       if( stat(filename, &as) == -1 )
156 +               return NULL;
157 +
158 +       if( !(as.st_mode & S_IFREG) )
159 +               return NULL;
160 +
161 +       if( (fd = open(filename, O_RDONLY)) != -1 )
162 +       {
163 +               ar = (lar_archive *)malloc(sizeof(lar_archive));
164 +               ar->fd       = fd;
165 +               ar->length   = as.st_size;
166 +               ar->index    = lar_get_index(ar);
167 +               strncpy(ar->filename, filename, sizeof(ar->filename));
168 +
169 +               return ar;
170 +       }
171 +
172 +       return NULL;
173 +}
174 +
175 +int lar_close( lar_archive *ar )
176 +{
177 +       lar_index *idx_head;
178 +       lar_index *idx_next;
179 +
180 +       close(ar->fd);
181 +
182 +       idx_head = ar->index;
183 +       do {
184 +               idx_next = idx_head->next;
185 +               free(idx_head);
186 +       } while( (idx_head = idx_next) != NULL );
187 +
188 +       free(ar);
189 +
190 +       return 0;
191 +}
192 +
193 +lar_archive * lar_find_archive( const char *package, const char *path )
194 +{
195 +       int seg = 1;
196 +       int len = 0;
197 +       int pln = 0;
198 +       int i, j;
199 +       struct stat s;
200 +       LAR_FNAME(buffer);
201 +
202 +       if( path )
203 +       {
204 +               for( pln = 0; path[pln] != '\0'; pln++ )
205 +                       if( pln >= (sizeof(buffer) - 5) )
206 +                               LAR_DIE("Library path exceeds maximum allowed length");
207 +
208 +               memcpy(buffer, path, pln);
209 +       }
210 +
211 +       for( len = 0; package[len] != '\0'; len++ )
212 +       {
213 +               if( len >= (sizeof(buffer) - 5 - pln) )
214 +                       LAR_DIE("Package name exceeds maximum allowed length");
215 +
216 +               if( package[len] == '.' ) seg++;
217 +       }
218 +
219 +       while( seg > 0 )
220 +       {
221 +               for( i = 0, j = 1; (i < len) && (j <= seg); i++ )
222 +               {
223 +                       if( package[i] == '.' ) {
224 +                               if( j < seg ) j++; else break;
225 +                       }
226 +
227 +                       buffer[pln+i] = ( package[i] == '.' ) ? LAR_DIRSEP : package[i];
228 +               }
229 +
230 +               buffer[pln+i+0] = '.'; buffer[pln+i+1] = 'l'; buffer[pln+i+2] = 'a';
231 +               buffer[pln+i+3] = 'r'; buffer[pln+i+4] = '\0';
232 +
233 +               if( (stat(buffer, &s) > -1) && (s.st_mode & S_IFREG) )
234 +                       return lar_open(buffer);
235 +
236 +               seg--;
237 +       }
238 +
239 +       return NULL;
240 +}
241 +
242 +lar_member * lar_find_member( lar_archive *ar, const char *package )
243 +{
244 +       int len;
245 +       LAR_FNAME(buffer);
246 +
247 +       for( len = 0; package[len] != '\0'; len++ )
248 +       {
249 +               if( len >= (sizeof(buffer) - 5) )
250 +                       LAR_DIE("Package name exceeds maximum allowed length");
251 +
252 +               buffer[len] = ( package[len] == '.' ) ? '/' : package[len];
253 +       }
254 +
255 +       buffer[len+0] = '.'; buffer[len+1] = 'l'; buffer[len+2] = 'u';
256 +       buffer[len+3] = 'a'; buffer[len+4] = '\0';
257 +
258 +       return lar_open_member(ar, buffer);
259 +}
260 diff -Nurb lua-5.1.4.orig/src/lar.h lua-5.1.4/src/lar.h
261 --- lua-5.1.4.orig/src/lar.h    1970-01-01 01:00:00.000000000 +0100
262 +++ lua-5.1.4/src/lar.h 2009-04-06 23:06:31.000000000 +0200
263 @@ -0,0 +1,88 @@
264 +#ifndef __LAR_H
265 +#define __LAR_H
266 +
267 +#include <stdio.h>
268 +#include <stdlib.h>
269 +#include <unistd.h>
270 +#include <stdint.h>
271 +#include <fcntl.h>
272 +#include <string.h>
273 +#include <errno.h>
274 +#include <arpa/inet.h>
275 +#include <sys/types.h>
276 +#include <sys/mman.h>
277 +#include <sys/stat.h>
278 +
279 +
280 +#define LAR_DIE(s) \
281 +       do { \
282 +               fprintf(stderr, "%s(%i): %s(): %s\n", \
283 +                       __FILE__, __LINE__, __FUNCTION__, s); \
284 +               if( errno ) fprintf(stderr, "%s(%i): %s\n", \
285 +                       __FILE__, __LINE__, strerror(errno) ); \
286 +               exit(1); \
287 +       } while(0)
288 +
289 +
290 +#define LAR_FNAME_BUFFER 1024
291 +#define LAR_FNAME(s) char s[LAR_FNAME_BUFFER]
292 +
293 +#ifdef __WIN32__
294 +#define LAR_DIRSEP     '\\'
295 +#else
296 +#define LAR_DIRSEP     '/'
297 +#endif
298 +
299 +
300 +struct lar_index_item {
301 +       uint32_t noffset;
302 +       uint32_t nlength;
303 +       uint32_t foffset;
304 +       uint32_t flength;
305 +       uint16_t type;
306 +       uint16_t flags;
307 +       struct lar_index_item *next;
308 +};
309 +
310 +struct lar_member_item {
311 +       uint16_t type;
312 +       uint16_t flags;
313 +       uint32_t length;
314 +       char *data;
315 +       char *mmap;
316 +       size_t mlen;
317 +};
318 +
319 +struct lar_archive_handle {
320 +       int fd;
321 +       off_t length;
322 +       char filename[LAR_FNAME_BUFFER];
323 +       struct lar_index_item *index;
324 +};
325 +
326 +typedef struct lar_index_item lar_index;
327 +typedef struct lar_member_item lar_member;
328 +typedef struct lar_archive_handle lar_archive;
329 +
330 +
331 +int lar_read32( int fd, uint32_t *val );
332 +int lar_read16( int fd, uint16_t *val );
333 +
334 +lar_index * lar_get_index( lar_archive *ar );
335 +
336 +uint32_t lar_get_filename( lar_archive *ar,
337 +       lar_index *idx_ptr, char *filename );
338 +
339 +lar_member * lar_open_member( lar_archive *ar, const char *name );
340 +
341 +int lar_close_member( lar_member *member );
342 +
343 +lar_archive * lar_open( const char *filename );
344 +
345 +int lar_close( lar_archive *ar );
346 +
347 +lar_archive * lar_find_archive( const char *package, const char *path );
348 +
349 +lar_member * lar_find_member( lar_archive *ar, const char *package );
350 +
351 +#endif
352 diff -Nurb lua-5.1.4.orig/src/loadlib.c lua-5.1.4/src/loadlib.c
353 --- lua-5.1.4.orig/src/loadlib.c        2009-04-06 21:36:52.000000000 +0200
354 +++ lua-5.1.4/src/loadlib.c     2009-04-07 01:55:21.000000000 +0200
355 @@ -21,6 +21,7 @@
356  #include "lauxlib.h"
357  #include "lualib.h"
358  
359 +#include "lar.h"
360  
361  /* prefix for open functions in C libraries */
362  #define LUA_POF                "luaopen_"
363 @@ -388,6 +389,36 @@
364  }
365  
366  
367 +static int loader_Lar (lua_State *L) {
368 +  lar_archive *ar;
369 +  lar_member  *mb;
370 +  const char  *name = luaL_checkstring(L, 1);
371 +
372 +  if( (ar = lar_find_archive(name, "./"))     ||
373 +      (ar = lar_find_archive(name, LUA_LDIR)) ||
374 +      (ar = lar_find_archive(name, LUA_CDIR))
375 +  ) {
376 +    if( (mb = lar_find_member(ar, name)) != NULL ) {
377 +      if( luaL_loadbuffer(L, mb->data, mb->length, ar->filename) != 0 ) {
378 +        luaL_error(L, "error while loading lar member '%s':\n\t%s",
379 +          name, lua_tostring(L, -1));
380 +      }
381 +      lar_close_member(mb);
382 +    }
383 +    else {
384 +      lua_pushfstring(L, "\n\tno matching lar member " LUA_QS " in " LUA_QS,
385 +        name, ar->filename);
386 +    }
387 +    lar_close(ar);
388 +  }
389 +  else {
390 +    lua_pushfstring(L, "\n\tno matching lar archive for " LUA_QS, name);
391 +  }
392 +
393 +  return 1;
394 +}
395 +
396 +
397  static const char *mkfuncname (lua_State *L, const char *modname) {
398    const char *funcname;
399    const char *mark = strchr(modname, *LUA_IGMARK);
400 @@ -621,7 +652,7 @@
401  
402  
403  static const lua_CFunction loaders[] =
404 -  {loader_preload, loader_Lua, loader_C, loader_Croot, NULL};
405 +  {loader_preload, loader_Lua, loader_Lar, loader_C, loader_Croot, NULL};
406  
407  
408  LUALIB_API int luaopen_package (lua_State *L) {