1 /* $Id: macstore.c,v 1.11 2003/01/18 20:09:21 ben Exp $ */
4 * macstore.c: Macintosh-specific impementation of the interface
11 #include <Resources.h>
12 #include <TextUtils.h>
23 OSErr
FSpGetDirID(FSSpec
*f
, long *idp
, Boolean makeit
);
26 * We store each session as a file in the "PuTTY" sub-directory of the
27 * preferences folder. Each (key,value) pair is stored as a resource.
30 OSErr
get_putty_dir(Boolean makeit
, short *pVRefNum
, long *pDirID
)
35 long prefDirID
, puttyDirID
;
37 error
= FindFolder(kOnSystemDisk
, kPreferencesFolderType
, makeit
,
38 &prefVRefNum
, &prefDirID
);
39 if (error
!= noErr
) goto out
;
41 error
= FSMakeFSSpec(prefVRefNum
, prefDirID
, "\pPuTTY", &puttydir
);
42 if (error
!= noErr
&& error
!= fnfErr
) goto out
;
43 error
= FSpGetDirID(&puttydir
, &puttyDirID
, makeit
);
44 if (error
!= noErr
) goto out
;
46 *pVRefNum
= prefVRefNum
;
53 OSErr
get_session_dir(Boolean makeit
, short *pVRefNum
, long *pDirID
) {
57 long puttyDirID
, sessDirID
;
59 error
= get_putty_dir(makeit
, &puttyVRefNum
, &puttyDirID
);
60 if (error
!= noErr
) goto out
;
61 error
= FSMakeFSSpec(puttyVRefNum
, puttyDirID
, "\pSaved Sessions",
63 if (error
!= noErr
&& error
!= fnfErr
) goto out
;
64 error
= FSpGetDirID(&sessdir
, &sessDirID
, makeit
);
65 if (error
!= noErr
) goto out
;
67 *pVRefNum
= puttyVRefNum
;
74 OSErr
FSpGetDirID(FSSpec
*f
, long *idp
, Boolean makeit
) {
78 pb
.dirInfo
.ioNamePtr
= f
->name
;
79 pb
.dirInfo
.ioVRefNum
= f
->vRefNum
;
80 pb
.dirInfo
.ioDrDirID
= f
->parID
;
81 pb
.dirInfo
.ioFDirIndex
= 0;
82 error
= PBGetCatInfoSync(&pb
);
83 if (error
== fnfErr
&& makeit
)
84 return FSpDirCreate(f
, smSystemScript
, idp
);
85 if (error
!= noErr
) goto out
;
86 if ((pb
.dirInfo
.ioFlAttrib
& ioDirMask
) == 0) {
90 *idp
= pb
.dirInfo
.ioDrDirID
;
96 /* Copy a resource into the current resource file */
97 static OSErr
copy_resource(ResType restype
, short resid
)
102 fprintf(stderr
, "getting resource %x, id %d\n", restype
, resid
);
103 h
= GetResource(restype
, resid
);
105 GetResInfo(h
, &resid
, &restype
, resname
);
107 AddResource(h
, restype
, resid
, resname
);
108 if (ResError() == noErr
)
111 fprintf(stderr
, "ResError() == %d\n", ResError());
115 struct write_settings
{
121 void *open_settings_w(char const *sessionname
) {
128 error
= get_session_dir(kCreateFolder
, &sessVRefNum
, &sessDirID
);
129 if (error
!= noErr
) return NULL
;
131 c2pstrcpy(psessionname
, sessionname
);
132 error
= FSMakeFSSpec(sessVRefNum
, sessDirID
, psessionname
, &dstfile
);
133 if (error
== fnfErr
) {
134 FSpCreateResFile(&dstfile
, PUTTY_CREATOR
, SESS_TYPE
, smSystemScript
);
135 if ((error
= ResError()) != noErr
) return NULL
;
136 } else if (error
!= noErr
) return NULL
;
138 return open_settings_w_fsp(&dstfile
);
142 * NB: Destination file must exist.
144 void *open_settings_w_fsp(FSSpec
*dstfile
)
148 struct write_settings
*ws
;
152 ws
= smalloc(sizeof *ws
);
153 ws
->dstfile
= *dstfile
;
155 /* Create a temporary file to save to first. */
156 error
= FindFolder(ws
->dstfile
.vRefNum
, kTemporaryFolderType
,
157 kCreateFolder
, &tmpVRefNum
, &tmpDirID
);
158 if (error
!= noErr
) goto out
;
159 c2pstrcpy(tmpname
, tmpnam(NULL
));
160 error
= FSMakeFSSpec(tmpVRefNum
, tmpDirID
, tmpname
, &ws
->tmpfile
);
161 if (error
!= noErr
&& error
!= fnfErr
) goto out
;
162 if (error
== noErr
) {
163 error
= FSpDelete(&ws
->tmpfile
);
164 if (error
!= noErr
) goto out
;
166 FSpCreateResFile(&ws
->tmpfile
, PUTTY_CREATOR
, SESS_TYPE
, smSystemScript
);
167 if ((error
= ResError()) != noErr
) goto out
;
169 ws
->fd
= FSpOpenResFile(&ws
->tmpfile
, fsWrPerm
);
170 if (ws
->fd
== -1) {error
= ResError(); goto out
;}
172 /* Set up standard resources. Doesn't matter if these fail. */
173 copy_resource('STR ', -16396);
174 copy_resource('TMPL', TMPL_Int
);
180 fatalbox("Failed to open session for write (%d)", error
);
183 void write_setting_s(void *handle
, char const *key
, char const *value
) {
184 int fd
= *(int *)handle
;
190 if (ResError() != noErr
)
191 fatalbox("Failed to open saved session (%d)", ResError());
193 error
= PtrToHand(value
, &h
, strlen(value
));
195 fatalbox("Failed to allocate memory");
196 /* Put the data in a resource. */
197 id
= Unique1ID(FOUR_CHAR_CODE('TEXT'));
198 if (ResError() != noErr
)
199 fatalbox("Failed to get ID for resource %s (%d)", key
, ResError());
200 addresource(h
, FOUR_CHAR_CODE('TEXT'), id
, key
);
201 if (ResError() != noErr
)
202 fatalbox("Failed to add resource %s (%d)", key
, ResError());
205 void write_setting_i(void *handle
, char const *key
, int value
) {
206 int fd
= *(int *)handle
;
212 if (ResError() != noErr
)
213 fatalbox("Failed to open saved session (%d)", ResError());
215 /* XXX assume all systems have the same "int" format */
216 error
= PtrToHand(&value
, &h
, sizeof(int));
218 fatalbox("Failed to allocate memory (%d)", error
);
220 /* Put the data in a resource. */
221 id
= Unique1ID(FOUR_CHAR_CODE('Int '));
222 if (ResError() != noErr
)
223 fatalbox("Failed to get ID for resource %s (%d)", key
, ResError());
224 addresource(h
, FOUR_CHAR_CODE('Int '), id
, key
);
225 if (ResError() != noErr
)
226 fatalbox("Failed to add resource %s (%d)", key
, ResError());
229 void close_settings_w(void *handle
) {
230 struct write_settings
*ws
= handle
;
233 CloseResFile(ws
->fd
);
234 if ((error
= ResError()) != noErr
)
236 error
= FSpExchangeFiles(&ws
->tmpfile
, &ws
->dstfile
);
237 if (error
!= noErr
) goto out
;
238 error
= FSpDelete(&ws
->tmpfile
);
239 if (error
!= noErr
) goto out
;
243 fatalbox("Close of saved session failed (%d)", error
);
247 void *open_settings_r(char const *sessionname
)
255 error
= get_session_dir(kDontCreateFolder
, &sessVRefNum
, &sessDirID
);
257 c2pstrcpy(psessionname
, sessionname
);
258 error
= FSMakeFSSpec(sessVRefNum
, sessDirID
, psessionname
, &sessfile
);
259 if (error
!= noErr
) goto out
;
260 return open_settings_r_fsp(&sessfile
);
266 void *open_settings_r_fsp(FSSpec
*sessfile
)
272 fd
= FSpOpenResFile(sessfile
, fsRdPerm
);
273 if (fd
== 0) {error
= ResError(); goto out
;}
275 handle
= safemalloc(sizeof *handle
);
283 char *read_setting_s(void *handle
, char const *key
, char *buffer
, int buflen
) {
288 if (handle
== NULL
) goto out
;
291 if (ResError() != noErr
) goto out
;
292 h
= get1namedresource(FOUR_CHAR_CODE('TEXT'), key
);
293 if (h
== NULL
) goto out
;
295 len
= GetHandleSize(h
);
296 if (len
+ 1 > buflen
) goto out
;
297 memcpy(buffer
, *h
, len
);
301 if (ResError() != noErr
) goto out
;
308 int read_setting_i(void *handle
, char const *key
, int defvalue
) {
313 if (handle
== NULL
) goto out
;
316 if (ResError() != noErr
) goto out
;
317 h
= get1namedresource(FOUR_CHAR_CODE('Int '), key
);
318 if (h
== NULL
) goto out
;
321 if (ResError() != noErr
) goto out
;
328 void close_settings_r(void *handle
) {
331 if (handle
== NULL
) return;
334 if (ResError() != noErr
)
335 fatalbox("Close of saved session failed (%d)", ResError());
339 void del_settings(char const *sessionname
) {
346 error
= get_session_dir(kDontCreateFolder
, &sessVRefNum
, &sessDirID
);
348 c2pstrcpy(psessionname
, sessionname
);
349 error
= FSMakeFSSpec(sessVRefNum
, sessDirID
, psessionname
, &sessfile
);
350 if (error
!= noErr
) goto out
;
352 error
= FSpDelete(&sessfile
);
355 fatalbox("Delete session failed (%d)", error
);
358 struct enum_settings_state
{
364 void *enum_settings_start(void) {
366 struct enum_settings_state
*state
;
368 state
= safemalloc(sizeof(*state
));
369 error
= get_session_dir(kDontCreateFolder
, &state
->vRefNum
, &state
->dirID
);
370 if (error
!= noErr
) {
378 char *enum_settings_next(void *handle
, char *buffer
, int buflen
) {
379 struct enum_settings_state
*e
= handle
;
384 if (e
== NULL
) return NULL
;
386 pb
.hFileInfo
.ioNamePtr
= name
;
387 pb
.hFileInfo
.ioVRefNum
= e
->vRefNum
;
388 pb
.hFileInfo
.ioDirID
= e
->dirID
;
389 pb
.hFileInfo
.ioFDirIndex
= e
->index
++;
390 error
= PBGetCatInfoSync(&pb
);
391 if (error
!= noErr
) return NULL
;
392 } while (!((pb
.hFileInfo
.ioFlAttrib
& ioDirMask
) == 0 &&
393 pb
.hFileInfo
.ioFlFndrInfo
.fdCreator
== PUTTY_CREATOR
&&
394 pb
.hFileInfo
.ioFlFndrInfo
.fdType
== SESS_TYPE
&&
397 p2cstrcpy(buffer
, name
);
401 void enum_settings_finish(void *handle
) {
406 #define SEED_SIZE 512
408 void read_random_seed(noise_consumer_t consumer
)
415 long count
= SEED_SIZE
;
417 if (get_putty_dir(kDontCreateFolder
, &puttyVRefNum
, &puttyDirID
) != noErr
)
419 if (HOpenDF(puttyVRefNum
, puttyDirID
, "\pPuTTY Random Seed", fsRdPerm
,
422 error
= FSRead(refnum
, &count
, buf
);
423 if (error
!= noErr
&& error
!= eofErr
)
425 (*consumer
)(buf
, count
);
430 * We don't bother with the usual FSpExchangeFiles dance here because
431 * it doesn't really matter if the old random seed gets lost.
433 void write_random_seed(void *data
, int len
)
442 if (get_putty_dir(kCreateFolder
, &puttyVRefNum
, &puttyDirID
) != noErr
)
445 error
= FSMakeFSSpec(puttyVRefNum
, puttyDirID
, "\pPuTTY Random Seed",
447 if (error
== fnfErr
) {
448 /* Set up standard resources */
449 FSpCreateResFile(&dstfile
, INTERNAL_CREATOR
, SEED_TYPE
, smRoman
);
450 refnum
= FSpOpenResFile(&dstfile
, fsWrPerm
);
451 if (ResError() == noErr
) {
452 copy_resource('STR ', -16397);
453 CloseResFile(refnum
);
455 } else if (error
!= noErr
) return;
457 if (FSpOpenDF(&dstfile
, fsWrPerm
, &refnum
) != noErr
) return;
458 FSWrite(refnum
, &count
, data
);
467 * c-file-style: "simon"