home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Dream 52
/
Amiga_Dream_52.iso
/
Amiga
/
Workbench
/
Archivers
/
mpackPPC.lha
/
mpackPPC
/
src
/
macos.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-04-08
|
10KB
|
391 lines
/* macos.c -- operating system dependant mpack code for the Macintosh
*/
/* (C) Copyright 1993-1995 by Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of Carnegie Mellon University
* not be used in advertising or publicity pertaining to distribution of the
* software without specific, written prior permission. Carnegie
* Mellon University makes no representations about the suitability of
* this software for any purpose. It is provided "as is" without
* express or implied warranty.
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include "common.h"
#include "macnapp.h"
#include "macmpack.h"
extern char *malloc(), *realloc();
char copy_buf[COPY_BUFSIZE];
char *xmalloc(unsigned size)
{
char *ret;
if (ret = malloc((unsigned) size))
return ret;
yell("Not enough memory available.");
maccleanup();
exit(1);
}
char *xrealloc (char *ptr, unsigned size)
{
char *ret;
/* xrealloc (NULL, size) behaves like xmalloc (size), as in ANSI C */
if (ret = !ptr ? malloc ((unsigned) size) : realloc (ptr, (unsigned) size))
return ret;
yell("Not enough memory available");
maccleanup();
exit(1);
}
char *strsave(char *str)
{
char *p = xmalloc(strlen(str)+1);
strcpy(p, str);
return p;
}
/* save output filename buffer */
static char *output_fname = NULL;
static short applefile_flag = 0;
static FSSpec fspec;
/* rename or copy a file to a new location
*/
static void rename_or_copy(srcfname, dstfname, dstvol, dirid)
char *srcfname;
PCstr *dstfname;
short dstvol;
long dirid;
{
PCstr tstr[257];
short srefnum, drefnum;
long count;
WDPBRec wdpb;
HParamBlockRec hpb;
CMovePBRec cpb;
wdpb.ioNamePtr = P(tstr);
if (PBHGetVol(&wdpb, FALSE) != noErr) return;
CtoPCstrcpy(tstr, srcfname);
if (HOpen(0, 0, P(tstr), fsRdPerm, &srefnum) != noErr) return;
if (GetEOF(srefnum, &count) == noErr && !count) {
FSClose(srefnum);
return;
}
if (wdpb.ioWDVRefNum == dstvol) {
/* files on same drive -- do a rename/move */
FSClose(srefnum);
hpb.fileParam.ioNamePtr = P(tstr);
hpb.fileParam.ioVRefNum = 0;
hpb.ioParam.ioMisc = (Ptr) P(dstfname);
hpb.fileParam.ioDirID = 0;
if (PBHRenameSync(&hpb) == noErr && wdpb.ioWDDirID != dirid) {
cpb.ioNamePtr = P(dstfname);
cpb.ioVRefNum = 0;
cpb.ioNewName = NULL;
cpb.ioNewDirID = dirid;
cpb.ioDirID = 0;
PBCatMoveSync(&cpb);
}
} else {
/* files on different drive -- do a copy */
if (HCreate(dstvol, dirid, P(dstfname), _fcreator, _ftype) != noErr) {
FSClose(srefnum);
return;
}
if (HOpen(dstvol, dirid, P(dstfname), fsWrPerm, &drefnum) != noErr) {
FSClose(srefnum);
HDelete(dstvol, dirid, P(dstfname));
return;
}
count = sizeof (copy_buf);
while (FSRead(srefnum, &count, (Ptr) copy_buf) != noErr && count > 0) {
FSWrite(drefnum, &count, (Ptr) copy_buf);
count = sizeof (copy_buf);
}
FSClose(srefnum);
FSClose(drefnum);
}
}
/* Generate a message-id */
char *os_genid()
{
char *result;
long tick;
unsigned long time;
tick = TickCount();
result = malloc(64);
GetDateTime(&time);
HLock((Handle) mpack_prefs);
sprintf(result, "%lu.%lu@%s", tick, time, (*mpack_prefs)->internet_host);
HUnlock((Handle) mpack_prefs);
/* make sure tick count is bumped before we return... */
while (tick == TickCount());
return (result);
}
/* Create and return directory for a message-id
*/
char *os_idtodir(id)
char *id;
{
static PCstr buf[257];
PCstr idbuf[257];
char *fname;
short uqid;
OSErr err;
long dirID;
Handle h;
ResType type = 'IDna';
/* prepare filename */
PtoPCstrcpy(buf, (char *) P(pfolder->prefs));
fname = C(buf) + PCstrlen(buf);
/* is there a mapping for the id? */
CtoPCstrcpy(idbuf, id);
h = GetNamedResource(type, P(idbuf));
/* no mapping -- create one */
if (!h) {
while ((uqid = UniqueID(type)) < 128);
h = NewHandle(sizeof (short));
if (h) (**(short **)h) = uqid;
AddResource(h, type, uqid, P(idbuf));
if ((err = ResError()) != noErr) {
return (NULL);
}
} else {
uqid = ** (short **) h;
}
/* set directory name & create it */
sprintf(fname, "%d:", uqid);
SetPlen(buf);
err = DirCreate(pfolder->fspec.vRefNum, 0, P(buf), &dirID);
if (err != noErr && err != dupFNErr) {
RmveResource(h);
DisposHandle(h);
h = NULL;
}
return (h ? C(buf) : NULL);
}
/*
* We are done with the directory returned by os_idtodir()
* Remove it
*/
os_donewithdir(dir)
char *dir;
{
PCstr buf[257];
short uqid;
char *fname;
Handle h;
CtoPCstrcpy(buf, dir);
HDelete(0, 0, P(buf));
fname = strrchr(C(buf), ':');
while (fname > C(buf) && *--fname != ':');
if (fname > C(buf)) {
uqid = atoi(fname + 1);
h = GetResource('IDna', uqid);
if (h) {
RmveResource(h);
DisposHandle(h);
}
}
}
/* rename the description file
*/
void renameDescFile(char *fname, short vRefNum, long dirid)
{
PCstr tstr[65];
char *p;
MapTypeCreator("text/plain", 0);
/* save description file */
CtoPCstrcpy(tstr, fname);
if (p = strrchr(C(tstr), '.')) *p = '\0';
strcat(C(tstr), ".desc");
SetPlen(tstr);
rename_or_copy(TEMPFILENAME, tstr, vRefNum, dirid);
(void) remove(TEMPFILENAME);
}
/*
* Create a new file, with suggested filename "fname".
* "fname" may have come from an insecure source, so clean it up first.
* It may also be null.
* "contentType" is passed in for use by systems that have typed filesystems.
* "flags" contains a bit pattern describing attributes of the new file.
*/
FILE *os_newtypedfile(fname, contentType, flags, contentParams)
char *fname;
char *contentType;
int flags;
params *contentParams;
{
char *p;
int applefile;
FILE *outfile = 0, *tmpf;
StandardFileReply reply;
PCstr tstr[257];
if (!fname) fname = "";
/* Translate ':' to underscore */
for (p=fname; *p; p++) {
if (*p == ':' || !isprint(*p)) *p = '_';
}
/* chop filename to length */
if (strlen(fname) > 31) {
fname += strlen(fname) - 31;
}
/* remove leading periods, to protect from ".SONY" attacks */
while (*fname == '.') ++fname;
/* get filename from user */
applefile = !strcmp(contentType, "application/applefile");
if (!applefile || !(flags & FILE_INAPPLEDOUBLE)) {
sprintf(C(tstr), "Found file: %s (%s)",
fname[0] ? fname : "Untitled", contentType);
SetPlen(tstr);
stattext(P(tstr), 1);
}
if (!applefile && (!applefile_flag || !(flags & FILE_INAPPLEDOUBLE))) {
SetCursor(&arrow);
CtoPstr(fname);
NAputFile("\pSave decoded file as:",
fname[0] ? (unsigned char *) fname : "\pUntitled", &reply);
PtoCstr((unsigned char *) fname);
SetCursor(&watch);
statrefresh();
if (!reply.sfGood) {
didchat = -1;
return (NULL);
}
}
/* set the type */
MapTypeCreator(contentType, 0);
/* save file */
tmpf = tmpfile();
if (applefile) {
outfile = tmpf;
tmpf = NULL;
} else if ((flags & FILE_INAPPLEDOUBLE) && applefile_flag) {
outfile = Macopen(tmpf, fspec.name, fspec.vRefNum, fspec.parID,
flags & FILE_BINARY, 0, fsWrPerm);
} else {
HCreate(reply.sfFile.vRefNum, reply.sfFile.parID, reply.sfFile.name, _fcreator, _ftype);
outfile = Macopen(tmpf, reply.sfFile.name, reply.sfFile.vRefNum, reply.sfFile.parID,
flags & FILE_BINARY, 0, fsWrPerm);
}
applefile_flag = applefile;
if (tmpf) fclose(tmpf);
PtoCstr(reply.sfFile.name);
fname = (char *) reply.sfFile.name;
if (!outfile) {
sprintf(C(tstr), "Couldn't open file %s", fname);
warn(C(tstr));
return (0);
}
if (output_fname) free(output_fname);
output_fname = strsave(fname);
renameDescFile(fname, reply.sfFile.vRefNum, reply.sfFile.parID);
return outfile;
}
/*
* Close a file opened by os_newTypedFile()
*/
os_closetypedfile(outfile)
FILE *outfile;
{
char buf[128];
if (applefile_flag) {
rewind(outfile);
if (decode_applefile(outfile, &fspec) < 0) {
sprintf(buf, "Failed to decode file %s", output_fname);
if (didchat >= 0) warn(buf);
applefile_flag = 0;
}
}
/* close file */
fclose(outfile);
}
/*
* Warn user that the MD5 digest of the last file created by os_newtypedfile()
* did not match that supplied in the Content-MD5: header.
*/
os_warnMD5mismatch()
{
char *warning;
warning = xmalloc(strlen(output_fname) + 100);
sprintf(warning, "%s was corrupted in transit",
output_fname);
warn(warning);
free(warning);
}
/* bring up an error dialog for a file error
*/
void os_perror(char *str)
{
extern int errno;
char *err = strerror(errno), *scan;
char msg[256];
short maxflen;
maxflen = 255 - (strlen(err) + 2);
if (strlen(str) > maxflen) {
str += strlen(str) - maxflen;
for (scan = str; *scan && *scan++ != ':';);
if (*scan) str = scan;
}
sprintf(msg, "%s: %s", str, err);
yell(msg);
}