home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Fish 1
/
GoldFishApril1994_CD1.img
/
d1xx
/
d162
/
iffar
/
replace.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-10-02
|
7KB
|
221 lines
/* 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 a FNAM chunk*/
if (textbuf[0] == '\0')
{
fprintf(stderr,"FORM, CAT or LIST in archive doesn't have an FNAM 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 */