parse.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. /*
  2. * libdpkg - Debian packaging suite library routines
  3. * parse.c - database file parsing, main package/field loop
  4. *
  5. * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
  6. *
  7. * This is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as
  9. * published by the Free Software Foundation; either version 2,
  10. * or (at your option) any later version.
  11. *
  12. * This is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public
  18. * License along with dpkg; if not, write to the Free Software
  19. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <ctype.h>
  24. #include <stdarg.h>
  25. #include "config.h"
  26. #include "dpkg.h"
  27. #include "dpkg-db.h"
  28. #include "parsedump.h"
  29. const struct fieldinfo fieldinfos[]= {
  30. /* NB: capitalisation of these strings is important. */
  31. { "Package", f_name, w_name },
  32. { "Essential", f_boolean, w_booleandefno, PKGIFPOFF(essential) },
  33. { "Status", f_status, w_status },
  34. { "Priority", f_priority, w_priority },
  35. { "Section", f_section, w_section },
  36. { "Maintainer", f_charfield, w_charfield, PKGIFPOFF(maintainer) },
  37. { "Architecture", f_charfield, w_charfield, PKGIFPOFF(architecture) },
  38. { "Source", f_charfield, w_charfield, PKGIFPOFF(source) },
  39. { "Version", f_charfield, w_version, PKGIFPOFF(version) },
  40. { "Revision", f_charfield, w_null, PKGIFPOFF(revision) },
  41. { "Config-Version", f_configversion, w_configversion },
  42. { "Replaces", f_dependency, w_dependency, dep_replaces },
  43. { "Provides", f_dependency, w_dependency, dep_provides },
  44. { "Depends", f_dependency, w_dependency, dep_depends },
  45. { "Pre-Depends", f_dependency, w_dependency, dep_predepends },
  46. { "Recommends", f_dependency, w_dependency, dep_recommends },
  47. { "Suggests", f_dependency, w_dependency, dep_suggests },
  48. { "Conflicts", f_dependency, w_dependency, dep_conflicts },
  49. { "Conffiles", f_conffiles, w_conffiles },
  50. { "Filename", f_filecharf, w_filecharf, FILEFOFF(name) },
  51. { "Size", f_filecharf, w_filecharf, FILEFOFF(size) },
  52. { "MD5sum", f_filecharf, w_filecharf, FILEFOFF(md5sum) },
  53. { "MSDOS-Filename", f_filecharf, w_filecharf, FILEFOFF(msdosname) },
  54. { "Description", f_charfield, w_charfield, PKGIFPOFF(description) },
  55. /* Note that aliases are added to the nicknames table in parsehelp.c. */
  56. { 0 /* sentinel - tells code that list is ended */ }
  57. };
  58. #define NFIELDS (sizeof(fieldinfos)/sizeof(struct fieldinfo))
  59. const int nfields= NFIELDS;
  60. static void cu_parsedb(int argc, void **argv) { fclose((FILE*)*argv); }
  61. int parsedb(const char *filename, enum parsedbflags flags,
  62. struct pkginfo **donep, FILE *warnto, int *warncount) {
  63. /* warnto, warncount and donep may be null.
  64. * If donep is not null only one package's information is expected.
  65. */
  66. static char readbuf[16384];
  67. FILE *file;
  68. struct pkginfo newpig, *pigp;
  69. struct pkginfoperfile *newpifp, *pifp;
  70. struct arbitraryfield *arp, **larpp;
  71. struct varbuf field, value;
  72. int lno;
  73. int pdone;
  74. int fieldencountered[NFIELDS];
  75. const struct fieldinfo *fip;
  76. const struct nickname *nick;
  77. const char *fieldname;
  78. char *hyphen;
  79. int *ip, i, c;
  80. if (warncount) *warncount= 0;
  81. newpifp= (flags & pdb_recordavailable) ? &newpig.available : &newpig.installed;
  82. file= fopen(filename,"r");
  83. if (!file) ohshite("failed to open package info file `%.255s' for reading",filename);
  84. if (!donep) /* Reading many packages, use a nice big buffer. */
  85. if (setvbuf(file,readbuf,_IOFBF,sizeof(readbuf)))
  86. ohshite("unable to set buffering on status file");
  87. push_cleanup(cu_parsedb,~0, 0,0, 1,(void*)file);
  88. varbufinit(&field); varbufinit(&value);
  89. lno= 1;
  90. pdone= 0;
  91. for (;;) { /* loop per package */
  92. i= sizeof(fieldencountered)/sizeof(int); ip= fieldencountered;
  93. while (i--) *ip++= 0;
  94. blankpackage(&newpig);
  95. blankpackageperfile(newpifp);
  96. for (;;) {
  97. c= getc(file); if (c!='\n' && c!=MSDOS_EOF_CHAR) break;
  98. lno++;
  99. }
  100. if (c == EOF) break;
  101. for (;;) { /* loop per field */
  102. varbufreset(&field);
  103. while (c!=EOF && !isspace(c) && c!=':' && c!=MSDOS_EOF_CHAR) {
  104. varbufaddc(&field,c);
  105. c= getc(file);
  106. }
  107. varbufaddc(&field,0);
  108. while (c != EOF && c != '\n' && isspace(c)) c= getc(file);
  109. if (c == EOF)
  110. parseerr(file,filename,lno, warnto,warncount,&newpig,0,
  111. "EOF after field name `%.50s'",field.buf);
  112. if (c == '\n')
  113. parseerr(file,filename,lno, warnto,warncount,&newpig,0,
  114. "newline in field name `%.50s'",field.buf);
  115. if (c == MSDOS_EOF_CHAR)
  116. parseerr(file,filename,lno, warnto,warncount,&newpig,0,
  117. "MSDOS EOF (^Z) in field name `%.50s'", field.buf);
  118. if (c != ':')
  119. parseerr(file,filename,lno, warnto,warncount,&newpig,0,
  120. "field name `%.50s' must be followed by colon", field.buf);
  121. varbufreset(&value);
  122. for (;;) {
  123. c= getc(file);
  124. if (c == EOF || c == '\n' || !isspace(c)) break;
  125. }
  126. if (c == EOF)
  127. parseerr(file,filename,lno, warnto,warncount,&newpig,0,
  128. "EOF before value of field `%.50s' (missing final newline)",
  129. field.buf);
  130. if (c == MSDOS_EOF_CHAR)
  131. parseerr(file,filename,lno, warnto,warncount,&newpig,0,
  132. "MSDOS EOF char in value of field `%.50s' (missing newline?)",
  133. field.buf);
  134. for (;;) {
  135. if (c == '\n' || c == MSDOS_EOF_CHAR) {
  136. lno++;
  137. c= getc(file);
  138. if (c == EOF || c == '\n' || !isspace(c)) break;
  139. ungetc(c,file);
  140. c= '\n';
  141. } else if (c == EOF) {
  142. parseerr(file,filename,lno, warnto,warncount,&newpig,0,
  143. "EOF during value of field `%.50s' (missing final newline)",
  144. field.buf);
  145. }
  146. varbufaddc(&value,c);
  147. c= getc(file);
  148. }
  149. while (value.used && isspace(value.buf[value.used-1])) value.used--;
  150. varbufaddc(&value,0);
  151. fieldname= field.buf;
  152. for (nick= nicknames; nick->nick && strcasecmp(nick->nick,fieldname); nick++);
  153. if (nick->nick) fieldname= nick->canon;
  154. for (fip= fieldinfos, ip= fieldencountered;
  155. fip->name && strcasecmp(fieldname,fip->name);
  156. fip++, ip++);
  157. if (fip->name) {
  158. if (*ip++)
  159. parseerr(file,filename,lno, warnto,warncount,&newpig,0,
  160. "duplicate value for `%s' field", fip->name);
  161. fip->rcall(&newpig,newpifp,flags,filename,lno-1,warnto,warncount,value.buf,fip);
  162. } else {
  163. if (strlen(fieldname)<2)
  164. parseerr(file,filename,lno, warnto,warncount,&newpig,0,
  165. "user-defined field name `%s' too short", fieldname);
  166. larpp= &newpifp->arbs;
  167. while ((arp= *larpp) != 0) {
  168. if (!strcasecmp(arp->name,fieldname))
  169. parseerr(file,filename,lno, warnto,warncount,&newpig,0,
  170. "duplicate value for user-defined field `%.50s'", fieldname);
  171. larpp= &arp->next;
  172. }
  173. arp= nfmalloc(sizeof(struct arbitraryfield));
  174. arp->name= nfstrsave(fieldname);
  175. arp->value= nfstrsave(value.buf);
  176. arp->next= 0;
  177. *larpp= arp;
  178. }
  179. if (c == EOF || c == '\n' || c == MSDOS_EOF_CHAR) break;
  180. } /* loop per field */
  181. if (pdone && donep)
  182. parseerr(file,filename,lno, warnto,warncount,&newpig,0,
  183. "several package info entries found, only one allowed");
  184. parsemustfield(file,filename,lno, warnto,warncount,&newpig,0,
  185. &newpig.name, "package name");
  186. if ((flags & pdb_recordavailable) || newpig.status != stat_notinstalled) {
  187. parsemustfield(file,filename,lno, warnto,warncount,&newpig,1,
  188. &newpifp->description, "description");
  189. parsemustfield(file,filename,lno, warnto,warncount,&newpig,1,
  190. &newpifp->maintainer, "maintainer");
  191. parsemustfield(file,filename,lno, warnto,warncount,&newpig,1,
  192. &newpifp->version, "version");
  193. }
  194. if (flags & pdb_recordavailable)
  195. parsemustfield(file,filename,lno, warnto,warncount,&newpig,1,
  196. &newpifp->architecture, "architecture");
  197. else if (newpifp->architecture && *newpifp->architecture)
  198. newpifp->architecture= 0;
  199. /* Break out the revision */
  200. if (newpifp->revision) {
  201. parseerr(file,filename,lno, warnto,warncount,&newpig,1,
  202. "obsolete `Revision' or `Package-Revision' field used");
  203. } else if (newpifp->version) {
  204. hyphen= strrchr(newpifp->version,'-');
  205. if (hyphen) {
  206. *hyphen++= 0;
  207. newpifp->revision= hyphen;
  208. } else {
  209. newpifp->revision= nfstrsave("");
  210. }
  211. }
  212. /* Check the Config-Version information:
  213. * If there is a Config-Version it is definitely to be used, but
  214. * there shouldn't be one if the package is `installed' (in which case
  215. * the Version and/or Revision will be copied) or if the package is
  216. * `not-installed' (in which case there is no Config-Version).
  217. */
  218. if (!(flags & pdb_recordavailable)) {
  219. if (newpig.configversion) {
  220. if (newpig.status == stat_installed || newpig.status == stat_notinstalled)
  221. parseerr(file,filename,lno, warnto,warncount,&newpig,0,
  222. "Configured-Version for package with inappropriate Status");
  223. } else {
  224. if (newpig.status == stat_installed) {
  225. newpig.configversion= newpifp->version;
  226. newpig.configrevision= newpifp->revision;
  227. }
  228. }
  229. }
  230. pigp= findpackage(newpig.name);
  231. pifp= (flags & pdb_recordavailable) ? &pigp->available : &pigp->installed;
  232. if (!pifp->valid) blankpackageperfile(pifp);
  233. if (!(flags & pdb_preferversion) ||
  234. versioncompare(newpifp->version,newpifp->revision,
  235. pifp->version,pifp->revision) >= 0) {
  236. /* If we're ignoring older versions compare version numbers
  237. * and only process this entry if it's a higher version.
  238. */
  239. /* Copy the priority and section across, but don't overwrite existing
  240. * values if the pdb_weakclassification flag is set.
  241. */
  242. if (newpig.section && *newpig.section &&
  243. !((flags & pdb_weakclassification) && pigp->section && *pigp->section))
  244. pigp->section= newpig.section;
  245. if (newpig.priority != pri_unknown &&
  246. !((flags & pdb_weakclassification) && pigp->priority != pri_unknown)) {
  247. pigp->priority= newpig.priority;
  248. if (newpig.priority == pri_other) pigp->otherpriority= newpig.otherpriority;
  249. }
  250. /* Sort out the dependency mess. */
  251. copy_dependency_links(pigp,&pifp->depends,newpifp->depends,
  252. (flags & pdb_recordavailable) ? 1 : 0);
  253. /* Leave the `depended' pointer alone, we've just gone to such
  254. * trouble to get it right :-). The `depends' pointer in
  255. * pifp was indeed also updated by copy_dependency_links,
  256. * but since the value was that from newpifp anyway there's
  257. * no need to copy it back.
  258. */
  259. newpifp->depended= pifp->depended;
  260. /* Copy across data */
  261. memcpy(pifp,newpifp,sizeof(struct pkginfoperfile));
  262. if (!(flags & pdb_recordavailable)) {
  263. pigp->want= newpig.want;
  264. pigp->eflag= newpig.eflag;
  265. pigp->status= newpig.status;
  266. pigp->configversion= newpig.configversion;
  267. pigp->configrevision= newpig.configrevision;
  268. pigp->files= 0;
  269. } else {
  270. pigp->files= newpig.files;
  271. }
  272. }
  273. if (donep) *donep= pigp;
  274. pdone++;
  275. if (c == EOF) break;
  276. if (c == '\n') lno++;
  277. }
  278. if (ferror(file)) ohshite("failed to read from `%.255s'",filename);
  279. pop_cleanup(0);
  280. if (fclose(file)) ohshite("failed to close after read: `%.255s'",filename);
  281. if (donep && !pdone) ohshit("no package information in `%.255s'",filename);
  282. varbuffree(&field); varbuffree(&value);
  283. return pdone;
  284. }
  285. void copy_dependency_links(struct pkginfo *pkg,
  286. struct dependency **updateme,
  287. struct dependency *newdepends,
  288. int available) {
  289. /* This routine is used to update the `reverse' dependency pointers
  290. * when new `forwards' information has been constructed. It first
  291. * removes all the links based on the old information. The old
  292. * information starts in *updateme; after much brou-ha-ha
  293. * the reverse structures are created and *updateme is set
  294. * to the value from newdepends.
  295. *
  296. * Parameters are:
  297. * pkg - the package we're doing this for. This is used to
  298. * construct correct uplinks.
  299. * updateme - the forwards dependency pointer that we are to
  300. * update. This starts out containing the old forwards
  301. * info, which we use to unthread the old reverse
  302. * links. After we're done it is updated.
  303. * newdepends - the value that we ultimately want to have in
  304. * updateme.
  305. * It is likely that the backward pointer for the package in
  306. * question (`depended') will be updated by this routine,
  307. * but this will happen by the routine traversing the dependency
  308. * data structures. It doesn't need to be told where to update
  309. * that; I just mention it as something that one should be
  310. * cautious about.
  311. */
  312. struct dependency *dyp;
  313. struct deppossi *dop;
  314. struct pkginfoperfile *addtopifp;
  315. /* Delete `backward' (`depended') links from other packages to
  316. * dependencies listed in old version of this one. We do this by
  317. * going through all the dependencies in the old version of this
  318. * one and following them down to find which deppossi nodes to
  319. * remove.
  320. */
  321. for (dyp= *updateme; dyp; dyp= dyp->next) {
  322. for (dop= dyp->list; dop; dop= dop->next) {
  323. if (dop->backrev)
  324. dop->backrev->nextrev= dop->nextrev;
  325. else
  326. if (available)
  327. dop->ed->available.depended= dop->nextrev;
  328. else
  329. dop->ed->installed.depended= dop->nextrev;
  330. if (dop->nextrev)
  331. dop->nextrev->backrev= dop->backrev;
  332. }
  333. }
  334. /* Now fill in new `ed' links from other packages to dependencies listed
  335. * in new version of this one, and set our uplinks correctly.
  336. */
  337. for (dyp= newdepends; dyp; dyp= dyp->next) {
  338. dyp->up= pkg;
  339. for (dop= dyp->list; dop; dop= dop->next) {
  340. addtopifp= available ? &dop->ed->available : &dop->ed->installed;
  341. if (!addtopifp->valid) blankpackageperfile(addtopifp);
  342. dop->nextrev= addtopifp->depended;
  343. dop->backrev= 0;
  344. if (addtopifp->depended)
  345. addtopifp->depended->backrev= dop;
  346. addtopifp->depended= dop;
  347. }
  348. }
  349. /* Finally, we fill in the new value. */
  350. *updateme= newdepends;
  351. }