triglib.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823
  1. /*
  2. * libdpkg - Debian packaging suite library routines
  3. * triglib.c - trigger handling
  4. *
  5. * Copyright © 2007 Canonical Ltd
  6. * Written by Ian Jackson <ian@chiark.greenend.org.uk>
  7. * Copyright © 2008-2012 Guillem Jover <guillem@debian.org>
  8. *
  9. * This is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  21. */
  22. #include <config.h>
  23. #include <compat.h>
  24. #include <sys/types.h>
  25. #include <sys/stat.h>
  26. #include <assert.h>
  27. #include <errno.h>
  28. #include <stdlib.h>
  29. #include <unistd.h>
  30. #include <dpkg/i18n.h>
  31. #include <dpkg/dpkg.h>
  32. #include <dpkg/dpkg-db.h>
  33. #include <dpkg/pkg.h>
  34. #include <dpkg/dlist.h>
  35. #include <dpkg/dir.h>
  36. #include <dpkg/pkg-spec.h>
  37. #include <dpkg/trigdeferred.h>
  38. #include <dpkg/triglib.h>
  39. /*========== Recording triggers. ==========*/
  40. static char *triggersdir, *triggersfilefile;
  41. static char *
  42. trig_get_filename(const char *dir, const char *filename)
  43. {
  44. char *path;
  45. m_asprintf(&path, "%s/%s", dir, filename);
  46. return path;
  47. }
  48. static struct trig_hooks trigh;
  49. /*---------- Noting trigger activation in memory. ----------*/
  50. /*
  51. * Called via trig_*activate* et al from:
  52. * - trig_incorporate: reading of Unincorp (explicit trigger activations)
  53. * - various places: processing start (‘activate’ in triggers ci file)
  54. * - namenodetouse: file triggers during unpack / remove
  55. * - deferred_configure: file triggers during config file processing
  56. *
  57. * Not called from trig_transitional_activation; that runs
  58. * trig_note_pend directly which means that (a) awaiters are not
  59. * recorded (how would we know?) and (b) we don't enqueue them for
  60. * deferred processing in this run.
  61. *
  62. * We add the trigger to Triggers-Pending first. This makes it
  63. * harder to get into the state where Triggers-Awaited for aw lists
  64. * pend but Triggers-Pending for pend is empty. (See also the
  65. * comment in deppossi_ok_found regarding this situation.)
  66. */
  67. /*
  68. * aw might be NULL.
  69. * trig is not copied!
  70. */
  71. static void
  72. trig_record_activation(struct pkginfo *pend, struct pkginfo *aw, const char *trig)
  73. {
  74. if (pend->status < stat_triggersawaited)
  75. return; /* Not interested then. */
  76. if (trig_note_pend(pend, trig))
  77. modstatdb_note_ifwrite(pend);
  78. if (trigh.enqueue_deferred)
  79. trigh.enqueue_deferred(pend);
  80. if (aw && pend->status > stat_configfiles)
  81. if (trig_note_aw(pend, aw)) {
  82. if (aw->status > stat_triggersawaited)
  83. pkg_set_status(aw, stat_triggersawaited);
  84. modstatdb_note_ifwrite(aw);
  85. }
  86. }
  87. void
  88. trig_clear_awaiters(struct pkginfo *notpend)
  89. {
  90. struct trigaw *ta;
  91. struct pkginfo *aw;
  92. assert(!notpend->trigpend_head);
  93. ta = notpend->othertrigaw_head;
  94. notpend->othertrigaw_head = NULL;
  95. for (; ta; ta = ta->samepend_next) {
  96. aw = ta->aw;
  97. if (!aw)
  98. continue;
  99. LIST_UNLINK_PART(aw->trigaw, ta, sameaw.);
  100. if (!aw->trigaw.head && aw->status == stat_triggersawaited) {
  101. if (aw->trigpend_head)
  102. pkg_set_status(aw, stat_triggerspending);
  103. else
  104. pkg_set_status(aw, stat_installed);
  105. modstatdb_note(aw);
  106. }
  107. }
  108. }
  109. /*
  110. * Fix up packages in state triggers-awaited w/o the corresponding package
  111. * with pending triggers. This can happen when dpkg was interrupted
  112. * while in modstatdb_note, and the package in triggers-pending had its
  113. * state modified but dpkg could not finish clearing the awaiters.
  114. *
  115. * XXX: Possibly get rid of some of the checks done somewhere else for
  116. * this condition at run-time.
  117. */
  118. void
  119. trig_fixup_awaiters(enum modstatdb_rw cstatus)
  120. {
  121. if (cstatus < msdbrw_write)
  122. return;
  123. trig_awaited_pend_foreach(trig_clear_awaiters);
  124. trig_awaited_pend_free();
  125. }
  126. /*---------- Generalized handling of trigger kinds. ----------*/
  127. struct trigkindinfo {
  128. /* Only for trig_activate_start. */
  129. void (*activate_start)(void);
  130. /* Rest are for everyone: */
  131. void (*activate_awaiter)(struct pkginfo *pkg /* may be NULL */);
  132. void (*activate_done)(void);
  133. void (*interest_change)(const char *name, struct pkginfo *pkg,
  134. struct pkgbin *pkgbin,
  135. int signum, enum trig_options opts);
  136. };
  137. static const struct trigkindinfo tki_explicit, tki_file, tki_unknown;
  138. static const struct trigkindinfo *dtki;
  139. /* As passed into activate_start. */
  140. static const char *trig_activating_name;
  141. static const struct trigkindinfo *
  142. trig_classify_byname(const char *name)
  143. {
  144. if (name[0] == '/') {
  145. const char *slash;
  146. slash = name;
  147. while (slash) {
  148. if (slash[1] == '\0' || slash[1] == '/')
  149. goto invalid;
  150. slash = strchr(slash + 2, '/');
  151. }
  152. return &tki_file;
  153. }
  154. if (!pkg_name_is_illegal(name) && !strchr(name, '_'))
  155. return &tki_explicit;
  156. invalid:
  157. return &tki_unknown;
  158. }
  159. /*
  160. * Calling sequence is:
  161. * trig_activate_start(triggername)
  162. * dtki->activate_awaiter(awaiting_package) } zero or more times
  163. * dtki->activate_awaiter(0) } in any order
  164. * dtki->activate_done(0)
  165. */
  166. static void
  167. trig_activate_start(const char *name)
  168. {
  169. dtki = trig_classify_byname(name);
  170. trig_activating_name = name;
  171. dtki->activate_start();
  172. }
  173. /*---------- Unknown trigger kinds. ----------*/
  174. static void
  175. trk_unknown_activate_start(void)
  176. {
  177. }
  178. static void
  179. trk_unknown_activate_awaiter(struct pkginfo *aw)
  180. {
  181. }
  182. static void
  183. trk_unknown_activate_done(void)
  184. {
  185. }
  186. static void DPKG_ATTR_NORET
  187. trk_unknown_interest_change(const char *trig, struct pkginfo *pkg,
  188. struct pkgbin *pkgbin, int signum,
  189. enum trig_options opts)
  190. {
  191. ohshit(_("invalid or unknown syntax in trigger name `%.250s'"
  192. " (in trigger interests for package `%.250s')"),
  193. trig, pkgbin_name(pkg, pkgbin, pnaw_nonambig));
  194. }
  195. static const struct trigkindinfo tki_unknown = {
  196. .activate_start = trk_unknown_activate_start,
  197. .activate_awaiter = trk_unknown_activate_awaiter,
  198. .activate_done = trk_unknown_activate_done,
  199. .interest_change = trk_unknown_interest_change,
  200. };
  201. /*---------- Explicit triggers. ----------*/
  202. static FILE *trk_explicit_f;
  203. static struct varbuf trk_explicit_fn;
  204. static char *trk_explicit_trig;
  205. static void
  206. trk_explicit_activate_done(void)
  207. {
  208. if (trk_explicit_f) {
  209. fclose(trk_explicit_f);
  210. trk_explicit_f = NULL;
  211. }
  212. }
  213. static void
  214. trk_explicit_start(const char *trig)
  215. {
  216. trk_explicit_activate_done();
  217. varbuf_reset(&trk_explicit_fn);
  218. varbuf_add_str(&trk_explicit_fn, triggersdir);
  219. varbuf_add_char(&trk_explicit_fn, '/');
  220. varbuf_add_str(&trk_explicit_fn, trig);
  221. varbuf_end_str(&trk_explicit_fn);
  222. trk_explicit_f = fopen(trk_explicit_fn.buf, "r");
  223. if (!trk_explicit_f) {
  224. if (errno != ENOENT)
  225. ohshite(_("failed to open trigger interest list file `%.250s'"),
  226. trk_explicit_fn.buf);
  227. }
  228. }
  229. static int
  230. trk_explicit_fgets(char *buf, size_t sz)
  231. {
  232. return fgets_checked(buf, sz, trk_explicit_f, trk_explicit_fn.buf);
  233. }
  234. static void
  235. trk_explicit_activate_start(void)
  236. {
  237. trk_explicit_start(trig_activating_name);
  238. trk_explicit_trig = nfstrsave(trig_activating_name);
  239. }
  240. static void
  241. trk_explicit_activate_awaiter(struct pkginfo *aw)
  242. {
  243. char buf[1024];
  244. struct pkginfo *pend;
  245. if (!trk_explicit_f)
  246. return;
  247. if (fseek(trk_explicit_f, 0, SEEK_SET))
  248. ohshite(_("failed to rewind trigger interest file `%.250s'"),
  249. trk_explicit_fn.buf);
  250. while (trk_explicit_fgets(buf, sizeof(buf)) >= 0) {
  251. struct dpkg_error err;
  252. char *slash;
  253. bool noawait = false;
  254. slash = strchr(buf, '/');
  255. if (slash && strcmp("/noawait", slash) == 0) {
  256. noawait = true;
  257. *slash = '\0';
  258. }
  259. pend = pkg_spec_parse_pkg(buf, &err);
  260. if (pend == NULL)
  261. ohshit(_("trigger interest file `%.250s' syntax error; "
  262. "illegal package name `%.250s': %.250s"),
  263. trk_explicit_fn.buf, buf, err.str);
  264. trig_record_activation(pend, noawait ? NULL : aw,
  265. trk_explicit_trig);
  266. }
  267. }
  268. static void
  269. trk_explicit_interest_change(const char *trig, struct pkginfo *pkg,
  270. struct pkgbin *pkgbin, int signum,
  271. enum trig_options opts)
  272. {
  273. char buf[1024];
  274. struct atomic_file *file;
  275. bool empty = true;
  276. trk_explicit_start(trig);
  277. file = atomic_file_new(trk_explicit_fn.buf, 0);
  278. atomic_file_open(file);
  279. while (trk_explicit_f && trk_explicit_fgets(buf, sizeof(buf)) >= 0) {
  280. const char *pkgname = pkgbin_name(pkg, pkgbin, pnaw_nonambig);
  281. int len = strlen(pkgname);
  282. if (strncmp(buf, pkgname, len) == 0 &&
  283. (buf[len] == '\0' || buf[len] == '/'))
  284. continue;
  285. fprintf(file->fp, "%s\n", buf);
  286. empty = false;
  287. }
  288. if (signum > 0) {
  289. fprintf(file->fp, "%s%s\n",
  290. pkgbin_name(pkg, pkgbin, pnaw_nonambig),
  291. (opts == trig_noawait) ? "/noawait" : "");
  292. empty = false;
  293. }
  294. if (!empty)
  295. atomic_file_sync(file);
  296. atomic_file_close(file);
  297. if (empty)
  298. atomic_file_remove(file);
  299. else
  300. atomic_file_commit(file);
  301. atomic_file_free(file);
  302. dir_sync_path(triggersdir);
  303. }
  304. static const struct trigkindinfo tki_explicit = {
  305. .activate_start = trk_explicit_activate_start,
  306. .activate_awaiter = trk_explicit_activate_awaiter,
  307. .activate_done = trk_explicit_activate_done,
  308. .interest_change = trk_explicit_interest_change,
  309. };
  310. /*---------- File triggers. ----------*/
  311. static struct {
  312. struct trigfileint *head, *tail;
  313. } filetriggers;
  314. /*
  315. * Values:
  316. * -1: Not read.
  317. * 0: Not edited.
  318. * 1: Edited
  319. */
  320. static int filetriggers_edited = -1;
  321. /*
  322. * Called by various people with signum -1 and +1 to mean remove and add
  323. * and also by trig_file_interests_ensure() with signum +2 meaning add
  324. * but die if already present.
  325. */
  326. static void
  327. trk_file_interest_change(const char *trig, struct pkginfo *pkg,
  328. struct pkgbin *pkgbin, int signum,
  329. enum trig_options opts)
  330. {
  331. struct filenamenode *fnn;
  332. struct trigfileint **search, *tfi;
  333. fnn = trigh.namenode_find(trig, signum <= 0);
  334. if (!fnn) {
  335. assert(signum < 0);
  336. return;
  337. }
  338. for (search = trigh.namenode_interested(fnn);
  339. (tfi = *search);
  340. search = &tfi->samefile_next)
  341. if (tfi->pkg == pkg)
  342. goto found;
  343. /* Not found. */
  344. if (signum < 0)
  345. return;
  346. tfi = nfmalloc(sizeof(*tfi));
  347. tfi->pkg = pkg;
  348. tfi->pkgbin = pkgbin;
  349. tfi->fnn = fnn;
  350. tfi->options = opts;
  351. tfi->samefile_next = *trigh.namenode_interested(fnn);
  352. *trigh.namenode_interested(fnn) = tfi;
  353. LIST_LINK_TAIL_PART(filetriggers, tfi, inoverall.);
  354. goto edited;
  355. found:
  356. tfi->options = opts;
  357. if (signum > 1)
  358. ohshit(_("duplicate file trigger interest for filename `%.250s' "
  359. "and package `%.250s'"), trig,
  360. pkgbin_name(pkg, pkgbin, pnaw_nonambig));
  361. if (signum > 0)
  362. return;
  363. /* Remove it: */
  364. *search = tfi->samefile_next;
  365. LIST_UNLINK_PART(filetriggers, tfi, inoverall.);
  366. edited:
  367. filetriggers_edited = 1;
  368. }
  369. static void
  370. trig_file_interests_remove(void)
  371. {
  372. if (unlink(triggersfilefile) && errno != ENOENT)
  373. ohshite(_("cannot remove `%.250s'"), triggersfilefile);
  374. }
  375. static void
  376. trig_file_interests_update(void)
  377. {
  378. struct trigfileint *tfi;
  379. struct atomic_file *file;
  380. file = atomic_file_new(triggersfilefile, 0);
  381. atomic_file_open(file);
  382. for (tfi = filetriggers.head; tfi; tfi = tfi->inoverall.next)
  383. fprintf(file->fp, "%s %s%s\n", trigh.namenode_name(tfi->fnn),
  384. pkgbin_name(tfi->pkg, tfi->pkgbin, pnaw_nonambig),
  385. (tfi->options == trig_noawait) ? "/noawait" : "");
  386. atomic_file_sync(file);
  387. atomic_file_close(file);
  388. atomic_file_commit(file);
  389. atomic_file_free(file);
  390. }
  391. void
  392. trig_file_interests_save(void)
  393. {
  394. if (filetriggers_edited <= 0)
  395. return;
  396. if (!filetriggers.head)
  397. trig_file_interests_remove();
  398. else
  399. trig_file_interests_update();
  400. dir_sync_path(triggersdir);
  401. filetriggers_edited = 0;
  402. }
  403. void
  404. trig_file_interests_ensure(void)
  405. {
  406. FILE *f;
  407. char linebuf[1024], *space;
  408. struct pkginfo *pkg;
  409. struct pkgbin *pkgbin;
  410. if (filetriggers_edited >= 0)
  411. return;
  412. f = fopen(triggersfilefile, "r");
  413. if (!f) {
  414. if (errno == ENOENT)
  415. goto ok;
  416. ohshite(_("unable to read file triggers file `%.250s'"),
  417. triggersfilefile);
  418. }
  419. push_cleanup(cu_closestream, ~0, NULL, 0, 1, f);
  420. while (fgets_checked(linebuf, sizeof(linebuf), f, triggersfilefile) >= 0) {
  421. struct dpkg_error err;
  422. char *slash;
  423. enum trig_options trig_opts = trig_await;
  424. space = strchr(linebuf, ' ');
  425. if (!space || linebuf[0] != '/')
  426. ohshit(_("syntax error in file triggers file `%.250s'"),
  427. triggersfilefile);
  428. *space++ = '\0';
  429. slash = strchr(space, '/');
  430. if (slash && strcmp("/noawait", slash) == 0) {
  431. trig_opts = trig_noawait;
  432. *slash = '\0';
  433. }
  434. pkg = pkg_spec_parse_pkg(space, &err);
  435. if (pkg == NULL)
  436. ohshit(_("file triggers record mentions illegal "
  437. "package name `%.250s' (for interest in file "
  438. "`%.250s'): %.250s"), space, linebuf, err.str);
  439. pkgbin = &pkg->installed;
  440. trk_file_interest_change(linebuf, pkg, pkgbin, +2, trig_opts);
  441. }
  442. pop_cleanup(ehflag_normaltidy);
  443. ok:
  444. filetriggers_edited = 0;
  445. }
  446. static struct filenamenode *filetriggers_activating;
  447. void
  448. trig_file_activate_byname(const char *trig, struct pkginfo *aw)
  449. {
  450. struct filenamenode *fnn = trigh.namenode_find(trig, 1);
  451. if (fnn)
  452. trig_file_activate(fnn, aw);
  453. }
  454. void
  455. trig_file_activate(struct filenamenode *trig, struct pkginfo *aw)
  456. {
  457. struct trigfileint *tfi;
  458. for (tfi = *trigh.namenode_interested(trig); tfi;
  459. tfi = tfi->samefile_next)
  460. trig_record_activation(tfi->pkg, (tfi->options == trig_noawait) ?
  461. NULL : aw, trigh.namenode_name(trig));
  462. }
  463. static void
  464. trk_file_activate_start(void)
  465. {
  466. filetriggers_activating = trigh.namenode_find(trig_activating_name, 1);
  467. }
  468. static void
  469. trk_file_activate_awaiter(struct pkginfo *aw)
  470. {
  471. if (!filetriggers_activating)
  472. return;
  473. trig_file_activate(filetriggers_activating, aw);
  474. }
  475. static void
  476. trk_file_activate_done(void)
  477. {
  478. }
  479. static const struct trigkindinfo tki_file = {
  480. .activate_start = trk_file_activate_start,
  481. .activate_awaiter = trk_file_activate_awaiter,
  482. .activate_done = trk_file_activate_done,
  483. .interest_change = trk_file_interest_change,
  484. };
  485. /*---------- Trigger control info file. ----------*/
  486. static void
  487. trig_cicb_interest_change(const char *trig, struct pkginfo *pkg,
  488. struct pkgbin *pkgbin, int signum,
  489. enum trig_options opts)
  490. {
  491. const struct trigkindinfo *tki = trig_classify_byname(trig);
  492. assert(filetriggers_edited >= 0);
  493. tki->interest_change(trig, pkg, pkgbin, signum, opts);
  494. }
  495. void
  496. trig_cicb_interest_delete(const char *trig, struct pkginfo *pkg,
  497. struct pkgbin *pkgbin, enum trig_options opts)
  498. {
  499. trig_cicb_interest_change(trig, pkg, pkgbin, -1, opts);
  500. }
  501. void
  502. trig_cicb_interest_add(const char *trig, struct pkginfo *pkg,
  503. struct pkgbin *pkgbin, enum trig_options opts)
  504. {
  505. trig_cicb_interest_change(trig, pkg, pkgbin, +1, opts);
  506. }
  507. void
  508. trig_cicb_statuschange_activate(const char *trig, struct pkginfo *pkg,
  509. struct pkgbin *pkgbin, enum trig_options opts)
  510. {
  511. struct pkginfo *aw = pkg;
  512. trig_activate_start(trig);
  513. dtki->activate_awaiter((opts == trig_noawait) ? NULL : aw);
  514. dtki->activate_done();
  515. }
  516. static void
  517. parse_ci_call(const char *file, const char *cmd, trig_parse_cicb *cb,
  518. const char *trig, struct pkginfo *pkg, struct pkgbin *pkgbin,
  519. enum trig_options opts)
  520. {
  521. const char *emsg;
  522. emsg = trig_name_is_illegal(trig);
  523. if (emsg)
  524. ohshit(_("triggers ci file `%.250s' contains illegal trigger "
  525. "syntax in trigger name `%.250s': %.250s"),
  526. file, trig, emsg);
  527. if (cb)
  528. cb(trig, pkg, pkgbin, opts);
  529. }
  530. void
  531. trig_parse_ci(const char *file, trig_parse_cicb *interest,
  532. trig_parse_cicb *activate, struct pkginfo *pkg,
  533. struct pkgbin *pkgbin)
  534. {
  535. FILE *f;
  536. char linebuf[MAXTRIGDIRECTIVE], *cmd, *spc, *eol;
  537. int l;
  538. f = fopen(file, "r");
  539. if (!f) {
  540. if (errno == ENOENT)
  541. return; /* No file is just like an empty one. */
  542. ohshite(_("unable to open triggers ci file `%.250s'"), file);
  543. }
  544. push_cleanup(cu_closestream, ~0, NULL, 0, 1, f);
  545. while ((l = fgets_checked(linebuf, sizeof(linebuf), f, file)) >= 0) {
  546. for (cmd = linebuf; cisspace(*cmd); cmd++);
  547. if (*cmd == '#')
  548. continue;
  549. for (eol = linebuf + l; eol > cmd && cisspace(eol[-1]); eol--);
  550. if (eol == cmd)
  551. continue;
  552. *eol = '\0';
  553. for (spc = cmd; *spc && !cisspace(*spc); spc++);
  554. if (!*spc)
  555. ohshit(_("triggers ci file contains unknown directive syntax"));
  556. *spc++ = '\0';
  557. while (cisspace(*spc))
  558. spc++;
  559. if (strcmp(cmd, "interest") == 0) {
  560. parse_ci_call(file, cmd, interest, spc, pkg, pkgbin, trig_await);
  561. } else if (strcmp(cmd, "interest-noawait") == 0) {
  562. parse_ci_call(file, cmd, interest, spc, pkg, pkgbin, trig_noawait);
  563. } else if (strcmp(cmd, "activate") == 0) {
  564. parse_ci_call(file, cmd, activate, spc, pkg, pkgbin, trig_await);
  565. } else if (strcmp(cmd, "activate-noawait") == 0) {
  566. parse_ci_call(file, cmd, activate, spc, pkg, pkgbin, trig_noawait);
  567. } else {
  568. ohshit(_("triggers ci file contains unknown directive `%.250s'"),
  569. cmd);
  570. }
  571. }
  572. pop_cleanup(ehflag_normaltidy); /* fclose() */
  573. }
  574. /*---------- Unincorp file incorporation. ----------*/
  575. static void
  576. tdm_incorp_trig_begin(const char *trig)
  577. {
  578. trig_activate_start(trig);
  579. }
  580. static void
  581. tdm_incorp_package(const char *awname)
  582. {
  583. struct pkginfo *aw;
  584. if (strcmp(awname, "-") == 0)
  585. aw = NULL;
  586. else
  587. aw = pkg_spec_parse_pkg(awname, NULL);
  588. dtki->activate_awaiter(aw);
  589. }
  590. static void
  591. tdm_incorp_trig_end(void)
  592. {
  593. dtki->activate_done();
  594. }
  595. static const struct trigdefmeths tdm_incorp = {
  596. .trig_begin = tdm_incorp_trig_begin,
  597. .package = tdm_incorp_package,
  598. .trig_end = tdm_incorp_trig_end
  599. };
  600. void
  601. trig_incorporate(enum modstatdb_rw cstatus)
  602. {
  603. enum trigdef_update_status ur;
  604. enum trigdef_updateflags tduf;
  605. free(triggersdir);
  606. triggersdir = dpkg_db_get_path(TRIGGERSDIR);
  607. free(triggersfilefile);
  608. triggersfilefile = trig_get_filename(triggersdir, TRIGGERSFILEFILE);
  609. trigdef_set_methods(&tdm_incorp);
  610. trig_file_interests_ensure();
  611. tduf = tduf_nolockok;
  612. if (cstatus >= msdbrw_write) {
  613. tduf |= tduf_write;
  614. if (trigh.transitional_activate)
  615. tduf |= tduf_writeifenoent;
  616. }
  617. ur = trigdef_update_start(tduf);
  618. if (ur == tdus_error_no_dir && cstatus >= msdbrw_write) {
  619. if (mkdir(triggersdir, 0755)) {
  620. if (errno != EEXIST)
  621. ohshite(_("unable to create triggers state"
  622. " directory `%.250s'"), triggersdir);
  623. } else if (chown(triggersdir, 0, 0)) {
  624. ohshite(_("unable to set ownership of triggers state"
  625. " directory `%.250s'"), triggersdir);
  626. }
  627. ur = trigdef_update_start(tduf);
  628. }
  629. switch (ur) {
  630. case tdus_error_empty_deferred:
  631. return;
  632. case tdus_error_no_dir:
  633. case tdus_error_no_deferred:
  634. if (!trigh.transitional_activate)
  635. return;
  636. /* Fall through. */
  637. case tdus_no_deferred:
  638. trigh.transitional_activate(cstatus);
  639. break;
  640. case tdus_ok:
  641. /* Read and incorporate triggers. */
  642. trigdef_parse();
  643. break;
  644. default:
  645. internerr("unknown trigdef_update_start return value '%d'", ur);
  646. }
  647. /* Right, that's it. New (empty) Unincorp can be installed. */
  648. trigdef_process_done();
  649. }
  650. /*---------- Default hooks. ----------*/
  651. struct filenamenode {
  652. struct filenamenode *next;
  653. const char *name;
  654. struct trigfileint *trig_interested;
  655. };
  656. static struct filenamenode *trigger_files;
  657. static struct filenamenode *
  658. th_simple_nn_find(const char *name, bool nonew)
  659. {
  660. struct filenamenode *search;
  661. for (search = trigger_files; search; search = search->next)
  662. if (strcmp(search->name, name) == 0)
  663. return search;
  664. /* Not found. */
  665. if (nonew)
  666. return NULL;
  667. search = nfmalloc(sizeof(*search));
  668. search->name = nfstrsave(name);
  669. search->trig_interested = NULL;
  670. search->next = trigger_files;
  671. trigger_files = search;
  672. return search;
  673. }
  674. TRIGHOOKS_DEFINE_NAMENODE_ACCESSORS
  675. static struct trig_hooks trigh = {
  676. .enqueue_deferred = NULL,
  677. .transitional_activate = NULL,
  678. .namenode_find = th_simple_nn_find,
  679. .namenode_interested = th_nn_interested,
  680. .namenode_name = th_nn_name,
  681. };
  682. void
  683. trig_override_hooks(const struct trig_hooks *hooks)
  684. {
  685. trigh = *hooks;
  686. }