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");