version 1.6, 1999/05/10 16:14:07 |
version 1.7, 1999/09/21 13:15:43 |
|
|
#include <limits.h> |
#include <limits.h> |
#include <ranlib.h> |
#include <ranlib.h> |
#include <stdio.h> |
#include <stdio.h> |
|
#include <stdlib.h> |
#include <string.h> |
#include <string.h> |
#include <archive.h> |
#include <archive.h> |
|
#include <err.h> |
#include "byte.c" |
#include "byte.c" |
|
#include "extern.h" |
|
|
|
|
extern CHDR chdr; /* converted header */ |
extern CHDR chdr; /* converted header */ |
extern char *archive; /* archive name */ |
|
extern char *tname; /* temporary file "name" */ |
|
|
|
typedef struct _rlib { |
typedef struct _rlib { |
struct _rlib *next; /* next structure */ |
struct _rlib *next; /* next structure */ |
|
|
|
|
static int rexec(); |
static int rexec(); |
static void symobj(); |
static void symobj(); |
extern void *emalloc(); |
|
|
|
|
int |
build() |
build() |
{ |
{ |
CF cf; |
CF cf; |
int afd, tfd; |
int afd, tfd; |
int check_mid; |
|
int current_mid; |
int current_mid; |
off_t size; |
off_t size; |
|
|
check_mid = 0; |
current_mid = -1; |
afd = open_archive(O_RDWR); |
afd = open_archive(O_RDWR); |
fp = fdopen(afd, "r+"); |
fp = fdopen(afd, "r+"); |
tfd = tmp(); |
tfd = tmp(); |
|
|
continue; |
continue; |
} |
} |
new_mid = rexec(afd, tfd); |
new_mid = rexec(afd, tfd); |
if (check_mid && new_mid != current_mid) |
if (new_mid != -1) { |
errx(1, "Mixed object format archive: %d / %d", |
if (current_mid == -1) |
new_mid, current_mid); |
current_mid = new_mid; |
current_mid = new_mid; |
else if (new_mid != current_mid) |
check_mid = 1; |
errx(1, "Mixed object format archive: %d / %d", |
|
new_mid, current_mid); |
|
} |
put_arobj(&cf, (struct stat *)NULL); |
put_arobj(&cf, (struct stat *)NULL); |
} |
} |
*pnext = NULL; |
*pnext = NULL; |
|
|
* rexec |
* rexec |
* Read the exec structure; ignore any files that don't look |
* Read the exec structure; ignore any files that don't look |
* exactly right. Return MID. |
* exactly right. Return MID. |
|
* return -1 for files that don't look right. |
|
* XXX it's hard to be sure when to ignore files, and when to error |
|
* out. |
*/ |
*/ |
static int |
static int |
rexec(rfd, wfd) |
rexec(rfd, wfd) |
|
|
register RLIB *rp; |
register RLIB *rp; |
register long nsyms; |
register long nsyms; |
register int nr, symlen; |
register int nr, symlen; |
register char *strtab, *sym; |
register char *strtab = 0; |
|
char *sym; |
struct exec ebuf; |
struct exec ebuf; |
struct nlist nl; |
struct nlist nl; |
off_t r_off, w_off; |
off_t r_off, w_off; |
long strsize; |
long strsize; |
|
int result = -1; |
|
|
/* Get current offsets for original and tmp files. */ |
/* Get current offsets for original and tmp files. */ |
r_off = lseek(rfd, (off_t)0, SEEK_CUR); |
r_off = lseek(rfd, (off_t)0, SEEK_CUR); |
|
|
/* Read in exec structure. */ |
/* Read in exec structure. */ |
nr = read(rfd, (char *)&ebuf, sizeof(struct exec)); |
nr = read(rfd, (char *)&ebuf, sizeof(struct exec)); |
if (nr != sizeof(struct exec)) |
if (nr != sizeof(struct exec)) |
goto badread; |
goto bad; |
|
|
/* Check magic number and symbol count. */ |
/* Check magic number and symbol count. */ |
if (BAD_OBJECT(ebuf) || ebuf.a_syms == 0) |
if (BAD_OBJECT(ebuf) || ebuf.a_syms == 0) |
goto bad1; |
goto bad; |
fix_header_order(&ebuf); |
fix_header_order(&ebuf); |
|
|
/* Seek to string table. */ |
/* Seek to string table. */ |
if (lseek(rfd, N_STROFF(ebuf) + r_off, SEEK_SET) == (off_t)-1) |
if (lseek(rfd, N_STROFF(ebuf) + r_off, SEEK_SET) == (off_t)-1) { |
error(archive); |
if (errno == EINVAL) |
|
goto bad; |
|
else |
|
error(archive); |
|
} |
|
|
/* Read in size of the string table. */ |
/* Read in size of the string table. */ |
nr = read(rfd, (char *)&strsize, sizeof(strsize)); |
nr = read(rfd, (char *)&strsize, sizeof(strsize)); |
if (nr != sizeof(strsize)) |
if (nr != sizeof(strsize)) |
goto badread; |
goto bad; |
|
|
strsize = fix_long_order(strsize, N_GETMID(ebuf)); |
strsize = fix_long_order(strsize, N_GETMID(ebuf)); |
|
|
/* Read in the string table. */ |
/* Read in the string table. */ |
strsize -= sizeof(strsize); |
strsize -= sizeof(strsize); |
strtab = (char *)emalloc(strsize); |
strtab = (char *)emalloc(strsize); |
nr = read(rfd, strtab, strsize); |
nr = read(rfd, strtab, strsize); |
if (nr != strsize) { |
if (nr != strsize) |
badread: if (nr < 0) |
goto bad; |
error(archive); |
|
goto bad2; |
|
} |
|
|
|
/* Seek to symbol table. */ |
/* Seek to symbol table. */ |
if (fseek(fp, N_SYMOFF(ebuf) + r_off, SEEK_SET) == (off_t)-1) |
if (fseek(fp, N_SYMOFF(ebuf) + r_off, SEEK_SET) == (off_t)-1) |
goto bad2; |
goto bad; |
|
|
|
result = N_GETMID(ebuf); |
/* For each symbol read the nlist entry and save it as necessary. */ |
/* For each symbol read the nlist entry and save it as necessary. */ |
nsyms = ebuf.a_syms / sizeof(struct nlist); |
nsyms = ebuf.a_syms / sizeof(struct nlist); |
while (nsyms--) { |
while (nsyms--) { |
|
|
badfmt(); |
badfmt(); |
error(archive); |
error(archive); |
} |
} |
fix_nlist_order(&nl, N_GETMID(ebuf)); |
fix_nlist_order(&nl, N_GETMID(ebuf)); |
|
|
/* Ignore if no name or local. */ |
/* Ignore if no name or local. */ |
if (!nl.n_un.n_strx || !(nl.n_type & N_EXT)) |
if (!nl.n_un.n_strx || !(nl.n_type & N_EXT)) |
|
|
tsymlen += symlen; |
tsymlen += symlen; |
} |
} |
|
|
bad2: free(strtab); |
bad: if (nr < 0) |
bad1: (void)lseek(rfd, (off_t)r_off, SEEK_SET); |
error(archive); |
return N_GETMID(ebuf); |
free(strtab); |
|
(void)lseek(rfd, (off_t)r_off, SEEK_SET); |
|
return result; |
} |
} |
|
|
/* |
/* |