File: | lib/rpmscript.c |
Warning: | line 390, column 9 Branch condition evaluates to a garbage value |
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); | |||
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 | } |