File: | lib/rpmscript.c |
Warning: | line 185, column 6 Value stored to 'xx' is never read |
1 | #include "system.h" |
2 | |
3 | #include <sys/types.h> |
4 | #include <sys/wait.h> |
5 | #include <errno(*__errno_location ()).h> |
6 | #include <unistd.h> |
7 | |
8 | #include <rpm/rpmfileutil.h> |
9 | #include <rpm/rpmmacro.h> |
10 | #include <rpm/rpmio.h> |
11 | #include <rpm/rpmlog.h> |
12 | #include <rpm/header.h> |
13 | #include <rpm/rpmds.h> |
14 | |
15 | #include "rpmio/rpmlua.h" |
16 | #include "lib/rpmscript.h" |
17 | |
18 | #include "lib/rpmplugins.h" /* rpm plugins hooks */ |
19 | |
20 | #include "debug.h" |
21 | |
22 | struct scriptNextFileFunc_s { |
23 | char *(*func)(void *); /* function producing input for script */ |
24 | void *param; /* parameter for func */ |
25 | }; |
26 | |
27 | typedef struct scriptNextFileFunc_s *scriptNextFileFunc; |
28 | |
29 | struct rpmScript_s { |
30 | rpmscriptTypes type; /* script type */ |
31 | rpmTagVal tag; /* script tag */ |
32 | char **args; /* scriptlet call arguments */ |
33 | char *body; /* script body */ |
34 | char *descr; /* description for logging */ |
35 | rpmscriptFlags flags; /* flags to control operation */ |
36 | struct scriptNextFileFunc_s nextFileFunc; /* input function */ |
37 | }; |
38 | |
39 | struct scriptInfo_s { |
40 | rpmscriptTypes type; |
41 | const char *desc; |
42 | rpmsenseFlags sense; |
43 | rpmTagVal tag; |
44 | rpmTagVal progtag; |
45 | rpmTagVal flagtag; |
46 | }; |
47 | |
48 | static const struct scriptInfo_s scriptInfo[] = { |
49 | { RPMSCRIPT_PREIN, "%prein", 0, |
50 | RPMTAG_PREIN, RPMTAG_PREINPROG, RPMTAG_PREINFLAGS }, |
51 | { RPMSCRIPT_PREUN, "%preun", 0, |
52 | RPMTAG_PREUN, RPMTAG_PREUNPROG, RPMTAG_PREUNFLAGS }, |
53 | { RPMSCRIPT_POSTIN, "%post", 0, |
54 | RPMTAG_POSTIN, RPMTAG_POSTINPROG, RPMTAG_POSTINFLAGS }, |
55 | { RPMSCRIPT_POSTUN, "%postun", 0, |
56 | RPMTAG_POSTUN, RPMTAG_POSTUNPROG, RPMTAG_POSTUNFLAGS }, |
57 | { RPMSCRIPT_PRETRANS, "%pretrans", 0, |
58 | RPMTAG_PRETRANS, RPMTAG_PRETRANSPROG, RPMTAG_PRETRANSFLAGS }, |
59 | { RPMSCRIPT_POSTTRANS, "%posttrans", 0, |
60 | RPMTAG_POSTTRANS, RPMTAG_POSTTRANSPROG, RPMTAG_POSTTRANSFLAGS }, |
61 | { RPMSCRIPT_TRIGGERPREIN, "%triggerprein", RPMSENSE_TRIGGERPREIN, |
62 | RPMTAG_TRIGGERPREIN, 0, 0 }, |
63 | { RPMSCRIPT_TRIGGERUN, "%triggerun", RPMSENSE_TRIGGERUN, |
64 | RPMTAG_TRIGGERUN, 0, 0 }, |
65 | { RPMSCRIPT_TRIGGERIN, "%triggerin", RPMSENSE_TRIGGERIN, |
66 | RPMTAG_TRIGGERIN, 0, 0 }, |
67 | { RPMSCRIPT_TRIGGERPOSTUN, "%triggerpostun", RPMSENSE_TRIGGERPOSTUN, |
68 | RPMTAG_TRIGGERPOSTUN, 0, 0 }, |
69 | { RPMSCRIPT_VERIFY, "%verify", 0, |
70 | RPMTAG_VERIFYSCRIPT, RPMTAG_VERIFYSCRIPTPROG, RPMTAG_VERIFYSCRIPTFLAGS}, |
71 | { 0, "unknown", 0, |
72 | RPMTAG_NOT_FOUND, RPMTAG_NOT_FOUND, RPMTAG_NOT_FOUND } |
73 | }; |
74 | |
75 | static const struct scriptInfo_s * findTag(rpmTagVal tag) |
76 | { |
77 | const struct scriptInfo_s * si = scriptInfo; |
78 | while (si->type && si->tag != tag) |
79 | si++; |
80 | return si; |
81 | } |
82 | /** |
83 | * Run internal Lua script. |
84 | */ |
85 | static rpmRC runLuaScript(rpmPlugins plugins, ARGV_const_t prefixes, |
86 | const char *sname, rpmlogLvl lvl, FD_t scriptFd, |
87 | ARGV_t * argvp, const char *script, int arg1, int arg2, |
88 | scriptNextFileFunc nextFileFunc) |
89 | { |
90 | rpmRC rc = RPMRC_FAIL; |
91 | #ifdef WITH_LUA1 |
92 | ARGV_t argv = argvp ? *argvp : NULL((void*)0); |
93 | rpmlua lua = NULL((void*)0); /* Global state. */ |
94 | rpmluav var = rpmluavNew(); |
95 | int cwd = -1; |
96 | |
97 | rpmlog(RPMLOG_DEBUG, "%s: running <lua> scriptlet.\n", sname); |
98 | |
99 | /* Create arg variable */ |
100 | rpmluaPushTable(lua, "arg"); |
101 | rpmluavSetListMode(var, 1); |
102 | rpmluaSetNextFileFunc(nextFileFunc->func, nextFileFunc->param); |
103 | if (argv) { |
104 | char **p; |
105 | for (p = argv; *p; p++) { |
106 | rpmluavSetValue(var, RPMLUAV_STRING, *p); |
107 | rpmluaSetVar(lua, var); |
108 | } |
109 | } |
110 | if (arg1 >= 0) { |
111 | rpmluavSetValueNum(var, arg1); |
112 | rpmluaSetVar(lua, var); |
113 | } |
114 | if (arg2 >= 0) { |
115 | rpmluavSetValueNum(var, arg2); |
116 | rpmluaSetVar(lua, var); |
117 | } |
118 | rpmluaPop(lua); |
119 | |
120 | /* Lua scripts can change our cwd and umask, save and restore */ |
121 | /* XXX TODO: use cwd from chroot state to save unnecessary open here */ |
122 | cwd = open(".", O_RDONLY00); |
123 | if (cwd != -1) { |
124 | mode_t oldmask = umask(0); |
125 | umask(oldmask); |
126 | pid_t pid = getpid(); |
127 | |
128 | if (chdir("/") == 0 && rpmluaRunScript(lua, script, sname) == 0) { |
129 | rc = RPMRC_OK; |
130 | } |
131 | if (pid != getpid()) { |
132 | /* Terminate child process forked in lua scriptlet */ |
133 | rpmlog(RPMLOG_ERR, _("No exec() called after fork() in lua scriptlet\n")dcgettext ("rpm", "No exec() called after fork() in lua scriptlet\n" , 5)); |
134 | _exit(EXIT_FAILURE1); |
135 | } |
136 | /* This failing would be fatal, return something different for it... */ |
137 | if (fchdir(cwd)) { |
138 | rpmlog(RPMLOG_ERR, _("Unable to restore current directory: %m")dcgettext ("rpm", "Unable to restore current directory: %m", 5 )); |
139 | rc = RPMRC_NOTFOUND; |
140 | } |
141 | close(cwd); |
142 | umask(oldmask); |
143 | } |
144 | |
145 | rpmluaDelVar(lua, "arg"); |
146 | rpmluavFree(var); |
147 | |
148 | #else |
149 | rpmlog(lvl, _("<lua> scriptlet support not built in\n")dcgettext ("rpm", "<lua> scriptlet support not built in\n" , 5)); |
150 | #endif |
151 | |
152 | return rc; |
153 | } |
154 | |
155 | static const char * const SCRIPT_PATH = "PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin"; |
156 | |
157 | static void doScriptExec(ARGV_const_t argv, ARGV_const_t prefixes, |
158 | FD_t scriptFd, FD_t out) |
159 | { |
160 | int flag; |
161 | int fdno; |
162 | int xx; |
163 | int open_max; |
164 | |
165 | /* SIGPIPE is ignored in rpm, reset to default for the scriptlet */ |
166 | (void) signal(SIGPIPE13, SIG_DFL((__sighandler_t) 0)); |
167 | |
168 | /* XXX Force FD_CLOEXEC on all inherited fdno's. */ |
169 | open_max = sysconf(_SC_OPEN_MAX_SC_OPEN_MAX); |
170 | if (open_max == -1) { |
171 | open_max = 1024; |
172 | } |
173 | for (fdno = 3; fdno < open_max; fdno++) { |
174 | flag = fcntl(fdno, F_GETFD1); |
175 | if (flag == -1 || (flag & FD_CLOEXEC1)) |
176 | continue; |
177 | xx = fcntl(fdno, F_SETFD2, FD_CLOEXEC1); |
178 | /* XXX W2DO? debug msg for inheirited fdno w/o FD_CLOEXEC */ |
179 | } |
180 | |
181 | if (scriptFd != NULL((void*)0)) { |
182 | int sfdno = Fileno(scriptFd); |
183 | int ofdno = Fileno(out); |
184 | if (sfdno != STDERR_FILENO2) |
185 | xx = dup2(sfdno, STDERR_FILENO2); |
Value stored to 'xx' is never read | |
186 | if (ofdno != STDOUT_FILENO1) |
187 | xx = dup2(ofdno, STDOUT_FILENO1); |
188 | /* make sure we don't close stdin/stderr/stdout by mistake! */ |
189 | if (ofdno > STDERR_FILENO2 && ofdno != sfdno) |
190 | xx = Fclose (out); |
191 | if (sfdno > STDERR_FILENO2 && ofdno != sfdno) |
192 | xx = Fclose (scriptFd); |
193 | } |
194 | |
195 | { char *ipath = rpmExpand("%{_install_script_path}", NULL((void*)0)); |
196 | const char *path = SCRIPT_PATH; |
197 | |
198 | if (ipath && ipath[5] != '%') |
199 | path = ipath; |
200 | |
201 | xx = setenv("PATH", path, 1); |
202 | free(ipath); |
203 | } |
204 | |
205 | for (ARGV_const_t pf = prefixes; pf && *pf; pf++) { |
206 | char *name = NULL((void*)0); |
207 | int num = (pf - prefixes); |
208 | |
209 | rasprintf(&name, "RPM_INSTALL_PREFIX%d", num); |
210 | setenv(name, *pf, 1); |
211 | free(name); |
212 | |
213 | /* scripts might still be using the old style prefix */ |
214 | if (num == 0) { |
215 | setenv("RPM_INSTALL_PREFIX", *pf, 1); |
216 | } |
217 | } |
218 | |
219 | if (chdir("/") == 0) { |
220 | /* XXX Don't mtrace into children. */ |
221 | unsetenv("MALLOC_CHECK_"); |
222 | |
223 | if (xx == 0) { |
224 | xx = execv(argv[0], argv); |
225 | } |
226 | } |
227 | _exit(127); /* exit 127 for compatibility with bash(1) */ |
228 | } |
229 | |
230 | static char * writeScript(const char *cmd, const char *script) |
231 | { |
232 | char *fn = NULL((void*)0); |
233 | size_t slen = strlen(script); |
234 | int ok = 0; |
235 | FD_t fd = rpmMkTempFile("/", &fn); |
236 | |
237 | if (Ferror(fd)) |
238 | goto exit; |
239 | |
240 | if (rpmIsDebug()(rpmlogSetMask(0) >= (1 << ((unsigned)(RPMLOG_DEBUG) ))) && (rstreq(cmd, "/bin/sh") || rstreq(cmd, "/bin/bash"))) { |
241 | static const char set_x[] = "set -x\n"; |
242 | /* Assume failures will be caught by the write below */ |
243 | Fwrite(set_x, sizeof(set_x[0]), sizeof(set_x)-1, fd); |
244 | } |
245 | |
246 | ok = (Fwrite(script, sizeof(script[0]), slen, fd) == slen); |
247 | |
248 | exit: |
249 | if (!ok) fn = _free(fn)rfree((fn)); |
250 | Fclose(fd); |
251 | return fn; |
252 | } |
253 | |
254 | /** |
255 | * Run an external script. |
256 | */ |
257 | static rpmRC runExtScript(rpmPlugins plugins, ARGV_const_t prefixes, |
258 | const char *sname, rpmlogLvl lvl, FD_t scriptFd, |
259 | ARGV_t * argvp, const char *script, int arg1, int arg2, |
260 | scriptNextFileFunc nextFileFunc) |
261 | { |
262 | FD_t out = NULL((void*)0); |
263 | char * fn = NULL((void*)0); |
264 | pid_t pid, reaped; |
265 | int status; |
266 | int inpipe[2]; |
267 | FILE *in = NULL((void*)0); |
268 | const char *line; |
269 | char *mline = NULL((void*)0); |
270 | rpmRC rc = RPMRC_FAIL; |
271 | |
272 | rpmlog(RPMLOG_DEBUG, "%s: scriptlet start\n", sname); |
273 | |
274 | if (script) { |
275 | fn = writeScript(*argvp[0], script); |
276 | if (fn == NULL((void*)0)) { |
277 | rpmlog(RPMLOG_ERR, |
278 | _("Couldn't create temporary file for %s: %s\n")dcgettext ("rpm", "Couldn't create temporary file for %s: %s\n" , 5), |
279 | sname, strerror(errno(*__errno_location ()))); |
280 | goto exit; |
281 | } |
282 | |
283 | argvAdd(argvp, fn); |
284 | if (arg1 >= 0) { |
285 | argvAddNum(argvp, arg1); |
286 | } |
287 | if (arg2 >= 0) { |
288 | argvAddNum(argvp, arg2); |
289 | } |
290 | } |
291 | |
292 | if (pipe(inpipe) < 0) { |
293 | rpmlog(RPMLOG_ERR, |
294 | ("Couldn't create pipe: %s\n"), strerror(errno(*__errno_location ()))); |
295 | goto exit; |
296 | } |
297 | in = fdopen(inpipe[1], "w"); |
298 | inpipe[1] = 0; |
299 | |
300 | if (scriptFd != NULL((void*)0)) { |
301 | if (rpmIsVerbose()(rpmlogSetMask(0) >= (1 << ((unsigned)(RPMLOG_INFO)) ))) { |
302 | out = fdDup(Fileno(scriptFd)); |
303 | } else { |
304 | out = Fopen("/dev/null", "w.fdio"); |
305 | if (Ferror(out)) { |
306 | out = fdDup(Fileno(scriptFd)); |
307 | } |
308 | } |
309 | } else { |
310 | out = fdDup(STDOUT_FILENO1); |
311 | } |
312 | if (out == NULL((void*)0)) { |
313 | rpmlog(RPMLOG_ERR, _("Couldn't duplicate file descriptor: %s: %s\n")dcgettext ("rpm", "Couldn't duplicate file descriptor: %s: %s\n" , 5), |
314 | sname, strerror(errno(*__errno_location ()))); |
315 | goto exit; |
316 | } |
317 | |
318 | pid = fork(); |
319 | if (pid == (pid_t) -1) { |
320 | rpmlog(RPMLOG_ERR, _("Couldn't fork %s: %s\n")dcgettext ("rpm", "Couldn't fork %s: %s\n", 5), |
321 | sname, strerror(errno(*__errno_location ()))); |
322 | goto exit; |
323 | } else if (pid == 0) {/* Child */ |
324 | rpmlog(RPMLOG_DEBUG, "%s: execv(%s) pid %d\n", |
325 | sname, *argvp[0], (unsigned)getpid()); |
326 | |
327 | fclose(in); |
328 | dup2(inpipe[0], STDIN_FILENO0); |
329 | |
330 | /* Run scriptlet post fork hook for all plugins */ |
331 | if (rpmpluginsCallScriptletForkPost(plugins, *argvp[0], RPMSCRIPTLET_FORK | RPMSCRIPTLET_EXEC) != RPMRC_FAIL) { |
332 | doScriptExec(*argvp, prefixes, scriptFd, out); |
333 | } else { |
334 | _exit(126); /* exit 126 for compatibility with bash(1) */ |
335 | } |
336 | } |
337 | close(inpipe[0]); |
338 | inpipe[0] = 0; |
339 | |
340 | if (nextFileFunc->func) { |
341 | while ((line = nextFileFunc->func(nextFileFunc->param)) != NULL((void*)0)) { |
342 | size_t size = strlen(line); |
343 | size_t ret_size; |
344 | mline = xstrdup(line)rstrdup((line)); |
345 | mline[size] = '\n'; |
346 | |
347 | ret_size = fwrite(mline, size + 1, 1, in); |
348 | mline = _free(mline)rfree((mline)); |
349 | if (ret_size != 1) { |
350 | if (errno(*__errno_location ()) == EPIPE32) { |
351 | break; |
352 | } else { |
353 | rpmlog(RPMLOG_ERR, _("Fwrite failed: %s")dcgettext ("rpm", "Fwrite failed: %s", 5), strerror(errno(*__errno_location ()))); |
354 | rc = RPMRC_FAIL; |
355 | goto exit; |
356 | } |
357 | } |
358 | } |
359 | } |
360 | fclose(in); |
361 | in = NULL((void*)0); |
362 | |
363 | do { |
364 | reaped = waitpid(pid, &status, 0); |
365 | } while (reaped == -1 && errno(*__errno_location ()) == EINTR4); |
366 | |
367 | rpmlog(RPMLOG_DEBUG, "%s: waitpid(%d) rc %d status %x\n", |
368 | sname, (unsigned)pid, (unsigned)reaped, status); |
369 | |
370 | if (reaped < 0) { |
371 | rpmlog(lvl, _("%s scriptlet failed, waitpid(%d) rc %d: %s\n")dcgettext ("rpm", "%s scriptlet failed, waitpid(%d) rc %d: %s\n" , 5), |
372 | sname, pid, reaped, strerror(errno(*__errno_location ()))); |
373 | } else if (!WIFEXITED(status)(((status) & 0x7f) == 0) || WEXITSTATUS(status)(((status) & 0xff00) >> 8)) { |
374 | if (WIFSIGNALED(status)(((signed char) (((status) & 0x7f) + 1) >> 1) > 0 )) { |
375 | rpmlog(lvl, _("%s scriptlet failed, signal %d\n")dcgettext ("rpm", "%s scriptlet failed, signal %d\n", 5), |
376 | sname, WTERMSIG(status)((status) & 0x7f)); |
377 | } else { |
378 | rpmlog(lvl, _("%s scriptlet failed, exit status %d\n")dcgettext ("rpm", "%s scriptlet failed, exit status %d\n", 5), |
379 | sname, WEXITSTATUS(status)(((status) & 0xff00) >> 8)); |
380 | } |
381 | } else { |
382 | /* if we get this far we're clear */ |
383 | rc = RPMRC_OK; |
384 | } |
385 | |
386 | exit: |
387 | if (in) |
388 | fclose(in); |
389 | |
390 | if (inpipe[0]) |
391 | close(inpipe[0]); |
392 | |
393 | if (out) |
394 | Fclose(out); /* XXX dup'd STDOUT_FILENO */ |
395 | |
396 | if (fn) { |
397 | if (!rpmIsDebug()(rpmlogSetMask(0) >= (1 << ((unsigned)(RPMLOG_DEBUG) )))) |
398 | unlink(fn); |
399 | free(fn); |
400 | } |
401 | free(mline); |
402 | |
403 | return rc; |
404 | } |
405 | |
406 | rpmRC rpmScriptRun(rpmScript script, int arg1, int arg2, FD_t scriptFd, |
407 | ARGV_const_t prefixes, int warn_only, rpmPlugins plugins) |
408 | { |
409 | ARGV_t args = NULL((void*)0); |
410 | rpmlogLvl lvl = warn_only ? RPMLOG_WARNING : RPMLOG_ERR; |
411 | rpmRC rc; |
412 | int script_type = RPMSCRIPTLET_FORK | RPMSCRIPTLET_EXEC; |
413 | |
414 | if (script == NULL((void*)0)) return RPMRC_OK; |
415 | |
416 | /* construct a new argv as we can't modify the one from header */ |
417 | if (script->args) { |
418 | argvAppend(&args, script->args); |
419 | } else { |
420 | argvAdd(&args, "/bin/sh"); |
421 | } |
422 | |
423 | if (rstreq(args[0], "<lua>")) |
424 | script_type = RPMSCRIPTLET_NONE; |
425 | |
426 | /* Run scriptlet pre hook for all plugins */ |
427 | rc = rpmpluginsCallScriptletPre(plugins, script->descr, script_type); |
428 | |
429 | if (rc != RPMRC_FAIL) { |
430 | if (script_type & RPMSCRIPTLET_EXEC) { |
431 | rc = runExtScript(plugins, prefixes, script->descr, lvl, scriptFd, &args, script->body, arg1, arg2, &script->nextFileFunc); |
432 | } else { |
433 | rc = runLuaScript(plugins, prefixes, script->descr, lvl, scriptFd, &args, script->body, arg1, arg2, &script->nextFileFunc); |
434 | } |
435 | } |
436 | |
437 | /* Run scriptlet post hook for all plugins */ |
438 | rpmpluginsCallScriptletPost(plugins, script->descr, script_type, rc); |
439 | |
440 | argvFree(args); |
441 | |
442 | return rc; |
443 | } |
444 | |
445 | static rpmscriptTypes getScriptType(rpmTagVal scriptTag) |
446 | { |
447 | return findTag(scriptTag)->type; |
448 | } |
449 | |
450 | static rpmTagVal getProgTag(rpmTagVal scriptTag) |
451 | { |
452 | return findTag(scriptTag)->progtag; |
453 | } |
454 | |
455 | static rpmTagVal getFlagTag(rpmTagVal scriptTag) |
456 | { |
457 | return findTag(scriptTag)->flagtag; |
458 | } |
459 | |
460 | static const char * tag2sln(rpmTagVal tag) |
461 | { |
462 | return findTag(tag)->desc; |
463 | } |
464 | |
465 | static rpmScript rpmScriptNew(Header h, rpmTagVal tag, const char *body, |
466 | rpmscriptFlags flags) |
467 | { |
468 | char *nevra = headerGetAsString(h, RPMTAG_NEVRA); |
469 | rpmScript script = xcalloc(1, sizeof(*script))rcalloc((1), (sizeof(*script))); |
470 | script->tag = tag; |
471 | script->type = getScriptType(tag); |
472 | script->flags = flags; |
473 | script->body = (body != NULL((void*)0)) ? xstrdup(body)rstrdup((body)) : NULL((void*)0); |
474 | rasprintf(&script->descr, "%s(%s)", tag2sln(tag), nevra); |
475 | |
476 | /* macros need to be expanded before possible queryformat */ |
477 | if (script->body && (script->flags & RPMSCRIPT_FLAG_EXPAND)) { |
478 | char *body = rpmExpand(script->body, NULL((void*)0)); |
479 | free(script->body); |
480 | script->body = body; |
481 | } |
482 | if (script->body && (script->flags & RPMSCRIPT_FLAG_QFORMAT)) { |
483 | /* XXX TODO: handle queryformat errors */ |
484 | char *body = headerFormat(h, script->body, NULL((void*)0)); |
485 | free(script->body); |
486 | script->body = body; |
487 | } |
488 | |
489 | script->nextFileFunc.func = NULL((void*)0); |
490 | script->nextFileFunc.param = NULL((void*)0); |
491 | |
492 | free(nevra); |
493 | return script; |
494 | } |
495 | |
496 | void rpmScriptSetNextFileFunc(rpmScript script, char *(*func)(void *), |
497 | void *param) |
498 | { |
499 | script->nextFileFunc.func = func; |
500 | script->nextFileFunc.param = param; |
501 | } |
502 | |
503 | rpmTagVal triggerDsTag(rpmscriptTriggerModes tm) |
504 | { |
505 | rpmTagVal tag = RPMTAG_NOT_FOUND; |
506 | switch (tm) { |
507 | case RPMSCRIPT_NORMALTRIGGER: |
508 | tag = RPMTAG_TRIGGERNAME; |
509 | break; |
510 | case RPMSCRIPT_FILETRIGGER: |
511 | tag = RPMTAG_FILETRIGGERNAME; |
512 | break; |
513 | case RPMSCRIPT_TRANSFILETRIGGER: |
514 | tag = RPMTAG_TRANSFILETRIGGERNAME; |
515 | break; |
516 | } |
517 | return tag; |
518 | } |
519 | |
520 | rpmscriptTriggerModes triggerMode(rpmTagVal tag) |
521 | { |
522 | rpmscriptTriggerModes tm = 0; |
523 | switch (tag) { |
524 | case RPMTAG_TRIGGERNAME: |
525 | tm = RPMSCRIPT_NORMALTRIGGER; |
526 | break; |
527 | case RPMTAG_FILETRIGGERNAME: |
528 | tm = RPMSCRIPT_FILETRIGGER; |
529 | break; |
530 | case RPMTAG_TRANSFILETRIGGERNAME: |
531 | tm = RPMSCRIPT_TRANSFILETRIGGER; |
532 | break; |
533 | } |
534 | return tm; |
535 | } |
536 | |
537 | rpmTagVal triggertag(rpmsenseFlags sense) |
538 | { |
539 | rpmTagVal tag = RPMTAG_NOT_FOUND; |
540 | switch (sense) { |
541 | case RPMSENSE_TRIGGERIN: |
542 | tag = RPMTAG_TRIGGERIN; |
543 | break; |
544 | case RPMSENSE_TRIGGERUN: |
545 | tag = RPMTAG_TRIGGERUN; |
546 | break; |
547 | case RPMSENSE_TRIGGERPOSTUN: |
548 | tag = RPMTAG_TRIGGERPOSTUN; |
549 | break; |
550 | case RPMSENSE_TRIGGERPREIN: |
551 | tag = RPMTAG_TRIGGERPREIN; |
552 | break; |
553 | default: |
554 | break; |
555 | } |
556 | return tag; |
557 | } |
558 | |
559 | rpmScript rpmScriptFromTriggerTag(Header h, rpmTagVal triggerTag, |
560 | rpmscriptTriggerModes tm, uint32_t ix) |
561 | { |
562 | rpmScript script = NULL((void*)0); |
563 | struct rpmtd_s tscripts, tprogs, tflags; |
564 | headerGetFlags hgflags = HEADERGET_MINMEM; |
565 | |
566 | switch (tm) { |
567 | case RPMSCRIPT_NORMALTRIGGER: |
568 | headerGet(h, RPMTAG_TRIGGERSCRIPTS, &tscripts, hgflags); |
569 | headerGet(h, RPMTAG_TRIGGERSCRIPTPROG, &tprogs, hgflags); |
570 | headerGet(h, RPMTAG_TRIGGERSCRIPTFLAGS, &tflags, hgflags); |
571 | break; |
572 | case RPMSCRIPT_FILETRIGGER: |
573 | headerGet(h, RPMTAG_FILETRIGGERSCRIPTS, &tscripts, hgflags); |
574 | headerGet(h, RPMTAG_FILETRIGGERSCRIPTPROG, &tprogs, hgflags); |
575 | headerGet(h, RPMTAG_FILETRIGGERSCRIPTFLAGS, &tflags, hgflags); |
576 | break; |
577 | case RPMSCRIPT_TRANSFILETRIGGER: |
578 | headerGet(h, RPMTAG_TRANSFILETRIGGERSCRIPTS, &tscripts, hgflags); |
579 | headerGet(h, RPMTAG_TRANSFILETRIGGERSCRIPTPROG, &tprogs, hgflags); |
580 | headerGet(h, RPMTAG_TRANSFILETRIGGERSCRIPTFLAGS, &tflags, hgflags); |
581 | break; |
582 | } |
583 | |
584 | if (rpmtdSetIndex(&tscripts, ix) >= 0 && rpmtdSetIndex(&tprogs, ix) >= 0) { |
585 | rpmscriptFlags sflags = 0; |
586 | const char *prog = rpmtdGetString(&tprogs); |
587 | |
588 | if (rpmtdSetIndex(&tflags, ix) >= 0) |
589 | sflags = rpmtdGetNumber(&tflags); |
590 | |
591 | script = rpmScriptNew(h, triggerTag, rpmtdGetString(&tscripts), sflags); |
592 | |
593 | /* hack up a hge-style NULL-terminated array */ |
594 | script->args = xmalloc(2 * sizeof(*script->args) + strlen(prog) + 1)rmalloc((2 * sizeof(*script->args) + strlen(prog) + 1)); |
595 | script->args[0] = (char *)(script->args + 2); |
596 | script->args[1] = NULL((void*)0); |
597 | strcpy(script->args[0], prog); |
598 | } |
599 | |
600 | rpmtdFreeData(&tscripts); |
601 | rpmtdFreeData(&tprogs); |
602 | rpmtdFreeData(&tflags); |
603 | |
604 | return script; |
605 | } |
606 | |
607 | rpmScript rpmScriptFromTag(Header h, rpmTagVal scriptTag) |
608 | { |
609 | rpmScript script = NULL((void*)0); |
610 | rpmTagVal progTag = getProgTag(scriptTag); |
611 | |
612 | if (headerIsEntry(h, scriptTag) || headerIsEntry(h, progTag)) { |
613 | struct rpmtd_s prog; |
614 | |
615 | script = rpmScriptNew(h, scriptTag, |
616 | headerGetString(h, scriptTag), |
617 | headerGetNumber(h, getFlagTag(scriptTag))); |
618 | |
619 | if (headerGet(h, progTag, &prog, (HEADERGET_ALLOC|HEADERGET_ARGV))) { |
620 | script->args = prog.data; |
621 | } |
622 | } |
623 | return script; |
624 | } |
625 | |
626 | rpmScript rpmScriptFree(rpmScript script) |
627 | { |
628 | if (script) { |
629 | free(script->args); |
630 | free(script->body); |
631 | free(script->descr); |
632 | free(script); |
633 | } |
634 | return NULL((void*)0); |
635 | } |
636 | |
637 | rpmTagVal rpmScriptTag(rpmScript script) |
638 | { |
639 | return (script != NULL((void*)0)) ? script->tag : RPMTAG_NOT_FOUND; |
640 | } |
641 | |
642 | rpmscriptTypes rpmScriptType(rpmScript script) |
643 | { |
644 | return (script != NULL((void*)0)) ? script->type : 0; |
645 | } |