1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 28 #include <stdio.h> 29 #include <sys/param.h> 30 #include <fcntl.h> 31 #include <stdlib.h> 32 #include <strings.h> 33 #include <errno.h> 34 #include <dirent.h> 35 #include <ctype.h> 36 #include <sys/stat.h> 37 38 #include "list.h" 39 #include "protodir.h" 40 #include "arch.h" 41 42 static pkg_list *packages[HASH_SIZE]; 43 44 #define HASH(name) (hash(name) % HASH_SIZE) 45 46 int 47 processed_package(const char *pkgname) 48 { 49 int bucket; 50 pkg_list *tmp; 51 52 bucket = HASH(pkgname); 53 for (tmp = packages[bucket]; tmp != NULL; tmp = tmp->next) { 54 if (strcmp(tmp->pkg_name, pkgname) == 0) 55 return (1); 56 } 57 return (0); 58 } 59 60 void 61 mark_processed(const char *pkgname) 62 { 63 int bucket; 64 pkg_list *tmp; 65 66 bucket = HASH(pkgname); 67 tmp = malloc(sizeof (pkg_list)); 68 bzero(tmp, sizeof (pkg_list)); 69 (void) strcpy(tmp->pkg_name, pkgname); 70 tmp->next = packages[bucket]; 71 packages[bucket] = tmp; 72 } 73 74 static pkg_list * 75 add_dependency(pkg_list *dependlist, const char *pkgname) 76 { 77 pkg_list *tmp; 78 pkg_list *pkg; 79 80 pkg = malloc(sizeof (pkg_list)); 81 bzero(pkg, sizeof (pkg_list)); 82 (void) strcpy(pkg->pkg_name, pkgname); 83 84 /* easy case */ 85 if (dependlist == NULL) 86 return (pkg); 87 /* insert at end, since the order matters */ 88 for (tmp = dependlist; tmp->next != NULL; tmp = tmp->next) { 89 /* NULL */ 90 } 91 tmp->next = pkg; 92 return (dependlist); 93 } 94 95 static void 96 free_dependency_list(pkg_list *dependlist) 97 { 98 pkg_list *tmp; 99 100 while (dependlist) { 101 tmp = dependlist; 102 dependlist = dependlist->next; 103 tmp->next = NULL; 104 free(tmp); 105 } 106 } 107 108 #ifdef DEBUG 109 void 110 print_dependencies(const char *pkgname, pkg_list *dependlist) 111 { 112 pkg_list *tmp; 113 114 fprintf(stderr, "%s:", pkgname); 115 for (tmp = dependlist; tmp != NULL; tmp = tmp->next) 116 fprintf(stderr, " %s", tmp->pkg_name); 117 fprintf(stderr, "\n"); 118 } 119 #endif 120 121 static char *suffix_list[] = { 122 #if defined(__i386) 123 ".i", 124 #elif defined(__sparc) 125 ".c", 126 ".d", 127 ".m", 128 ".u", 129 ".v", 130 #else 131 #error "Unknown architecture." 132 #endif 133 NULL, 134 }; 135 136 static pkg_list * 137 find_dependencies(const char *pkgname, const char *parentdir) 138 { 139 char dependfile[MAXPATHLEN + 1]; 140 char pkgdir[MAXPATHLEN + 1]; 141 char buf[BUFSIZ]; 142 char deppkg[MAXNAME]; 143 char archpkg[MAXNAME]; 144 struct stat sbuf; 145 FILE *fp; 146 pkg_list *dependlist = NULL; 147 char **suffixes; 148 149 (void) sprintf(dependfile, "%s/%s/depend", parentdir, pkgname); 150 fp = fopen(dependfile, "r"); 151 if (fp == NULL) { 152 /* 153 * depend won't exist in ON packages until a build 154 * has been done, but it would be nice if you didn't have 155 * to do that. So try the generic depend file that those 156 * packages would copy in during the build. 157 */ 158 (void) sprintf(dependfile, "%s/common_files/depend", parentdir); 159 fp = fopen(dependfile, "r"); 160 if (fp == NULL) 161 return (NULL); 162 } 163 while (fgets(buf, BUFSIZ, fp) != NULL) { 164 if ((buf[0] == '\0') || (buf[0] == '#') || isspace(buf[0])) 165 continue; 166 /* we only care about prerequisites */ 167 if (buf[0] != 'P') 168 continue; 169 (void) sscanf(buf, "P %s", deppkg); 170 /* 171 * We have to be careful with some of the packages that are 172 * listed as dependencies but exist under a different name - 173 * SUNWcar is good, because it's actually SUNWcar.{c,d,i,m,u}. 174 * What do we do there? We can't just go for all the '.' 175 * packages, since on x86 we only want the .i one, and on sparc 176 * we want everything _but_ .i. Maybe 177 * 178 * I think perhaps what we do is, if we don't find a package 179 * dependency, on intel we append '.i' and try for that, and on 180 * sparc we try the other extensions. Any we find get added. 181 * 182 * Note also we're quiet on failures. This is because you might 183 * be dependant on some outside package. 184 */ 185 (void) sprintf(pkgdir, "%s/%s", parentdir, deppkg); 186 if (stat(pkgdir, &sbuf) == -1) { 187 if (errno != ENOENT) { 188 continue; 189 } 190 for (suffixes = &suffix_list[0]; *suffixes != NULL; 191 suffixes++) { 192 (void) sprintf(archpkg, "%s%s", deppkg, 193 *suffixes); 194 (void) sprintf(pkgdir, "%s/%s", parentdir, 195 archpkg); 196 if (stat(pkgdir, &sbuf) == -1) { 197 continue; 198 } 199 if (!S_ISDIR(sbuf.st_mode)) { 200 continue; 201 } 202 /* found one */ 203 dependlist = add_dependency(dependlist, 204 archpkg); 205 } 206 } 207 if (!S_ISDIR(sbuf.st_mode)) { 208 continue; 209 } 210 dependlist = add_dependency(dependlist, deppkg); 211 } 212 (void) fclose(fp); 213 return (dependlist); 214 } 215 216 int 217 process_dependencies(const char *pkgname, const char *parentdir, 218 elem_list *list, int verbose) 219 { 220 int count = 0; 221 char pkgdir[MAXPATHLEN + 1]; 222 pkg_list *dependlist; 223 pkg_list *tmp; 224 225 dependlist = find_dependencies(pkgname, parentdir); 226 /* 227 * print_dependencies(pkgname, dependlist); 228 */ 229 if (dependlist == NULL) 230 return (0); 231 232 for (tmp = dependlist; tmp != NULL; tmp = tmp->next) { 233 (void) sprintf(pkgdir, "%s/%s", parentdir, tmp->pkg_name); 234 count += process_package_dir(tmp->pkg_name, pkgdir, list, 235 verbose); 236 } 237 238 free_dependency_list(dependlist); 239 return (count); 240 } 241