Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6725 siemargl 1
/****************************************************************
2
    MacBinaryIII.c
3
 
4
    Copyright  1997 Christopher Evans (cevans@poppybank.com)
5
 
6
    Basic encoding and decoding of Macintosh files to the
7
    MacBinary III spec.
8
 
9
 This file is part of the MacBinaryIII_src_C.sit package
10
 see macbin3.h for more information
11
 
12
****************************************************************/
13
 
14
/*****************************************************************************/
15
/*  Includes                                                                 */
16
/*****************************************************************************/
17
 
18
#include 
19
#include 
20
#include "macbin3.h"
21
 
22
/*****************************************************************************/
23
/*  Macros, typedefs                                                         */
24
/*****************************************************************************/
25
 
26
/* source (the macbinary file) will be deleted */
27
#define DELETE_MACBINARY_SOURCE
28
 
29
/* enable encoding
30
#define INCLUDE_ENCODE_MACBINARY         */
31
 
32
/* enable decoding */
33
#define INCLUDE_DECODE_MACBINARY
34
 
35
/* include own CRC 32 Bit Calculation
36
#define INCLUDE_CRC32CALC               */
37
 
38
/* produce some helpful printouts for tracing
39
#define TRACE_MACBINARY   */
40
 
41
 
42
 
43
#define LONG_AT_OFFSET(data, offset) *((long *)((unsigned char *)&data[offset]))
44
#define WORD_AT_OFFSET(data, offset) *((Word *)((unsigned char *)&data[offset]))
45
#define BYTE_AT_OFFSET(data, offset) *((Byte *)((unsigned char *)&data[offset]))
46
#define PTR_AT_OFFSET(data, offset)  ((Ptr)((unsigned char *)&data[offset]))
47
 
48
typedef     unsigned short      Word;
49
 
50
#define kOldVersionOffset               0
51
#define kFileNameLengthOffset           1
52
#define kFileNameOffset                 2
53
#define kFileTypeOffset                 65
54
#define kFileCreatorOffset              69
55
#define kFinderFlagsHiOffset            73
56
#define kVersionCheckZero               74
57
#define kFileVPositionOffset            75
58
#define kFileHPositionOffset            77
59
#define kFileFolderIDOffset             79
60
#define kProtectedFlagOffset            81
61
#define kVersionOneCheckZero            82
62
#define kDataForkLengthOffset           83
63
#define kResourceForkLengthOffset       87
64
#define kFileCreationDateOffset         91
65
#define kFileModificationDateOffset     95
66
#define kGetInfoCommentLengthOffset     99
67
#define kFinderFlagsLowOffset           101
68
#define kMacbinarySigOffset             102
69
#define kFilenameScriptOffset           106
70
#define kExtendedFinderFlagsOffset      107
71
#define kTotalFileLengthOffset          116
72
#define kSecondaryHeaderLengthOffset    120
73
#define kCurrentVersionOffset           122
74
#define kMinimumVersionOffset           123
75
#define kCRCOffset                      124
76
 
77
#define kResourceForkMaxLen             (1024 * 1024 * 16)
78
 
79
 
80
/*****************************************************************************/
81
/*  Module level Vars                                                        */
82
/*****************************************************************************/
83
 
84
#ifdef INCLUDE_CRC32CALC
85
static unsigned long crc_table[256] = {
86
  0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
87
  0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
88
  0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
89
  0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
90
  0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
91
  0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
92
  0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
93
  0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
94
  0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
95
  0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
96
  0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
97
  0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
98
  0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
99
  0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
100
  0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
101
  0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
102
  0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
103
  0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
104
  0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
105
  0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
106
  0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
107
  0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
108
  0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
109
  0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
110
  0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
111
  0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
112
  0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
113
  0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
114
  0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
115
  0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
116
  0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
117
  0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
118
  0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
119
  0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
120
  0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
121
  0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
122
  0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
123
  0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
124
  0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
125
  0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
126
  0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
127
  0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
128
  0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
129
  0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
130
  0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
131
  0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
132
  0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
133
  0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
134
  0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
135
  0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
136
  0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
137
  0x2d02ef8dL
138
};
139
#endif
140
 
141
 
142
/*****************************************************************************/
143
/*  Prototypes                                                               */
144
/*****************************************************************************/
145
 
146
static Boolean  HeaderIsMacBinary(char *header,
147
                                  Word *version,
148
                                  long maxDataLen);
149
static Boolean FSpExists(FSSpec *file);
150
#ifdef INCLUDE_CRC32CALC
151
static unsigned long crc32(unsigned long seed, unsigned char *p, size_t len);
152
#else
153
extern unsigned long crc32(unsigned long seed, unsigned char *p, size_t len);
154
#endif
155
static OSErr GetDesktopComment(FSSpec *file, char*comment, long *length);
156
static OSErr SetDesktopComment(FSSpec *file, char*comment, long length);
157
static Handle  EncodeMacbinary(FSSpec *file);
158
static OSErr   DecodeMacBinary(Handle data, FSSpec *destination);
159
 
160
/*****************************************************************************/
161
/*  Functions                                                                */
162
/*****************************************************************************/
163
 
164
 
165
#ifdef INCLUDE_CRC32CALC
166
/* taken from the mcvert source code */
167
static unsigned long crc32(unsigned long seed, unsigned char *p, size_t len)
168
{
169
    unsigned long hold;     /* crc computed so far */
170
    size_t i;               /* index into data */
171
 
172
    hold = seed;                   /* start with seed */
173
    for (i = 0; i < len; i++, p++)
174
        {
175
        hold ^= (*p << 8);
176
        hold  = (hold << 8) ^ crc_table[(unsigned char) (hold >> 8)];
177
        }
178
 
179
    return (hold);
180
}               /* crc32() */
181
#endif
182
 
183
 
184
 
185
static Boolean FSpExists(FSSpec *file)
186
{
187
    FInfo   fndrInfo;
188
 
189
    return FSpGetFInfo(file, &fndrInfo) == noErr;
190
}
191
 
192
 
193
static Boolean  HeaderIsMacBinary(char *header,
194
                                  Word *version,
195
                                  long maxDataLen)
196
{
197
    Boolean isIt = false;
198
    unsigned long resourceForkLength, dataForkLength, df_rf_length;
199
    short commentLength;
200
    Byte    mbVersion;
201
 
202
#ifdef TRACE_MACBINARY
203
printf("\n\n Function HeaderIsMacBinary(): ");
204
#endif
205
 
206
    if(LONG_AT_OFFSET(header, kMacbinarySigOffset) == 'mBIN')
207
        {
208
        isIt = true;
209
        mbVersion = 130;
210
        }
211
    else
212
        if(BYTE_AT_OFFSET(header, kVersionCheckZero) == 0 &&
213
            BYTE_AT_OFFSET(header, kOldVersionOffset) == 0)
214
            {
215
            if(WORD_AT_OFFSET(header, kCRCOffset) ==
216
               crc32(0, (unsigned char*) &header, 124))
217
                {
218
                isIt = true;
219
                mbVersion = 129;
220
                }
221
            else
222
                {
223
                if(BYTE_AT_OFFSET(header, kVersionOneCheckZero) == 0)
224
                    {
225
                    isIt = true;
226
                    mbVersion = 128;
227
                    }
228
                }
229
            }
230
 
231
#ifdef TRACE_MACBINARY
232
printf("\n           mbVersion: %d",mbVersion);
233
#endif
234
 
235
    resourceForkLength = LONG_AT_OFFSET(header, kResourceForkLengthOffset);
236
    dataForkLength     = LONG_AT_OFFSET(header, kDataForkLengthOffset);
237
    commentLength      = WORD_AT_OFFSET(header, kGetInfoCommentLengthOffset);
238
    df_rf_length = dataForkLength + resourceForkLength;
239
 
240
#ifdef TRACE_MACBINARY
241
printf("\n  resourceForkLength: %d",resourceForkLength);
242
printf("\n      dataForkLength: %d",dataForkLength);
243
printf("\n       commentLength: %d",commentLength);
244
printf("\n        df_rf_length: %d",df_rf_length);
245
printf("\n                                                 1. isIt: bool: %d",
246
       isIt);
247
printf("\n BYTE_AT_OFFSET(header, kFileNameLengthOffset) >= 1       bool: %d",
248
       BYTE_AT_OFFSET(header, kFileNameLengthOffset) >= 1);
249
printf("\n BYTE_AT_OFFSET(header, kFileNameLengthOffset) <= 31      bool: %d",
250
       BYTE_AT_OFFSET(header, kFileNameLengthOffset) <= 31);
251
printf("\n dataForkLength >= 0                                      bool: %d",
252
       dataForkLength >= 0);
253
printf("\n resourceForkLength >= 0                                  bool: %d",
254
       resourceForkLength >= 0);
255
printf("\n resourceForkLength <= 0x%8x                         bool: %d",
256
       kResourceForkMaxLen, resourceForkLength <= kResourceForkMaxLen);
257
printf("\n dataForkLength     <= %8u                           bool: %d",
258
       maxDataLen, dataForkLength <= maxDataLen);
259
printf("\n df_rf_length        > 0                                  bool: %d",
260
       df_rf_length > 0);
261
printf("\n df_rf_length       <= %8u                           bool: %d",
262
       maxDataLen, df_rf_length <= maxDataLen);
263
#endif
264
 
265
    if(isIt                                                &&
266
       BYTE_AT_OFFSET(header, kFileNameLengthOffset) >=  1 &&
267
       BYTE_AT_OFFSET(header, kFileNameLengthOffset) <= 31 &&
268
       dataForkLength     >= 0                             &&
269
       resourceForkLength >= 0                             &&
270
       resourceForkLength <= kResourceForkMaxLen           &&
271
       df_rf_length       > 0                              &&
272
       df_rf_length       <= maxDataLen)
273
        {
274
        isIt = true;
275
        }
276
    else
277
        isIt = false;   /* something is wrong with the header */
278
 
279
#ifdef TRACE_MACBINARY
280
printf("\n                                                 2. isIt: bool: %d",
281
       isIt);
282
#endif
283
 
284
    if(version)
285
        *version = mbVersion;
286
    return isIt;
287
}
288
 
289
 
290
 
291
Boolean FSpIsMacBinary(FSSpec *file)
292
{
293
    char header[128];
294
    short dfRefNum = 0;
295
    OSErr   err;
296
    long    size;
297
    Boolean isIt = false;
298
    CInfoPBRec  pb;
299
    long maxDataLen;
300
 
301
    memset(&pb, 0, sizeof(CInfoPBRec));
302
    pb.hFileInfo.ioNamePtr   = file->name;
303
    pb.hFileInfo.ioVRefNum   = file->vRefNum;
304
    pb.hFileInfo.ioFDirIndex = 0;           /*  query a file */
305
    pb.hFileInfo.ioDirID     = file->parID;
306
    err = PBGetCatInfo(&pb,false);
307
    maxDataLen = pb.hFileInfo.ioFlLgLen;
308
 
309
    memset(header, 0, 128);
310
 
311
    err = FSpOpenDF(file, fsRdPerm, &dfRefNum);
312
    if(!err)
313
        {
314
        err = GetEOF(dfRefNum, &size);
315
        if(size > 128)
316
            {
317
            size = 128;
318
            err = FSRead(dfRefNum, &size, &header);
319
 
320
            if(err == noErr)
321
                {
322
                isIt = HeaderIsMacBinary(header, nil, maxDataLen);
323
                }
324
            }
325
        FSClose(dfRefNum);
326
        }
327
    return isIt;
328
}
329
 
330
 
331
 
332
#ifdef INCLUDE_ENCODE_MACBINARY
333
 
334
static OSErr    GetDesktopComment(FSSpec *file, char*comment, long *length)
335
{
336
    DTPBRec     pb;
337
    OSErr       err;
338
 
339
    pb.ioCompletion = nil;
340
    pb.ioNamePtr = NULL;
341
    pb.ioVRefNum = file->vRefNum;
342
 
343
    err = PBDTGetPath(&pb);
344
 
345
    if(err == noErr)
346
        {
347
        pb.ioNamePtr = file->name;
348
        pb.ioDTBuffer = comment;
349
        pb.ioDirID = file->parID;
350
        err = PBDTGetComment(&pb, false);
351
        *length = pb.ioDTActCount;
352
        }
353
    return err;
354
}
355
 
356
 
357
 
358
 
359
OSErr   EncodeMacbinaryFile(FSSpec *file)
360
{
361
    Handle data;
362
    OSErr   err = paramErr;
363
    short   dfRefNum;
364
 
365
    data = EncodeMacbinary(file);
366
 
367
    if(data)
368
        {
369
        if(file->name[0] > 27)
370
            file->name[0] = 27;
371
 
372
        PtoCstr(file->name);
373
        strcat((char*)file->name, ".bin");
374
        CtoPstr((char *)file->name);
375
 
376
        FSpDelete(file);
377
        if(FSpCreate(file, 'dMB3', 'mBIN', smSystemScript) == noErr)
378
            {
379
            err = FSpOpenDF(file, fsWrPerm, &dfRefNum);
380
            if(err == noErr)
381
                {
382
                long    inOutCount = GetHandleSize(data);
383
 
384
                HLock(data);
385
                err = FSWrite(dfRefNum,&inOutCount,*data);
386
                HUnlock(data);
387
                FSClose(dfRefNum);
388
                }
389
            }
390
        DisposeHandle(data);
391
        }
392
    return err;
393
}
394
 
395
 
396
 
397
 
398
 
399
static Handle EncodeMacbinary(FSSpec *file)
400
{
401
    Handle result = nil;
402
    FInfo   fndrInfo;
403
    FXInfo  fndrXInfo;
404
    OSErr   err;
405
    CInfoPBRec  pb;
406
    short   dfRefNum, rfRefNum;
407
    long    ioCount;
408
    char    buffer[128];
409
    char    header[128];
410
    char    comment[256];
411
    long    resourceForkLength, dataForkLength, commentLength;
412
 
413
    memset(&header, 0, sizeof(header));
414
    err = FSpGetFInfo(file, &fndrInfo);
415
 
416
    memset(&pb, 0, sizeof(CInfoPBRec));
417
    pb.hFileInfo.ioNamePtr = file->name;
418
    pb.hFileInfo.ioVRefNum = file->vRefNum;
419
    pb.hFileInfo.ioFDirIndex = 0;           //query a file
420
    pb.hFileInfo.ioDirID = file->parID;
421
    err = PBGetCatInfo(&pb,false);
422
 
423
    fndrXInfo = pb.hFileInfo.ioFlXFndrInfo;
424
 
425
    BYTE_AT_OFFSET(header, kFileNameLengthOffset) = file->name[0];
426
    BlockMoveData( &(file->name[1]),
427
                   PTR_AT_OFFSET(header,
428
                   kFileNameOffset),
429
                   file->name[0]);
430
    LONG_AT_OFFSET(header, kFileTypeOffset)    = fndrInfo.fdType;
431
    LONG_AT_OFFSET(header, kFileCreatorOffset) = fndrInfo.fdCreator;
432
 
433
    BYTE_AT_OFFSET(header, kFinderFlagsHiOffset) =
434
                                          (fndrInfo.fdFlags & 0xFF00) >> 8;
435
    BYTE_AT_OFFSET(header, kFinderFlagsLowOffset) =
436
                                          (fndrInfo.fdFlags & 0x00FF);
437
 
438
    WORD_AT_OFFSET(header, kFileVPositionOffset) = fndrInfo.fdLocation.v;
439
    WORD_AT_OFFSET(header, kFileHPositionOffset) = fndrInfo.fdLocation.h;
440
    WORD_AT_OFFSET(header, kFileFolderIDOffset)  = fndrInfo.fdFldr;
441
 
442
    LONG_AT_OFFSET(header, kFileCreationDateOffset) = pb.hFileInfo.ioFlCrDat;
443
    LONG_AT_OFFSET(header, kFileModificationDateOffset) =
444
                                                      pb.hFileInfo.ioFlMdDat;
445
 
446
    LONG_AT_OFFSET(header, kMacbinarySigOffset)        = 'mBIN';
447
    BYTE_AT_OFFSET(header, kFilenameScriptOffset)      = fndrXInfo.fdScript;
448
    BYTE_AT_OFFSET(header, kExtendedFinderFlagsOffset) = fndrXInfo.fdXFlags;
449
 
450
    LONG_AT_OFFSET(header, kTotalFileLengthOffset) = 0;
451
    WORD_AT_OFFSET(header, kSecondaryHeaderLengthOffset) = 0;
452
 
453
    WORD_AT_OFFSET(header, kCurrentVersionOffset) = 130;
454
    WORD_AT_OFFSET(header, kMinimumVersionOffset) = 129;
455
 
456
    err = FSpOpenDF(file,fsRdPerm,&dfRefNum);
457
    if(err == noErr)
458
        {
459
        err = GetEOF(dfRefNum,&dataForkLength);
460
        LONG_AT_OFFSET(header, kDataForkLengthOffset) = dataForkLength;
461
        }
462
    else
463
        {
464
        dfRefNum = 0;
465
        }
466
 
467
    err = FSpOpenRF(file,fsRdPerm,&rfRefNum);
468
    if(err == noErr)
469
        {
470
        err = GetEOF(rfRefNum,&resourceForkLength);
471
        LONG_AT_OFFSET(header, kResourceForkLengthOffset) = resourceForkLength;
472
        }
473
    else
474
        {
475
        rfRefNum = 0;
476
        }
477
 
478
    memset(comment, 0, 256);
479
    if(GetDesktopComment(file, comment, &commentLength) != noErr)
480
        commentLength = 0;
481
 
482
    WORD_AT_OFFSET(header, kGetInfoCommentLengthOffset) = commentLength;
483
    WORD_AT_OFFSET(header, kCRCOffset) =
484
                                     crc32( 0, (unsigned char*) &header, 124);
485
 
486
    result = TempNewHandle(0, &err);
487
    if(result)
488
        {
489
        err = PtrAndHand(&header,result,128);
490
 
491
        if(dfRefNum && dataForkLength)
492
            {
493
            err = noErr;
494
            while(dataForkLength > 0 && err == noErr)
495
                {
496
                ioCount = 128;
497
                err = FSRead(dfRefNum,&ioCount,&buffer);
498
 
499
                if(err == noErr || err == eofErr)
500
                    err = PtrAndHand(&buffer,result,128);
501
 
502
                dataForkLength -= ioCount;
503
                }
504
            }
505
 
506
        if(rfRefNum && resourceForkLength)
507
            {
508
            err = noErr;
509
            while(resourceForkLength > 0 && err == noErr)
510
                {
511
                ioCount = 128;
512
                err = FSRead(rfRefNum,&ioCount,&buffer);
513
 
514
                if(err == noErr || err == eofErr)
515
                    err = PtrAndHand(&buffer,result,128);
516
 
517
                resourceForkLength -= ioCount;
518
                }
519
            }
520
 
521
        if(commentLength)
522
            {
523
            PtrAndHand(&comment,result,commentLength);
524
            }
525
        }
526
 
527
    if(rfRefNum)
528
        FSClose(rfRefNum);
529
 
530
    if(dfRefNum)
531
        FSClose(dfRefNum);
532
 
533
    return result;
534
}
535
 
536
#endif /* INCLUDE_ENCODE_MACBINARY */
537
 
538
 
539
 
540
#ifdef INCLUDE_DECODE_MACBINARY
541
 
542
static OSErr    SetDesktopComment(FSSpec *file, char*comment, long length)
543
{
544
    DTPBRec     pb;
545
    OSErr       err;
546
 
547
    pb.ioCompletion = nil;
548
    pb.ioNamePtr = NULL;
549
    pb.ioVRefNum = file->vRefNum;
550
 
551
    err = PBDTGetPath(&pb);
552
 
553
    if(err == noErr)
554
        {
555
        pb.ioNamePtr    = file->name;
556
        pb.ioDTBuffer   = comment;
557
        pb.ioDirID      = file->parID;
558
        pb.ioDTReqCount = length;
559
        err = PBDTSetComment(&pb, false);
560
        }
561
    return err;
562
}
563
 
564
 
565
 
566
 
567
OSErr   DecodeMacBinaryFile(FSSpec *source)
568
{
569
    Handle  data = nil;
570
    OSErr   err;
571
    short   dfRefNum = 0;
572
    long    size;
573
    FSSpec  McBin_source;
574
 
575
    memcpy(McBin_source.name,source->name,source->name[0]+1);
576
    McBin_source.vRefNum = source->vRefNum;
577
    McBin_source.parID   = source->parID;
578
 
579
    err = FSpOpenDF(source, fsRdPerm, &dfRefNum);
580
    if(!err)
581
        {
582
        err = GetEOF(dfRefNum, &size);
583
 
584
        data = TempNewHandle(size, &err);
585
 
586
        if(data)
587
            {
588
            HLock(data);
589
            err = FSRead(dfRefNum,&size,*data);
590
            HUnlock(data);
591
            }
592
        FSClose(dfRefNum);
593
        }
594
 
595
    if(data && err == noErr)
596
        {
597
        err =  DecodeMacBinary(data, source);
598
        DisposeHandle(data);
599
        }
600
 
601
#ifdef DELETE_MACBINARY_SOURCE
602
    if (err == noErr)
603
        err = FSpDelete(&McBin_source);
604
#endif
605
 
606
    return err;
607
}
608
 
609
 
610
 
611
 
612
 
613
static OSErr   DecodeMacBinary(Handle data, FSSpec *destination)
614
{
615
    Handle result = nil;
616
    FInfo   fndrInfo;
617
    OSErr   err;
618
    CInfoPBRec  pb;
619
    short   dfRefNum, rfRefNum;
620
    long    ioCount;
621
    char    header[128];
622
    char    comment[256];
623
    long    resourceForkLength, dataForkLength, commentLength;
624
    Boolean isMacBinaryFile = false;
625
    short   headerEnd = 128;
626
    long    rfOffset;
627
    long maxDataLen;
628
 
629
    memset(&pb, 0, sizeof(CInfoPBRec));
630
    pb.hFileInfo.ioNamePtr   = destination->name;
631
    pb.hFileInfo.ioVRefNum   = destination->vRefNum;
632
    pb.hFileInfo.ioFDirIndex = 0;           /*  query a file */
633
    pb.hFileInfo.ioDirID     = destination->parID;
634
    err = PBGetCatInfo(&pb,false);
635
    maxDataLen = pb.hFileInfo.ioFlLgLen;
636
 
637
    HLock(data);
638
    memcpy(header, *data, 128);
639
 
640
     /* already checked with FSpIsMacBinary()    */
641
    isMacBinaryFile = HeaderIsMacBinary(header, nil, maxDataLen);;
642
 
643
    if(!isMacBinaryFile)
644
        return paramErr;
645
 
646
    if(WORD_AT_OFFSET(header, kSecondaryHeaderLengthOffset))
647
        {
648
        headerEnd = WORD_AT_OFFSET(header, kSecondaryHeaderLengthOffset);
649
        headerEnd = (headerEnd + 127) & ~127L;
650
        }
651
 
652
    resourceForkLength = LONG_AT_OFFSET(header, kResourceForkLengthOffset);
653
    dataForkLength     = LONG_AT_OFFSET(header, kDataForkLengthOffset);
654
    commentLength      = WORD_AT_OFFSET(header, kGetInfoCommentLengthOffset);
655
 
656
    memcpy( destination->name,
657
            PTR_AT_OFFSET(header,
658
            kFileNameLengthOffset),
659
            BYTE_AT_OFFSET(header,
660
            kFileNameLengthOffset));
661
 
662
    fndrInfo.fdType    = LONG_AT_OFFSET(header, kFileTypeOffset);
663
    fndrInfo.fdCreator = LONG_AT_OFFSET(header, kFileCreatorOffset);
664
 
665
    fndrInfo.fdFlags = BYTE_AT_OFFSET(header, kFinderFlagsHiOffset);
666
    fndrInfo.fdFlags << 8;
667
    fndrInfo.fdFlags |= BYTE_AT_OFFSET(header, kFinderFlagsLowOffset);
668
 
669
    fndrInfo.fdLocation.v = WORD_AT_OFFSET(header, kFileVPositionOffset);
670
    fndrInfo.fdLocation.h = WORD_AT_OFFSET(header, kFileHPositionOffset);
671
    fndrInfo.fdFldr       = WORD_AT_OFFSET(header, kFileFolderIDOffset);
672
/*
673
    index = 1;
674
    checkFile = *destination;
675
    while(FSpExists(&checkFile))
676
        {
677
        checkFile = *destination;
678
 
679
        if(index < 10)
680
            checkFile.name[++checkFile.name[0]] = '0' + index;
681
        else
682
            checkFile.name[++checkFile.name[0]] = ('a' - 10) + index;
683
        index++;
684
        }
685
    *destination = checkFile;
686
*/
687
    err = FSpCreate(destination,
688
                    fndrInfo.fdCreator,
689
                    fndrInfo.fdType,
690
                    smSystemScript);
691
 
692
    dfRefNum = 0;
693
    if(err == noErr)
694
        {
695
        err = FSpOpenDF(destination, fsRdWrPerm, &dfRefNum);
696
        }
697
 
698
    if(err == noErr && dfRefNum)
699
        {
700
        ioCount = dataForkLength;
701
        err = FSWrite(dfRefNum,&ioCount,*data + headerEnd);
702
        FSClose(dfRefNum);
703
        }
704
 
705
    rfRefNum = 0;
706
    if(err == noErr)
707
        {
708
        err = FSpOpenRF(destination, fsRdWrPerm, &rfRefNum);
709
        }
710
 
711
    rfOffset = headerEnd + dataForkLength;
712
    rfOffset = (rfOffset + 127) & ~127L;
713
 
714
    if(err == noErr && rfRefNum)
715
        {
716
        ioCount = resourceForkLength;
717
        err = FSWrite(rfRefNum,&ioCount,*data + rfOffset);
718
        FSClose(rfRefNum);
719
        }
720
 
721
    rfOffset += resourceForkLength;
722
    rfOffset = (rfOffset + 127) & ~127L;
723
 
724
    if(err == noErr)
725
       {
726
        FSpSetFInfo(destination,&fndrInfo);
727
 
728
        memset(&pb, 0, sizeof(CInfoPBRec));
729
        pb.hFileInfo.ioNamePtr   = destination->name;
730
        pb.hFileInfo.ioVRefNum   = destination->vRefNum;
731
        pb.hFileInfo.ioFDirIndex = 0;           /*  query a file */
732
        pb.hFileInfo.ioDirID     = destination->parID;
733
        err = PBGetCatInfo(&pb,false);
734
 
735
        if(err == noErr)
736
            {
737
            pb.hFileInfo.ioDirID   = destination->parID;
738
            pb.hFileInfo.ioFlCrDat =
739
                          LONG_AT_OFFSET(header, kFileCreationDateOffset);
740
            pb.hFileInfo.ioFlMdDat =
741
                          LONG_AT_OFFSET(header, kFileModificationDateOffset);
742
            pb.hFileInfo.ioFlXFndrInfo.fdXFlags =
743
                          BYTE_AT_OFFSET(header, kExtendedFinderFlagsOffset);
744
            pb.hFileInfo.ioFlXFndrInfo.fdScript =
745
                          BYTE_AT_OFFSET(header, kFilenameScriptOffset);
746
            err = PBSetCatInfo(&pb, false);
747
            }
748
 
749
        if(commentLength)
750
            {
751
            memcpy(comment,*data + rfOffset, commentLength);
752
            SetDesktopComment(destination, comment, commentLength);
753
            }
754
 
755
        }
756
    HUnlock(data);
757
    return err;
758
}
759
 
760
#endif /*  INCLUDE_DECODE_MACBINARY  */
761