📄 cfar.c
字号:
void *dirh;
CFDIRENT *d;
memclr(ltypes, MAXLIBTYPE);
dirh = cfopendir(name);
while((d = cfreaddir(dirh)) != NULL) {
if( d->d_name[0] == 'l'
&& d->d_name[1] == 't')
{
long x = atol(&d->d_name[5]);
ltypes[x] = 1;
}
}
cfclosedir(dirh);
}
static void
get_libnums(char *name)
{
void *dirh;
CFDIRENT *d;
memclr(lnums, 4096);
dirh = cfopendir(name);
while((d = cfreaddir(dirh)) != NULL)
{
if( d->d_name[0] == 'l'
&& d->d_name[1] == 'i')
{
long x = atol(&d->d_name[3]);
lnums[x] = 1;
}
}
cfclosedir(dirh);
}
static char *
fileof(char *path)
{
int len = strlen(path);
char *cp = &path[len-1];
char *cp1;
while(cp != path)
{
if(*cp == '/' || *cp == '\\' || *cp == ':') {
++cp;
break;
}
--cp;
}
len = strlen(cp);
cp1 = malloc(len+1);
strcpy(cp1, cp);
return cp1;
}
static char *
objof(char *name)
{
if(issymbol) {
long dupnum = 0;
SymItem symval;
int symlen = strlen(name);
for(;;)
{
int result = cffind_dupnum(msyms, name, symlen, &symval, &dupnum);
if(result >= FOUND)
{
if( (act == arCHECK)
|| ( symval.libtype == libtype
&& symval.libnum == libnum))
{
char curpath[256];
if(cfget(qipaths, &symval, 8, curpath, 256) >= FOUND) {
if(act == arCHECK)
cfprintf("symbol %s is defined in %s\n", name, curpath);
else return fileof(curpath);
}
}
++dupnum;
}
else return NULL;
}
}
else return fileof(name);
}
static void
delete_file(char *name, int internal)
{
char *objname = objof(name);
int objlen;
Item packval;
SymItem symval;
char cpath[256];
int cpathlen;
Item objloc;
if(!objname)
return;
cpathlen = cfsprintf(cpath, "%s/%s", curlib, objname);
/* Delete the data chunk */
objlen = strlen(objname);
if(cffind(lib, objname, objlen, &objloc) < FOUND) {
if(!internal)
cfprintf("cfar: %s not found\n", cpath);
return;
}
if(verbose && !internal)
cfprintf("%s\n", objname);
cfdelete(lib, objname, objlen);
/* Read the quick access symbol pack and delete the symbols */
objname[objlen-1] = 'x';
if(cffind(lib, objname, objlen, &packval) >= FOUND)
{
char *cp, *sp, symlen;
cp = cflocalize(lib, &packval);
for(sp = cp; *sp ; sp += symlen+1)
{
long dupnum = 0;
symlen = strlen(sp);
for(;;)
{
int result = cffind_dupnum(msyms, sp, symlen, &symval, &dupnum);
if(result >= FOUND)
{
if( symval.libtype == libtype
&& symval.libnum == libnum)
{
cfdelete_dupnum(msyms, sp, symlen, dupnum);
break;
}
++dupnum;
}
else break;
}
}
cfrelease(cp, R_CLEAN);
/* Delete the symbol pack */
cfdelete(lib, objname, objlen);
/* Delete the origin linkage */
objname[objlen-1] = 't';
cfdelete(lib, objname, objlen);
}
/* Delete the path info */
cfdelete(ipaths, cpath, cpathlen);
cfdelete(qipaths, &symval, 8);
free(objname);
}
static void
extract_file(char *name)
{
char *objname = objof(name);
int objlen;
Item objloc;
if(!objname)
return;
objlen = strlen(objname);
if(cffind(lib, objname, objlen, &objloc) == FOUND)
{
void *hobj;
void *fd;
if((hobj = cfopen_chunk(lib, &objloc)) != NULL)
{
if((fd = cfopen(objname, F_RDWR|F_CREAT, NULL)) != NULL)
{
cfcopy_file(fd, hobj);
cfclose(fd);
if(verbose)
cfprintf("%s\n", objname);
}
cfclose(hobj);
}
}
free(objname);
}
static void
setup_origin(unsigned long filetime, int flag)
{
int orglen;
char *cp;
Item orgsn;
cur_org.filetime = filetime;
cur_org.tag = STO_VALUE;
cp = &cur_orgpath[strlen(cur_orgpath)-1];
if(!flag && (*cp != 'a' || cp[-1] != '.'))
{/* origin is not a library */
cp = strrchr(cur_orgpath, '/');
*cp = 0;
}
if(flag && !newname)
{
cp = strrchr(cur_orgpath, '/');
*cp = 0;
}
/* Check if the origin is in the system */
orglen = strlen(cur_orgpath);
if(cffind(origins, cur_orgpath, orglen, &orgsn) >= FOUND)
{/* It is in the system, get the serial number */
cur_org.sn = orgsn.a0;
}
else
{/* Enter this origin into the system */
orgsn.item = new_sn("SN1");
orgsn.a2.type = STO_VALUE;
cur_org.sn = orgsn.a0;
/* Store the origin, indexed both ways */
cfinsert(origins, cur_orgpath, orglen, &orgsn);
cfput(qorigins, &orgsn, 4, cur_orgpath, orglen+1, NULL);
}
if(*cp == 0) *cp = '/';
}
static void
insert_file(char *path)
{
void *desc;
/* Open the input file */
if((desc = cfopen(path, F_RDONLY, NULL)) != NULL)
{
int numobjs;
int i, j;
char *objname;
char *sympack;
int packx;
void *scratch;
CFSTAT s;
cfstat(desc, &s);
setup_origin(s.st_mtime, 0);
/* Create a scratch object in memory */
scratch = make_scratch();
/* Take a look at the input file */
numobjs = oxlink_scan_file(desc, scratch);
/* oxlink_scan_file returns results in 'scratch'
and on the 'scratch' stack */
for(i = 0; i < numobjs; ++i, free(objname), free(sympack))
{
unsigned long numsyms;
unsigned long symsize;
unsigned long objsize;
unsigned long objoffset;
unsigned long objnum;
unsigned long objnamlen;
SymItem objval;
int objexists = 0;
int clash = 0;
cfpop_value(scratch, &symsize);
cfpop_value(scratch, &numsyms);
cfpop_value(scratch, &objnum);
cfpop_value(scratch, &objnamlen);
if(objnamlen > 0) {
objname = malloc(objnamlen);
cfpop_data(scratch, objname, objnamlen);
} else {
objname = fileof(path);
objnamlen = strlen(objname)+1;
}
cfpop_value(scratch, &objsize);
cfpop_value(scratch, &objoffset);
/* Get space for a chunk of symbols */
sympack = malloc(symsize+1);
packx = 0;
if((objnamlen + curliblen) > 255)
{
cfprintf("%s -- name too long. CONTINUING\n", objname);
continue;
}
/* Check the object file for current existence */
curobjlen = cfsprintf(curobj, "%s/%s", curlib, objname);
if(cffind(ipaths, curobj, curobjlen, &objval) >= FOUND)
{
objexists = 1;
if(!(act & (arREPLACE|arUPDATE))) {
cfprintf("%s found in archive. CONTINUING\n", curobj);
continue;
}
}
/* Pass 1 over the symbols, check for clashes */
for(j = 0; j < numsyms; ++j)
{/* The global symbols for each .o file have been saved
in 'sratch', keyed by (objnum<<18+symnum) */
Item symptr;
long key = (objnum<<18)+j;
SymItem symval;
int x;
if(cffind(scratch, &key, 4, &symptr) == FOUND)
{
char *cp = cflocalize(scratch, &symptr);
if(cp)
{
/* Add to the quick access pack of symbols */
x = _strcpy(&sympack[packx], cp)+1;
if(!objexists)
{/* Check for symbol clash with other .o files in lib */
long dupnum = 0;
for(;;)
{/* Duplicate symbols are allowed, in separate libs */
int result = cffind_dupnum(msyms,cp,x-1,&symval,&dupnum);
if(result >= FOUND)
{
if( symval.libtype == libtype
&& symval.libnum == libnum)
{
clash = 1;
}
if(!clash && result > FOUND)
{/* Duplicate symbols exist */
++dupnum;
continue;
} else break;
} else break;
}
}/* if(!objexists) */
cfrelease(cp, R_CLEAN);
if(clash)
{
char pathname[256];
pathname[0] = 0;
cfget(qipaths, &symval, 8, pathname, 256);
cfprintf("cfar: symbol `%s' in %s clashes with `%s' CONTINUING\n",
&sympack[packx], objname, pathname);
break;
}
packx += x;
}/* if(cp) */
}/* if(cffind ) */
}/* END: for(j ) symbol pass 1 */
if(clash || !(act & (arADD|arREPLACE|arUPDATE)))
continue;
/* NOW add or replace the object file */
if(verbose || act == arUPDATE)
{
if(act == arUPDATE)
cfprintf("updating %s\n",objname);
else cfprintf("%s\n", objname);
}
if(objexists) {
delete_file(objname, 1);
} else {/* Get a new serial number for the .o file */
objval.sn = new_sn("SN0");
objval.libnum = libnum;
objval.libtype = libtype;
objval.unused = 0;
objval.tag = STO_VALUE;
}
/* Store the object file in a chunk */
#if 1 /* the easy slow way, not much memory usage */
{
void *of;
if((of = cfmake_chunk(lib, objname, objnamlen-1, objsize)))
{
if(cfcopy_file(of, desc) != objsize)
{
cfclose(of);
cfprintf("cfar: ERROR copying %s\n", objname);
break;
}
cfclose(of);
}
else
{
cfprintf("cfar: ERROR can't make chunk for %s\n", objname);
break;
}
}
#else /* the hard fast way, may use a LOT of memory */
{
Item space;
char *loc;
if(cfgetspace(lib, objsize, &space) != NULL)
{/* ensure that there is enough space in the localizer bufs */
long curbufs, objbufs;
objbufs = (objsize / 1024)+1;
curbufs = cfcurbufs();
if(objbufs > curbufs)
{
cfmodbufs((objbufs-curbufs)+16);
objbufs = cfcurbufs();
}
if((loc = cflocalize(lib, &space)) != NULL) {
cfseek(desc, objoffset, S_SET);
cfread(desc, loc, objsize);
cfrelease(loc, R_DIRTY);
cfinsert(lib, objname, objnamlen-1, &space);
} else {
cfretspace(lib, &space);
cfprintf("cfar: ERROR can't localize space for %s\n", objname);
break;
}
}
else
{
cfprintf("cfar: ERROR can't allocate space for %s\n", objname);
break;
}
}
#endif
/* Store the quick access package of symbols */
objname[objnamlen-2] = 'x';
sympack[symsize] = 0;
cfput(lib, objname, objnamlen-1, sympack, symsize+1, NULL);
/* Store the backlink to the origin, time + origin serial number */
objname[objnamlen-2] = 't';
cfinsert(lib, objname, objnamlen-1, &cur_org);
/* Store the path, indexed both ways */
cfinsert(ipaths, curobj, curobjlen, &objval);
cfput(qipaths, &objval, 8, curobj, curobjlen+1, NULL);
/* Store the symbols, symname is the key, objval is the item */
/* Pass 2 over the symbols */
for(j = 0; j < numsyms; ++j)
{/* The global symbols for each .o file have been saved
in 'scratch', keyed by (objnum<<18+symnum) */
Item symptr;
long key = (objnum<<18)+j;
if(cffind(scratch, &key, 4, &symptr) == FOUND)
{
char *cp;
if((cp = cflocalize(scratch, &symptr)) != NULL) {
cfinsert_dupnum(msyms, cp, strlen(cp), &objval, NULL);
cfrelease(cp, R_CLEAN);
} else {
cfprintf("cfar: ERROR can't localize space for symbol %d\n", j);
break;
}
}
}
}/* END: for(numobjs) */
cfclose(scratch);
cfclose(desc);
}/* END: if(desc) */
else cfprintf("cfar: can't open file %s, CONTINUING\n", path);
}
static void
proc_objfile(char *path)
{
if(issymbol && (act == arCHECK))
{
objof(path);
return;
}
if(act & arEXTRACT)
extract_file(path);
if(act & arDELETE)
delete_file(path, 0);
if(act & (arADD|arREPLACE|arCHECK|arUPDATE))
insert_file(path);
}
static void
print_map(char *arch)
{
char path[256];
void *dirh;
CFDIRENT *d;
int i, j;
cfprintf("MAP of %s\n", arch);
if(map_entries) {
cfprintentries(arch);
cfsprintf(path, "%s/ipaths", arch);
cfprintentries(path);
cfsprintf(path, "%s/qipaths", arch);
cfprintentries(path);
cfsprintf(path, "%s/origins", arch);
cfprintentries(path);
cfsprintf(path, "%s/qorigins", arch);
cfprintentries(path);
cfsprintf(path, "%s/msyms", arch);
cfprintentries(path);
}
/* Print a list of origins */
cfprintf("\n-------- OUTSIDE ORIGINS ----------\n\n");
cfsprintf(path, "%s/origins", arch);
if((origins = cfopen(path, F_STAT, NULL)) != NULL)
{
Item orgnum;
if(cfhead(origins, &orgnum) == OK)
{
do {
memclr(path, 255);
cfkey(origins, path, 255);
cfprintf("oid:%u\t%s\n", orgnum.a0, path);
} while(cfnext(origins, &orgnum) == OK);
}
cfclose(origins);
}
/* Print the various libraries and entries */
cfprintf("\n-------- LIBRARIES ----------\n\n");
get_libtypes(arch);
for(i = 0; i < MAXLIBTYPE; ++i)
{
if(!ltypes[i])
continue;
cfsprintf(path, "%s/ltype%d", arch, i);
cfprintf("\nLibrary type %d\n", i);
get_libnums(path);
if(map_entries) {
cfprintf("------------ RAW ENTRIES -----------\n");
cfprintentries(path);
}
if(i == 3)
{/* dllmode library */
cfprintf("DLL SYMBOL ENTRIES\n");
continue;
}
for(j = 0; j < 4096; ++j)
{
void *clib;
if(!lnums[j])
continue;
cfsprintf(path, "%s/ltype%d/lib%d", arch, i, j);
if((clib = cfopen(path, F_STAT, NULL)) != NULL) {
if(verbose)
cfprintf("------- lib%d %d bytes -------\n",
j, cfbytesused(clib));
else
cfprintf("------- lib%d --------\n", j);
cfhead(clib, NULL);
do {
char key[256];
int keylen;
memclr(key,256);
cfkey(clib, key, 255);
keylen = strlen(key);
if(key[keylen-1] == 'o') {
if(verbose) {
int dlen;
OrgItem oi;
cfdatalen(clib, &dlen);
key[keylen-1] = 't';
cffind(clib, key, keylen, &oi);
key[keylen-1] = 'o';
cfprintf(" %s bytes:%u oid:%u %s",
key, dlen, oi.sn, ctime(&oi.filetime));
}
else
cfprintf(" %s\n", key);
if(verbose) {
Item pakval;
char *cp, *sp;
key[keylen-1] = 'x';
cfmark(clib);
cffind(clib, key, keylen, &pakval);
cp = cflocalize(clib, &pakval);
for(sp=cp; *sp; sp += strlen(sp)+1)
{
cfprintf(" %s\n", sp);
}
cfrelease(cp, R_CLEAN);
cffind_mark(clib, NULL);
}
}
} while (cfnext(clib, NULL) == OK);
if(map_entries) {
cfprintf("------------ RAW ENTRIES -----------\n");
cfprintentries(clib);
}
cfclose(clib);
}
}
}
/* Print the list of stored files */
cfprintf("\n---------- STORED FILES ----------\n\n");
cfsprintf(path, "%s/fipaths", arch);
if((fipaths = cfopen(path, F_STAT, NULL)) != NULL)
{
OrgItem oi;
if(cfhead(fipaths, &oi) == OK)
{
do {
memclr(path, 255);
cfkey(fipaths, path, 255);
cfprintf("%s\toid:%u %s",
path, oi.sn, ctime(&oi.filetime));
} while(cfnext(fipaths, &oi) == OK);
}
if(map_entries) {
cfprintf("------------ RAW ENTRIES -----------\n");
cfprintentries(fipaths);
}
cfclose(fipaths);
}
if(map_bitmaps) {
cfprintf("\n------------ BITMAPS ---------------\n");
cfprintbitmaps(arch);
}
}
static void
Usage()
{
cfprintf("\
Usage: cfar [-acdflmrstvxCDFMNS] cfpath [file...]\n\
Switch -- Meaning\n\
a Add file, do not overwrite\n\
c Check input files against library for clashes\n\
d Delete file\n\
f Freshen the archive (replace outdated files)\n\
l# Place file in libnum #, max:4095\n\
m Print archive map to stdout\n\
r Replace/Add file\n\
s 'file' is a symbol name not a file name (for extract/delete)\n\
t# Set libtype # 0=module, 1=class, 2=subsystem, max:15\n\
v Verbose\n\
x Extract file\n\
M Print to stdout, commands which would recreate the archive\n\
S Shrink archive\n\
D Dll mode, deal with symbols stored in dlls\n\
F File mode, symbols not saved\n\
C If File mode, put file in a chunk\n\
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -