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