2 * lar - Lua Archive Library
4 * Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
31 static int larlib_perror( lua_State *L, const char *message )
34 lua_pushstring(L, message);
39 int larlib_open( lua_State *L )
41 lar_archive *ar, **udata;
42 const char *filename = luaL_checkstring( L, 1 );
44 if( filename != NULL && (ar = lar_open(filename)) != NULL )
46 if( (udata = lua_newuserdata(L, sizeof(lar_archive *))) != NULL )
49 luaL_getmetatable(L, "lar.archive");
50 lua_setmetatable(L, -2);
54 return luaL_error(L, "Out of memory");
59 return larlib_perror(L, "Archive not found");
65 int larlib_find( lua_State *L )
67 const char *filename = luaL_checkstring( L, 1 );
68 const char *basepath = luaL_optstring( L, 2, "./" );
69 int is_pkg = strstr(filename, "/") ? 0 : 1;
70 lar_archive *ar, **udata;
72 if( ((ar = lar_find_archive(filename, basepath, is_pkg)) != NULL) ||
73 ((ar = lar_find_archive(filename, LUA_LDIR, is_pkg)) != NULL) ||
74 ((ar = lar_find_archive(filename, LUA_CDIR, is_pkg)) != NULL) )
76 if( (udata = lua_newuserdata(L, sizeof(lar_archive *))) != NULL )
79 luaL_getmetatable(L, "lar.archive");
80 lua_setmetatable(L, -2);
84 return luaL_error(L, "Out of memory");
89 return larlib_perror(L, "Archive not found");
95 int larlib_md5( lua_State *L )
98 char md5[16], md5_hex[33];
99 const char *data = luaL_checkstring( L, 1 );
103 md5_append(&state, (const md5_byte_t *)data, strlen(data));
104 md5_finish(&state, (md5_byte_t *)md5);
106 for( i = 0; i < 16; i++ )
107 sprintf(&md5_hex[i*2], "%02x", (unsigned char)md5[i]);
109 lua_pushstring(L, md5_hex);
113 int larlib_md5_file( lua_State *L )
116 char md5[16], md5_hex[33], buffer[1024];
117 const char *filename = luaL_checkstring( L, 1 );
120 if( (fd = open(filename, O_RDONLY)) != -1 )
124 while( (len = read(fd, buffer, 1024)) > 0 )
125 md5_append(&state, (const md5_byte_t *)buffer, len);
127 md5_finish(&state, (md5_byte_t *)md5);
129 for( i = 0; i < 16; i++ )
130 sprintf(&md5_hex[i*2], "%02x", (unsigned char)md5[i]);
133 lua_pushstring(L, md5_hex);
137 return larlib_perror(L, strerror(errno));
143 static int larlib_mkpath( const char *name, const char *path, char *buffer )
145 int nlen = strlen(name);
146 int plen = strlen(path);
148 if( (nlen + plen + 1) <= LAR_FNAME_BUFFER )
150 strcpy(buffer, path);
152 if( buffer[plen-1] != '/' )
153 buffer[plen++] = '/';
155 strcpy(&buffer[plen], name);
156 buffer[plen + nlen] = '\0';
164 static int larlib__gc( lua_State *L )
166 lar_archive **archive = luaL_checkudata( L, 1, "lar.archive" );
176 static int larlib_member__open( lua_State *L, lar_member *mb )
178 lar_archive **archive = NULL;
179 const char *filename = NULL;
184 *archive = luaL_checkudata( L, 1, "lar.archive" );
185 filename = luaL_checkstring( L, 2 );
188 if( mb != NULL || (mb = lar_open_member(*archive, filename)) != NULL )
190 if( (udata = lua_newuserdata(L, sizeof(lar_member *))) != NULL )
193 luaL_getmetatable(L, "lar.member");
194 lua_setmetatable(L, -2);
198 return luaL_error(L, "Out of memory");
203 return larlib_perror(L, "Member not found in archive");
209 int larlib_member_open( lua_State *L )
211 return larlib_member__open( L, NULL );
214 int larlib_member_find( lua_State *L )
216 lar_archive **archive = luaL_checkudata( L, 1, "lar.archive" );
217 const char *package = luaL_checkstring( L, 2 );
218 lar_member *mb, **udata;
220 if( (mb = lar_find_member(*archive, package)) != NULL )
222 if( (udata = lua_newuserdata(L, sizeof(lar_member *))) != NULL )
225 luaL_getmetatable(L, "lar.member");
226 lua_setmetatable(L, -2);
230 return luaL_error(L, "Out of memory");
235 return larlib_perror(L, "Member not found in archive");
241 int larlib_member_size( lua_State *L )
243 lar_member **member = luaL_checkudata( L, 1, "lar.member" );
244 lua_pushnumber(L, (*member)->length);
248 int larlib_member_type( lua_State *L )
250 lar_member **member = luaL_checkudata( L, 1, "lar.member" );
251 lua_pushnumber(L, (*member)->type);
255 int larlib_member_flags( lua_State *L )
257 lar_member **member = luaL_checkudata( L, 1, "lar.member" );
258 lua_pushnumber(L, (*member)->flags);
262 int larlib_member_read( lua_State *L )
264 lar_member **member = luaL_checkudata( L, 1, "lar.member" );
265 int start = luaL_checknumber( L, 2 );
266 int length = luaL_optnumber( L, 3, (*member)->length );
269 if( (start >= 0) && (start < (*member)->length) && (length > 0) )
271 if( (start + length) >= (*member)->length )
272 length = (*member)->length - start;
274 if( (stringcopy = (char *)malloc(length + 1)) != NULL )
276 memcpy(stringcopy, &(*member)->data[start], length);
277 stringcopy[length] = '\0';
278 lua_pushstring(L, stringcopy);
283 return luaL_error(L, "Out of memory");
288 return larlib_perror(L, "Invalid argument");
294 int larlib_member_data( lua_State *L )
296 lar_member **member = luaL_checkudata( L, 1, "lar.member" );
297 lua_pushstring(L, (*member)->data);
301 int larlib_member_load( lua_State *L )
303 lar_member **member = luaL_checkudata( L, 1, "lar.member" );
304 int status = luaL_loadbuffer( L, (*member)->data, (*member)->length,
317 static int larlib_member__gc( lua_State *L )
319 lar_member **member = luaL_checkudata( L, 1, "lar.member" );
322 lar_close_member(*member);
329 static int larlib_mmfile__open( lua_State *L, const char *filename )
332 mmap_handle *fh, **udata;
334 if( filename == NULL )
335 filename = (const char *)luaL_checkstring( L, 1 );
337 if( (fh = (mmap_handle *)malloc(sizeof(mmap_handle))) == NULL )
338 return larlib_perror(L, "Out of memory");
340 if( stat(filename, &s) > -1 && (fh->fd = open(filename, O_RDONLY)) > -1 )
342 fh->length = s.st_size;
343 fh->data = mmap( 0, s.st_size, PROT_READ, MAP_PRIVATE, fh->fd, 0 );
345 if( fh->data == MAP_FAILED )
346 return larlib_perror(L, "Failed to mmap() file");
348 if( (udata = lua_newuserdata(L, sizeof(char *))) != NULL )
351 luaL_getmetatable(L, "lar.mmfile");
352 lua_setmetatable(L, -2);
356 return larlib_perror(L, "Out of memory");
361 return larlib_perror(L, strerror(errno));
367 int larlib_mmfile_open( lua_State *L )
369 return larlib_mmfile__open(L, NULL);
372 int larlib_mmfile_size( lua_State *L )
374 mmap_handle **fh = luaL_checkudata( L, 1, "lar.mmfile" );
375 lua_pushnumber(L, (*fh)->length);
379 int larlib_mmfile_read( lua_State *L )
381 mmap_handle **fh = luaL_checkudata( L, 1, "lar.mmfile" );
382 int start = luaL_checknumber( L, 2 );
383 int length = luaL_optnumber( L, 3, (*fh)->length );
386 if( (start >= 0) && (start < (*fh)->length) && (length > 0) )
388 if( (start + length) >= (*fh)->length )
389 length = (*fh)->length - start;
391 if( (stringcopy = (char *)malloc(length + 1)) != NULL )
393 memcpy(stringcopy, &(*fh)->data[start], length);
394 stringcopy[length] = '\0';
395 lua_pushstring(L, stringcopy);
400 return luaL_error(L, "Out of memory");
405 return larlib_perror(L, "Invalid argument");
411 int larlib_mmfile_data( lua_State *L )
413 mmap_handle **fh = luaL_checkudata( L, 1, "lar.mmfile" );
414 lua_pushstring(L, (*fh)->data);
418 int larlib_mmfile_load( lua_State *L )
420 mmap_handle **fh = luaL_checkudata( L, 1, "lar.mmfile" );
421 int status = luaL_loadbuffer(L, (*fh)->data, (*fh)->length, "=(mmap file)");
433 static int larlib_mmfile__gc( lua_State *L )
435 mmap_handle **fh = luaL_checkudata( L, 1, "lar.mmfile" );
440 munmap((*fh)->data, (*fh)->length);
449 int larlib_findfile( lua_State *L )
452 const char *filename = luaL_checkstring( L, 1 );
453 const char *basepath = luaL_optstring( L, 2, "./" );
459 const char *searchpath[3] = { basepath, LUA_LDIR, LUA_CDIR };
461 for( i = 0; i < 3; i++ )
462 if( !larlib_mkpath(filename, searchpath[i], filepath) )
463 if( stat(filepath, &s) > -1 && (s.st_mode & S_IFREG) )
464 return larlib_mmfile__open( L, filepath );
466 for( i = 0; i < 3; i++ )
467 if( (ar = lar_find_archive(filename, searchpath[i], 0)) != NULL )
468 if( (mb = lar_open_member(ar, filename)) != NULL )
469 return larlib_member__open( L, mb );
471 return larlib_perror(L, "File not found");
475 static const luaL_reg LAR_REG[] = {
476 { "open", larlib_open },
477 { "find", larlib_find },
478 { "md5", larlib_md5 },
479 { "md5_file", larlib_md5_file },
480 { "mmap", larlib_mmfile_open },
481 { "findfile", larlib_findfile },
485 static const luaL_reg LAR_ARCHIVE_REG[] = {
486 { "member", larlib_member_open },
487 { "find", larlib_member_find },
488 { "__gc", larlib__gc },
492 static const luaL_reg LAR_MEMBER_REG[] = {
493 { "size", larlib_member_size },
494 { "type", larlib_member_type },
495 { "flags", larlib_member_flags },
496 { "read", larlib_member_read },
497 { "data", larlib_member_data },
498 { "load", larlib_member_load },
499 { "__gc", larlib_member__gc },
503 static const luaL_reg LAR_MMFILE_REG[] = {
504 { "size", larlib_mmfile_size },
505 { "read", larlib_mmfile_read },
506 { "data", larlib_mmfile_data },
507 { "load", larlib_mmfile_load },
508 { "__gc", larlib_mmfile__gc },
513 LUALIB_API int luaopen_larlib( lua_State *L )
515 luaL_newmetatable(L, "lar");
516 luaL_register(L, NULL, LAR_REG);
517 lua_pushvalue(L, -1);
518 lua_setfield(L, -2, "__index");
519 lua_setglobal(L, "lar");
521 luaL_newmetatable(L, "lar.archive");
522 luaL_register(L, NULL, LAR_ARCHIVE_REG);
523 lua_pushvalue(L, -1);
524 lua_setfield(L, -2, "__index");
525 lua_setglobal(L, "lar.archive");
527 luaL_newmetatable(L, "lar.member");
528 luaL_register(L, NULL, LAR_MEMBER_REG);
529 lua_pushvalue(L, -1);
530 lua_setfield(L, -2, "__index");
531 lua_setglobal(L, "lar.member");
533 luaL_newmetatable(L, "lar.mmfile");
534 luaL_register(L, NULL, LAR_MMFILE_REG);
535 lua_pushvalue(L, -1);
536 lua_setfield(L, -2, "__index");
537 lua_setglobal(L, "lar.mmfile");