1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
#include "pow_lua.h"
#include "archive.h"
#include "archive_entry.h"
#include "lauxlib.h"
#include "stdlib.h"
#include "string.h"
int pow_lua_extract(lua_State *L) {
int r;
ssize_t size;
struct archive *a;
struct archive_entry *entry;
if (!lua_isstring(L, 1)) {
lua_pushnil(L);
lua_pushstring(L, "arg 1 must be string (src)");
return 2;
}
if (!lua_isstring(L, 2)) {
lua_pushnil(L);
lua_pushstring(L, "arg 2 must be string (dest)");
return 2;
}
const char *filename = lua_tostring(L, 1);
const char *dest = lua_tostring(L, 2);
a = archive_read_new();
archive_read_support_filter_all(a);
archive_read_support_format_all(a);
if ((r = archive_read_open_filename(a, filename, 10240))) {
return 0;
}
for (;;) {
r = archive_read_next_header(a, &entry);
if (r == ARCHIVE_EOF)
break;
if (r < ARCHIVE_OK)
printf("warn while unpacking: %s\n", archive_error_string(a));
if (r < ARCHIVE_WARN) {
printf("error while unpacking: %s\n", archive_error_string(a));
lua_pop(L, 1);
char *error_msg = malloc(256);
lua_pushnil(L);
if (!error_msg) {
lua_pushstring(L, "error while unpacking and failed to malloc to push "
"real error message");
printf("error while unpacking and failed to push real error message\n");
return 2;
}
snprintf(error_msg, 256, "error while unpacking: %s",
archive_error_string(a));
lua_pushstring(L, error_msg);
free(error_msg);
return 2;
}
const char *cur = archive_entry_pathname(entry);
if (cur) {
size_t need = strlen(dest) + strlen(cur) + 2;
char *full = malloc(need);
if (!full) {
lua_pushnil(L);
lua_pushstring(L, "failed to malloc entry path\n");
archive_read_close(a);
archive_read_free(a);
return 2;
}
snprintf(full, need, "%s/%s", dest, cur);
archive_entry_set_pathname(entry, full);
}
r = archive_read_extract(a, entry, 0);
if (r < ARCHIVE_WARN) {
lua_pushnil(L);
lua_pushfstring(
L, "failed to extract '%s': %s", archive_entry_pathname(entry),
archive_error_string(a) ? archive_error_string(a) : "unknown");
archive_read_close(a);
archive_read_free(a);
return 2;
}
}
archive_read_close(a);
archive_read_free(a);
lua_pushboolean(L, 1);
return 1;
}
luaL_Reg libpow[] = {{"extract", pow_lua_extract}, {NULL, NULL}};
int pow_lua_load(lua_State *L) {
luaL_newlib(L, libpow);
lua_setglobal(L, "pow");
return 0;
}
|