home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Amiga / Workbench / Archivers / mpackPPC.lha / mpackPPC / src / macos.c < prev    next >
C/C++ Source or Header  |  1998-04-08  |  10KB  |  391 lines

  1. /* macos.c -- operating system dependant mpack code for the Macintosh
  2.  */
  3. /* (C) Copyright 1993-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 fee,
  8.  * provided that the above copyright notice appear in all copies and
  9.  * that both that copyright notice and this permission notice appear in
  10.  * supporting documentation, and that the name of Carnegie Mellon University
  11.  * not be used in advertising or publicity pertaining to distribution of the
  12.  * software without specific, written prior permission.  Carnegie
  13.  * Mellon University makes no representations about the suitability of
  14.  * this software for any purpose.  It is provided "as is" without
  15.  * express or implied warranty.
  16.  *
  17.  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
  18.  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  19.  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
  20.  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  21.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  22.  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
  23.  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  24.  * SOFTWARE.
  25.  */
  26.  
  27. #include <stdio.h>
  28. #include <ctype.h>
  29. #include <string.h>
  30. #include <errno.h>
  31. #include "common.h"
  32. #include "macnapp.h"
  33. #include "macmpack.h"
  34.  
  35. extern char *malloc(), *realloc();
  36.  
  37. char copy_buf[COPY_BUFSIZE];
  38.  
  39. char *xmalloc(unsigned size)
  40. {
  41.     char *ret;
  42.  
  43.     if (ret = malloc((unsigned) size))
  44.       return ret;
  45.  
  46.     yell("Not enough memory available.");
  47.     maccleanup();
  48.     exit(1);
  49. }
  50.  
  51. char *xrealloc (char *ptr, unsigned size)
  52. {
  53.     char *ret;
  54.  
  55.     /* xrealloc (NULL, size) behaves like xmalloc (size), as in ANSI C */
  56.     if (ret = !ptr ? malloc ((unsigned) size) : realloc (ptr, (unsigned) size))
  57.       return ret;
  58.  
  59.     yell("Not enough memory available");
  60.     maccleanup();
  61.     exit(1);
  62. }
  63.  
  64. char *strsave(char *str)
  65. {
  66.     char *p = xmalloc(strlen(str)+1);
  67.     strcpy(p, str);
  68.     return p;
  69. }
  70.  
  71. /* save output filename buffer */
  72. static char *output_fname = NULL;
  73. static short applefile_flag = 0;
  74. static FSSpec fspec;
  75.  
  76. /* rename or copy a file to a new location
  77.  */
  78. static void rename_or_copy(srcfname, dstfname, dstvol, dirid)
  79.     char *srcfname;
  80.     PCstr *dstfname;
  81.     short dstvol;
  82.     long dirid;
  83. {
  84.     PCstr tstr[257];
  85.     short srefnum, drefnum;
  86.     long count;
  87.     WDPBRec wdpb;
  88.     HParamBlockRec hpb;
  89.     CMovePBRec cpb;
  90.     
  91.     wdpb.ioNamePtr = P(tstr);
  92.     if (PBHGetVol(&wdpb, FALSE) != noErr) return;
  93.     CtoPCstrcpy(tstr, srcfname);
  94.     if (HOpen(0, 0, P(tstr), fsRdPerm, &srefnum) != noErr) return;
  95.     if (GetEOF(srefnum, &count) == noErr && !count) {
  96.         FSClose(srefnum);
  97.         return;
  98.     }
  99.     if (wdpb.ioWDVRefNum == dstvol) {
  100.         /* files on same drive -- do a rename/move */
  101.         FSClose(srefnum);
  102.         hpb.fileParam.ioNamePtr = P(tstr);
  103.         hpb.fileParam.ioVRefNum = 0;
  104.         hpb.ioParam.ioMisc = (Ptr) P(dstfname);
  105.         hpb.fileParam.ioDirID = 0;
  106.         if (PBHRenameSync(&hpb) == noErr && wdpb.ioWDDirID != dirid) {
  107.             cpb.ioNamePtr = P(dstfname);
  108.             cpb.ioVRefNum = 0;
  109.             cpb.ioNewName = NULL;
  110.             cpb.ioNewDirID = dirid;
  111.             cpb.ioDirID = 0;
  112.             PBCatMoveSync(&cpb);
  113.         }
  114.     } else {
  115.         /* files on different drive -- do a copy */
  116.         if (HCreate(dstvol, dirid, P(dstfname), _fcreator, _ftype) != noErr) {
  117.             FSClose(srefnum);
  118.             return;
  119.         }
  120.         if (HOpen(dstvol, dirid, P(dstfname), fsWrPerm, &drefnum) != noErr) {
  121.             FSClose(srefnum);
  122.             HDelete(dstvol, dirid, P(dstfname));
  123.             return;
  124.         }
  125.         count = sizeof (copy_buf);
  126.         while (FSRead(srefnum, &count, (Ptr) copy_buf) != noErr && count > 0) {
  127.             FSWrite(drefnum, &count, (Ptr) copy_buf);
  128.             count = sizeof (copy_buf);
  129.         }
  130.         FSClose(srefnum);
  131.         FSClose(drefnum);
  132.     }
  133. }
  134.  
  135. /* Generate a message-id */
  136. char *os_genid()
  137. {
  138.     char *result;
  139.     long tick;
  140.     unsigned long time;
  141.  
  142.     tick = TickCount();
  143.     result = malloc(64);
  144.     GetDateTime(&time);
  145.     HLock((Handle) mpack_prefs);
  146.     sprintf(result, "%lu.%lu@%s", tick, time, (*mpack_prefs)->internet_host);
  147.     HUnlock((Handle) mpack_prefs);
  148.     
  149.     /* make sure tick count is bumped before we return... */
  150.     while (tick == TickCount());
  151.     
  152.     return (result);
  153. }
  154.  
  155. /* Create and return directory for a message-id
  156.  */
  157. char *os_idtodir(id)
  158. char *id;
  159. {
  160.     static PCstr buf[257];
  161.     PCstr idbuf[257];
  162.     char *fname;
  163.     short uqid;
  164.     OSErr err;
  165.     long dirID;
  166.     Handle h;
  167.     ResType type = 'IDna';
  168.  
  169.     /* prepare filename */
  170.     PtoPCstrcpy(buf, (char *) P(pfolder->prefs));
  171.     fname = C(buf) + PCstrlen(buf);
  172.     
  173.     /* is there a mapping for the id? */
  174.     CtoPCstrcpy(idbuf, id);
  175.     h = GetNamedResource(type, P(idbuf));
  176.     
  177.     /* no mapping -- create one */
  178.     if (!h) {
  179.         while ((uqid = UniqueID(type)) < 128);
  180.         h = NewHandle(sizeof (short));
  181.         if (h) (**(short **)h) = uqid;
  182.         AddResource(h, type, uqid, P(idbuf));
  183.         if ((err = ResError()) != noErr) {
  184.             return (NULL);
  185.         }
  186.     } else {
  187.         uqid = ** (short **) h;
  188.     }
  189.     
  190.     /* set directory name & create it */
  191.     sprintf(fname, "%d:", uqid);
  192.     SetPlen(buf);
  193.     err = DirCreate(pfolder->fspec.vRefNum, 0, P(buf), &dirID);
  194.     if (err != noErr && err != dupFNErr) {
  195.         RmveResource(h);
  196.         DisposHandle(h);
  197.         h = NULL;
  198.     }
  199.     
  200.     return (h ? C(buf) : NULL);
  201. }
  202.  
  203. /*
  204.  * We are done with the directory returned by os_idtodir()
  205.  * Remove it
  206.  */
  207. os_donewithdir(dir)
  208. char *dir;
  209. {
  210.     PCstr buf[257];
  211.     short uqid;
  212.     char *fname;
  213.     Handle h;
  214.     
  215.     CtoPCstrcpy(buf, dir);
  216.     HDelete(0, 0, P(buf));
  217.     fname = strrchr(C(buf), ':');
  218.     while (fname > C(buf) && *--fname != ':');
  219.     if (fname > C(buf)) {
  220.         uqid = atoi(fname + 1);
  221.         h = GetResource('IDna', uqid);
  222.         if (h) {
  223.             RmveResource(h);
  224.             DisposHandle(h);
  225.         }
  226.     }
  227. }
  228.  
  229. /* rename the description file
  230.  */
  231. void renameDescFile(char *fname, short vRefNum, long dirid)
  232. {
  233.     PCstr tstr[65];
  234.     char *p;
  235.  
  236.     MapTypeCreator("text/plain", 0);
  237.  
  238.     /* save description file */
  239.     CtoPCstrcpy(tstr, fname);
  240.     if (p = strrchr(C(tstr), '.')) *p = '\0';
  241.     strcat(C(tstr), ".desc");
  242.     SetPlen(tstr);
  243.     rename_or_copy(TEMPFILENAME, tstr, vRefNum, dirid);
  244.     (void) remove(TEMPFILENAME);
  245. }
  246.  
  247. /*
  248.  * Create a new file, with suggested filename "fname".
  249.  * "fname" may have come from an insecure source, so clean it up first.
  250.  * It may also be null.
  251.  * "contentType" is passed in for use by systems that have typed filesystems.
  252.  * "flags" contains a bit pattern describing attributes of the new file.
  253.  */
  254. FILE *os_newtypedfile(fname, contentType, flags, contentParams)
  255. char *fname;
  256. char *contentType;
  257. int flags;
  258. params *contentParams;
  259. {
  260.     char *p;
  261.     int applefile;
  262.     FILE *outfile = 0, *tmpf;
  263.     StandardFileReply reply;
  264.     PCstr tstr[257];
  265.  
  266.     if (!fname) fname = "";
  267.     
  268.     /* Translate ':' to underscore */
  269.     for (p=fname; *p; p++) {
  270.         if (*p == ':' || !isprint(*p)) *p = '_';
  271.     }
  272.     
  273.     /* chop filename to length */
  274.     if (strlen(fname) > 31) {
  275.         fname += strlen(fname) - 31;
  276.     }
  277.     
  278.     /* remove leading periods, to protect from ".SONY" attacks */
  279.     while (*fname == '.') ++fname;
  280.  
  281.     /* get filename from user */
  282.     applefile = !strcmp(contentType, "application/applefile");
  283.     if (!applefile || !(flags & FILE_INAPPLEDOUBLE)) {
  284.         sprintf(C(tstr), "Found file: %s (%s)",
  285.             fname[0] ? fname : "Untitled", contentType);
  286.         SetPlen(tstr);
  287.         stattext(P(tstr), 1);
  288.     }
  289.     if (!applefile && (!applefile_flag || !(flags & FILE_INAPPLEDOUBLE))) {
  290.         SetCursor(&arrow);
  291.         CtoPstr(fname);
  292.         NAputFile("\pSave decoded file as:",
  293.             fname[0] ? (unsigned char *) fname : "\pUntitled", &reply);
  294.         PtoCstr((unsigned char *) fname);
  295.         SetCursor(&watch);
  296.         statrefresh();
  297.         if (!reply.sfGood) {
  298.             didchat = -1;
  299.             return (NULL);
  300.         }
  301.     }
  302.  
  303.     /* set the type */
  304.     MapTypeCreator(contentType, 0);
  305.  
  306.     /* save file */
  307.     tmpf = tmpfile();
  308.     if (applefile) {
  309.         outfile = tmpf;
  310.         tmpf = NULL;
  311.     } else if ((flags & FILE_INAPPLEDOUBLE) && applefile_flag) {
  312.         outfile = Macopen(tmpf, fspec.name, fspec.vRefNum, fspec.parID,
  313.             flags & FILE_BINARY, 0, fsWrPerm);
  314.     } else {
  315.         HCreate(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, _fcreator, _ftype);
  316.         outfile = Macopen(tmpf, reply.sfFile.name, reply.sfFile.vRefNum, reply.sfFile.parID,
  317.             flags & FILE_BINARY, 0, fsWrPerm);
  318.     }
  319.     applefile_flag = applefile;
  320.     if (tmpf) fclose(tmpf);
  321.     PtoCstr(reply.sfFile.name);
  322.     fname = (char *) reply.sfFile.name;
  323.     if (!outfile) {
  324.         sprintf(C(tstr), "Couldn't open file %s", fname);
  325.         warn(C(tstr));
  326.         return (0);
  327.     }
  328.     
  329.     if (output_fname) free(output_fname);
  330.     output_fname = strsave(fname);
  331.     
  332.     renameDescFile(fname, reply.sfFile.vRefNum, reply.sfFile.parID);
  333.  
  334.     return outfile;
  335. }
  336.  
  337. /*
  338.  * Close a file opened by os_newTypedFile()
  339.  */
  340. os_closetypedfile(outfile)
  341. FILE *outfile;
  342. {
  343.     char buf[128];
  344.     
  345.     if (applefile_flag) {
  346.         rewind(outfile);
  347.         if (decode_applefile(outfile, &fspec) < 0) {
  348.             sprintf(buf, "Failed to decode file %s", output_fname);
  349.             if (didchat >= 0) warn(buf);
  350.             applefile_flag = 0;
  351.         }
  352.     }
  353.  
  354.     /* close file */
  355.     fclose(outfile);
  356. }
  357.  
  358. /*
  359.  * Warn user that the MD5 digest of the last file created by os_newtypedfile()
  360.  * did not match that supplied in the Content-MD5: header.
  361.  */
  362. os_warnMD5mismatch()
  363. {
  364.     char *warning;
  365.  
  366.     warning = xmalloc(strlen(output_fname) + 100);
  367.     sprintf(warning, "%s was corrupted in transit",
  368.         output_fname);
  369.     warn(warning);
  370.     free(warning);
  371. }
  372.  
  373. /* bring up an error dialog for a file error
  374.  */
  375. void os_perror(char *str)
  376. {
  377.     extern int errno;
  378.     char *err = strerror(errno), *scan;
  379.     char msg[256];
  380.     short maxflen;
  381.     
  382.     maxflen = 255 - (strlen(err) + 2);
  383.     if (strlen(str) > maxflen) {
  384.         str += strlen(str) - maxflen;
  385.         for (scan = str; *scan && *scan++ != ':';);
  386.         if (*scan) str = scan;
  387.     }
  388.     sprintf(msg, "%s: %s", str, err);
  389.     yell(msg);
  390. }
  391.