From 02cf40019f8ae19176a73f9220603cc9e28d5224 Mon Sep 17 00:00:00 2001 From: ben Date: Sat, 1 Feb 2003 21:44:05 +0000 Subject: [PATCH] Rather more natural (if much more complex) Mac Filename implementation. Filenames are represented as a FSSpec, which is converted to and from an alias record ('alis' resource) when saving and loading sessions. . It might be an idea to allow in-core Filenames to contain alias records too, so that they can refer to directories that don't exist on the current system, but that requires Filenames to be dynamically allocated, which is likely to be a pain. git-svn-id: svn://svn.tartarus.org/sgt/putty@2771 cda61777-01e9-0310-a592-d414129be87e --- mac/mac.c | 72 +++++++++++++++++++++++++++++++++++++++++------ mac/macstore.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- mac/macstuff.h | 10 +++++-- 3 files changed, 155 insertions(+), 15 deletions(-) diff --git a/mac/mac.c b/mac/mac.c index 50d3199c..cea87fbf 100644 --- a/mac/mac.c +++ b/mac/mac.c @@ -1,4 +1,4 @@ -/* $Id: mac.c,v 1.40 2003/02/01 17:24:26 simon Exp $ */ +/* $Id: mac.c,v 1.41 2003/02/01 21:44:05 ben Exp $ */ /* * Copyright (c) 1999 Ben Harris * All rights reserved. @@ -771,9 +771,9 @@ Filename platform_default_filename(const char *name) { Filename ret; if (!strcmp(name, "LogFileName")) - strcpy(ret.path, "putty.log"); + FSMakeFSSpec(0, 0, "\pputty.log", &ret.fss); else - *ret.path = '\0'; + memset(&ret, 0, sizeof(ret)); return ret; } @@ -804,24 +804,80 @@ void platform_get_x11_auth(char *display, int *proto, Filename filename_from_str(const char *str) { Filename ret; - strncpy(ret.path, str, sizeof(ret.path)); - ret.path[sizeof(ret.path)-1] = '\0'; + Str255 tmp; + + /* XXX This fails for filenames over 255 characters long. */ + c2pstrcpy(tmp, str); + FSMakeFSSpec(0, 0, tmp, &ret.fss); return ret; } +/* + * Convert a filename to a string for display purposes. + * See pp 2-44--2-46 of IM:Files + * + * XXX static storage considered harmful + */ const char *filename_to_str(const Filename *fn) { - return fn->path; + CInfoPBRec pb; + Str255 dirname; + OSErr err; + static char *path = NULL; + char *newpath; + + if (path != NULL) sfree(path); + path = smalloc(fn->fss.name[0]); + p2cstrcpy(path, fn->fss.name); + pb.dirInfo.ioNamePtr = dirname; + pb.dirInfo.ioVRefNum = fn->fss.vRefNum; + pb.dirInfo.ioDrParID = fn->fss.parID; + pb.dirInfo.ioFDirIndex = -1; + do { + pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID; + err = PBGetCatInfoSync(&pb); + + /* XXX Assume not A/UX */ + newpath = smalloc(strlen(path) + dirname[0] + 2); + p2cstrcpy(newpath, dirname); + strcat(newpath, ":"); + strcat(newpath, path); + sfree(path); + path = newpath; + } while (pb.dirInfo.ioDrDirID != fsRtDirID); + return path; } int filename_equal(Filename f1, Filename f2) { - return !strcmp(f1.path, f2.path); + + return f1.fss.vRefNum == f2.fss.vRefNum && + f1.fss.parID == f2.fss.parID && + f1.fss.name[0] == f2.fss.name[0] && + memcmp(f1.fss.name + 1, f2.fss.name + 1, f1.fss.name[0]) == 0; } int filename_is_null(Filename fn) { - return !*fn.path; + + return fn.fss.vRefNum == 0 && fn.fss.parID == 0 && fn.fss.name[0] == 0; +} + +FILE *f_open(Filename fn, char const *mode) +{ + short savevol; + long savedir; + char tmp[256]; + FILE *ret; + + HGetVol(NULL, &savevol, &savedir); + if (HSetVol(NULL, fn.fss.vRefNum, fn.fss.parID) == noErr) { + p2cstrcpy(tmp, fn.fss.name); + ret = fopen(tmp, mode); + } else + ret = NULL; + HSetVol(NULL, savevol, savedir); + return ret; } /* diff --git a/mac/macstore.c b/mac/macstore.c index 57ed7721..244569e9 100644 --- a/mac/macstore.c +++ b/mac/macstore.c @@ -1,4 +1,4 @@ -/* $Id: macstore.c,v 1.14 2003/02/01 15:44:08 ben Exp $ */ +/* $Id: macstore.c,v 1.15 2003/02/01 21:44:05 ben Exp $ */ /* * macstore.c: Macintosh-specific impementation of the interface @@ -360,12 +360,92 @@ void write_setting_fontspec(void *handle, const char *name, FontSpec font) int read_setting_filename(void *handle, const char *name, Filename *result) { - return !!read_setting_s(handle, name, result->path, sizeof(result->path)); + int fd; + AliasHandle h; + Boolean changed; + OSErr err; + + if (handle == NULL) goto out; + fd = *(int *)handle; + UseResFile(fd); + if (ResError() != noErr) goto out; + h = (AliasHandle)get1namedresource(rAliasType, name); + if (h == NULL) goto out; + if ((*h)->userType == 'pTTY' && (*h)->aliasSize == sizeof(**h)) + memset(result, 0, sizeof(*result)); + else { + err = ResolveAlias(NULL, h, &result->fss, &changed); + if (err != noErr && err != fnfErr) goto out; + if ((*h)->userType == 'pTTY') { + long dirid; + StrFileName fname; + + /* Tail of record is pascal string contaning leafname */ + if (FSpGetDirID(&result->fss, &dirid, FALSE) != noErr) goto out; + memcpy(fname, (char *)*h + (*h)->aliasSize, + GetHandleSize((Handle)h) - (*h)->aliasSize); + err = FSMakeFSSpec(result->fss.vRefNum, dirid, fname, + &result->fss); + if (err != noErr && err != fnfErr) goto out; + } + } + ReleaseResource((Handle)h); + if (ResError() != noErr) goto out; + return 1; + + out: + return 0; } -void write_setting_filename(void *handle, const char *name, Filename result) +void write_setting_filename(void *handle, const char *name, Filename fn) { - write_setting_s(handle, name, result.path); + int fd = *(int *)handle; + AliasHandle h; + int id; + OSErr error; + + UseResFile(fd); + if (ResError() != noErr) + fatalbox("Failed to open saved session (%d)", ResError()); + + if (filename_is_null(fn)) { + /* Generate a special "null" alias */ + h = (AliasHandle)NewHandle(sizeof(**h)); + if (h == NULL) + fatalbox("Failed to create fake alias"); + (*h)->userType = 'pTTY'; + (*h)->aliasSize = sizeof(**h); + } else { + error = NewAlias(NULL, &fn.fss, &h); + if (error == fnfErr) { + /* + * NewAlias can't create an alias for a nonexistent file. + * Create an alias for the directory, and record the + * filename as well. + */ + FSSpec tmpfss; + + FSMakeFSSpec(fn.fss.vRefNum, fn.fss.parID, NULL, &tmpfss); + error = NewAlias(NULL, &tmpfss, &h); + if (error != noErr) + fatalbox("Failed to create alias"); + (*h)->userType = 'pTTY'; + SetHandleSize((Handle)h, (*h)->aliasSize + fn.fss.name[0] + 1); + if (MemError() != noErr) + fatalbox("Failed to create alias"); + memcpy((char *)*h + (*h)->aliasSize, fn.fss.name, + fn.fss.name[0] + 1); + } + if (error != noErr) + fatalbox("Failed to create alias"); + } + /* Put the data in a resource. */ + id = Unique1ID(rAliasType); + if (ResError() != noErr) + fatalbox("Failed to get ID for resource %s (%d)", name, ResError()); + addresource((Handle)h, rAliasType, id, name); + if (ResError() != noErr) + fatalbox("Failed to add resource %s (%d)", name, ResError()); } void close_settings_r(void *handle) { diff --git a/mac/macstuff.h b/mac/macstuff.h index 1193e005..c0728859 100644 --- a/mac/macstuff.h +++ b/mac/macstuff.h @@ -5,17 +5,21 @@ typedef void *Context; /* FIXME */ #include -#include /* for FILENAME_MAX */ +#include + +#include struct Filename { - char path[FILENAME_MAX]; + FSSpec fss; }; -#define f_open(filename, mode) ( fopen((filename).path, (mode)) ) + +extern FILE * f_open(struct Filename, char const *); /* Suspiciously similar to an ICFontRecord */ struct FontSpec { short size; Style face; + char pad; Str255 name; }; -- 2.11.0