home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 138.lha / Iff_Archiver / replace.c < prev    next >
C/C++ Source or Header  |  1986-11-20  |  7KB  |  221 lines

  1. /* iffar - IFF CAT archiver replace functions
  2.  
  3.    By Karl Lehenbauer, version 1.2, release date 5/9/88.
  4.    This code is released to the public domain.
  5.    See the README file for more information.
  6.  
  7. */
  8.  
  9. #include <exec/types.h>
  10. #include <exec/memory.h>
  11. #include <stdio.h>
  12. #include <fcntl.h>
  13. #include "assert.h"
  14. #include "iff.h"
  15.  
  16. /* if a "insert before" or "insert after" position modifier is
  17.  * not specified, the program attepts to replace entries at the
  18.  * same place as where they occurred in the original archive.
  19.  * if the entry could not be found, the file is appended to the
  20.  * end of the archive.  hence, when a position modifier is not
  21.  * specified and a file being replaced did not exist in the archive,
  22.  * the file needs to be appended onto the
  23.  * end - we do this by nulling out the argument if and only if
  24.  * neiter insert_before or insert_after is set, else a bug would
  25.  * be introduced as when they are selected the delete and insert
  26.  * portions are asynchronous and either could occur before the
  27.  * other, hence one guy nulling it makes the other guy not see
  28.  * it.  it's not a problem for the specified case, though, 'cuz
  29.  * it's only looked at in this one place and at the end,
  30.  * where, again only when neither insert_before and insert_after
  31.  * are checked, we run through the arguments and if the first byte
  32.  * of any entry is not null, this implies that entry was not in
  33.  * the original archive, hence not replaced in-place, so we tack
  34.  * it on to the end.
  35.  * if insert_before or insert_after is selected, archive entries
  36.  * are deleted on the fly as they are read from the original
  37.  * archive by being skipped and, when the insert conditions are
  38.  * met, all of the names in the list of names are appended, thus, 
  39.  * we don't have to worry about it 
  40.  *
  41.  * note that it's kind of broken for insert_after and insert_before
  42.  * when the after or before name isn't found the old entries will
  43.  * be deleted but the new ones won't be inserted, heck, the program
  44.  * may even blow up
  45.  */
  46.  
  47. extern ULONG nextchunk();
  48.  
  49. extern int insert_before;
  50. extern int insert_after;
  51. extern char *location_modifier_name;
  52.  
  53. int replace_entries(archive_name,fnames,nfiles)
  54. char *archive_name;
  55. char *fnames[];
  56. int nfiles;
  57. {
  58.     int old_archive_fd, new_archive_fd;
  59.     ULONG cat_type, chunkid, innerchunkid, subtype;
  60.     long chunksize, innerchunksize, filesize;
  61.     char textbuf[128], old_archive_name[128];
  62.     int i, replace_file, file_bytes;
  63.     int entryindex, insert_next_time = 0;
  64.     int modifier_matches, did_insert = 0;
  65.  
  66.     extern int verbose;
  67.  
  68.     /* rename the archive to its old name concatenated with ".old"
  69.      */
  70.     sprintf(old_archive_name,"%s.old",archive_name);
  71.     unlink(old_archive_name);
  72.     rename(archive_name,old_archive_name);
  73.  
  74.     if ((old_archive_fd = OpenCAT(old_archive_name,&cat_type,&filesize)) == -1)
  75.     {
  76.         fprintf(stderr,"Can't open archive '%s'\n",old_archive_name);
  77.         return(0);
  78.     }
  79.  
  80.     if ((new_archive_fd = create_archive(archive_name,ID_MISC)) < 0)
  81.         return(0);
  82.  
  83.     while ((chunkid = nextCATchunk(old_archive_fd,&subtype,&textbuf[0],&chunksize,&filesize)) != 0L)
  84.     {
  85.         /* if the chunk type isn't FORM, CAT or LIST, copy it across 
  86.          * without looking at it */
  87.         if (chunkid != ID_FORM && chunkid != ID_CAT && chunkid != ID_LIST)
  88.         {
  89.              if (!WriteChunkHeader(new_archive_fd,chunkid,chunksize))
  90.                 return(0);
  91.             copychunkbytes(old_archive_fd,new_archive_fd,chunksize,&filesize);
  92.             break;
  93.         }
  94.  
  95.         /* we shouldn't ever not get a filename back here at the top level 
  96.          * that is, we saw a CAT, LIST or FORM, we expect a FNAM chunk*/
  97.          if (textbuf[0] == '\0')
  98.          {
  99.              fprintf(stderr,"FORM, CAT or LIST in archive doesn't have an FNAM chunk, abandoning\n");
  100.             return(0);
  101.         }
  102.  
  103.         if (insert_before || insert_after)
  104.             modifier_matches = !strnicmp(location_modifier_name,textbuf,128);
  105.  
  106.         /* if insert_before option has been selected and the chunk ID
  107.          * we just read from the old archive matches global 
  108.          * location_modifier_name, append all the named files to the
  109.          * new archive.  also do this if it's insert_after and
  110.          * we matched the name last time */
  111.         if ((modifier_matches && insert_before) || insert_next_time)
  112.         {
  113.             insert_next_time = 0;
  114.  
  115.             for (entryindex = 0; entryindex < nfiles; entryindex++)
  116.             {
  117.                 if (verbose)
  118.                 {
  119.                     if (insert_before)
  120.                         fprintf(stderr,"inserting ");
  121.                     else
  122.                         fprintf(stderr,"appending ");
  123.                     fprintf(stderr,"%s\n",fnames[entryindex]);
  124.                 }
  125.                 append_file_to_archive(fnames[entryindex],new_archive_fd);
  126.             }
  127.  
  128.             did_insert = 1;
  129.         }
  130.  
  131.         /* if this is a match and insert_after is selected, set 
  132.          * insert_next_time so we'll know to do the appends after the
  133.          * next entry */
  134.         if (modifier_matches && insert_after)
  135.             insert_next_time = 1;
  136.  
  137.         /* search to see if this chunk's name is one specified in fnames,
  138.          * an array of pointer to char strings */
  139.         replace_file = 0;
  140.         for (i = 0; i < nfiles; i++)
  141.         {
  142.             if (!strnicmp(basename(fnames[i]),textbuf,128))
  143.             {
  144.                 /* it is */
  145.                 replace_file = 1;
  146.                 break;
  147.             }
  148.         }
  149.  
  150.         /* if we want to replace it, */
  151.         if (replace_file)
  152.         {
  153.             /* copy the file being replaced into the archive if
  154.              * neither insert_before or insert_after are set.
  155.              * if they are set, this will be done elsewhere */
  156.             if (!insert_before && !insert_after)
  157.             {
  158.                 if (verbose)
  159.                     fprintf(stderr,"replacing %s\n",textbuf);
  160.                     append_file_to_archive(fnames[i],new_archive_fd);
  161.                     /* null out the first byte of the name so we won't
  162.                      * append it again at the end */
  163.                     *fnames[i] = '\0';
  164.             }
  165.             else if (verbose)
  166.                 fprintf(stderr,"removing old %s\n",textbuf);
  167.  
  168.             /* in either case (replace selected, we don't care if
  169.              * before or after are chosen), skip the chunk in the 
  170.              * old archive */
  171.             if (!skipchunk(old_archive_fd,chunksize,&filesize))
  172.             {
  173.                 fprintf(stderr,"replace: skipchunk failed\n");
  174.                 return(0);
  175.             }
  176.         }
  177.         else    /* not on the replacement list, we copy it */
  178.         {
  179.             if (!WriteCATentry(new_archive_fd,textbuf,chunkid,subtype,chunksize))
  180.                 return(0);
  181.  
  182.             copychunkbytes(old_archive_fd,new_archive_fd,chunksize,&filesize);
  183.         }
  184.     }
  185.  
  186.     /* now if insert_before or insert_after were not set, for all entries 
  187.      * in the list that don't have a null byte for their first byte,
  188.      * append them to the archive */
  189.     if ((!insert_before && !insert_after) || !did_insert)
  190.     {
  191.         /* if we didn't do the insert, report that we're planning
  192.          * to append.  note that if insert_after and !insert_next_time
  193.          * it means that they said append after the last one, so
  194.          * don't mention it
  195.          */
  196.         if (insert_before || (insert_after && !insert_next_time))
  197.             fprintf(stderr,"couldn't find entry %s that was specified as a position modifier\n, appending your entries\n",textbuf);
  198.  
  199.         for (i = 0; i < nfiles; i++)
  200.         {
  201.             if (*fnames[i] != '\0')
  202.             {
  203.                 if (verbose)
  204.                     fprintf(stderr,"appending %s\n",fnames[i]);
  205.                 append_file_to_archive(fnames[i],new_archive_fd);
  206.             }
  207.         }
  208.     }
  209.  
  210.     /* write the right length in for the header */
  211.     rewrite_archive_header(new_archive_fd);
  212.  
  213.     /* close the old and new archive files and return success */
  214.     close(old_archive_fd);
  215.     close(new_archive_fd);
  216.     return(1);
  217. }
  218.  
  219. /* end of extract.c */
  220.  
  221.