"Fossies" - the Fresh Open Source Software Archive

Member "mpack-1.6/macfile.c" (16 Feb 1995, 11034 Bytes) of package /linux/misc/old/mpack-1.6.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "macfile.c" see the Fossies "Dox" file reference documentation.

    1 /* macfile.c -- simple applesingle/appledouble encoding/decoding routines
    2  */
    3 /* (C) Copyright 1995 by Carnegie Mellon University
    4  * All Rights Reserved.
    5  *
    6  * Permission to use, copy, modify, distribute, and sell this software
    7  * and its documentation for any purpose is hereby granted without
    8  * fee, provided that the above copyright notice appear in all copies
    9  * and that both that copyright notice and this permission notice
   10  * appear in supporting documentation, and that the name of Carnegie
   11  * Mellon University not be used in advertising or publicity
   12  * pertaining to distribution of the software without specific,
   13  * written prior permission.  Carnegie Mellon University makes no
   14  * representations about the suitability of this software for any
   15  * purpose.  It is provided "as is" without express or implied
   16  * warranty.
   17  *
   18  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
   19  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
   20  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
   21  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   22  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
   23  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
   24  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
   25  * SOFTWARE.
   26  */
   27 /* (C) Copyright 1994-1995 by Christopher J. Newman
   28  * All Rights Reserved.
   29  *
   30  * Permission to use, copy, modify, distribute, and sell this software and its
   31  * documentation for any purpose is hereby granted without fee, provided that
   32  * the above copyright notice appear in all copies and that both that
   33  * copyright notice and this permission notice appear in supporting
   34  * documentation, and that the name of Christopher J. Newman not be used in
   35  * advertising or publicity pertaining to distribution of the software without
   36  * specific, written prior permission.  Christopher J. Newman makes no
   37  * representations about the suitability of this software for any purpose.  It
   38  * is provided "as is" without express or implied warranty.
   39  *
   40  * CHRISTOPHER J. NEWMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
   41  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
   42  * SHALL CHRISTOPHER J. NEWMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR
   43  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
   44  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
   45  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
   46  * OF THIS SOFTWARE.
   47  */
   48 
   49 #include <stdio.h>
   50 #include <string.h>
   51 #include "macmpack.h"   /* for copy_buf & watch */
   52 
   53 /* applefile definitions used */
   54 #define APPLESINGLE_MAGIC 0x00051600L
   55 #define APPLEDOUBLE_MAGIC 0x00051607L
   56 #define VERSION 0x00020000
   57 #define ENT_DFORK   1
   58 #define ENT_RFORK   2
   59 #define ENT_NAME    3
   60 #define ENT_COMMENT 4
   61 #define ENT_DATES   8
   62 #define ENT_FINFO   9
   63 #define CONVERT_TIME 1265437696L
   64 
   65 /* applefile structures */
   66 typedef struct ap_header {
   67     long magic;
   68     long version;
   69     char fill[16];
   70     short entries;
   71 } ap_header;
   72 typedef struct ap_entry {
   73     unsigned long id;
   74     unsigned long offset;
   75     unsigned long length;
   76 } ap_entry;
   77 typedef struct ap_dates {
   78     long create, modify, backup, access;
   79 } ap_dates;
   80 
   81 /* default number of entries */
   82 #define NUM_ENTRIES 6
   83 
   84 /* Generate an applefile
   85  *  outfile -- output file
   86  *  fpb -- hierarchical file parameter block
   87  *  rfork, dfork -- resource & data forks
   88  * returns -1 on failure, 0 on success
   89  *
   90  * closes dfork & rfork, but not outputfile
   91  */
   92 int encode_applefile(FILE *outfile, HFileInfo *fpb, FILE *rfork, FILE *dfork)
   93 {
   94     ap_header head;
   95     ap_entry entries[NUM_ENTRIES];
   96     ap_dates dates;
   97     short i, count;
   98     long comlen, procID;
   99     DateTimeRec cur_time;
  100     unsigned long cur_secs;
  101     IOParam vinfo;
  102     GetVolParmsInfoBuffer vp;
  103     DTPBRec dtp;
  104     char comment[256];
  105     
  106     /* make sure things look OK */
  107     if (!rfork || !outfile) {
  108         if (rfork) fclose(rfork);
  109         if (dfork) fclose(dfork);
  110         if (outfile) fclose(outfile);
  111         return (-1);
  112     }
  113     
  114     /* get a file comment, if possible */
  115     procID = 0;
  116     GetWDInfo(fpb->ioVRefNum, &fpb->ioVRefNum, &fpb->ioDirID, &procID);
  117     memset((void *) &vinfo, '\0', sizeof (vinfo));
  118     vinfo.ioVRefNum = fpb->ioVRefNum;
  119     vinfo.ioBuffer = (Ptr) &vp;
  120     vinfo.ioReqCount = sizeof (vp);
  121     comlen = 0;
  122     if (PBHGetVolParmsSync((HParmBlkPtr) &vinfo) == noErr &&
  123         ((vp.vMAttrib >> bHasDesktopMgr) & 1)) {
  124         memset((void *) &dtp, '\0', sizeof (dtp));
  125         dtp.ioVRefNum = fpb->ioVRefNum;
  126         if (PBDTGetPath(&dtp) == noErr) {
  127             dtp.ioDTBuffer = (Ptr) comment;
  128             dtp.ioNamePtr = fpb->ioNamePtr;
  129             dtp.ioDirID = fpb->ioFlParID;
  130             if (PBDTGetCommentSync(&dtp) == noErr) comlen = dtp.ioDTActCount;
  131         }
  132     }
  133     
  134     /* write header */
  135     head.magic = dfork ? APPLESINGLE_MAGIC : APPLEDOUBLE_MAGIC;
  136     head.version = VERSION;
  137     memset(head.fill, '\0', sizeof (head.fill));
  138     head.entries = NUM_ENTRIES - (dfork ? 0 : 1);
  139     fwrite((char *) &head, sizeof (head), 1, outfile);
  140     
  141     /* write entry descriptors */
  142     entries[0].offset = sizeof (head) + sizeof (ap_entry) * head.entries;
  143     entries[0].id = ENT_NAME;
  144     entries[0].length = *fpb->ioNamePtr;
  145     entries[1].id = ENT_FINFO;
  146     entries[1].length = sizeof (FInfo) + sizeof (FXInfo);
  147     entries[2].id = ENT_DATES;
  148     entries[2].length = sizeof (ap_dates);
  149     entries[3].id = ENT_COMMENT;
  150     entries[3].length = comlen;
  151     entries[4].id = ENT_RFORK;
  152     entries[4].length = fpb->ioFlRLgLen;
  153     entries[5].id = ENT_DFORK;
  154     entries[5].length = fpb->ioFlLgLen;
  155     for (i = 1; i < NUM_ENTRIES; ++i) {
  156         entries[i].offset = entries[i-1].offset + entries[i-1].length;
  157     }
  158     fwrite((char *) entries, sizeof (ap_entry), head.entries, outfile);
  159     
  160     /* write name */
  161     fwrite((char *) fpb->ioNamePtr + 1, *fpb->ioNamePtr, 1, outfile);
  162     /* write finder info */
  163     fwrite((char *) &fpb->ioFlFndrInfo, sizeof (FInfo), 1, outfile);
  164     fwrite((char *) &fpb->ioFlXFndrInfo, sizeof (FXInfo), 1, outfile);
  165     /* write dates */
  166     GetTime(&cur_time);
  167     Date2Secs(&cur_time, &cur_secs);
  168     dates.create = fpb->ioFlCrDat + CONVERT_TIME;
  169     dates.modify = fpb->ioFlMdDat + CONVERT_TIME;
  170     dates.backup = fpb->ioFlBkDat + CONVERT_TIME;
  171     dates.access = cur_secs + CONVERT_TIME;
  172     fwrite((char *) &dates, sizeof (ap_dates), 1, outfile);
  173     /* write comment */
  174     if (comlen) fwrite(comment, sizeof (char), comlen, outfile);
  175     /* write resource fork */
  176     while ((count = fread(copy_buf, sizeof (char), sizeof (copy_buf), rfork)) > 0) {
  177         fwrite(copy_buf, sizeof (char), count, outfile);
  178     }
  179     fclose(rfork);
  180     /* write data fork */
  181     if (dfork) {
  182         while ((count = fread(copy_buf, sizeof (char), sizeof (copy_buf), dfork)) > 0) {
  183             fwrite(copy_buf, sizeof (char), count, outfile);
  184         }
  185         fclose(dfork);
  186     }
  187     
  188     return (0);
  189 }
  190 
  191 /* decode an applefile
  192  *  infile -- input file
  193  *  fspec  -- file spec of saved file
  194  * returns -1 on failure, 0 on success
  195  */
  196 int decode_applefile(FILE *infile, FSSpec *fspec)
  197 {
  198     ap_header head;
  199     ap_entry entries[NUM_ENTRIES + 1];
  200     ap_dates dates;
  201     StandardFileReply reply;
  202     int i, j;
  203     short refnum;
  204     long count;
  205     OSErr err;
  206     HFileInfo *fpb;
  207     CInfoPBRec cipbr;
  208     long procID;
  209     IOParam vinfo;
  210     GetVolParmsInfoBuffer vp;
  211     DTPBRec dtp;
  212     char comment[256];
  213     
  214     /* read & verify header */
  215     fread((char *) &head, sizeof (head), 1, infile);
  216     if (head.magic != APPLESINGLE_MAGIC && head.magic != APPLEDOUBLE_MAGIC) {
  217         return (-1);
  218     }
  219     if (head.version != VERSION) {
  220         return (-1);
  221     }
  222     
  223     /* read entries */
  224     for (i = j = 0; i < head.entries; ++i) {
  225         fread((char *) (entries + j), sizeof (ap_entry), 1, infile);
  226         if (j < NUM_ENTRIES) switch (entries[j].id) {
  227             case ENT_NAME:
  228             case ENT_FINFO:
  229             case ENT_DATES:
  230             case ENT_COMMENT:
  231             case ENT_RFORK:
  232             case ENT_DFORK:
  233                 ++j;
  234                 break;
  235         }
  236     }
  237     
  238     /* read name */
  239     for (i = 0; i < j && entries[i].id != ENT_NAME; ++i);
  240     if (i == j) return (-1);
  241     fseek(infile, entries[i].offset, SEEK_SET);
  242     if (entries[i].length > 63) entries[i].length = 63;
  243     *fspec->name = fread((char *) fspec->name + 1, sizeof (char), entries[i].length, infile);
  244     SetCursor(&arrow);
  245     NAputFile("\pSave decoded file as:", fspec->name, &reply);
  246     SetCursor(&watch);
  247     statrefresh();
  248     if (!reply.sfGood) return (didchat = -1);
  249     *fspec = reply.sfFile;
  250 
  251     /* create & get info for file */
  252     if (reply.sfReplacing) HDelete(fspec->vRefNum, fspec->parID, fspec->name);
  253     if (HCreate(fspec->vRefNum, fspec->parID, fspec->name, '????', '????') != noErr) {
  254         return (-1);
  255     }
  256     fpb = (HFileInfo *) &cipbr;
  257     fpb->ioVRefNum = fspec->vRefNum;
  258     fpb->ioNamePtr = fspec->name;
  259     fpb->ioDirID = fspec->parID;
  260     fpb->ioFDirIndex = 0;
  261     PBGetCatInfoSync(&cipbr);
  262     
  263     /* get finder info */
  264     for (i = 0; i < j && entries[i].id != ENT_FINFO; ++i);
  265     if (i < j) {
  266         fseek(infile, entries[i].offset, SEEK_SET);
  267         fread((char *) &fpb->ioFlFndrInfo, sizeof (FInfo), 1, infile);
  268         fread((char *) &fpb->ioFlXFndrInfo, sizeof (FXInfo), 1, infile);
  269         fpb->ioFlFndrInfo.fdFlags &= 0xf800; /* clear flags maintained by finder */
  270     }
  271     
  272     /* get file date info */
  273     for (i = 0; i < j && entries[i].id != ENT_DATES; ++i);
  274     if (i < j) {
  275         fseek(infile, entries[i].offset, SEEK_SET);
  276         fread((char *) &dates, sizeof (dates), 1, infile);
  277         fpb->ioFlCrDat = dates.create - CONVERT_TIME;
  278         fpb->ioFlMdDat = dates.modify - CONVERT_TIME;
  279         fpb->ioFlBkDat = dates.backup - CONVERT_TIME;
  280     }
  281     
  282     /* update info */
  283     fpb->ioDirID = fpb->ioFlParID;
  284     PBSetCatInfoSync(&cipbr);
  285     
  286     /* get comment & save it */
  287     for (i = 0; i < j && entries[i].id != ENT_COMMENT; ++i);
  288     if (i < j && entries[i].length != 0) {
  289         memset((void *) &vinfo, '\0', sizeof (vinfo));
  290         vinfo.ioVRefNum = fpb->ioVRefNum;
  291         vinfo.ioBuffer = (Ptr) &vp;
  292         vinfo.ioReqCount = sizeof (vp);
  293         if (PBHGetVolParmsSync((HParmBlkPtr) &vinfo) == noErr &&
  294             ((vp.vMAttrib >> bHasDesktopMgr) & 1)) {
  295             memset((void *) &dtp, '\0', sizeof (dtp));
  296             dtp.ioVRefNum = fpb->ioVRefNum;
  297             if (PBDTGetPath(&dtp) == noErr) {
  298                 if (entries[i].length > 255) entries[i].length = 255;
  299                 fseek(infile, entries[i].offset, SEEK_SET);
  300                 fread(comment, entries[i].length, 1, infile);
  301                 dtp.ioDTBuffer = (Ptr) comment;
  302                 dtp.ioNamePtr = fpb->ioNamePtr;
  303                 dtp.ioDirID = fpb->ioDirID;
  304                 dtp.ioDTReqCount = entries[i].length;
  305                 if (PBDTSetCommentSync(&dtp) == noErr) {
  306                     PBDTFlushSync(&dtp);
  307                 }
  308             }
  309         }
  310     }
  311     
  312     /* do resource/data forks */
  313     for (i = 0; i < j; ++i) {
  314         if (entries[i].id == ENT_RFORK || entries[i].id == ENT_DFORK) {
  315             fseek(infile, entries[i].offset, SEEK_SET);
  316             if (entries[i].id == ENT_DFORK) {
  317                 err = HOpen(fspec->vRefNum, fspec->parID, fspec->name, 2, &refnum);
  318             } else {
  319                 err = HOpenRF(fspec->vRefNum, fspec->parID, fspec->name, 2, &refnum);
  320             }
  321             if (err != noErr) {
  322                 HDelete(fspec->vRefNum, fspec->parID, fspec->name);
  323                 return (-1);
  324             }
  325             while (entries[i].length > sizeof (copy_buf)) {
  326                 count = fread(copy_buf, sizeof (char), sizeof (copy_buf), infile);
  327                 entries[i].length -= count;
  328                 FSWrite(refnum, &count, (Ptr) copy_buf);
  329             }
  330             count = fread(copy_buf, sizeof (char), entries[i].length, infile);
  331             FSWrite(refnum, &count, (Ptr) copy_buf);
  332             FSClose(refnum);
  333         }
  334     }
  335     
  336     return (0);
  337 }