/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include #include #include #include #include #include #include "list.h" #include "protodir.h" #include "arch.h" static pkg_list *packages[HASH_SIZE]; #define HASH(name) (hash(name) % HASH_SIZE) int processed_package(const char *pkgname) { int bucket; pkg_list *tmp; bucket = HASH(pkgname); for (tmp = packages[bucket]; tmp != NULL; tmp = tmp->next) { if (strcmp(tmp->pkg_name, pkgname) == 0) return (1); } return (0); } void mark_processed(const char *pkgname) { int bucket; pkg_list *tmp; bucket = HASH(pkgname); tmp = malloc(sizeof (pkg_list)); bzero(tmp, sizeof (pkg_list)); (void) strcpy(tmp->pkg_name, pkgname); tmp->next = packages[bucket]; packages[bucket] = tmp; } static pkg_list * add_dependency(pkg_list *dependlist, const char *pkgname) { pkg_list *tmp; pkg_list *pkg; pkg = malloc(sizeof (pkg_list)); bzero(pkg, sizeof (pkg_list)); (void) strcpy(pkg->pkg_name, pkgname); /* easy case */ if (dependlist == NULL) return (pkg); /* insert at end, since the order matters */ for (tmp = dependlist; tmp->next != NULL; tmp = tmp->next) { /* NULL */ } tmp->next = pkg; return (dependlist); } static void free_dependency_list(pkg_list *dependlist) { pkg_list *tmp; while (dependlist) { tmp = dependlist; dependlist = dependlist->next; tmp->next = NULL; free(tmp); } } #ifdef DEBUG void print_dependencies(const char *pkgname, pkg_list *dependlist) { pkg_list *tmp; fprintf(stderr, "%s:", pkgname); for (tmp = dependlist; tmp != NULL; tmp = tmp->next) fprintf(stderr, " %s", tmp->pkg_name); fprintf(stderr, "\n"); } #endif static char *suffix_list[] = { #if defined(__i386) ".i", #elif defined(__sparc) ".c", ".d", ".m", ".u", ".v", #else #error "Unknown architecture." #endif NULL, }; static pkg_list * find_dependencies(const char *pkgname, const char *parentdir) { char dependfile[MAXPATHLEN + 1]; char pkgdir[MAXPATHLEN + 1]; char buf[BUFSIZ]; char deppkg[MAXNAME]; char archpkg[MAXNAME]; struct stat sbuf; FILE *fp; pkg_list *dependlist = NULL; char **suffixes; (void) sprintf(dependfile, "%s/%s/depend", parentdir, pkgname); fp = fopen(dependfile, "r"); if (fp == NULL) { /* * depend won't exist in ON packages until a build * has been done, but it would be nice if you didn't have * to do that. So try the generic depend file that those * packages would copy in during the build. */ (void) sprintf(dependfile, "%s/common_files/depend", parentdir); fp = fopen(dependfile, "r"); if (fp == NULL) return (NULL); } while (fgets(buf, BUFSIZ, fp) != NULL) { if ((buf[0] == '\0') || (buf[0] == '#') || isspace(buf[0])) continue; /* we only care about prerequisites */ if (buf[0] != 'P') continue; (void) sscanf(buf, "P %s", deppkg); /* * We have to be careful with some of the packages that are * listed as dependencies but exist under a different name - * SUNWcar is good, because it's actually SUNWcar.{c,d,i,m,u}. * What do we do there? We can't just go for all the '.' * packages, since on x86 we only want the .i one, and on sparc * we want everything _but_ .i. Maybe * * I think perhaps what we do is, if we don't find a package * dependency, on intel we append '.i' and try for that, and on * sparc we try the other extensions. Any we find get added. * * Note also we're quiet on failures. This is because you might * be dependant on some outside package. */ (void) sprintf(pkgdir, "%s/%s", parentdir, deppkg); if (stat(pkgdir, &sbuf) == -1) { if (errno != ENOENT) { continue; } for (suffixes = &suffix_list[0]; *suffixes != NULL; suffixes++) { (void) sprintf(archpkg, "%s%s", deppkg, *suffixes); (void) sprintf(pkgdir, "%s/%s", parentdir, archpkg); if (stat(pkgdir, &sbuf) == -1) { continue; } if (!S_ISDIR(sbuf.st_mode)) { continue; } /* found one */ dependlist = add_dependency(dependlist, archpkg); } } if (!S_ISDIR(sbuf.st_mode)) { continue; } dependlist = add_dependency(dependlist, deppkg); } (void) fclose(fp); return (dependlist); } int process_dependencies(const char *pkgname, const char *parentdir, elem_list *list, int verbose) { int count = 0; char pkgdir[MAXPATHLEN + 1]; pkg_list *dependlist; pkg_list *tmp; dependlist = find_dependencies(pkgname, parentdir); /* * print_dependencies(pkgname, dependlist); */ if (dependlist == NULL) return (0); for (tmp = dependlist; tmp != NULL; tmp = tmp->next) { (void) sprintf(pkgdir, "%s/%s", parentdir, tmp->pkg_name); count += process_package_dir(tmp->pkg_name, pkgdir, list, verbose); } free_dependency_list(dependlist); return (count); }