/* * Copyright (C) 2011-2013 Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "config.h" #include #include #include #include #include #include #include "rpmutils.h" #include "dd_utils.h" static const char shortopts[] = "a:d:k:v"; static const char *usage = "Usage: dd_list [-vh] -k -d -a \n"; enum { OPT_NONE = 0, }; static const struct option longopts[] = { //{name, no_argument | required_argument | optional_argument, *flag, val} {"directory", required_argument, NULL, 'd'}, {"kernel", required_argument, NULL, 'k'}, {"anaconda", required_argument, NULL, 'a'}, {"verbose", no_argument, NULL, 'v'}, {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0} }; static const char *options_help [][2] = { {"directory", "Directory to search for *.rpm files"}, {"kernel", "kernel version"}, {"anaconda", "anaconda version"}, {"verbose", "Verbose output"}, {"help", "Show this help"}, {NULL, NULL} }; struct _version_struct { char* kernel; char* anaconda; }; int globErrFunc(const char *epath, int eerrno) { /* TODO check fatal errors */ return 0; } /** * Show the available options and their help strings */ void show_help() { int i; printf("%s", usage); for (i=0; options_help[i][0]; i++) { printf(" -%c, --%-20s %s\n", options_help[i][0][0], options_help[i][0], options_help[i][1]); } } /** * check if the RPM in question provides * Provides: = * we use it to check if kernel-modules = * and installer-enhancement = */ int dlabelProvides(const char* dep, const char* version, uint32_t sense, void *userptr) { char *kernelver = ((struct _version_struct*)userptr)->kernel; char *anacondaver = ((struct _version_struct*)userptr)->anaconda; int packageflags = 0; if (version == NULL) { logMessage(DEBUGLVL, "Provides does not have version specified!"); return 0; } logMessage(DEBUGLVL, "Provides: %s = %s\n", dep, version); /* is it a modules package? */ if (!strcmp(dep, "kernel-modules")) { /* * exception for 6.0 and 6.1 DDs, we changed the logic a bit and need to maintain compatibility. */ if ((!strncmp(version, "2.6.32-131", 10)) || (!strncmp(version, "2.6.32-71", 9))) packageflags |= dup_modules | dup_firmwares; /* * Use this package only if the version match string is true for this kernel version */ if (!matchVersions(kernelver, sense, version)) packageflags |= dup_modules | dup_firmwares; } /* is it an app package? */ if (!strcmp(dep, "installer-enhancement")) { /* * If the version string matches anaconda version, unpack binaries to /tmp/DD */ if (!matchVersions(anacondaver, sense, version)) packageflags |= dup_binaries | dup_libraries; } return packageflags; } /** * Print information about the rpm to stdout */ int dlabelOK(const char* source, Header *h, int packageflags) { struct rpmtd_s tdname; struct rpmtd_s tddesc; const char *name; const char *description; if (!headerGet(*h, RPMTAG_NAME, &tdname, HEADERGET_MINMEM)) return 0; if (!headerGet(*h, RPMTAG_DESCRIPTION, &tddesc, HEADERGET_MINMEM)){ rpmtdFreeData(&tdname); return 0; } /* iterator */ name = rpmtdNextString(&tdname); description = rpmtdNextString(&tddesc); fprintf(stdout, "%s\n%s\n", source, name); if (packageflags & dup_modules) fprintf(stdout, "modules "); if (packageflags & dup_firmwares) fprintf(stdout, "firmwares "); if (packageflags & dup_binaries) fprintf(stdout, "binaries "); if (packageflags & dup_libraries) fprintf(stdout, "libraries "); fprintf(stdout, "\n%s\n---\n", description); rpmtdFreeData(&tdname); rpmtdFreeData(&tddesc); return 0; } int main(int argc, char *argv[]) { int rc = 0; int option; int option_index; char *path = NULL; int path_len; int verbose = 0; struct _version_struct versions = {NULL, NULL}; char *globpattern; glob_t globres; char** globitem; while ((option = getopt_long(argc, argv, shortopts, longopts, &option_index)) != -1) { switch (option) { case 0: /* long option */ break; case 'd': if (path) { logMessage(ERROR, "Multiple -d arguments\n"); show_help(); rc = 1; goto cleanup; } path = strdup(optarg); break; case 'k': if (versions.kernel) { logMessage(ERROR, "Multiple -k arguments\n"); show_help(); rc = 1; goto cleanup; } versions.kernel = strdup(optarg); break; case 'a': if (versions.anaconda) { logMessage(ERROR, "Multiple -a arguments\n"); show_help(); rc = 1; goto cleanup; } versions.anaconda = strdup(optarg); break; case 'v': verbose = 1; break; case 'h': show_help(); rc = 0; goto cleanup; } } if (!path || !versions.kernel || !versions.anaconda) { show_help(); rc = 1; goto cleanup; } init_rpm(); path_len = strlen(path); /* determine if the path is rpm filename or directory */ if ((path_len > 5) && (strcmp(path + path_len - 4, ".rpm") == 0)) { if (verbose) { /* careful - standard output is being parsed */ printf("Listing DD file %s\n", path); } checkDDRPM(path, dlabelProvides, NULL, dlabelOK, &versions); } else { if (verbose) { /* careful - standard output is being parsed */ printf("Listing DD dir %s\n", path); } /* look for all .rpm files in a given direcory */ checked_asprintf(&globpattern, "%s/*.rpm", path); if (!glob(globpattern, GLOB_NOSORT|GLOB_NOESCAPE, globErrFunc, &globres)) { /* iterate over all rpm files */ globitem = globres.gl_pathv; while (globres.gl_pathc>0 && globitem != NULL && *globitem != NULL) { checkDDRPM(*globitem, dlabelProvides, NULL, dlabelOK, &versions); globitem++; } globfree(&globres); /* end of iteration */ } free(globpattern); } cleanup: free(path); free(versions.kernel); free(versions.anaconda); return rc; }