Back to home page

MITgcm

 
 

    


File indexing completed on 2018-03-02 18:44:48 UTC

view on githubraw file Latest commit ec6cf3b0 on 2003-08-26 20:45:25 UTC
ec6cf3b09d Ed H*0001 /* macfile.c -- simple applesingle/appledouble encoding/decoding routines
                0002  */
                0003 /* (C) Copyright 1995 by Carnegie Mellon University
                0004  * All Rights Reserved.
                0005  *
                0006  * Permission to use, copy, modify, distribute, and sell this software
                0007  * and its documentation for any purpose is hereby granted without
                0008  * fee, provided that the above copyright notice appear in all copies
                0009  * and that both that copyright notice and this permission notice
                0010  * appear in supporting documentation, and that the name of Carnegie
                0011  * Mellon University not be used in advertising or publicity
                0012  * pertaining to distribution of the software without specific,
                0013  * written prior permission.  Carnegie Mellon University makes no
                0014  * representations about the suitability of this software for any
                0015  * purpose.  It is provided "as is" without express or implied
                0016  * warranty.
                0017  *
                0018  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
                0019  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
                0020  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
                0021  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                0022  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
                0023  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
                0024  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
                0025  * SOFTWARE.
                0026  */
                0027 /* (C) Copyright 1994-1995 by Christopher J. Newman
                0028  * All Rights Reserved.
                0029  *
                0030  * Permission to use, copy, modify, distribute, and sell this software and its
                0031  * documentation for any purpose is hereby granted without fee, provided that
                0032  * the above copyright notice appear in all copies and that both that
                0033  * copyright notice and this permission notice appear in supporting
                0034  * documentation, and that the name of Christopher J. Newman not be used in
                0035  * advertising or publicity pertaining to distribution of the software without
                0036  * specific, written prior permission.  Christopher J. Newman makes no
                0037  * representations about the suitability of this software for any purpose.  It
                0038  * is provided "as is" without express or implied warranty.
                0039  *
                0040  * CHRISTOPHER J. NEWMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
                0041  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
                0042  * SHALL CHRISTOPHER J. NEWMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR
                0043  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
                0044  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
                0045  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
                0046  * OF THIS SOFTWARE.
                0047  */
                0048 
                0049 #include <stdio.h>
                0050 #include <string.h>
                0051 #include "macmpack.h"   /* for copy_buf & watch */
                0052 
                0053 /* applefile definitions used */
                0054 #define APPLESINGLE_MAGIC 0x00051600L
                0055 #define APPLEDOUBLE_MAGIC 0x00051607L
                0056 #define VERSION 0x00020000
                0057 #define ENT_DFORK   1
                0058 #define ENT_RFORK   2
                0059 #define ENT_NAME    3
                0060 #define ENT_COMMENT 4
                0061 #define ENT_DATES   8
                0062 #define ENT_FINFO   9
                0063 #define CONVERT_TIME 1265437696L
                0064 
                0065 /* applefile structures */
                0066 typedef struct ap_header {
                0067     long magic;
                0068     long version;
                0069     char fill[16];
                0070     short entries;
                0071 } ap_header;
                0072 typedef struct ap_entry {
                0073     unsigned long id;
                0074     unsigned long offset;
                0075     unsigned long length;
                0076 } ap_entry;
                0077 typedef struct ap_dates {
                0078     long create, modify, backup, access;
                0079 } ap_dates;
                0080 
                0081 /* default number of entries */
                0082 #define NUM_ENTRIES 6
                0083 
                0084 /* Generate an applefile
                0085  *  outfile -- output file
                0086  *  fpb -- hierarchical file parameter block
                0087  *  rfork, dfork -- resource & data forks
                0088  * returns -1 on failure, 0 on success
                0089  *
                0090  * closes dfork & rfork, but not outputfile
                0091  */
                0092 int encode_applefile(FILE *outfile, HFileInfo *fpb, FILE *rfork, FILE *dfork)
                0093 {
                0094     ap_header head;
                0095     ap_entry entries[NUM_ENTRIES];
                0096     ap_dates dates;
                0097     short i, count;
                0098     long comlen, procID;
                0099     DateTimeRec cur_time;
                0100     unsigned long cur_secs;
                0101     IOParam vinfo;
                0102     GetVolParmsInfoBuffer vp;
                0103     DTPBRec dtp;
                0104     char comment[256];
                0105     
                0106     /* make sure things look OK */
                0107     if (!rfork || !outfile) {
                0108         if (rfork) fclose(rfork);
                0109         if (dfork) fclose(dfork);
                0110         if (outfile) fclose(outfile);
                0111         return (-1);
                0112     }
                0113     
                0114     /* get a file comment, if possible */
                0115     procID = 0;
                0116     GetWDInfo(fpb->ioVRefNum, &fpb->ioVRefNum, &fpb->ioDirID, &procID);
                0117     memset((void *) &vinfo, '\0', sizeof (vinfo));
                0118     vinfo.ioVRefNum = fpb->ioVRefNum;
                0119     vinfo.ioBuffer = (Ptr) &vp;
                0120     vinfo.ioReqCount = sizeof (vp);
                0121     comlen = 0;
                0122     if (PBHGetVolParmsSync((HParmBlkPtr) &vinfo) == noErr &&
                0123         ((vp.vMAttrib >> bHasDesktopMgr) & 1)) {
                0124         memset((void *) &dtp, '\0', sizeof (dtp));
                0125         dtp.ioVRefNum = fpb->ioVRefNum;
                0126         if (PBDTGetPath(&dtp) == noErr) {
                0127             dtp.ioDTBuffer = (Ptr) comment;
                0128             dtp.ioNamePtr = fpb->ioNamePtr;
                0129             dtp.ioDirID = fpb->ioFlParID;
                0130             if (PBDTGetCommentSync(&dtp) == noErr) comlen = dtp.ioDTActCount;
                0131         }
                0132     }
                0133     
                0134     /* write header */
                0135     head.magic = dfork ? APPLESINGLE_MAGIC : APPLEDOUBLE_MAGIC;
                0136     head.version = VERSION;
                0137     memset(head.fill, '\0', sizeof (head.fill));
                0138     head.entries = NUM_ENTRIES - (dfork ? 0 : 1);
                0139     fwrite((char *) &head, sizeof (head), 1, outfile);
                0140     
                0141     /* write entry descriptors */
                0142     entries[0].offset = sizeof (head) + sizeof (ap_entry) * head.entries;
                0143     entries[0].id = ENT_NAME;
                0144     entries[0].length = *fpb->ioNamePtr;
                0145     entries[1].id = ENT_FINFO;
                0146     entries[1].length = sizeof (FInfo) + sizeof (FXInfo);
                0147     entries[2].id = ENT_DATES;
                0148     entries[2].length = sizeof (ap_dates);
                0149     entries[3].id = ENT_COMMENT;
                0150     entries[3].length = comlen;
                0151     entries[4].id = ENT_RFORK;
                0152     entries[4].length = fpb->ioFlRLgLen;
                0153     entries[5].id = ENT_DFORK;
                0154     entries[5].length = fpb->ioFlLgLen;
                0155     for (i = 1; i < NUM_ENTRIES; ++i) {
                0156         entries[i].offset = entries[i-1].offset + entries[i-1].length;
                0157     }
                0158     fwrite((char *) entries, sizeof (ap_entry), head.entries, outfile);
                0159     
                0160     /* write name */
                0161     fwrite((char *) fpb->ioNamePtr + 1, *fpb->ioNamePtr, 1, outfile);
                0162     /* write finder info */
                0163     fwrite((char *) &fpb->ioFlFndrInfo, sizeof (FInfo), 1, outfile);
                0164     fwrite((char *) &fpb->ioFlXFndrInfo, sizeof (FXInfo), 1, outfile);
                0165     /* write dates */
                0166     GetTime(&cur_time);
                0167     Date2Secs(&cur_time, &cur_secs);
                0168     dates.create = fpb->ioFlCrDat + CONVERT_TIME;
                0169     dates.modify = fpb->ioFlMdDat + CONVERT_TIME;
                0170     dates.backup = fpb->ioFlBkDat + CONVERT_TIME;
                0171     dates.access = cur_secs + CONVERT_TIME;
                0172     fwrite((char *) &dates, sizeof (ap_dates), 1, outfile);
                0173     /* write comment */
                0174     if (comlen) fwrite(comment, sizeof (char), comlen, outfile);
                0175     /* write resource fork */
                0176     while ((count = fread(copy_buf, sizeof (char), sizeof (copy_buf), rfork)) > 0) {
                0177         fwrite(copy_buf, sizeof (char), count, outfile);
                0178     }
                0179     fclose(rfork);
                0180     /* write data fork */
                0181     if (dfork) {
                0182         while ((count = fread(copy_buf, sizeof (char), sizeof (copy_buf), dfork)) > 0) {
                0183             fwrite(copy_buf, sizeof (char), count, outfile);
                0184         }
                0185         fclose(dfork);
                0186     }
                0187     
                0188     return (0);
                0189 }
                0190 
                0191 /* decode an applefile
                0192  *  infile -- input file
                0193  *  fspec  -- file spec of saved file
                0194  * returns -1 on failure, 0 on success
                0195  */
                0196 int decode_applefile(FILE *infile, FSSpec *fspec)
                0197 {
                0198     ap_header head;
                0199     ap_entry entries[NUM_ENTRIES + 1];
                0200     ap_dates dates;
                0201     StandardFileReply reply;
                0202     int i, j;
                0203     short refnum;
                0204     long count;
                0205     OSErr err;
                0206     HFileInfo *fpb;
                0207     CInfoPBRec cipbr;
                0208     long procID;
                0209     IOParam vinfo;
                0210     GetVolParmsInfoBuffer vp;
                0211     DTPBRec dtp;
                0212     char comment[256];
                0213     
                0214     /* read & verify header */
                0215     fread((char *) &head, sizeof (head), 1, infile);
                0216     if (head.magic != APPLESINGLE_MAGIC && head.magic != APPLEDOUBLE_MAGIC) {
                0217         return (-1);
                0218     }
                0219     if (head.version != VERSION) {
                0220         return (-1);
                0221     }
                0222     
                0223     /* read entries */
                0224     for (i = j = 0; i < head.entries; ++i) {
                0225         fread((char *) (entries + j), sizeof (ap_entry), 1, infile);
                0226         if (j < NUM_ENTRIES) switch (entries[j].id) {
                0227             case ENT_NAME:
                0228             case ENT_FINFO:
                0229             case ENT_DATES:
                0230             case ENT_COMMENT:
                0231             case ENT_RFORK:
                0232             case ENT_DFORK:
                0233                 ++j;
                0234                 break;
                0235         }
                0236     }
                0237     
                0238     /* read name */
                0239     for (i = 0; i < j && entries[i].id != ENT_NAME; ++i);
                0240     if (i == j) return (-1);
                0241     fseek(infile, entries[i].offset, SEEK_SET);
                0242     if (entries[i].length > 63) entries[i].length = 63;
                0243     *fspec->name = fread((char *) fspec->name + 1, sizeof (char), entries[i].length, infile);
                0244     SetCursor(&arrow);
                0245     NAputFile("\pSave decoded file as:", fspec->name, &reply);
                0246     SetCursor(&watch);
                0247     statrefresh();
                0248     if (!reply.sfGood) return (didchat = -1);
                0249     *fspec = reply.sfFile;
                0250 
                0251     /* create & get info for file */
                0252     if (reply.sfReplacing) HDelete(fspec->vRefNum, fspec->parID, fspec->name);
                0253     if (HCreate(fspec->vRefNum, fspec->parID, fspec->name, '????', '????') != noErr) {
                0254         return (-1);
                0255     }
                0256     fpb = (HFileInfo *) &cipbr;
                0257     fpb->ioVRefNum = fspec->vRefNum;
                0258     fpb->ioNamePtr = fspec->name;
                0259     fpb->ioDirID = fspec->parID;
                0260     fpb->ioFDirIndex = 0;
                0261     PBGetCatInfoSync(&cipbr);
                0262     
                0263     /* get finder info */
                0264     for (i = 0; i < j && entries[i].id != ENT_FINFO; ++i);
                0265     if (i < j) {
                0266         fseek(infile, entries[i].offset, SEEK_SET);
                0267         fread((char *) &fpb->ioFlFndrInfo, sizeof (FInfo), 1, infile);
                0268         fread((char *) &fpb->ioFlXFndrInfo, sizeof (FXInfo), 1, infile);
                0269         fpb->ioFlFndrInfo.fdFlags &= 0xf800; /* clear flags maintained by finder */
                0270     }
                0271     
                0272     /* get file date info */
                0273     for (i = 0; i < j && entries[i].id != ENT_DATES; ++i);
                0274     if (i < j) {
                0275         fseek(infile, entries[i].offset, SEEK_SET);
                0276         fread((char *) &dates, sizeof (dates), 1, infile);
                0277         fpb->ioFlCrDat = dates.create - CONVERT_TIME;
                0278         fpb->ioFlMdDat = dates.modify - CONVERT_TIME;
                0279         fpb->ioFlBkDat = dates.backup - CONVERT_TIME;
                0280     }
                0281     
                0282     /* update info */
                0283     fpb->ioDirID = fpb->ioFlParID;
                0284     PBSetCatInfoSync(&cipbr);
                0285     
                0286     /* get comment & save it */
                0287     for (i = 0; i < j && entries[i].id != ENT_COMMENT; ++i);
                0288     if (i < j && entries[i].length != 0) {
                0289         memset((void *) &vinfo, '\0', sizeof (vinfo));
                0290         vinfo.ioVRefNum = fpb->ioVRefNum;
                0291         vinfo.ioBuffer = (Ptr) &vp;
                0292         vinfo.ioReqCount = sizeof (vp);
                0293         if (PBHGetVolParmsSync((HParmBlkPtr) &vinfo) == noErr &&
                0294             ((vp.vMAttrib >> bHasDesktopMgr) & 1)) {
                0295             memset((void *) &dtp, '\0', sizeof (dtp));
                0296             dtp.ioVRefNum = fpb->ioVRefNum;
                0297             if (PBDTGetPath(&dtp) == noErr) {
                0298                 if (entries[i].length > 255) entries[i].length = 255;
                0299                 fseek(infile, entries[i].offset, SEEK_SET);
                0300                 fread(comment, entries[i].length, 1, infile);
                0301                 dtp.ioDTBuffer = (Ptr) comment;
                0302                 dtp.ioNamePtr = fpb->ioNamePtr;
                0303                 dtp.ioDirID = fpb->ioDirID;
                0304                 dtp.ioDTReqCount = entries[i].length;
                0305                 if (PBDTSetCommentSync(&dtp) == noErr) {
                0306                     PBDTFlushSync(&dtp);
                0307                 }
                0308             }
                0309         }
                0310     }
                0311     
                0312     /* do resource/data forks */
                0313     for (i = 0; i < j; ++i) {
                0314         if (entries[i].id == ENT_RFORK || entries[i].id == ENT_DFORK) {
                0315             fseek(infile, entries[i].offset, SEEK_SET);
                0316             if (entries[i].id == ENT_DFORK) {
                0317                 err = HOpen(fspec->vRefNum, fspec->parID, fspec->name, 2, &refnum);
                0318             } else {
                0319                 err = HOpenRF(fspec->vRefNum, fspec->parID, fspec->name, 2, &refnum);
                0320             }
                0321             if (err != noErr) {
                0322                 HDelete(fspec->vRefNum, fspec->parID, fspec->name);
                0323                 return (-1);
                0324             }
                0325             while (entries[i].length > sizeof (copy_buf)) {
                0326                 count = fread(copy_buf, sizeof (char), sizeof (copy_buf), infile);
                0327                 entries[i].length -= count;
                0328                 FSWrite(refnum, &count, (Ptr) copy_buf);
                0329             }
                0330             count = fread(copy_buf, sizeof (char), entries[i].length, infile);
                0331             FSWrite(refnum, &count, (Ptr) copy_buf);
                0332             FSClose(refnum);
                0333         }
                0334     }
                0335     
                0336     return (0);
                0337 }