trigdeferred.l 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. /*
  2. * dpkg - main program for package management
  3. * trigdeferred.l - parsing of triggers/Deferred
  4. *
  5. * Copyright © 2007 Canonical Ltd
  6. * written by Ian Jackson <ian@chiark.greenend.org.uk>
  7. *
  8. * This is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as
  10. * published by the Free Software Foundation; either version 2,
  11. * or (at your option) any later version.
  12. *
  13. * This is distributed in the hope that it will be useful, but
  14. * WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public
  19. * License along with dpkg; if not, write to the Free Software
  20. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21. */
  22. %option prefix="trigdef_yy"
  23. /* Reset the name to the default value (instead of using "trigdeferred.c")
  24. * so that automake (ylwrap) can find it. */
  25. %option outfile="lex.yy.c"
  26. %option noyywrap
  27. %option batch
  28. %option nodefault
  29. %option perf-report
  30. %option warn
  31. %option nounput
  32. %x midline
  33. %{
  34. #include <config.h>
  35. #include <dpkg-i18n.h>
  36. #include <sys/stat.h>
  37. #include <sys/fcntl.h>
  38. #include <dpkg.h>
  39. #include <dpkg-db.h>
  40. #define YY_NO_INPUT
  41. static struct varbuf fn, newfn;
  42. %}
  43. %%
  44. [ \t\n] /* whitespace */
  45. #.*\n /* comments */
  46. [\x21-\x7e]+ {
  47. trigdef->trig_begin(trigdef_yytext);
  48. BEGIN(midline);
  49. }
  50. <midline>[ \t] /* whitespace */
  51. <midline>[-0-9a-z][-+.0-9a-z]* {
  52. if (trigdef_yytext[0] == '-' && trigdef_yytext[1])
  53. ohshit(_("invalid package name `%.250s' in triggers deferred "
  54. "file `%.250s'"), trigdef_yytext, fn.buf);
  55. trigdef->package(trigdef_yytext);
  56. }
  57. <midline>\n|#.*\n {
  58. trigdef->trig_end();
  59. BEGIN(0);
  60. }
  61. <midline><<EOF>> {
  62. ohshit(_("truncated triggers deferred file `%.250s'"), fn.buf);
  63. }
  64. <*>. {
  65. ohshit(_("syntax error in triggers deferred file `%.250s' at "
  66. "character `%s'%s"),
  67. fn.buf, yytext, YY_START == midline ? " midline": "");
  68. }
  69. %%
  70. /*---------- Deferred file handling ----------*/
  71. static int lock_fd = -1;
  72. static FILE *old_deferred;
  73. FILE *trig_new_deferred;
  74. const struct trigdefmeths *trigdef;
  75. static void
  76. constructfn(struct varbuf *vb, const char *admindir, const char *tail)
  77. {
  78. varbufreset(vb);
  79. varbufaddstr(vb, admindir);
  80. varbufaddstr(vb, "/" TRIGGERSDIR);
  81. varbufaddstr(vb, tail);
  82. varbufaddc(vb, 0);
  83. }
  84. int
  85. trigdef_update_start(enum trigdef_updateflags uf, const char *admindir)
  86. {
  87. struct stat stab;
  88. int r;
  89. if (uf & tduf_write) {
  90. constructfn(&fn, admindir, TRIGGERSLOCKFILE);
  91. if (lock_fd == -1) {
  92. lock_fd = open(fn.buf, O_RDWR | O_CREAT | O_TRUNC, 0600);
  93. if (lock_fd == -1) {
  94. if (!(errno == ENOENT && (uf & tduf_nolockok)))
  95. ohshite(_("unable to open/create "
  96. "triggers lockfile `%.250s'"),
  97. fn.buf);
  98. return -1;
  99. }
  100. }
  101. lock_file(&lock_fd, fn.buf, _("unable to lock triggers area"),
  102. NULL);
  103. } else {
  104. /* Dummy for pop_cleanups. */
  105. push_cleanup(NULL, 0, NULL, 0, 0);
  106. }
  107. constructfn(&fn, admindir, TRIGGERSDEFERREDFILE);
  108. r = stat(fn.buf, &stab);
  109. if (r) {
  110. if (errno != ENOENT)
  111. ohshite(_("unable to stat triggers deferred file `%.250s'"),
  112. fn.buf);
  113. } else if (!stab.st_size) {
  114. if (!(uf & tduf_writeifempty)) {
  115. pop_cleanup(ehflag_normaltidy);
  116. return -2;
  117. }
  118. }
  119. if (old_deferred)
  120. fclose(old_deferred);
  121. old_deferred = fopen(fn.buf, "r");
  122. if (!old_deferred) {
  123. if (errno != ENOENT)
  124. ohshite(_("unable to open triggers deferred file `%.250s'"),
  125. fn.buf);
  126. if (!(uf & tduf_writeifenoent)) {
  127. pop_cleanup(ehflag_normaltidy);
  128. return -3;
  129. }
  130. }
  131. if (uf & tduf_write) {
  132. constructfn(&newfn, admindir, TRIGGERSDEFERREDFILE ".new");
  133. if (trig_new_deferred)
  134. fclose(trig_new_deferred);
  135. trig_new_deferred = fopen(newfn.buf, "w");
  136. if (!trig_new_deferred)
  137. ohshite(_("unable to open/create new triggers deferred file `%.250s'"),
  138. newfn.buf);
  139. }
  140. if (!old_deferred)
  141. return 1;
  142. trigdef_yyrestart(old_deferred);
  143. BEGIN(0);
  144. return 2;
  145. }
  146. void
  147. trigdef_process_done(void)
  148. {
  149. int r;
  150. if (old_deferred) {
  151. if (ferror(old_deferred))
  152. ohshite(_("error reading triggers deferred file `%.250s'"),
  153. fn.buf);
  154. fclose(old_deferred);
  155. old_deferred = NULL;
  156. }
  157. if (trig_new_deferred) {
  158. if (ferror(trig_new_deferred))
  159. ohshite(_("unable to write new triggers deferred "
  160. "file `%.250s'"), newfn.buf);
  161. r = fclose(trig_new_deferred);
  162. trig_new_deferred = NULL;
  163. if (r)
  164. ohshite(_("unable to close new triggers deferred "
  165. "file `%.250s'"), newfn.buf);
  166. if (rename(newfn.buf, fn.buf))
  167. ohshite(_("unable to install new triggers deferred "
  168. "file `%.250s'"), fn.buf);
  169. }
  170. /* Unlock. */
  171. pop_cleanup(ehflag_normaltidy);
  172. }