home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / oxcc1433.zip / SRC / CFAR.C < prev    next >
C/C++ Source or Header  |  1995-11-04  |  37KB  |  1,545 lines

  1. /* cfar.c */
  2. /* Import .o and .a (a.out format) files into a cff archive */
  3. /* Version 2 now incorporates FILE mode, absorbing 'cfin' and 'cfdel' */
  4. /* Copyright 1993, 1995 Norman D. Culver, All Rights Reserved */
  5.  
  6. /* compile: gcc -o -O2 -DSKELETON cfar.c */
  7.  
  8. typedef unsigned long size_t;
  9.  
  10. #include "oxbow.h"
  11.  
  12. extern void (*BUGPRINTF)(char *fmt, ...);
  13.  
  14. extern long atol(const char *);
  15. extern int strlen(const char *);
  16. extern void *strcpy(char *, const char *);
  17. extern int _strcpy(char *, char *);
  18. extern void memclr(char *, long);
  19. extern int strlwr(char *);
  20. extern void *strrchr(const char *, char);
  21. static void setup_origin(unsigned long, int);
  22. extern void oxlink_close_libs(void);
  23.  
  24. /* Program version */
  25. static Item prgversion = (Item)2;
  26. /* Archive version */
  27. static Item arversion;
  28.  
  29. /* Maximum library types */
  30. #define MAXLIBTYPE 16
  31.  
  32. typedef struct {
  33.     unsigned long sn;
  34.     unsigned long libnum : 12;    /* capacity for 4096 libraries per libtype */
  35.     unsigned long libtype : 4;    /* capacity for 16 library types */
  36.     unsigned long unused : 12;
  37.     unsigned long tag : 4;
  38. } SymItem;
  39.  
  40. typedef struct {
  41.     unsigned long filetime;
  42.     unsigned long sn : 28;
  43.     unsigned long tag : 4;
  44. } OrgItem;
  45.  
  46. /* Action bitmap */
  47. static int act;
  48. #define arADD (1)
  49. #define arREPLACE (2)
  50. #define arDELETE (4)
  51. #define arEXTRACT (8)
  52. #define arCHECK (16)
  53. #define arUPDATE (32)
  54.  
  55. static int verbose;            /* if 1, verbose mode */
  56. static long libtype;    /* 0 = modules, 1 = classes */
  57. static long oldlibtype = -1;
  58. static long libnum;        /* library number into which files are stored */
  59. static long oldlibnum = -1;
  60. static int map;            /* if 1, print archive map */
  61. static int map_bitmaps;    /* if 1, and map, print bitmaps */
  62. static int map_entries; /* if 1, and map, print entries */
  63. static int freshen;        /* if 1, freshen entries */
  64. static int shrink;        /* if 1, shrink archive */
  65. static int issymbol;    /* if 1, file names are really symbol names */
  66. static int batfile;        /* if 1, print a batchfile to remake archive */
  67. static void *archive;    /* handle of the open archive */
  68. static void *msyms;        /* handle of the master symbol table */
  69. static void *fipaths;    /* handle of the internal filemode path table */
  70. static void *ipaths;    /* handle of the internal path table */
  71. static void *qipaths;
  72. static void *origins;    /* handle of the origin path table */
  73. static void *qorigins;
  74. static void *lib;            /* handle of the current internal library */
  75. static void *plib;            /* handle of the library parent directory */
  76. static char curlib[1024];        /* internal path to the current library */
  77. static int curliblen;
  78. static char curobj[1024];    /* internal path to the current file */
  79. static int curobjlen;
  80. static char *cur_orgpath;    /* current origin path as given by cfpathtrn */
  81. static int cur_orgtype;        /* current origin type as given by cfpathtrn */
  82. static OrgItem cur_org;        /* current origin time and serial num */
  83. static char ltypes[MAXLIBTYPE];
  84. static char lnums[4096];
  85.  
  86.  
  87. /* +++++++++++++++++++++++++++++ FILEMODE ++++++++++++++++++++++++++++++ */
  88. static int filemode;
  89. static int chunk;
  90. static int newname;
  91. static int replace;
  92. static int add;
  93. static void *subdir;
  94. static char *midpart;
  95. static char *lastpart;
  96. static char basefile[256];
  97. static char midpath[1024];
  98. static char innerpath[1024];
  99.  
  100. static void
  101. proc_filemode(char *filepath)
  102. {
  103. void *fit;
  104. void *h = (subdir) ? subdir : archive;
  105. void *fd;
  106. char *filename;
  107. char *cfname;
  108. Item item;
  109. CFSTAT sbuf;
  110. int cfnamlen;
  111. int filesize;
  112. char *tag;
  113. int exists = 0;
  114.  
  115.     filename = strrchr(filepath, '/');
  116.     if(filename)
  117.         ++filename;
  118.     else filename = filepath;
  119.  
  120.     if(newname)
  121.         cfname = lastpart;
  122.     else
  123.         cfname = filename;
  124.  
  125.     cfnamlen = strlen(cfname);
  126.  
  127.     if((fit = cfopen(filepath, F_RDONLY, NULL)) != NULL)
  128.     {
  129.         /* check for existance of the archive item */
  130.         if(cfsubstat(h, cfname, &sbuf) == OK)
  131.         {
  132.           if(!replace)
  133.           {
  134.             cfprintf("cfar: %s exists and replace not enabled\n", cfname);
  135.             return;
  136.             cfclose(fit);
  137.           }
  138.           exists = 1;
  139.           cfunlink(h, cfname);
  140.         }
  141.         cfstat(fit, &sbuf);
  142.         filesize = sbuf.st_filesize;
  143.         setup_origin(sbuf.st_mtime, 1);
  144.  
  145.         if(verbose || act == arUPDATE)
  146.         {
  147.             if(act == arUPDATE)
  148.                  cfprintf("updating %s\n", cfname);
  149.             else cfprintf("%s\n", cfname);
  150.         }
  151.         if(chunk)
  152.         {
  153.             if(!(fd = cfmake_chunk(h, cfname, cfnamlen, filesize)))
  154.             {
  155.                 cfprintf("cfar: cannot make chunk for %s\n", cfname);
  156.                 cfclose(fit);
  157.                 return;
  158.             } 
  159.         }
  160.         else
  161.         {
  162.             if(!(fd = cfsubopen(h, cfname, F_RDWR|F_CREAT|F_FILEONLY, NULL)))
  163.             {
  164.                 cfprintf("cfar: could not create file %s\n", cfname);
  165.                 cfclose(fit);
  166.                 return;
  167.             }
  168.         }
  169.  
  170.         if(cfcopy_file(fd, fit) != filesize)
  171.             cfprintf("cfar: ERROR copying %s\n", cfname);
  172.  
  173.         cfclose(fd);
  174.         cfclose(fit);
  175.  
  176.         /* Store the backlink to the origin, time + origin serial number */
  177.         if(newname)
  178.             tag = "?";
  179.         else
  180.             tag = " ";
  181.         
  182.         curobjlen = cfsprintf(curobj, "%s/%s%s", innerpath, cfname, tag);
  183.         if(exists || act == arUPDATE)
  184.         {
  185.             cfreinsert(fipaths, curobj, curobjlen, &cur_org);
  186.         }
  187.         else
  188.         {
  189.             cfinsert(fipaths, curobj, curobjlen, &cur_org);
  190.         }
  191.     }
  192.     else
  193.     {
  194.         cfprintf("cfar: input file %s not found\n", filepath);
  195.     }
  196. }
  197. static void *
  198. create_middle(char *path, void *basehandle)
  199. {
  200. char *cp;
  201.  
  202.     cp = path;
  203.     while((cp = (char*)strchr(cp, '/')) != NULL)
  204.     {
  205.     void *subhandle;
  206.         *cp = '\0';        
  207.         subhandle = cfsubopen(basehandle, path, F_RDWR|F_CREAT, NULL);
  208.         cfclose(subhandle);
  209.         *cp = '/';
  210.         ++cp;
  211.     } 
  212.     return cfsubopen(basehandle, path, F_RDWR|F_CREAT, NULL);
  213. }
  214. static void *
  215. open_middle(void *basehandle)
  216. {
  217. void *subhandle = NULL;
  218.  
  219.     if(newname)
  220.     {
  221.       if(midpart)
  222.       {
  223.         subhandle = cfsubopen(basehandle, midpath, F_RDWR|F_CREAT, NULL);
  224.         if(subhandle == NULL)
  225.         {/* create the path in pieces */
  226.             subhandle = create_middle(midpath, basehandle);
  227.         }
  228.       }
  229.     }
  230.     else /* not newname */
  231.     {
  232.       if(innerpath[0])
  233.       {
  234.         subhandle = cfsubopen(basehandle, &innerpath[1], F_RDWR|F_CREAT, NULL);
  235.         if(subhandle == NULL)
  236.         {/* create the path in pieces */
  237.             subhandle = create_middle(&innerpath[1], basehandle);
  238.         }
  239.       }
  240.     }
  241. #if 0
  242.     if(subhandle)
  243.         cfsetverylazy(subhandle);
  244. #endif
  245.     return subhandle;
  246. }
  247. static void
  248. del_entry()
  249. {
  250. CFSTAT sbuf;
  251. char forgpath[1024];
  252.  
  253.     if(innerpath[0])
  254.     {
  255.         if(verbose)    
  256.             cfprintf("%s\n", lastpart);
  257.  
  258.         if(cfunlink(archive, innerpath) != OK)
  259.         {
  260.             cfprintf("cfar: delete failed for `%s'\n", innerpath);
  261.         }
  262.         else
  263.         {
  264.             cfsprintf(forgpath, "/fipaths%s ", innerpath);
  265.             if(cfunlink(archive, forgpath) != OK)
  266.             {
  267.                 cfsprintf(forgpath, "/fipath/%s?", innerpath);
  268.                 if(cfunlink(archive, forgpath) != OK)
  269.                     cfprintf("cfar: delerror, fipath:%s\n", forgpath);
  270.             }
  271.         }
  272.     }
  273.     else
  274.     {
  275.         cfprintf("cfar: delete, path missing\n");
  276.     }
  277. }
  278. static void
  279. out_entry()
  280. {
  281. void *in, *of;
  282.  
  283.     if(innerpath[0])
  284.     {
  285.       if((in = cfsubopen(archive, innerpath, F_RDONLY, NULL)) == NULL)
  286.       {
  287.         cfprintf("cfar: extract, `%s' does not exist\n", innerpath);
  288.         return;
  289.       }
  290.       if((of = cfopen(lastpart, F_RDWR|F_CREAT, NULL)) == NULL)
  291.       {
  292.           cfprintf("cfar: extract, cannot create output file `%s'\n", lastpart);
  293.         cfclose(in);
  294.       }
  295.       if(verbose)
  296.           cfprintf("%s\n", lastpart);
  297.       cfcopy_file(of, in);
  298.       cfclose(in);
  299.       cfclose(of);
  300.     }
  301.     else
  302.     {
  303.         cfprintf("cfar: extract, path missing\n");
  304.     }
  305. }
  306. /* ====================== END FILEMODE =================================== */
  307. static int
  308. open_curlib()
  309. {
  310.     if(lib)
  311.     {/* library is already open */
  312.         if(libtype == oldlibtype && libnum == oldlibnum)
  313.             return 1;
  314.  
  315.         cfclose(lib);
  316.         if(oldlibtype != libtype)
  317.         {
  318.             cfclose(plib);
  319.             cfsprintf(curlib, "ltype%d", libtype);
  320.             plib = cfsubopen(archive, curlib, F_RDWR|F_CREAT, NULL);
  321.         }
  322.         oldlibtype = libtype;
  323.         oldlibnum = libnum;
  324.     }
  325.     if(oldlibtype != libtype) {
  326.         cfsprintf(curlib, "ltype%d", libtype);
  327.         plib = cfsubopen(archive, curlib, F_RDWR|F_CREAT, NULL);
  328.     }
  329.     curliblen = cfsprintf(curlib, "ltype%d/lib%d", libtype, libnum);
  330.     lib = cfsubopen(archive, curlib, F_RDWR|F_CREAT|F_SORTED, NULL);
  331.     if(!lib)
  332.     {
  333.         cfprintf("cfar: can't open library %s\n", curlib);
  334.         return 0;
  335.     }
  336. #if 0
  337.     cfsetverylazy(lib);
  338.     cfsetverylazy(plib);
  339. #endif
  340.     return 1;
  341. }
  342. static void *
  343. make_scratch()
  344. {
  345.     return cfsubopen(MEMTEMP, "", F_TEMPFILE|F_BITMAP, NULL);
  346. }
  347. static void
  348. get_libtypes(char *name)
  349. {
  350. void *dirh;
  351. CFDIRENT *d;
  352.     memclr(ltypes, MAXLIBTYPE);
  353.     dirh = cfopendir(name);
  354.     while((d = cfreaddir(dirh)) != NULL) {
  355.         if(        d->d_name[0] == 'l'
  356.             &&    d->d_name[1] == 't')
  357.         {
  358.         long x = atol(&d->d_name[5]);
  359.             ltypes[x] = 1;
  360.         }
  361.     }
  362.     cfclosedir(dirh);
  363. }
  364. static void
  365. get_libnums(char *name)
  366. {
  367. void *dirh;
  368. CFDIRENT *d;
  369.     memclr(lnums, 4096);        
  370.     dirh = cfopendir(name);
  371.     while((d = cfreaddir(dirh)) != NULL)
  372.     {
  373.     long x = atol(&d->d_name[3]);
  374.         lnums[x] = 1;
  375.     }
  376.     cfclosedir(dirh);
  377. }
  378. static unsigned long
  379. new_sn(char *name)
  380. {
  381. Item sn;
  382. int namlen = strlen(name);
  383.     if(cffind(archive, name, namlen, &sn) >= FOUND)
  384.     {
  385.         ++sn.a0;
  386.         cfreinsert(archive, name, namlen, &sn);
  387.         return sn.a0;
  388.     }
  389.     return 0;
  390. }
  391. static char *
  392. fileof(char *path)
  393. {
  394. int len = strlen(path);
  395. char *cp = &path[len-1];
  396. char *cp1;
  397.     while(cp != path)
  398.     {
  399.         if(*cp == '/' || *cp == '\\' || *cp == ':') {
  400.             ++cp;
  401.             break;
  402.         }
  403.         --cp;
  404.     }
  405.     len = strlen(cp);
  406.     cp1 = malloc(len+1);
  407.     strcpy(cp1, cp);
  408.     return cp1;
  409. }
  410. static char *
  411. objof(char *name)
  412. {
  413.     if(issymbol) {
  414.     long dupnum = 0;
  415.     SymItem symval;
  416.     int symlen = strlen(name);
  417.         for(;;)
  418.         {
  419.         int    result = cffind_dupnum(msyms, name, symlen, &symval, &dupnum);
  420.  
  421.             if(result >= FOUND)
  422.             {
  423.                 if(        (act == arCHECK)
  424.                     ||    (    symval.libtype == libtype
  425.                          &&    symval.libnum == libnum))
  426.                 {
  427.                 char curpath[256];
  428.                     if(cfget(qipaths, &symval, 8, curpath, 256) >= FOUND) {
  429.                       if(act == arCHECK)
  430.                         cfprintf("symbol %s is defined in %s\n", name, curpath);
  431.                       else return fileof(curpath);
  432.                     }
  433.                 }
  434.                 ++dupnum;
  435.             }
  436.             else return NULL;
  437.         }
  438.     }
  439.     else return fileof(name);
  440. }
  441. static void
  442. delete_file(char *name, int internal)
  443. {
  444. char *objname = objof(name);
  445. int objlen;
  446. Item packval;
  447. SymItem symval;
  448. char cpath[256];
  449. int cpathlen;
  450. Item objloc;
  451.  
  452.     if(!objname)
  453.         return;
  454.  
  455.     cpathlen = cfsprintf(cpath, "%s/%s", curlib, objname);
  456.  
  457.     /* Delete the data chunk */
  458.  
  459.     objlen = strlen(objname);
  460.     if(cffind(lib, objname, objlen, &objloc) < FOUND) {
  461.         if(!internal)
  462.             cfprintf("cfar: %s not found\n", cpath);
  463.         return;
  464.     }
  465.     if(verbose && !internal)
  466.         cfprintf("%s\n", objname);
  467.  
  468.     cfdelete(lib, objname, objlen);
  469.  
  470.     /* Read the quick access symbol pack and delete the symbols */
  471.     objname[objlen-1] = 'x';
  472.     if(cffind(lib, objname, objlen, &packval) >= FOUND)
  473.     {
  474.     char *cp, *sp, symlen;
  475.         cp = cflocalize(lib, &packval);
  476.         for(sp = cp; *sp ; sp += symlen+1)
  477.         {
  478.         long dupnum = 0;
  479.             symlen = strlen(sp);            
  480.             for(;;)
  481.             {
  482.             int    result = cffind_dupnum(msyms, sp, symlen, &symval, &dupnum);
  483.                 if(result >= FOUND)
  484.                 {
  485.                     if(        symval.libtype == libtype
  486.                         &&    symval.libnum == libnum)
  487.                     {
  488.                         cfdelete_dupnum(msyms, sp, symlen, dupnum);
  489.                         break;
  490.                     }
  491.                     ++dupnum;
  492.                 }
  493.                 else break;
  494.             }
  495.         }
  496.         cfrelease(cp, R_CLEAN);
  497.         /* Delete the symbol pack */
  498.         cfdelete(lib, objname, objlen);
  499.         /* Delete the origin linkage */
  500.         objname[objlen-1] = 't';
  501.         cfdelete(lib, objname, objlen);
  502.     }
  503.     /* Delete the path info */
  504.     cfdelete(ipaths, cpath, cpathlen);
  505.     cfdelete(qipaths, &symval, 8);
  506.     free(objname);
  507. }
  508. static void
  509. extract_file(char *name)
  510. {
  511. char *objname = objof(name);
  512. int objlen;
  513. Item objloc;
  514.  
  515.     if(!objname)
  516.         return;
  517.  
  518.     objlen = strlen(objname);
  519.     if(cffind(lib, objname, objlen, &objloc) == FOUND)
  520.     {
  521.     void *hobj;
  522.     void *fd;
  523.  
  524.         if((hobj = cfopen_chunk(lib, &objloc)) != NULL)
  525.         {
  526.             if((fd = cfopen(objname, F_RDWR|F_CREAT, NULL)) != NULL)
  527.             {
  528.                 cfcopy_file(fd, hobj);
  529.                 cfclose(fd);
  530.                 if(verbose)
  531.                     cfprintf("%s\n", objname);
  532.             }
  533.             cfclose(hobj);
  534.         }
  535.     }
  536.     free(objname);
  537. }
  538. static void
  539. setup_origin(unsigned long filetime, int flag)
  540. {
  541. int orglen;
  542. char *cp;
  543. Item orgsn;
  544.  
  545.     cur_org.filetime = filetime;
  546.     cur_org.tag = STO_VALUE;
  547.     cp = &cur_orgpath[strlen(cur_orgpath)-1];
  548.  
  549.     if(!flag && (*cp != 'a' || cp[-1] != '.'))
  550.     {/* origin is not a library */
  551.         cp = strrchr(cur_orgpath, '/');
  552.         *cp = 0;
  553.     }
  554.     if(flag & !newname)
  555.     {
  556.         cp = strrchr(cur_orgpath, '/');
  557.         *cp = 0;
  558.     }
  559.     /* Check if the origin is in the system */
  560.     orglen = strlen(cur_orgpath);
  561.     if(cffind(origins, cur_orgpath, orglen, &orgsn) >= FOUND)
  562.     {/* It is in the system, get the serial number */
  563.         cur_org.sn = orgsn.a0;
  564.     }
  565.     else
  566.     {/* Enter this origin into the system */
  567.         orgsn.item = new_sn("SN1");
  568.         orgsn.a2.type = STO_VALUE;
  569.         cur_org.sn = orgsn.a0;
  570.  
  571.         /* Store the origin, indexed both ways */
  572.         cfinsert(origins, cur_orgpath, orglen, &orgsn);
  573.         cfput(qorigins, &orgsn, 4, cur_orgpath, orglen+1, NULL);
  574.     }
  575.     if(*cp == 0) *cp = '/';
  576. }
  577. static void
  578. insert_file(char *path)
  579. {
  580. void *desc;
  581.  
  582.     /* Open the input file */
  583.     if((desc = cfopen(path, F_RDONLY, NULL)) != NULL)
  584.     {
  585.     int numobjs;
  586.     int i, j;
  587.     char *objname;
  588.     char *sympack;
  589.     int packx;
  590.     void *scratch;
  591.     CFSTAT s;
  592.  
  593.         cfstat(desc, &s);
  594.         setup_origin(s.st_mtime, 0);
  595.  
  596.         /* Create a scratch object in memory */
  597.         scratch = make_scratch();
  598.  
  599.         /* Take a look at the input file */
  600.         numobjs = oxlink_scan_file(desc, scratch);        
  601.  
  602.         /* oxlink_scan_file returns results in 'scratch' 
  603.             and on the 'scratch' stack */
  604.         for(i = 0; i < numobjs; ++i, free(objname), free(sympack))
  605.         {
  606.         unsigned long numsyms;
  607.         unsigned long symsize;
  608.         unsigned long objsize;
  609.         unsigned long objoffset;
  610.         unsigned long objnum;
  611.         unsigned long objnamlen;
  612.         SymItem objval;
  613.         int objexists = 0;
  614.         int clash = 0;
  615.  
  616.             cfpop_value(scratch, &symsize);
  617.             cfpop_value(scratch, &numsyms);
  618.             cfpop_value(scratch, &objnum);
  619.             cfpop_value(scratch, &objnamlen);
  620.             if(objnamlen > 0) {
  621.                 objname = malloc(objnamlen);
  622.                 cfpop_data(scratch, objname, objnamlen);
  623.             } else {
  624.                 objname = fileof(path);
  625.                 objnamlen = strlen(objname)+1;
  626.             }
  627.             cfpop_value(scratch, &objsize);
  628.             cfpop_value(scratch, &objoffset);
  629.  
  630.             /* Get space for a chunk of symbols */
  631.             sympack = malloc(symsize+1);
  632.             packx = 0;
  633.  
  634.             if((objnamlen + curliblen) > 255)
  635.             {
  636.                 cfprintf("%s -- name too long. CONTINUING\n", objname);
  637.                 continue;
  638.             }
  639.              /* Check the object file for current existence */
  640.             curobjlen = cfsprintf(curobj, "%s/%s", curlib, objname);
  641.             if(cffind(ipaths, curobj, curobjlen, &objval) >= FOUND)
  642.             {
  643.                 objexists = 1;
  644.                 if(!(act & (arREPLACE|arUPDATE))) {
  645.                     cfprintf("%s found in archive. CONTINUING\n", curobj);
  646.                     continue;
  647.                 }
  648.             }
  649.             /* Pass 1 over the symbols, check for clashes */ 
  650.             for(j = 0; j < numsyms; ++j)
  651.             {/* The global symbols for each .o file have been saved
  652.                     in 'sratch', keyed by (objnum<<18+symnum) */
  653.             Item symptr;
  654.             long key = (objnum<<18)+j;
  655.             SymItem symval;
  656.             int x;
  657.               if(cffind(scratch, &key, 4, &symptr) == FOUND)
  658.               {
  659.               char *cp = cflocalize(scratch, &symptr);
  660.                 if(cp)
  661.                 {
  662.                   /* Add to the quick access pack of symbols */
  663.                   x = _strcpy(&sympack[packx], cp)+1;
  664.                   if(!objexists)
  665.                   {/* Check for symbol clash with other .o files in lib */
  666.                     long dupnum = 0;
  667.                       for(;;)
  668.                       {/* Duplicate symbols are allowed, in separate libs */
  669.                       int result = cffind_dupnum(msyms,cp,x-1,&symval,&dupnum);
  670.                         if(result >= FOUND)
  671.                         {
  672.                             if(        symval.libtype == libtype
  673.                                 &&    symval.libnum == libnum)
  674.                             {
  675.                                 clash = 1;
  676.                             }
  677.                             if(!clash && result > FOUND)
  678.                             {/* Duplicate symbols exist */
  679.                                 ++dupnum;
  680.                                 continue;
  681.                             } else break;
  682.                         } else break;
  683.                       }
  684.                     }/* if(!objexists) */
  685.                     cfrelease(cp, R_CLEAN);
  686.                     if(clash)
  687.                     {
  688.                     char pathname[256];
  689.  
  690.                       pathname[0] = 0;
  691.                       cfget(qipaths, &symval, 8, pathname, 256);
  692.                       cfprintf("cfar: symbol `%s' in %s clashes with `%s' CONTINUING\n",
  693.                                 &sympack[packx], objname, pathname);
  694.                       break;
  695.                     }
  696.                     packx += x;
  697.                   }/* if(cp) */
  698.                 }/* if(cffind ) */
  699.             }/* END: for(j ) symbol pass 1 */
  700.             if(clash || !(act & (arADD|arREPLACE|arUPDATE)))
  701.                 continue;
  702.  
  703.             /* NOW add or replace the object file */
  704.             if(verbose || act == arUPDATE)
  705.             {
  706.                 if(act == arUPDATE)
  707.                      cfprintf("updating %s\n",objname);
  708.                 else cfprintf("%s\n", objname);
  709.             }
  710.             if(objexists) {
  711.                 delete_file(objname, 1);    
  712.             } else {/* Get a new serial number for the .o file */
  713.                 objval.sn = new_sn("SN0");                
  714.                 objval.libnum = libnum;
  715.                 objval.libtype = libtype;
  716.                 objval.unused = 0;
  717.                 objval.tag = STO_VALUE;
  718.             }
  719.  
  720.             /* Store the object file in a chunk */
  721. #if 1 /* the easy slow way, not much memory usage */
  722.             {
  723.             void *of;
  724.                 if((of = cfmake_chunk(lib, objname, objnamlen-1, objsize)))
  725.                 {
  726.                     if(cfcopy_file(of, desc) != objsize)
  727.                     {
  728.                         cfclose(of);
  729.                         cfprintf("cfar: ERROR copying %s\n", objname);
  730.                         break;
  731.                     }
  732.                     cfclose(of);
  733.                 }
  734.                 else
  735.                 {
  736.                     cfprintf("cfar: ERROR can't make chunk for %s\n", objname);
  737.                     break;
  738.                 }
  739.             }
  740. #else /* the hard fast way, may use a LOT of memory */
  741.             {
  742.             Item space;
  743.             char *loc;
  744.                 if(cfgetspace(lib, objsize, &space) != NULL)
  745.                 {/* ensure that there is enough space in the localizer bufs */
  746.                 long curbufs, objbufs;
  747.                     objbufs = (objsize / 1024)+1;
  748.                     curbufs = cfcurbufs();
  749.                     if(objbufs > curbufs)
  750.                     {
  751.                         cfmodbufs((objbufs-curbufs)+16);
  752.                         objbufs = cfcurbufs();
  753.                     }
  754.                     if((loc = cflocalize(lib, &space)) != NULL) {
  755.                         cfseek(desc, objoffset, S_SET);
  756.                         cfread(desc, loc, objsize);
  757.                         cfrelease(loc, R_DIRTY);
  758.                         cfinsert(lib, objname, objnamlen-1, &space);
  759.                     } else {
  760.                         cfretspace(lib, &space);
  761.                         cfprintf("cfar: ERROR can't localize space for %s\n", objname);
  762.                         break;
  763.                     }
  764.                 }
  765.                 else
  766.                 {
  767.                     cfprintf("cfar: ERROR can't allocate space for %s\n", objname);
  768.                     break;
  769.                 }
  770.             }
  771. #endif
  772.             /* Store the quick access package of symbols */
  773.             objname[objnamlen-2] = 'x';
  774.             sympack[symsize] = 0;
  775.             cfput(lib, objname, objnamlen-1, sympack, symsize+1, NULL); 
  776.  
  777.             /* Store the backlink to the origin, time + origin serial number */
  778.             objname[objnamlen-2] = 't';
  779.             cfinsert(lib, objname, objnamlen-1, &cur_org);
  780.  
  781.             /* Store the path, indexed both ways */
  782.             cfinsert(ipaths, curobj, curobjlen, &objval);
  783.             cfput(qipaths, &objval, 8, curobj, curobjlen+1, NULL);
  784.  
  785.             /* Store the symbols, symname is the key, objval is the item */
  786.             /* Pass 2 over the symbols */ 
  787.             for(j = 0; j < numsyms; ++j)
  788.             {/* The global symbols for each .o file have been saved
  789.                     in 'scratch', keyed by (objnum<<18+symnum) */
  790.             Item symptr;
  791.             long key = (objnum<<18)+j;
  792.                 if(cffind(scratch, &key, 4, &symptr) == FOUND)
  793.                 {
  794.                 char *cp;
  795.                     if((cp = cflocalize(scratch, &symptr)) != NULL) {
  796.                         cfinsert_dupnum(msyms, cp, strlen(cp), &objval, NULL);
  797.                         cfrelease(cp, R_CLEAN);
  798.                     } else {
  799.                         cfprintf("cfar: ERROR can't localize space for symbol %d\n", j);
  800.                         break;
  801.                     }
  802.                 }
  803.             }
  804.         }/* END: for(numobjs) */
  805.         cfclose(scratch);
  806.         cfclose(desc);
  807.     }/* END: if(desc) */
  808.     else cfprintf("cfar: can't open file %s, CONTINUING\n", path);
  809. }
  810. static void
  811. proc_objfile(char *path)
  812. {
  813.     if(issymbol && (act == arCHECK))
  814.     {
  815.         objof(path);
  816.         return;
  817.     }
  818.     if(act & arEXTRACT)
  819.         extract_file(path);
  820.     if(act & arDELETE)
  821.         delete_file(path, 0);
  822.     if(act & (arADD|arREPLACE|arCHECK|arUPDATE))
  823.         insert_file(path);
  824. }
  825. static void
  826. print_map(char *arch)
  827. {
  828. char path[256];
  829. void *dirh;
  830. CFDIRENT *d;
  831. int i, j;
  832.  
  833.     cfprintf("MAP of %s\n", arch);
  834.     if(map_entries) {
  835.         cfprintentries(arch);
  836.         cfsprintf(path, "%s/ipaths", arch);
  837.         cfprintentries(path);
  838.         cfsprintf(path, "%s/qipaths", arch);
  839.         cfprintentries(path);
  840.         cfsprintf(path, "%s/origins", arch);
  841.         cfprintentries(path);
  842.         cfsprintf(path, "%s/qorigins", arch);
  843.         cfprintentries(path);
  844.         cfsprintf(path, "%s/msyms", arch);
  845.         cfprintentries(path);
  846.     }
  847.     /* Print a list of origins */
  848.     cfprintf("\n-------- OUTSIDE ORIGINS ----------\n\n");
  849.     cfsprintf(path, "%s/origins", arch);
  850.     if((origins = cfopen(path, F_STAT, NULL)) != NULL)
  851.     {
  852.     Item orgnum;
  853.         if(cfhead(origins, &orgnum) == OK)
  854.         {
  855.             do {
  856.                 memclr(path, 255);
  857.                 cfkey(origins, path, 255);
  858.                 cfprintf("oid:%u\t%s\n", orgnum.a0, path);            
  859.             } while(cfnext(origins, &orgnum) == OK);
  860.         }    
  861.         cfclose(origins);
  862.     }
  863.     /* Print the various libraries and entries */
  864.     cfprintf("\n-------- LIBRARIES ----------\n\n");
  865.  
  866.     get_libtypes(arch);
  867.     for(i = 0; i < MAXLIBTYPE; ++i)
  868.     {
  869.         if(!ltypes[i])
  870.             continue;
  871.         cfsprintf(path, "%s/ltype%d", arch, i);
  872.         cfprintf("\nLibrary type %d\n", i);
  873.         get_libnums(path);
  874.         if(map_entries) {
  875.             cfprintf("------------ RAW ENTRIES -----------\n");
  876.             cfprintentries(path);
  877.         }
  878.         for(j = 0; j < 4096; ++j)
  879.         {
  880.         void *clib;
  881.             if(!lnums[j])
  882.                 continue;
  883.             cfsprintf(path, "%s/ltype%d/lib%d", arch, i, j);
  884.             if((clib = cfopen(path, F_STAT, NULL)) != NULL) {
  885.                 if(verbose)
  886.                     cfprintf("------- lib%d  %d bytes -------\n",
  887.                         j, cfbytesused(clib));
  888.                 else
  889.                     cfprintf("------- lib%d --------\n", j);
  890.                 cfhead(clib, NULL);
  891.                 do {
  892.                 char key[256];
  893.                 int keylen;
  894.                     memclr(key,256);
  895.                     cfkey(clib, key, 255);
  896.                     keylen = strlen(key);
  897.                     if(key[keylen-1] == 'o') {
  898.                         if(verbose) {
  899.                         int dlen;
  900.                         OrgItem oi;
  901.                             cfdatalen(clib, &dlen);
  902.                             key[keylen-1] = 't';
  903.                             cffind(clib, key, keylen, &oi);
  904.                             key[keylen-1] = 'o';
  905.                             cfprintf("    %s  bytes:%u oid:%u %s", 
  906.                                 key, dlen, oi.sn, ctime(&oi.filetime));
  907.                         }
  908.                         else
  909.                             cfprintf("     %s\n", key);
  910.                         if(verbose) {
  911.                         Item pakval;
  912.                         char *cp, *sp;
  913.                             key[keylen-1] = 'x';
  914.                             cfmark(clib);
  915.                             cffind(clib, key, keylen, &pakval);
  916.                             cp = cflocalize(clib, &pakval);
  917.                             for(sp=cp; *sp; sp += strlen(sp)+1)
  918.                             {
  919.                                 cfprintf("        %s\n", sp);
  920.                             }
  921.                             cfrelease(cp, R_CLEAN);
  922.                             cffind_mark(clib, NULL);
  923.                         }
  924.                     }
  925.                 } while (cfnext(clib, NULL) == OK);
  926.                 if(map_entries) {
  927.                     cfprintf("------------ RAW ENTRIES -----------\n");
  928.                     cfprintentries(clib);
  929.                 }
  930.                 cfclose(clib);
  931.             }
  932.         }
  933.     }
  934.     /* Print the list of stored files */
  935.     cfprintf("\n---------- STORED FILES ----------\n\n");
  936.     cfsprintf(path, "%s/fipaths", arch);
  937.     if((fipaths = cfopen(path, F_STAT, NULL)) != NULL)
  938.     {
  939.     OrgItem oi;
  940.         if(cfhead(fipaths, &oi) == OK)
  941.         {
  942.             do {
  943.                 memclr(path, 255);
  944.                 cfkey(fipaths, path, 255);
  945.                 cfprintf("%s\toid:%u  %s",
  946.                     path, oi.sn, ctime(&oi.filetime));
  947.             } while(cfnext(fipaths, &oi) == OK);
  948.         }
  949.         if(map_entries) {
  950.             cfprintf("------------ RAW ENTRIES -----------\n");
  951.             cfprintentries(fipaths);
  952.         }
  953.         cfclose(fipaths);
  954.     }
  955.     if(map_bitmaps) {
  956.         cfprintf("\n------------ BITMAPS ---------------\n");
  957.         cfprintbitmaps(arch);
  958.     }
  959. }
  960. static void
  961. Usage()
  962. {
  963. cfprintf("\
  964. Usage: cfar [-acdflmrstvxCFMNS] cfpath [file...]\n\
  965.     Switch -- Meaning\n\
  966.     a         Add file, do not overwrite\n\
  967.     c         Check input files against library for clashes\n\
  968.     d         Delete file\n\
  969.     f         Freshen the archive (replace outdated files)\n\
  970.     l#        Place file in libnum #, max:4095\n\
  971.     m         Print archive map to stdout\n\
  972.     r         Replace/Add file\n\
  973.     s         'file' is a symbol name not a file name (for extract/delete)\n\
  974.     t#        Set libtype # 0=module, 1=class, 2=subsystem, max:15\n\
  975.     v         Verbose\n\
  976.     x         Extract file\n\
  977.     M         Print to stdout, commands which would recreate the archive\n\
  978.     S         Shrink archive\n\
  979.     F         File mode, symbols not saved\n\
  980.     C         If File mode, put file in a chunk\n\
  981.     N         If File mode, give input file a new name (last part of cfpath)\n\
  982. ");
  983. }
  984. static int
  985. get_nameparts(char *name)
  986. {
  987. int namlen = strlen(name);
  988. int i,j;
  989.  
  990.     basefile[0] = 0;
  991.     midpath[0] = 0;
  992.     innerpath[0] = 0;
  993.     midpart = 0;
  994.     if((lastpart = strrchr(name, '/')) != NULL)
  995.         ++lastpart;
  996.     if(newname && !lastpart)
  997.     {
  998.         cfprintf("cfar: new filename enabled but not supplied\n");
  999.         Usage();
  1000.         return 1;
  1001.     }
  1002.     for(i = namlen-1; i >= 0; --i)
  1003.     {
  1004.         if(        name[i] == 'f'
  1005.             &&    name[i-1] == 'f'
  1006.             &&    name[i-2] == 'c'
  1007.             &&    name[i-3] == '.')
  1008.         {
  1009.             _strncpy(basefile, name, i+1);
  1010.  
  1011.             if(&name[i] > lastpart)
  1012.             {/* basefile is all there is */
  1013.                 lastpart = NULL;
  1014.             }
  1015.             else if(&name[i] != lastpart-2)
  1016.             {/* there is more than just a root directory mentioned */
  1017.                 midpart = &name[i]+2;
  1018.                 _strncpy(midpath, midpart, (int)(lastpart-midpart-1));
  1019.             }
  1020.             j = 0;
  1021.             if(midpart)
  1022.             {
  1023.                 innerpath[0] = '/';
  1024.                 j = _strcpy(&innerpath[1], midpath);
  1025.                 ++j;
  1026.             }
  1027.             if(lastpart && !newname)
  1028.             {
  1029.                 innerpath[j++] = '/';
  1030.                 strcpy(&innerpath[j], lastpart);
  1031.             }
  1032.         }
  1033.     }
  1034.     return 0;
  1035. }
  1036. static void
  1037. shrink_archive(char *name)
  1038. {
  1039. void *x;
  1040. void *y;
  1041.  
  1042.     cfprintf("cfar: shrink_archive %s\n", name);
  1043.     if(verbose)
  1044.         cfprintf("cfar: copy in\n");
  1045.     x = cfcopy("MEMORY/shrink", name);
  1046.     if(verbose)
  1047.         cfprintf("cfar: copy out\n");
  1048.     y = cfcopy(name, x);
  1049.     if(verbose)
  1050.         cfprintf("cfar: clean up\n");
  1051.     cfunlink(x, NULL);
  1052.     cfclose(y);
  1053. }
  1054. static void
  1055. stat_file(OrgItem *op, char *name, long namlen, long typ, long num, 
  1056.         char *arch, void *scratch)
  1057. {
  1058. Item orgtag;
  1059. char orgpath[1024];
  1060. char *in;
  1061. long orglen;
  1062. long sn = op->sn;
  1063.  
  1064.     cfget(qorigins, &sn, 4, &orgpath, 1023);
  1065.     orglen = strlen(orgpath);
  1066.  
  1067.     if(typ >= 0 && orgpath[orglen-1] == 'a' && orgpath[orglen-2] == '.')
  1068.     {/* This origin is a library */
  1069.         /* Mark this origin or return if it has been marked */
  1070.         orgtag.a2.size = op->sn;
  1071.         orgtag.a0 = typ<<4 + num;
  1072.         orgtag.a2.type = STO_VALUE;
  1073.         /* libraries are handled differently */
  1074.         if(cfinsert(scratch, &orgtag, 8, &orgtag) != OK)
  1075.             return;
  1076.     }
  1077.     else if(typ >= 0)
  1078.     {/* This origin is a directory, with an embedded file */
  1079.         orgpath[orglen] = '/';
  1080.         ++orglen;
  1081.         orglen += _strcpy(&orgpath[orglen], name);
  1082.     }
  1083.     else
  1084.     {/* this origin is for a filemode entry */
  1085.         in = strrchr(name, '/');
  1086.         if(name[namlen-1] == '?')
  1087.             typ = -2;        /* the entry was made with newname */
  1088.         else
  1089.         {
  1090.             orglen += _strcpy(&orgpath[orglen], in);
  1091.             orgpath[orglen-1] = 0;    /* strip tag */
  1092.         }
  1093.     }
  1094.     /* The origin has not been examined, do it */
  1095.     if(freshen)
  1096.     {
  1097.     CFSTAT s;
  1098.         if(cfstat(orgpath, &s) == OK)
  1099.         {
  1100.             if(s.st_mtime > op->filetime)
  1101.             { /* REFRESH THIS ITEM */
  1102.                 ++orglen;
  1103.                 if(typ < 0)
  1104.                 {
  1105.                     --namlen;    /* clip tag */
  1106.                     cfpush_data(scratch, name, namlen);
  1107.                     cfpush_value(scratch, &namlen);
  1108.                     ++namlen;
  1109.                 }
  1110.                 cfpush_data(scratch, orgpath, orglen);
  1111.                 cfpush_value(scratch, &orglen);
  1112.                 cfpush_value(scratch, &typ);
  1113.                 cfpush_value(scratch, &num);
  1114.             }
  1115.         }
  1116.         else
  1117.             cfprintf("cannot stat %s, CONTINUING\n", orgpath);
  1118.     }
  1119.     if(batfile)
  1120.     {
  1121.         if(typ < 0)
  1122.         {/* filemode entry */
  1123.         int c = (num == 1) ? 'C' : ' ';    /* chunk flag */
  1124.             if(typ == -2)
  1125.             {/* rename needed */
  1126.                 name[namlen-1] = 0;    /* clip off the tag */
  1127.                 cfprintf("cfar -FNr%c %s%s %s\n", c, arch, name, orgpath);
  1128.             }
  1129.             else
  1130.             {/* no rename, clip off the last part of name */
  1131.                 *in = 0;
  1132.                 cfprintf("cfar -Fr%c %s%s %s\n", c, arch, name, orgpath);
  1133.                 *in = '/';
  1134.             }
  1135.         }
  1136.         else
  1137.         {/* object file entry */
  1138.             cfprintf("cfar -rt%dl%d %s %s\n", typ, num, arch, orgpath);
  1139.         }
  1140.     }
  1141. }
  1142. static void
  1143. scan_archive(char *archname, void *scratch)
  1144. {
  1145. int i;
  1146. OrgItem oi;
  1147.  
  1148.     /* Check stored object files */
  1149.     get_libtypes(archname);
  1150.     for(i = 0; i < MAXLIBTYPE; ++i)
  1151.     {
  1152.     char path[256];
  1153.     int j;
  1154.         if(!ltypes[i])
  1155.             continue;
  1156.         cfsprintf(path, "%s/ltype%d", archname, i);
  1157.         get_libnums(path);
  1158.         for(j = 0; j < 4096; ++j)
  1159.         {
  1160.         void *clib;
  1161.             if(!lnums[j])
  1162.                 continue;
  1163.             cfsprintf(path, "%s/ltype%d/lib%d", archname, i, j);
  1164.             if((clib = cfopen(path, F_RDONLY, NULL)) != NULL) {
  1165.                 cfhead(clib, &oi);
  1166.                 do {
  1167.                 char key[256];
  1168.                 int keylen;
  1169.                     memclr(key,256);
  1170.                     cfkey(clib, key, 255);
  1171.                     keylen = strlen(key);
  1172.                     if(key[keylen-1] == 't') {
  1173.                         key[keylen-1] = 'o';
  1174.                         stat_file(&oi, key, keylen, i, j, archname, scratch);
  1175.                     }
  1176.                 } while (cfnext(clib, &oi) == OK);
  1177.                 cfclose(clib);
  1178.             }
  1179.         }
  1180.     }
  1181.     /* Check stored FILEMODE files */
  1182.     cfhead(fipaths, &oi);
  1183.     do {
  1184.     char key[1024];
  1185.     int keylen;
  1186.     char tag;
  1187.     int ischunk;
  1188.     CFSTAT sbuf;
  1189.         memclr(key,1024);
  1190.         cfkey(fipaths, key, 1023);
  1191.         keylen = strlen(key);
  1192.         tag = key[keylen-1];
  1193.         key[keylen-1] = 0;
  1194.         if(cfsubstat(archive, &key[1], &sbuf) != OK)
  1195.         {
  1196.             cfprintf("cfar: can't stat internal file %s\n", key);
  1197.             continue;
  1198.         }
  1199.         if(sbuf.st_mode & M_CHUNK)
  1200.             ischunk = 1;
  1201.         else
  1202.             ischunk = 0;
  1203.         key[keylen-1] = tag;
  1204.         stat_file(&oi, key, keylen, -1, ischunk, archname, scratch);
  1205.     } while (cfnext(fipaths, &oi) == OK);
  1206. }
  1207. static void
  1208. setup_version(int flag, char *archname)
  1209. {
  1210. KeyItem snval = 0;
  1211.     cfinsert(archive, "ArVer", 5, &prgversion);
  1212.     cfinsert(archive, "SN0", 3, &snval);
  1213.     cfinsert(archive, "SN1", 3, &snval);
  1214.     cfinsert(archive, "SN2", 3, &snval);
  1215.     if(flag)
  1216.          cfprintf("cfar: add archive property to %s\n", archname);
  1217.     else cfprintf("cfar: create archive %s\n", archname);
  1218. }
  1219. static void
  1220. lose_backslashes(char *cp)
  1221. {
  1222.     while(*cp) {
  1223.         if(*cp == '\\')
  1224.             *cp = '/';
  1225.         ++cp;
  1226.     }
  1227. }
  1228. #ifdef SKELETON
  1229. int cfar(int argc, char **argv)
  1230. #else
  1231. int main(int argc, char **argv)
  1232. #endif
  1233. {
  1234. int err = 0;
  1235. int i, j;
  1236. long curbufs, newbufs;
  1237.  
  1238. #ifndef SKELETON
  1239.     cfinit("cfar", 400, NULL);
  1240.     if((err = oxlink_init(cf_find_file(argv[0], 0))) == 0)
  1241.     {
  1242. #endif
  1243.       /* Get the switches */
  1244.       for(i = 1; i < argc; ++i)
  1245.       {
  1246.       int trimsize = 1;
  1247.         lose_backslashes(argv[i]);
  1248.         if(argv[i][0] == '-')
  1249.         {
  1250.           for(j=1; argv[i][j]; ++j)
  1251.           {
  1252.             switch(argv[i][j])
  1253.             {
  1254.               case 'f':
  1255.                 freshen = 1;
  1256.                 break;
  1257.               case 'r':
  1258.                 act = arREPLACE;
  1259.                 replace = 1;
  1260.                 break;
  1261.               case 'a':
  1262.                 act = arADD;
  1263.                 add = 1;
  1264.                 replace = 0;
  1265.                 break;
  1266.               case 'x':
  1267.                 act |= arEXTRACT;
  1268.                 break;
  1269.               case 'd':
  1270.                 act |= arDELETE;
  1271.                 break;
  1272.               case 'v':
  1273.                 verbose = 1;
  1274.                 break;
  1275.               case 'c':
  1276.                 act = arCHECK;
  1277.                 add = 0;
  1278.                 replace = 0;
  1279.                 break;
  1280.               case 'S':
  1281.                 shrink = 1;
  1282.                 break;
  1283.               case 'l':
  1284.                 libnum = atol(&argv[i][j+1]);
  1285.                 if(libnum < 0 || libnum > 4095)
  1286.                     err = 1;
  1287.                 break;
  1288.               case 't':
  1289.                 libtype = atol(&argv[i][j+1]);
  1290.                 if(libtype < 0 || libtype >= MAXLIBTYPE)
  1291.                     err = 1;
  1292.                 break;
  1293.               case 'm':
  1294.                 map = 1;
  1295.                 break;
  1296.               case 's':
  1297.                 issymbol = 1;
  1298.                 break;
  1299.               case 'B':
  1300.                 map_bitmaps = 1;
  1301.                 break;
  1302.               case 'C':
  1303.                 chunk = 1;
  1304.                 break;
  1305.               case 'F':
  1306.                 filemode = 1;
  1307.                 break;
  1308.               case 'N':
  1309.                 newname = 1;
  1310.                 break;
  1311.               case 'E':
  1312.                 map_entries = 1;
  1313.                 break;
  1314.               case 'M':
  1315.                 batfile = 1;
  1316.                 break;
  1317.               case '?':
  1318.                 err = 1;
  1319.                 break;
  1320.               default:
  1321.                 break;
  1322.             }
  1323.           }/* END: switch */
  1324. trim:
  1325.           /* Trim switch */
  1326.           for(j = i; j < argc-trimsize; ++j)
  1327.             argv[j] = argv[j+trimsize];
  1328.           argc -= trimsize;
  1329.           --i;
  1330.         }/* END: if('-') */
  1331.       }/* END: for(argc) (get switches) */
  1332.       if(verbose) {
  1333.         cfprintf("cff archiver Version:%u Copyright 1993, 1995 Norman D. Culver\n",
  1334.                 prgversion.a0);
  1335.       }
  1336.       if(err) Usage();
  1337.  
  1338.       if(argc > 1)
  1339.           err = get_nameparts(argv[1]);
  1340.  
  1341.       /* Get the archive */
  1342.       if(!err && (     (map|shrink|freshen|batfile)
  1343.                     || (act && argc > 2)
  1344.                     || (filemode && (act & (arDELETE|arEXTRACT)))
  1345.                  )
  1346.         )
  1347.       {
  1348.       int mode = F_RDWR;
  1349.       int new = 0;
  1350.  
  1351.         if(act & (arADD|arREPLACE))
  1352.             mode |= F_CREAT;
  1353.  
  1354.         curbufs = cfcurbufs(); /* current size of localizer space */
  1355.  
  1356. #ifdef SKELETON
  1357.         oxlink_close_libs();
  1358. #endif
  1359.         if((archive = cfopen(basefile, mode, NULL)) != NULL)
  1360.         {
  1361.           if(!(cfobtype(archive) & OB_XFILE))
  1362.           {
  1363. #if 0
  1364.             cfsetverylazy(archive);
  1365. #endif
  1366.             if(cfisnew(archive))
  1367.             {/* new file, set up version and serial numbers */
  1368.                 setup_version(0, basefile);
  1369.                 new = 1;
  1370.             }
  1371.             else
  1372.             {
  1373.                 if(cffind(archive, "ArVer", 5, &arversion) < FOUND) 
  1374.                 {/* old .cff file without archive property, enable it */
  1375.                     setup_version(1, basefile);
  1376.                     new = 1;
  1377.                 }
  1378.             }
  1379.             if(cffind(archive, "ArVer", 5, &arversion) >= FOUND)
  1380.             {
  1381.               if(arversion.a0 <= prgversion.a0)
  1382.               {
  1383.                 ipaths = cfsubopen(archive,"ipaths",F_RDWR|F_CREAT|F_SORTED,NULL);
  1384.                 qipaths = cfsubopen(archive,"qipaths",F_RDWR|F_CREAT, NULL);
  1385.                 origins = cfsubopen(archive,"origins",F_RDWR|F_CREAT|F_SORTED|F_BIGDIR, NULL);
  1386.                 qorigins = cfsubopen(archive,"qorigins",F_RDWR|F_CREAT, NULL);
  1387.                 msyms = cfsubopen(archive,"msyms",F_RDWR|F_CREAT|F_SORTED|F_HUGEDIR,NULL);
  1388.                 fipaths = cfsubopen(archive,"fipaths",F_RDWR|F_CREAT|F_SORTED,NULL); 
  1389.  
  1390.                 if(!ipaths) {
  1391.                     cfprintf("cfar: can't open subdir `ipaths'\n");
  1392.                     goto xt;
  1393.                 }
  1394.                 if(!qipaths) {
  1395.                     cfprintf("cfar: can't open subdir `ipaths'\n");
  1396.                     goto xt;
  1397.                 }
  1398.                 if(!origins) {
  1399.                     cfprintf("cfar: can't open subdir `origins'\n");
  1400.                     goto xt;
  1401.                 }
  1402.                 if(!qorigins) {
  1403.                     cfprintf("cfar: can't open subdir `qorigins'\n");
  1404.                     goto xt;
  1405.                 }
  1406.                 if(!msyms) {
  1407.                     cfprintf("cfar: can't open subdir `msyms'\n");
  1408.                     goto xt;
  1409.                 }
  1410.                 if(!fipaths) {
  1411.                     cfprintf("cfar: can't open subdir `fipaths'\n");
  1412.                     goto xt;
  1413.                 }
  1414. #if 0
  1415.                 cfsetverylazy(msyms);
  1416.                 cfsetverylazy(ipaths);
  1417.                 cfsetverylazy(qipaths);
  1418.                 cfsetverylazy(origins);
  1419.                 cfsetverylazy(qorigins);
  1420.                 cfsetverylazy(fipaths);
  1421. #endif
  1422.                 if(filemode)
  1423.                 {/* PROCESS FILES STORED IN FILEMODE */
  1424.  
  1425.                     if(act & (arEXTRACT|arDELETE))
  1426.                     {
  1427.                         if(act & arEXTRACT)
  1428.                             out_entry();
  1429.                         else
  1430.                             del_entry();
  1431.                     }
  1432.                     else if(add || chunk || newname || replace)
  1433.                     {
  1434.                         subdir = open_middle(archive);
  1435.                         for(i = 2; i < argc; ++i)
  1436.                         {
  1437.                             lose_backslashes(argv[i]);
  1438.                             strlwr(argv[i]);
  1439.                             cur_orgtype = cfpathtrn(argv[i], &cur_orgpath);
  1440.                             proc_filemode(argv[i]);
  1441.                             free(cur_orgpath);
  1442.                         }
  1443.                         if(subdir)
  1444.                             cfclose(subdir);
  1445.                     }
  1446.                     else
  1447.                     {
  1448.                         cfprintf("cfar: incorrect filemode spec\n");
  1449.                     }
  1450.                 }
  1451.                 else if((argc < 3) && (freshen|batfile) && (!new))
  1452.                 {/* FRESHEN FILES IN ARCHIVE, OR PRINT BATCHFILE */
  1453.                 void *scratch = make_scratch();
  1454.  
  1455.                   /* check for files to freshen, print batfile if requested */
  1456.                   scan_archive(basefile, scratch);            
  1457.                   act = arUPDATE;
  1458.                   replace = 1;
  1459.  
  1460.                   /* files to freshen will be on the stack */
  1461.                   while(cfstackdepth(scratch) > 0)
  1462.                   {
  1463.                   long filelen;
  1464.                     cfpop_value(scratch, &libnum);
  1465.                     cfpop_value(scratch, &libtype);
  1466.                     cfpop_value(scratch, &filelen);
  1467.                     cur_orgpath = malloc(filelen);
  1468.                     cfpop_data(scratch, cur_orgpath, filelen);
  1469.  
  1470.                     if(libtype < 0)
  1471.                     {/* Freshen a filemode file */
  1472.                     long namlen, x;
  1473.                     char *cur_name;
  1474.                         cfpop_value(scratch, &namlen);
  1475.                         cur_name = calloc(1, namlen+strlen(basefile)+2);
  1476.                         x = _strcpy(cur_name, basefile);
  1477.                         cfpop_data(scratch, &cur_name[x], namlen);
  1478.                         chunk = (libnum == 1) ? 1 : 0;
  1479.                         newname = (libtype == -2) ? 1 : 0;
  1480.                         if(!newname) cur_name[x] = 0;
  1481.  
  1482.                         get_nameparts(cur_name);
  1483.                         subdir = open_middle(archive);
  1484.  
  1485.                         proc_filemode(cur_orgpath);
  1486.                         if(subdir)
  1487.                             cfclose(subdir);
  1488.                         free(cur_name);
  1489.                     }
  1490.                     else if(open_curlib())
  1491.                     {/* Freshen an object file */
  1492.                         proc_objfile(cur_orgpath);
  1493.                     }
  1494.                     free(cur_orgpath);
  1495.                   }/* END: freshen files on stack */
  1496.                   cfclose(scratch);
  1497.                 }
  1498.                 else if(argc > 2)
  1499.                 {/* PROCESS OBJECT FILES STORED WITH SYMBOL TABLES */
  1500.                   if(open_curlib())
  1501.                   {/* Process the input files */
  1502.                       for(i = 2; i < argc; ++i)
  1503.                       {
  1504.                         if(!issymbol)
  1505.                         {
  1506.                           lose_backslashes(argv[i]);
  1507.                           strlwr(argv[i]);
  1508.                         }
  1509.                         cur_orgtype = cfpathtrn(argv[i], &cur_orgpath);
  1510.                         proc_objfile(argv[i]);
  1511.                         free(cur_orgpath);
  1512.                       }        
  1513.                     }
  1514.                 }
  1515.                 cfclose(lib);
  1516.                 cfclose(plib);
  1517.                 cfclose(msyms);
  1518.                 cfclose(ipaths);
  1519.                 cfclose(qipaths);
  1520.                 cfclose(origins);
  1521.                 cfclose(qorigins);
  1522.                 cfclose(fipaths);
  1523.                 cfclose(archive);
  1524.  
  1525.                 if(shrink) shrink_archive(basefile);
  1526.                 if(map) print_map(basefile);
  1527.  
  1528.                 cfmodbufs(curbufs-cfcurbufs()); /* reset localizer space */
  1529.  
  1530.               } else cfprintf("cfar: a version %u archive cannot be processed by a version %u program\n", arversion.a0, prgversion.a0);
  1531.             } else cfprintf("cfar: %s is not an archive\n", basefile);
  1532.           } else cfprintf("cfar: %s is not a cff database\n", basefile);
  1533.         } else cfprintf("cfar: can't open archive %s\n", basefile);
  1534.       } else {cfprintf("cfar: insufficient args\n"); Usage();}
  1535. #ifndef SKELETON
  1536.     } else cfprintf("cfar: cannot find executable %s\n", argv[0]);
  1537. xt:
  1538.     cfexit();
  1539.     return 0;
  1540. #else
  1541. xt:
  1542.     return 0;
  1543. #endif
  1544. }
  1545.