1/* 2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23#ifndef RLD 24#import <libc.h> 25#import <ctype.h> 26#import <sys/types.h> 27#ifdef __OPENSTEP__ 28#define _POSIX_SOURCE 29#endif 30#import <dirent.h> 31#import <pwd.h> 32#import "stuff/bool.h" 33#import "stuff/errors.h" 34#import "stuff/allocate.h" 35#import "stuff/SymLoc.h" 36 37const char * 38symLocForDylib(const char *installName, const char *releaseName, 39enum bool *found_project, 40enum bool disablewarnings, 41enum bool no_error_if_missing) 42{ 43 return(LocForDylib(installName, releaseName, "Symbols", found_project, 44 disablewarnings, no_error_if_missing)); 45} 46 47const char * 48dstLocForDylib(const char *installName, const char *releaseName, 49enum bool *found_project, 50enum bool disablewarnings, 51enum bool no_error_if_missing) 52{ 53 return(LocForDylib(installName, releaseName, "Roots", found_project, 54 disablewarnings, no_error_if_missing)); 55} 56 57// caller is responsible for freeing the returned string (using free(3)) 58const char * 59LocForDylib(const char *installName, const char *releaseName, 60const char *dirname, 61enum bool *found_project, 62enum bool disablewarnings, 63enum bool no_error_if_missing) 64{ 65 struct passwd *passwd = NULL; 66 struct dirent *dp = NULL; 67 FILE *file = NULL; 68 DIR *dirp = NULL; 69 DIR *dirp2 = NULL; 70 char *line = NULL; 71 char *c = NULL; 72 char *v = NULL; 73 char *viewMap = NULL; 74 int releaseLen = strlen(releaseName); 75 char buf[MAXPATHLEN+MAXNAMLEN+64]; 76 char readbuf[MAXPATHLEN+64]; 77 char viewPath[MAXPATHLEN]; 78 char dylibList[MAXPATHLEN]; 79 char installNameList[MAXPATHLEN]; 80 81 *found_project = FALSE; 82 83 // check parameters 84 if (!installName || !*installName || !releaseName || !*releaseName) { 85 fatal("internal error symLocForDylib(): Null or empty parameter"); 86 return NULL; 87 } 88 89 viewMap = getenv("RC_VIEW_MAP_LOCATION"); 90 if(!viewMap) { 91 // find ~rc's home directory 92 if (!(passwd = getpwnam("rc"))) { 93 system_error("symLocForDylib(): getpwnam(\"rc\") returns NULL"); 94 return NULL; 95 } 96 strcpy(buf, passwd->pw_dir); 97 // open release-to-view file 98 strcat(buf, "/Data/release_to_view.map"); 99 } else { 100 strcpy(buf, viewMap); 101 } 102 if (!(file = fopen(buf, "r"))) { 103 system_error("symLocForDylib(): Can't fopen %s", buf); 104 return NULL; 105 } 106 107 // parse release-to-view file 108 *viewPath = '\0'; 109 while ((line = fgets(buf, sizeof(buf), file))) { 110 if (!strncmp(line, releaseName, releaseLen) && isspace(line[releaseLen])) { 111 c = &line[releaseLen] + 1; 112 while (isspace(*c)) c++; 113 for (v = &viewPath[0]; !isspace(*c); c++, v++) *v = *c; 114 *v = '\0'; 115 break; 116 } 117 } 118 if(fclose(file) != 0) 119 system_error("fclose() failed"); 120 if (!*viewPath) { 121 error("symLocForDylib(): Can't locate view path for release %s", 122 releaseName); 123 return NULL; 124 } 125 126 // open DylibProjects directory 127 strcpy(dylibList, viewPath); 128 c = &dylibList[strlen(dylibList)]; 129 strcpy(c, "/.BuildData/DylibProjects"); 130 if (!(dirp = opendir(dylibList))) { 131 system_error("symLocForDylib(): Can't opendir %s", buf); 132 return NULL; 133 } 134 135 // open the InstallNames directory 136 strcpy(installNameList, viewPath); 137 c = &installNameList[strlen(installNameList)]; 138 strcpy(c, "/.BuildData/InstallNames"); 139 if (!(dirp2 = opendir(installNameList))) { 140 system_error("symLocForDylib(): Can't opendir %s", buf); 141 return NULL; 142 } 143 c = NULL; 144 145 // read DylibProjects entries 146 *buf = '\0'; 147 v = &dylibList[strlen(dylibList)]; 148 *v = '/'; 149 v++; 150 while ((dp = readdir(dirp))) { 151 152 // skip "." and ".." 153 if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) continue; 154 155 // open file 156 strcpy(v, dp->d_name); 157 if (!(file = fopen(dylibList, "r"))) { 158 system_error("symLocForDylib(): Can't fopen %s", dylibList); 159 if(closedir(dirp) != 0) 160 system_error("closedir() failed"); 161 return NULL; 162 } 163 164 // parse file 165 while ((line = fgets(readbuf, sizeof(readbuf), file))) { 166 if (!*line || *line == '(' || *line == ')') continue; 167 while (*line == ' ') line++; 168 if (*line != '"') { 169 warning("symLocForDylib(): %s contains malformed line", 170 dp->d_name); 171 continue; 172 } 173 line++; 174 for (c = &buf[0]; *line && *line != '"'; *c++ = *line++); 175 if (*line != '"') { 176 warning("symLocForDylib(): %s contains malformed line", 177 dp->d_name); 178 continue; 179 } 180 *c = '\0'; 181 if (!strcmp(buf, installName)) { 182 c = allocate(strlen(viewPath) + strlen(releaseName) + 183 strlen(dirname) + strlen(dp->d_name) + 32); 184 sprintf(c, "%s/Updates/Built%s/%s/%s", viewPath, releaseName, 185 dirname, dp->d_name); 186 break; 187 } else { 188 c = NULL; 189 } 190 } 191 if(fclose(file) != 0) 192 system_error("fclose() failed"); 193 if (c) break; 194 } 195 if(closedir(dirp) != 0) 196 system_error("closedir() failed"); 197 198 if(!c) { 199 // read InstallNames entries 200 *buf = '\0'; 201 v = &installNameList[strlen(installNameList)]; 202 *v = '/'; 203 v++; 204 205 while ((dp = readdir(dirp2))) { 206 207 // skip "." and ".." 208 if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) continue; 209 210 // open file 211 strcpy(v, dp->d_name); 212 if (!(file = fopen(installNameList, "r"))) { 213 system_error("symLocForDylib(): Can't fopen %s", installNameList); 214 if(closedir(dirp) != 0) 215 system_error("closedir() failed"); 216 return NULL; 217 } 218 219 // parse file 220 while ((line = fgets(readbuf, sizeof(readbuf), file))) { 221 if (!*line || *line == '(' || *line == ')') continue; 222 while (*line == ' ') line++; 223 if (*line != '"') { 224 warning("symLocForDylib(): %s contains malformed line", 225 dp->d_name); 226 continue; 227 } 228 line++; 229 for (c = &buf[0]; *line && *line != '"'; *c++ = *line++); 230 if (*line != '"') { 231 warning("symLocForDylib(): %s contains malformed line", 232 dp->d_name); 233 continue; 234 } 235 *c = '\0'; 236 if (!strcmp(buf, installName)) { 237 c = allocate(strlen(viewPath) + strlen(releaseName) + 238 strlen(dirname) + strlen(dp->d_name) + 32); 239 sprintf(c, "%s/Updates/Built%s/%s/%s", viewPath, releaseName, 240 dirname, dp->d_name); 241 break; 242 } else { 243 c = NULL; 244 } 245 } 246 if(fclose(file) != 0) 247 system_error("fclose() failed"); 248 if (c) break; 249 } 250 } 251 252 // process return value 253 if (!c) { 254 if(no_error_if_missing == FALSE) 255 error("Can't find project that builds %s", installName); 256 return NULL; 257 } else { 258 *found_project = TRUE; 259 return c; 260 } 261} 262#endif /* !defined(RLD) */ 263