diff options
| author | John Polstra <jdp@FreeBSD.org> | 1996-05-02 16:07:33 +0000 |
|---|---|---|
| committer | John Polstra <jdp@FreeBSD.org> | 1996-05-02 16:07:33 +0000 |
| commit | b2f01a7ab60adb216f907b1d46594ff48738cb5e (patch) | |
| tree | 5c61eebb2cb5f8f15b82a6fa995c9d253afcd206 /gnu/usr.bin | |
| parent | f5dda3dad884b70d94ab30b72e48498b1c2c5a27 (diff) | |
Notes
Diffstat (limited to 'gnu/usr.bin')
| -rw-r--r-- | gnu/usr.bin/ld/ld.c | 8 | ||||
| -rw-r--r-- | gnu/usr.bin/ld/ld.h | 4 | ||||
| -rw-r--r-- | gnu/usr.bin/ld/lib.c | 6 | ||||
| -rw-r--r-- | gnu/usr.bin/ld/shlib.c | 217 |
4 files changed, 149 insertions, 86 deletions
diff --git a/gnu/usr.bin/ld/ld.c b/gnu/usr.bin/ld/ld.c index 7796307bc66a..6333f6cb7c67 100644 --- a/gnu/usr.bin/ld/ld.c +++ b/gnu/usr.bin/ld/ld.c @@ -32,7 +32,7 @@ static char sccsid[] = "@(#)ld.c 6.10 (Berkeley) 5/22/91"; Set, indirect, and warning symbol features added by Randy Smith. */ /* - * $Id: ld.c,v 1.27.4.1 1995/06/28 05:54:50 davidg Exp $ + * $Id: ld.c,v 1.27.4.2 1995/08/25 04:39:51 davidg Exp $ */ /* Define how to initialize system-dependent header fields. */ @@ -560,7 +560,7 @@ decode_command(argc, argv) /* Append the standard search directories to the user-specified ones. */ add_search_path(getenv("LD_LIBRARY_PATH")); - if (!nostdlib && getenv("LD_NOSTD_PATH") == NULL) + if (!nostdlib) std_search_path(); } @@ -959,7 +959,7 @@ file_open(entry) } else fd = open(entry->filename, O_RDONLY, 0); - if (fd > 0) { + if (fd >= 0) { input_file = entry; input_desc = fd; return fd; @@ -2475,7 +2475,7 @@ write_output() outstream = fopen(output_filename, "w"); if (outstream == NULL) - err(1, "open: %s", output_filename); + err(1, "fopen: %s", output_filename); if (atexit(cleanup)) err(1, "atexit"); diff --git a/gnu/usr.bin/ld/ld.h b/gnu/usr.bin/ld/ld.h index 82f88e8b10df..fe9e39e8b541 100644 --- a/gnu/usr.bin/ld/ld.h +++ b/gnu/usr.bin/ld/ld.h @@ -1,5 +1,5 @@ /* - * $Id: ld.h,v 1.13 1995/03/04 17:46:07 nate Exp $ + * $Id: ld.h,v 1.16 1996/04/20 18:27:55 jdp Exp $ */ /*- * This code is derived from software copyrighted by the Free Software @@ -643,6 +643,8 @@ int findlib __P((struct file_entry *)); /* In shlib.c: */ char *findshlib __P((char *, int *, int *, int)); +char *find_lib_file __P((char *)); +char *search_lib_dir __P((char *, char *, int *, int *, int)); void add_search_dir __P((char *)); void add_search_path __P((char *)); void std_search_path __P((void)); diff --git a/gnu/usr.bin/ld/lib.c b/gnu/usr.bin/ld/lib.c index 78d692610f14..fce30480f7fc 100644 --- a/gnu/usr.bin/ld/lib.c +++ b/gnu/usr.bin/ld/lib.c @@ -1,5 +1,5 @@ /* - * $Id: lib.c,v 1.14 1995/04/07 05:08:28 nate Exp $ - library routines + * $Id: lib.c,v 1.16 1995/09/28 19:43:22 bde Exp $ - library routines */ #include <sys/param.h> @@ -830,7 +830,7 @@ struct file_entry *p; fname = findshlib(p->filename, &major, &minor, 1); - if (fname && (fd = open(fname, O_RDONLY, 0)) > 0) { + if (fname && (fd = open(fname, O_RDONLY, 0)) >= 0) { p->filename = fname; p->lib_major = major; p->lib_minor = minor; @@ -852,7 +852,7 @@ dot_a: register char *path = concat(search_dirs[i], "/", fname); fd = open(path, O_RDONLY, 0); - if (fd > 0) { + if (fd >= 0) { p->filename = path; p->flags &= ~E_SEARCH_DIRS; break; diff --git a/gnu/usr.bin/ld/shlib.c b/gnu/usr.bin/ld/shlib.c index f256508b55d7..0343423bc0d6 100644 --- a/gnu/usr.bin/ld/shlib.c +++ b/gnu/usr.bin/ld/shlib.c @@ -27,7 +27,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: shlib.c,v 1.12 1995/03/04 17:46:09 nate Exp $ + * $Id: shlib.c,v 1.15 1996/04/20 18:27:56 jdp Exp $ */ #include <sys/param.h> @@ -169,111 +169,172 @@ int n1, n2; /* * Search directories for a shared library matching the given - * major and minor version numbers. + * major and minor version numbers. See search_lib_dir() below for + * the detailed matching rules. * - * MAJOR == -1 && MINOR == -1 --> find highest version - * MAJOR != -1 && MINOR == -1 --> find highest minor version - * MAJOR == -1 && MINOR != -1 --> invalid - * MAJOR != -1 && MINOR != -1 --> find highest micro version + * As soon as a directory with an acceptable match is found, the search + * terminates. Subsequent directories are not searched for a better + * match. This is in conformance with the SunOS searching rules. Also, + * it avoids a lot of directory searches that are virtually guaranteed to + * be fruitless. + * + * The return value is a full pathname to the matching library. The + * string is dynamically allocated. If no matching library is found, the + * function returns NULL. */ -/* Not interested in devices right now... */ -#undef major -#undef minor - char * findshlib(name, majorp, minorp, do_dot_a) char *name; int *majorp, *minorp; int do_dot_a; { - int dewey[MAXDEWEY]; - int ndewey; - int tmp[MAXDEWEY]; int i; - int len; - char *lname, *path = NULL; - int major = *majorp, minor = *minorp; - len = strlen(name); - lname = (char *)alloca(len + sizeof("lib")); - sprintf(lname, "lib%s", name); - len += 3; + for (i = 0; i < n_search_dirs; i++) { + char *path; + + path = search_lib_dir(search_dirs[i], name, majorp, minorp, + do_dot_a); + if(path != NULL) + return path; + } + + return NULL; +} - ndewey = 0; +/* + * Search library directories for a file with the given name. The + * return value is a full pathname to the matching file. The string + * is dynamically allocated. If no matching file is found, the function + * returns NULL. + */ + +char * +find_lib_file(name) + char *name; +{ + int i; for (i = 0; i < n_search_dirs; i++) { - DIR *dd = opendir(search_dirs[i]); - struct dirent *dp; - int found_dot_a = 0; + char *path = concat(search_dirs[i], "/", name); + struct stat sb; - if (dd == NULL) - continue; + if (lstat(path, &sb) != -1) /* We found it */ + return path; - while ((dp = readdir(dd)) != NULL) { - int n, might_take_it = 0; + free(path); + } - if (do_dot_a && path == NULL && - dp->d_namlen == len + 2 && - strncmp(dp->d_name, lname, len) == 0 && - (dp->d_name+len)[0] == '.' && - (dp->d_name+len)[1] == 'a') { + return NULL; +} - path = concat(search_dirs[i], "/", dp->d_name); - found_dot_a = 1; - } +/* + * Search a given directory for a library (preferably shared) satisfying + * the given criteria. + * + * The matching rules are as follows: + * + * if(*majorp == -1) + * find the library with the highest major version; + * else + * insist on a major version identical to *majorp; + * + * Always find the library with the highest minor version; + * if(*minorp != -1) + * insist on a minor version >= *minorp; + * + * It is invalid to specify a specific minor number while wildcarding + * the major number. + * + * The actual major and minor numbers found are returned via the pointer + * arguments. + * + * A suitable shared library is always preferred over a static (.a) library. + * If do_dot_a is false, then a static library will not be accepted in + * any case. + * + * The return value is a full pathname to the matching library. The + * string is dynamically allocated. If no matching library is found, the + * function returns NULL. + */ - if (dp->d_namlen < len + 4) - continue; - if (strncmp(dp->d_name, lname, len) != 0) - continue; - if (strncmp(dp->d_name+len, ".so.", 4) != 0) - continue; +char * +search_lib_dir(dir, name, majorp, minorp, do_dot_a) + char *dir; + char *name; + int *majorp; + int *minorp; + int do_dot_a; +{ + int namelen; + DIR *dd; + struct dirent *dp; + int best_dewey[MAXDEWEY]; + int best_ndewey; + char dot_a_name[MAXNAMLEN+1]; + char dot_so_name[MAXNAMLEN+1]; - if ((n = getdewey(tmp, dp->d_name+len+4)) == 0) - continue; + if((dd = opendir(dir)) == NULL) + return NULL; - if (major != -1 && found_dot_a) { /* XXX */ - free(path); - path = NULL; - found_dot_a = 0; - } + namelen = strlen(name); + best_ndewey = 0; + dot_a_name[0] = '\0'; + dot_so_name[0] = '\0'; - if (major == -1 && minor == -1) { - might_take_it = 1; - } else if (major != -1 && minor == -1) { - if (tmp[0] == major) - might_take_it = 1; - } else if (major != -1 && minor != -1) { - if (tmp[0] == major) - if (n == 1 || tmp[1] >= minor) - might_take_it = 1; - } + while((dp = readdir(dd)) != NULL) { + char *extension; + + if(strlen(dp->d_name) < 3 + namelen + 2 || /* lib+xxx+.a */ + strncmp(dp->d_name, "lib", 3) != 0 || + strncmp(dp->d_name + 3, name, namelen) != 0 || + dp->d_name[3+namelen] != '.') + continue; + + extension = dp->d_name + 3 + namelen + 1; /* a or so.* */ + + if(strncmp(extension, "so.", 3) == 0) { + int cur_dewey[MAXDEWEY]; + int cur_ndewey; - if (!might_take_it) + cur_ndewey = getdewey(cur_dewey, extension+3); + if(cur_ndewey == 0) /* No version number */ continue; - if (cmpndewey(tmp, n, dewey, ndewey) <= 0) + if(*majorp != -1) { /* Need exact match on major */ + if(cur_dewey[0] != *majorp) + continue; + if(*minorp != -1) { /* Need minor >= minimum */ + if(cur_ndewey < 2 || + cur_dewey[1] < *minorp) + continue; + } + } + + if(cmpndewey(cur_dewey, cur_ndewey, best_dewey, + best_ndewey) <= 0) /* No better than prior match */ continue; - /* We have a better version */ - if (path) - free(path); - path = concat(search_dirs[i], "/", dp->d_name); - found_dot_a = 0; - bcopy(tmp, dewey, sizeof(dewey)); - ndewey = n; - *majorp = dewey[0]; - *minorp = dewey[1]; - } - closedir(dd); + /* We found a better match */ + strcpy(dot_so_name, dp->d_name); + bcopy(cur_dewey, best_dewey, + cur_ndewey * sizeof best_dewey[0]); + best_ndewey = cur_ndewey; + } else if(do_dot_a && strcmp(extension, "a") == 0) + strcpy(dot_a_name, dp->d_name); + } + closedir(dd); - if (found_dot_a) - /* - * There's a .a archive here. - */ - return path; + if(dot_so_name[0] != '\0') { + *majorp = best_dewey[0]; + if(best_ndewey >= 2) + *minorp = best_dewey[1]; + return concat(dir, "/", dot_so_name); } - return path; + if(dot_a_name[0] != '\0') + return concat(dir, "/", dot_a_name); + + return NULL; } |
