pkg_parse.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. /* pkg_parse.c - the opkg package management system
  2. Copyright (C) 2009 Ubiq Technologies <graham.gower@gmail.com>
  3. Steven M. Ayer
  4. Copyright (C) 2002 Compaq Computer Corporation
  5. This program is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2, or (at
  8. your option) any later version.
  9. This program is distributed in the hope that it will be useful, but
  10. WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. General Public License for more details.
  13. */
  14. #include "config.h"
  15. #include <stdio.h>
  16. #include <ctype.h>
  17. #include <unistd.h>
  18. #include "pkg.h"
  19. #include "opkg_utils.h"
  20. #include "pkg_parse.h"
  21. #include "pkg_depends.h"
  22. #include "libbb/libbb.h"
  23. #include "file_util.h"
  24. #include "parse_util.h"
  25. static void parse_status(pkg_t * pkg, const char *sstr)
  26. {
  27. char sw_str[64], sf_str[64], ss_str[64];
  28. if (sscanf(sstr, "Status: %63s %63s %63s", sw_str, sf_str, ss_str) != 3) {
  29. opkg_msg(ERROR, "Failed to parse Status line for %s\n",
  30. pkg->name);
  31. return;
  32. }
  33. pkg->state_want = pkg_state_want_from_str(sw_str);
  34. pkg->state_flag |= pkg_state_flag_from_str(sf_str);
  35. pkg->state_status = pkg_state_status_from_str(ss_str);
  36. }
  37. static void parse_conffiles(pkg_t * pkg, const char *cstr)
  38. {
  39. conffile_list_t *cl;
  40. char file_name[1024], md5sum[85];
  41. if (sscanf(cstr, "%1023s %84s", file_name, md5sum) != 2) {
  42. opkg_msg(ERROR, "Failed to parse Conffiles line for %s\n",
  43. pkg->name);
  44. return;
  45. }
  46. cl = pkg_get_ptr(pkg, PKG_CONFFILES);
  47. if (cl)
  48. conffile_list_append(cl, file_name, md5sum);
  49. }
  50. int parse_version(pkg_t * pkg, const char *vstr)
  51. {
  52. char *colon, *rev;
  53. if (strncmp(vstr, "Version:", 8) == 0)
  54. vstr += 8;
  55. while (*vstr && isspace(*vstr))
  56. vstr++;
  57. colon = strchr(vstr, ':');
  58. if (colon) {
  59. errno = 0;
  60. pkg_set_int(pkg, PKG_EPOCH, strtoul(vstr, NULL, 10));
  61. if (errno) {
  62. opkg_perror(ERROR, "%s: invalid epoch", pkg->name);
  63. }
  64. vstr = ++colon;
  65. }
  66. rev = strrchr(vstr, '-');
  67. if (rev) {
  68. *rev++ = '\0';
  69. pkg_set_string(pkg, PKG_REVISION, rev);
  70. }
  71. pkg_set_string(pkg, PKG_VERSION, vstr);
  72. return 0;
  73. }
  74. static char *parse_architecture(pkg_t *pkg, const char *str)
  75. {
  76. const char *s = str;
  77. const char *e;
  78. while (isspace(*s))
  79. s++;
  80. e = s + strlen(s);
  81. while (e > s && isspace(*e))
  82. e--;
  83. return pkg_set_architecture(pkg, s, e - s);
  84. }
  85. int pkg_parse_line(void *ptr, const char *line, uint mask)
  86. {
  87. pkg_t *pkg = (pkg_t *) ptr;
  88. abstract_pkg_t *ab_pkg = NULL;
  89. /* these flags are a bit hackish... */
  90. static int reading_conffiles = 0, reading_description = 0;
  91. static char *description = NULL;
  92. char *s;
  93. int ret = 0;
  94. /* Exclude globally masked fields. */
  95. mask |= conf->pfm;
  96. /* Flip the semantics of the mask. */
  97. mask ^= PFM_ALL;
  98. switch (*line) {
  99. case 'A':
  100. if ((mask & PFM_ARCHITECTURE) && is_field("Architecture", line))
  101. parse_architecture(pkg, line + strlen("Architecture") + 1);
  102. else if ((mask & PFM_AUTO_INSTALLED)
  103. && is_field("Auto-Installed", line)) {
  104. char *tmp = parse_simple("Auto-Installed", line);
  105. if (strcmp(tmp, "yes") == 0)
  106. pkg->auto_installed = 1;
  107. free(tmp);
  108. }
  109. break;
  110. case 'C':
  111. if ((mask & PFM_CONFFILES) && is_field("Conffiles", line)) {
  112. reading_conffiles = 1;
  113. reading_description = 0;
  114. goto dont_reset_flags;
  115. } else if ((mask & PFM_CONFLICTS)
  116. && is_field("Conflicts", line))
  117. parse_deplist(pkg, CONFLICTS, line + strlen("Conflicts") + 1);
  118. break;
  119. case 'D':
  120. if ((mask & PFM_DESCRIPTION) && is_field("Description", line)) {
  121. description = parse_simple("Description", line);
  122. reading_conffiles = 0;
  123. reading_description = 1;
  124. goto dont_reset_flags;
  125. } else if ((mask & PFM_DEPENDS) && is_field("Depends", line))
  126. parse_deplist(pkg, DEPEND, line + strlen("Depends") + 1);
  127. break;
  128. case 'E':
  129. if ((mask & PFM_ESSENTIAL) && is_field("Essential", line)) {
  130. char *tmp = parse_simple("Essential", line);
  131. if (strcmp(tmp, "yes") == 0)
  132. pkg->essential = 1;
  133. free(tmp);
  134. }
  135. break;
  136. case 'F':
  137. if ((mask & PFM_FILENAME) && is_field("Filename", line))
  138. pkg_set_string(pkg, PKG_FILENAME, line + strlen("Filename") + 1);
  139. break;
  140. case 'I':
  141. if ((mask & PFM_INSTALLED_SIZE)
  142. && is_field("Installed-Size", line)) {
  143. pkg_set_int(pkg, PKG_INSTALLED_SIZE, strtoul(line + strlen("Installed-Size") + 1, NULL, 0));
  144. } else if ((mask & PFM_INSTALLED_TIME)
  145. && is_field("Installed-Time", line)) {
  146. pkg_set_int(pkg, PKG_INSTALLED_TIME, strtoul(line + strlen("Installed-Time") + 1, NULL, 0));
  147. }
  148. break;
  149. case 'M':
  150. if ((mask & PFM_MD5SUM) && (is_field("MD5sum:", line) || is_field("MD5Sum:", line)))
  151. pkg_set_md5(pkg, line + strlen("MD5sum") + 1);
  152. else if ((mask & PFM_MAINTAINER)
  153. && is_field("Maintainer", line))
  154. pkg_set_string(pkg, PKG_MAINTAINER, line + strlen("Maintainer") + 1);
  155. break;
  156. case 'P':
  157. if ((mask & PFM_PACKAGE) && is_field("Package", line)) {
  158. pkg->name = parse_simple("Package", line);
  159. ab_pkg = abstract_pkg_fetch_by_name(pkg->name);
  160. if (ab_pkg && (ab_pkg->state_flag & SF_NEED_DETAIL)) {
  161. if (!(pkg->state_flag & SF_NEED_DETAIL)) {
  162. opkg_msg(DEPEND, "propagating abpkg flag to pkg %s\n", pkg->name);
  163. pkg->state_flag |= SF_NEED_DETAIL;
  164. }
  165. }
  166. }
  167. else if ((mask & PFM_PRIORITY) && is_field("Priority", line))
  168. pkg_set_string(pkg, PKG_PRIORITY, line + strlen("Priority") + 1);
  169. else if ((mask & PFM_PROVIDES) && is_field("Provides", line))
  170. parse_providelist(pkg, line + strlen("Provides") + 1);
  171. else if ((mask & PFM_PRE_DEPENDS)
  172. && is_field("Pre-Depends", line))
  173. parse_deplist(pkg, PREDEPEND, line + strlen("Pre-Depends") + 1);
  174. break;
  175. case 'R':
  176. if ((mask & PFM_RECOMMENDS) && is_field("Recommends", line))
  177. parse_deplist(pkg, RECOMMEND, line + strlen("Recommends") + 1);
  178. else if ((mask & PFM_REPLACES) && is_field("Replaces", line))
  179. parse_replacelist(pkg, line + strlen("Replaces") + 1);
  180. break;
  181. case 'S':
  182. if ((mask & PFM_SECTION) && is_field("Section", line))
  183. pkg_set_string(pkg, PKG_SECTION, line + strlen("Section") + 1);
  184. #ifdef HAVE_SHA256
  185. else if ((mask & PFM_SHA256SUM) && is_field("SHA256sum", line))
  186. pkg_set_sha256(pkg, line + strlen("SHA256sum") + 1);
  187. #endif
  188. else if ((mask & PFM_SIZE) && is_field("Size", line)) {
  189. pkg_set_int(pkg, PKG_SIZE, strtoul(line + strlen("Size") + 1, NULL, 0));
  190. } else if ((mask & PFM_SOURCE) && is_field("Source", line))
  191. pkg_set_string(pkg, PKG_SOURCE, line + strlen("Source") + 1);
  192. else if ((mask & PFM_STATUS) && is_field("Status", line))
  193. parse_status(pkg, line);
  194. else if ((mask & PFM_SUGGESTS) && is_field("Suggests", line))
  195. parse_deplist(pkg, SUGGEST, line + strlen("Suggests") + 1);
  196. break;
  197. case 'T':
  198. if ((mask & PFM_TAGS) && is_field("Tags", line))
  199. pkg_set_string(pkg, PKG_TAGS, line + strlen("Tags") + 1);
  200. break;
  201. case 'V':
  202. if ((mask & PFM_VERSION) && is_field("Version", line))
  203. parse_version(pkg, line);
  204. break;
  205. case ' ':
  206. if ((mask & PFM_DESCRIPTION) && reading_description) {
  207. if (isatty(1)) {
  208. description = xrealloc(description,
  209. strlen(description)
  210. + 1 + strlen(line) +
  211. 1);
  212. strcat(description, "\n");
  213. } else {
  214. description = xrealloc(description,
  215. strlen(description)
  216. + 1 + strlen(line));
  217. }
  218. strcat(description, (line));
  219. goto dont_reset_flags;
  220. } else if ((mask & PFM_CONFFILES) && reading_conffiles) {
  221. parse_conffiles(pkg, line);
  222. goto dont_reset_flags;
  223. }
  224. /* FALLTHROUGH */
  225. default:
  226. /* For package lists, signifies end of package. */
  227. if (line_is_blank(line)) {
  228. ret = 1;
  229. break;
  230. }
  231. }
  232. if (reading_description && description) {
  233. pkg_set_string(pkg, PKG_DESCRIPTION, description);
  234. free(description);
  235. reading_description = 0;
  236. description = NULL;
  237. }
  238. reading_conffiles = 0;
  239. dont_reset_flags:
  240. return ret;
  241. }
  242. int pkg_parse_from_stream(pkg_t * pkg, FILE * fp, uint mask)
  243. {
  244. int ret;
  245. char *buf;
  246. const size_t len = 4096;
  247. buf = xmalloc(len);
  248. ret =
  249. parse_from_stream_nomalloc(pkg_parse_line, pkg, fp, mask, &buf,
  250. len);
  251. free(buf);
  252. if (pkg->name == NULL) {
  253. /* probably just a blank line */
  254. ret = 1;
  255. }
  256. return ret;
  257. }