diff options
author | ache <ache@FreeBSD.org> | 1994-12-28 00:47:24 +0000 |
---|---|---|
committer | ache <ache@FreeBSD.org> | 1994-12-28 00:47:24 +0000 |
commit | 917d2f1645290dc67b41de0e3e3267621f955ffa (patch) | |
tree | 22be0668ba88d0af485e5327e0f4a14e8989d074 | |
parent | 38aef237686d50296294ac17ae1df9dfedcdcac4 (diff) | |
download | FreeBSD-src-917d2f1645290dc67b41de0e3e3267621f955ffa.zip FreeBSD-src-917d2f1645290dc67b41de0e3e3267621f955ffa.tar.gz |
Fix for handling long archive names
Submitted by: dufault@hda.com
-rw-r--r-- | usr.bin/nm/nm.c | 68 |
1 files changed, 58 insertions, 10 deletions
diff --git a/usr.bin/nm/nm.c b/usr.bin/nm/nm.c index 6744cf6..542f8e0 100644 --- a/usr.bin/nm/nm.c +++ b/usr.bin/nm/nm.c @@ -48,6 +48,7 @@ static char sccsid[] = "@(#)nm.c 8.1 (Berkeley) 6/6/93"; #include <a.out.h> #include <stab.h> #include <ar.h> +#include <dirent.h> #include <ranlib.h> #include <unistd.h> #include <errno.h> @@ -182,6 +183,21 @@ process_file(fname) return(retval); } +/* scat: concatenate strings, returning new concatenation point + * and permitting overlap. + */ +static char *scat(char *dest, char *src) +{ + char *end; + int l1 = strlen(dest), l2 = strlen(src); + + memmove(dest + l1, src, l2); + end = dest + l1 + l2; + *end = 0; + + return end; +} + /* * show_archive() * show symbols in the given archive file @@ -194,9 +210,10 @@ show_archive(fname, fp) struct exec exec_head; int i, rval; long last_ar_off; - char *p, *name; + char *p, *name, *ar_name; + int buffend = strlen(fname) + 3; - name = emalloc(sizeof(ar_head.ar_name) + strlen(fname) + 3); + name = emalloc(sizeof(MAXNAMLEN) + buffend); rval = 0; @@ -214,25 +231,56 @@ show_archive(fname, fp) last_ar_off = ftell(fp); /* skip ranlib entries */ - if (!strncmp(ar_head.ar_name, RANLIBMAG, sizeof(RANLIBMAG) - 1)) + if (!bcmp(ar_head.ar_name, RANLIBMAG, sizeof(RANLIBMAG) - 1)) goto skip; + /* handle long names. If one is present, read it in at the + * end of the "name" buffer. + */ + if (!bcmp(ar_head.ar_name, AR_EFMT1, sizeof(AR_EFMT1) - 1)) + { + char *end_part = name + buffend; + size_t len = atoi(ar_head.ar_name + sizeof(AR_EFMT1) - 1); + + if (len <= 0 || len > MAXNAMLEN) + { + fprintf(stderr, "nm: Illegal length for format 1 long name.\n"); + goto skip; + } + if (fread(end_part, 1, len, fp) != len) + { + (void)fprintf(stderr, "nm: EOF reading format 1 long name.\n"); + (void)free(name); + return(1); + } + end_part[len] = 0; + ar_name = end_part; + } + else + { + p = ar_name = ar_head.ar_name; + for (i = 0; i < sizeof(ar_head.ar_name); i++) + if (*p && *p != ' ') + p++; + *p = '\0'; + } + /* * construct a name of the form "archive.a:obj.o:" for the * current archive entry if the object name is to be printed * on each output line */ p = name; + *p = 0; if (print_file_each_line) - p += sprintf(p, "%s:", fname); - for (i = 0; i < sizeof(ar_head.ar_name); ++i) - if (ar_head.ar_name[i] && ar_head.ar_name[i] != ' ') - *p++ = ar_head.ar_name[i]; - *p++ = '\0'; + { + p = scat(p, fname); + p = scat(p, ":"); + } + p = scat(p, ar_name); /* get and check current object's header */ - if (fread((char *)&exec_head, sizeof(exec_head), - (size_t)1, fp) != 1) { + if (fread((char *)&exec_head, sizeof(exec_head), (size_t)1, fp) != 1) { (void)fprintf(stderr, "nm: %s: premature EOF.\n", name); (void)free(name); return(1); |