📄 cfar.c
字号:
/* cfar.c */
/* Import .o and .a (a.out format) files into a cff archive */
/* Version 2 now incorporates FILE mode, absorbing 'cfin' and 'cfdel' */
/* Copyright 1993, 1995 Norman D. Culver, All Rights Reserved */
/* compile: gcc -o -O2 -DSKELETON cfar.c */
typedef unsigned long size_t;
#include "oxbow.h"
extern void (*BUGPRINTF)(char *fmt, ...);
extern long atol(const char *);
extern int strlen(const char *);
extern void *strcpy(char *, const char *);
extern int _strcpy(char *, char *);
extern void memclr(char *, long);
extern int strlwr(char *);
extern void *strrchr(const char *, char);
extern void *strstr(const char *, const char *);
static void setup_origin(unsigned long, int);
extern void oxlink_close_libs(void);
/* Program version */
static Item prgversion = (Item)2;
/* Archive version */
static Item arversion;
/* Maximum library types */
#define MAXLIBTYPE 16
typedef struct {
unsigned long sn;
unsigned long libnum : 12; /* capacity for 4096 libraries per libtype */
unsigned long libtype : 4; /* capacity for 16 library types */
unsigned long unused : 12;
unsigned long tag : 4;
} SymItem;
typedef struct {
unsigned long filetime;
unsigned long sn : 28;
unsigned long tag : 4;
} OrgItem;
/* Action bitmap */
static int act;
#define arADD (1)
#define arREPLACE (2)
#define arDELETE (4)
#define arEXTRACT (8)
#define arCHECK (16)
#define arUPDATE (32)
static int verbose; /* if 1, verbose mode */
static long libtype; /* 0 = modules, 1 = classes */
static long oldlibtype = -1;
static long libnum; /* library number into which files are stored */
static long oldlibnum = -1;
static int map; /* if 1, print archive map */
static int map_bitmaps; /* if 1, and map, print bitmaps */
static int map_entries; /* if 1, and map, print entries */
static int freshen; /* if 1, freshen entries */
static int shrink; /* if 1, shrink archive */
static int issymbol; /* if 1, file names are really symbol names */
static int batfile; /* if 1, print a batchfile to remake archive */
static void *archive; /* handle of the open archive */
static void *msyms; /* handle of the master symbol table */
static void *fipaths; /* handle of the internal filemode path table */
static void *ipaths; /* handle of the internal path table */
static void *qipaths;
static void *origins; /* handle of the origin path table */
static void *qorigins;
static void *lib; /* handle of the current internal library */
static void *plib; /* handle of the library parent directory */
static char curlib[1024]; /* internal path to the current library */
static int curliblen;
static char curobj[1024]; /* internal path to the current file */
static int curobjlen;
static char *cur_orgpath; /* current origin path as given by cfpathtrn */
static int cur_orgtype; /* current origin type as given by cfpathtrn */
static OrgItem cur_org; /* current origin time and serial num */
static char ltypes[MAXLIBTYPE];
static char lnums[4096];
static int delete;
static int replace;
static int add;
static unsigned long
new_sn(char *name)
{
Item sn;
int namlen = strlen(name);
if(cffind(archive, name, namlen, &sn) >= FOUND)
{
++sn.a0;
cfreinsert(archive, name, namlen, &sn);
return sn.a0;
}
return 0;
}
/* ++++++++++++++++++++++++++++ DLLMODE ++++++++++++++++++++++++++++++++ */
static int dllmode;
static void
proc_dllmode(char *dllpath)
{
char buf[256];
char symbol[256];
char dllname[256];
char dlldef[256];
int ordinal, argcnt, symlen, match, deflen;
int filesize, filesize1;
long dupnum;
SymItem symval, saveval;
char *filename;
cfFILE *df;
CFSTAT sbuf;
void *xx, *xx1, *yy;
int dlltype, dll_sn;
char *cp;
filename = strrchr(dllpath, '/');
if(filename)
++filename;
else filename = dllpath;
deflen = _strcpy(dlldef, filename);
if(strstr(dlldef, ".w32"))
dlltype = 1<<4;
else if(strstr(dlldef, ".os2"))
dlltype = 2<<4;
else if(strstr(dlldef, ".lnx"))
dlltype = 3<<4;
else if(strstr(dlldef, ".w16"))
dlltype = 4<<4;
else if(strstr(dlldef, ".os1"))
dlltype = 5<<4;
else
dlltype = 0;
strcpy(curlib, "ltype3");
plib = cfsubopen(archive, curlib, F_RDWR|F_CREAT, NULL);
xx = cfsubopen(plib, dlldef, F_RDONLY, NULL);
if(!xx && delete)
{
cfprintf("cfar: %s does not exist\n", filename);
return;
}
if(xx && !(replace || delete))
{
cfclose(xx);
cfprintf("cfar: %s exists and replace not enabled\n", dlldef);
return;
}
if(add || replace)
{
if(!(xx1 = cfopen(dllpath, F_RDONLY, NULL)))
{
cfclose(xx);
cfprintf("cfar: cannot open %s\n", dllpath);
return;
}
cfstat(xx1, &sbuf);
setup_origin(sbuf.st_mtime, 1);
}
symbol[0] = '_'; /* add leading underscore to symbols */
if(xx && (replace || delete))
{/* DELETE ALL OF THE OLD SYMBOLS */
saveval.sn = 0;
/* get an in-memory uncompressed copy */
yy = cfsubopen(MEMTEMP, "", F_TEMPFILE, NULL);
filesize = cfunzip(yy,0,xx,0);
cfclose(xx);
/* convert the memory file to a stream FILE */
cfseek(yy, 0, S_SET);
df = cffdopen(yy, "rt");
while(cffgets(buf, sizeof(buf)-1, df))
{
if( buf[0] == '#' || !isalnum(buf[0]) )
continue;
if(buf[0] == 'U' && strstr(buf, "UNHANDLED "))
break;
if(isdigit(buf[0]))
{
if(!strstr(buf, "ERROR:"))
{
/* the symbol is stored as oooo sssssssss cccc\n */
cfsscanf(buf, "%d %s %d", &ordinal, &symbol[1], &argcnt);
/* Delete the symbol from msyms */
symlen = strlen(symbol);
dupnum = 0;
for(;;)
{
int result = cffind_dupnum(msyms, symbol, symlen, &symval, &dupnum);
if(result >= FOUND)
{
symval.unused = 0;
match = 0;
if(saveval.sn)
{
if(symval.sn == saveval.sn && symval.libtype == 3)
{
match = 1;
}
}
else
{/* first */
if(symval.libtype == 3)
{/* check if the dll names match */
int snum = symval.libnum;
symval.libnum = 0;
if(cfget(qipaths, &symval, 8, buf, 256) >= FOUND)
{
if(!strcmp(buf, dllname))
{
symval.libnum = snum;
saveval = symval;
match = 1;
}
}
}/* END: symval.libtype == 3 */
}/* END: first */
if(match)
{
if(cfdelete_dupnum(msyms, symbol, symlen, dupnum) != OK)
cfprintf("cfar: ERROR can't delete %s dumpnum=%d\n",
symbol, dupnum);
break;
}
++dupnum;
}/* END: result >= FOUND */
else break;
}/* END: for(;;) */
}/* END: !strstr(ERROR) */
}/* END: isdigit(buf[0]) */
else if((cp = strstr(buf, ".dll")))
{/* new dll encountered */
cp[4]=0;
if(saveval.sn)
{/* delete previous dll name from qipath */
int u = saveval.unused;
int n = saveval.libnum;
saveval.unused = 0;
saveval.libnum = 0;
cfdelete(qipaths, &saveval, 8);
saveval.unused = u;
saveval.libnum = n;
}
strcpy(dllname, buf);
saveval.sn = 0;
if(verbose)
cfprintf("delete %s\n", dllname);
continue;
}/* END: new dll encountered */
}/* END: while(cffgets()) */
/* delete last dllname from qipaths */
if(saveval.sn)
{
saveval.unused = 0;
saveval.libnum = 0;
cfdelete(qipaths, &saveval, 8);
}
cffclose(df); /* auto delete of tempfile yy */
/* Delete the internal copy of dlldef */
cfdelete(plib, dlldef, deflen);
/* Delete the origin linkage */
strcat(dlldef, ".org");
cfdelete(plib, dlldef, deflen+4);
dlldef[deflen] = 0;
}/* END: DELETE OLD SYMBOLS */
if(add || replace)
{/* INSERT NEW SYMBOLS */
/* get the compressed file size */
filesize = cfzip(0,0,xx1,0);
/* create a chunk to hold the compressed file */
xx = cfmake_chunk(plib, dlldef, deflen, filesize);
if(!xx)
{
cfprintf("cfar: cannot create internal file %s\n", filename);
cfclose(xx1);
return;
}
#if 1
/* compress the external file into the internal chunk */
cfseek(xx1, 0, S_SET);
if((filesize1 = cfzip(xx,0,xx1,0)) != filesize)
cfprintf("cfar: ERROR ziperr fs1=%d fs=%d\n", filesize1, filesize);
#else
/* copy the external file into the internal chunk */
cfseek(xx1, 0, S_SET);
if(cfcopy_file(xx, xx1) != sbuf.st_filesize)
{
cfprintf("cfar: ERROR copying %s\n", filename);
cfclose(xx);
cfclose(xx1);
return;
}
#endif
cfclose(xx); /* close the internal dlldef file chunk */
/* Process the external dlldef file */
cfseek(xx1, 0, S_SET);
df = cffdopen(xx1, "rt");
while(cffgets(buf, sizeof(buf)-1, df))
{
if( buf[0] == '#' || !isalnum(buf[0]) )
continue;
if((buf[0] == 'U') && strstr(buf, "UNHANDLED "))
break;
if(isdigit(buf[0]))
{
if(!strstr(buf, "ERROR:"))
{
/* the symbol is stored as oooo sssssssss cccc\n */
cfsscanf(buf, "%d %s %d", &ordinal, &symbol[1], &argcnt);
/* INSERT THE SYMBOL IN MSYMS, symval links to dllname */
symlen = strlen(symbol);
symval.sn = dll_sn;
symval.libtype = 3;
symval.unused = ordinal;
symval.libnum = (argcnt&15) | dlltype;
cfinsert_dupnum(msyms, symbol, symlen, &symval, NULL);
if(verbose)
cfprintf("ord:%d argcnt:%d %s\n", ordinal, argcnt, symbol);
}
}
else if((cp = strstr(buf, ".dll")))
{/* new dll encountered */
cp[4]=0;
strcpy(dllname, buf);
/* insert in qipaths */
dll_sn = new_sn("SN0");
symval.sn = dll_sn;
symval.libtype = 3;
symval.unused = 0;
symval.libnum = 0;
symval.tag = STO_VALUE;
if(verbose)
cfprintf("%s\n", dllname);
if(!cfput(qipaths, &symval, 8, dllname, strlen(dllname)+1,NULL))
cfprintf("cfar: ERROR put dllname `%s' failed\n", dllname);
}
}/* END: while(cffgets()) */
cffclose(df);
/* save the backlink to the origin */
strcat(dlldef, ".org");
cfinsert(plib, dlldef, deflen+4, &cur_org);
}/* END: INSERT NEW SYMBOLS */
}/* proc_dllmode() */
/* +++++++++++++++++++++++++++++ FILEMODE ++++++++++++++++++++++++++++++ */
static int filemode;
static int chunk;
static int newname;
static void *subdir;
static char *midpart;
static char *lastpart;
static char basefile[256];
static char midpath[1024];
static char innerpath[1024];
static void
proc_filemode(char *filepath)
{
void *fit;
void *h = (subdir) ? subdir : archive;
void *fd;
char *filename;
char *cfname;
Item item;
CFSTAT sbuf;
int cfnamlen;
int filesize;
char *tag;
int exists = 0;
filename = strrchr(filepath, '/');
if(filename)
++filename;
else filename = filepath;
if(newname)
cfname = lastpart;
else
cfname = filename;
cfnamlen = strlen(cfname);
if((fit = cfopen(filepath, F_RDONLY, NULL)) != NULL)
{
/* check for existance of the archive item */
if(cfsubstat(h, cfname, &sbuf) == OK)
{
if(!replace)
{
cfclose(fit);
cfprintf("cfar: %s exists and replace not enabled\n", cfname);
return;
}
exists = 1;
cfunlink(h, cfname);
}
cfstat(fit, &sbuf);
filesize = sbuf.st_filesize;
setup_origin(sbuf.st_mtime, 1);
if(verbose || act == arUPDATE)
{
if(act == arUPDATE)
cfprintf("updating %s\n", cfname);
else cfprintf("%s\n", cfname);
}
if(chunk)
{
if(!(fd = cfmake_chunk(h, cfname, cfnamlen, filesize)))
{
cfprintf("cfar: cannot make chunk for %s\n", cfname);
cfclose(fit);
return;
}
}
else
{
if(!(fd = cfsubopen(h, cfname, F_RDWR|F_CREAT|F_FILEONLY, NULL)))
{
cfprintf("cfar: could not create file %s\n", cfname);
cfclose(fit);
return;
}
}
if(cfcopy_file(fd, fit) != filesize)
cfprintf("cfar: ERROR copying %s\n", cfname);
cfclose(fd);
cfclose(fit);
/* Store the backlink to the origin, time + origin serial number */
if(newname)
tag = "?";
else
tag = " ";
curobjlen = cfsprintf(curobj, "%s/%s%s", innerpath, cfname, tag);
if(exists || act == arUPDATE)
{
cfreinsert(fipaths, curobj, curobjlen, &cur_org);
}
else
{
cfinsert(fipaths, curobj, curobjlen, &cur_org);
}
}
else
{
cfprintf("cfar: input file %s not found\n", filepath);
}
}
static void *
create_middle(char *path, void *basehandle)
{
char *cp;
cp = path;
while((cp = (char*)strchr(cp, '/')) != NULL)
{
void *subhandle;
*cp = '\0';
subhandle = cfsubopen(basehandle, path, F_RDWR|F_CREAT, NULL);
cfclose(subhandle);
*cp = '/';
++cp;
}
return cfsubopen(basehandle, path, F_RDWR|F_CREAT, NULL);
}
static void *
open_middle(void *basehandle)
{
void *subhandle = NULL;
if(newname)
{
if(midpart)
{
subhandle = cfsubopen(basehandle, midpath, F_RDWR|F_CREAT, NULL);
if(subhandle == NULL)
{/* create the path in pieces */
subhandle = create_middle(midpath, basehandle);
}
}
}
else /* not newname */
{
if(innerpath[0])
{
subhandle = cfsubopen(basehandle, &innerpath[1], F_RDWR|F_CREAT, NULL);
if(subhandle == NULL)
{/* create the path in pieces */
subhandle = create_middle(&innerpath[1], basehandle);
}
}
}
#if 0
if(subhandle)
cfsetverylazy(subhandle);
#endif
return subhandle;
}
static void
del_entry()
{
CFSTAT sbuf;
char forgpath[1024];
if(innerpath[0])
{
if(verbose)
cfprintf("%s\n", lastpart);
if(cfunlink(archive, innerpath) != OK)
{
cfprintf("cfar: delete failed for `%s'\n", innerpath);
}
else
{
cfsprintf(forgpath, "/fipaths%s ", innerpath);
if(cfunlink(archive, forgpath) != OK)
{
cfsprintf(forgpath, "/fipath/%s?", innerpath);
if(cfunlink(archive, forgpath) != OK)
cfprintf("cfar: delerror, fipath:%s\n", forgpath);
}
}
}
else
{
cfprintf("cfar: delete, path missing\n");
}
}
static void
out_entry()
{
void *in, *of;
if(innerpath[0])
{
if((in = cfsubopen(archive, innerpath, F_RDONLY, NULL)) == NULL)
{
cfprintf("cfar: extract, `%s' does not exist\n", innerpath);
return;
}
if((of = cfopen(lastpart, F_RDWR|F_CREAT, NULL)) == NULL)
{
cfprintf("cfar: extract, cannot create output file `%s'\n", lastpart);
cfclose(in);
}
if(verbose)
cfprintf("%s\n", lastpart);
cfcopy_file(of, in);
cfclose(in);
cfclose(of);
}
else
{
cfprintf("cfar: extract, path missing\n");
}
}
/* ====================== END FILEMODE =================================== */
static int
open_curlib()
{
if(lib)
{/* library is already open */
if(libtype == oldlibtype && libnum == oldlibnum)
return 1;
cfclose(lib);
if(oldlibtype != libtype)
{
cfclose(plib);
cfsprintf(curlib, "ltype%d", libtype);
plib = cfsubopen(archive, curlib, F_RDWR|F_CREAT, NULL);
}
oldlibtype = libtype;
oldlibnum = libnum;
}
if(oldlibtype != libtype) {
cfsprintf(curlib, "ltype%d", libtype);
plib = cfsubopen(archive, curlib, F_RDWR|F_CREAT, NULL);
}
curliblen = cfsprintf(curlib, "ltype%d/lib%d", libtype, libnum);
lib = cfsubopen(archive, curlib, F_RDWR|F_CREAT|F_SORTED, NULL);
if(!lib)
{
cfprintf("cfar: can't open library %s\n", curlib);
return 0;
}
#if 0
cfsetverylazy(lib);
cfsetverylazy(plib);
#endif
return 1;
}
static void *
make_scratch()
{
return cfsubopen(MEMTEMP, "", F_TEMPFILE|F_BITMAP, NULL);
}
static void
get_libtypes(char *name)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -