/*
|
/*
|
* ranlib.c -- archive index generator
|
* ranlib.c -- archive index generator
|
*/
|
*/
|
|
|
|
|
#include <stdio.h>
|
#include <stdio.h>
|
#include <stdlib.h>
|
#include <stdlib.h>
|
#include <string.h>
|
#include <string.h>
|
#include <unistd.h>
|
#include <unistd.h>
|
#include <time.h>
|
#include <time.h>
|
#include <fcntl.h>
|
#include <fcntl.h>
|
|
|
#include "endian.h"
|
#include "endian.h"
|
#include "ranlib.h"
|
#include "ranlib.h"
|
#include "../include/ar.h"
|
#include "../include/ar.h"
|
#include "../include/a.out.h"
|
#include "../include/a.out.h"
|
|
|
|
|
#define TEMP_NAME "__.SYMDEF"
|
#define TEMP_NAME "__.SYMDEF"
|
|
|
#define STRING_SIZE_INIT 1024
|
#define STRING_SIZE_INIT 1024
|
#define STRING_SIZE_GROW 2
|
#define STRING_SIZE_GROW 2
|
|
|
#define MAX_SYM_ENTRIES 1000
|
#define MAX_SYM_ENTRIES 1000
|
|
|
#define MSB ((unsigned int) 1 << (sizeof(unsigned int) * 8 - 1))
|
#define MSB ((unsigned int) 1 << (sizeof(unsigned int) * 8 - 1))
|
|
|
|
|
typedef struct {
|
typedef struct {
|
unsigned int name; /* name of symbol (as offset into string space) */
|
unsigned int name; /* name of symbol (as offset into string space) */
|
off_t position; /* position of member which defines the symbol */
|
long position; /* position of member which defines the symbol */
|
/* (as file offset to the member's ArHeader) */
|
/* (as file offset to the member's ArHeader) */
|
} Entry;
|
} Entry;
|
|
|
|
|
FILE *fi;
|
FILE *fi;
|
FILE *fo;
|
FILE *fo;
|
|
|
off_t nxtOff; /* file offset to next member */
|
long nxtOff; /* file offset to next member */
|
off_t curOff;
|
long curOff;
|
|
|
Entry table[MAX_SYM_ENTRIES];
|
Entry table[MAX_SYM_ENTRIES];
|
int numEntries;
|
int numEntries;
|
|
|
int createIndex;
|
int createIndex;
|
char firstName[MAX_NAME];
|
char firstName[MAX_NAME];
|
|
|
ArHeader arhdr;
|
ArHeader arhdr;
|
ExecHeader exhdr;
|
ExecHeader exhdr;
|
|
|
|
|
/**************************************************************/
|
/**************************************************************/
|
|
|
|
|
char *stringArea = NULL;
|
char *stringArea = NULL;
|
unsigned int sizeAllocated = 0;
|
unsigned int sizeAllocated = 0;
|
unsigned int sizeUsed = 0;
|
unsigned int sizeUsed = 0;
|
|
|
|
|
unsigned int getStringPos(void) {
|
unsigned int getStringPos(void) {
|
return sizeUsed;
|
return sizeUsed;
|
}
|
}
|
|
|
|
|
void storeCharacter(char c) {
|
void storeCharacter(char c) {
|
unsigned int newSize;
|
unsigned int newSize;
|
char *newArea;
|
char *newArea;
|
|
|
if (sizeUsed + 1 > sizeAllocated) {
|
if (sizeUsed + 1 > sizeAllocated) {
|
if (sizeAllocated == 0) {
|
if (sizeAllocated == 0) {
|
newSize = STRING_SIZE_INIT;
|
newSize = STRING_SIZE_INIT;
|
} else {
|
} else {
|
newSize = STRING_SIZE_GROW * sizeAllocated;
|
newSize = STRING_SIZE_GROW * sizeAllocated;
|
}
|
}
|
newArea = malloc(newSize);
|
newArea = malloc(newSize);
|
if (newArea == NULL) {
|
if (newArea == NULL) {
|
fprintf(stderr, "ar: cannot allocate string area\n");
|
fprintf(stderr, "ar: cannot allocate string area\n");
|
exit(1);
|
exit(1);
|
}
|
}
|
if (stringArea != NULL) {
|
if (stringArea != NULL) {
|
memcpy(newArea, stringArea, sizeUsed);
|
memcpy(newArea, stringArea, sizeUsed);
|
free(stringArea);
|
free(stringArea);
|
}
|
}
|
stringArea = newArea;
|
stringArea = newArea;
|
sizeAllocated = newSize;
|
sizeAllocated = newSize;
|
}
|
}
|
stringArea[sizeUsed++] = c;
|
stringArea[sizeUsed++] = c;
|
}
|
}
|
|
|
|
|
/**************************************************************/
|
/**************************************************************/
|
|
|
|
|
int nextMember(void) {
|
int nextMember(void) {
|
int pad;
|
int pad;
|
|
|
curOff = nxtOff;
|
curOff = nxtOff;
|
fseek(fi, nxtOff, SEEK_SET);
|
fseek(fi, nxtOff, SEEK_SET);
|
if (fread(&arhdr, sizeof(arhdr), 1, fi) != 1) {
|
if (fread(&arhdr, sizeof(arhdr), 1, fi) != 1) {
|
return 0;
|
return 0;
|
}
|
}
|
conv4FromEcoToNative((unsigned char *) &arhdr.date);
|
conv4FromEcoToNative((unsigned char *) &arhdr.date);
|
conv4FromEcoToNative((unsigned char *) &arhdr.uid);
|
conv4FromEcoToNative((unsigned char *) &arhdr.uid);
|
conv4FromEcoToNative((unsigned char *) &arhdr.gid);
|
conv4FromEcoToNative((unsigned char *) &arhdr.gid);
|
conv4FromEcoToNative((unsigned char *) &arhdr.mode);
|
conv4FromEcoToNative((unsigned char *) &arhdr.mode);
|
conv4FromEcoToNative((unsigned char *) &arhdr.size);
|
conv4FromEcoToNative((unsigned char *) &arhdr.size);
|
pad = -arhdr.size & 0x03;
|
pad = -arhdr.size & 0x03;
|
arhdr.size += pad;
|
arhdr.size += pad;
|
nxtOff = ftell(fi) + arhdr.size;
|
nxtOff = ftell(fi) + arhdr.size;
|
return 1;
|
return 1;
|
}
|
}
|
|
|
|
|
void addSymbol(unsigned int nameOffset) {
|
void addSymbol(unsigned int nameOffset) {
|
off_t curPos;
|
long curPos;
|
int c;
|
int c;
|
|
|
if (numEntries >= MAX_SYM_ENTRIES) {
|
if (numEntries >= MAX_SYM_ENTRIES) {
|
fprintf(stderr, "ar: symbol table overflow\n");
|
fprintf(stderr, "ar: symbol table overflow\n");
|
exit(1);
|
exit(1);
|
}
|
}
|
table[numEntries].name = getStringPos();
|
table[numEntries].name = getStringPos();
|
table[numEntries].position = curOff;
|
table[numEntries].position = curOff;
|
numEntries++;
|
numEntries++;
|
curPos = ftell(fi);
|
curPos = ftell(fi);
|
fseek(fi, curOff + sizeof(arhdr) + nameOffset, SEEK_SET);
|
fseek(fi, curOff + sizeof(arhdr) + nameOffset, SEEK_SET);
|
do {
|
do {
|
c = fgetc(fi);
|
c = fgetc(fi);
|
storeCharacter(c);
|
storeCharacter(c);
|
} while (c != 0) ;
|
} while (c != 0) ;
|
fseek(fi, curPos, SEEK_SET);
|
fseek(fi, curPos, SEEK_SET);
|
}
|
}
|
|
|
|
|
void fixSize(void) {
|
void fixSize(void) {
|
off_t deltaOff;
|
long deltaOff;
|
int pad;
|
int pad;
|
int i;
|
int i;
|
|
|
deltaOff = sizeof(arhdr) + sizeof(int) +
|
deltaOff = sizeof(arhdr) + sizeof(int) +
|
numEntries * sizeof(Entry) + getStringPos();
|
numEntries * sizeof(Entry) + getStringPos();
|
pad = -deltaOff & 0x03;
|
pad = -deltaOff & 0x03;
|
deltaOff += pad;
|
deltaOff += pad;
|
nxtOff = sizeof(unsigned int);
|
nxtOff = sizeof(unsigned int);
|
nextMember();
|
nextMember();
|
if(strncmp(arhdr.name, TEMP_NAME, MAX_NAME) == 0) {
|
if(strncmp(arhdr.name, TEMP_NAME, MAX_NAME) == 0) {
|
/* there is an index already present */
|
/* there is an index already present */
|
createIndex = 0;
|
createIndex = 0;
|
deltaOff -= sizeof(arhdr) + arhdr.size;
|
deltaOff -= sizeof(arhdr) + arhdr.size;
|
} else {
|
} else {
|
/* no index yet present, create new one */
|
/* no index yet present, create new one */
|
createIndex = 1;
|
createIndex = 1;
|
strncpy(firstName, arhdr.name, MAX_NAME);
|
strncpy(firstName, arhdr.name, MAX_NAME);
|
}
|
}
|
for (i = 0; i < numEntries; i++) {
|
for (i = 0; i < numEntries; i++) {
|
table[i].position += deltaOff;
|
table[i].position += deltaOff;
|
}
|
}
|
}
|
}
|
|
|
|
|
/**************************************************************/
|
/**************************************************************/
|
|
|
|
|
void showSymdefs(char *symdefs) {
|
void showSymdefs(char *symdefs) {
|
FILE *in;
|
FILE *in;
|
int numSymbols;
|
int numSymbols;
|
int i;
|
int i;
|
Entry e;
|
Entry e;
|
off_t curPos;
|
long curPos;
|
off_t pos;
|
long pos;
|
int c;
|
int c;
|
|
|
in = fopen(symdefs, "r");
|
in = fopen(symdefs, "r");
|
if (in == NULL) {
|
if (in == NULL) {
|
printf("error: cannot open symdef file '%s'\n", symdefs);
|
printf("error: cannot open symdef file '%s'\n", symdefs);
|
exit(1);
|
exit(1);
|
}
|
}
|
if (fread(&numSymbols, sizeof(int), 1, in) != 1) {
|
if (fread(&numSymbols, sizeof(int), 1, in) != 1) {
|
printf("cannot read symdef file\n");
|
printf("cannot read symdef file\n");
|
exit(1);
|
exit(1);
|
}
|
}
|
conv4FromEcoToNative((unsigned char *) &numSymbols);
|
conv4FromEcoToNative((unsigned char *) &numSymbols);
|
printf("%d symbols\n", numSymbols);
|
printf("%d symbols\n", numSymbols);
|
for (i = 0; i < numSymbols; i++) {
|
for (i = 0; i < numSymbols; i++) {
|
if (fread(&e, sizeof(e), 1, in) != 1) {
|
if (fread(&e, sizeof(e), 1, in) != 1) {
|
printf("cannot read symdef file\n");
|
printf("cannot read symdef file\n");
|
exit(1);
|
exit(1);
|
}
|
}
|
conv4FromEcoToNative((unsigned char *) &e.name);
|
conv4FromEcoToNative((unsigned char *) &e.name);
|
conv4FromEcoToNative((unsigned char *) &e.position);
|
conv4FromEcoToNative((unsigned char *) &e.position);
|
printf("%4d: name = 0x%08X, position = 0x%08lX, string = '",
|
printf("%4d: name = 0x%08X, position = 0x%08lX, string = '",
|
i, e.name, e.position);
|
i, e.name, e.position);
|
curPos = ftell(in);
|
curPos = ftell(in);
|
pos = sizeof(int) + numSymbols * sizeof(Entry) + e.name;
|
pos = sizeof(int) + numSymbols * sizeof(Entry) + e.name;
|
fseek(in, pos, SEEK_SET);
|
fseek(in, pos, SEEK_SET);
|
while (1) {
|
while (1) {
|
c = fgetc(in);
|
c = fgetc(in);
|
if (c == EOF) {
|
if (c == EOF) {
|
printf("\nerror: unexpected end of file\n");
|
printf("\nerror: unexpected end of file\n");
|
exit(1);
|
exit(1);
|
}
|
}
|
if (c == 0) {
|
if (c == 0) {
|
break;
|
break;
|
}
|
}
|
printf("%c", c);
|
printf("%c", c);
|
}
|
}
|
printf("'\n");
|
printf("'\n");
|
fseek(in, curPos, SEEK_SET);
|
fseek(in, curPos, SEEK_SET);
|
}
|
}
|
fclose(in);
|
fclose(in);
|
}
|
}
|
|
|
|
|
/**************************************************************/
|
/**************************************************************/
|
|
|
|
|
int hasSymbols(char *archive) {
|
int hasSymbols(char *archive) {
|
unsigned int arMagic;
|
unsigned int arMagic;
|
int res;
|
int res;
|
|
|
fi = fopen(archive, "r");
|
fi = fopen(archive, "r");
|
if (fi == NULL) {
|
if (fi == NULL) {
|
return 0;
|
return 0;
|
}
|
}
|
nxtOff = sizeof(unsigned int);
|
nxtOff = sizeof(unsigned int);
|
if (fread(&arMagic, sizeof(arMagic), 1, fi) != 1 ||
|
if (fread(&arMagic, sizeof(arMagic), 1, fi) != 1 ||
|
read4FromEco((unsigned char *) &arMagic) != AR_MAGIC) {
|
read4FromEco((unsigned char *) &arMagic) != AR_MAGIC) {
|
fclose(fi);
|
fclose(fi);
|
return 0;
|
return 0;
|
}
|
}
|
fseek(fi, 0, SEEK_SET);
|
fseek(fi, 0, SEEK_SET);
|
if (nextMember() == 0) {
|
if (nextMember() == 0) {
|
fclose(fi);
|
fclose(fi);
|
return 0;
|
return 0;
|
}
|
}
|
fclose(fi);
|
fclose(fi);
|
res = (strncmp(arhdr.name, TEMP_NAME, MAX_NAME) == 0);
|
res = (strncmp(arhdr.name, TEMP_NAME, MAX_NAME) == 0);
|
return res;
|
return res;
|
}
|
}
|
|
|
|
|
int updateSymbols(char *archive, int verbose) {
|
int updateSymbols(char *archive, int verbose) {
|
unsigned int arMagic;
|
unsigned int arMagic;
|
unsigned int skip;
|
unsigned int skip;
|
int numSymbols;
|
int numSymbols;
|
unsigned int stringStart;
|
unsigned int stringStart;
|
SymbolRecord symbol;
|
SymbolRecord symbol;
|
int i;
|
int i;
|
char *args[3];
|
char *args[3];
|
int res;
|
int res;
|
|
|
if (verbose) {
|
if (verbose) {
|
printf("ar: updating symbols in %s\n", archive);
|
printf("ar: updating symbols in %s\n", archive);
|
}
|
}
|
fi = fopen(archive, "r");
|
fi = fopen(archive, "r");
|
if (fi == NULL) {
|
if (fi == NULL) {
|
fprintf(stderr, "ar: cannot re-open %s\n", archive);
|
fprintf(stderr, "ar: cannot re-open %s\n", archive);
|
return 1;
|
return 1;
|
}
|
}
|
nxtOff = sizeof(unsigned int);
|
nxtOff = sizeof(unsigned int);
|
if (fread(&arMagic, sizeof(arMagic), 1, fi) != 1 ||
|
if (fread(&arMagic, sizeof(arMagic), 1, fi) != 1 ||
|
read4FromEco((unsigned char *) &arMagic) != AR_MAGIC) {
|
read4FromEco((unsigned char *) &arMagic) != AR_MAGIC) {
|
fprintf(stderr, "ar: %s not in archive format\n", archive);
|
fprintf(stderr, "ar: %s not in archive format\n", archive);
|
fclose(fi);
|
fclose(fi);
|
return 1;
|
return 1;
|
}
|
}
|
fseek(fi, 0, SEEK_SET);
|
fseek(fi, 0, SEEK_SET);
|
numEntries = 0;
|
numEntries = 0;
|
if (nextMember() == 0) {
|
if (nextMember() == 0) {
|
fclose(fi);
|
fclose(fi);
|
return 0;
|
return 0;
|
}
|
}
|
/* iterate over archive members */
|
/* iterate over archive members */
|
do {
|
do {
|
if (fread(&exhdr, sizeof(exhdr), 1, fi) != 1 ||
|
if (fread(&exhdr, sizeof(exhdr), 1, fi) != 1 ||
|
read4FromEco((unsigned char *) &exhdr.magic) != EXEC_MAGIC) {
|
read4FromEco((unsigned char *) &exhdr.magic) != EXEC_MAGIC) {
|
/* archive member not in proper format - skip */
|
/* archive member not in proper format - skip */
|
continue;
|
continue;
|
}
|
}
|
conv4FromEcoToNative((unsigned char *) &exhdr.magic);
|
conv4FromEcoToNative((unsigned char *) &exhdr.magic);
|
conv4FromEcoToNative((unsigned char *) &exhdr.csize);
|
conv4FromEcoToNative((unsigned char *) &exhdr.csize);
|
conv4FromEcoToNative((unsigned char *) &exhdr.dsize);
|
conv4FromEcoToNative((unsigned char *) &exhdr.dsize);
|
conv4FromEcoToNative((unsigned char *) &exhdr.bsize);
|
conv4FromEcoToNative((unsigned char *) &exhdr.bsize);
|
conv4FromEcoToNative((unsigned char *) &exhdr.crsize);
|
conv4FromEcoToNative((unsigned char *) &exhdr.crsize);
|
conv4FromEcoToNative((unsigned char *) &exhdr.drsize);
|
conv4FromEcoToNative((unsigned char *) &exhdr.drsize);
|
conv4FromEcoToNative((unsigned char *) &exhdr.symsize);
|
conv4FromEcoToNative((unsigned char *) &exhdr.symsize);
|
conv4FromEcoToNative((unsigned char *) &exhdr.strsize);
|
conv4FromEcoToNative((unsigned char *) &exhdr.strsize);
|
skip = exhdr.csize + exhdr.dsize + exhdr.crsize + exhdr.drsize;
|
skip = exhdr.csize + exhdr.dsize + exhdr.crsize + exhdr.drsize;
|
fseek(fi, skip, SEEK_CUR);
|
fseek(fi, skip, SEEK_CUR);
|
numSymbols = exhdr.symsize / sizeof(SymbolRecord);
|
numSymbols = exhdr.symsize / sizeof(SymbolRecord);
|
if (numSymbols == 0) {
|
if (numSymbols == 0) {
|
fprintf(stderr,
|
fprintf(stderr,
|
"ar: symbol table of %s is empty\n",
|
"ar: symbol table of %s is empty\n",
|
arhdr.name);
|
arhdr.name);
|
continue;
|
continue;
|
}
|
}
|
stringStart = sizeof(exhdr) + skip + exhdr.symsize;
|
stringStart = sizeof(exhdr) + skip + exhdr.symsize;
|
/* iterate over symbols */
|
/* iterate over symbols */
|
while (--numSymbols >= 0) {
|
while (--numSymbols >= 0) {
|
if (fread(&symbol, sizeof(symbol), 1, fi) != 1) {
|
if (fread(&symbol, sizeof(symbol), 1, fi) != 1) {
|
fprintf(stderr, "ar: cannot read archive\n");
|
fprintf(stderr, "ar: cannot read archive\n");
|
break;
|
break;
|
}
|
}
|
conv4FromEcoToNative((unsigned char *) &symbol.name);
|
conv4FromEcoToNative((unsigned char *) &symbol.name);
|
conv4FromEcoToNative((unsigned char *) &symbol.type);
|
conv4FromEcoToNative((unsigned char *) &symbol.type);
|
conv4FromEcoToNative((unsigned char *) &symbol.value);
|
conv4FromEcoToNative((unsigned char *) &symbol.value);
|
if ((symbol.type & MSB) == 0) {
|
if ((symbol.type & MSB) == 0) {
|
/* this is an exported symbol */
|
/* this is an exported symbol */
|
addSymbol(stringStart + symbol.name);
|
addSymbol(stringStart + symbol.name);
|
}
|
}
|
}
|
}
|
} while (nextMember() != 0) ;
|
} while (nextMember() != 0) ;
|
fixSize();
|
fixSize();
|
fclose(fi);
|
fclose(fi);
|
fo = fopen(TEMP_NAME, "w");
|
fo = fopen(TEMP_NAME, "w");
|
if (fo == NULL) {
|
if (fo == NULL) {
|
fprintf(stderr, "ar: can't create temporary file\n");
|
fprintf(stderr, "ar: can't create temporary file\n");
|
return 1;
|
return 1;
|
}
|
}
|
conv4FromNativeToEco((unsigned char *) &numEntries);
|
conv4FromNativeToEco((unsigned char *) &numEntries);
|
if (fwrite(&numEntries, sizeof(numEntries), 1, fo) != 1) {
|
if (fwrite(&numEntries, sizeof(numEntries), 1, fo) != 1) {
|
fprintf(stderr, "ar: can't write temporary file\n");
|
fprintf(stderr, "ar: can't write temporary file\n");
|
fclose(fo);
|
fclose(fo);
|
unlink(TEMP_NAME);
|
unlink(TEMP_NAME);
|
return 1;
|
return 1;
|
}
|
}
|
conv4FromEcoToNative((unsigned char *) &numEntries);
|
conv4FromEcoToNative((unsigned char *) &numEntries);
|
for (i = 0; i < numEntries; i++) {
|
for (i = 0; i < numEntries; i++) {
|
conv4FromNativeToEco((unsigned char *) &table[i].name);
|
conv4FromNativeToEco((unsigned char *) &table[i].name);
|
conv4FromNativeToEco((unsigned char *) &table[i].position);
|
conv4FromNativeToEco((unsigned char *) &table[i].position);
|
}
|
}
|
if (fwrite(table, sizeof(Entry), numEntries, fo) != numEntries) {
|
if (fwrite(table, sizeof(Entry), numEntries, fo) != numEntries) {
|
fprintf(stderr, "ar: can't write temporary file\n");
|
fprintf(stderr, "ar: can't write temporary file\n");
|
fclose(fo);
|
fclose(fo);
|
unlink(TEMP_NAME);
|
unlink(TEMP_NAME);
|
return 1;
|
return 1;
|
}
|
}
|
for (i = 0; i < numEntries; i++) {
|
for (i = 0; i < numEntries; i++) {
|
conv4FromEcoToNative((unsigned char *) &table[i].name);
|
conv4FromEcoToNative((unsigned char *) &table[i].name);
|
conv4FromEcoToNative((unsigned char *) &table[i].position);
|
conv4FromEcoToNative((unsigned char *) &table[i].position);
|
}
|
}
|
if (fwrite(stringArea, 1, getStringPos(), fo) != getStringPos()) {
|
if (fwrite(stringArea, 1, getStringPos(), fo) != getStringPos()) {
|
fprintf(stderr, "ar: can't write temporary file\n");
|
fprintf(stderr, "ar: can't write temporary file\n");
|
fclose(fo);
|
fclose(fo);
|
unlink(TEMP_NAME);
|
unlink(TEMP_NAME);
|
return 1;
|
return 1;
|
}
|
}
|
fclose(fo);
|
fclose(fo);
|
if (verbose) {
|
if (verbose) {
|
showSymdefs(TEMP_NAME);
|
showSymdefs(TEMP_NAME);
|
}
|
}
|
if (createIndex) {
|
if (createIndex) {
|
/* ar -rlb firstName archive TEMP_NAME */
|
/* ar -rlb firstName archive TEMP_NAME */
|
args[0] = firstName;
|
args[0] = firstName;
|
args[1] = archive;
|
args[1] = archive;
|
args[2] = TEMP_NAME;
|
args[2] = TEMP_NAME;
|
res = exec_rCmd(1, args);
|
res = exec_rCmd(1, args);
|
} else {
|
} else {
|
/* ar -rl archive TEMP_NAME */
|
/* ar -rl archive TEMP_NAME */
|
args[0] = archive;
|
args[0] = archive;
|
args[1] = TEMP_NAME;
|
args[1] = TEMP_NAME;
|
args[2] = NULL;
|
args[2] = NULL;
|
res = exec_rCmd(0, args);
|
res = exec_rCmd(0, args);
|
}
|
}
|
unlink(TEMP_NAME);
|
unlink(TEMP_NAME);
|
return res;
|
return res;
|
}
|
}
|
|
|