Rather more natural (if much more complex) Mac Filename implementation.
authorben <ben@cda61777-01e9-0310-a592-d414129be87e>
Sat, 1 Feb 2003 21:44:05 +0000 (21:44 +0000)
committerben <ben@cda61777-01e9-0310-a592-d414129be87e>
Sat, 1 Feb 2003 21:44:05 +0000 (21:44 +0000)
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
mac/macstore.c
mac/macstuff.h

index 50d3199..cea87fb 100644 (file)
--- 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;
 }
 
 /*
index 57ed772..244569e 100644 (file)
@@ -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) {
index 1193e00..c072885 100644 (file)
@@ -5,17 +5,21 @@
 typedef void *Context; /* FIXME */
 
 #include <MacTypes.h>
-#include <stdio.h>                    /* for FILENAME_MAX */
+#include <Files.h>
+
+#include <stdio.h>
 
 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;
 };