home *** CD-ROM | disk | FTP | other *** search
- /* iffar - IFF CAT archiver replace functions
-
- By Karl Lehenbauer, version 1.2, release date 5/9/88.
- This code is released to the public domain.
- See the README file for more information.
-
- */
-
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <stdio.h>
- #include <fcntl.h>
- #include "assert.h"
- #include "iff.h"
-
- /* if a "insert before" or "insert after" position modifier is
- * not specified, the program attepts to replace entries at the
- * same place as where they occurred in the original archive.
- * if the entry could not be found, the file is appended to the
- * end of the archive. hence, when a position modifier is not
- * specified and a file being replaced did not exist in the archive,
- * the file needs to be appended onto the
- * end - we do this by nulling out the argument if and only if
- * neiter insert_before or insert_after is set, else a bug would
- * be introduced as when they are selected the delete and insert
- * portions are asynchronous and either could occur before the
- * other, hence one guy nulling it makes the other guy not see
- * it. it's not a problem for the specified case, though, 'cuz
- * it's only looked at in this one place and at the end,
- * where, again only when neither insert_before and insert_after
- * are checked, we run through the arguments and if the first byte
- * of any entry is not null, this implies that entry was not in
- * the original archive, hence not replaced in-place, so we tack
- * it on to the end.
- * if insert_before or insert_after is selected, archive entries
- * are deleted on the fly as they are read from the original
- * archive by being skipped and, when the insert conditions are
- * met, all of the names in the list of names are appended, thus,
- * we don't have to worry about it
- *
- * note that it's kind of broken for insert_after and insert_before
- * when the after or before name isn't found the old entries will
- * be deleted but the new ones won't be inserted, heck, the program
- * may even blow up
- */
-
- extern ULONG nextchunk();
-
- extern int insert_before;
- extern int insert_after;
- extern char *location_modifier_name;
-
- int replace_entries(archive_name,fnames,nfiles)
- char *archive_name;
- char *fnames[];
- int nfiles;
- {
- int old_archive_fd, new_archive_fd;
- ULONG cat_type, chunkid, innerchunkid, subtype;
- long chunksize, innerchunksize, filesize;
- char textbuf[128], old_archive_name[128];
- int i, replace_file, file_bytes;
- int entryindex, insert_next_time = 0;
- int modifier_matches, did_insert = 0;
-
- extern int verbose;
-
- /* rename the archive to its old name concatenated with ".old"
- */
- sprintf(old_archive_name,"%s.old",archive_name);
- unlink(old_archive_name);
- rename(archive_name,old_archive_name);
-
- if ((old_archive_fd = OpenCAT(old_archive_name,&cat_type,&filesize)) == -1)
- {
- fprintf(stderr,"Can't open archive '%s'\n",old_archive_name);
- return(0);
- }
-
- if ((new_archive_fd = create_archive(archive_name,ID_MISC)) < 0)
- return(0);
-
- while ((chunkid = nextCATchunk(old_archive_fd,&subtype,&textbuf[0],&chunksize,&filesize)) != 0L)
- {
- /* if the chunk type isn't FORM, CAT or LIST, copy it across
- * without looking at it */
- if (chunkid != ID_FORM && chunkid != ID_CAT && chunkid != ID_LIST)
- {
- if (!WriteChunkHeader(new_archive_fd,chunkid,chunksize))
- return(0);
- copychunkbytes(old_archive_fd,new_archive_fd,chunksize,&filesize);
- break;
- }
-
- /* we shouldn't ever not get a filename back here at the top level
- * that is, we saw a CAT, LIST or FORM, we expect an IFAR chunk*/
- if (textbuf[0] == '\0')
- {
- fprintf(stderr,"FORM, CAT or LIST in archive doesn't have an IFAR chunk, abandoning\n");
- return(0);
- }
-
- if (insert_before || insert_after)
- modifier_matches = !strnicmp(location_modifier_name,textbuf,128);
-
- /* if insert_before option has been selected and the chunk ID
- * we just read from the old archive matches global
- * location_modifier_name, append all the named files to the
- * new archive. also do this if it's insert_after and
- * we matched the name last time */
- if ((modifier_matches && insert_before) || insert_next_time)
- {
- insert_next_time = 0;
-
- for (entryindex = 0; entryindex < nfiles; entryindex++)
- {
- if (verbose)
- {
- if (insert_before)
- fprintf(stderr,"inserting ");
- else
- fprintf(stderr,"appending ");
- fprintf(stderr,"%s\n",fnames[entryindex]);
- }
- append_file_to_archive(fnames[entryindex],new_archive_fd);
- }
-
- did_insert = 1;
- }
-
- /* if this is a match and insert_after is selected, set
- * insert_next_time so we'll know to do the appends after the
- * next entry */
- if (modifier_matches && insert_after)
- insert_next_time = 1;
-
- /* search to see if this chunk's name is one specified in fnames,
- * an array of pointer to char strings */
- replace_file = 0;
- for (i = 0; i < nfiles; i++)
- {
- if (!strnicmp(basename(fnames[i]),textbuf,128))
- {
- /* it is */
- replace_file = 1;
- break;
- }
- }
-
- /* if we want to replace it, */
- if (replace_file)
- {
- /* copy the file being replaced into the archive if
- * neither insert_before or insert_after are set.
- * if they are set, this will be done elsewhere */
- if (!insert_before && !insert_after)
- {
- if (verbose)
- fprintf(stderr,"replacing %s\n",textbuf);
- append_file_to_archive(fnames[i],new_archive_fd);
- /* null out the first byte of the name so we won't
- * append it again at the end */
- *fnames[i] = '\0';
- }
- else if (verbose)
- fprintf(stderr,"removing old %s\n",textbuf);
-
- /* in either case (replace selected, we don't care if
- * before or after are chosen), skip the chunk in the
- * old archive */
- if (!skipchunk(old_archive_fd,chunksize,&filesize))
- {
- fprintf(stderr,"replace: skipchunk failed\n");
- return(0);
- }
- }
- else /* not on the replacement list, we copy it */
- {
- if (!WriteCATentry(new_archive_fd,textbuf,chunkid,subtype,chunksize))
- return(0);
-
- copychunkbytes(old_archive_fd,new_archive_fd,chunksize,&filesize);
- }
- }
-
- /* now if insert_before or insert_after were not set, for all entries
- * in the list that don't have a null byte for their first byte,
- * append them to the archive */
- if ((!insert_before && !insert_after) || !did_insert)
- {
- /* if we didn't do the insert, report that we're planning
- * to append. note that if insert_after and !insert_next_time
- * it means that they said append after the last one, so
- * don't mention it
- */
- if (insert_before || (insert_after && !insert_next_time))
- fprintf(stderr,"couldn't find entry %s that was specified as a position modifier\n, appending your entries\n",textbuf);
-
- for (i = 0; i < nfiles; i++)
- {
- if (*fnames[i] != '\0')
- {
- if (verbose)
- fprintf(stderr,"appending %s\n",fnames[i]);
- append_file_to_archive(fnames[i],new_archive_fd);
- }
- }
- }
-
- /* write the right length in for the header */
- rewrite_archive_header(new_archive_fd);
-
- /* close the old and new archive files and return success */
- close(old_archive_fd);
- close(new_archive_fd);
- return(1);
- }
-
- /* end of extract.c */
-
-