/* macbin.c - Part of the unsea program. * Copyright 1992 by David W. Rankin, Jr. * * See "unsea.txt" for full copyright information applying * to all text in this package. * * * macbin.c holds the unsea_mb() and associated routines. */ #include "unsea.h" int unsea_mb(char *oldfilename, char *newfilename) { /* start of declared variables */ extern struct starting_flags stflags; FILE *oldfilep; /* the original SEA MacBinary file */ FILE *newfilep; /* the new non-SEA MacBinary file */ unsigned long int i, /* general counter */ datablock, /* holds the number of blocks in the data fork of the sea */ resblock; /* same as datablock, except for the resource fork */ unsigned char fileblock[128]; /* storage area for blocks in the MacBinary file */ unsigned char *kfileblock; /* This pointer is for kblock transmission, if needed. */ int j, kblocks; /* other counters */ /* start of code */ /* Let's see if the file even exists */ if ( (oldfilep=fopen(oldfilename,"rb") ) == NULL) { fprintf(stderr, "Cannot open %s to convert.\n", oldfilename); return 1; /* Standard error return */ } /* Can I read the file?? */ if (getfileblock(oldfilep,fileblock,128) ) /* getfileblock() returns 1 as an error */ { ERROR("Unable to read %s.\n", oldfilename); return 1; } /* Is it a SEA, and if so what kind? Let's check. */ if ((!check_mb_sea(fileblock))||(!stflags.sea_mode)) /* if check_mb_sea or sea_mode == 0, then the file is not * an mb_sea.*/ { ERROR("%s is not a valid file for unsea.\n", oldfilename); return 1; /* spit it back */ } /* Get a new filename for the file if one was not provided */ if (!strlen(newfilename)) convert_file_name(oldfilename, newfilename, TRUE); /* The TRUE says that a "new_" prefix is to be used * if necessary */ /* Can we open the new file?? If there is one there by the * same name, the answer is no, unless option 'o' has * been selected. In that case, it is yes, no matter what.*/ if(!(stflags.overwrite)&&((newfilep=fopen(newfilename,"r"))!=NULL)) { ERROR3("New file %s for converting %s already exists.\n", newfilename, oldfilename); return 1; } /* Now let's see if the new file can be created... */ if ( (newfilep=fopen(newfilename,"wb") ) == NULL) /* UNSEA can't open the output file */ { printf("File error opening file %s for converting %s.\n", newfilename, oldfilename); fclose(oldfilep); return 1; } /* how long are the two forks of the Mac SEA file?? Note that * getforksize() produces a figure in x bytes, while getblocksize() * produces the number of 128 byte blocks in said number. */ datablock=getblocksize(getforksize(&fileblock[83])); resblock=getblocksize(getforksize(&fileblock[87])); /* Let's now let the user know about what this SEA is like, * unless he already told us not to, via the b option. */ if(!stflags.less_talk) { printf("Opening %s for MacBinary conversion.\n\t SEA type:",oldfilename); switch (stflags.sea_mode){ case 1: printf("Compact Pro. \n"); break; case 3: printf("StuffIt Deluxe/Lite\n"); break; } printf("\t Output file: %s \n\t\ Output file size (in bytes): %ld \n",newfilename,((datablock+1)*128)); } /* Let's produce a block header for "newfilename" */ convert_mb_header(fileblock); /* now, push the converted header into the new file, dealing gracefully (at least somewhat gracefully...) with any file errors. */ if (sendfileblock(newfilep,fileblock,128) ) { ERROR3("File error accessing file %s for converting %s.\n", newfilename, oldfilename); DELETE_FILE(newfilename); /* Let's clean up the newly-generated file, as well. */ return 1; } /* Send the data block through unmolested, if it exists at all. */ if (datablock) { if(((datablock/8)>2)&&((kfileblock=calloc(1024,1))!=NULL)) { /* Basically, is the "fast" method worth the effort, and if * so, can we get space for it?? */ kblocks = (datablock / 8); for(i=1;i<= kblocks;i++) { if((getfileblock(oldfilep,kfileblock,1024))||(sendfileblock(newfilep,kfileblock,1024))) { ERROR3("File error during conversion of %s into %s.\n", oldfilename,newfilename); DELETE_FILE(newfilename); /* Let's clean up the newly-generated file, as well. */ return 1; } datablock -= 8; } free(kfileblock); }/* There, the "big" parts are out of the way... */ /* Now, let's get the leftovers... */ for(i=1;i<=datablock;i++) { if((getfileblock(oldfilep,fileblock,128))||(sendfileblock(newfilep,fileblock,128))) { ERROR3("File error during conversion of %s into %s.\n", oldfilename,newfilename); DELETE_FILE(newfilename); /* Let's clean up the newly-generated file, as well. */ return 1; } } } /* End of datablock sending */ /* Now that we have sent the data block, we can trash the old res fork */ if(((resblock/8)>2)&&((kfileblock=calloc(1024,1))!=NULL)) { /* Again, is the "fast" method worth the effort, and if * so, can we get space for it?? */ kblocks = (resblock / 8); for(i=1;i<= kblocks;i++) { if(getfileblock(oldfilep,kfileblock,1024)) { ERROR3("File error during conversion of %s into %s.\n", oldfilename,newfilename); DELETE_FILE(newfilename); /* Let's clean up the newly-generated file, as well. */ return 1; } resblock -= 8; } free(kfileblock); }/* There, the "big" parts are out of the way... */ for(i=1;i<=resblock;i++) { /* Again, let's check for errors (my, aren't we being paranoid * about errors.. ;) */ if (getfileblock(oldfilep,fileblock,128) ) { ERROR3("File error during conversion of %s into %s.\n", oldfilename,newfilename); DELETE_FILE(newfilename); /* Let's clean up the newly-generated file, as well. */ return 1; } } /* Send the rest of oldfile over, if any. (for compatability with * standard, which allows Info block after the two forks.) */ while ( (j=fgetc(oldfilep) ) != EOF) { fputc(j,newfilep); } ERROR3("%s successfully converted to %s.\n\n", oldfilename, newfilename); return 0; /* a job well done :) */ } /* end of unsea_mb() */ int check_mb_sea(unsigned char block[]) { extern struct starting_flags stflags; int i; /* counter, both general and specific */ char restype[5]; /* 4 byte length, for file type and creator */ int j; stflags.sea_mode = 0; if (block[0] || block[74] || block[82]) return 0; /* If any of these are != 0, this is NOT a MB file */ /* From this point on, cmb() should return 1, to indicate that this * is a MB file, simply not a MB SEA*/ for(i=0;i<4;i++) restype[i]=block[65+i]; restype[4] = 0; if (strcmp(restype, "APPL")) /* This is TRUE if restype != "APPL" */ return 1; /* Can add "appe" here if needed later... */ /* Time to do the same thing with the creator type */ for(i=0; i<4; i++) restype[i]=block[69+i]; if ((!stflags.ignore_cpt_seas)&&(!strcmp(restype, "EXTR"))) /* If we can even read CompactPro SEAs, is it one? */ { stflags.sea_mode = 1; return 1; /* it is */} else if ((!stflags.ignore_sitd_seas)&&(!strcmp(restype, "aust"))) /* Can we read StuffIt SEAs, and if so is this file one? */ { stflags.sea_mode = 3; return 1; /* Yep. :) */} return 1; /* None of these is true, so instead, let's just return * that it's a MacBinary file. */ } /* end of check_mb_sea() */