diff options
author | Mike Frysinger <vapier@gentoo.org> | 2006-04-21 03:14:51 +0000 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2006-04-21 03:14:51 +0000 |
commit | c1835709ef39b970b37a0666a336eb6bc2c4450a (patch) | |
tree | 721172a3fa6cbe3d62bc1f9fdd3e2e9facc24266 /qglsa.c | |
parent | fix signed warnings (diff) | |
download | portage-utils-c1835709ef39b970b37a0666a336eb6bc2c4450a.tar.gz portage-utils-c1835709ef39b970b37a0666a336eb6bc2c4450a.tar.bz2 portage-utils-c1835709ef39b970b37a0666a336eb6bc2c4450a.zip |
flesh out more features
Diffstat (limited to 'qglsa.c')
-rw-r--r-- | qglsa.c | 242 |
1 files changed, 198 insertions, 44 deletions
@@ -1,13 +1,13 @@ /* * Copyright 2005-2006 Gentoo Foundation * Distributed under the terms of the GNU General Public License v2 - * $Header: /var/cvsroot/gentoo-projects/portage-utils/qglsa.c,v 1.4 2006/01/26 02:32:04 vapier Exp $ + * $Header: /var/cvsroot/gentoo-projects/portage-utils/qglsa.c,v 1.5 2006/04/21 03:14:51 vapier Exp $ * * Copyright 2005-2006 Ned Ludd - <solar@gentoo.org> * Copyright 2005-2006 Mike Frysinger - <vapier@gentoo.org> */ -#ifdef APPLET_glsa +#ifdef APPLET_qglsa #define QGLSA_DB "/var/cache/edb/glsa" @@ -26,15 +26,100 @@ static const char *qglsa_opts_help[] = { "List GLSAs", "Dump info about GLSAs", "Test if system is affected by GLSAs", - "Show what would be done to fix the GLSA", + "Do everything but actually emerge the package", "Auto-apply GLSAs to the system", "Mark specified GLSAs as fixed", COMMON_OPTS_HELP }; -static const char qglsa_rcsid[] = "$Id: qglsa.c,v 1.4 2006/01/26 02:32:04 vapier Exp $"; +static const char qglsa_rcsid[] = "$Id: qglsa.c,v 1.5 2006/04/21 03:14:51 vapier Exp $"; #define qglsa_usage(ret) usage(ret, QGLSA_FLAGS, qglsa_long_opts, qglsa_opts_help, lookup_applet_idx("qglsa")) +static char *qglsa_load_list(void); +static char *qglsa_load_list(void) +{ + char *ret; + struct stat st; + + if (stat(QGLSA_DB, &st)) + return NULL; + + ret = xmalloc(st.st_size+1); + + if (!eat_file(QGLSA_DB, ret, st.st_size)) { + free(ret); + return NULL; + } + + return ret; +} +static void qglsa_append_to_list(const char *glsa); +static void qglsa_append_to_list(const char *glsa) +{ + FILE *f; + if ((f = fopen(QGLSA_DB, "a")) != NULL) { + fwrite(glsa, 1, strlen(glsa), f); + fclose(f); + } +} + +static void qglsa_decode_entities(char *xml_buf, size_t len); +static void qglsa_decode_entities(char *xml_buf, size_t len) +{ + const char const *encoded[] = { "<", ">", """, "&"}; + const char const *decoded[] = { "<", ">", "\"", "&"}; + int i; + char *p, *q; + + /* most things dont have entities so let's just bail real quick */ + if (strchr(xml_buf, '&') == NULL) + return; + + for (i=0; i<ARRAY_SIZE(encoded); ++i) { + /* for now, we assume that strlen(decoded) is always 1 ... if + * this changes, we have to update the 'p++' accordingly */ + while ((p=strstr(xml_buf, encoded[i])) != NULL) { + strcpy(p, decoded[i]); + q = p++ + strlen(encoded[i]); + memmove(p, q, len-(q-xml_buf)+1); + } + } +} + +static char *qglsa_get_xml_tag_attribute(const char *xml_buf, const char *tag, const char *attribute) +{ + static char tmp_buf[BUFSIZE]; + char *start, *end, *start_attr, *end_attr; + + /* find the start of this tag */ + sprintf(tmp_buf, "<%s ", tag); + if ((start = strstr(xml_buf, tmp_buf)) == NULL) + return NULL; + + /* find the end of this tag */ + start += strlen(tmp_buf) - 1; + if ((end = strchr(start, '>')) == NULL) + return NULL; + + /* find the attribute in this tag */ + sprintf(tmp_buf, " %s=", attribute); + if ((start_attr = strstr(start, tmp_buf)) == NULL) + return NULL; + + /* get the value */ + start_attr += strlen(tmp_buf); + if (*start_attr == '"') { + end_attr = strchr(++start_attr, '"'); + } else { + end_attr = strchr(start_attr, ' '); + } + assert(end_attr - start_attr < sizeof(tmp_buf)); + memcpy(tmp_buf, start_attr, end_attr-start_attr); + tmp_buf[end_attr-start_attr] = '\0'; + + qglsa_decode_entities(tmp_buf, end-start); + return tmp_buf; +} static char *qglsa_get_xml_tag(const char *xml_buf, const char *tag) { static char tmp_buf[BUFSIZE]; @@ -48,11 +133,13 @@ static char *qglsa_get_xml_tag(const char *xml_buf, const char *tag) } start += strlen(tmp_buf); sprintf(tmp_buf, "</%s>", tag); - if ((end = strstr(xml_buf, tmp_buf)) == NULL) + if ((end = strstr(start, tmp_buf)) == NULL) return NULL; assert(end - start < sizeof(tmp_buf)); memcpy(tmp_buf, start, end - start); tmp_buf[end - start] = '\0'; + + qglsa_decode_entities(tmp_buf, end-start); return tmp_buf; } @@ -71,12 +158,13 @@ static void qglsa_act_list(char *glsa) */ int qglsa_main(int argc, char **argv) { - enum { GLSA_FUNKYTOWN, GLSA_LIST, GLSA_DUMP, GLSA_TEST, GLSA_PRETEND, GLSA_FIX, GLSA_INJECT }; + enum { GLSA_FUNKYTOWN, GLSA_LIST, GLSA_DUMP, GLSA_TEST, GLSA_FIX, GLSA_INJECT }; int i; DIR *dir; struct dirent *dentry; + struct stat st; char buf[BUFSIZE*4]; - char *s, *p; + char *s, *p, *glsa_fixed_list; int action = GLSA_FUNKYTOWN; int all_glsas = 0; @@ -89,7 +177,7 @@ int qglsa_main(int argc, char **argv) case 'l': set_action(GLSA_LIST); break; case 'd': set_action(GLSA_DUMP); break; case 't': set_action(GLSA_TEST); break; - case 'p': set_action(GLSA_PRETEND); break; + case 'p': pretend = 1; break; case 'f': set_action(GLSA_FIX); break; case 'i': set_action(GLSA_INJECT); break; COMMON_GETOPTS_CASES(qglsa) @@ -100,58 +188,124 @@ int qglsa_main(int argc, char **argv) if (action != GLSA_LIST && optind == argc) err("specified action requires a list, either 'all', 'new', or GLSA numbers"); - if (optind+1 == argc) { - if (!strcmp(argv[optind], "all")) + glsa_fixed_list = NULL; + for (i = optind; i < argc; ++i) { + if (!strcmp(argv[i], "all")) { all_glsas = 1; - else if (!strcmp(argv[optind], "new")) + if (optind+1 != argc) + err("You may only use class names by themselves"); + } else if (!strcmp(argv[i], "new")) { all_glsas = 0; + if (optind+1 != argc) + err("You may only use class names by themselves"); + } } + glsa_fixed_list = qglsa_load_list(); if (chdir(portdir) != 0) errp("could not chdir to portdir %s", portdir); if (chdir("./metadata/glsa") != 0) errp("could not chdir to glsa dir"); - if ((dir = opendir(".")) == NULL) - return EXIT_FAILURE; - while ((dentry = readdir(dir)) != NULL) { - if (strncmp(dentry->d_name, "glsa-", 5)) - continue; + switch (action) { + /*case GLSA_FIX:*/ + case GLSA_INJECT: + for (i = optind; i < argc; ++i) { + snprintf(buf, sizeof(buf), "glsa-%s.xml", argv[i]); + if (stat(buf, &st)) { + warn("Skipping invalid GLSA '%s'", argv[i]); + continue; + } + if (glsa_fixed_list) { + if (strstr(glsa_fixed_list, argv[i])) { + warn("Skipping already installed GLSA %s", argv[i]); + continue; + } + } + if (action == GLSA_FIX) { + printf("Fixing GLSA %s%s%s\n", GREEN, argv[i], NORM); + continue; + } else if (action == GLSA_INJECT) + printf("Injecting GLSA %s%s%s\n", GREEN, argv[i], NORM); + qglsa_append_to_list(argv[i]); + } + break; - if (eat_file(dentry->d_name, buf, sizeof(buf)) == 0) - errp("could not eat %s", dentry->d_name); + default: + if ((dir = opendir(".")) == NULL) + return EXIT_FAILURE; - if ((s = strchr(dentry->d_name, '.')) != NULL) + while ((dentry = readdir(dir)) != NULL) { + /* validate this file as a proper glsa */ + char glsa_id[20]; + if (strncmp(dentry->d_name, "glsa-", 5)) + continue; + strcpy(glsa_id, dentry->d_name + 5); + if ((s = strchr(glsa_id, '.')) == NULL || memcmp(s, ".xml\0", 5)) + continue; *s = '\0'; - switch (action) { - case GLSA_LIST: - s = qglsa_get_xml_tag(buf, "title"); - p = dentry->d_name + 5; - printf("%s%s%s: %s\n", GREEN, p, NORM, s); - break; - case GLSA_DUMP: - s = qglsa_get_xml_tag(buf, "title"); - p = dentry->d_name + 5; - printf("%s%s%s: %s\n", GREEN, p, NORM, s); - s = qglsa_get_xml_tag(buf, "bug"); - printf(" %sRef%s: http://bugs.gentoo.org/%s\n", BLUE, NORM, s); - s = qglsa_get_xml_tag(buf, "access"); - printf(" %saccess%s: %s\n", BLUE, NORM, s); - s = qglsa_get_xml_tag(buf, "synopsis"); - printf(" %ssynopsis%s:\n%s\n", BLUE, NORM, s); - s = qglsa_get_xml_tag(buf, "affected"); - printf(" %saffected%s:\n%s\n", BLUE, NORM, s); - if (verbose) { - s = qglsa_get_xml_tag(buf, "description"); - printf(" %sdescription%s:\n%s\n", BLUE, NORM, s); - s = qglsa_get_xml_tag(buf, "workaround"); - printf(" %sworkaround%s:\n%s\n", BLUE, NORM, s); + /* see if we want to skip glsa's already fixed */ + if (!all_glsas && glsa_fixed_list) { + if (strstr(glsa_fixed_list, glsa_id)) + continue; + } + + /* load the glsa into memory */ + if (eat_file(dentry->d_name, buf, sizeof(buf)) == 0) + errp("could not eat %s", dentry->d_name); + + /* now lets figure out what to do with this memory */ + switch (action) { + case GLSA_LIST: + s = qglsa_get_xml_tag(buf, "title"); + printf("%s%s%s: %s", GREEN, glsa_id, NORM, s); + if (verbose) { + int num_shown = 0; + p = qglsa_get_xml_tag(buf, "affected"); + if (p) { + printf(" ("); + while (p++) { + s = qglsa_get_xml_tag_attribute(p, "package", "name"); + if (s) { + if (verbose < 2 && ++num_shown > 3) { + printf(" ..."); + break; + } + printf(" %s", s); + } else + break; + p = strstr(p, "</package>"); + } + printf(" )"); + } + } + printf("\n"); + break; + case GLSA_DUMP: + s = qglsa_get_xml_tag(buf, "title"); + printf("%s%s%s: %s\n", GREEN, glsa_id, NORM, s); + s = qglsa_get_xml_tag(buf, "bug"); + printf(" %sRef%s: http://bugs.gentoo.org/%s\n", BLUE, NORM, s); + s = qglsa_get_xml_tag(buf, "access"); + printf(" %saccess%s: %s\n", BLUE, NORM, s); + s = qglsa_get_xml_tag(buf, "synopsis"); + printf(" %ssynopsis%s:\n%s\n", BLUE, NORM, s); + s = qglsa_get_xml_tag(buf, "affected"); + printf(" %saffected%s:\n%s\n", BLUE, NORM, s); + if (verbose) { + s = qglsa_get_xml_tag(buf, "description"); + printf(" %sdescription%s:\n%s\n", BLUE, NORM, s); + s = qglsa_get_xml_tag(buf, "workaround"); + printf(" %sworkaround%s:\n%s\n", BLUE, NORM, s); + } + break; } - break; } + closedir(dir); } - closedir(dir); + + free(glsa_fixed_list); return EXIT_SUCCESS; } |