rpm  5.4.15
rpmluaext.c
Go to the documentation of this file.
1 
5 #if defined(RPM_VENDOR_OPENPKG) || defined(RPM_LUA_EXTENSIONS_BASED_ON_RPMLIB) /* rpm-lua-extensions-based-on-rpm-lib-functionality */
6 
7 #include "system.h"
8 
9 #ifdef WITH_LUA
10 
11 #define _MIRE_INTERNAL
12 #include <rpmio_internal.h>
13 #include <rpmiotypes.h>
14 #include <rpmlog.h>
15 #include <rpmmacro.h>
16 #include <argv.h>
17 
18 #include <rpmtag.h>
19 #include <rpmtypes.h>
20 
21 #include <rpmds.h>
22 
23 #define _RPMLUA_INTERNAL
24 #include <rpmlua.h>
25 #include <rpmluaext.h>
26 
27 #include <lua.h>
28 #include <lualib.h>
29 #include <lauxlib.h>
30 
31 #include <rpmcli.h>
32 
33 #include "debug.h"
34 
35 /* RPM Lua function:
36  * <result> = rpm.vercmp(
37  * <version1> -- first version (e.g. "N.N.N")
38  * <version2> -- second version (e.g. "N.N.N")
39  * )
40  */
41 static int rpmluaext_vercmp(lua_State *L)
42 {
43  const char *version1;
44  const char *version2;
45  int rc;
46 
47  /* fetch arguments */
48  if (lua_isstring(L, 1))
49  version1 = lua_tostring(L, 1);
50  else {
51  (void)luaL_argerror(L, 1, "first version string");
52  return 0;
53  }
54  if (lua_isstring(L, 2))
55  version2 = lua_tostring(L, 2);
56  else {
57  (void)luaL_argerror(L, 2, "second version string");
58  return 0;
59  }
60 
61  /* compare versions */
62  rc = rpmvercmp(version1, version2);
63 
64  /* provide results */
65  lua_pushinteger(L, rc);
66  return 1;
67 }
68 
69 /* RPM Lua function:
70  * <digest> = rpm.digest(
71  * <type>, -- digest algorithm type ("md5", "sha1", etc)
72  * <data-file> -- file to calculate digest for
73  * )
74  */
75 static int rpmluaext_digest(lua_State *L)
76 {
77  const char *filename;
78  pgpHashAlgo algo;
79  FD_t fd;
80  const char *digest = NULL;
81  size_t digest_len = 0;
82  DIGEST_CTX ctx;
83  char buf[8 * BUFSIZ];
84  size_t nb;
85 
86  /* fetch arguments */
87  if (lua_isstring(L, 1)) {
88  if ((algo = pgpHashAlgoStringToNumber(lua_tostring(L, 1), 0)) == PGPHASHALGO_ERROR) {
89  (void)luaL_argerror(L, 1, "digest type");
90  return 0;
91  }
92  }
93  else {
94  (void)luaL_argerror(L, 1, "digest type");
95  return 0;
96  }
97  if (lua_isstring(L, 2))
98  filename = lua_tostring(L, 2);
99  else {
100  (void)luaL_argerror(L, 2, "data file");
101  return 0;
102  }
103 
104  /* open file */
105  fd = Fopen(filename, "r.fdio");
106  if (fd == NULL || Ferror(fd)) {
107  luaL_error(L, "failed to create transaction");
108  return 0;
109  }
110 
111  /* read file and calculate digest */
112  ctx = rpmDigestInit(algo, RPMDIGEST_NONE);
113  while ((nb = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
114  rpmDigestUpdate(ctx, buf, nb);
115  rpmDigestFinal(ctx, &digest, &digest_len, 1);
116  if (digest == NULL || digest[0] == '\0') {
117  luaL_error(L, "failed to calculate digest");
118  return 0;
119  }
120 
121  /* close file */
122  (void)Fclose(fd);
123 
124  /* provide results */
125  lua_pushstring(L, digest);
126  return 1;
127 }
128 
129 /* RPM Lua function:
130  * <ok> = rpm.signature(
131  * <data-file>, -- file to check signature on
132  * <detached-signature-file>, -- file to contain detached signature (or "nil" for clearsigning)
133  * <public-key-file>, -- file containing the signing public key (or "nil" to consult RPMDB)
134  * <public-key-fingerprint> -- fingerprint of signing public key (or "nil" to accept any signing key)
135  * )
136  */
137 static int rpmluaext_signature(lua_State *L)
138 {
139  rpmts ts;
140  rpmRC rc;
141  const char *fn_data;
142  const char *fn_sig;
143  const char *fn_pkey;
144  const char *fp;
145 
146  /* fetch arguments */
147  if (lua_isstring(L, 1))
148  fn_data = lua_tostring(L, 1);
149  else {
150  (void)luaL_argerror(L, 1, "filename of data file");
151  return 0;
152  }
153  if (lua_isstring(L, 2))
154  fn_sig = lua_tostring(L, 2);
155  else
156  fn_sig = NULL;
157  if (lua_isstring(L, 3))
158  fn_pkey = lua_tostring(L, 3);
159  else
160  fn_pkey = NULL;
161  if (lua_isstring(L, 4))
162  fp = lua_tostring(L, 4);
163  else
164  fp = NULL;
165 
166  /* create RPM transaction and open RPM database */
167  if ((ts = rpmtsCreate()) == NULL) {
168  luaL_error(L, "failed to create transaction");
169  return 0;
170  }
171  rpmtsOpenDB(ts, O_RDONLY);
172 
173  /* check signature on integrity specification file */
174  rc = rpmnsProbeSignature(ts, fn_data, fn_sig, fn_pkey, fp, 0);
175 
176  /* destroy transaction */
177  (void)rpmtsFree(ts);
178  ts = NULL;
179 
180  /* provide results */
181  lua_pushboolean(L, rc == RPMRC_OK);
182  return 1;
183 }
184 
185 /* callback for converting rpmlog() output into Lua result table */
186 static int rpmluaext_query_cb(rpmlogRec rec, rpmlogCallbackData data)
187 {
188  lua_State *L = (lua_State *)data;
189  size_t n;
190 
191  if (rpmlogRecPriority(rec) & RPMLOG_NOTICE) {
192  const char *msg = rpmlogRecMessage(rec);
193  if (msg != NULL) {
194  luaL_checktype(L, -1, LUA_TTABLE);
195  n = lua_objlen(L, -1);
196  lua_pushinteger(L, n + 1);
197  lua_pushstring(L, msg);
198  lua_settable(L, -3);
199  }
200  }
201  return 0;
202 }
203 
204 /* RPM Lua function:
205  * <outputs> = rpm.query(
206  * <query-format>, -- query format (corresponds to CLI "rpm -q --qf <query-format>")
207  * <is-all-query> -- query all flag (corresponds to CLI "rpm -q -a")
208  * <query-filter> -- query filter (corresponds to CLI "rpm -q ... <query-filter>")
209  * )
210  */
211 static int rpmluaext_query(lua_State *L)
212 {
213  rpmts ts;
214  QVA_t qva;
215  const char *argv[2];
216  rpmlogCallback rpmlog_cb;
217  rpmlogCallbackData rpmlog_cb_data;
218  int ec;
219 
220  /* configure RPMDB query */
221  if ((qva = (QVA_t)malloc(sizeof(*qva))) == NULL) {
222  luaL_error(L, "failed to allocate query configuration");
223  return 0;
224  }
225  memset(qva, '\0', sizeof(*qva));
226  if (!lua_isstring(L, 1)) {
227  (void)luaL_argerror(L, 1, "query format");
228  return 0;
229  }
230  qva->qva_queryFormat = lua_tostring(L, 1);
231  qva->qva_mode = 'q';
232  qva->qva_char = ' ';
233  if (!lua_isboolean(L, 2)) {
234  (void)luaL_argerror(L, 1, "query all flag");
235  return 0;
236  }
237  if (lua_toboolean(L, 2)) {
238  qva->qva_source |= RPMQV_ALL;
239  qva->qva_sourceCount++;
240  }
241  argv[0] = NULL;
242  if (lua_isstring(L, 3)) {
243  argv[0] = lua_tostring(L, 3);
244  argv[1] = NULL;
245  }
246 
247  /* create RPM transaction and open RPM database */
248  if ((ts = rpmtsCreate()) == NULL) {
249  luaL_error(L, "failed to create transaction");
250  return 0;
251  }
252  rpmtsOpenDB(ts, O_RDONLY);
253 
254  /* intercept output channel */
255  rpmlogGetCallback(&rpmlog_cb, &rpmlog_cb_data);
256  rpmlogSetCallback(rpmluaext_query_cb, L);
257 
258  /* create result Lua table on Lua stack */
259  lua_newtable(L);
260 
261  /* perform query */
262  ec = rpmcliQuery(ts, qva, argv);
263 
264  /* restore output channel */
265  rpmlogSetCallback(rpmlog_cb, rpmlog_cb_data);
266 
267  /* destroy transaction */
268  (void)rpmtsFree(ts);
269  ts = NULL;
270 
271  return 1;
272 }
273 
274 /* RPM Lua "rpm.*" function registry */
275 static const luaL_reg rpmluaext_registry[] = {
276  { "vercmp", rpmluaext_vercmp },
277  { "digest", rpmluaext_digest },
278  { "signature", rpmluaext_signature },
279  { "query", rpmluaext_query },
280  { NULL, NULL }
281 };
282 
283 /* activate our RPM Lua extensions */
284 void rpmluaextActivate(rpmlua lua)
285 {
286  lua_pushvalue(lua->L, LUA_GLOBALSINDEX);
287  luaL_openlib(lua->L, "rpm", rpmluaext_registry, 0);
288  return;
289 }
290 
291 #endif /* WITH_LUA */
292 
293 #endif /* RPM_VENDOR_OPENPKG */
294 
int qva_sourceCount
Definition: rpmcli.h:632
const char bson_timestamp_t * ts
Definition: bson.h:1004
int rpmcliQuery(rpmts ts, QVA_t qva, const char **argv)
Display package information.
Definition: query.c:956
rpmlogCallback rpmlogSetCallback(rpmlogCallback cb, rpmlogCallbackData data)
Set rpmlog callback function.
Definition: rpmlog.c:114
FD_t Fopen(const char *path, const char *_fmode)
fopen(3) clone.
Definition: rpmio.c:2840
DIGEST_CTX rpmDigestInit(pgpHashAlgo hashalgo, rpmDigestFlags flags)
Initialize digest context.
Definition: digest.c:247
void * rpmlogCallbackData
Definition: rpmlog.h:158
int(* rpmvercmp)(const char *a, const char *b)
Segmented string compare vector.
Definition: rpmevr.c:379
enum pgpHashAlgo_e pgpHashAlgo
9.4.
rpmlogLvl rpmlogRecPriority(rpmlogRec rec)
Retrieve log priority from rpmlog record.
Definition: rpmlog.c:47
void rpmlogGetCallback(rpmlogCallback *cb, rpmlogCallbackData *data)
Get rpmlog callback function and data.
Definition: rpmlog.c:124
Command line option information.
Definition: rpmcli.h:630
Yet Another syslog(3) API clone.
int rpmDigestUpdate(DIGEST_CTX ctx, const void *data, size_t len)
Update context with next plain text buffer.
Definition: digest.c:986
rpmRC rpmnsProbeSignature(void *_ts, const char *fn, const char *sigfn, const char *pubfn, const char *pubid, int flags)
Verify OpenPGP signature on a file.
Definition: rpmns.c:329
struct rpmlogRec_s * rpmlogRec
Definition: rpmlog.h:154
const char const bson * data
Definition: mongo.h:463
int(* rpmlogCallback)(rpmlogRec rec, rpmlogCallbackData data)
Definition: rpmlog.h:168
Structure(s) used for dependency tag sets.
Digest private data.
Definition: digest.c:130
rpmQVSources qva_source
Definition: rpmcli.h:631
The FD_t File Handle data structure.
const char * qva_queryFormat
Definition: rpmcli.h:650
pgpHashAlgo pgpHashAlgoStringToNumber(const char *name, size_t name_len)
Convert a hash algorithm "foo" to the internal PGPHASHALGO_FOO number.
Definition: rpmpgp.c:1805
size_t Fread(void *buf, size_t size, size_t nmemb, FD_t fd)
fread(3) clone.
Definition: rpmio.c:2412
int Fclose(FD_t fd)
fclose(3) clone.
Definition: rpmio.c:2534
enum rpmRC_e rpmRC
RPM return codes.
int Ferror(FD_t fd)
ferror(3) clone.
Definition: rpmio.c:2951
#define L(CS)
Definition: fnmatch.c:161
rpmts rpmtsFree(rpmts ts)
Destroy transaction set, closing the database as well.
rpmts rpmtsCreate(void)
Create an empty transaction set.
Definition: rpmts.c:1470
struct rpmts_s * rpmts
The RPM Transaction Set.
Definition: rpmtypes.h:14
void rpmluaextActivate(rpmlua lua)
Add RPM library based Lua extension.
int rpmtsOpenDB(rpmts ts, int dbmode)
Open the database used by the transaction.
Definition: rpmts.c:115
struct rpmlua_s * rpmlua
Definition: rpmlua.h:53
int rpmDigestFinal(DIGEST_CTX ctx, void *datap, size_t *lenp, int asAscii)
Return digest and destroy context.
Definition: digest.c:1000
const char * rpmlogRecMessage(rpmlogRec rec)
Retrieve log message string from rpmlog record.
Definition: rpmlog.c:42